1 /* 2 * mod_wolfssl - wolfSSL support for lighttpd 3 * 4 * Copyright(c) 2020 Glenn Strauss gstrauss()gluelogic.com All rights reserved 5 * License: BSD 3-clause (same as lighttpd) 6 */ 7 /* 8 * Note: If session tickets are -not- disabled with 9 * ssl.openssl.ssl-conf-cmd = ("Options" => "-SessionTicket") 10 * mod_wolfssl rotates server ticket encryption key (STEK) every 8 hours 11 * and keeps the prior two STEKs around, so ticket lifetime is 24 hours. 12 * This is fine for use with a single lighttpd instance, but with multiple 13 * lighttpd workers, no coordinated STEK (server ticket encryption key) 14 * rotation occurs unless ssl.stek-file is defined and maintained (preferred), 15 * or if some external job restarts lighttpd. Restarting lighttpd generates a 16 * new key that is shared by lighttpd workers for the lifetime of the new key. 17 * If the rotation period expires and lighttpd has not been restarted, and if 18 * ssl.stek-file is not in use, then lighttpd workers will generate new 19 * independent keys, making session tickets less effective for session 20 * resumption, since clients have a lower chance for future connections to 21 * reach the same lighttpd worker. However, things will still work, and a new 22 * session will be created if session resumption fails. Admins should plan to 23 * restart lighttpd at least every 8 hours if session tickets are enabled and 24 * multiple lighttpd workers are configured. Since that is likely disruptive, 25 * if multiple lighttpd workers are configured, ssl.stek-file should be 26 * defined and the file maintained externally. 27 */ 28 #include "first.h" 29 30 #include <sys/types.h> 31 #include <sys/stat.h> 32 #include <errno.h> 33 #include <fcntl.h> 34 #include <stdint.h> 35 #include <stdlib.h> 36 #include <string.h> 37 38 /* 39 * Note: mod_wolfssl.c is forked from mod_openssl.c 40 * Many internal symbol names in mod_wolfssl.c retain the mod_openssl_* prefix 41 * (wolfSSL provides an OpenSSL compatibility layer) 42 */ 43 44 /* wolfSSL needs to be built with ./configure --enable-lighty for lighttpd. 45 * Doing so defines OPENSSL_EXTRA and HAVE_LIGHTY in <wolfssl/options.h>, and 46 * these defines are necessary for wolfSSL headers to expose sufficient openssl 47 * compatibility layer for wolfSSL to be able to provide an openssl substitute 48 * for use by lighttpd */ 49 50 /* workaround fragile code in wolfssl/wolfcrypto/types.h */ 51 #if !defined(SIZEOF_LONG) || !defined(SIZEOF_LONG_LONG) 52 #undef SIZEOF_LONG 53 #undef SIZEOF_LONG_LONG 54 #endif 55 56 #include <wolfssl/options.h> 57 #include <wolfssl/ssl.h> 58 59 static char global_err_buf[WOLFSSL_MAX_ERROR_SZ]; 60 #undef ERR_error_string 61 #define ERR_error_string(e,b) \ 62 (wolfSSL_ERR_error_string_n((e),global_err_buf,WOLFSSL_MAX_ERROR_SZ), \ 63 global_err_buf) 64 65 #if 0 /* symbols and definitions requires WolfSSL built with -DOPENSSL_EXTRA */ 66 #define SSL_TLSEXT_ERR_OK 0 67 #define SSL_TLSEXT_ERR_ALERT_FATAL alert_fatal 68 #define SSL_TLSEXT_ERR_NOACK alert_warning 69 70 WOLFSSL_API void wolfSSL_set_verify_depth(WOLFSSL *ssl,int depth); 71 72 WOLFSSL_API void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME* name); 73 WOLFSSL_API int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x, const WOLFSSL_X509_NAME* y); 74 WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_NAME_dup(WOLFSSL_X509_NAME*); 75 WOLFSSL_API char* wolfSSL_X509_get_name_oneline(WOLFSSL_X509_NAME*, char*, int); 76 77 WOLFSSL_API const char* wolfSSL_OBJ_nid2sn(int n); 78 WOLFSSL_API int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o); 79 WOLFSSL_API WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne); 80 WOLFSSL_API WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry(WOLFSSL_X509_NAME *name, int loc); 81 #endif 82 83 #if !defined(OPENSSL_ALL) || LIBWOLFSSL_VERSION_HEX < 0x04002000 84 /*(invalid; but centralize making these calls no-ops)*/ 85 #define wolfSSL_sk_X509_NAME_num(a) 0 86 #define wolfSSL_sk_X509_NAME_push(a, b) 0 87 #define wolfSSL_sk_X509_NAME_pop_free(a, b) do { } while (0) 88 #define wolfSSL_sk_X509_NAME_free(a) do { } while (0) 89 #define wolfSSL_X509_get_subject_name(ca) \ 90 ((WOLFSSL_X509_NAME *)1) /* ! NULL */ 91 #define wolfSSL_sk_X509_NAME_new(a) \ 92 ((WOLF_STACK_OF(WOLFSSL_X509_NAME) *)1) /* ! NULL */ 93 #endif 94 95 #if LIBWOLFSSL_VERSION_HEX < 0x04006000 || defined(WOLFSSL_NO_FORCE_ZERO) 96 #define wolfSSL_OPENSSL_cleanse(x,sz) ck_memzero((x),(sz)) 97 #endif 98 99 #if LIBWOLFSSL_VERSION_HEX < 0x04002000 /*(exact version needed not checked)*/ 100 #ifndef STACK_OF 101 #define STACK_OF(x) WOLFSSL_STACK 102 #endif 103 #endif 104 105 #include "base.h" 106 #include "ck.h" 107 #include "fdevent.h" 108 #include "http_header.h" 109 #include "http_kv.h" 110 #include "log.h" 111 #include "plugin.h" 112 113 typedef struct { 114 /* SNI per host: with COMP_SERVER_SOCKET, COMP_HTTP_SCHEME, COMP_HTTP_HOST */ 115 buffer *ssl_pemfile_pkey; 116 buffer *ssl_pemfile_x509; 117 buffer **ssl_pemfile_chain; 118 buffer *ssl_stapling; 119 const buffer *ssl_pemfile; 120 const buffer *ssl_privkey; 121 const buffer *ssl_stapling_file; 122 unix_time64_t ssl_stapling_loadts; 123 unix_time64_t ssl_stapling_nextts; 124 char must_staple; 125 } plugin_cert; 126 127 typedef struct { 128 WOLFSSL_CTX *ssl_ctx; 129 } plugin_ssl_ctx; 130 131 typedef struct { 132 STACK_OF(X509_NAME) *names; 133 X509_STORE *certs; 134 } plugin_cacerts; 135 136 typedef struct { 137 WOLFSSL_CTX *ssl_ctx; /* output from network_init_ssl() */ 138 139 /*(used only during startup; not patched)*/ 140 unsigned char ssl_enabled; /* only interesting for setting up listening sockets. don't use at runtime */ 141 unsigned char ssl_honor_cipher_order; /* determine SSL cipher in server-preferred order, not client-order */ 142 unsigned char ssl_empty_fragments; /* whether to not set SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */ 143 unsigned char ssl_use_sslv2; 144 unsigned char ssl_use_sslv3; 145 const buffer *ssl_cipher_list; 146 const buffer *ssl_dh_file; 147 const buffer *ssl_ec_curve; 148 array *ssl_conf_cmd; 149 150 /*(copied from plugin_data for socket ssl_ctx config)*/ 151 const plugin_cert *pc; 152 const plugin_cacerts *ssl_ca_file; 153 STACK_OF(X509_NAME) *ssl_ca_dn_file; 154 const buffer *ssl_ca_crl_file; 155 unsigned char ssl_verifyclient; 156 unsigned char ssl_verifyclient_enforce; 157 unsigned char ssl_verifyclient_depth; 158 unsigned char ssl_read_ahead; 159 unsigned char ssl_disable_client_renegotiation; 160 } plugin_config_socket; /*(used at startup during configuration)*/ 161 162 typedef struct { 163 /* SNI per host: w/ COMP_SERVER_SOCKET, COMP_HTTP_SCHEME, COMP_HTTP_HOST */ 164 plugin_cert *pc; 165 const plugin_cacerts *ssl_ca_file; 166 STACK_OF(X509_NAME) *ssl_ca_dn_file; 167 const buffer *ssl_ca_crl_file; 168 169 unsigned char ssl_verifyclient; 170 unsigned char ssl_verifyclient_enforce; 171 unsigned char ssl_verifyclient_depth; 172 unsigned char ssl_verifyclient_export_cert; 173 unsigned char ssl_read_ahead; 174 unsigned char ssl_log_noise; 175 unsigned char ssl_disable_client_renegotiation; 176 const buffer *ssl_verifyclient_username; 177 const buffer *ssl_acme_tls_1; 178 } plugin_config; 179 180 typedef struct { 181 PLUGIN_DATA; 182 plugin_ssl_ctx *ssl_ctxs; 183 plugin_config defaults; 184 server *srv; 185 array *cafiles; 186 const char *ssl_stek_file; 187 } plugin_data; 188 189 static int ssl_is_init; 190 /* need assigned p->id for deep access of module handler_ctx for connection 191 * i.e. handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id]; */ 192 static plugin_data *plugin_data_singleton; 193 #define LOCAL_SEND_BUFSIZE (16 * 1024) 194 static char *local_send_buffer; 195 196 typedef struct { 197 WOLFSSL *ssl; 198 request_st *r; 199 connection *con; 200 short renegotiations; /* count of SSL_CB_HANDSHAKE_START */ 201 short close_notify; 202 unsigned short alpn; 203 plugin_config conf; 204 buffer *tmp_buf; 205 log_error_st *errh; 206 } handler_ctx; 207 208 209 static handler_ctx * 210 handler_ctx_init (void) 211 { 212 handler_ctx *hctx = calloc(1, sizeof(*hctx)); 213 force_assert(hctx); 214 return hctx; 215 } 216 217 218 static void 219 handler_ctx_free (handler_ctx *hctx) 220 { 221 if (hctx->ssl) SSL_free(hctx->ssl); 222 free(hctx); 223 } 224 225 226 #ifdef HAVE_SESSION_TICKET 227 /* ssl/ssl_local.h */ 228 #define TLSEXT_KEYNAME_LENGTH 16 229 #define TLSEXT_TICK_KEY_LENGTH 32 230 231 /* openssl has a huge number of interfaces, but not the most useful; 232 * construct our own session ticket encryption key structure */ 233 typedef struct tlsext_ticket_key_st { 234 unix_time64_t active_ts; /* tickets not issued w/ key until activation ts*/ 235 unix_time64_t expire_ts; /* key not valid after expiration timestamp */ 236 unsigned char tick_key_name[TLSEXT_KEYNAME_LENGTH]; 237 unsigned char tick_hmac_key[TLSEXT_TICK_KEY_LENGTH]; 238 unsigned char tick_aes_key[TLSEXT_TICK_KEY_LENGTH]; 239 } tlsext_ticket_key_t; 240 241 static tlsext_ticket_key_t session_ticket_keys[4]; 242 static unix_time64_t stek_rotate_ts; 243 244 245 static int 246 mod_openssl_session_ticket_key_generate (unix_time64_t active_ts, unix_time64_t expire_ts) 247 { 248 /* openssl RAND_*bytes() functions are called multiple times since the 249 * funcs might have a 32-byte limit on number of bytes returned each call 250 * 251 * (Note: session ticket encryption key generation is not expected to fail) 252 * 253 * 3 keys are stored in session_ticket_keys[] 254 * The 4th element of session_ticket_keys[] is used for STEK construction 255 */ 256 /*(RAND_priv_bytes() not in openssl 1.1.0; introduced in openssl 1.1.1)*/ 257 #define RAND_priv_bytes(x,sz) RAND_bytes((x),(sz)) 258 if (RAND_bytes(session_ticket_keys[3].tick_key_name, 259 TLSEXT_KEYNAME_LENGTH) <= 0 260 || RAND_priv_bytes(session_ticket_keys[3].tick_hmac_key, 261 TLSEXT_TICK_KEY_LENGTH) <= 0 262 || RAND_priv_bytes(session_ticket_keys[3].tick_aes_key, 263 TLSEXT_TICK_KEY_LENGTH) <= 0) 264 return 0; 265 session_ticket_keys[3].active_ts = active_ts; 266 session_ticket_keys[3].expire_ts = expire_ts; 267 return 1; 268 } 269 270 271 static void 272 mod_openssl_session_ticket_key_rotate (void) 273 { 274 /* discard oldest key (session_ticket_keys[2]) and put newest key first 275 * 3 keys are stored in session_ticket_keys[0], [1], [2] 276 * session_ticket_keys[3] is used to construct and pass new STEK */ 277 278 session_ticket_keys[2] = session_ticket_keys[1]; 279 session_ticket_keys[1] = session_ticket_keys[0]; 280 /*memmove(session_ticket_keys+1, 281 session_ticket_keys+0, sizeof(tlsext_ticket_key_t)*2);*/ 282 session_ticket_keys[0] = session_ticket_keys[3]; 283 284 wolfSSL_OPENSSL_cleanse(session_ticket_keys+3, sizeof(tlsext_ticket_key_t)); 285 } 286 287 288 static tlsext_ticket_key_t * 289 tlsext_ticket_key_get (void) 290 { 291 const unix_time64_t cur_ts = log_epoch_secs; 292 const int e = sizeof(session_ticket_keys)/sizeof(*session_ticket_keys) - 1; 293 for (int i = 0; i < e; ++i) { 294 if (session_ticket_keys[i].active_ts > cur_ts) continue; 295 if (session_ticket_keys[i].expire_ts < cur_ts) continue; 296 return &session_ticket_keys[i]; 297 } 298 return NULL; 299 } 300 301 302 static tlsext_ticket_key_t * 303 tlsext_ticket_key_find (unsigned char key_name[16], int *refresh) 304 { 305 *refresh = 0; 306 const unix_time64_t cur_ts = log_epoch_secs; 307 const int e = sizeof(session_ticket_keys)/sizeof(*session_ticket_keys) - 1; 308 for (int i = 0; i < e; ++i) { 309 if (session_ticket_keys[i].expire_ts < cur_ts) continue; 310 if (0 == memcmp(session_ticket_keys[i].tick_key_name, key_name, 16)) 311 return &session_ticket_keys[i]; 312 if (session_ticket_keys[i].active_ts <= cur_ts) 313 *refresh = 1; /* newer active key is available */ 314 } 315 return NULL; 316 } 317 318 319 static void 320 tlsext_ticket_wipe_expired (const unix_time64_t cur_ts) 321 { 322 const int e = sizeof(session_ticket_keys)/sizeof(*session_ticket_keys) - 1; 323 for (int i = 0; i < e; ++i) { 324 if (session_ticket_keys[i].expire_ts != 0 325 && session_ticket_keys[i].expire_ts < cur_ts) 326 wolfSSL_OPENSSL_cleanse(session_ticket_keys+i, 327 sizeof(tlsext_ticket_key_t)); 328 } 329 } 330 331 332 /* based on reference implementation from openssl 1.1.1g man page 333 * man SSL_CTX_set_tlsext_ticket_key_cb 334 * but openssl code uses EVP_aes_256_cbc() instead of EVP_aes_128_cbc() 335 */ 336 #ifndef EVP_MAX_IV_LENGTH 337 #define EVP_MAX_IV_LENGTH 16 338 #endif 339 static int 340 ssl_tlsext_ticket_key_cb (SSL *s, unsigned char key_name[16], 341 unsigned char iv[EVP_MAX_IV_LENGTH], 342 EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc) 343 { 344 UNUSED(s); 345 if (enc) { /* create new session */ 346 tlsext_ticket_key_t *k = tlsext_ticket_key_get(); 347 if (NULL == k) 348 return 0; /* current key does not exist or is not valid */ 349 memcpy(key_name, k->tick_key_name, 16); 350 if (RAND_bytes(iv, EVP_MAX_IV_LENGTH) <= 0) 351 return -1; /* insufficient random */ 352 EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, k->tick_aes_key, iv); 353 HMAC_Init_ex(hctx, k->tick_hmac_key, sizeof(k->tick_hmac_key), 354 EVP_sha256(), NULL); 355 return 1; 356 } 357 else { /* retrieve session */ 358 int refresh; 359 tlsext_ticket_key_t *k = tlsext_ticket_key_find(key_name, &refresh); 360 if (NULL == k) 361 return 0; 362 HMAC_Init_ex(hctx, k->tick_hmac_key, sizeof(k->tick_hmac_key), 363 EVP_sha256(), NULL); 364 EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, k->tick_aes_key, iv); 365 return refresh ? 2 : 1; 366 /* 'refresh' will trigger issuing new ticket for session 367 * even though the current ticket is still valid */ 368 } 369 } 370 371 372 static int 373 mod_openssl_session_ticket_key_file (const char *fn) 374 { 375 /* session ticket encryption key (STEK) 376 * 377 * STEK file should be stored in non-persistent storage, 378 * e.g. /dev/shm/lighttpd/stek-file (in memory) 379 * with appropriate permissions set to keep stek-file from being 380 * read by other users. Where possible, systems should also be 381 * configured without swap. 382 * 383 * admin should schedule an independent job to periodically 384 * generate new STEK up to 3 times during key lifetime 385 * (lighttpd stores up to 3 keys) 386 * 387 * format of binary file is: 388 * 4-byte - format version (always 0; for use if format changes) 389 * 4-byte - activation timestamp 390 * 4-byte - expiration timestamp 391 * 16-byte - session ticket key name 392 * 32-byte - session ticket HMAC encrpytion key 393 * 32-byte - session ticket AES encrpytion key 394 * 395 * STEK file can be created with a command such as: 396 * dd if=/dev/random bs=1 count=80 status=none | \ 397 * perl -e 'print pack("iii",0,time()+300,time()+86400),<>' \ 398 * > STEK-file.$$ && mv STEK-file.$$ STEK-file 399 * 400 * The above delays activation time by 5 mins (+300 sec) to allow file to 401 * be propagated to other machines. (admin must handle this independently) 402 * If STEK generation is performed immediately prior to starting lighttpd, 403 * admin should activate keys immediately (without +300). 404 */ 405 int buf[23]; /* 92 bytes */ 406 int rc = 0; /*(will retry on next check interval upon any error)*/ 407 if (0 != fdevent_load_file_bytes((char *)buf,(off_t)sizeof(buf),0,fn,NULL)) 408 return rc; 409 if (buf[0] == 0) { /*(format version 0)*/ 410 session_ticket_keys[3].active_ts = TIME64_CAST(buf[1]); 411 session_ticket_keys[3].expire_ts = TIME64_CAST(buf[2]); 412 #ifndef __COVERITY__ /* intentional; hide from Coverity Scan */ 413 /* intentionally copy 80 bytes into consecutive arrays 414 * tick_key_name[], tick_hmac_key[], tick_aes_key[] */ 415 memcpy(&session_ticket_keys[3].tick_key_name, buf+3, 80); 416 #endif 417 rc = 1; 418 } 419 420 wolfSSL_OPENSSL_cleanse(buf, sizeof(buf)); 421 return rc; 422 } 423 424 425 static void 426 mod_openssl_session_ticket_key_check (const plugin_data *p, const unix_time64_t cur_ts) 427 { 428 static unix_time64_t detect_retrograde_ts; 429 if (detect_retrograde_ts > cur_ts && detect_retrograde_ts - cur_ts > 28800) 430 stek_rotate_ts = 0; 431 detect_retrograde_ts = cur_ts; 432 433 int rotate = 0; 434 if (p->ssl_stek_file) { 435 struct stat st; 436 if (0 == stat(p->ssl_stek_file, &st) 437 && TIME64_CAST(st.st_mtime) > stek_rotate_ts) 438 rotate = mod_openssl_session_ticket_key_file(p->ssl_stek_file); 439 tlsext_ticket_wipe_expired(cur_ts); 440 } 441 else if (cur_ts - 28800 >= stek_rotate_ts || 0 == stek_rotate_ts)/*(8 hrs)*/ 442 rotate = mod_openssl_session_ticket_key_generate(cur_ts, cur_ts+86400); 443 444 if (rotate) { 445 mod_openssl_session_ticket_key_rotate(); 446 stek_rotate_ts = cur_ts; 447 } 448 } 449 450 #endif /* HAVE_SESSION_TICKET */ 451 452 453 #ifdef HAVE_OCSP 454 static int 455 ssl_tlsext_status_cb(SSL *ssl, void *arg) 456 { 457 #ifdef SSL_get_tlsext_status_type 458 if (TLSEXT_STATUSTYPE_ocsp != SSL_get_tlsext_status_type(ssl)) 459 return SSL_TLSEXT_ERR_NOACK; /* ignore if not client OCSP request */ 460 #endif 461 462 handler_ctx *hctx = (handler_ctx *) SSL_get_app_data(ssl); 463 if (NULL == hctx->conf.pc) return SSL_TLSEXT_ERR_NOACK;/*should not happen*/ 464 buffer *ssl_stapling = hctx->conf.pc->ssl_stapling; 465 if (NULL == ssl_stapling) return SSL_TLSEXT_ERR_NOACK; 466 UNUSED(arg); 467 468 int len = (int)buffer_clen(ssl_stapling); 469 470 /* wolfSSL caller is going to XFREE() */ 471 uint8_t *ocsp_resp = XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL); 472 if (NULL == ocsp_resp) 473 return SSL_TLSEXT_ERR_NOACK; /* ignore OCSP request if error occurs */ 474 memcpy(ocsp_resp, ssl_stapling->ptr, (uint32_t)len); 475 476 if (!SSL_set_tlsext_status_ocsp_resp(ssl, ocsp_resp, len)) { 477 log_error(hctx->r->conf.errh, __FILE__, __LINE__, 478 "SSL: failed to set OCSP response for TLS server name %s: %s", 479 hctx->r->uri.authority.ptr, ERR_error_string(ERR_get_error(), NULL)); 480 return SSL_TLSEXT_ERR_NOACK; /* ignore OCSP request if error occurs */ 481 /*return SSL_TLSEXT_ERR_ALERT_FATAL;*/ 482 } 483 return SSL_TLSEXT_ERR_OK; 484 } 485 #endif 486 487 488 INIT_FUNC(mod_openssl_init) 489 { 490 plugin_data_singleton = (plugin_data *)calloc(1, sizeof(plugin_data)); 491 #ifdef DEBUG_WOLFSSL 492 wolfSSL_Debugging_ON(); 493 #endif 494 return plugin_data_singleton; 495 } 496 497 498 static int mod_openssl_init_once_openssl (server *srv) 499 { 500 if (ssl_is_init) return 1; 501 502 if (wolfSSL_Init() != WOLFSSL_SUCCESS) { 503 log_error(srv->errh, __FILE__, __LINE__, 504 "SSL: wolfSSL_Init() failed"); 505 return 0; 506 } 507 ssl_is_init = 1; 508 509 if (0 == RAND_status()) { 510 log_error(srv->errh, __FILE__, __LINE__, 511 "SSL: not enough entropy in the pool"); 512 return 0; 513 } 514 515 local_send_buffer = malloc(LOCAL_SEND_BUFSIZE); 516 force_assert(NULL != local_send_buffer); 517 518 return 1; 519 } 520 521 522 static void mod_openssl_free_openssl (void) 523 { 524 if (!ssl_is_init) return; 525 526 #ifdef HAVE_SESSION_TICKET 527 wolfSSL_OPENSSL_cleanse(session_ticket_keys, sizeof(session_ticket_keys)); 528 stek_rotate_ts = 0; 529 #endif 530 531 if (wolfSSL_Cleanup() != WOLFSSL_SUCCESS) { 532 log_error(plugin_data_singleton->srv->errh, __FILE__, __LINE__, 533 "SSL: wolfSSL_Cleanup() failed"); 534 } 535 536 free(local_send_buffer); 537 ssl_is_init = 0; 538 } 539 540 541 static void 542 mod_wolfssl_free_der_certs (buffer **certs) 543 { 544 if (NULL == certs) return; 545 for (int i = 0; NULL != certs[i]; ++i) 546 buffer_free(certs[i]); 547 free(certs); 548 } 549 550 551 static void 552 mod_openssl_free_config (server *srv, plugin_data * const p) 553 { 554 array_free(p->cafiles); 555 556 if (NULL != p->ssl_ctxs) { 557 SSL_CTX * const ssl_ctx_global_scope = p->ssl_ctxs->ssl_ctx; 558 /* free ssl_ctx from $SERVER["socket"] (if not copy of global scope) */ 559 for (uint32_t i = 1; i < srv->config_context->used; ++i) { 560 plugin_ssl_ctx * const s = p->ssl_ctxs + i; 561 if (s->ssl_ctx && s->ssl_ctx != ssl_ctx_global_scope) 562 SSL_CTX_free(s->ssl_ctx); 563 } 564 /* free ssl_ctx from global scope */ 565 if (ssl_ctx_global_scope) 566 SSL_CTX_free(ssl_ctx_global_scope); 567 free(p->ssl_ctxs); 568 } 569 570 if (NULL == p->cvlist) return; 571 /* (init i to 0 if global context; to 1 to skip empty global context) */ 572 for (int i = !p->cvlist[0].v.u2[1], used = p->nconfig; i < used; ++i) { 573 config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0]; 574 for (; -1 != cpv->k_id; ++cpv) { 575 switch (cpv->k_id) { 576 case 0: /* ssl.pemfile */ 577 if (cpv->vtype == T_CONFIG_LOCAL) { 578 plugin_cert *pc = cpv->v.v; 579 wolfSSL_OPENSSL_cleanse(pc->ssl_pemfile_pkey->ptr, 580 pc->ssl_pemfile_pkey->size); 581 buffer_free(pc->ssl_pemfile_pkey); 582 /*buffer_free(pc->ssl_pemfile_x509);*//*(part of chain)*/ 583 mod_wolfssl_free_der_certs(pc->ssl_pemfile_chain); 584 buffer_free(pc->ssl_stapling); 585 free(pc); 586 } 587 break; 588 case 2: /* ssl.ca-file */ 589 if (cpv->vtype == T_CONFIG_LOCAL) { 590 plugin_cacerts *cacerts = cpv->v.v; 591 wolfSSL_sk_X509_NAME_pop_free(cacerts->names, 592 X509_NAME_free); 593 wolfSSL_X509_STORE_free(cacerts->certs); 594 free(cacerts); 595 } 596 break; 597 case 3: /* ssl.ca-dn-file */ 598 if (cpv->vtype == T_CONFIG_LOCAL) 599 wolfSSL_sk_X509_NAME_pop_free(cpv->v.v, X509_NAME_free); 600 break; 601 default: 602 break; 603 } 604 } 605 } 606 } 607 608 609 /* WolfSSL OpenSSL compat API does not wipe temp mem used; write our own */ 610 /* (pemfile might contain private key)*/ 611 /* code here is based on similar code in mod_nss */ 612 #include "base64.h" 613 614 #define PEM_BEGIN "-----BEGIN " 615 #define PEM_END "-----END " 616 #define PEM_BEGIN_CERT "-----BEGIN CERTIFICATE-----" 617 #define PEM_END_CERT "-----END CERTIFICATE-----" 618 #define PEM_BEGIN_TRUSTED_CERT "-----BEGIN TRUSTED CERTIFICATE-----" 619 #define PEM_END_TRUSTED_CERT "-----END TRUSTED CERTIFICATE-----" 620 #define PEM_BEGIN_PKEY "-----BEGIN PRIVATE KEY-----" 621 #define PEM_END_PKEY "-----END PRIVATE KEY-----" 622 #define PEM_BEGIN_EC_PKEY "-----BEGIN EC PRIVATE KEY-----" 623 #define PEM_END_EC_PKEY "-----END EC PRIVATE KEY-----" 624 #define PEM_BEGIN_RSA_PKEY "-----BEGIN RSA PRIVATE KEY-----" 625 #define PEM_END_RSA_PKEY "-----END RSA PRIVATE KEY-----" 626 #define PEM_BEGIN_DSA_PKEY "-----BEGIN DSA PRIVATE KEY-----" 627 #define PEM_END_DSA_PKEY "-----END DSA PRIVATE KEY-----" 628 #define PEM_BEGIN_ANY_PKEY "-----BEGIN ANY PRIVATE KEY-----" 629 #define PEM_END_ANY_PKEY "-----END ANY PRIVATE KEY-----" 630 /* (not implemented: support to get password from user for encrypted key) */ 631 #define PEM_BEGIN_ENCRYPTED_PKEY "-----BEGIN ENCRYPTED PRIVATE KEY-----" 632 #define PEM_END_ENCRYPTED_PKEY "-----END ENCRYPTED PRIVATE KEY-----" 633 634 #define PEM_BEGIN_X509_CRL "-----BEGIN X509 CRL-----" 635 #define PEM_END_X509_CRL "-----END X509 CRL-----" 636 637 638 static buffer * 639 mod_wolfssl_load_pem_file (const char *fn, log_error_st *errh, buffer ***chain) 640 { 641 off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/ 642 char *data = fdevent_load_file(fn, &dlen, errh, malloc, free); 643 if (NULL == data) return NULL; 644 645 buffer **certs = NULL; 646 int rc = -1; 647 do { 648 int count = 0; 649 char *b = data; 650 for (; (b = strstr(b, PEM_BEGIN_CERT)); b += sizeof(PEM_BEGIN_CERT)-1) 651 ++count; 652 b = data; 653 for (; (b = strstr(b, PEM_BEGIN_TRUSTED_CERT)); 654 b += sizeof(PEM_BEGIN_TRUSTED_CERT)-1) 655 ++count; 656 if (0 == count) { 657 rc = 0; 658 break; 659 } 660 661 certs = malloc((count+1) * sizeof(buffer *)); 662 force_assert(NULL != certs); 663 certs[count] = NULL; 664 for (int i = 0; i < count; ++i) 665 certs[i] = buffer_init(); 666 667 buffer *der; 668 int i = 0; 669 for (char *e = data; (b = strstr(e, PEM_BEGIN_CERT)); ++i) { 670 b += sizeof(PEM_BEGIN_CERT)-1; 671 if (*b == '\r') ++b; 672 if (*b == '\n') ++b; 673 e = strstr(b, PEM_END_CERT); 674 if (NULL == e) break; 675 uint32_t len = (uint32_t)(e - b); 676 e += sizeof(PEM_END_CERT)-1; 677 if (i >= count) break; /*(should not happen)*/ 678 der = certs[i]; 679 if (NULL == buffer_append_base64_decode(der,b,len,BASE64_STANDARD)) 680 break; 681 } 682 for (char *e = data; (b = strstr(e, PEM_BEGIN_TRUSTED_CERT)); ++i) { 683 b += sizeof(PEM_BEGIN_TRUSTED_CERT)-1; 684 if (*b == '\r') ++b; 685 if (*b == '\n') ++b; 686 e = strstr(b, PEM_END_TRUSTED_CERT); 687 if (NULL == e) break; 688 uint32_t len = (uint32_t)(e - b); 689 e += sizeof(PEM_END_TRUSTED_CERT)-1; 690 if (i >= count) break; /*(should not happen)*/ 691 der = certs[i]; 692 if (NULL == buffer_append_base64_decode(der,b,len,BASE64_STANDARD)) 693 break; 694 } 695 if (i == count) 696 rc = 0; 697 else 698 errno = EIO; 699 } while (0); 700 701 if (dlen) ck_memzero(data, dlen); 702 free(data); 703 704 if (rc < 0) { 705 log_perror(errh, __FILE__, __LINE__, "error loading %s", fn); 706 mod_wolfssl_free_der_certs(certs); 707 certs = NULL; 708 } 709 710 *chain = certs; 711 return certs ? certs[0] : NULL; 712 } 713 714 715 static buffer * 716 mod_wolfssl_evp_pkey_load_pem_file (const char *fn, log_error_st *errh) 717 { 718 off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/ 719 char *data = fdevent_load_file(fn, &dlen, errh, malloc, free); 720 if (NULL == data) return NULL; 721 722 buffer *pkey = NULL; 723 int rc = -1; 724 do { 725 /*(expecting single private key in file, so first match)*/ 726 char *b, *e; 727 if ((b = strstr(data, PEM_BEGIN_PKEY)) 728 && (e = strstr(b, PEM_END_PKEY))) 729 b += sizeof(PEM_BEGIN_PKEY)-1; 730 else if ((b = strstr(data, PEM_BEGIN_EC_PKEY)) 731 && (e = strstr(b, PEM_END_EC_PKEY))) 732 b += sizeof(PEM_BEGIN_EC_PKEY)-1; 733 else if ((b = strstr(data, PEM_BEGIN_RSA_PKEY)) 734 && (e = strstr(b, PEM_END_RSA_PKEY))) 735 b += sizeof(PEM_BEGIN_RSA_PKEY)-1; 736 else if ((b = strstr(data, PEM_BEGIN_DSA_PKEY)) 737 && (e = strstr(b, PEM_END_DSA_PKEY))) 738 b += sizeof(PEM_BEGIN_DSA_PKEY)-1; 739 else if ((b = strstr(data, PEM_BEGIN_ANY_PKEY)) 740 && (e = strstr(b, PEM_END_ANY_PKEY))) 741 b += sizeof(PEM_BEGIN_ANY_PKEY)-1; 742 else 743 break; 744 if (*b == '\r') ++b; 745 if (*b == '\n') ++b; 746 747 pkey = buffer_init(); 748 size_t len = (size_t)(e - b); 749 if (NULL == buffer_append_base64_decode(pkey, b, len, BASE64_STANDARD)) 750 break; 751 rc = 0; 752 } while (0); 753 754 if (dlen) ck_memzero(data, dlen); 755 free(data); 756 757 if (rc < 0) { 758 log_error(errh, __FILE__, __LINE__, "%s() %s", __func__, fn); 759 if (pkey) { 760 wolfSSL_OPENSSL_cleanse(pkey->ptr, pkey->size); 761 buffer_free(pkey); 762 } 763 return NULL; 764 } 765 766 return pkey; 767 } 768 769 770 static int 771 mod_wolfssl_CTX_use_certificate_chain_file (WOLFSSL_CTX *ssl_ctx, const char *fn, log_error_st *errh) 772 { 773 /* (While it should be possible to parse DERs from (buffer **) 774 * s->pc->ssl_pemfile_chain, it is simpler to re-read file and use the 775 * built-in wolfSSL_CTX_use_certificate_chain_buffer() interface) */ 776 off_t dlen = 4*1024*1024;/*(arbitrary limit: 4 MB file; expect < 1 KB)*/ 777 char *data = fdevent_load_file(fn, &dlen, errh, malloc, free); 778 if (NULL == data) return -1; 779 780 int rc = wolfSSL_CTX_use_certificate_chain_buffer(ssl_ctx, 781 (unsigned char *)data, 782 (long)dlen); 783 784 if (dlen) ck_memzero(data, dlen); 785 free(data); 786 787 if (rc == WOLFSSL_SUCCESS) 788 return 1; 789 790 log_error(errh, __FILE__, __LINE__, 791 "SSL: %s %s", ERR_error_string(rc, NULL), fn); 792 return 0; 793 } 794 795 796 static STACK_OF(X509_NAME) * 797 mod_wolfssl_load_client_CA_file (const buffer *ssl_ca_file, log_error_st *errh) 798 { 799 /* similar to wolfSSL_load_client_CA_file(), plus some processing */ 800 buffer **certs = NULL; 801 if (NULL == mod_wolfssl_load_pem_file(ssl_ca_file->ptr, errh, &certs)) { 802 #if defined(__clang_analyzer__) || defined(__COVERITY__) 803 mod_wolfssl_free_der_certs(certs); /*unnecessary; quiet clang analyzer*/ 804 #endif 805 return NULL; 806 } 807 808 WOLF_STACK_OF(WOLFSSL_X509_NAME) *canames = wolfSSL_sk_X509_NAME_new(NULL); 809 if (NULL == canames) { 810 mod_wolfssl_free_der_certs(certs); 811 return NULL; 812 } 813 814 /* wolfSSL_sk_X509_NAME_push prior to version 4.8.0 returned 0 on success. 815 * The return value was changed to WOLFSSL_SUCCESS (not 0) from 4.8.0. */ 816 const int x = wolfSSL_lib_version_hex() < 0x04008000 ? 0 : WOLFSSL_SUCCESS; 817 for (int i = 0; NULL != certs[i]; ++i) { 818 WOLFSSL_X509 *ca = 819 wolfSSL_X509_load_certificate_buffer((unsigned char *)certs[i]->ptr, 820 (int)buffer_clen(certs[i]), 821 WOLFSSL_FILETYPE_ASN1); 822 WOLFSSL_X509_NAME *subj = NULL; 823 if (NULL == ca 824 || NULL == (subj = wolfSSL_X509_get_subject_name(ca)) 825 || x != wolfSSL_sk_X509_NAME_push(canames, 826 wolfSSL_X509_NAME_dup(subj))) { 827 log_error(errh, __FILE__, __LINE__, 828 "SSL: couldn't read X509 certificates from '%s'", 829 ssl_ca_file->ptr); 830 if (subj) wolfSSL_X509_NAME_free(subj); 831 if (ca) wolfSSL_X509_free(ca); 832 wolfSSL_sk_X509_NAME_free(canames); 833 mod_wolfssl_free_der_certs(certs); 834 return NULL; 835 } 836 837 wolfSSL_X509_free(ca); 838 } 839 840 mod_wolfssl_free_der_certs(certs); 841 return canames; 842 } 843 844 845 static plugin_cacerts * 846 mod_wolfssl_load_cacerts (const buffer *ssl_ca_file, log_error_st *errh) 847 { 848 /* similar to mod_wolfSSL_load_client_CA_file(), plus some processing */ 849 /* similar to wolfSSL_load_client_CA_file(), plus some processing */ 850 buffer **certs = NULL; 851 if (NULL == mod_wolfssl_load_pem_file(ssl_ca_file->ptr, errh, &certs)) { 852 #if defined(__clang_analyzer__) || defined(__COVERITY__) 853 mod_wolfssl_free_der_certs(certs); /*unnecessary; quiet clang analyzer*/ 854 #endif 855 return NULL; 856 } 857 858 WOLFSSL_X509_STORE *castore = wolfSSL_X509_STORE_new(); 859 if (NULL == castore) { 860 mod_wolfssl_free_der_certs(certs); 861 return NULL; 862 } 863 864 WOLF_STACK_OF(WOLFSSL_X509_NAME) *canames = wolfSSL_sk_X509_NAME_new(NULL); 865 if (NULL == canames) { 866 wolfSSL_X509_STORE_free(castore); 867 mod_wolfssl_free_der_certs(certs); 868 return NULL; 869 } 870 871 /* wolfSSL_sk_X509_NAME_push prior to version 4.8.0 returned 0 on success. 872 * The return value was changed to WOLFSSL_SUCCESS (not 0) from 4.8.0. */ 873 const int x = wolfSSL_lib_version_hex() < 0x04008000 ? 0 : WOLFSSL_SUCCESS; 874 for (int i = 0; NULL != certs[i]; ++i) { 875 WOLFSSL_X509 *ca = 876 wolfSSL_X509_load_certificate_buffer((unsigned char *)certs[i]->ptr, 877 (int)buffer_clen(certs[i]), 878 WOLFSSL_FILETYPE_ASN1); 879 WOLFSSL_X509_NAME *subj = NULL; 880 if (NULL == ca || !wolfSSL_X509_STORE_add_cert(castore, ca) 881 || NULL == (subj = wolfSSL_X509_get_subject_name(ca)) 882 || x != wolfSSL_sk_X509_NAME_push(canames, 883 wolfSSL_X509_NAME_dup(subj))) { 884 log_error(errh, __FILE__, __LINE__, 885 "SSL: couldn't read X509 certificates from '%s'", 886 ssl_ca_file->ptr); 887 if (subj) wolfSSL_X509_NAME_free(subj); 888 if (ca) wolfSSL_X509_free(ca); 889 wolfSSL_sk_X509_NAME_free(canames); 890 wolfSSL_X509_STORE_free(castore); 891 mod_wolfssl_free_der_certs(certs); 892 return NULL; 893 } 894 895 wolfSSL_X509_free(ca); 896 } 897 898 mod_wolfssl_free_der_certs(certs); 899 900 plugin_cacerts *cacerts = malloc(sizeof(plugin_cacerts)); 901 force_assert(cacerts); 902 903 cacerts->names = canames; 904 cacerts->certs = castore; 905 return cacerts; 906 } 907 908 909 static int 910 mod_wolfssl_load_cacrls (WOLFSSL_CTX *ssl_ctx, const buffer *ssl_ca_crl_file, server *srv) 911 { 912 #ifdef HAVE_CRL /* <wolfssl/options.h> */ 913 int rc = wolfSSL_CTX_EnableCRL(ssl_ctx, 914 WOLFSSL_CRL_CHECK | WOLFSSL_CRL_CHECKALL); 915 if (rc != WOLFSSL_SUCCESS) return 0; 916 917 const char *fn = ssl_ca_crl_file->ptr; 918 off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/ 919 char *data = fdevent_load_file(fn, &dlen, srv->errh, malloc, free); 920 if (NULL == data) return 0; 921 922 rc = wolfSSL_CTX_LoadCRLBuffer(ssl_ctx, (byte *)data, (long)dlen, 923 WOLFSSL_FILETYPE_PEM); 924 925 if (dlen) ck_memzero(data, dlen); 926 free(data); 927 928 if (rc == WOLFSSL_SUCCESS) 929 return 1; 930 931 log_error(srv->errh, __FILE__, __LINE__, 932 "SSL: %s %s", ERR_error_string(rc, NULL), fn); 933 return 0; 934 #else 935 UNUSED(ssl_ctx); 936 log_error(srv->errh, __FILE__, __LINE__, 937 "WolfSSL not built with CRL support; ignoring %s", ssl_ca_crl_file->ptr); 938 return WOLFSSL_FAILURE; 939 #endif 940 } 941 942 943 static int 944 mod_wolfssl_load_verify_locn (SSL_CTX *ssl_ctx, const buffer *b, server *srv) 945 { 946 const char *fn = b->ptr; 947 off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/ 948 char *data = fdevent_load_file(fn, &dlen, srv->errh, malloc, free); 949 if (NULL == data) return 0; 950 951 int rc = wolfSSL_CTX_load_verify_buffer(ssl_ctx, (unsigned char *)data, 952 (long)dlen, WOLFSSL_FILETYPE_PEM); 953 954 if (dlen) ck_memzero(data, dlen); 955 free(data); 956 957 if (rc == WOLFSSL_SUCCESS) 958 return 1; 959 960 log_error(srv->errh, __FILE__, __LINE__, 961 "SSL: %s %s", ERR_error_string(rc, NULL), fn); 962 return 0; 963 } 964 965 966 static int 967 mod_wolfssl_load_ca_files (SSL_CTX *ssl_ctx, plugin_data *p, server *srv) 968 { 969 /* load all ssl.ca-files specified in the config into each SSL_CTX */ 970 971 for (uint32_t i = 0, used = p->cafiles->used; i < used; ++i) { 972 const buffer *b = &((data_string *)p->cafiles->data[i])->value; 973 if (!mod_wolfssl_load_verify_locn(ssl_ctx, b, srv)) 974 return 0; 975 } 976 return 1; 977 } 978 979 980 FREE_FUNC(mod_openssl_free) 981 { 982 plugin_data *p = p_d; 983 if (NULL == p->srv) return; 984 mod_openssl_free_config(p->srv, p); 985 mod_openssl_free_openssl(); 986 } 987 988 989 static void 990 mod_openssl_merge_config_cpv (plugin_config * const pconf, const config_plugin_value_t * const cpv) 991 { 992 switch (cpv->k_id) { /* index into static config_plugin_keys_t cpk[] */ 993 case 0: /* ssl.pemfile */ 994 if (cpv->vtype == T_CONFIG_LOCAL) 995 pconf->pc = cpv->v.v; 996 break; 997 case 1: /* ssl.privkey */ 998 break; 999 case 2: /* ssl.ca-file */ 1000 if (cpv->vtype == T_CONFIG_LOCAL) 1001 pconf->ssl_ca_file = cpv->v.v; 1002 break; 1003 case 3: /* ssl.ca-dn-file */ 1004 if (cpv->vtype == T_CONFIG_LOCAL) 1005 pconf->ssl_ca_dn_file = cpv->v.v; 1006 break; 1007 case 4: /* ssl.ca-crl-file */ 1008 pconf->ssl_ca_crl_file = cpv->v.b; 1009 break; 1010 case 5: /* ssl.read-ahead */ 1011 pconf->ssl_read_ahead = (0 != cpv->v.u); 1012 break; 1013 case 6: /* ssl.disable-client-renegotiation */ 1014 pconf->ssl_disable_client_renegotiation = (0 != cpv->v.u); 1015 break; 1016 case 7: /* ssl.verifyclient.activate */ 1017 pconf->ssl_verifyclient = (0 != cpv->v.u); 1018 break; 1019 case 8: /* ssl.verifyclient.enforce */ 1020 pconf->ssl_verifyclient_enforce = (0 != cpv->v.u); 1021 break; 1022 case 9: /* ssl.verifyclient.depth */ 1023 pconf->ssl_verifyclient_depth = (unsigned char)cpv->v.shrt; 1024 break; 1025 case 10:/* ssl.verifyclient.username */ 1026 pconf->ssl_verifyclient_username = cpv->v.b; 1027 break; 1028 case 11:/* ssl.verifyclient.exportcert */ 1029 pconf->ssl_verifyclient_export_cert = (0 != cpv->v.u); 1030 break; 1031 case 12:/* ssl.acme-tls-1 */ 1032 pconf->ssl_acme_tls_1 = cpv->v.b; 1033 break; 1034 case 13:/* ssl.stapling-file */ 1035 break; 1036 case 14:/* debug.log-ssl-noise */ 1037 pconf->ssl_log_noise = (0 != cpv->v.u); 1038 break; 1039 #if 0 /*(cpk->k_id remapped in mod_openssl_set_defaults())*/ 1040 case 15:/* ssl.verifyclient.ca-file */ 1041 case 16:/* ssl.verifyclient.ca-dn-file */ 1042 case 17:/* ssl.verifyclient.ca-crl-file */ 1043 break; 1044 #endif 1045 default:/* should not happen */ 1046 return; 1047 } 1048 } 1049 1050 1051 static void 1052 mod_openssl_merge_config(plugin_config * const pconf, const config_plugin_value_t *cpv) 1053 { 1054 do { 1055 mod_openssl_merge_config_cpv(pconf, cpv); 1056 } while ((++cpv)->k_id != -1); 1057 } 1058 1059 1060 static void 1061 mod_openssl_patch_config (request_st * const r, plugin_config * const pconf) 1062 { 1063 plugin_data * const p = plugin_data_singleton; 1064 memcpy(pconf, &p->defaults, sizeof(plugin_config)); 1065 for (int i = 1, used = p->nconfig; i < used; ++i) { 1066 if (config_check_cond(r, (uint32_t)p->cvlist[i].k_id)) 1067 mod_openssl_merge_config(pconf, p->cvlist + p->cvlist[i].v.u2[0]); 1068 } 1069 } 1070 1071 1072 static int 1073 safer_X509_NAME_oneline(X509_NAME *name, char *buf, size_t sz) 1074 { 1075 #if LIBWOLFSSL_VERSION_HEX < 0x04003000 1076 UNUSED(name); 1077 UNUSED(sz); 1078 #else 1079 if (wolfSSL_X509_get_name_oneline(name, buf, (int)sz)) 1080 return (int)strlen(buf); 1081 else 1082 #endif 1083 { 1084 buf[0] = '\0'; 1085 return -1; 1086 } 1087 } 1088 1089 1090 static void 1091 ssl_info_callback (const SSL *ssl, int where, int ret) 1092 { 1093 UNUSED(ret); 1094 1095 if (0 != (where & SSL_CB_HANDSHAKE_START)) { 1096 handler_ctx *hctx = (handler_ctx *) SSL_get_app_data(ssl); 1097 if (hctx->renegotiations >= 0) ++hctx->renegotiations; 1098 } 1099 /* https://github.com/openssl/openssl/issues/5721 1100 * "TLSv1.3 unexpected InfoCallback after handshake completed" */ 1101 if (0 != (where & SSL_CB_HANDSHAKE_DONE)) { 1102 /* SSL_version() is valid after initial handshake completed */ 1103 SSL *ssl_nonconst; 1104 *(const SSL **)&ssl_nonconst = ssl; 1105 if (wolfSSL_GetVersion(ssl_nonconst) >= WOLFSSL_TLSV1_3) { 1106 /* https://wiki.openssl.org/index.php/TLS1.3 1107 * "Renegotiation is not possible in a TLSv1.3 connection" */ 1108 handler_ctx *hctx = (handler_ctx *) SSL_get_app_data(ssl); 1109 hctx->renegotiations = -1; 1110 } 1111 } 1112 } 1113 1114 /* https://wiki.openssl.org/index.php/Manual:SSL_CTX_set_verify(3)#EXAMPLES */ 1115 static int 1116 verify_callback(int preverify_ok, X509_STORE_CTX *ctx) 1117 { 1118 char buf[256]; 1119 X509 *err_cert; 1120 int err, depth; 1121 SSL *ssl; 1122 handler_ctx *hctx; 1123 1124 err = X509_STORE_CTX_get_error(ctx); 1125 depth = X509_STORE_CTX_get_error_depth(ctx); 1126 1127 /* 1128 * Retrieve the pointer to the SSL of the connection currently treated 1129 * and the application specific data stored into the SSL object. 1130 */ 1131 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); 1132 hctx = (handler_ctx *) SSL_get_app_data(ssl); 1133 1134 /* 1135 * Catch a too long certificate chain. The depth limit set using 1136 * wolfSSL_CTX_set_verify_depth() is by purpose set to "limit+1" so 1137 * that whenever the "depth>verify_depth" condition is met, we 1138 * have violated the limit and want to log this error condition. 1139 * We must do it here, because the CHAIN_TOO_LONG error would not 1140 * be found explicitly; only errors introduced by cutting off the 1141 * additional certificates would be logged. 1142 */ 1143 if (depth > hctx->conf.ssl_verifyclient_depth) { 1144 preverify_ok = 0; 1145 err = X509_V_ERR_CERT_CHAIN_TOO_LONG; 1146 X509_STORE_CTX_set_error(ctx, err); 1147 } 1148 1149 if (preverify_ok && 0 == depth && NULL != hctx->conf.ssl_ca_dn_file) { 1150 /* verify that client cert is issued by CA in ssl.ca-dn-file 1151 * if both ssl.ca-dn-file and ssl.ca-file were configured */ 1152 STACK_OF(X509_NAME) * const cert_names = hctx->conf.ssl_ca_dn_file; 1153 X509_NAME *issuer; 1154 err_cert = ctx->current_cert;/*wolfSSL_X509_STORE_CTX_get_current_cert*/ 1155 if (NULL == err_cert) return !hctx->conf.ssl_verifyclient_enforce; 1156 issuer = X509_get_issuer_name(err_cert); 1157 #if 0 /*(?desirable/undesirable to have cert_names sorted?)*/ 1158 if (-1 != sk_X509_NAME_find(cert_names, issuer)) 1159 return preverify_ok; /* match */ 1160 #else 1161 for (int i=0, len=wolfSSL_sk_X509_NAME_num(cert_names); i < len; ++i) { 1162 if (0 == wolfSSL_X509_NAME_cmp(sk_X509_NAME_value(cert_names, i), 1163 issuer)) 1164 return preverify_ok; /* match */ 1165 } 1166 #endif 1167 1168 preverify_ok = 0; 1169 err = X509_V_ERR_CERT_REJECTED; 1170 X509_STORE_CTX_set_error(ctx, err); 1171 } 1172 1173 if (preverify_ok) { 1174 return preverify_ok; 1175 } 1176 1177 err_cert = ctx->current_cert; /*wolfSSL_X509_STORE_CTX_get_current_cert()*/ 1178 if (NULL == err_cert) return !hctx->conf.ssl_verifyclient_enforce; 1179 safer_X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof(buf)); 1180 log_error_st *errh = hctx->r->conf.errh; 1181 log_error(errh, __FILE__, __LINE__, 1182 "SSL: verify error:num=%d:%s:depth=%d:subject=%s", 1183 err, X509_verify_cert_error_string(err), depth, buf); 1184 1185 /* 1186 * At this point, err contains the last verification error. We can use 1187 * it for something special 1188 */ 1189 if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY || 1190 err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) { 1191 safer_X509_NAME_oneline(X509_get_issuer_name(err_cert),buf,sizeof(buf)); 1192 log_error(errh, __FILE__, __LINE__, "SSL: issuer=%s", buf); 1193 } 1194 1195 return !hctx->conf.ssl_verifyclient_enforce; 1196 } 1197 1198 static int 1199 mod_openssl_cert_cb (SSL *ssl, void *arg) 1200 { 1201 handler_ctx *hctx = (handler_ctx *) SSL_get_app_data(ssl); 1202 plugin_cert *pc = hctx->conf.pc; 1203 UNUSED(arg); 1204 1205 if (!pc || NULL == pc->ssl_pemfile_x509 || NULL == pc->ssl_pemfile_pkey) { 1206 /* x509/pkey available <=> pemfile was set <=> pemfile got patched: 1207 * so this should never happen, unless you nest $SERVER["socket"] */ 1208 log_error(hctx->r->conf.errh, __FILE__, __LINE__, 1209 "SSL: no certificate/private key for TLS server name \"%s\". " 1210 "$SERVER[\"socket\"] should not be nested in other conditions.", 1211 hctx->r->uri.authority.ptr); 1212 return 0; 1213 } 1214 1215 /* first set certificate! 1216 * setting private key checks whether certificate matches it */ 1217 buffer *cert = pc->ssl_pemfile_x509; 1218 if (1 != wolfSSL_use_certificate_ASN1(ssl, (unsigned char *)cert->ptr, 1219 (int)buffer_clen(cert))) { 1220 log_error(hctx->r->conf.errh, __FILE__, __LINE__, 1221 "SSL: failed to set certificate for TLS server name %s: %s", 1222 hctx->r->uri.authority.ptr, ERR_error_string(ERR_get_error(), NULL)); 1223 return 0; 1224 } 1225 1226 buffer *pkey = pc->ssl_pemfile_pkey; 1227 if (1 != wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char *)pkey->ptr, 1228 (int)buffer_clen(pkey), 1229 WOLFSSL_FILETYPE_ASN1)) { 1230 log_error(hctx->r->conf.errh, __FILE__, __LINE__, 1231 "SSL: failed to set private key for TLS server name %s: %s", 1232 hctx->r->uri.authority.ptr, ERR_error_string(ERR_get_error(), NULL)); 1233 return 0; 1234 } 1235 1236 if (hctx->conf.ssl_verifyclient) { 1237 if (NULL == hctx->conf.ssl_ca_file) { 1238 log_error(hctx->r->conf.errh, __FILE__, __LINE__, 1239 "SSL: can't verify client without ssl.verifyclient.ca-file " 1240 "for TLS server name %s", hctx->r->uri.authority.ptr); 1241 return 0; 1242 } 1243 /* WolfSSL does not support setting per-session CA list; 1244 * limitation is to per-CTX CA list, and is not changed after SNI */ 1245 int mode = SSL_VERIFY_PEER; 1246 if (hctx->conf.ssl_verifyclient_enforce) 1247 mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; 1248 wolfSSL_set_verify(ssl, mode, verify_callback); 1249 wolfSSL_set_verify_depth(ssl, hctx->conf.ssl_verifyclient_depth + 1); 1250 } 1251 else { 1252 wolfSSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); 1253 } 1254 1255 return 1; 1256 } 1257 1258 #ifdef HAVE_TLS_EXTENSIONS 1259 1260 enum { 1261 MOD_OPENSSL_ALPN_HTTP11 = 1 1262 ,MOD_OPENSSL_ALPN_HTTP10 = 2 1263 ,MOD_OPENSSL_ALPN_H2 = 3 1264 ,MOD_OPENSSL_ALPN_ACME_TLS_1 = 4 1265 }; 1266 1267 static int 1268 mod_openssl_SNI (handler_ctx *hctx, const char *servername, size_t len) 1269 { 1270 request_st * const r = hctx->r; 1271 if (len >= 1024) { /*(expecting < 256; TLSEXT_MAXLEN_host_name is 255)*/ 1272 log_error(r->conf.errh, __FILE__, __LINE__, 1273 "SSL: SNI name too long %.*s", (int)len, servername); 1274 return SSL_TLSEXT_ERR_ALERT_FATAL; 1275 } 1276 1277 /* use SNI to patch mod_openssl config and then reset COMP_HTTP_HOST */ 1278 buffer_copy_string_len_lc(&r->uri.authority, servername, len); 1279 #if 0 1280 /*(r->uri.authority used below for configuration before request read; 1281 * revisit for h2)*/ 1282 if (0 != http_request_host_policy(&r->uri.authority, 1283 r->conf.http_parseopts, 443)) 1284 return SSL_TLSEXT_ERR_ALERT_FATAL; 1285 #endif 1286 1287 r->conditional_is_valid |= (1 << COMP_HTTP_SCHEME) 1288 | (1 << COMP_HTTP_HOST); 1289 mod_openssl_patch_config(r, &hctx->conf); 1290 /* reset COMP_HTTP_HOST so that conditions re-run after request hdrs read */ 1291 /*(done in response.c:config_cond_cache_reset() after request hdrs read)*/ 1292 /*config_cond_cache_reset_item(r, COMP_HTTP_HOST);*/ 1293 /*buffer_clear(&r->uri.authority);*/ 1294 1295 return (mod_openssl_cert_cb(hctx->ssl, NULL) == 1) 1296 ? SSL_TLSEXT_ERR_OK 1297 : SSL_TLSEXT_ERR_ALERT_FATAL; 1298 } 1299 1300 static int 1301 network_ssl_servername_callback (SSL *ssl, int *al, void *srv) 1302 { 1303 handler_ctx *hctx = (handler_ctx *) SSL_get_app_data(ssl); 1304 #ifdef HAVE_ALPN 1305 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation 1306 /*(do not repeat if acme-tls/1 creds have been set 1307 * and still in handshake (hctx->alpn not unset yet))*/ 1308 if (hctx->alpn == MOD_OPENSSL_ALPN_ACME_TLS_1) 1309 return SSL_TLSEXT_ERR_OK; /*(wolfSSL might call twice in client hello)*/ 1310 #endif 1311 #endif 1312 if (hctx->r->conditional_is_valid & (1 << COMP_HTTP_HOST))/*(already done)*/ 1313 return SSL_TLSEXT_ERR_OK; /*(wolfSSL might call twice in client hello)*/ 1314 buffer_copy_string_len(&hctx->r->uri.scheme, CONST_STR_LEN("https")); 1315 UNUSED(al); 1316 UNUSED(srv); 1317 1318 const char *servername; 1319 size_t len = (size_t) 1320 #ifdef HAVE_SNI 1321 wolfSSL_SNI_GetRequest(ssl, WOLFSSL_SNI_HOST_NAME, (void **)&servername); 1322 #else 1323 0; 1324 #endif 1325 if (0 == len) 1326 return SSL_TLSEXT_ERR_NOACK; /* client did not provide SNI */ 1327 #if 0 /* WolfSSL does not provide per-session SSL_set_read_ahead() */ 1328 int read_ahead = hctx->conf.ssl_read_ahead; 1329 int rc = mod_openssl_SNI(hctx, servername, len); 1330 if (!read_ahead && hctx->conf.ssl_read_ahead) 1331 SSL_set_read_ahead(ssl, hctx->conf.ssl_read_ahead); 1332 return rc; 1333 #else 1334 return mod_openssl_SNI(hctx, servername, len); 1335 #endif 1336 } 1337 1338 #endif /* HAVE_TLS_EXTENSIONS */ 1339 1340 1341 #ifdef HAVE_OCSP 1342 1343 #define OCSP_RESPONSE OcspResponse 1344 #define OCSP_RESPONSE_free wolfSSL_OCSP_RESPONSE_free 1345 #define d2i_OCSP_RESPONSE_bio wolfSSL_d2i_OCSP_RESPONSE_bio 1346 #define d2i_OCSP_RESPONSE wolfSSL_d2i_OCSP_RESPONSE 1347 #define i2d_OCSP_RESPONSE wolfSSL_i2d_OCSP_RESPONSE 1348 1349 static buffer * 1350 mod_openssl_load_stapling_file (const char *file, log_error_st *errh, buffer *b) 1351 { 1352 /* load stapling .der into buffer *b only if successful 1353 * 1354 * Note: for some TLS libs, the OCSP stapling response is not copied when 1355 * assigned to a session (and is reasonable since not changed frequently) 1356 * - BoringSSL SSL_set_ocsp_response() 1357 * - WolfSSL SSL_set_tlsext_status_ocsp_resp() (differs from OpenSSL API) 1358 * Therefore, there is a potential race condition if the OCSP response is 1359 * assigned to the session during the handshake and the Server Hello is 1360 * partially sent, AND (unlikely, if possible at all), the TLS library is 1361 * in the middle of reading this OSCP response buffer. If the OCSP response 1362 * is replaced due to an updated ssl.stapling-file (checked periodically), 1363 * AND the buffer is resized, this would be a problem. Resizing the buffer 1364 * is unlikely since updated OSCP response for same certificate are 1365 * typically the same size with the signature and dates refreshed. 1366 */ 1367 1368 /* load raw .der file */ 1369 off_t dlen = 1*1024*1024;/*(arbitrary limit: 1 MB file; expect < 1 KB)*/ 1370 char *data = fdevent_load_file(file, &dlen, errh, malloc, free); 1371 if (NULL == data) return NULL; 1372 1373 if (NULL == b) 1374 b = buffer_init(); 1375 else if (b->ptr) 1376 free(b->ptr); 1377 b->ptr = data; 1378 b->used = (uint32_t)dlen; 1379 b->size = (uint32_t)dlen+1; 1380 return b; 1381 } 1382 1383 1384 static unix_time64_t 1385 mod_openssl_asn1_time_to_posix (ASN1_TIME *asn1time) 1386 { 1387 #if LIBWOLFSSL_VERSION_HEX >= 0x04002000 1388 /* Note: up to at least wolfSSL 4.5.0 (current version as this is written) 1389 * wolfSSL_ASN1_TIME_diff() is a stub function which always returns 0 */ 1390 /* Note: this does not check for integer overflow of time_t! */ 1391 int day, sec; 1392 return wolfSSL_ASN1_TIME_diff(&day, &sec, NULL, asn1time) 1393 ? log_epoch_secs + day*86400 + sec 1394 : -1; 1395 #else 1396 UNUSED(asn1time); 1397 return -1; 1398 #endif 1399 } 1400 1401 1402 static unix_time64_t 1403 mod_openssl_ocsp_next_update (plugin_cert *pc) 1404 { 1405 #if defined(WOLFSSL_VERSION) 1406 /* XXX: future TODO */ 1407 UNUSED(pc); 1408 (void)mod_openssl_asn1_time_to_posix(NULL); 1409 return -1; /*(not implemented)*/ 1410 #else 1411 buffer *der = pc->ssl_stapling; 1412 const unsigned char *p = (unsigned char *)der->ptr; /*(p gets modified)*/ 1413 OCSP_RESPONSE *ocsp = d2i_OCSP_RESPONSE(NULL, &p, buffer_clen(der)); 1414 if (NULL == ocsp) return -1; 1415 OCSP_BASICRESP *bs = OCSP_response_get1_basic(ocsp); 1416 if (NULL == bs) { 1417 OCSP_RESPONSE_free(ocsp); 1418 return -1; 1419 } 1420 1421 /* XXX: should save and evaluate cert status returned by these calls */ 1422 ASN1_TIME *nextupd = NULL; 1423 #ifdef WOLFSSL_VERSION /* WolfSSL limitation */ 1424 /* WolfSSL does not provide OCSP_resp_get0() OCSP_single_get0_status() */ 1425 /* (inactive code path; alternative path followed in #if above for WolfSSL) 1426 * (chain not currently available in mod_openssl when used with WolfSSL) 1427 * (For WolfSSL, pc->ssl_pemfile_chain might not be filled in with actual 1428 * chain, but is used to store (buffer **) of DER decoded from PEM certs 1429 * read from ssl.pemfile, which may be a single cert, pc->ssl_pemfile_x509. 1430 * The chain is not calculated or filled in if single cert, and neither are 1431 * (X509 *), though (X509 *) could be temporarily created to calculated 1432 * (OCSP_CERTID *), which additionally could be calculated once at startup) 1433 */ 1434 OCSP_CERTID *id = (NULL != pc->ssl_pemfile_chain) 1435 ? OCSP_cert_to_id(NULL, pc->ssl_pemfile_x509, 1436 sk_X509_value(pc->ssl_pemfile_chain, 0)) 1437 : NULL; 1438 if (id == NULL) { 1439 OCSP_BASICRESP_free(bs); 1440 OCSP_RESPONSE_free(ocsp); 1441 return -1; 1442 } 1443 OCSP_resp_find_status(bs, id, NULL, NULL, NULL, NULL, &nextupd); 1444 OCSP_CERTID_free(id); 1445 #else 1446 OCSP_single_get0_status(OCSP_resp_get0(bs, 0), NULL, NULL, NULL, &nextupd); 1447 #endif 1448 unix_time64_t t = nextupd ? mod_openssl_asn1_time_to_posix(nextupd) : -1; 1449 1450 /* Note: trust external process which creates ssl.stapling-file to verify 1451 * (as well as to validate certificate status) 1452 * future: verify OCSP response here to double-check */ 1453 1454 OCSP_BASICRESP_free(bs); 1455 OCSP_RESPONSE_free(ocsp); 1456 1457 return t; 1458 #endif 1459 } 1460 1461 1462 __attribute_cold__ 1463 static void 1464 mod_openssl_expire_stapling_file (server *srv, plugin_cert *pc) 1465 { 1466 if (NULL == pc->ssl_stapling) /*(previously discarded or never loaded)*/ 1467 return; 1468 1469 /* discard expired OCSP stapling response */ 1470 buffer_free(pc->ssl_stapling); 1471 pc->ssl_stapling = NULL; 1472 if (pc->must_staple) 1473 log_error(srv->errh, __FILE__, __LINE__, 1474 "certificate marked OCSP Must-Staple, " 1475 "but OCSP response expired from ssl.stapling-file %s", 1476 pc->ssl_stapling_file->ptr); 1477 } 1478 1479 1480 static int 1481 mod_openssl_reload_stapling_file (server *srv, plugin_cert *pc, const unix_time64_t cur_ts) 1482 { 1483 buffer *b = mod_openssl_load_stapling_file(pc->ssl_stapling_file->ptr, 1484 srv->errh, pc->ssl_stapling); 1485 if (!b) return 0; 1486 1487 pc->ssl_stapling = b; /*(unchanged unless orig was NULL)*/ 1488 pc->ssl_stapling_loadts = cur_ts; 1489 pc->ssl_stapling_nextts = mod_openssl_ocsp_next_update(pc); 1490 if (pc->ssl_stapling_nextts == -1) { 1491 /* "Next Update" might not be provided by OCSP responder 1492 * Use 3600 sec (1 hour) in that case. */ 1493 /* retry in 1 hour if unable to determine Next Update */ 1494 pc->ssl_stapling_nextts = cur_ts + 3600; 1495 pc->ssl_stapling_loadts = 0; 1496 } 1497 else if (pc->ssl_stapling_nextts < cur_ts) { 1498 mod_openssl_expire_stapling_file(srv, pc); 1499 return 0; 1500 } 1501 1502 return 1; 1503 } 1504 1505 1506 static int 1507 mod_openssl_refresh_stapling_file (server *srv, plugin_cert *pc, const unix_time64_t cur_ts) 1508 { 1509 if (pc->ssl_stapling && pc->ssl_stapling_nextts > cur_ts + 256) 1510 return 1; /* skip check for refresh unless close to expire */ 1511 struct stat st; 1512 if (0 != stat(pc->ssl_stapling_file->ptr, &st) 1513 || TIME64_CAST(st.st_mtime) <= pc->ssl_stapling_loadts) { 1514 if (pc->ssl_stapling && pc->ssl_stapling_nextts < cur_ts) 1515 mod_openssl_expire_stapling_file(srv, pc); 1516 return 1; 1517 } 1518 return mod_openssl_reload_stapling_file(srv, pc, cur_ts); 1519 } 1520 1521 1522 static void 1523 mod_openssl_refresh_stapling_files (server *srv, const plugin_data *p, const unix_time64_t cur_ts) 1524 { 1525 /* future: might construct array of (plugin_cert *) at startup 1526 * to avoid the need to search for them here */ 1527 /* (init i to 0 if global context; to 1 to skip empty global context) */ 1528 if (NULL == p->cvlist) return; 1529 for (int i = !p->cvlist[0].v.u2[1], used = p->nconfig; i < used; ++i) { 1530 const config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0]; 1531 for (; cpv->k_id != -1; ++cpv) { 1532 if (cpv->k_id != 0) continue; /* k_id == 0 for ssl.pemfile */ 1533 if (cpv->vtype != T_CONFIG_LOCAL) continue; 1534 plugin_cert *pc = cpv->v.v; 1535 if (pc->ssl_stapling_file) 1536 mod_openssl_refresh_stapling_file(srv, pc, cur_ts); 1537 } 1538 } 1539 } 1540 1541 1542 static int 1543 mod_openssl_crt_must_staple (const WOLFSSL_X509 *crt) 1544 { 1545 /* XXX: TODO: not implemented */ 1546 #if 1 1547 UNUSED(crt); 1548 return 0; 1549 #else 1550 STACK_OF(ASN1_OBJECT) * const tlsf = (STACK_OF(ASN1_OBJECT)*) 1551 wolfSSL_X509_get_ext_d2i(crt, NID_tlsfeature, NULL, NULL); 1552 if (NULL == tlsf) return 0; 1553 1554 int rc = 0; 1555 1556 /* wolfSSL_sk_ASN1_INTEGER_num() not implemented */ 1557 /* wolfSSL_sk_ASN1_INTEGER_value() not implemented */ 1558 /* wolfSSL_sk_ASN1_INTEGER_pop_free() not implemented */ 1559 #define wolfSSL_sk_ASN1_INTEGER_num(sk) wolfSSL_sk_num(sk) 1560 #define wolfSSL_sk_ASN1_INTEGER_value(sk, i) wolfSSL_sk_value(sk, i) 1561 #define wolfSSL_sk_ASN1_INTEGER_pop_free(sk, fn) wolfSSL_sk_pop_free(sk, fn) 1562 1563 /* wolfSSL_ASN1_INTEGER_get() is a stub func <= 4.6.0; always returns 0 */ 1564 1565 for (int i = 0; i < wolfSSL_sk_ASN1_INTEGER_num(tlsf); ++i) { 1566 WOLFSSL_ASN1_INTEGER *ai = wolfSSL_sk_ASN1_INTEGER_value(tlsf, i); 1567 long tlsextid = wolfSSL_ASN1_INTEGER_get(ai); 1568 if (tlsextid == 5) { /* 5 = OCSP Must-Staple */ 1569 rc = 1; 1570 break; 1571 } 1572 } 1573 1574 wolfSSL_sk_ASN1_INTEGER_pop_free(tlsf, wolfSSL_ASN1_INTEGER_free); 1575 return rc; /* 1 if OCSP Must-Staple found; 0 if not */ 1576 #endif 1577 } 1578 1579 #endif /* HAVE_OCSP */ 1580 1581 1582 static plugin_cert * 1583 network_openssl_load_pemfile (server *srv, const buffer *pemfile, const buffer *privkey, const buffer *ssl_stapling_file) 1584 { 1585 if (!mod_openssl_init_once_openssl(srv)) return NULL; 1586 1587 buffer **ssl_pemfile_chain = NULL; 1588 buffer *ssl_pemfile_x509 = 1589 mod_wolfssl_load_pem_file(pemfile->ptr, srv->errh, &ssl_pemfile_chain); 1590 if (NULL == ssl_pemfile_x509) { 1591 #if defined(__clang_analyzer__) || defined(__COVERITY__) 1592 mod_wolfssl_free_der_certs(ssl_pemfile_chain); /*unnecessary*/ 1593 #endif 1594 return NULL; 1595 } 1596 1597 buffer *ssl_pemfile_pkey = 1598 mod_wolfssl_evp_pkey_load_pem_file(privkey->ptr, srv->errh); 1599 if (NULL == ssl_pemfile_pkey) { 1600 /*buffer_free(ssl_pemfile_x509);*//*(part of chain)*/ 1601 mod_wolfssl_free_der_certs(ssl_pemfile_chain); 1602 return NULL; 1603 } 1604 1605 /* X509_check_private_key() is a stub func (not implemented) in WolfSSL */ 1606 1607 plugin_cert *pc = malloc(sizeof(plugin_cert)); 1608 force_assert(pc); 1609 pc->ssl_pemfile_pkey = ssl_pemfile_pkey; 1610 pc->ssl_pemfile_x509 = ssl_pemfile_x509; 1611 pc->ssl_pemfile_chain= ssl_pemfile_chain; 1612 pc->ssl_pemfile = pemfile; 1613 pc->ssl_privkey = privkey; 1614 pc->ssl_stapling = NULL; 1615 pc->ssl_stapling_file= ssl_stapling_file; 1616 pc->ssl_stapling_loadts = 0; 1617 pc->ssl_stapling_nextts = 0; 1618 #ifdef HAVE_OCSP 1619 /*(not implemented for WolfSSL, though could convert the DER to (X509 *), 1620 * check Must-Staple, and then destroy (X509 *))*/ 1621 (void)mod_openssl_crt_must_staple(NULL); 1622 pc->must_staple = 0; 1623 #else 1624 pc->must_staple = 0; 1625 #endif 1626 1627 if (pc->ssl_stapling_file) { 1628 #ifdef HAVE_OCSP 1629 if (!mod_openssl_reload_stapling_file(srv, pc, log_epoch_secs)) { 1630 /* continue without OCSP response if there is an error */ 1631 } 1632 #else 1633 log_error(srv->errh, __FILE__, __LINE__, "SSL:" 1634 "OCSP stapling not supported; ignoring %s", 1635 pc->ssl_stapling_file->ptr); 1636 #endif 1637 } 1638 else if (pc->must_staple) { 1639 log_error(srv->errh, __FILE__, __LINE__, 1640 "certificate %s marked OCSP Must-Staple, " 1641 "but ssl.stapling-file not provided", pemfile->ptr); 1642 } 1643 1644 return pc; 1645 } 1646 1647 1648 #ifdef HAVE_TLS_EXTENSIONS 1649 1650 #ifdef HAVE_ALPN 1651 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation 1652 1653 static int 1654 mod_openssl_acme_tls_1 (SSL *ssl, handler_ctx *hctx) 1655 { 1656 buffer * const b = hctx->tmp_buf; 1657 const buffer * const name = &hctx->r->uri.authority; 1658 log_error_st * const errh = hctx->r->conf.errh; 1659 buffer *ssl_pemfile_x509 = NULL; 1660 buffer *ssl_pemfile_pkey = NULL; 1661 buffer **ssl_pemfile_chain = NULL; 1662 size_t len; 1663 int rc = SSL_TLSEXT_ERR_ALERT_FATAL; 1664 1665 /* check if acme-tls/1 protocol is enabled (path to dir of cert(s) is set)*/ 1666 if (!hctx->conf.ssl_acme_tls_1) 1667 return SSL_TLSEXT_ERR_NOACK; /*(reuse value here for not-configured)*/ 1668 1669 /* check if SNI set server name (required for acme-tls/1 protocol) 1670 * and perform simple path checks for no '/' 1671 * and no leading '.' (e.g. ignore "." or ".." or anything beginning '.') */ 1672 if (buffer_is_blank(name)) return rc; 1673 if (NULL != strchr(name->ptr, '/')) return rc; 1674 if (name->ptr[0] == '.') return rc; 1675 #if 0 1676 if (0 != http_request_host_policy(name,hctx->r->conf.http_parseopts,443)) 1677 return rc; 1678 #endif 1679 buffer_copy_path_len2(b, BUF_PTR_LEN(hctx->conf.ssl_acme_tls_1), 1680 BUF_PTR_LEN(name)); 1681 len = buffer_clen(b); 1682 1683 do { 1684 buffer_append_string_len(b, CONST_STR_LEN(".crt.pem")); 1685 ssl_pemfile_x509 = 1686 mod_wolfssl_load_pem_file(b->ptr, errh, &ssl_pemfile_chain); 1687 if (NULL == ssl_pemfile_x509) { 1688 log_error(errh, __FILE__, __LINE__, 1689 "SSL: Failed to load acme-tls/1 pemfile: %s", b->ptr); 1690 break; 1691 } 1692 1693 buffer_truncate(b, len); /*(remove ".crt.pem")*/ 1694 buffer_append_string_len(b, CONST_STR_LEN(".key.pem")); 1695 ssl_pemfile_pkey = mod_wolfssl_evp_pkey_load_pem_file(b->ptr, errh); 1696 if (NULL == ssl_pemfile_pkey) { 1697 log_error(errh, __FILE__, __LINE__, 1698 "SSL: Failed to load acme-tls/1 pemfile: %s", b->ptr); 1699 break; 1700 } 1701 1702 #if 0 /* redundant with below? */ 1703 if (!X509_check_private_key(ssl_pemfile_x509, ssl_pemfile_pkey)) { 1704 log_error(errh, __FILE__, __LINE__, 1705 "SSL: Private key does not match acme-tls/1 " 1706 "certificate public key, reason: %s %s" 1707 ERR_error_string(ERR_get_error(), NULL), b->ptr); 1708 break; 1709 } 1710 #endif 1711 1712 /* first set certificate! 1713 * setting private key checks whether certificate matches it */ 1714 buffer *cert = ssl_pemfile_x509; 1715 if (1 != wolfSSL_use_certificate_ASN1(ssl, (unsigned char *)cert->ptr, 1716 (int)buffer_clen(cert))){ 1717 log_error(errh, __FILE__, __LINE__, 1718 "SSL: failed to set acme-tls/1 certificate for TLS server " 1719 "name %s: %s", name->ptr, ERR_error_string(ERR_get_error(),NULL)); 1720 break; 1721 } 1722 1723 if (ssl_pemfile_chain) { 1724 /* WolfSSL limitation */ 1725 /* WolfSSL does not support setting per-session chain; 1726 * limitation is to per-CTX chain, and so chain is not provided for 1727 * "acme-tls/1" (might be non-issue; chain might not be present) */ 1728 } 1729 1730 buffer *pkey = ssl_pemfile_pkey; 1731 if (1 != wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char *)pkey->ptr, 1732 (int)buffer_clen(pkey), 1733 WOLFSSL_FILETYPE_ASN1)) { 1734 log_error(errh, __FILE__, __LINE__, 1735 "SSL: failed to set acme-tls/1 private key for TLS server " 1736 "name %s: %s", name->ptr, ERR_error_string(ERR_get_error(),NULL)); 1737 break; 1738 } 1739 1740 hctx->conf.ssl_verifyclient_enforce = 0; 1741 wolfSSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); 1742 rc = SSL_TLSEXT_ERR_OK; 1743 } while (0); 1744 1745 if (ssl_pemfile_pkey) { 1746 wolfSSL_OPENSSL_cleanse(b->ptr, b->size); 1747 buffer_free(ssl_pemfile_pkey); 1748 } 1749 /*if (ssl_pemfile_x509) buffer_free(ssl_pemfile_x509);*//*(part of chain)*/ 1750 mod_wolfssl_free_der_certs(ssl_pemfile_chain); 1751 1752 return rc; 1753 } 1754 1755 static int 1756 mod_openssl_alpn_h2_policy (handler_ctx * const hctx) 1757 { 1758 /*(currently called after handshake has completed)*/ 1759 #if 0 /* SNI omitted by client when connecting to IP instead of to name */ 1760 if (buffer_is_blank(&hctx->r->uri.authority)) { 1761 log_error(hctx->errh, __FILE__, __LINE__, 1762 "SSL: error ALPN h2 without SNI"); 1763 return -1; 1764 } 1765 #endif 1766 if (wolfSSL_version(hctx->ssl) < TLS1_2_VERSION) { 1767 log_error(hctx->errh, __FILE__, __LINE__, 1768 "SSL: error ALPN h2 requires TLSv1.2 or later"); 1769 return -1; 1770 } 1771 1772 return 0; 1773 } 1774 1775 /* https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids */ 1776 static int 1777 mod_openssl_alpn_select_cb (SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) 1778 { 1779 handler_ctx *hctx = (handler_ctx *) SSL_get_app_data(ssl); 1780 unsigned short proto; 1781 UNUSED(arg); 1782 1783 for (unsigned int i = 0, n; i < inlen; i += n) { 1784 n = in[i++]; 1785 if (i+n > inlen || 0 == n) break; 1786 switch (n) { 1787 case 2: /* "h2" */ 1788 if (in[i] == 'h' && in[i+1] == '2') { 1789 if (!hctx->r->conf.h2proto) continue; 1790 proto = MOD_OPENSSL_ALPN_H2; 1791 hctx->r->http_version = HTTP_VERSION_2; 1792 break; 1793 } 1794 continue; 1795 case 8: /* "http/1.1" "http/1.0" */ 1796 if (0 == memcmp(in+i, "http/1.", 7)) { 1797 if (in[i+7] == '1') { 1798 proto = MOD_OPENSSL_ALPN_HTTP11; 1799 break; 1800 } 1801 if (in[i+7] == '0') { 1802 proto = MOD_OPENSSL_ALPN_HTTP10; 1803 break; 1804 } 1805 } 1806 continue; 1807 case 10: /* "acme-tls/1" */ 1808 if (0 == memcmp(in+i, "acme-tls/1", 10)) { 1809 int rc = mod_openssl_acme_tls_1(ssl, hctx); 1810 if (rc == SSL_TLSEXT_ERR_OK) { 1811 proto = MOD_OPENSSL_ALPN_ACME_TLS_1; 1812 break; 1813 } 1814 /* (use SSL_TLSEXT_ERR_NOACK for not-configured) */ 1815 if (rc == SSL_TLSEXT_ERR_NOACK) continue; 1816 return rc; 1817 } 1818 continue; 1819 default: 1820 continue; 1821 } 1822 1823 hctx->alpn = proto; 1824 *out = in+i; 1825 *outlen = n; 1826 return SSL_TLSEXT_ERR_OK; 1827 } 1828 1829 return SSL_TLSEXT_ERR_NOACK; 1830 } 1831 1832 #endif /* TLSEXT_TYPE_application_layer_protocol_negotiation */ 1833 #endif /* HAVE_ALPN */ 1834 1835 #endif /* HAVE_TLS_EXTENSIONS */ 1836 1837 1838 static int 1839 mod_openssl_ssl_conf_cmd (server *srv, plugin_config_socket *s); 1840 1841 1842 #ifndef NO_DH 1843 #include <wolfssl/openssl/dh.h> 1844 /* wolfSSL provides wolfSSL_DH_set0_pqg() for 1845 * Apache w/ OPENSSL_VERSION_NUMBER >= 0x10100000L 1846 * but does not provide most other openssl 1.1.0+ interfaces 1847 * and get_dh2048() might not be necessary if wolfSSL defines 1848 * HAVE_TLS_EXTENSIONS HAVE_DH_DEFAULT_PARAMS HAVE_FFDHE HAVE_SUPPORTED_CURVES*/ 1849 #ifndef DH_set0_pqg /*(added in wolfssl v5.0.0)*/ 1850 #define DH_set0_pqg(dh, dh_p, NULL, dh_g) \ 1851 ((dh)->p = (dh_p), (dh)->g = (dh_g), (dh_p) != NULL && (dh_g) != NULL) 1852 #endif 1853 /* https://tools.ietf.org/html/rfc7919#appendix-A.1 1854 * A.1. ffdhe2048 1855 * 1856 * https://ssl-config.mozilla.org/ffdhe2048.txt 1857 * C code generated with: openssl dhparam -C -in ffdhe2048.txt 1858 */ 1859 static DH *get_dh2048(void) 1860 { 1861 static unsigned char dhp_2048[] = { 1862 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAD, 0xF8, 1863 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, 0xAF, 0xDC, 0x56, 0x20, 1864 0x27, 0x3D, 0x3C, 0xF1, 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 1865 0x36, 0x95, 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, 1866 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, 0x7D, 0x2F, 1867 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, 0xF6, 0x81, 0xB2, 0x02, 1868 0xAE, 0xC4, 0x61, 0x7A, 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 1869 0x65, 0x61, 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, 1870 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, 0xB5, 0x57, 1871 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, 0x98, 0x4F, 0x0C, 0x70, 1872 0xE0, 0xE6, 0x8B, 0x77, 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 1873 0xE8, 0x72, 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, 1874 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, 0xBC, 0x0A, 1875 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, 0xD1, 0x08, 0xA9, 0x4B, 1876 0xB2, 0xC8, 0xE3, 0xFB, 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 1877 0xF4, 0x68, 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, 1878 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, 0x0B, 0x07, 1879 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, 0x9E, 0x02, 0xFC, 0xE1, 1880 0xCD, 0xF7, 0xE2, 0xEC, 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 1881 0x2F, 0x61, 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, 1882 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, 0xC3, 0xFE, 1883 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, 0x3B, 0xB5, 0xFC, 0xBC, 1884 0x2E, 0xC2, 0x20, 0x05, 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 1885 0x83, 0xB2, 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, 1886 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, 0xFF, 0xFF, 1887 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 1888 }; 1889 static unsigned char dhg_2048[] = { 1890 0x02 1891 }; 1892 DH *dh = DH_new(); 1893 BIGNUM *p, *g; 1894 1895 if (dh == NULL) 1896 return NULL; 1897 p = BN_bin2bn(dhp_2048, sizeof(dhp_2048), NULL); 1898 g = BN_bin2bn(dhg_2048, sizeof(dhg_2048), NULL); 1899 if (p == NULL || g == NULL || !DH_set0_pqg(dh, p, NULL, g)) { 1900 DH_free(dh); 1901 BN_free(p); 1902 BN_free(g); 1903 return NULL; 1904 } 1905 return dh; 1906 } 1907 #endif 1908 1909 1910 static int 1911 mod_openssl_ssl_conf_curves(server *srv, plugin_config_socket *s, const buffer *ssl_ec_curve) 1912 { 1913 /* Support for Elliptic-Curve Diffie-Hellman key exchange */ 1914 /* OpenSSL only supports the "named curves" from RFC 4492, section 5.1.1. */ 1915 const char *curve = ssl_ec_curve ? ssl_ec_curve->ptr : "prime256v1"; 1916 int nid = wolfSSL_OBJ_sn2nid(curve); 1917 if (nid) { 1918 EC_KEY * const ecdh = EC_KEY_new_by_curve_name(nid); 1919 if (ecdh == NULL) { 1920 log_error(srv->errh, __FILE__, __LINE__, 1921 "SSL: Unable to create curve %s", curve); 1922 return 0; 1923 } 1924 wolfSSL_SSL_CTX_set_tmp_ecdh(s->ssl_ctx, ecdh); 1925 SSL_CTX_set_options(s->ssl_ctx, SSL_OP_SINGLE_ECDH_USE); 1926 EC_KEY_free(ecdh); 1927 return 1; 1928 } 1929 else { 1930 log_error(srv->errh, __FILE__, __LINE__, 1931 "SSL: Unknown curve name %s", curve); 1932 return 0; 1933 } 1934 } 1935 1936 1937 static int 1938 network_init_ssl (server *srv, plugin_config_socket *s, plugin_data *p) 1939 { 1940 /* load SSL certificates */ 1941 1942 #ifndef SSL_OP_NO_COMPRESSION 1943 #define SSL_OP_NO_COMPRESSION 0 1944 #endif 1945 long ssloptions = SSL_OP_ALL 1946 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 1947 | SSL_OP_NO_COMPRESSION; 1948 1949 #if LIBWOLFSSL_VERSION_HEX >= 0x04002000 1950 s->ssl_ctx = (!s->ssl_use_sslv2 && !s->ssl_use_sslv3) 1951 ? SSL_CTX_new(TLS_server_method()) 1952 : SSL_CTX_new(SSLv23_server_method()); 1953 #else 1954 s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()); 1955 #endif 1956 if (NULL == s->ssl_ctx) { 1957 log_error(srv->errh, __FILE__, __LINE__, 1958 "SSL: %s", ERR_error_string(ERR_get_error(), NULL)); 1959 return -1; 1960 } 1961 1962 #ifdef SSL_OP_NO_RENEGOTIATION /* openssl 1.1.0 */ 1963 if (s->ssl_disable_client_renegotiation) 1964 ssloptions |= SSL_OP_NO_RENEGOTIATION; 1965 #endif 1966 1967 /* completely useless identifier; 1968 * required for client cert verification to work with sessions */ 1969 if (0 == SSL_CTX_set_session_id_context( 1970 s->ssl_ctx,(const unsigned char*)CONST_STR_LEN("lighttpd"))){ 1971 log_error(srv->errh, __FILE__, __LINE__, 1972 "SSL: failed to set session context: %s", 1973 ERR_error_string(ERR_get_error(), NULL)); 1974 return -1; 1975 } 1976 1977 #if !defined(NO_SESSION_CACHE) 1978 const int disable_sess_cache = 1979 !config_feature_bool(srv, "ssl.session-cache", 0); 1980 if (disable_sess_cache) 1981 /* disable session cache; session tickets are preferred */ 1982 SSL_CTX_set_session_cache_mode(s->ssl_ctx, 1983 SSL_SESS_CACHE_OFF 1984 | SSL_SESS_CACHE_NO_AUTO_CLEAR 1985 | SSL_SESS_CACHE_NO_INTERNAL); 1986 #endif 1987 1988 if (s->ssl_empty_fragments) { 1989 #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 1990 ssloptions &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; 1991 #else 1992 ssloptions &= ~0x00000800L; /* hardcode constant */ 1993 log_error(srv->errh, __FILE__, __LINE__, 1994 "WARNING: SSL: 'insert empty fragments' not supported by the " 1995 "openssl version used to compile lighttpd with"); 1996 #endif 1997 } 1998 1999 SSL_CTX_set_options(s->ssl_ctx, ssloptions); 2000 SSL_CTX_set_info_callback(s->ssl_ctx, ssl_info_callback); 2001 2002 /*(wolfSSL does not support SSLv2)*/ 2003 2004 if (!s->ssl_use_sslv3 && 0 != SSL_OP_NO_SSLv3) { 2005 /* disable SSLv3 */ 2006 if ((SSL_OP_NO_SSLv3 2007 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv3)) 2008 != SSL_OP_NO_SSLv3) { 2009 log_error(srv->errh, __FILE__, __LINE__, 2010 "SSL: %s", ERR_error_string(ERR_get_error(), NULL)); 2011 return -1; 2012 } 2013 } 2014 2015 if (s->ssl_cipher_list) { 2016 /* Disable support for low encryption ciphers */ 2017 if (SSL_CTX_set_cipher_list(s->ssl_ctx,s->ssl_cipher_list->ptr)!=1){ 2018 log_error(srv->errh, __FILE__, __LINE__, 2019 "SSL: %s", ERR_error_string(ERR_get_error(), NULL)); 2020 return -1; 2021 } 2022 2023 if (s->ssl_honor_cipher_order) { 2024 SSL_CTX_set_options(s->ssl_ctx,SSL_OP_CIPHER_SERVER_PREFERENCE); 2025 } 2026 } 2027 2028 #ifdef SSL_OP_PRIORITIZE_CHACHA /*(openssl 1.1.1)*/ 2029 if (s->ssl_honor_cipher_order) 2030 SSL_CTX_set_options(s->ssl_ctx, SSL_OP_PRIORITIZE_CHACHA); 2031 #endif 2032 2033 #ifndef NO_DH 2034 { 2035 DH *dh; 2036 /* Support for Diffie-Hellman key exchange */ 2037 if (s->ssl_dh_file) { 2038 const char *fn = s->ssl_dh_file->ptr; 2039 off_t dlen = 1*1024*1024;/*(arbitrary limit: 1 MB; expect < 1 KB)*/ 2040 char *data = fdevent_load_file(fn, &dlen, srv->errh, malloc, free); 2041 int rc = (NULL != data) ? 0 : -1; 2042 if (0 == rc) 2043 wolfSSL_CTX_SetTmpDH_buffer(s->ssl_ctx, (unsigned char *)data, 2044 (long)dlen, WOLFSSL_FILETYPE_PEM); 2045 if (dlen) ck_memzero(data, dlen); 2046 free(data); 2047 if (rc < 0) { 2048 log_error(srv->errh, __FILE__, __LINE__, 2049 "SSL: Unable to read DH params from file %s", 2050 s->ssl_dh_file->ptr); 2051 return -1; 2052 } 2053 } 2054 else { 2055 dh = get_dh2048(); 2056 if (dh == NULL) { 2057 log_error(srv->errh, __FILE__, __LINE__, 2058 "SSL: get_dh2048() failed"); 2059 return -1; 2060 } 2061 SSL_CTX_set_tmp_dh(s->ssl_ctx,dh); 2062 DH_free(dh); 2063 } 2064 SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_DH_USE); 2065 } 2066 #else 2067 if (s->ssl_dh_file) { 2068 log_error(srv->errh, __FILE__, __LINE__, 2069 "SSL: openssl compiled without DH support, " 2070 "can't load parameters from %s", s->ssl_dh_file->ptr); 2071 } 2072 #endif 2073 2074 if (!mod_openssl_ssl_conf_curves(srv, s, s->ssl_ec_curve)) 2075 return -1; 2076 2077 #ifdef HAVE_SESSION_TICKET 2078 wolfSSL_CTX_set_tlsext_ticket_key_cb(s->ssl_ctx, ssl_tlsext_ticket_key_cb); 2079 #endif 2080 2081 #ifdef HAVE_OCSP 2082 wolfSSL_CTX_set_tlsext_status_cb(s->ssl_ctx, ssl_tlsext_status_cb); 2083 #endif 2084 2085 /* load all ssl.ca-files specified in the config into each SSL_CTX 2086 * XXX: This might be a bit excessive, but are all trusted CAs 2087 * TODO: prefer to load on-demand in mod_openssl_cert_cb() 2088 * for openssl >= 1.0.2 */ 2089 if (!mod_wolfssl_load_ca_files(s->ssl_ctx, p, srv)) 2090 return -1; 2091 2092 if (s->ssl_verifyclient) { 2093 if (NULL == s->ssl_ca_file) { 2094 log_error(srv->errh, __FILE__, __LINE__, 2095 "SSL: You specified ssl.verifyclient.activate " 2096 "but no ssl.verifyclient.ca-file"); 2097 return -1; 2098 } 2099 #ifndef OPENSSL_ALL 2100 log_error(srv->errh, __FILE__, __LINE__, 2101 "SSL: You specified ssl.verifyclient.activate " 2102 "but wolfssl library built without necessary support"); 2103 return -1; 2104 #else 2105 /* Before wolfssl 4.6.0, wolfSSL_dup_CA_list() is a stub function 2106 * which returns NULL, so DN names in cert request are not set here. 2107 * (A patch has been submitted to WolfSSL add is part of 4.6.0) 2108 * https://github.com/wolfSSL/wolfssl/pull/3098 */ 2109 STACK_OF(X509_NAME) * const cert_names = s->ssl_ca_dn_file 2110 ? s->ssl_ca_dn_file 2111 : s->ssl_ca_file->names; 2112 wolfSSL_CTX_set_client_CA_list(s->ssl_ctx, 2113 wolfSSL_dup_CA_list(cert_names)); 2114 int mode = SSL_VERIFY_PEER; 2115 if (s->ssl_verifyclient_enforce) { 2116 mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; 2117 } 2118 wolfSSL_CTX_set_verify(s->ssl_ctx, mode, verify_callback); 2119 wolfSSL_CTX_set_verify_depth(s->ssl_ctx, 2120 s->ssl_verifyclient_depth + 1); 2121 #endif 2122 if (s->ssl_ca_crl_file) { 2123 if (!mod_wolfssl_load_cacrls(s->ssl_ctx,s->ssl_ca_crl_file,srv)) 2124 return -1; 2125 } 2126 } 2127 2128 if (1 != mod_wolfssl_CTX_use_certificate_chain_file( 2129 s->ssl_ctx, s->pc->ssl_pemfile->ptr, srv->errh)) 2130 return -1; 2131 2132 buffer *k = s->pc->ssl_pemfile_pkey; 2133 if (1 != wolfSSL_CTX_use_PrivateKey_buffer(s->ssl_ctx, 2134 (unsigned char *)k->ptr, 2135 (int)buffer_clen(k), 2136 WOLFSSL_FILETYPE_ASN1)) { 2137 log_error(srv->errh, __FILE__, __LINE__, 2138 "SSL: %s %s %s", ERR_error_string(ERR_get_error(), NULL), 2139 s->pc->ssl_pemfile->ptr, s->pc->ssl_privkey->ptr); 2140 return -1; 2141 } 2142 2143 if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) { 2144 log_error(srv->errh, __FILE__, __LINE__, 2145 "SSL: Private key does not match the certificate public key, " 2146 "reason: %s %s %s", ERR_error_string(ERR_get_error(), NULL), 2147 s->pc->ssl_pemfile->ptr, s->pc->ssl_privkey->ptr); 2148 return -1; 2149 } 2150 2151 SSL_CTX_set_default_read_ahead(s->ssl_ctx, s->ssl_read_ahead); 2152 wolfSSL_CTX_set_mode(s->ssl_ctx, 2153 SSL_MODE_ENABLE_PARTIAL_WRITE); 2154 wolfSSL_CTX_set_mode(s->ssl_ctx, /*(wolfSSL default mode)*/ 2155 WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); 2156 #ifdef wolfSSL_SSL_MODE_RELEASE_BUFFERS 2157 wolfSSL_CTX_set_mode(s->ssl_ctx, /*(not currently implemented)*/ 2158 wolfSSL_SSL_MODE_RELEASE_BUFFERS); 2159 #endif 2160 2161 #ifdef HAVE_TLS_EXTENSIONS 2162 /*(wolfSSL preprocessor defines are obnoxious)*/ 2163 /*(code should be HAVE_SNI, but is hidden by OPENSSL_ALL 2164 * even though the comment in wolfssl code on the #endif 2165 * says (OPENSSL_ALL 2166 * || (OPENSSL_EXTRA 2167 * && (HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_LIGHTY))) 2168 * and sniRecvCb sniRecvCbArg are hidden by *different* set of defines 2169 * in wolfssl/internal.h) 2170 * Note: wolfSSL SNI callbacks members not present unless wolfSSL is 2171 * built OPENSSL_ALL or some additional combination of preprocessor 2172 * defines. The following should work with more recent wolfSSL versions 2173 * (and HAVE_LIGHTY is not sufficient in wolfssl <= 4.5.0) */ 2174 #if defined(OPENSSL_ALL) \ 2175 || (defined(OPENSSL_EXTRA) \ 2176 && (defined(HAVE_STUNNEL) \ 2177 || defined(WOLFSSL_NGINX) \ 2178 || defined(WOLFSSL_HAPROXY))) 2179 #else 2180 #undef HAVE_SNI 2181 #endif 2182 #ifdef HAVE_SNI 2183 wolfSSL_CTX_set_servername_callback( 2184 s->ssl_ctx, network_ssl_servername_callback); 2185 wolfSSL_CTX_set_servername_arg(s->ssl_ctx, srv); 2186 #else 2187 log_error(srv->errh, __FILE__, __LINE__, 2188 "SSL: WARNING: SNI callbacks *crippled* in wolfSSL library build"); 2189 UNUSED(network_ssl_servername_callback); 2190 #endif 2191 2192 #ifdef HAVE_ALPN 2193 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation 2194 SSL_CTX_set_alpn_select_cb(s->ssl_ctx,mod_openssl_alpn_select_cb,NULL); 2195 #endif 2196 #endif 2197 #endif 2198 2199 if (!s->ssl_use_sslv3 && !s->ssl_use_sslv2 2200 && wolfSSL_CTX_SetMinVersion(s->ssl_ctx, WOLFSSL_TLSV1_2) 2201 != WOLFSSL_SUCCESS) 2202 return -1; 2203 2204 if (s->ssl_conf_cmd && s->ssl_conf_cmd->used) { 2205 if (0 != mod_openssl_ssl_conf_cmd(srv, s)) return -1; 2206 } 2207 2208 return 0; 2209 } 2210 2211 2212 static int 2213 mod_openssl_set_defaults_sockets(server *srv, plugin_data *p) 2214 { 2215 static const config_plugin_keys_t cpk[] = { 2216 { CONST_STR_LEN("ssl.engine"), 2217 T_CONFIG_BOOL, 2218 T_CONFIG_SCOPE_CONNECTION } 2219 ,{ CONST_STR_LEN("ssl.cipher-list"), 2220 T_CONFIG_STRING, 2221 T_CONFIG_SCOPE_CONNECTION } 2222 ,{ CONST_STR_LEN("ssl.honor-cipher-order"), 2223 T_CONFIG_BOOL, 2224 T_CONFIG_SCOPE_CONNECTION } 2225 ,{ CONST_STR_LEN("ssl.dh-file"), 2226 T_CONFIG_STRING, 2227 T_CONFIG_SCOPE_CONNECTION } 2228 ,{ CONST_STR_LEN("ssl.ec-curve"), 2229 T_CONFIG_STRING, 2230 T_CONFIG_SCOPE_CONNECTION } 2231 ,{ CONST_STR_LEN("ssl.openssl.ssl-conf-cmd"), 2232 T_CONFIG_ARRAY_KVSTRING, 2233 T_CONFIG_SCOPE_CONNECTION } 2234 ,{ CONST_STR_LEN("ssl.pemfile"), /* included to process global scope */ 2235 T_CONFIG_STRING, 2236 T_CONFIG_SCOPE_CONNECTION } 2237 ,{ CONST_STR_LEN("ssl.empty-fragments"), 2238 T_CONFIG_BOOL, 2239 T_CONFIG_SCOPE_CONNECTION } 2240 ,{ CONST_STR_LEN("ssl.use-sslv2"), 2241 T_CONFIG_BOOL, 2242 T_CONFIG_SCOPE_CONNECTION } 2243 ,{ CONST_STR_LEN("ssl.use-sslv3"), 2244 T_CONFIG_BOOL, 2245 T_CONFIG_SCOPE_CONNECTION } 2246 ,{ CONST_STR_LEN("ssl.stek-file"), 2247 T_CONFIG_STRING, 2248 T_CONFIG_SCOPE_SERVER } 2249 ,{ NULL, 0, 2250 T_CONFIG_UNSET, 2251 T_CONFIG_SCOPE_UNSET } 2252 }; 2253 /* WolfSSL does not have mapping for "HIGH" */ 2254 /* cipher list is (current) output of "openssl ciphers HIGH" */ 2255 static const buffer default_ssl_cipher_list = { CONST_STR_LEN("TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-CCM8:ECDHE-ECDSA-AES256-CCM:DHE-RSA-AES256-CCM8:DHE-RSA-AES256-CCM:ECDHE-ECDSA-ARIA256-GCM-SHA384:ECDHE-ARIA256-GCM-SHA384:DHE-DSS-ARIA256-GCM-SHA384:DHE-RSA-ARIA256-GCM-SHA384:ADH-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-CCM8:ECDHE-ECDSA-AES128-CCM:DHE-RSA-AES128-CCM8:DHE-RSA-AES128-CCM:ECDHE-ECDSA-ARIA128-GCM-SHA256:ECDHE-ARIA128-GCM-SHA256:DHE-DSS-ARIA128-GCM-SHA256:DHE-RSA-ARIA128-GCM-SHA256:ADH-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:ECDHE-ECDSA-CAMELLIA256-SHA384:ECDHE-RSA-CAMELLIA256-SHA384:DHE-RSA-CAMELLIA256-SHA256:DHE-DSS-CAMELLIA256-SHA256:ADH-AES256-SHA256:ADH-CAMELLIA256-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:ECDHE-ECDSA-CAMELLIA128-SHA256:ECDHE-RSA-CAMELLIA128-SHA256:DHE-RSA-CAMELLIA128-SHA256:DHE-DSS-CAMELLIA128-SHA256:ADH-AES128-SHA256:ADH-CAMELLIA128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-DSS-CAMELLIA256-SHA:AECDH-AES256-SHA:ADH-AES256-SHA:ADH-CAMELLIA256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:DHE-RSA-CAMELLIA128-SHA:DHE-DSS-CAMELLIA128-SHA:AECDH-AES128-SHA:ADH-AES128-SHA:ADH-CAMELLIA128-SHA:RSA-PSK-AES256-GCM-SHA384:DHE-PSK-AES256-GCM-SHA384:RSA-PSK-CHACHA20-POLY1305:DHE-PSK-CHACHA20-POLY1305:ECDHE-PSK-CHACHA20-POLY1305:DHE-PSK-AES256-CCM8:DHE-PSK-AES256-CCM:RSA-PSK-ARIA256-GCM-SHA384:DHE-PSK-ARIA256-GCM-SHA384:AES256-GCM-SHA384:AES256-CCM8:AES256-CCM:ARIA256-GCM-SHA384:PSK-AES256-GCM-SHA384:PSK-CHACHA20-POLY1305:PSK-AES256-CCM8:PSK-AES256-CCM:PSK-ARIA256-GCM-SHA384:RSA-PSK-AES128-GCM-SHA256:DHE-PSK-AES128-GCM-SHA256:DHE-PSK-AES128-CCM8:DHE-PSK-AES128-CCM:RSA-PSK-ARIA128-GCM-SHA256:DHE-PSK-ARIA128-GCM-SHA256:AES128-GCM-SHA256:AES128-CCM8:AES128-CCM:ARIA128-GCM-SHA256:PSK-AES128-GCM-SHA256:PSK-AES128-CCM8:PSK-AES128-CCM:PSK-ARIA128-GCM-SHA256:AES256-SHA256:CAMELLIA256-SHA256:AES128-SHA256:CAMELLIA128-SHA256:ECDHE-PSK-AES256-CBC-SHA384:ECDHE-PSK-AES256-CBC-SHA:SRP-DSS-AES-256-CBC-SHA:SRP-RSA-AES-256-CBC-SHA:SRP-AES-256-CBC-SHA:RSA-PSK-AES256-CBC-SHA384:DHE-PSK-AES256-CBC-SHA384:RSA-PSK-AES256-CBC-SHA:DHE-PSK-AES256-CBC-SHA:ECDHE-PSK-CAMELLIA256-SHA384:RSA-PSK-CAMELLIA256-SHA384:DHE-PSK-CAMELLIA256-SHA384:AES256-SHA:CAMELLIA256-SHA:PSK-AES256-CBC-SHA384:PSK-AES256-CBC-SHA:PSK-CAMELLIA256-SHA384:ECDHE-PSK-AES128-CBC-SHA256:ECDHE-PSK-AES128-CBC-SHA:SRP-DSS-AES-128-CBC-SHA:SRP-RSA-AES-128-CBC-SHA:SRP-AES-128-CBC-SHA:RSA-PSK-AES128-CBC-SHA256:DHE-PSK-AES128-CBC-SHA256:RSA-PSK-AES128-CBC-SHA:DHE-PSK-AES128-CBC-SHA:ECDHE-PSK-CAMELLIA128-SHA256:RSA-PSK-CAMELLIA128-SHA256:DHE-PSK-CAMELLIA128-SHA256:AES128-SHA:CAMELLIA128-SHA:PSK-AES128-CBC-SHA256:PSK-AES128-CBC-SHA:PSK-CAMELLIA128-SHA256"), 0 }; 2256 2257 p->ssl_ctxs = calloc(srv->config_context->used, sizeof(plugin_ssl_ctx)); 2258 force_assert(p->ssl_ctxs); 2259 2260 int rc = HANDLER_GO_ON; 2261 plugin_data_base srvplug; 2262 memset(&srvplug, 0, sizeof(srvplug)); 2263 plugin_data_base * const ps = &srvplug; 2264 if (!config_plugin_values_init(srv, ps, cpk, "mod_openssl")) 2265 return HANDLER_ERROR; 2266 2267 plugin_config_socket defaults; 2268 memset(&defaults, 0, sizeof(defaults)); 2269 defaults.ssl_honor_cipher_order = 1; 2270 defaults.ssl_cipher_list = &default_ssl_cipher_list; 2271 2272 /* process and validate config directives for global and $SERVER["socket"] 2273 * (init i to 0 if global context; to 1 to skip empty global context) */ 2274 for (int i = !ps->cvlist[0].v.u2[1]; i < ps->nconfig; ++i) { 2275 config_cond_info cfginfo; 2276 config_get_config_cond_info(&cfginfo, (uint32_t)ps->cvlist[i].k_id); 2277 int is_socket_scope = (0 == i || cfginfo.comp == COMP_SERVER_SOCKET); 2278 int count_not_engine = 0; 2279 2280 plugin_config_socket conf; 2281 memcpy(&conf, &defaults, sizeof(conf)); 2282 2283 /*(preserve prior behavior; not inherited)*/ 2284 /*(forcing inheritance might break existing configs where SSL is enabled 2285 * by default in the global scope, but not $SERVER["socket"]=="*:80") */ 2286 conf.ssl_enabled = 0; 2287 2288 config_plugin_value_t *cpv = ps->cvlist + ps->cvlist[i].v.u2[0]; 2289 for (; -1 != cpv->k_id; ++cpv) { 2290 /* ignore ssl.pemfile (k_id=6); included to process global scope */ 2291 if (!is_socket_scope && cpv->k_id != 6) { 2292 log_error(srv->errh, __FILE__, __LINE__, 2293 "%s is valid only in global scope or " 2294 "$SERVER[\"socket\"] condition", cpk[cpv->k_id].k); 2295 continue; 2296 } 2297 ++count_not_engine; 2298 switch (cpv->k_id) { 2299 case 0: /* ssl.engine */ 2300 conf.ssl_enabled = (0 != cpv->v.u); 2301 --count_not_engine; 2302 break; 2303 case 1: /* ssl.cipher-list */ 2304 if (!buffer_is_blank(cpv->v.b)) 2305 conf.ssl_cipher_list = cpv->v.b; 2306 break; 2307 case 2: /* ssl.honor-cipher-order */ 2308 conf.ssl_honor_cipher_order = (0 != cpv->v.u); 2309 break; 2310 case 3: /* ssl.dh-file */ 2311 if (!buffer_is_blank(cpv->v.b)) 2312 conf.ssl_dh_file = cpv->v.b; 2313 break; 2314 case 4: /* ssl.ec-curve */ 2315 if (!buffer_is_blank(cpv->v.b)) 2316 conf.ssl_ec_curve = cpv->v.b; 2317 break; 2318 case 5: /* ssl.openssl.ssl-conf-cmd */ 2319 *(const array **)&conf.ssl_conf_cmd = cpv->v.a; 2320 break; 2321 case 6: /* ssl.pemfile */ 2322 /* ignore here; included to process global scope when 2323 * ssl.pemfile is set, but ssl.engine is not "enable" */ 2324 break; 2325 case 7: /* ssl.empty-fragments */ 2326 conf.ssl_empty_fragments = (0 != cpv->v.u); 2327 log_error(srv->errh, __FILE__, __LINE__, "SSL: " 2328 "ssl.empty-fragments is deprecated and will soon be " 2329 "removed. It is disabled by default."); 2330 if (conf.ssl_empty_fragments) 2331 log_error(srv->errh, __FILE__, __LINE__, "SSL: " 2332 "If needed, use: ssl.openssl.ssl-conf-cmd = " 2333 "(\"Options\" => \"EmptyFragments\")"); 2334 log_error(srv->errh, __FILE__, __LINE__, "SSL: " 2335 "ssl.empty-fragments is a " 2336 "counter-measure against a SSL 3.0/TLS 1.0 protocol " 2337 "vulnerability affecting CBC ciphers, which cannot be handled" 2338 " by some broken (Microsoft) SSL implementations."); 2339 break; 2340 case 8: /* ssl.use-sslv2 */ 2341 conf.ssl_use_sslv2 = (0 != cpv->v.u); 2342 log_error(srv->errh, __FILE__, __LINE__, "SSL: " 2343 "ssl.use-sslv2 is deprecated and will soon be removed. " 2344 "It is disabled by default. " 2345 "Many modern TLS libraries no longer support SSLv2."); 2346 break; 2347 case 9: /* ssl.use-sslv3 */ 2348 conf.ssl_use_sslv3 = (0 != cpv->v.u); 2349 log_error(srv->errh, __FILE__, __LINE__, "SSL: " 2350 "ssl.use-sslv3 is deprecated and will soon be removed. " 2351 "It is disabled by default. " 2352 "Many modern TLS libraries no longer support SSLv3."); 2353 if (conf.ssl_use_sslv3) 2354 log_error(srv->errh, __FILE__, __LINE__, "SSL: " 2355 "If needed, use: ssl.openssl.ssl-conf-cmd = " 2356 "(\"MinProtocol\" => \"SSLv3\")"); 2357 break; 2358 case 10:/* ssl.stek-file */ 2359 if (!buffer_is_blank(cpv->v.b)) 2360 p->ssl_stek_file = cpv->v.b->ptr; 2361 break; 2362 default:/* should not happen */ 2363 break; 2364 } 2365 } 2366 if (HANDLER_GO_ON != rc) break; 2367 if (0 == i) memcpy(&defaults, &conf, sizeof(conf)); 2368 2369 if (0 != i && !conf.ssl_enabled) continue; 2370 2371 /* fill plugin_config_socket with global context then $SERVER["socket"] 2372 * only for directives directly in current $SERVER["socket"] condition*/ 2373 2374 /*conf.pc = p->defaults.pc;*/ 2375 conf.ssl_ca_file = p->defaults.ssl_ca_file; 2376 conf.ssl_ca_dn_file = p->defaults.ssl_ca_dn_file; 2377 conf.ssl_ca_crl_file = p->defaults.ssl_ca_crl_file; 2378 conf.ssl_verifyclient = p->defaults.ssl_verifyclient; 2379 conf.ssl_verifyclient_enforce = p->defaults.ssl_verifyclient_enforce; 2380 conf.ssl_verifyclient_depth = p->defaults.ssl_verifyclient_depth; 2381 conf.ssl_read_ahead = p->defaults.ssl_read_ahead; 2382 2383 int sidx = ps->cvlist[i].k_id; 2384 for (int j = !p->cvlist[0].v.u2[1]; j < p->nconfig; ++j) { 2385 if (p->cvlist[j].k_id != sidx) continue; 2386 /*if (0 == sidx) break;*//*(repeat to get ssl_pemfile,ssl_privkey)*/ 2387 cpv = p->cvlist + p->cvlist[j].v.u2[0]; 2388 for (; -1 != cpv->k_id; ++cpv) { 2389 ++count_not_engine; 2390 switch (cpv->k_id) { 2391 case 0: /* ssl.pemfile */ 2392 if (cpv->vtype == T_CONFIG_LOCAL) 2393 conf.pc = cpv->v.v; 2394 break; 2395 case 2: /* ssl.ca-file */ 2396 if (cpv->vtype == T_CONFIG_LOCAL) 2397 conf.ssl_ca_file = cpv->v.v; 2398 break; 2399 case 3: /* ssl.ca-dn-file */ 2400 if (cpv->vtype == T_CONFIG_LOCAL) 2401 conf.ssl_ca_dn_file = cpv->v.v; 2402 break; 2403 case 4: /* ssl.ca-crl-file */ 2404 if (!buffer_is_blank(cpv->v.b)) 2405 conf.ssl_ca_crl_file = cpv->v.b; 2406 break; 2407 case 5: /* ssl.read-ahead */ 2408 conf.ssl_read_ahead = (0 != cpv->v.u); 2409 break; 2410 case 6: /* ssl.disable-client-renegotiation */ 2411 conf.ssl_disable_client_renegotiation = (0 != cpv->v.u); 2412 break; 2413 case 7: /* ssl.verifyclient.activate */ 2414 conf.ssl_verifyclient = (0 != cpv->v.u); 2415 break; 2416 case 8: /* ssl.verifyclient.enforce */ 2417 conf.ssl_verifyclient_enforce = (0 != cpv->v.u); 2418 break; 2419 case 9: /* ssl.verifyclient.depth */ 2420 conf.ssl_verifyclient_depth = (unsigned char)cpv->v.shrt; 2421 break; 2422 #if 0 /*(cpk->k_id remapped in mod_openssl_set_defaults())*/ 2423 case 15:/* ssl.verifyclient.ca-file */ 2424 case 16:/* ssl.verifyclient.ca-dn-file */ 2425 case 17:/* ssl.verifyclient.ca-crl-file */ 2426 #endif 2427 default: 2428 break; 2429 } 2430 } 2431 break; 2432 } 2433 2434 if (NULL == conf.pc) { 2435 if (0 == i && !conf.ssl_enabled) continue; 2436 if (0 != i) { 2437 /* inherit ssl settings from global scope 2438 * (if only ssl.engine = "enable" and no other ssl.* settings) 2439 * (This is for convenience when defining both IPv4 and IPv6 2440 * and desiring to inherit the ssl config from global context 2441 * without having to duplicate the directives)*/ 2442 if (count_not_engine 2443 || (conf.ssl_enabled && NULL == p->ssl_ctxs[0].ssl_ctx)) { 2444 log_error(srv->errh, __FILE__, __LINE__, 2445 "ssl.pemfile has to be set in same $SERVER[\"socket\"] scope " 2446 "as other ssl.* directives, unless only ssl.engine is set, " 2447 "inheriting ssl.* from global scope"); 2448 rc = HANDLER_ERROR; 2449 continue; 2450 } 2451 plugin_ssl_ctx * const s = p->ssl_ctxs + sidx; 2452 *s = *p->ssl_ctxs;/*(copy struct of ssl_ctx from global scope)*/ 2453 continue; 2454 } 2455 /* PEM file is required */ 2456 log_error(srv->errh, __FILE__, __LINE__, 2457 "ssl.pemfile has to be set when ssl.engine = \"enable\""); 2458 rc = HANDLER_ERROR; 2459 continue; 2460 } 2461 2462 /* configure ssl_ctx for socket */ 2463 2464 /*conf.ssl_ctx = NULL;*//*(filled by network_init_ssl() even on error)*/ 2465 if (0 == network_init_ssl(srv, &conf, p)) { 2466 plugin_ssl_ctx * const s = p->ssl_ctxs + sidx; 2467 s->ssl_ctx = conf.ssl_ctx; 2468 } 2469 else { 2470 SSL_CTX_free(conf.ssl_ctx); 2471 rc = HANDLER_ERROR; 2472 } 2473 } 2474 2475 #ifdef HAVE_SESSION_TICKET 2476 if (rc == HANDLER_GO_ON && ssl_is_init) 2477 mod_openssl_session_ticket_key_check(p, log_epoch_secs); 2478 #endif 2479 2480 free(srvplug.cvlist); 2481 return rc; 2482 } 2483 2484 2485 SETDEFAULTS_FUNC(mod_openssl_set_defaults) 2486 { 2487 static const config_plugin_keys_t cpk[] = { 2488 { CONST_STR_LEN("ssl.pemfile"), 2489 T_CONFIG_STRING, 2490 T_CONFIG_SCOPE_CONNECTION } 2491 ,{ CONST_STR_LEN("ssl.privkey"), 2492 T_CONFIG_STRING, 2493 T_CONFIG_SCOPE_CONNECTION } 2494 ,{ CONST_STR_LEN("ssl.ca-file"), 2495 T_CONFIG_STRING, 2496 T_CONFIG_SCOPE_CONNECTION } 2497 ,{ CONST_STR_LEN("ssl.ca-dn-file"), 2498 T_CONFIG_STRING, 2499 T_CONFIG_SCOPE_CONNECTION } 2500 ,{ CONST_STR_LEN("ssl.ca-crl-file"), 2501 T_CONFIG_STRING, 2502 T_CONFIG_SCOPE_CONNECTION } 2503 ,{ CONST_STR_LEN("ssl.read-ahead"), 2504 T_CONFIG_BOOL, 2505 T_CONFIG_SCOPE_CONNECTION } 2506 ,{ CONST_STR_LEN("ssl.disable-client-renegotiation"), 2507 T_CONFIG_BOOL, 2508 T_CONFIG_SCOPE_CONNECTION } 2509 ,{ CONST_STR_LEN("ssl.verifyclient.activate"), 2510 T_CONFIG_BOOL, 2511 T_CONFIG_SCOPE_CONNECTION } 2512 ,{ CONST_STR_LEN("ssl.verifyclient.enforce"), 2513 T_CONFIG_BOOL, 2514 T_CONFIG_SCOPE_CONNECTION } 2515 ,{ CONST_STR_LEN("ssl.verifyclient.depth"), 2516 T_CONFIG_SHORT, 2517 T_CONFIG_SCOPE_CONNECTION } 2518 ,{ CONST_STR_LEN("ssl.verifyclient.username"), 2519 T_CONFIG_STRING, 2520 T_CONFIG_SCOPE_CONNECTION } 2521 ,{ CONST_STR_LEN("ssl.verifyclient.exportcert"), 2522 T_CONFIG_BOOL, 2523 T_CONFIG_SCOPE_CONNECTION } 2524 ,{ CONST_STR_LEN("ssl.acme-tls-1"), 2525 T_CONFIG_STRING, 2526 T_CONFIG_SCOPE_CONNECTION } 2527 ,{ CONST_STR_LEN("ssl.stapling-file"), 2528 T_CONFIG_STRING, 2529 T_CONFIG_SCOPE_CONNECTION } 2530 ,{ CONST_STR_LEN("debug.log-ssl-noise"), 2531 T_CONFIG_BOOL, 2532 T_CONFIG_SCOPE_CONNECTION } 2533 ,{ CONST_STR_LEN("ssl.verifyclient.ca-file"), 2534 T_CONFIG_STRING, 2535 T_CONFIG_SCOPE_CONNECTION } 2536 ,{ CONST_STR_LEN("ssl.verifyclient.ca-dn-file"), 2537 T_CONFIG_STRING, 2538 T_CONFIG_SCOPE_CONNECTION } 2539 ,{ CONST_STR_LEN("ssl.verifyclient.ca-crl-file"), 2540 T_CONFIG_STRING, 2541 T_CONFIG_SCOPE_CONNECTION } 2542 ,{ NULL, 0, 2543 T_CONFIG_UNSET, 2544 T_CONFIG_SCOPE_UNSET } 2545 }; 2546 2547 plugin_data * const p = p_d; 2548 p->srv = srv; 2549 p->cafiles = array_init(0); 2550 if (!config_plugin_values_init(srv, p, cpk, "mod_openssl")) 2551 return HANDLER_ERROR; 2552 2553 const buffer *default_ssl_ca_crl_file = NULL; 2554 2555 /* process and validate config directives 2556 * (init i to 0 if global context; to 1 to skip empty global context) */ 2557 for (int i = !p->cvlist[0].v.u2[1]; i < p->nconfig; ++i) { 2558 config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0]; 2559 config_plugin_value_t *pemfile = NULL; 2560 config_plugin_value_t *privkey = NULL; 2561 const buffer *ssl_stapling_file = NULL; 2562 const buffer *ssl_ca_file = NULL; 2563 const buffer *ssl_ca_dn_file = NULL; 2564 const buffer *ssl_ca_crl_file = NULL; 2565 X509_STORE *ca_store = NULL; 2566 for (; -1 != cpv->k_id; ++cpv) { 2567 switch (cpv->k_id) { 2568 case 0: /* ssl.pemfile */ 2569 if (!buffer_is_blank(cpv->v.b)) pemfile = cpv; 2570 break; 2571 case 1: /* ssl.privkey */ 2572 if (!buffer_is_blank(cpv->v.b)) privkey = cpv; 2573 break; 2574 case 15:/* ssl.verifyclient.ca-file */ 2575 cpv->k_id = 2; 2576 __attribute_fallthrough__ 2577 case 2: /* ssl.ca-file */ 2578 if (buffer_is_blank(cpv->v.b)) break; 2579 if (!mod_openssl_init_once_openssl(srv)) return HANDLER_ERROR; 2580 ssl_ca_file = cpv->v.b; 2581 cpv->v.v = mod_wolfssl_load_cacerts(ssl_ca_file, srv->errh); 2582 if (NULL != cpv->v.v) { 2583 cpv->vtype = T_CONFIG_LOCAL; 2584 ca_store = ((plugin_cacerts *)cpv->v.v)->certs; 2585 } 2586 else { 2587 log_error(srv->errh, __FILE__, __LINE__, "SSL: %s %s", 2588 ERR_error_string(ERR_get_error(), NULL), 2589 ssl_ca_file->ptr); 2590 return HANDLER_ERROR; 2591 } 2592 break; 2593 case 16:/* ssl.verifyclient.ca-dn-file */ 2594 cpv->k_id = 3; 2595 __attribute_fallthrough__ 2596 case 3: /* ssl.ca-dn-file */ 2597 if (buffer_is_blank(cpv->v.b)) break; 2598 if (!mod_openssl_init_once_openssl(srv)) return HANDLER_ERROR; 2599 ssl_ca_dn_file = cpv->v.b; 2600 #ifndef OPENSSL_ALL 2601 { 2602 log_error(srv->errh, __FILE__, __LINE__, 2603 "SSL: You specified %s but wolfssl library built without " 2604 "necessary support", cpk[cpv->k_id].k); 2605 return HANDLER_ERROR; 2606 } 2607 #endif 2608 cpv->v.v = mod_wolfssl_load_client_CA_file(ssl_ca_dn_file, 2609 srv->errh); 2610 if (NULL != cpv->v.v) { 2611 cpv->vtype = T_CONFIG_LOCAL; 2612 } 2613 else { 2614 log_error(srv->errh, __FILE__, __LINE__, "SSL: %s %s", 2615 ERR_error_string(ERR_get_error(), NULL), 2616 ssl_ca_dn_file->ptr); 2617 return HANDLER_ERROR; 2618 } 2619 break; 2620 case 17:/* ssl.verifyclient.ca-crl-file */ 2621 cpv->k_id = 4; 2622 __attribute_fallthrough__ 2623 case 4: /* ssl.ca-crl-file */ 2624 if (buffer_is_blank(cpv->v.b)) break; 2625 ssl_ca_crl_file = cpv->v.b; 2626 if (0 == i) default_ssl_ca_crl_file = cpv->v.b; 2627 break; 2628 case 5: /* ssl.read-ahead */ 2629 break; 2630 case 6: /* ssl.disable-client-renegotiation */ 2631 /* (force disabled, the default, if HTTP/2 enabled in server) */ 2632 if (srv->srvconf.h2proto) 2633 cpv->v.u = 1; /* disable client renegotiation */ 2634 break; 2635 case 7: /* ssl.verifyclient.activate */ 2636 case 8: /* ssl.verifyclient.enforce */ 2637 break; 2638 case 9: /* ssl.verifyclient.depth */ 2639 if (cpv->v.shrt > 255) { 2640 log_error(srv->errh, __FILE__, __LINE__, 2641 "%s is absurdly large (%hu); limiting to 255", 2642 cpk[cpv->k_id].k, cpv->v.shrt); 2643 cpv->v.shrt = 255; 2644 } 2645 break; 2646 case 10:/* ssl.verifyclient.username */ 2647 if (buffer_is_blank(cpv->v.b)) 2648 cpv->v.b = NULL; 2649 break; 2650 case 11:/* ssl.verifyclient.exportcert */ 2651 break; 2652 case 12:/* ssl.acme-tls-1 */ 2653 if (buffer_is_blank(cpv->v.b)) 2654 cpv->v.b = NULL; 2655 break; 2656 case 13:/* ssl.stapling-file */ 2657 if (!buffer_is_blank(cpv->v.b)) 2658 ssl_stapling_file = cpv->v.b; 2659 break; 2660 case 14:/* debug.log-ssl-noise */ 2661 #if 0 /*(handled further above)*/ 2662 case 15:/* ssl.verifyclient.ca-file */ 2663 case 16:/* ssl.verifyclient.ca-dn-file */ 2664 case 17:/* ssl.verifyclient.ca-crl-file */ 2665 #endif 2666 break; 2667 default:/* should not happen */ 2668 break; 2669 } 2670 } 2671 2672 /* p->cafiles for legacy only */ 2673 /* load all ssl.ca-files into a single chain */ 2674 /*(certificate load order might matter)*/ 2675 if (ssl_ca_dn_file) 2676 array_insert_value(p->cafiles, BUF_PTR_LEN(ssl_ca_dn_file)); 2677 if (ssl_ca_file) 2678 array_insert_value(p->cafiles, BUF_PTR_LEN(ssl_ca_file)); 2679 UNUSED(ca_store); 2680 UNUSED(ssl_ca_crl_file); 2681 UNUSED(default_ssl_ca_crl_file); 2682 2683 if (pemfile) { 2684 #ifndef HAVE_TLS_EXTENSIONS 2685 config_cond_info cfginfo; 2686 uint32_t j = (uint32_t)p->cvlist[i].k_id; 2687 config_get_config_cond_info(&cfginfo, j); 2688 if (j > 0 && (COMP_SERVER_SOCKET != cfginfo.comp 2689 || cfginfo.cond != CONFIG_COND_EQ)) { 2690 if (COMP_HTTP_HOST == cfginfo.comp) 2691 log_error(srv->errh, __FILE__, __LINE__, "SSL:" 2692 "can't use ssl.pemfile with $HTTP[\"host\"], " 2693 "as openssl version does not support TLS extensions"); 2694 else 2695 log_error(srv->errh, __FILE__, __LINE__, "SSL:" 2696 "ssl.pemfile only works in SSL socket binding context " 2697 "as openssl version does not support TLS extensions"); 2698 return HANDLER_ERROR; 2699 } 2700 #endif 2701 if (NULL == privkey) privkey = pemfile; 2702 pemfile->v.v = 2703 network_openssl_load_pemfile(srv, pemfile->v.b, privkey->v.b, 2704 ssl_stapling_file); 2705 if (pemfile->v.v) 2706 pemfile->vtype = T_CONFIG_LOCAL; 2707 else 2708 return HANDLER_ERROR; 2709 } 2710 } 2711 2712 p->defaults.ssl_verifyclient = 0; 2713 p->defaults.ssl_verifyclient_enforce = 1; 2714 p->defaults.ssl_verifyclient_depth = 9; 2715 p->defaults.ssl_verifyclient_export_cert = 0; 2716 p->defaults.ssl_disable_client_renegotiation = 1; 2717 p->defaults.ssl_read_ahead = 0; 2718 2719 /* initialize p->defaults from global config context */ 2720 if (p->nconfig > 0 && p->cvlist->v.u2[1]) { 2721 const config_plugin_value_t *cpv = p->cvlist + p->cvlist->v.u2[0]; 2722 if (-1 != cpv->k_id) 2723 mod_openssl_merge_config(&p->defaults, cpv); 2724 } 2725 2726 return mod_openssl_set_defaults_sockets(srv, p); 2727 } 2728 2729 2730 /* local_send_buffer is a static buffer of size (LOCAL_SEND_BUFSIZE) 2731 * 2732 * it has to stay at the same location all the time to satisfy the needs 2733 * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE 2734 * 2735 * buffer is allocated once, is NOT realloced (note: not thread-safe) 2736 * 2737 * (Note: above restriction no longer true since SSL_CTX_set_mode() is 2738 * called with SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER) 2739 * */ 2740 2741 /* copy small mem chunks into single large buffer before SSL_write() 2742 * to reduce number times write() called underneath SSL_write() and 2743 * potentially reduce number of packets generated if TCP_NODELAY */ 2744 2745 2746 static int 2747 mod_openssl_close_notify(handler_ctx *hctx); 2748 2749 2750 static int 2751 connection_write_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes) 2752 { 2753 handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id]; 2754 SSL * const ssl = hctx->ssl; 2755 log_error_st * const errh = hctx->errh; 2756 2757 if (__builtin_expect( (0 != hctx->close_notify), 0)) 2758 return mod_openssl_close_notify(hctx); 2759 2760 while (max_bytes > 0 && !chunkqueue_is_empty(cq)) { 2761 char *data = local_send_buffer; 2762 uint32_t data_len = LOCAL_SEND_BUFSIZE < max_bytes 2763 ? LOCAL_SEND_BUFSIZE 2764 : (uint32_t)max_bytes; 2765 int wr; 2766 2767 if (0 != chunkqueue_peek_data(cq, &data, &data_len, errh)) return -1; 2768 if (__builtin_expect( (0 == data_len), 0)) { 2769 chunkqueue_remove_finished_chunks(cq); 2770 continue; 2771 } 2772 2773 /** 2774 * SSL_write man-page 2775 * 2776 * WARNING 2777 * When an SSL_write() operation has to be repeated because of 2778 * SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be 2779 * repeated with the same arguments. 2780 */ 2781 2782 ERR_clear_error(); 2783 wr = SSL_write(ssl, data, data_len); 2784 2785 if (__builtin_expect( (hctx->renegotiations > 1), 0) 2786 && hctx->conf.ssl_disable_client_renegotiation) { 2787 log_error(errh, __FILE__, __LINE__, 2788 "SSL: renegotiation initiated by client, killing connection"); 2789 return -1; 2790 } 2791 2792 if (wr <= 0) { 2793 int ssl_r; 2794 unsigned long err; 2795 2796 switch ((ssl_r = SSL_get_error(ssl, wr))) { 2797 case SSL_ERROR_WANT_READ: 2798 con->is_readable = -1; 2799 return 0; /* try again later */ 2800 case SSL_ERROR_WANT_WRITE: 2801 con->is_writable = -1; 2802 return 0; /* try again later */ 2803 case SSL_ERROR_SYSCALL: 2804 /* perhaps we have error waiting in our error-queue */ 2805 if (0 != (err = ERR_get_error())) { 2806 do { 2807 log_error(errh, __FILE__, __LINE__, 2808 "SSL: %d %d %s",ssl_r,wr,ERR_error_string(err,NULL)); 2809 } while((err = ERR_get_error())); 2810 } else if (wr == -1) { 2811 /* no, but we have errno */ 2812 switch(errno) { 2813 case EPIPE: 2814 case ECONNRESET: 2815 return -2; 2816 default: 2817 log_perror(errh, __FILE__, __LINE__, 2818 "SSL: %d %d", ssl_r, wr); 2819 break; 2820 } 2821 } else { 2822 /* neither error-queue nor errno ? */ 2823 log_perror(errh, __FILE__, __LINE__, 2824 "SSL (error): %d %d", ssl_r, wr); 2825 } 2826 break; 2827 2828 case SSL_ERROR_ZERO_RETURN: 2829 /* clean shutdown on the remote side */ 2830 2831 if (wr == 0) return -2; 2832 2833 __attribute_fallthrough__ 2834 default: 2835 while((err = ERR_get_error())) { 2836 log_error(errh, __FILE__, __LINE__, 2837 "SSL: %d %d %s", ssl_r, wr, ERR_error_string(err, NULL)); 2838 } 2839 break; 2840 } 2841 return -1; 2842 } 2843 2844 chunkqueue_mark_written(cq, wr); 2845 max_bytes -= wr; 2846 2847 if ((size_t) wr < data_len) break; /* try again later */ 2848 } 2849 2850 return 0; 2851 } 2852 2853 2854 static int 2855 connection_read_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes) 2856 { 2857 handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id]; 2858 int len; 2859 char *mem = NULL; 2860 size_t mem_len = 0; 2861 2862 UNUSED(max_bytes); 2863 2864 if (__builtin_expect( (0 != hctx->close_notify), 0)) 2865 return mod_openssl_close_notify(hctx); 2866 2867 ERR_clear_error(); 2868 do { 2869 len = SSL_pending(hctx->ssl); 2870 mem_len = len < 2048 ? 2048 : (size_t)len; 2871 chunk * const ckpt = cq->last; 2872 mem = chunkqueue_get_memory(cq, &mem_len); 2873 2874 len = SSL_read(hctx->ssl, mem, mem_len); 2875 if (len > 0) { 2876 chunkqueue_use_memory(cq, ckpt, len); 2877 con->bytes_read += len; 2878 } else { 2879 chunkqueue_use_memory(cq, ckpt, 0); 2880 } 2881 2882 if (hctx->renegotiations > 1 2883 && hctx->conf.ssl_disable_client_renegotiation) { 2884 log_error(hctx->errh, __FILE__, __LINE__, 2885 "SSL: renegotiation initiated by client, killing connection"); 2886 return -1; 2887 } 2888 2889 #ifdef HAVE_ALPN 2890 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation 2891 if (hctx->alpn) { 2892 if (hctx->alpn == MOD_OPENSSL_ALPN_H2) { 2893 if (0 != mod_openssl_alpn_h2_policy(hctx)) 2894 return -1; 2895 } 2896 else if (hctx->alpn == MOD_OPENSSL_ALPN_ACME_TLS_1) { 2897 chunkqueue_reset(cq); 2898 /* initiate handshake in order to send ServerHello. 2899 * Once TLS handshake is complete, return -1 to result in 2900 * CON_STATE_ERROR so that socket connection is quickly closed*/ 2901 if (1 == SSL_do_handshake(hctx->ssl)) return -1; 2902 len = -1; 2903 break; 2904 } 2905 hctx->alpn = 0; 2906 } 2907 #endif 2908 #endif 2909 } while (len > 0 2910 && (hctx->conf.ssl_read_ahead || SSL_pending(hctx->ssl) > 0)); 2911 2912 if (len < 0) { 2913 int oerrno = errno; 2914 int rc, ssl_err; 2915 switch ((rc = SSL_get_error(hctx->ssl, len))) { 2916 case SSL_ERROR_WANT_WRITE: 2917 con->is_writable = -1; 2918 __attribute_fallthrough__ 2919 case SSL_ERROR_WANT_READ: 2920 con->is_readable = 0; 2921 2922 /* the manual says we have to call SSL_read with the same arguments 2923 * next time. we ignore this restriction; no one has complained 2924 * about it in 1.5 yet, so it probably works anyway. 2925 */ 2926 2927 return 0; 2928 case SSL_ERROR_SYSCALL: 2929 /** 2930 * man SSL_get_error() 2931 * 2932 * SSL_ERROR_SYSCALL 2933 * Some I/O error occurred. The OpenSSL error queue may contain 2934 * more information on the error. If the error queue is empty 2935 * (i.e. ERR_get_error() returns 0), ret can be used to find out 2936 * more about the error: If ret == 0, an EOF was observed that 2937 * violates the protocol. If ret == -1, the underlying BIO 2938 * reported an I/O error (for socket I/O on Unix systems, consult 2939 * errno for details). 2940 * 2941 */ 2942 while((ssl_err = ERR_get_error())) { 2943 /* get all errors from the error-queue */ 2944 log_error(hctx->errh, __FILE__, __LINE__, 2945 "SSL: %d %s", rc, ERR_error_string(ssl_err, NULL)); 2946 } 2947 2948 switch(oerrno) { 2949 case ECONNRESET: 2950 if (!hctx->conf.ssl_log_noise) break; 2951 __attribute_fallthrough__ 2952 default: 2953 /* (oerrno should be something like ECONNABORTED not 0 2954 * if client disconnected before anything was sent 2955 * (e.g. TCP connection probe), but it does not appear 2956 * that openssl provides such notification, not even 2957 * something like SSL_R_SSL_HANDSHAKE_FAILURE) */ 2958 if (0==oerrno && 0==cq->bytes_in && !hctx->conf.ssl_log_noise) 2959 break; 2960 2961 errno = oerrno; /*(for log_perror())*/ 2962 log_perror(hctx->errh, __FILE__, __LINE__, 2963 "SSL: %d %d %d", len, rc, oerrno); 2964 break; 2965 } 2966 2967 break; 2968 case SSL_ERROR_ZERO_RETURN: 2969 /* clean shutdown on the remote side */ 2970 2971 if (rc == 0) { 2972 /* FIXME: later */ 2973 } 2974 2975 __attribute_fallthrough__ 2976 default: 2977 while((ssl_err = ERR_get_error())) { 2978 switch (ERR_GET_REASON(ssl_err)) { 2979 case SSL_R_SSL_HANDSHAKE_FAILURE: 2980 #ifdef SSL_R_UNEXPECTED_EOF_WHILE_READING 2981 case SSL_R_UNEXPECTED_EOF_WHILE_READING: 2982 #endif 2983 #ifdef SSL_R_TLSV1_ALERT_UNKNOWN_CA 2984 case SSL_R_TLSV1_ALERT_UNKNOWN_CA: 2985 #endif 2986 #ifdef SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN 2987 case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN: 2988 #endif 2989 #ifdef SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 2990 case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE: 2991 #endif 2992 if (!hctx->conf.ssl_log_noise) continue; 2993 break; 2994 default: 2995 break; 2996 } 2997 /* get all errors from the error-queue */ 2998 log_error(hctx->errh, __FILE__, __LINE__, 2999 "SSL: %d %s", rc, ERR_error_string(ssl_err, NULL)); 3000 } 3001 break; 3002 } 3003 return -1; 3004 } else if (len == 0) { 3005 con->is_readable = 0; 3006 /* the other end close the connection -> KEEP-ALIVE */ 3007 3008 return -2; 3009 } else { 3010 return 0; 3011 } 3012 } 3013 3014 3015 CONNECTION_FUNC(mod_openssl_handle_con_accept) 3016 { 3017 const server_socket *srv_sock = con->srv_socket; 3018 if (!srv_sock->is_ssl) return HANDLER_GO_ON; 3019 3020 plugin_data *p = p_d; 3021 handler_ctx * const hctx = handler_ctx_init(); 3022 request_st * const r = &con->request; 3023 hctx->r = r; 3024 hctx->con = con; 3025 hctx->tmp_buf = con->srv->tmp_buf; 3026 hctx->errh = r->conf.errh; 3027 con->plugin_ctx[p->id] = hctx; 3028 buffer_blank(&r->uri.authority); 3029 3030 plugin_ssl_ctx * const s = p->ssl_ctxs + srv_sock->sidx; 3031 hctx->ssl = SSL_new(s->ssl_ctx); 3032 if (NULL != hctx->ssl 3033 && SSL_set_app_data(hctx->ssl, hctx) 3034 && SSL_set_fd(hctx->ssl, con->fd)) { 3035 SSL_set_accept_state(hctx->ssl); 3036 con->network_read = connection_read_cq_ssl; 3037 con->network_write = connection_write_cq_ssl; 3038 con->proto_default_port = 443; /* "https" */ 3039 mod_openssl_patch_config(r, &hctx->conf); 3040 return HANDLER_GO_ON; 3041 } 3042 else { 3043 log_error(r->conf.errh, __FILE__, __LINE__, 3044 "SSL: %s", ERR_error_string(ERR_get_error(), NULL)); 3045 return HANDLER_ERROR; 3046 } 3047 } 3048 3049 3050 static void 3051 mod_openssl_detach(handler_ctx *hctx) 3052 { 3053 /* step aside from further SSL processing 3054 * (used after handle_connection_shut_wr hook) */ 3055 /* future: might restore prior network_read and network_write fn ptrs */ 3056 hctx->con->is_ssl_sock = 0; 3057 /* if called after handle_connection_shut_wr hook, shutdown SHUT_WR */ 3058 if (-1 == hctx->close_notify) shutdown(hctx->con->fd, SHUT_WR); 3059 hctx->close_notify = 1; 3060 } 3061 3062 3063 CONNECTION_FUNC(mod_openssl_handle_con_shut_wr) 3064 { 3065 plugin_data *p = p_d; 3066 handler_ctx *hctx = con->plugin_ctx[p->id]; 3067 if (NULL == hctx) return HANDLER_GO_ON; 3068 3069 hctx->close_notify = -2; 3070 if (SSL_is_init_finished(hctx->ssl)) { 3071 mod_openssl_close_notify(hctx); 3072 } 3073 else { 3074 mod_openssl_detach(hctx); 3075 } 3076 3077 return HANDLER_GO_ON; 3078 } 3079 3080 3081 static int 3082 mod_openssl_close_notify(handler_ctx *hctx) 3083 { 3084 int ret, ssl_r; 3085 unsigned long err; 3086 log_error_st *errh; 3087 3088 if (1 == hctx->close_notify) return -2; 3089 3090 ERR_clear_error(); 3091 switch ((ret = SSL_shutdown(hctx->ssl))) { 3092 case 1: 3093 mod_openssl_detach(hctx); 3094 return -2; 3095 case 0: 3096 /* Drain SSL read buffers in case pending records need processing. 3097 * Limit to reading next record to avoid denial of service when CPU 3098 * processing TLS is slower than arrival speed of TLS data packets. 3099 * (unless hctx->conf.ssl_read_ahead is set) 3100 * 3101 * references: 3102 * 3103 * "New session ticket breaks bidirectional shutdown of TLS 1.3 connection" 3104 * https://github.com/openssl/openssl/issues/6262 3105 * 3106 * The peer is still allowed to send data after receiving the 3107 * "close notify" event. If the peer did send data it need to be 3108 * processed by calling SSL_read() before calling SSL_shutdown() a 3109 * second time. SSL_read() will indicate the end of the peer data by 3110 * returning <= 0 and SSL_get_error() returning 3111 * SSL_ERROR_ZERO_RETURN. It is recommended to call SSL_read() 3112 * between SSL_shutdown() calls. 3113 * 3114 * Additional discussion in "Auto retry in shutdown" 3115 * https://github.com/openssl/openssl/pull/6340 3116 */ 3117 ssl_r = SSL_pending(hctx->ssl); 3118 if (ssl_r) { 3119 do { 3120 char buf[4096]; 3121 ret = SSL_read(hctx->ssl, buf, (int)sizeof(buf)); 3122 } while (ret > 0 && (hctx->conf.ssl_read_ahead||(ssl_r-=ret))); 3123 } 3124 3125 ERR_clear_error(); 3126 switch ((ret = SSL_shutdown(hctx->ssl))) { 3127 case 1: 3128 mod_openssl_detach(hctx); 3129 return -2; 3130 case 0: 3131 hctx->close_notify = -1; 3132 return 0; 3133 default: 3134 break; 3135 } 3136 3137 __attribute_fallthrough__ 3138 default: 3139 3140 if (!SSL_is_init_finished(hctx->ssl)) { 3141 mod_openssl_detach(hctx); 3142 return -2; 3143 } 3144 3145 switch ((ssl_r = SSL_get_error(hctx->ssl, ret))) { 3146 case SSL_ERROR_ZERO_RETURN: 3147 case SSL_ERROR_WANT_WRITE: 3148 case SSL_ERROR_WANT_READ: 3149 hctx->close_notify = -1; 3150 return 0; /* try again later */ 3151 case SSL_ERROR_SYSCALL: 3152 /* perhaps we have error waiting in our error-queue */ 3153 errh = hctx->r->conf.errh; 3154 if (0 != (err = ERR_get_error())) { 3155 do { 3156 log_error(errh, __FILE__, __LINE__, 3157 "SSL: %d %d %s",ssl_r,ret,ERR_error_string(err,NULL)); 3158 } while((err = ERR_get_error())); 3159 } else if (errno != 0) { 3160 /*ssl bug (see lighttpd ticket #2213): sometimes errno==0*/ 3161 switch(errno) { 3162 case EPIPE: 3163 case ECONNRESET: 3164 break; 3165 default: 3166 log_perror(errh, __FILE__, __LINE__, 3167 "SSL (error): %d %d", ssl_r, ret); 3168 break; 3169 } 3170 } 3171 3172 break; 3173 default: 3174 errh = hctx->r->conf.errh; 3175 while((err = ERR_get_error())) { 3176 log_error(errh, __FILE__, __LINE__, 3177 "SSL: %d %d %s", ssl_r, ret, ERR_error_string(err, NULL)); 3178 } 3179 3180 break; 3181 } 3182 } 3183 ERR_clear_error(); 3184 hctx->close_notify = -1; 3185 return ret; 3186 } 3187 3188 3189 CONNECTION_FUNC(mod_openssl_handle_con_close) 3190 { 3191 plugin_data *p = p_d; 3192 handler_ctx *hctx = con->plugin_ctx[p->id]; 3193 if (NULL != hctx) { 3194 con->plugin_ctx[p->id] = NULL; 3195 handler_ctx_free(hctx); 3196 } 3197 3198 return HANDLER_GO_ON; 3199 } 3200 3201 3202 #ifndef OBJ_nid2sn 3203 #define OBJ_nid2sn wolfSSL_OBJ_nid2sn 3204 #endif 3205 #ifndef OBJ_obj2nid 3206 #define OBJ_obj2nid wolfSSL_OBJ_obj2nid 3207 #endif 3208 #include <wolfssl/wolfcrypt/asn_public.h> 3209 3210 3211 static void 3212 https_add_ssl_client_subject (request_st * const r, X509_NAME *xn) 3213 { 3214 const size_t prelen = sizeof("SSL_CLIENT_S_DN_")-1; 3215 char key[64] = "SSL_CLIENT_S_DN_"; 3216 for (int i = 0, nentries = X509_NAME_entry_count(xn); i < nentries; ++i) { 3217 int xobjnid; 3218 const char * xobjsn; 3219 X509_NAME_ENTRY *xe; 3220 3221 if (!(xe = wolfSSL_X509_NAME_get_entry(xn, i))) { 3222 continue; 3223 } 3224 xobjnid = OBJ_obj2nid((ASN1_OBJECT*)X509_NAME_ENTRY_get_object(xe)); 3225 xobjsn = OBJ_nid2sn(xobjnid); 3226 if (xobjsn) { 3227 const size_t len = strlen(xobjsn); 3228 if (prelen+len >= sizeof(key)) continue; 3229 memcpy(key+prelen, xobjsn, len); /*(not '\0'-terminated)*/ 3230 http_header_env_set(r, key, prelen+len, 3231 (const char*)X509_NAME_ENTRY_get_data(xe)->data, 3232 X509_NAME_ENTRY_get_data(xe)->length); 3233 } 3234 } 3235 } 3236 3237 3238 __attribute_cold__ 3239 static void 3240 https_add_ssl_client_verify_err (buffer * const b, long status) 3241 { 3242 char errstr[256]; 3243 ERR_error_string_n(status, errstr, sizeof(errstr)); 3244 buffer_append_string(b, errstr); 3245 } 3246 3247 3248 __attribute_noinline__ 3249 static void 3250 https_add_ssl_client_entries (request_st * const r, handler_ctx * const hctx) 3251 { 3252 X509 *xs; 3253 X509_NAME *xn; 3254 buffer *vb = http_header_env_set_ptr(r, CONST_STR_LEN("SSL_CLIENT_VERIFY")); 3255 3256 long vr = SSL_get_verify_result(hctx->ssl); 3257 if (vr != X509_V_OK) { 3258 buffer_copy_string_len(vb, CONST_STR_LEN("FAILED:")); 3259 https_add_ssl_client_verify_err(vb, vr); 3260 return; 3261 } else if (!(xs = SSL_get_peer_certificate(hctx->ssl))) { 3262 buffer_copy_string_len(vb, CONST_STR_LEN("NONE")); 3263 return; 3264 } else { 3265 buffer_copy_string_len(vb, CONST_STR_LEN("SUCCESS")); 3266 } 3267 3268 xn = X509_get_subject_name(xs); 3269 { 3270 char buf[256]; 3271 int len = safer_X509_NAME_oneline(xn, buf, sizeof(buf)); 3272 if (len > 0) { 3273 if (len >= (int)sizeof(buf)) len = (int)sizeof(buf)-1; 3274 http_header_env_set(r, 3275 CONST_STR_LEN("SSL_CLIENT_S_DN"), 3276 buf, (size_t)len); 3277 } 3278 } 3279 3280 https_add_ssl_client_subject(r, xn); 3281 3282 { 3283 byte buf[64]; 3284 int bsz = (int)sizeof(buf); 3285 if (wolfSSL_X509_get_serial_number(xs, buf, &bsz) == WOLFSSL_SUCCESS) { 3286 buffer_append_string_encoded_hex_uc( 3287 http_header_env_set_ptr(r, CONST_STR_LEN("SSL_CLIENT_M_SERIAL")), 3288 (char *)buf, (size_t)bsz); 3289 } 3290 } 3291 3292 if (hctx->conf.ssl_verifyclient_username) { 3293 /* pick one of the exported values as "REMOTE_USER", for example 3294 * ssl.verifyclient.username = "SSL_CLIENT_S_DN_UID" 3295 * or 3296 * ssl.verifyclient.username = "SSL_CLIENT_S_DN_emailAddress" 3297 */ 3298 const buffer *varname = hctx->conf.ssl_verifyclient_username; 3299 vb = http_header_env_get(r, BUF_PTR_LEN(varname)); 3300 if (vb) { /* same as mod_auth_api.c:http_auth_setenv() */ 3301 http_header_env_set(r, 3302 CONST_STR_LEN("REMOTE_USER"), 3303 BUF_PTR_LEN(vb)); 3304 http_header_env_set(r, 3305 CONST_STR_LEN("AUTH_TYPE"), 3306 CONST_STR_LEN("SSL_CLIENT_VERIFY")); 3307 } 3308 } 3309 3310 if (hctx->conf.ssl_verifyclient_export_cert) { 3311 int dersz, pemsz; 3312 const unsigned char *der = wolfSSL_X509_get_der(xs, &dersz); 3313 pemsz = der ? wc_DerToPemEx(der, dersz, NULL, 0, NULL, CERT_TYPE) : 0; 3314 if (pemsz > 0) { 3315 vb = http_header_env_set_ptr(r, CONST_STR_LEN("SSL_CLIENT_CERT")); 3316 if (0 == wc_DerToPemEx(der, dersz, 3317 (byte *)buffer_string_prepare_copy(vb,pemsz), 3318 pemsz, NULL, CERT_TYPE)) 3319 buffer_commit(vb, (uint32_t)pemsz); 3320 } 3321 } 3322 X509_free(xs); 3323 } 3324 3325 3326 static void 3327 http_cgi_ssl_env (request_st * const r, handler_ctx * const hctx) 3328 { 3329 const char *s; 3330 const SSL_CIPHER *cipher; 3331 3332 s = SSL_get_version(hctx->ssl); 3333 http_header_env_set(r, CONST_STR_LEN("SSL_PROTOCOL"), s, strlen(s)); 3334 3335 if ((cipher = SSL_get_current_cipher(hctx->ssl))) { 3336 s = SSL_CIPHER_get_name(cipher); 3337 http_header_env_set(r, CONST_STR_LEN("SSL_CIPHER"), s, strlen(s)); 3338 /*(wolfSSL preprocessor defines are obnoxious)*/ 3339 #if defined(OPENSSL_ALL) \ 3340 || (defined(OPENSSL_EXTRA) \ 3341 && (defined(HAVE_STUNNEL) || \ 3342 defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \ 3343 defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH))) 3344 int usekeysize, algkeysize = 0; 3345 char buf[LI_ITOSTRING_LENGTH]; 3346 usekeysize = wolfSSL_CIPHER_get_bits(cipher, &algkeysize); 3347 if (0 == algkeysize) algkeysize = usekeysize; 3348 http_header_env_set(r, CONST_STR_LEN("SSL_CIPHER_USEKEYSIZE"), 3349 buf, li_itostrn(buf, sizeof(buf), usekeysize)); 3350 http_header_env_set(r, CONST_STR_LEN("SSL_CIPHER_ALGKEYSIZE"), 3351 buf, li_itostrn(buf, sizeof(buf), algkeysize)); 3352 #endif 3353 } 3354 } 3355 3356 3357 REQUEST_FUNC(mod_openssl_handle_request_env) 3358 { 3359 plugin_data *p = p_d; 3360 /* simple flag for request_env_patched */ 3361 if (r->plugin_ctx[p->id]) return HANDLER_GO_ON; 3362 handler_ctx *hctx = r->con->plugin_ctx[p->id]; 3363 if (NULL == hctx) return HANDLER_GO_ON; 3364 r->plugin_ctx[p->id] = (void *)(uintptr_t)1u; 3365 3366 http_cgi_ssl_env(r, hctx); 3367 if (hctx->conf.ssl_verifyclient) { 3368 https_add_ssl_client_entries(r, hctx); 3369 } 3370 3371 return HANDLER_GO_ON; 3372 } 3373 3374 3375 REQUEST_FUNC(mod_openssl_handle_uri_raw) 3376 { 3377 /* mod_openssl must be loaded prior to mod_auth 3378 * if mod_openssl is configured to set REMOTE_USER based on client cert */ 3379 /* mod_openssl must be loaded after mod_extforward 3380 * if mod_openssl config is based on lighttpd.conf remote IP conditional 3381 * using remote IP address set by mod_extforward, *unless* PROXY protocol 3382 * is enabled with extforward.hap-PROXY = "enable", in which case the 3383 * reverse is true: mod_extforward must be loaded after mod_openssl */ 3384 plugin_data *p = p_d; 3385 handler_ctx *hctx = r->con->plugin_ctx[p->id]; 3386 if (NULL == hctx) return HANDLER_GO_ON; 3387 3388 mod_openssl_patch_config(r, &hctx->conf); 3389 if (hctx->conf.ssl_verifyclient) { 3390 mod_openssl_handle_request_env(r, p); 3391 } 3392 3393 return HANDLER_GO_ON; 3394 } 3395 3396 3397 REQUEST_FUNC(mod_openssl_handle_request_reset) 3398 { 3399 plugin_data *p = p_d; 3400 r->plugin_ctx[p->id] = NULL; /* simple flag for request_env_patched */ 3401 return HANDLER_GO_ON; 3402 } 3403 3404 3405 TRIGGER_FUNC(mod_openssl_handle_trigger) { 3406 const plugin_data * const p = p_d; 3407 const unix_time64_t cur_ts = log_epoch_secs; 3408 if (cur_ts & 0x3f) return HANDLER_GO_ON; /*(continue once each 64 sec)*/ 3409 UNUSED(srv); 3410 UNUSED(p); 3411 3412 #ifdef HAVE_SESSION_TICKET 3413 mod_openssl_session_ticket_key_check(p, cur_ts); 3414 #endif 3415 3416 #ifdef HAVE_OCSP 3417 mod_openssl_refresh_stapling_files(srv, p, cur_ts); 3418 #endif 3419 3420 return HANDLER_GO_ON; 3421 } 3422 3423 3424 int mod_wolfssl_plugin_init (plugin *p); 3425 int mod_wolfssl_plugin_init (plugin *p) 3426 { 3427 p->version = LIGHTTPD_VERSION_ID; 3428 p->name = "wolfssl"; 3429 p->init = mod_openssl_init; 3430 p->cleanup = mod_openssl_free; 3431 p->priv_defaults= mod_openssl_set_defaults; 3432 3433 p->handle_connection_accept = mod_openssl_handle_con_accept; 3434 p->handle_connection_shut_wr = mod_openssl_handle_con_shut_wr; 3435 p->handle_connection_close = mod_openssl_handle_con_close; 3436 p->handle_uri_raw = mod_openssl_handle_uri_raw; 3437 p->handle_request_env = mod_openssl_handle_request_env; 3438 p->handle_request_reset = mod_openssl_handle_request_reset; 3439 p->handle_trigger = mod_openssl_handle_trigger; 3440 3441 return 0; 3442 } 3443 3444 3445 static int 3446 mod_openssl_ssl_conf_proto_val (server *srv, plugin_config_socket *s, const buffer *b, int max) 3447 { 3448 if (NULL == b) /* default: min TLSv1.2, max TLSv1.3 */ 3449 return max ? WOLFSSL_TLSV1_3 : WOLFSSL_TLSV1_2; 3450 else if (buffer_eq_icase_slen(b, CONST_STR_LEN("None"))) /*"disable" limit*/ 3451 return max 3452 ? WOLFSSL_TLSV1_3 3453 : (s->ssl_use_sslv3 ? WOLFSSL_SSLV3 : WOLFSSL_TLSV1); 3454 else if (buffer_eq_icase_slen(b, CONST_STR_LEN("SSLv3"))) 3455 return WOLFSSL_SSLV3; 3456 else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.0"))) 3457 return WOLFSSL_TLSV1; 3458 else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.1"))) 3459 return WOLFSSL_TLSV1_1; 3460 else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.2"))) 3461 return WOLFSSL_TLSV1_2; 3462 else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.3"))) 3463 return WOLFSSL_TLSV1_3; 3464 else { 3465 if (buffer_eq_icase_slen(b, CONST_STR_LEN("DTLSv1")) 3466 || buffer_eq_icase_slen(b, CONST_STR_LEN("DTLSv1.2"))) 3467 log_error(srv->errh, __FILE__, __LINE__, 3468 "SSL: ssl.openssl.ssl-conf-cmd %s %s ignored", 3469 max ? "MaxProtocol" : "MinProtocol", b->ptr); 3470 else 3471 log_error(srv->errh, __FILE__, __LINE__, 3472 "SSL: ssl.openssl.ssl-conf-cmd %s %s invalid; ignored", 3473 max ? "MaxProtocol" : "MinProtocol", b->ptr); 3474 } 3475 return max ? WOLFSSL_TLSV1_3 : WOLFSSL_TLSV1_2; 3476 } 3477 3478 3479 static int 3480 mod_openssl_ssl_conf_cmd (server *srv, plugin_config_socket *s) 3481 { 3482 /* reference: 3483 * https://www.openssl.org/docs/man1.1.1/man3/SSL_CONF_cmd.html */ 3484 int rc = 0; 3485 buffer *cipherstring = NULL; 3486 /*buffer *ciphersuites = NULL;*/ 3487 buffer *minb = NULL; 3488 buffer *maxb = NULL; 3489 buffer *curves = NULL; 3490 3491 for (size_t i = 0; i < s->ssl_conf_cmd->used; ++i) { 3492 data_string *ds = (data_string *)s->ssl_conf_cmd->data[i]; 3493 if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("CipherString"))) 3494 cipherstring = &ds->value; 3495 #if 0 3496 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Ciphersuites"))) 3497 ciphersuites = &ds->value; 3498 #endif 3499 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Curves")) 3500 || buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Groups"))) 3501 curves = &ds->value; 3502 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("MaxProtocol"))) 3503 maxb = &ds->value; 3504 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("MinProtocol"))) 3505 minb = &ds->value; 3506 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Protocol"))) { 3507 /* openssl config for Protocol=... is complex and deprecated */ 3508 log_error(srv->errh, __FILE__, __LINE__, 3509 "SSL: ssl.openssl.ssl-conf-cmd %s ignored; " 3510 "use MinProtocol=... and MaxProtocol=... instead", 3511 ds->key.ptr); 3512 } 3513 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Options"))) { 3514 for (char *v = ds->value.ptr, *e; *v; v = e) { 3515 while (*v == ' ' || *v == '\t' || *v == ',') ++v; 3516 int flag = 1; 3517 if (*v == '-') { 3518 flag = 0; 3519 ++v; 3520 } 3521 for (e = v; light_isalpha(*e); ++e) ; 3522 switch ((int)(e-v)) { 3523 case 11: 3524 if (buffer_eq_icase_ssn(v, "Compression", 11)) { 3525 /* (force disabled, the default, if HTTP/2 enabled) */ 3526 if (srv->srvconf.h2proto) 3527 flag = 0; 3528 if (flag) 3529 SSL_CTX_clear_options(s->ssl_ctx, 3530 SSL_OP_NO_COMPRESSION); 3531 else 3532 SSL_CTX_set_options(s->ssl_ctx, 3533 SSL_OP_NO_COMPRESSION); 3534 continue; 3535 } 3536 break; 3537 case 13: 3538 if (buffer_eq_icase_ssn(v, "SessionTicket", 13)) { 3539 if (flag) 3540 SSL_CTX_clear_options(s->ssl_ctx, 3541 SSL_OP_NO_TICKET); 3542 else 3543 SSL_CTX_set_options(s->ssl_ctx, 3544 SSL_OP_NO_TICKET); 3545 continue; 3546 } 3547 break; 3548 case 16: 3549 if (buffer_eq_icase_ssn(v, "ServerPreference", 16)) { 3550 if (flag) 3551 SSL_CTX_set_options(s->ssl_ctx, 3552 SSL_OP_CIPHER_SERVER_PREFERENCE); 3553 else 3554 SSL_CTX_clear_options(s->ssl_ctx, 3555 SSL_OP_CIPHER_SERVER_PREFERENCE); 3556 s->ssl_honor_cipher_order = flag; 3557 continue; 3558 } 3559 break; 3560 default: 3561 break; 3562 } 3563 /* warn if not explicitly handled or ignored above */ 3564 if (!flag) --v; 3565 log_error(srv->errh, __FILE__, __LINE__, 3566 "SSL: ssl.openssl.ssl-conf-cmd Options %.*s " 3567 "ignored", (int)(e-v), v); 3568 } 3569 } 3570 #if 0 3571 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("..."))) { 3572 } 3573 #endif 3574 else { 3575 /* warn if not explicitly handled or ignored above */ 3576 log_error(srv->errh, __FILE__, __LINE__, 3577 "SSL: ssl.openssl.ssl-conf-cmd %s ignored", 3578 ds->key.ptr); 3579 } 3580 3581 } 3582 3583 if (minb) { 3584 int n = mod_openssl_ssl_conf_proto_val(srv, s, minb, 0); 3585 if (wolfSSL_CTX_SetMinVersion(s->ssl_ctx, n) != WOLFSSL_SUCCESS) 3586 rc = -1; 3587 } 3588 3589 if (maxb) { 3590 /* WolfSSL max ver is set at WolfSSL compile-time */ 3591 #if LIBWOLFSSL_VERSION_HEX >= 0x04002000 3592 /*(could use SSL_OP_NO_* before 4.2.0)*/ 3593 /*(wolfSSL_CTX_set_max_proto_version() 4.6.0 uses different defines)*/ 3594 int n = mod_openssl_ssl_conf_proto_val(srv, s, maxb, 1); 3595 switch (n) { 3596 case WOLFSSL_SSLV3: 3597 wolfSSL_CTX_set_options(s->ssl_ctx, WOLFSSL_OP_NO_TLSv1); 3598 __attribute_fallthrough__ 3599 case WOLFSSL_TLSV1: 3600 wolfSSL_CTX_set_options(s->ssl_ctx, WOLFSSL_OP_NO_TLSv1_1); 3601 __attribute_fallthrough__ 3602 case WOLFSSL_TLSV1_1: 3603 wolfSSL_CTX_set_options(s->ssl_ctx, WOLFSSL_OP_NO_TLSv1_2); 3604 __attribute_fallthrough__ 3605 case WOLFSSL_TLSV1_2: 3606 wolfSSL_CTX_set_options(s->ssl_ctx, WOLFSSL_OP_NO_TLSv1_3); 3607 __attribute_fallthrough__ 3608 case WOLFSSL_TLSV1_3: 3609 default: 3610 break; 3611 } 3612 #endif 3613 } 3614 3615 if (cipherstring && !buffer_is_blank(cipherstring)) { 3616 /* Disable support for low encryption ciphers */ 3617 buffer_append_string_len(cipherstring, 3618 CONST_STR_LEN(":!aNULL:!eNULL:!EXP")); 3619 if (SSL_CTX_set_cipher_list(s->ssl_ctx, cipherstring->ptr) != 1) { 3620 log_error(srv->errh, __FILE__, __LINE__, 3621 "SSL: %s", ERR_error_string(ERR_get_error(), NULL)); 3622 rc = -1; 3623 } 3624 3625 if (s->ssl_honor_cipher_order) 3626 SSL_CTX_set_options(s->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); 3627 } 3628 3629 if (curves && !buffer_is_blank(curves)) { 3630 if (!mod_openssl_ssl_conf_curves(srv, s, curves)) 3631 rc = -1; 3632 } 3633 3634 return rc; 3635 } 3636