blob: 30949b261ed39c67bf031e04999e15627689fedb [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001#ifndef __ENABLE_MOCANA_SSL_SERVER__
2
3#include "wsIntrn.h"
4#include "webs.h"
5#include "websSSL.h"
6#include "ref_nv_def.h"
7
8
9#define DEFAULT_KEY_FILE "/etc_ro/certs/cakey.pem"
10#define DEFAULT_CA_FILE "/etc_ro/certs/cacert.pem"
11#define DEFAULT_PWD_FILE "/etc_ro/certs/password"
12#define SSL_PORT 443
13
14#define DEFAULT_KEY_MASK 0x60
15typedef struct websSSLKey {
16 char pwd[17];
17 unsigned char procType;
18 unsigned short dekType;
19 unsigned char dekInfo[16];
20 unsigned char privateKey[624];
21 unsigned short certLen;
22} websSSLKey;
23
24
25
26#ifdef SIGPIPE
27#define do_pipe_sig() signal(SIGPIPE,SIG_IGN)
28#else
29#define do_pipe_sig()
30#endif
31
32
33# if defined(MSDOS) || defined(WIN16) || defined(WIN32)
34# ifdef _O_BINARY
35# define apps_startup() \
36 _fmode=_O_BINARY; do_pipe_sig(); CRYPTO_malloc_init(); \
37 SSLC_add_all_algorithms()
38# else
39# define apps_startup() \
40 _fmode=O_BINARY; do_pipe_sig(); CRYPTO_malloc_init(); \
41 SSLC_add_all_algorithms()
42# endif
43# else
44# define apps_startup() do_pipe_sig(); SSLC_add_all_algorithms();
45# endif
46
47
48#ifdef OPENSSL
49#ifndef SSLeay_add_all_algorithms
50#define SSLeay_add_all_algorithms() OpenSSL_add_all_algorithms()
51#endif
52
53#define SSLC_add_all_algorithms() SSLeay_add_all_algorithms()
54#else
55extern void SSLC_add_all_algorithms(void);
56#endif
57
58
59static int websSSLVerifyCallback(int ok, X509_STORE_CTX *ctx);
60static RSA *websSSLTempRSACallback(SSL *s, int is_export, int keylength);
61
62static int websSSLReadEvent (webs_t wp);
63static int websSSLAccept(int sid, char *ipaddr, int port, int listenSid);
64static void websSSLSocketEvent(int sid, int mask, int data);
65static int websSSLSetCertStuff(SSL_CTX *ctx, char *cert_file, char *key_file);
66
67
68static int sslListenSock = -1;
69static SSL_CTX *sslctx = NULL;
70static char *sslpwd = NULL;
71static websSSLKey sslkey = {0};
72static unsigned char *sslcert = NULL;
73
74
75static int getFileSize(char *lpath)
76{
77 gstat_t s;
78
79 if (lpath && stat(lpath, &s) == 0) {
80 return s.st_size;
81 }
82 return 0;
83}
84
85
86int websSSLOpen()
87{
88 SSL_METHOD *meth;
89
90 apps_startup();
91 trace(7, T("SSL: Initializing SSL\n"));
92
93#ifdef SSLC
94 SSL_library_init();
95#endif
96
97 SSL_load_error_strings();
98
99#ifdef OPENSSL
100 SSLeay_add_ssl_algorithms();
101#endif
102
103
104#ifdef WEBINSPECT_FIX
105 meth = TLSv1_2_server_method();
106#else
107 meth = SSLv23_server_method();
108#endif
109 sslctx = SSL_CTX_new(meth);
110
111 a_assert(sslctx);
112
113 if (sslctx == NULL) {
114 trace(2, T("SSL: Unable to create SSL context!\n"));
115 return -1;
116 }
117
118
119 SSL_CTX_set_quiet_shutdown(sslctx, 1);
120 SSL_CTX_set_options(sslctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
121 SSL_CTX_sess_set_cache_size(sslctx, 128);
122
123 EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
124 if (ecdh){
125 long eret = SSL_CTX_set_tmp_ecdh (sslctx, ecdh);
126 trace(2, T("SSL: ecdh:%x ret=%d\n"), ecdh, eret);
127 EC_KEY_free(ecdh);
128 ecdh = NULL;
129 }
130
131
132#ifdef WEBINSPECT_FIX
133 if(!SSL_CTX_set_cipher_list(sslctx,"ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:!NULL:!RC4:!RC2:!DES:!3DES:!SHA:!SHA256:!SHA384:!MD5+HIGH:+MEDIUM"))
134 trace(2, T("SSL: Unable to set !DES:!RC4:!SHA1\n"));
135#endif
136
137 unsigned char webkey_flag = 0;
138 int retCode = cpnv_NvItemRead(ZPS_REF_MSINFO_WEBKEY_FLAG_BASE_ADDR, &webkey_flag, sizeof(webkey_flag));
139 if (retCode == CPNV_ERROR)
140 {
141 trace(2, T("SSL: read cpnv keyflag error\n"));
142 websSSLClose();
143 return -1;
144 }
145 trace(2, T("SSL: webkey_flag=%d\n"),webkey_flag);
146 if (webkey_flag != 1)
147 {
148 ssize_t read_len = 0;
149 char *pwdFile = DEFAULT_PWD_FILE;
150 int pwdSize = getFileSize(pwdFile);
151 if(pwdSize > 0)
152 {
153 int fd = open(pwdFile, SOCKET_RDONLY | SOCKET_BINARY, 0666);
154 if(fd >= 0)
155 {
156 sslpwd = balloc(B_L,pwdSize + 1);
157 if(sslpwd != NULL)
158 {
159 memset(sslpwd, 0, pwdSize + 1);
160 read_len = read(fd, sslpwd, pwdSize);
161 if(read_len < 0)
162 {
163 trace(2, T("read len:%d ; errno: %s\n"), read_len, strerror(errno));
164 }
165 trace(2, T("SSL: pwd:%s\n"), sslpwd);
166 SSL_CTX_set_default_passwd_cb_userdata(sslctx, (void *)sslpwd);
167 }
168 close(fd);
169 }
170 }
171
172 //char *certFile = DEFAULT_CA_FILE;
173 //char *keyFile = DEFAULT_KEY_FILE;// kw OVERWRITE_CONST_CHAR
174 if (websSSLSetCertStuff(sslctx, DEFAULT_CA_FILE, DEFAULT_KEY_FILE) != 0) {
175 websSSLClose();
176 return -1;
177 }
178 }
179 else
180 {
181 retCode = cpnv_NvItemRead(ZPS_REF_MSINFO_WEBKEY_DATA_BASE_ADDR, (unsigned char *)&sslkey, sizeof(sslkey));
182 char i = 0;
183 if (retCode == CPNV_ERROR)
184 {
185 trace(2, T("SSL: read cpnv key error\n"));
186 websSSLClose();
187 return -1;
188 }
189 trace(2, T("SSL: key procType=%d dekType=%d certLen=%d\n"),sslkey.procType,sslkey.dekType,sslkey.certLen);
190 sslcert = balloc(B_L, sslkey.certLen);
191 if(sslcert == NULL)
192 {
193 trace(2, T("SSL: alloc cpnv cert fail\n"));
194 websSSLClose();
195 return -1;
196 }
197 retCode = cpnv_NvItemRead(ZPS_REF_MSINFO_WEBKEY_DATA_BASE_ADDR+sizeof(sslkey), sslcert, sslkey.certLen);
198 if (retCode == CPNV_ERROR)
199 {
200 trace(2, T("SSL: read cpnv cert error\n"));
201 websSSLClose();
202 return -1;
203 }
204 for(i=0; i < sizeof(sslkey.pwd); i++)
205 {
206 if(sslkey.pwd[i] != 0)
207 {
208 sslkey.pwd[i] = sslkey.pwd[i] - DEFAULT_KEY_MASK;
209 }
210 else
211 {
212 break;
213 }
214 }
215 SSL_CTX_set_default_passwd_cb_userdata(sslctx, (void *)sslkey.pwd);
216 retCode = websSSLSetCertificate(sslctx, sslcert, sslkey.certLen);
217 if (retCode <= 0)
218 {
219 trace(2, T("SSL: websSSLSetCertificate fail ret=%d\n"),retCode);
220 websSSLClose();
221 return -1;
222 }
223 retCode = websSSLSetPrivateKey(sslctx, &sslkey);
224 if (retCode <= 0)
225 {
226 trace(2, T("SSL: websSSLSetPrivateKey fail ret=%d\n"),retCode);
227 websSSLClose();
228 return -1;
229 }
230 }
231
232 SSL_CTX_set_tmp_rsa_callback(sslctx, websSSLTempRSACallback);
233
234
235 SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, websSSLVerifyCallback);
236
237
238 sslListenSock = socketOpenConnection6(NULL, SSL_PORT,
239 websSSLAccept, SOCKET_BLOCK);
240
241 if (sslListenSock < 0) {
242 trace(2, T("SSL: Unable to open SSL socket on port <%d>!\n"),
243 SSL_PORT);
244 return -1;
245 }
246
247 return 0;
248}
249
250
251
252int websSSLIsOpen()
253{
254 return (sslListenSock != -1);
255}
256
257
258
259int websSSLAccept(int sid, char *ipaddr, int port, int listenSid)
260{
261 webs_t wp;
262 int wid;
263
264 a_assert(ipaddr && *ipaddr);
265 a_assert(sid >= 0);
266 a_assert(port >= 0);
267
268
269 if ((wid = websAlloc(sid)) < 0) {
270 return -1;
271 }
272 wp = webs[wid];
273 a_assert(wp);
274 wp->listenSid = listenSid;
275
276 ascToUni(wp->ipaddr, ipaddr, min(sizeof(wp->ipaddr), strlen(ipaddr)+1));
277
278
279 if (gstrcmp(wp->ipaddr, T("127.0.0.1")) == 0 ||
280 gstrcmp(wp->ipaddr, websIpaddr) == 0 ||
281 gstrcmp(wp->ipaddr, websHost) == 0) {
282 wp->flags |= WEBS_LOCAL_REQUEST;
283 }
284
285 wp->flags |= WEBS_SECURE;
286
287
288 socketCreateHandler(sid, SOCKET_READABLE, websSSLSocketEvent, (int) wp);
289
290 wp->timeout = emfSchedCallback(WEBS_TIMEOUT, websTimeout, (void *) wp);
291 //trace(8, T("webs: accept request\n"));
292 return 0;
293}
294
295void websSSLClose()
296{
297 trace(7, T("SSL: Closing SSL\n"));
298
299 if (sslctx != NULL) {
300 SSL_CTX_free(sslctx);
301 sslctx = NULL;
302 }
303
304 if (sslListenSock != -1) {
305 socketCloseConnection(sslListenSock);
306 sslListenSock = -1;
307 }
308
309 if(sslpwd != NULL) {
310 bfree(B_L, sslpwd);
311 sslpwd = NULL;
312 }
313
314#ifdef SSLC
315 SSL_library_cleanup();
316#endif
317}
318
319
320static int websSSLReadEvent (webs_t wp)
321{
322 int ret, sock;
323 socket_t *sptr;
324 SSL *ssl;
325 BIO *bio, *bioSSL, *bioSock;
326#ifdef DEV
327 const char *ciphers;
328#endif
329
330 a_assert (wp);
331 a_assert(websValid(wp));
332
333 sptr = socketPtr(wp->sid);
334 a_assert(sptr);
335 if(sptr == NULL)
336 return -1;
337 sock = sptr->sock;
338
339 bio = BIO_new(BIO_f_buffer());
340 a_assert(bio);
341
342 if (!BIO_set_write_buffer_size(bio, 128)) {
343 return -1;
344 }
345
346 ssl = (SSL *) SSL_new(sslctx);
347 a_assert(ssl);
348
349 if (ssl == NULL) {
350 return -1;
351 }
352
353 SSL_set_session(ssl, NULL);
354
355 bioSSL = BIO_new(BIO_f_ssl());
356 a_assert(bioSSL);
357
358 bioSock = BIO_new_socket(sock, BIO_NOCLOSE);
359 a_assert(bioSock);
360
361 SSL_set_bio(ssl, bioSock, bioSock);
362 SSL_set_accept_state(ssl);
363
364 ret = BIO_set_ssl(bioSSL, ssl, BIO_CLOSE);
365 BIO_push(bio, bioSSL);
366
367#ifdef DEV
368 ciphers = SSL_get_cipher_list(ssl, 10);
369#endif
370
371#ifdef WEBS_SSL_SUPPORT
372 websSSLFree(wp->wsp);
373 wp->wsp = balloc(B_L, sizeof(websSSL_t));
374 a_assert (wp->wsp);
375 if(wp->wsp == NULL)
376 return -1;
377 (wp->wsp)->bio = bio;
378 (wp->wsp)->ssl = ssl;
379#endif
380
381 websReadEvent(wp);
382
383 return ret;
384}
385
386static void websSSLSocketEvent(int sid, int mask, int iwp)
387{
388 webs_t wp;
389
390 wp = (webs_t) iwp;
391 a_assert(wp);
392
393 if (! websValid(wp)) {
394 return;
395 }
396
397 if (mask & SOCKET_READABLE) {
398 websSSLReadEvent(wp);
399 }
400 if (mask & SOCKET_WRITABLE) {
401 if (websValid(wp) && wp->writeSocket) {//cov
402 (*wp->writeSocket)(wp);
403 }
404 }
405}
406
407static int sslVerifyDepth = 0;
408static int sslVerifyError = X509_V_OK;
409
410int websSSLVerifyCallback(int ok, X509_STORE_CTX *ctx)
411{
412 char buf[256];
413 X509 *errCert;
414 int err;
415 int depth;
416
417 errCert = X509_STORE_CTX_get_current_cert(ctx);
418 err = X509_STORE_CTX_get_error(ctx);
419 depth = X509_STORE_CTX_get_error_depth(ctx);
420
421 X509_NAME_oneline(X509_get_subject_name(errCert), buf, 256);
422
423 if (!ok) {
424 if (sslVerifyDepth >= depth) {
425 ok = 1;
426 sslVerifyError = X509_V_OK;
427 } else {
428 ok=0;
429 sslVerifyError = X509_V_ERR_CERT_CHAIN_TOO_LONG;
430 }
431 }
432
433 switch (err) {
434 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
435#ifdef OPENSSL
436 //X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
437 X509_NAME_oneline(X509_get_issuer_name(X509_STORE_CTX_get_current_cert(ctx)), buf, 256);
438#endif
439 break;
440
441 case X509_V_ERR_CERT_NOT_YET_VALID:
442 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
443 case X509_V_ERR_CERT_HAS_EXPIRED:
444 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
445 break;
446 }
447
448 return ok;
449}
450
451int websSSLSetCertificate(SSL_CTX *ctx, const unsigned char *data, int len)
452{
453 BIO *in;
454 int ret = 0;
455 X509 *x = NULL;
456
457 in = BIO_new(BIO_s_mem());
458 if (in == NULL) {
459 trace(2, T("SSL: cert BIO_new NULL\n"));
460 goto end;
461 }
462
463 ret = PEM_write_bio(in, PEM_STRING_X509, "", data, len);
464 if (ret <= 0){
465 trace(2, T("SSL: cert PEM_write_bio fail ret=%d\n"),ret);
466 goto end;
467 }
468 x = PEM_read_bio_X509(in, NULL,
469 SSL_CTX_get_default_passwd_cb(ctx),//ctx->default_passwd_callback,
470 SSL_CTX_get_default_passwd_cb_userdata(ctx));//ctx->default_passwd_callback_userdata);
471
472 if (x == NULL) {
473 trace(2, T("SSL: cert PEM_read_bio_X509 NULL\n"));
474 goto end;
475 }
476
477 ret = SSL_CTX_use_certificate(ctx, x);
478 X509_free(x);
479
480 end:
481 if (in != NULL)
482 BIO_free(in);
483 return (ret);
484}
485
486int websSSLSetPrivateKey(SSL_CTX *ctx, websSSLKey *key)
487{
488 int ret = 0;
489 BIO *in;
490 EVP_PKEY *pkey = NULL;
491 const char *objstr = NULL;
492 char buf[PEM_BUFSIZE] = {0};
493
494 in = BIO_new(BIO_s_mem());
495 if (in == NULL) {
496 trace(2, T("SSL: key BIO_new NULL\n"));
497 goto end;
498 }
499
500 objstr = OBJ_nid2sn(key->dekType);
501 if (objstr == NULL) {
502 trace(2, T("SSL: key OBJ_nid2sn NULL type = %d\n"),key->dekType);
503 goto end;
504 }
505 PEM_proc_type(buf, key->procType);
506 PEM_dek_info(buf, objstr, sizeof(key->dekInfo), (char *)key->dekInfo);
507
508 ret = PEM_write_bio(in, PEM_STRING_RSA, buf, key->privateKey, sizeof(key->privateKey));
509 if (ret <= 0){
510 trace(2, T("SSL: key PEM_write_bio fail ret=%d\n"),ret);
511 goto end;
512 }
513 pkey = PEM_read_bio_PrivateKey(in, NULL,
514 SSL_CTX_get_default_passwd_cb(ctx),//ctx->default_passwd_callback,
515 SSL_CTX_get_default_passwd_cb_userdata(ctx));//ctx->default_passwd_callback_userdata);
516 if (pkey == NULL) {
517 trace(2, T("SSL: key PEM_read_bio_PrivateKey NULL\n"));
518 goto end;
519 }
520 ret = SSL_CTX_use_PrivateKey(ctx, pkey);
521 EVP_PKEY_free(pkey);
522
523 end:
524 if (in != NULL)
525 BIO_free(in);
526 return (ret);
527}
528
529
530int websSSLSetCertStuff(SSL_CTX *ctx, char *certFile, char *keyFile)
531{
532 a_assert (ctx);
533 a_assert (certFile);
534
535 if (certFile != NULL) {
536 if (SSL_CTX_use_certificate_file(ctx, certFile,
537 SSL_FILETYPE_PEM) <= 0) {
538 trace(2, T("SSL: Unable to set certificate file <%s>\n"),
539 certFile);
540 return -1;
541 }
542
543 if (keyFile == NULL) {
544 keyFile = certFile;
545 }
546
547 if (SSL_CTX_use_PrivateKey_file(ctx, keyFile, SSL_FILETYPE_PEM) <= 0) {
548 trace(2, T("SSL: Unable to set private key file <%s>\n"),
549 keyFile);
550 return -1;
551 }
552
553
554 if (!SSL_CTX_check_private_key(ctx)) {
555 trace(2, T("SSL: Check of private key file <%s> FAILED!\n"),
556 keyFile);
557 return -1;
558 }
559 }
560
561 return 0;
562}
563
564
565int websSSLSetKeyFile(char_t *keyFile)
566{
567 a_assert (sslctx);
568 a_assert (keyFile);
569
570 if (sslctx == NULL) {
571 return -1;
572 }
573
574 if (SSL_CTX_use_PrivateKey_file(sslctx, keyFile, SSL_FILETYPE_PEM) <= 0) {
575 return -1;
576 }
577
578 if (!SSL_CTX_check_private_key(sslctx)) {
579 return -1;
580 }
581
582 return 0;
583}
584
585
586int websSSLSetCertFile(char_t *certFile)
587{
588 a_assert (sslctx);
589 a_assert (certFile);
590
591 if (sslctx == NULL) {
592 return -1;
593 }
594
595 if (SSL_CTX_use_certificate_file(sslctx, certFile,
596 SSL_FILETYPE_PEM) <= 0) {
597 return -1;
598 }
599
600 if (!SSL_CTX_check_private_key(sslctx)) {
601 return -1;
602 }
603
604 return 0;
605}
606
607#ifdef SSLC
608extern RSA *RSA_new(void);
609#endif
610
611int websSSLEof(websSSL_t *wsp)
612{
613 a_assert(wsp);
614
615 if ((wsp == NULL) || (wsp->bio == NULL)) {
616 return -1;
617 }
618
619 return BIO_eof(wsp->bio);
620}
621
622
623int websSSLRead(websSSL_t *wsp, char_t *buf, int len)
624{
625 a_assert(wsp);
626 a_assert(buf);
627
628 if ((wsp == NULL) || (wsp->bio == NULL)) {
629 return -1;
630 }
631
632 return BIO_read(wsp->bio, buf, len);
633}
634
635static RSA *websSSLTempRSACallback(SSL *ssl, int isExport, int keyLength)
636{
637 static RSA *rsaTemp = NULL;
638
639 if (rsaTemp == NULL) {
640
641#ifdef OPENSSL
642 rsaTemp = RSA_generate_key(keyLength, RSA_F4, NULL, NULL);
643#endif
644
645#ifdef SSLC
646 rsaTemp = RSA_new();
647#endif
648
649 }
650
651 return rsaTemp;
652}
653
654
655int websSSLFree(websSSL_t *wsp)
656{
657 if (wsp == NULL) {
658 return -1;
659 }
660
661 if (wsp->ssl != NULL) {
662 SSL_set_shutdown(wsp->ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
663 }
664
665 if (wsp->bio != NULL) {
666 BIO_free_all(wsp->bio);
667 }
668
669 bfree(B_L, wsp);
670
671 return 0;
672}
673
674
675
676
677#define BUF_BLOCK 256
678
679int websSSLGets(websSSL_t *wsp, char_t **buf)
680{
681 int rc, len, lenBuf;
682 char c;
683
684 a_assert(wsp);
685 a_assert(buf);
686
687 lenBuf = 0;
688 len = 0;
689
690 if ((wsp == NULL) || (wsp->bio == NULL)) {
691 return -1;
692 }
693
694 while (len < 1536) {
695
696 if ((rc = BIO_read(wsp->bio, &c, 1)) < 0) {
697 return rc;
698 }
699
700 if (rc == 0) {
701
702 if (len > 0 && BIO_eof(wsp->bio)) {
703 c = '\n';
704 } else {
705 return -1;
706 }
707 }
708
709 if (c == '\n') {
710 if ((len > 0) && (len < lenBuf)) {
711 (*buf)[len] = 0;
712 }
713 return len;
714 } else if (c == '\r') {
715 continue;
716 }
717
718 if (lenBuf == 0 || len >= lenBuf - 1) {
719 lenBuf += BUF_BLOCK;
720 *buf = brealloc(B_L, *buf, lenBuf);
721 }
722
723 a_assert(*buf);
724 if(*buf == NULL)
725 return -1;
726 (*buf)[len] = c;
727 len++;
728 }
729 bfreeSafe(B_L,*buf);
730 *buf = NULL;
731 return -1;
732}
733
734
735int websSSLWrite(websSSL_t *wsp, char_t *buf, int len)
736{
737 a_assert(wsp);
738 a_assert(buf);
739
740 if ((wsp == NULL) || (wsp->bio == NULL)) {
741 return -1;
742 }
743
744 return BIO_write(wsp->bio, buf, len);
745}
746
747
748int websSSLFlush(websSSL_t *wsp)
749{
750 a_assert(wsp);
751
752 if ((wsp == NULL) || (wsp->bio == NULL)) {
753 return -1;
754 }
755
756 return BIO_flush(wsp->bio);
757}
758
759#endif