lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 1 | #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 |
| 15 | typedef 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 |
| 55 | extern void SSLC_add_all_algorithms(void); |
| 56 | #endif |
| 57 | |
| 58 | |
| 59 | static int websSSLVerifyCallback(int ok, X509_STORE_CTX *ctx); |
| 60 | static RSA *websSSLTempRSACallback(SSL *s, int is_export, int keylength); |
| 61 | |
| 62 | static int websSSLReadEvent (webs_t wp); |
| 63 | static int websSSLAccept(int sid, char *ipaddr, int port, int listenSid); |
| 64 | static void websSSLSocketEvent(int sid, int mask, int data); |
| 65 | static int websSSLSetCertStuff(SSL_CTX *ctx, char *cert_file, char *key_file); |
| 66 | |
| 67 | |
| 68 | static int sslListenSock = -1; |
| 69 | static SSL_CTX *sslctx = NULL; |
| 70 | static char *sslpwd = NULL; |
| 71 | static websSSLKey sslkey = {0}; |
| 72 | static unsigned char *sslcert = NULL; |
| 73 | |
| 74 | |
| 75 | static 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 | |
| 86 | int 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 | |
| 252 | int websSSLIsOpen() |
| 253 | { |
| 254 | return (sslListenSock != -1); |
| 255 | } |
| 256 | |
| 257 | |
| 258 | |
| 259 | int 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 | |
| 295 | void 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 | |
| 320 | static 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 | |
| 386 | static 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 | |
| 407 | static int sslVerifyDepth = 0; |
| 408 | static int sslVerifyError = X509_V_OK; |
| 409 | |
| 410 | int 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 | |
| 451 | int 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 | |
| 486 | int 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 | |
| 530 | int 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 | |
| 565 | int 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 | |
| 586 | int 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 |
| 608 | extern RSA *RSA_new(void); |
| 609 | #endif |
| 610 | |
| 611 | int 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 | |
| 623 | int 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 | |
| 635 | static 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 | |
| 655 | int 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 | |
| 679 | int 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 | |
| 735 | int 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 | |
| 748 | int 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 |