1 /* 2 * mod_nss - Network Security Services (NSS) 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 * Portions supporting mod_nss_ssl_conf_ciphersuites() (see end of file) 8 * Copyright 2001-2004 The Apache Software Foundation 9 */ 10 /* 11 * NSS docs: https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS 12 * 13 * NSS documentation is seriously lacking and man pages exist only for apps; 14 * be prepared to slog through organic piles of NSS library code 15 * 16 * Note: If session tickets are -not- disabled with 17 * ssl.openssl.ssl-conf-cmd = ("Options" => "-SessionTicket") 18 * NSS never rotates server ticket encryption key (STEK) while running. 19 * Therefore, if session tickets are enabled, lighttpd server should be 20 * restarted (by an external job) at least every 24 hours. Restarting 21 * lighttpd generates a new key that is shared by lighttpd workers. There 22 * is no mechanism implemented in lighttpd mod_nss to share STEK between 23 * independent lighttpd servers. ssl.stek-file is not used in mod_nss. 24 * 25 * NSS provides SSL_SetSessionTicketKeyPair(pubKey, privKey) to set RSA keys. 26 * However, to match behavior of other lighttpd TLS modules, it seems we want 27 * to set the private struct ssl_self_encrypt_keys in lib/ssl/sslsnce.c 28 * instead of the private struct ssl_self_encrypt_key_pair. 29 * sslSelfEncryptKeys ssl_self_encrypt_keys contains: 30 * PRUint8 keyName[SELF_ENCRYPT_KEY_NAME_LEN]; 31 * PK11SymKey *encKey; 32 * PK11SymKey *macKey; 33 * (see lib/ssl/sslsnce.c:GenerateSelfEncryptKeys()) 34 * PK11SymKey *masterSecret in ssl3CipherSpec in ssl3State in sslSessionID 35 * is private in lib/ssl/ssl3con.c 36 * 37 * Update: NSS developer explains: 38 * "The way that we currently operate is to tie the session key encryption to 39 * the server public key. Which only works if you have an RSA key configured" 40 * https://bugzilla.mozilla.org/show_bug.cgi?id=1673254 41 * 42 * not implemented: 43 * - session ticket rotation (see comments above) 44 * - OCSP Must Staple detection 45 * - ssl.honor-cipher-order 46 * - ssl.verifyclient.depth 47 * - ssl.dh-file 48 * - ssl.ec-curve 49 * - ssl.openssl.ssl-conf-cmd Ciphersuite 50 * 51 * future: 52 * - consider SSL_AlertReceivedCallback() to set SSLAlertCallback 53 * in order to (optionally) log alerts, and to abort connection if fatal alert 54 * - consider using experimental API for cipher suite choice in lib/ssl/sslexp.h 55 * SSL_CipherSuiteOrderGet 56 * SSL_CipherSuiteOrderSet 57 * - detect CLOSE_NOTIFY from client 58 * - feature options 59 * - SSL_ENABLE_FALSE_START 60 * - SSL_ENABLE_DELEGATED_CREDENTIALS 61 * - SSL_ENABLE_0RTT_DATA 62 * - SSL_SUPPRESS_END_OF_EARLY_DATA 63 * - crypto option using FreeBL 64 * "A core element of NSS is FreeBL, a base library providing hash functions, 65 * big number calculations, and cryptographic algorithms." 66 * "Softoken is an NSS module that exposes most FreeBL functionality as a 67 * PKCS#11 module." 68 * "PR_GetRandomNoise - Produces a random value for use as a seed value for 69 * another random number generator." 70 */ 71 #include "first.h" 72 73 #include <sys/types.h> 74 #include <sys/stat.h> 75 #include <errno.h> 76 #include <fcntl.h> 77 #include <stdarg.h> 78 #include <stdlib.h> 79 #include <stdio.h> /* vsnprintf() */ 80 #include <string.h> 81 82 #ifdef __has_include 83 #if __has_include(<nss3/nss.h>) 84 #define NSS_VER_INCLUDE 85 #endif 86 #endif 87 88 #ifndef NSS_VER_INCLUDE 89 #include <nspr/nspr.h> 90 #include <nspr/private/pprio.h> /* see mod_nss_io_ctor() comments */ 91 #include <nss/nss.h> 92 #include <nss/nssb64.h> 93 #include <nss/keyhi.h> 94 #include <nss/pk11pub.h> 95 #include <nss/secder.h> 96 #include <nss/secerr.h> 97 #include <nss/ssl.h> 98 #include <nss/sslproto.h> 99 #else 100 #include <nspr4/nspr.h> 101 #include <nspr4/private/pprio.h> /* see mod_nss_io_ctor() comments */ 102 #include <nss3/nss.h> 103 #include <nss3/nssb64.h> 104 #include <nss3/keyhi.h> 105 #include <nss3/pk11pub.h> 106 #include <nss3/secder.h> 107 #include <nss3/secerr.h> 108 #include <nss3/ssl.h> 109 #include <nss3/sslproto.h> 110 #endif 111 112 #include "base.h" 113 #include "fdevent.h" 114 #include "http_header.h" 115 #include "http_kv.h" 116 #include "log.h" 117 #include "plugin.h" 118 #include "safe_memclear.h" 119 120 typedef struct { 121 /* SNI per host: with COMP_SERVER_SOCKET, COMP_HTTP_SCHEME, COMP_HTTP_HOST */ 122 char must_staple; 123 CERTCertificate *ssl_pemfile_x509; 124 SECKEYPrivateKey *ssl_pemfile_pkey; 125 SSLExtraServerCertData ssl_credex; 126 const buffer *ssl_stapling_file; 127 time_t ssl_stapling_loadts; 128 time_t ssl_stapling_nextts; 129 SECItemArray OCSPResponses; 130 SECItem OCSPResponse; 131 } plugin_cert; 132 133 typedef struct { 134 PRFileDesc *model; 135 SSLVersionRange protos; 136 PRBool ssl_compression; 137 int8_t ssl_session_ticket; 138 } plugin_ssl_ctx; 139 140 typedef struct { 141 plugin_cert *pc; 142 143 /*(used only during startup; not patched)*/ 144 unsigned char ssl_enabled; /* only interesting for setting up listening sockets. don't use at runtime */ 145 unsigned char ssl_honor_cipher_order; /* determine SSL cipher in server-preferred order, not client-order */ 146 unsigned char ssl_empty_fragments; 147 unsigned char ssl_use_sslv2; 148 unsigned char ssl_use_sslv3; 149 const buffer *ssl_cipher_list; 150 const buffer *ssl_ec_curve; 151 array *ssl_conf_cmd; 152 153 /*(copied from plugin_data for socket ssl_ctx config)*/ 154 unsigned char ssl_session_ticket; 155 unsigned char ssl_verifyclient; 156 unsigned char ssl_verifyclient_enforce; 157 unsigned char ssl_verifyclient_depth; 158 159 PRFileDesc *model; 160 SSLVersionRange protos; 161 PRBool ssl_compression; 162 } plugin_config_socket; /*(used at startup during configuration)*/ 163 164 typedef struct { 165 /* SNI per host: w/ COMP_SERVER_SOCKET, COMP_HTTP_SCHEME, COMP_HTTP_HOST */ 166 plugin_cert *pc; 167 CERTCertList *ssl_ca_file; 168 CERTCertList *ssl_ca_dn_file; 169 170 unsigned char ssl_verifyclient; 171 unsigned char ssl_verifyclient_enforce; 172 unsigned char ssl_verifyclient_depth; 173 unsigned char ssl_verifyclient_export_cert; 174 unsigned char ssl_read_ahead; 175 unsigned char ssl_log_noise; 176 unsigned char ssl_disable_client_renegotiation; 177 const buffer *ssl_verifyclient_username; 178 const buffer *ssl_acme_tls_1; 179 } plugin_config; 180 181 typedef struct { 182 PLUGIN_DATA; 183 plugin_ssl_ctx *ssl_ctxs; 184 plugin_config defaults; 185 server *srv; 186 } plugin_data; 187 188 static int ssl_is_init; 189 /* need assigned p->id for deep access of module handler_ctx for connection 190 * i.e. handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id]; */ 191 static plugin_data *plugin_data_singleton; 192 #define LOCAL_SEND_BUFSIZE 16384 /* DEFAULT_MAX_RECORD_SIZE */ 193 static char *local_send_buffer; 194 195 typedef struct { 196 PRFileDesc *ssl; 197 request_st *r; 198 connection *con; 199 int8_t close_notify; 200 uint8_t alpn; 201 int8_t ssl_session_ticket; 202 int handshake; 203 size_t pending_write; 204 plugin_config conf; 205 int verify_status; 206 buffer *tmp_buf; 207 log_error_st *errh; 208 } handler_ctx; 209 210 211 static handler_ctx * 212 handler_ctx_init (void) 213 { 214 handler_ctx *hctx = calloc(1, sizeof(*hctx)); 215 force_assert(hctx); 216 return hctx; 217 } 218 219 220 static void mod_nss_io_dtor (PRFileDesc *ssl); 221 222 static void 223 handler_ctx_free (handler_ctx *hctx) 224 { 225 mod_nss_io_dtor(hctx->ssl); 226 free(hctx); 227 } 228 229 230 __attribute_cold__ 231 static void elog(log_error_st * const errh, 232 const char * const file, const int line, 233 const char * const msg) 234 { 235 /* error logging convenience function that decodes NSS result codes */ 236 const PRErrorCode rc = PR_GetError(); 237 const char *s = PR_ErrorToName(rc); 238 log_error(errh, file, line, "NSS: %s: (%s) %s", 239 msg, s ? s : "", PR_ErrorToString(rc, 0)); 240 } 241 242 243 __attribute_cold__ 244 __attribute_format__((__printf__, 4, 5)) 245 static void elogf(log_error_st * const errh, 246 const char * const file, const int line, 247 const char * const fmt, ...) 248 { 249 char msg[1024]; 250 va_list ap; 251 va_start(ap, fmt); 252 vsnprintf(msg, sizeof(msg), fmt, ap); 253 va_end(ap); 254 elog(errh, file, line, msg); 255 } 256 257 258 static PRFileDesc * 259 mod_nss_io_ctor (int fd, PRFileDesc *model, log_error_st *errh) 260 { 261 /* WTH? Why not a public PR_ImportTCPSocket() interface from NSPR? 262 * (and PR_GetInheritedFD() is not a great replacement interface to 263 * fudge NSPR_INHERIT_FDS in environment for each connection) 264 * 265 * #include <nspr4/private/pprio.h> 266 * Use internal routines to set up PRFileDesc. Perform actions underlying 267 * PR_ImportTCPSocket() to avoid excess work done by PR_ImportTCPSocket(), 268 * which includes closing the fd if there is a failure. Could pass 0 as fd 269 * to PR_AllocFileDesc() to avoid NSPR setting O_NONBLOCK since already set. 270 * Instead, employ simpler PR_CreateSocketPollFd() and change methods table, 271 * which handles _PR_ImplicitInitialization() (PR_AllocFileDesc() does not). 272 * (WTH?: PR_AllocFileDesc() has limit fd < FD_SETSIZE when XP_UNIX defined) 273 * Note: since bypassing PR_ImportTCPSocket() this might not work on Windows 274 * which expects prfd->secret->af to be set to AF_INET. 275 */ 276 #if defined(_WIN32) && !defined(__CYGWIN__) 277 PRFileDesc *prfd = PR_ImportTCPSocket(fd); 278 if (NULL == prfd) { 279 elog(errh, __FILE__, __LINE__, "PR_ImportTCPSocket()"); 280 return NULL; 281 } 282 #else 283 /*PRFileDesc *prfd = PR_AllocFileDesc(0, PR_GetTCPMethods());*/ 284 PRFileDesc *prfd = PR_CreateSocketPollFd(fd); 285 if (NULL == prfd) { 286 elog(errh, __FILE__, __LINE__, "PR_CreateSocketPollFd()"); 287 return NULL; 288 } 289 /*PR_ChangeFileDescNativeHandle(prfd, fd);*/ 290 prfd->methods = PR_GetTCPMethods(); 291 /*prfd->dtor = PR_FreeFileDesc();*/ /* PR_FreeFileDesc() is private */ 292 #endif 293 294 /* set prfd->secret->nonblocking flag */ 295 PRSocketOptionData data; 296 data.option = PR_SockOpt_Nonblocking; 297 data.value.non_blocking = PR_TRUE; 298 if (PR_SetSocketOption(prfd, &data) != PR_SUCCESS) { 299 elog(errh, __FILE__, __LINE__, "PR_SocketSetSocketOption()"); 300 PR_DestroySocketPollFd(prfd); /* PR_FreeFileDesc() is private */ 301 return NULL; 302 } 303 304 PRFileDesc *ssl = SSL_ImportFD(model, prfd); 305 if (NULL == ssl) { 306 elog(errh, __FILE__, __LINE__, "SSL_ImportFD()"); 307 PR_DestroySocketPollFd(prfd); /* PR_FreeFileDesc() is private */ 308 return NULL; 309 } 310 311 return ssl; 312 } 313 314 315 static void 316 mod_nss_io_detach (PRFileDesc *ssl) 317 { 318 #if 0 /* PR_PopIOLayer() forbids pop of PR_NSPR_IO_LAYER */ 319 PRFileDesc *prfd = PR_PopIOLayer(ssl, PR_NSPR_IO_LAYER); 320 if (prfd) { 321 PR_ChangeFileDescNativeHandle(prfd, -1); 322 PR_DestroySocketPollFd(prfd); /* PR_FreeFileDesc() is private */ 323 } 324 #else 325 /*(results in close(-1) and EBADF from PR_Close() in mod_nss_io_dtor())*/ 326 PRFileDesc *prfd = PR_GetIdentitiesLayer(ssl, PR_NSPR_IO_LAYER); 327 if (prfd) 328 PR_ChangeFileDescNativeHandle(prfd, -1); 329 #endif 330 } 331 332 333 static void 334 mod_nss_io_dtor (PRFileDesc *ssl) 335 { 336 if (NULL == ssl) return; 337 mod_nss_io_detach(ssl); 338 PR_Close(ssl); 339 } 340 341 342 static int 343 mod_nss_load_file (const char * const fn, SECItem * const d, log_error_st *errh) 344 { 345 off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/ 346 char *data = fdevent_load_file(fn, &dlen, errh, PORT_Alloc, PORT_Free); 347 if (NULL == data) return -1; 348 d->type = siBuffer; 349 d->data = (unsigned char *)data; 350 d->len = (unsigned int)dlen; 351 return 0; 352 } 353 354 355 static void 356 mod_nss_secitem_wipe (SECItem * const d) 357 { 358 /* safer than SECITEM_ZfreeItem() */ 359 if (NULL == d) return; 360 if (d->data) { 361 if (d->len) safe_memclear(d->data, d->len); /*safer than PORT_Memset()*/ 362 PORT_Free(d->data); /* safe_memclear() is safer than PORT_ZFree() */ 363 d->data = NULL; 364 } 365 d->len = 0; 366 } 367 368 369 INIT_FUNC(mod_nss_init) 370 { 371 plugin_data_singleton = (plugin_data *)calloc(1, sizeof(plugin_data)); 372 return plugin_data_singleton; 373 } 374 375 376 static int mod_nss_init_once_nss (void) 377 { 378 if (ssl_is_init) return 1; 379 ssl_is_init = 1; 380 381 /*PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);*//*implicit on first use*/ 382 383 if (!NSS_IsInitialized() && NSS_NoDB_Init(NULL) < 0) 384 return 0; 385 386 if (SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE) < 0) 387 return 0; 388 if (SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_FALSE) < 0) 389 return 0; 390 /* XXX: lighttpd is single threaded and so SSL_NO_LOCKS is desirable, 391 * but NSS crashes if SSL_NO_LOCKS option is set to PR_TRUE. 392 * (Crash in SSL3_SendAlert() call to PR_GetMonitorEntryCount() 393 * with NULL ptr to monitor (mon)) 394 * NSS lib/ssl/sslimpl.h macros such as ssl_HaveSSL3HandshakeLock(ss), 395 * plus some other .c files use macros without first checking if 396 * (!ss->opt.noLocks): PZ_InMonitor() PZ_InMonitor() PZ_InMonitor() */ 397 /*if (SSL_OptionSetDefault(SSL_NO_LOCKS, PR_TRUE) < 0)*/ 398 if (SSL_OptionSetDefault(SSL_NO_LOCKS, PR_FALSE) < 0) 399 return 0; 400 if (SSL_OptionSetDefault(SSL_NO_CACHE, PR_TRUE) < 0) 401 return 0; 402 if (SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, PR_TRUE) < 0) 403 return 0; 404 if (SSL_OptionSetDefault(SSL_ENABLE_ALPN, PR_TRUE) < 0) 405 return 0; 406 if (SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION, 407 SSL_RENEGOTIATE_NEVER) < 0) 408 return 0; 409 410 if (NSS_SetDomesticPolicy() < 0) 411 return 0; 412 413 local_send_buffer = malloc(LOCAL_SEND_BUFSIZE); 414 force_assert(NULL != local_send_buffer); 415 416 return 1; 417 } 418 419 420 static void mod_nss_free_nss (void) 421 { 422 if (!ssl_is_init) return; 423 424 NSS_Shutdown(); 425 426 free(local_send_buffer); 427 ssl_is_init = 0; 428 } 429 430 431 #define PEM_BEGIN "-----BEGIN " 432 #define PEM_END "-----END " 433 #define PEM_BEGIN_CERT "-----BEGIN CERTIFICATE-----" 434 #define PEM_END_CERT "-----END CERTIFICATE-----" 435 #define PEM_BEGIN_TRUSTED_CERT "-----BEGIN TRUSTED CERTIFICATE-----" 436 #define PEM_END_TRUSTED_CERT "-----END TRUSTED CERTIFICATE-----" 437 #define PEM_BEGIN_PKEY "-----BEGIN PRIVATE KEY-----" 438 #define PEM_END_PKEY "-----END PRIVATE KEY-----" 439 #define PEM_BEGIN_EC_PKEY "-----BEGIN EC PRIVATE KEY-----" 440 #define PEM_END_EC_PKEY "-----END EC PRIVATE KEY-----" 441 #define PEM_BEGIN_RSA_PKEY "-----BEGIN RSA PRIVATE KEY-----" 442 #define PEM_END_RSA_PKEY "-----END RSA PRIVATE KEY-----" 443 #define PEM_BEGIN_DSA_PKEY "-----BEGIN DSA PRIVATE KEY-----" 444 #define PEM_END_DSA_PKEY "-----END DSA PRIVATE KEY-----" 445 #define PEM_BEGIN_ANY_PKEY "-----BEGIN ANY PRIVATE KEY-----" 446 #define PEM_END_ANY_PKEY "-----END ANY PRIVATE KEY-----" 447 /* (not implemented: support to get password from user for encrypted key) */ 448 #define PEM_BEGIN_ENCRYPTED_PKEY "-----BEGIN ENCRYPTED PRIVATE KEY-----" 449 #define PEM_END_ENCRYPTED_PKEY "-----END ENCRYPTED PRIVATE KEY-----" 450 451 #define PEM_BEGIN_X509_CRL "-----BEGIN X509 CRL-----" 452 #define PEM_END_X509_CRL "-----END X509 CRL-----" 453 454 455 static CERTCertificateList * 456 mod_nss_load_pem_file (const char *fn, log_error_st *errh) 457 { 458 if (!mod_nss_init_once_nss()) return NULL; 459 460 SECItem f; 461 int rc = mod_nss_load_file(fn, &f, errh); 462 if (rc < 0) return NULL; 463 464 rc = -1; 465 CERTCertificateList *chain = NULL; 466 do { 467 int count = 0; 468 char *b = (char *)f.data; 469 for (; (b = strstr(b, PEM_BEGIN_CERT)); b += sizeof(PEM_BEGIN_CERT)-1) 470 ++count; 471 b = (char *)f.data; 472 for (; (b = strstr(b, PEM_BEGIN_TRUSTED_CERT)); 473 b += sizeof(PEM_BEGIN_TRUSTED_CERT)-1) 474 ++count; 475 if (0 == count) { 476 rc = 0; 477 break; 478 } 479 480 PLArenaPool *arena = PORT_NewArena(4096); 481 if (NULL == arena) 482 break; 483 484 chain = (CERTCertificateList *) 485 PORT_ArenaAlloc(arena, sizeof(CERTCertificateList)); 486 if (NULL == chain) { 487 PORT_FreeArena(arena, PR_FALSE); 488 break; 489 } 490 491 chain->arena = arena; 492 chain->len = count; 493 chain->certs = (SECItem *)PORT_ArenaAlloc(arena, count*sizeof(SECItem)); 494 if (NULL == chain->certs) 495 break; 496 497 int i = 0; 498 for (char *e = (char *)f.data; (b = strstr(e, PEM_BEGIN_CERT)); ++i) { 499 b += sizeof(PEM_BEGIN_CERT)-1; 500 if (*b == '\r') ++b; 501 if (*b == '\n') ++b; 502 e = strstr(b, PEM_END_CERT); 503 if (NULL == e) break; 504 uint32_t len = (uint32_t)(e - b); 505 e += sizeof(PEM_END_CERT)-1; 506 chain->certs[i].type = 0; 507 chain->certs[i].data = NULL; 508 chain->certs[i].len = 0; 509 if (NULL == NSSBase64_DecodeBuffer(arena, chain->certs+i, b, len)) 510 break; 511 } 512 for (char *e=(char *)f.data; (b=strstr(e,PEM_BEGIN_TRUSTED_CERT)); ++i){ 513 b += sizeof(PEM_BEGIN_TRUSTED_CERT)-1; 514 if (*b == '\r') ++b; 515 if (*b == '\n') ++b; 516 e = strstr(b, PEM_END_TRUSTED_CERT); 517 if (NULL == e) break; 518 uint32_t len = (uint32_t)(e - b); 519 e += sizeof(PEM_END_TRUSTED_CERT)-1; 520 chain->certs[i].type = 0; 521 chain->certs[i].data = NULL; 522 chain->certs[i].len = 0; 523 if (NULL == NSSBase64_DecodeBuffer(arena, chain->certs+i, b, len)) 524 break; 525 } 526 if (i == count) 527 rc = 0; 528 else 529 PORT_SetError(SEC_ERROR_IO); 530 } while (0); 531 532 mod_nss_secitem_wipe(&f); 533 534 if (rc < 0) { 535 elogf(errh, __FILE__, __LINE__, "error loading %s", fn); 536 if (chain) 537 CERT_DestroyCertificateList(chain); 538 return NULL; 539 } 540 541 return chain; 542 } 543 544 545 static CERTCertificate * 546 mod_nss_load_pem_crts (const char *fn, log_error_st *errh, CERTCertificateList **pchain) 547 { 548 *pchain = mod_nss_load_pem_file(fn, errh); 549 if (NULL == *pchain) return NULL; 550 551 CERTCertificate *cert = CERT_NewTempCertificate(NULL, (*pchain)->certs+0, 552 NULL, PR_FALSE, PR_TRUE); 553 if (NULL == cert) { 554 CERT_DestroyCertificateList(*pchain); 555 *pchain = NULL; 556 } 557 return cert; 558 } 559 560 static CERTCertList * 561 mod_nss_cert_list (CERTCertificateList *crts) 562 { 563 SECStatus rc = SECFailure; 564 CERTCertificate *cert = NULL; 565 CERTCertList *clist = CERT_NewCertList(); 566 if (NULL != clist) { 567 for (int i = 0; i < crts->len; ++i) { 568 cert = CERT_NewTempCertificate(NULL, crts->certs+i, 569 NULL, PR_FALSE, PR_TRUE); 570 if (NULL == cert) break; 571 rc = CERT_AddCertToListTail(clist, cert); 572 if (rc < 0) break; 573 } 574 } 575 576 if (rc < 0 || NULL == cert) { 577 if (cert) CERT_DestroyCertificate(cert); 578 if (clist) CERT_DestroyCertList(clist); 579 PORT_SetError(SEC_ERROR_NO_MEMORY); 580 return NULL; 581 } 582 583 return clist; 584 } 585 586 587 static CERTCertList * 588 mod_nss_load_config_crts (const char *fn, log_error_st *errh) 589 { 590 CERTCertificateList *crts = mod_nss_load_pem_file(fn, errh); 591 if (NULL == crts) return NULL; 592 593 CERTCertList *clist = NULL; 594 SECStatus rc = 595 CERT_ImportCAChainTrusted(crts->certs,crts->len,certUsageUserCertImport); 596 if (rc == SECSuccess) 597 clist = mod_nss_cert_list(crts); 598 else { 599 elogf(errh, __FILE__, __LINE__, "CERT_ImportCAChainTrusted() %s", fn); 600 CERT_DestroyCertificateList(crts); 601 return NULL; 602 } 603 604 CERT_DestroyCertificateList(crts); 605 return clist; 606 } 607 608 609 static CERTCertList * 610 mod_nss_load_config_dncrts (const char *fn, log_error_st *errh) 611 { 612 CERTCertificateList *crts = mod_nss_load_pem_file(fn, errh); 613 if (NULL == crts) return NULL; 614 615 CERTCertList *clist = mod_nss_cert_list(crts); 616 617 CERT_DestroyCertificateList(crts); 618 return clist; 619 } 620 621 622 static void 623 mod_nss_free_config_crls (CERTCertificateList *crls) 624 { 625 if (NULL == crls) return; 626 CERTCertDBHandle * const dbhandle = CERT_GetDefaultCertDB(); 627 for (int i = 0; i < crls->len; ++i) 628 CERT_UncacheCRL(dbhandle, crls->certs+i); 629 CERT_DestroyCertificateList(crls); 630 } 631 632 633 static CERTCertificateList * 634 mod_nss_load_config_crls (const char *fn, log_error_st *errh) 635 { 636 /*(similar start to other mod_nss_load_config_*())*/ 637 if (!mod_nss_init_once_nss()) return NULL; 638 639 SECItem f; 640 int rc = mod_nss_load_file(fn, &f, errh); 641 if (rc < 0) return NULL; 642 643 rc = -1; 644 CERTCertificateList *chain = NULL; 645 CERTCertDBHandle * const dbhandle = CERT_GetDefaultCertDB(); 646 do { 647 int count = 0; 648 char *b = (char *)f.data; 649 for (; (b = strstr(b, PEM_BEGIN_X509_CRL)); 650 b += sizeof(PEM_BEGIN_X509_CRL)-1) 651 ++count; 652 if (0 == count) { 653 rc = 0; 654 break; 655 } 656 657 PLArenaPool *arena = PORT_NewArena(4096); 658 if (NULL == arena) 659 break; 660 661 chain = (CERTCertificateList *) 662 PORT_ArenaAlloc(arena, sizeof(CERTCertificateList)); 663 if (NULL == chain) { 664 PORT_FreeArena(arena, PR_FALSE); 665 break; 666 } 667 668 chain->arena = arena; 669 chain->len = count; 670 chain->certs = (SECItem *)PORT_ArenaAlloc(arena, count*sizeof(SECItem)); 671 if (NULL == chain->certs) 672 break; 673 674 int i = 0; 675 for (char *e = (char *)f.data; (b = strstr(e,PEM_BEGIN_X509_CRL)); ++i){ 676 b += sizeof(PEM_BEGIN_X509_CRL)-1; 677 if (*b == '\r') ++b; 678 if (*b == '\n') ++b; 679 e = strstr(b, PEM_END_X509_CRL); 680 if (NULL == e) break; 681 uint32_t len = (uint32_t)(e - b); 682 e += sizeof(PEM_END_X509_CRL)-1; 683 chain->certs[i].type = 0; 684 chain->certs[i].data = NULL; 685 chain->certs[i].len = 0; 686 if (NULL == NSSBase64_DecodeBuffer(arena, chain->certs+i, b, len)) 687 break; 688 /* using ephemeral db, so cache CRL instead of CERT_ImportCRL() */ 689 if (CERT_CacheCRL(dbhandle, chain->certs+i) < 0) 690 break; 691 } 692 if (i == count) 693 rc = 0; 694 else 695 PORT_SetError(SEC_ERROR_IO); 696 } while (0); 697 698 mod_nss_secitem_wipe(&f); 699 700 if (rc < 0) { 701 elogf(errh, __FILE__, __LINE__, "error loading %s", fn); 702 if (chain) 703 CERT_DestroyCertificateList(chain); 704 return NULL; 705 } 706 707 return chain; 708 } 709 710 711 static SECItem * 712 mod_nss_cert_get_publicValue (SECKEYPublicKey *pubKey) 713 { 714 /*(lib/pkcs12/p12d.c:sec_pkcs12_get_public_value_and_type() private)*/ 715 /*(lib/pk11wrap/pk11akey.c:pk11_MakeIDFromPublicKey() private, hashes)*/ 716 /*(lib/crmf/crmfcont.c:crmf_get_public_value() public but incomplete)*/ 717 switch (pubKey->keyType) { 718 case dsaKey: return &pubKey->u.dsa.publicValue; 719 case dhKey: return &pubKey->u.dh.publicValue; 720 case rsaKey: return &pubKey->u.rsa.modulus; 721 case ecKey: return &pubKey->u.ec.publicValue; 722 default: return NULL; 723 } 724 } 725 726 727 static SECKEYPrivateKey * 728 mod_nss_load_config_pkey (const char *fn, CERTCertificate *cert, log_error_st *errh) 729 { 730 /* NSS does not provide convenient mechanisms to read PEM or DER private key 731 * instead expecting PKCS12-format, which is not the convention used by many 732 * other TLS modules */ 733 734 /*(similar start to other mod_nss_load_config_*())*/ 735 if (!mod_nss_init_once_nss()) return NULL; 736 737 SECItem f; 738 int rc = mod_nss_load_file(fn, &f, errh); 739 if (rc < 0) return NULL; 740 741 SECItem der = { 0, NULL, 0 }; 742 PK11SlotInfo *slot = NULL; 743 SECKEYPrivateKey *pkey = NULL; 744 SECStatus src = SECFailure; 745 do { 746 /*(expecting single private key in file, so first match)*/ 747 char *b, *e; 748 if ((b = strstr((char *)f.data, PEM_BEGIN_PKEY)) 749 && (e = strstr(b, PEM_END_PKEY))) 750 b += sizeof(PEM_BEGIN_PKEY)-1; 751 else if ((b = strstr((char *)f.data, PEM_BEGIN_EC_PKEY)) 752 && (e = strstr(b, PEM_END_EC_PKEY))) 753 b += sizeof(PEM_BEGIN_EC_PKEY)-1; 754 else if ((b = strstr((char *)f.data, PEM_BEGIN_RSA_PKEY)) 755 && (e = strstr(b, PEM_END_RSA_PKEY))) 756 b += sizeof(PEM_BEGIN_RSA_PKEY)-1; 757 else if ((b = strstr((char *)f.data, PEM_BEGIN_DSA_PKEY)) 758 && (e = strstr(b, PEM_END_DSA_PKEY))) 759 b += sizeof(PEM_BEGIN_DSA_PKEY)-1; 760 else if ((b = strstr((char *)f.data, PEM_BEGIN_ANY_PKEY)) 761 && (e = strstr(b, PEM_END_ANY_PKEY))) 762 b += sizeof(PEM_BEGIN_ANY_PKEY)-1; 763 else 764 break; 765 if (*b == '\r') ++b; 766 if (*b == '\n') ++b; 767 768 if (NULL == NSSBase64_DecodeBuffer(NULL, &der, b, (uint32_t)(e - b))) 769 break; 770 771 slot = PK11_GetInternalKeySlot(); 772 if (NULL == slot) break; 773 774 SECItem nickname = { 0, NULL, strlen(fn) }; 775 *(const unsigned char **)&nickname.data = (unsigned char *)fn; 776 unsigned int keyUsage = KU_ALL; /* XXX: limit to fewer flags? */ 777 PRBool isPerm = PR_FALSE; 778 PRBool isPrivate = PR_TRUE; 779 SECKEYPublicKey *pubKey = CERT_ExtractPublicKey(cert); 780 SECItem *pubValue = mod_nss_cert_get_publicValue(pubKey); 781 src = 782 PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, &der, &nickname, 783 pubValue, isPerm, isPrivate, 784 keyUsage, &pkey, NULL); 785 /* nickname attribute has reference taken to data; 786 * data must persist longer than SECKEYPrivateKey */ 787 /* (pubValue data is of decoded type SEC_ASN1_INTEGER and is copied) */ 788 SECKEY_DestroyPublicKey(pubKey); 789 } while (0); 790 791 if (slot) PK11_FreeSlot(slot); 792 if (der.data) { 793 mod_nss_secitem_wipe(&der); 794 PORT_Free(der.data); 795 } 796 mod_nss_secitem_wipe(&f); 797 798 if (src < 0) { 799 elogf(errh, __FILE__, __LINE__, 800 "PK11_ImportDERPrivateKeyInfoAndReturnKey() %s", fn); 801 return NULL; 802 } 803 804 return pkey; 805 } 806 807 808 static void 809 mod_nss_free_config (server *srv, plugin_data * const p) 810 { 811 if (NULL != p->ssl_ctxs) { 812 PRFileDesc *global_model = p->ssl_ctxs->model; 813 /* free from $SERVER["socket"] (if not copy of global scope) */ 814 for (uint32_t i = 1; i < srv->config_context->used; ++i) { 815 plugin_ssl_ctx * const s = p->ssl_ctxs + i; 816 if (s->model && s->model != global_model) 817 PR_Close(s->model); 818 } 819 /* free from global scope */ 820 if (global_model) 821 PR_Close(global_model); 822 free(p->ssl_ctxs); 823 } 824 825 if (NULL == p->cvlist) return; 826 /* (init i to 0 if global context; to 1 to skip empty global context) */ 827 for (int i = !p->cvlist[0].v.u2[1], used = p->nconfig; i < used; ++i) { 828 config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0]; 829 for (; -1 != cpv->k_id; ++cpv) { 830 switch (cpv->k_id) { 831 case 0: /* ssl.pemfile */ 832 if (cpv->vtype == T_CONFIG_LOCAL) { 833 plugin_cert *pc = cpv->v.v; 834 CERT_DestroyCertificate(pc->ssl_pemfile_x509); 835 SECKEY_DestroyPrivateKey(pc->ssl_pemfile_pkey); 836 CERTCertificateList *certChain; 837 *(const CERTCertificateList **)&certChain = 838 pc->ssl_credex.certChain; 839 CERT_DestroyCertificateList(certChain); 840 PORT_Free(pc->OCSPResponse.data); 841 //CERT_Destroy...(pc->ssl_credex.signedCertTimestamps); 842 //CERT_Destroy...(pc->ssl_credex.delegCred); 843 //CERT_Destroy...(pc->ssl_credex.delegCredPrivKey); 844 free(pc); 845 } 846 break; 847 case 2: /* ssl.ca-file */ 848 case 3: /* ssl.ca-dn-file */ 849 if (cpv->vtype == T_CONFIG_LOCAL) 850 CERT_DestroyCertList(cpv->v.v); 851 break; 852 case 4: /* ssl.ca-crl-file */ 853 if (cpv->vtype == T_CONFIG_LOCAL) 854 mod_nss_free_config_crls(cpv->v.v); 855 break; 856 default: 857 break; 858 } 859 } 860 } 861 } 862 863 864 FREE_FUNC(mod_nss_free) 865 { 866 plugin_data *p = p_d; 867 if (NULL == p->srv) return; 868 mod_nss_free_config(p->srv, p); 869 mod_nss_free_nss(); 870 } 871 872 873 static void 874 mod_nss_merge_config_cpv (plugin_config * const pconf, const config_plugin_value_t * const cpv) 875 { 876 switch (cpv->k_id) { /* index into static config_plugin_keys_t cpk[] */ 877 case 0: /* ssl.pemfile */ 878 if (cpv->vtype == T_CONFIG_LOCAL) 879 pconf->pc = cpv->v.v; 880 break; 881 case 1: /* ssl.privkey */ 882 break; 883 case 2: /* ssl.ca-file */ 884 if (cpv->vtype == T_CONFIG_LOCAL) 885 pconf->ssl_ca_file = cpv->v.v; 886 break; 887 case 3: /* ssl.ca-dn-file */ 888 if (cpv->vtype == T_CONFIG_LOCAL) 889 pconf->ssl_ca_dn_file = cpv->v.v; 890 break; 891 case 4: /* ssl.ca-crl-file */ 892 break; 893 case 5: /* ssl.read-ahead */ 894 pconf->ssl_read_ahead = (0 != cpv->v.u); 895 break; 896 case 6: /* ssl.disable-client-renegotiation */ 897 pconf->ssl_disable_client_renegotiation = (0 != cpv->v.u); 898 break; 899 case 7: /* ssl.verifyclient.activate */ 900 pconf->ssl_verifyclient = (0 != cpv->v.u); 901 break; 902 case 8: /* ssl.verifyclient.enforce */ 903 pconf->ssl_verifyclient_enforce = (0 != cpv->v.u); 904 break; 905 case 9: /* ssl.verifyclient.depth */ 906 pconf->ssl_verifyclient_depth = (unsigned char)cpv->v.shrt; 907 break; 908 case 10:/* ssl.verifyclient.username */ 909 pconf->ssl_verifyclient_username = cpv->v.b; 910 break; 911 case 11:/* ssl.verifyclient.exportcert */ 912 pconf->ssl_verifyclient_export_cert = (0 != cpv->v.u); 913 break; 914 case 12:/* ssl.acme-tls-1 */ 915 pconf->ssl_acme_tls_1 = cpv->v.b; 916 break; 917 case 13:/* ssl.stapling-file */ 918 break; 919 case 14:/* debug.log-ssl-noise */ 920 pconf->ssl_log_noise = (unsigned char)cpv->v.shrt; 921 break; 922 #if 0 /*(cpk->k_id remapped in mod_nss_set_defaults())*/ 923 case 15:/* ssl.verifyclient.ca-file */ 924 case 16:/* ssl.verifyclient.ca-dn-file */ 925 case 17:/* ssl.verifyclient.ca-crl-file */ 926 break; 927 #endif 928 default:/* should not happen */ 929 return; 930 } 931 } 932 933 934 static void 935 mod_nss_merge_config(plugin_config * const pconf, const config_plugin_value_t *cpv) 936 { 937 do { 938 mod_nss_merge_config_cpv(pconf, cpv); 939 } while ((++cpv)->k_id != -1); 940 } 941 942 943 static void 944 mod_nss_patch_config (request_st * const r, plugin_config * const pconf) 945 { 946 plugin_data * const p = plugin_data_singleton; 947 memcpy(pconf, &p->defaults, sizeof(plugin_config)); 948 for (int i = 1, used = p->nconfig; i < used; ++i) { 949 if (config_check_cond(r, (uint32_t)p->cvlist[i].k_id)) 950 mod_nss_merge_config(pconf, p->cvlist + p->cvlist[i].v.u2[0]); 951 } 952 } 953 954 955 static SECStatus 956 mod_nss_verify_cb (void *arg, PRFileDesc *ssl, PRBool checkSig, PRBool isServer) 957 { 958 handler_ctx * const hctx = arg; 959 if (!hctx->conf.ssl_verifyclient) return SECSuccess; 960 961 /* Notes 962 * trusted CAs in ssl.ca-file were loaded into default cert db at startup 963 * OCSP checking (querying OCSP Responder) is disabled by default 964 * CERT_EnableOCSPChecking() 965 * CERT_DisableOCSPChecking() 966 * cert_VerifyCertWithFlags() is not public, 967 * so unable to use CERT_VERIFYCERT_SKIP_OCSP 968 * hctx->verify_status is set here; not setting SSL_BadCertHook() 969 * XXX: not implemented (yet) here: hctx->conf.ssl_verifyclient_depth) 970 */ 971 972 CERTCertificate *peer = NULL; 973 974 #if 0 975 peer = SSL_PeerCertificate(ssl); 976 if (NULL == peer) 977 return (PORT_GetError() == SSL_ERROR_NO_CERTIFICATE) 978 ? SECSuccess 979 : SECFailure; 980 981 if (CERT_VerifyCert(CERT_GetDefaultCertDB(), peer, PR_TRUE, 982 certUsageSSLClient, (PRInt64)log_epoch_secs * 1000000, 983 SSL_RevealPinArg(ssl), NULL) < 0) 984 #else 985 if (SSL_AuthCertificate((void *)CERT_GetDefaultCertDB(), 986 ssl, checkSig, isServer) < 0) 987 #endif 988 { 989 hctx->verify_status = PORT_GetError(); 990 if (0 == hctx->verify_status) 991 hctx->verify_status = SEC_ERROR_UNTRUSTED_CERT; 992 } 993 994 if (hctx->verify_status == 0 && hctx->conf.ssl_ca_dn_file) { 995 /* verify that client cert is issued by CA in ssl.ca-dn-file 996 * if both ssl.ca-dn-file and ssl.ca-file were configured */ 997 if (NULL == peer) peer = SSL_PeerCertificate(ssl); 998 if (peer) { 999 CERTCertList * const certList = hctx->conf.ssl_ca_dn_file; 1000 SECItem * const derIssuer = &peer->derIssuer; 1001 CERTCertListNode *node = CERT_LIST_HEAD(certList); 1002 for (; !CERT_LIST_END(node, certList); node = CERT_LIST_NEXT(node)){ 1003 SECItem * const derSubject = &node->cert->derSubject; 1004 if (SECITEM_CompareItem(derIssuer, derSubject) == SECEqual) 1005 break; 1006 } 1007 if (CERT_LIST_END(node, certList)) 1008 hctx->verify_status = SEC_ERROR_UNTRUSTED_CERT; 1009 } 1010 } 1011 1012 if (peer) CERT_DestroyCertificate(peer); 1013 1014 if (hctx->verify_status != 0 && hctx->conf.ssl_verifyclient_enforce) { 1015 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); 1016 return SECFailure; 1017 } 1018 1019 return SECSuccess; 1020 } 1021 1022 1023 __attribute_cold__ 1024 static void 1025 mod_nss_expire_stapling_file (server *srv, plugin_cert *pc) 1026 { 1027 /* discard expired OCSP stapling response */ 1028 pc->ssl_credex.stapledOCSPResponses = NULL; 1029 if (pc->must_staple) 1030 log_error(srv->errh, __FILE__, __LINE__, 1031 "certificate marked OCSP Must-Staple, " 1032 "but OCSP response expired from ssl.stapling-file %s", 1033 pc->ssl_stapling_file->ptr); 1034 } 1035 1036 1037 static int 1038 mod_nss_reload_stapling_file (server *srv, plugin_cert *pc, const time_t cur_ts) 1039 { 1040 SECItem f; 1041 int rc = mod_nss_load_file(pc->ssl_stapling_file->ptr, &f, srv->errh); 1042 if (rc < 0) return rc; 1043 1044 /* NSS has the ability to include multiple OCSP responses for 1045 * certificate chain as allowed in TLSv1.3, but that is not utilized here. 1046 * If implemented, it will probably operate on a new directive, 1047 * e.g. ssl.stapling-pemfile 1048 */ 1049 1050 /* Note that the credentials structure should be read-only when in 1051 * use, thus when reloading, either the credentials structure must not 1052 * be in use by any sessions, or a new credentials structure should be 1053 * allocated for new sessions. 1054 * XXX: lighttpd is not threaded, so this is probably not an issue (?) 1055 */ 1056 1057 PORT_Free(pc->OCSPResponse.data); 1058 pc->OCSPResponse.data = f.data; 1059 pc->OCSPResponse.len = f.len; 1060 pc->OCSPResponses.items = &pc->OCSPResponse; 1061 pc->OCSPResponses.len = 1; 1062 pc->ssl_credex.stapledOCSPResponses = &pc->OCSPResponses; 1063 1064 /* NSS does not expose CERTOCSPSingleResponse member nextUpdate 1065 * to allow getting (PRTime) of nextUpdate from the OCSP response. 1066 * (PRTime is (PRInt64) of microseconds since epoch) 1067 * e.g. DER_GeneralizedTimeToTime(&nextUpdate, single->nextUpdate); 1068 * XXX: *not* implementing our own ASN.1 DER decoder for OCSP response 1069 * ssl.stapling-file will be reloaded hourly 1070 */ 1071 time_t nextupd = (time_t)-1; 1072 1073 pc->ssl_stapling_loadts = cur_ts; 1074 pc->ssl_stapling_nextts = nextupd; 1075 if (pc->ssl_stapling_nextts == (time_t)-1) { 1076 /* "Next Update" might not be provided by OCSP responder 1077 * Use 3600 sec (1 hour) in that case. */ 1078 /* retry in 1 hour if unable to determine Next Update */ 1079 pc->ssl_stapling_nextts = cur_ts + 3600; 1080 pc->ssl_stapling_loadts = 0; 1081 } 1082 else if (pc->ssl_stapling_nextts < cur_ts) 1083 mod_nss_expire_stapling_file(srv, pc); 1084 1085 return 0; 1086 } 1087 1088 1089 static int 1090 mod_nss_refresh_stapling_file (server *srv, plugin_cert *pc, const time_t cur_ts) 1091 { 1092 if (pc->ssl_stapling_nextts > cur_ts + 256) 1093 return 0; /* skip check for refresh unless close to expire */ 1094 struct stat st; 1095 if (0 != stat(pc->ssl_stapling_file->ptr, &st) 1096 || st.st_mtime <= pc->ssl_stapling_loadts) { 1097 if (pc->ssl_stapling_nextts < cur_ts) 1098 mod_nss_expire_stapling_file(srv, pc); 1099 return 0; 1100 } 1101 return mod_nss_reload_stapling_file(srv, pc, cur_ts); 1102 } 1103 1104 1105 static void 1106 mod_nss_refresh_stapling_files (server *srv, const plugin_data *p, const time_t cur_ts) 1107 { 1108 /* future: might construct array of (plugin_cert *) at startup 1109 * to avoid the need to search for them here */ 1110 /* (init i to 0 if global context; to 1 to skip empty global context) */ 1111 if (NULL == p->cvlist) return; 1112 for (int i = !p->cvlist[0].v.u2[1], used = p->nconfig; i < used; ++i) { 1113 const config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0]; 1114 for (; cpv->k_id != -1; ++cpv) { 1115 if (cpv->k_id != 0) continue; /* k_id == 0 for ssl.pemfile */ 1116 if (cpv->vtype != T_CONFIG_LOCAL) continue; 1117 plugin_cert *pc = cpv->v.v; 1118 if (!buffer_string_is_empty(pc->ssl_stapling_file)) 1119 mod_nss_refresh_stapling_file(srv, pc, cur_ts); 1120 } 1121 } 1122 } 1123 1124 1125 static int 1126 mod_nss_crt_must_staple (CERTCertificate *crt) 1127 { 1128 /* Look for TLS features X.509 extension with value 5 1129 * RFC 7633 https://tools.ietf.org/html/rfc7633#appendix-A 1130 * 5 = OCSP Must-Staple (security mechanism) 1131 * 1132 * id-pe-tlsfeature 1.3.6.1.5.5.7.1.24 1133 * 1.3.6.1.5.5.7.1.24 = DER:30:03:02:01:05 1134 */ 1135 1136 int rc; 1137 1138 /* XXX: not implemented */ 1139 UNUSED(crt); 1140 rc = 0; 1141 1142 return rc; /* 1 if OCSP Must-Staple found; 0 if not */ 1143 } 1144 1145 1146 static void * 1147 network_nss_load_pemfile (server *srv, const buffer *pemfile, const buffer *privkey, const buffer *ssl_stapling_file) 1148 { 1149 CERTCertificateList *ssl_pemfile_chain; 1150 CERTCertificate *ssl_pemfile_x509 = 1151 mod_nss_load_pem_crts(pemfile->ptr, srv->errh, &ssl_pemfile_chain); 1152 if (NULL == ssl_pemfile_x509) 1153 return NULL; 1154 1155 SECKEYPrivateKey *pkey = 1156 mod_nss_load_config_pkey(privkey->ptr, ssl_pemfile_x509, srv->errh); 1157 if (NULL == pkey) { 1158 CERT_DestroyCertificate(ssl_pemfile_x509); 1159 if (ssl_pemfile_chain) CERT_DestroyCertificateList(ssl_pemfile_chain); 1160 return NULL; 1161 } 1162 1163 if (NULL == ssl_pemfile_chain) 1164 ssl_pemfile_chain = CERT_CertChainFromCert(ssl_pemfile_x509, 1165 certUsageSSLServer, 1166 PR_FALSE); 1167 1168 plugin_cert *pc = calloc(1, sizeof(plugin_cert)); 1169 force_assert(pc); 1170 pc->ssl_pemfile_pkey = pkey; 1171 pc->ssl_pemfile_x509 = ssl_pemfile_x509; 1172 pc->ssl_credex.certChain = ssl_pemfile_chain; 1173 pc->ssl_stapling_file= ssl_stapling_file; 1174 pc->ssl_stapling_loadts = 0; 1175 pc->ssl_stapling_nextts = 0; 1176 pc->OCSPResponse.type = 0; 1177 pc->OCSPResponse.data = NULL; 1178 pc->OCSPResponse.len = 0; 1179 pc->OCSPResponses.items = NULL; 1180 pc->OCSPResponses.len = 0; 1181 pc->must_staple = mod_nss_crt_must_staple(ssl_pemfile_x509); 1182 1183 if (!buffer_string_is_empty(pc->ssl_stapling_file)) { 1184 if (mod_nss_reload_stapling_file(srv, pc, log_epoch_secs) < 0) { 1185 /* continue without OCSP response if there is an error */ 1186 } 1187 } 1188 else if (pc->must_staple) { 1189 log_error(srv->errh, __FILE__, __LINE__, 1190 "certificate %s marked OCSP Must-Staple, " 1191 "but ssl.stapling-file not provided", pemfile->ptr); 1192 } 1193 1194 return pc; 1195 } 1196 1197 1198 static int 1199 mod_nss_acme_tls_1 (handler_ctx *hctx) 1200 { 1201 buffer * const b = hctx->tmp_buf; 1202 const buffer * const name = &hctx->r->uri.authority; 1203 log_error_st * const errh = hctx->r->conf.errh; 1204 1205 /* check if acme-tls/1 protocol is enabled (path to dir of cert(s) is set)*/ 1206 if (buffer_string_is_empty(hctx->conf.ssl_acme_tls_1)) 1207 return SECFailure; /*(should not happen)*/ 1208 1209 /* check if SNI set server name (required for acme-tls/1 protocol) 1210 * and perform simple path checks for no '/' 1211 * and no leading '.' (e.g. ignore "." or ".." or anything beginning '.') */ 1212 if (buffer_string_is_empty(name)) return SECFailure; 1213 if (NULL != strchr(name->ptr, '/')) return SECFailure; 1214 if (name->ptr[0] == '.') return SECFailure; 1215 #if 0 1216 if (0 != http_request_host_policy(name, hctx->r->conf.http_parseopts, 443)) 1217 return SECFailure; 1218 #endif 1219 buffer_copy_path_len2(b, CONST_BUF_LEN(hctx->conf.ssl_acme_tls_1), 1220 CONST_BUF_LEN(name)); 1221 1222 /* cert and key load is similar to network_nss_load_pemfile() */ 1223 1224 uint32_t len = buffer_string_length(b); 1225 buffer_append_string_len(b, CONST_STR_LEN(".crt.pem")); 1226 1227 CERTCertificateList *ssl_pemfile_chain; 1228 CERTCertificate *ssl_pemfile_x509 = 1229 mod_nss_load_pem_crts(b->ptr, errh, &ssl_pemfile_chain); 1230 if (NULL == ssl_pemfile_x509) 1231 return SECFailure; 1232 1233 buffer_string_set_length(b, len); 1234 buffer_append_string_len(b, CONST_STR_LEN(".key.pem")); 1235 1236 SECKEYPrivateKey *pkey = 1237 mod_nss_load_config_pkey(b->ptr, ssl_pemfile_x509, errh); 1238 if (NULL == pkey) { 1239 CERT_DestroyCertificate(ssl_pemfile_x509); 1240 if (ssl_pemfile_chain) CERT_DestroyCertificateList(ssl_pemfile_chain); 1241 return SECFailure; 1242 } 1243 1244 /* use NSS deprecated functions to unconfigure an already-configured cert. 1245 * This is because SSL_ConfigServerCert() will replace an existing cert 1246 * of the same type, but not if an existing cert is of a different type */ 1247 if (hctx->conf.pc) { 1248 SSLKEAType certType = 1249 NSS_FindCertKEAType(hctx->conf.pc->ssl_pemfile_x509); 1250 SSL_ConfigSecureServerWithCertChain(hctx->ssl,NULL,NULL,NULL,certType); 1251 } 1252 1253 unsigned int dlen = 0; 1254 SSLExtraServerCertData *data = NULL; 1255 SSLExtraServerCertData d; 1256 if (ssl_pemfile_chain) { 1257 data = &d; 1258 dlen = sizeof(d); 1259 memset(&d, 0, sizeof(d)); 1260 d.certChain = ssl_pemfile_chain; 1261 } 1262 SECStatus rc = 1263 SSL_ConfigServerCert(hctx->ssl, ssl_pemfile_x509, pkey, data, dlen); 1264 1265 CERT_DestroyCertificate(ssl_pemfile_x509); 1266 SECKEY_DestroyPrivateKey(pkey); 1267 if (ssl_pemfile_chain) CERT_DestroyCertificateList(ssl_pemfile_chain); 1268 1269 if (hctx->conf.ssl_verifyclient) { 1270 /*(disable client certificate verification for "acme-tls/1")*/ 1271 hctx->conf.ssl_verifyclient = 0; 1272 SSL_OptionSet(hctx->ssl, SSL_REQUEST_CERTIFICATE, PR_FALSE); 1273 SSL_OptionSet(hctx->ssl, SSL_REQUIRE_CERTIFICATE, SSL_REQUIRE_NEVER); 1274 } 1275 1276 return rc; 1277 } 1278 1279 1280 enum { 1281 MOD_NSS_ALPN_HTTP11 = 1 1282 ,MOD_NSS_ALPN_HTTP10 = 2 1283 ,MOD_NSS_ALPN_H2 = 3 1284 ,MOD_NSS_ALPN_ACME_TLS_1 = 4 1285 }; 1286 1287 1288 static SECStatus 1289 mod_nss_alpn_select_cb (void *arg, PRFileDesc *ssl, 1290 const unsigned char *protos, unsigned int protosLen, 1291 unsigned char *protoOut, unsigned int *protoOutLen, 1292 unsigned int protoMaxOut) 1293 { 1294 /* https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids */ 1295 static const SECItem alpn[] = { 1296 { 0, (unsigned char *)CONST_STR_LEN("h2") } 1297 ,{ 0, (unsigned char *)CONST_STR_LEN("http/1.1") } 1298 ,{ 0, (unsigned char *)CONST_STR_LEN("http/1.0") } 1299 ,{ 0, (unsigned char *)CONST_STR_LEN("acme-tls/1") } 1300 }; 1301 UNUSED(ssl); 1302 /* reference: lib/ssl/sslsock.c:ssl_NextProtoNegoCallback() */ 1303 for (unsigned int i = 0; i < protosLen; i += 1 + protos[i]) { 1304 for (unsigned int j = 0; j < sizeof(alpn)/sizeof(*alpn); ++j) { 1305 if (protos[i] == alpn[j].len && i+1+protos[i] <= protosLen 1306 && 0 == PORT_Memcmp(protos+i+1, alpn[j].data, alpn[j].len)) { 1307 1308 if (protoMaxOut < alpn[j].len) { 1309 PORT_SetError(SEC_ERROR_OUTPUT_LEN); 1310 return SECFailure; 1311 } 1312 1313 handler_ctx *hctx = arg; 1314 switch (j) { /*(must match SECItem alpn[] above)*/ 1315 case 0: 1316 if (!hctx->r->conf.h2proto) continue; 1317 hctx->alpn = MOD_NSS_ALPN_H2; 1318 hctx->r->http_version = HTTP_VERSION_2; 1319 break; 1320 case 1: 1321 hctx->alpn = MOD_NSS_ALPN_HTTP11; 1322 break; 1323 case 2: 1324 hctx->alpn = MOD_NSS_ALPN_HTTP10; 1325 break; 1326 case 3: 1327 if (buffer_string_is_empty(hctx->conf.ssl_acme_tls_1)) 1328 continue; 1329 hctx->alpn = MOD_NSS_ALPN_ACME_TLS_1; 1330 break; 1331 default: 1332 break; 1333 } 1334 1335 memcpy(protoOut, alpn[j].data, alpn[j].len); 1336 *protoOutLen = alpn[j].len; 1337 1338 return SECSuccess; 1339 } 1340 } 1341 } 1342 return SECSuccess; 1343 } 1344 1345 1346 static PRInt32 1347 mod_nss_SNI (PRFileDesc *ssl, const SECItem *srvNameArr, PRUint32 srvNameArrSize, 1348 void *arg) 1349 { 1350 if (0 == srvNameArrSize) /* should not happen */ 1351 return SSL_SNI_CURRENT_CONFIG_IS_USED; 1352 1353 handler_ctx * const hctx = (handler_ctx *)arg; 1354 request_st * const r = hctx->r; 1355 buffer_copy_string_len(&r->uri.scheme, CONST_STR_LEN("https")); 1356 PRUint32 i = 0; /* index into srvNameArr; always take first element */ 1357 const SECItem *sn = srvNameArr+i; 1358 1359 if (sn->len >= 1024) { /*(expecting < 256; TLSEXT_MAXLEN_host_name is 255)*/ 1360 log_error(r->conf.errh, __FILE__, __LINE__, 1361 "NSS: SNI name too long %.*s", (int)sn->len,(char *)sn->data); 1362 return SSL_SNI_SEND_ALERT; 1363 } 1364 1365 /* use SNI to patch mod_nss config and then reset COMP_HTTP_HOST */ 1366 buffer_copy_string_len(&r->uri.authority, (const char *)sn->data, sn->len); 1367 buffer_to_lower(&r->uri.authority); 1368 #if 0 1369 /*(r->uri.authority used below for configuration before request read; 1370 * revisit for h2)*/ 1371 if (0 != http_request_host_policy(&r->uri.authority, 1372 r->conf.http_parseopts, 443)) 1373 return SSL_SNI_SEND_ALERT; 1374 #endif 1375 1376 r->conditional_is_valid |= (1 << COMP_HTTP_SCHEME) 1377 | (1 << COMP_HTTP_HOST); 1378 1379 plugin_cert *pc = hctx->conf.pc; 1380 1381 mod_nss_patch_config(r, &hctx->conf); 1382 /* reset COMP_HTTP_HOST so that conditions re-run after request hdrs read */ 1383 /*(done in configfile-glue.c:config_cond_cache_reset() after request hdrs read)*/ 1384 /*config_cond_cache_reset_item(r, COMP_HTTP_HOST);*/ 1385 /*buffer_clear(&r->uri.authority);*/ 1386 1387 /* XXX: it appears that ALPN callback is called before SNI callback in NSS, 1388 * so handle acme-tls/1 here, prior to and instead of setting cert below */ 1389 if (hctx->alpn == MOD_NSS_ALPN_ACME_TLS_1) { 1390 if (0 == mod_nss_acme_tls_1(hctx)) 1391 return (PRInt32)i; 1392 else { 1393 log_error(hctx->r->conf.errh, __FILE__, __LINE__, 1394 "failed to set acme-tls/1 certificate for TLS" 1395 " server name %s", hctx->r->uri.authority.ptr); 1396 return SSL_SNI_SEND_ALERT; 1397 } 1398 } 1399 1400 if (pc == hctx->conf.pc) 1401 return SSL_SNI_CURRENT_CONFIG_IS_USED; 1402 1403 /* use NSS deprecated functions to unconfigure an already-configured cert. 1404 * This is because SSL_ConfigServerCert() will replace an existing cert 1405 * of the same type, but not if an existing cert is of a different type */ 1406 SSLKEAType certType = 1407 NSS_FindCertKEAType(hctx->conf.pc->ssl_pemfile_x509); 1408 SSL_ConfigSecureServerWithCertChain(ssl, NULL, NULL, NULL, certType); 1409 SECStatus rc = 1410 SSL_ConfigServerCert(ssl, hctx->conf.pc->ssl_pemfile_x509, 1411 hctx->conf.pc->ssl_pemfile_pkey, 1412 &hctx->conf.pc->ssl_credex, 1413 sizeof(hctx->conf.pc->ssl_credex)); 1414 if (rc < 0) { 1415 elogf(r->conf.errh, __FILE__, __LINE__, 1416 "failed to set SNI certificate for TLS server name %s", 1417 r->uri.authority.ptr); 1418 return SSL_SNI_SEND_ALERT; 1419 } 1420 1421 if (hctx->conf.ssl_verifyclient) { 1422 /*(XXX: technically do not need to redo if it has not changed)*/ 1423 if (SSL_AuthCertificateHook(ssl, mod_nss_verify_cb, hctx) < 0) { 1424 elog(r->conf.errh, __FILE__, __LINE__, "SSL_AuthCertificateHook"); 1425 return SSL_SNI_SEND_ALERT; 1426 } 1427 CERTCertList * const certList = hctx->conf.ssl_ca_dn_file 1428 ? hctx->conf.ssl_ca_dn_file 1429 : hctx->conf.ssl_ca_file; 1430 if (NULL == certList) 1431 log_error(hctx->r->conf.errh, __FILE__, __LINE__, 1432 "NSS: can't verify client without ssl.verifyclient.ca-file " 1433 "for TLS server name %s", 1434 hctx->r->uri.authority.ptr); /*(might not be set yet if no SNI)*/ 1435 if (certList && SSL_SetTrustAnchors(ssl, certList) < 0) { 1436 elog(r->conf.errh, __FILE__, __LINE__, "SSL_SetTrustAnchors"); 1437 return SSL_SNI_SEND_ALERT; 1438 } 1439 SSL_OptionSet(ssl, SSL_REQUEST_CERTIFICATE, PR_TRUE); 1440 SSL_OptionSet(ssl, SSL_REQUIRE_CERTIFICATE, 1441 hctx->conf.ssl_verifyclient_enforce 1442 ? SSL_REQUIRE_ALWAYS 1443 : SSL_REQUIRE_NEVER); 1444 } 1445 else { 1446 SSL_OptionSet(ssl, SSL_REQUEST_CERTIFICATE, PR_FALSE); 1447 SSL_OptionSet(ssl, SSL_REQUIRE_CERTIFICATE, SSL_REQUIRE_NEVER); 1448 } 1449 1450 return (PRInt32)i; 1451 } 1452 1453 1454 static int 1455 mod_nss_ssl_conf_ciphersuites (server *srv, plugin_config_socket *s, buffer *ciphersuites, const buffer *cipherstring); 1456 1457 1458 static int 1459 mod_nss_ssl_conf_curves(server *srv, plugin_config_socket *s, const buffer *curvelist); 1460 1461 1462 static void 1463 mod_nss_ssl_conf_proto (server *srv, plugin_config_socket *s, const buffer *minb, const buffer *maxb); 1464 1465 1466 static int 1467 mod_nss_ssl_conf_cmd (server *srv, plugin_config_socket *s) 1468 { 1469 /* reference: 1470 * https://www.openssl.org/docs/man1.1.1/man3/SSL_CONF_cmd.html */ 1471 int rc = 0; 1472 buffer *cipherstring = NULL; 1473 buffer *ciphersuites = NULL; 1474 buffer *minb = NULL; 1475 buffer *maxb = NULL; 1476 buffer *curves = NULL; 1477 1478 for (size_t i = 0; i < s->ssl_conf_cmd->used; ++i) { 1479 data_string *ds = (data_string *)s->ssl_conf_cmd->data[i]; 1480 if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("CipherString"))) 1481 cipherstring = &ds->value; 1482 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Ciphersuites"))) 1483 ciphersuites = &ds->value; 1484 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Curves")) 1485 || buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Groups"))) 1486 curves = &ds->value; 1487 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("MaxProtocol"))) 1488 maxb = &ds->value; 1489 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("MinProtocol"))) 1490 minb = &ds->value; 1491 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Protocol"))) { 1492 /* openssl config for Protocol=... is complex and deprecated */ 1493 log_error(srv->errh, __FILE__, __LINE__, 1494 "NSS: ssl.openssl.ssl-conf-cmd %s ignored; " 1495 "use MinProtocol=... and MaxProtocol=... instead", 1496 ds->key.ptr); 1497 } 1498 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Options"))) { 1499 for (char *v = ds->value.ptr, *e; *v; v = e) { 1500 while (*v == ' ' || *v == '\t' || *v == ',') ++v; 1501 int flag = 1; 1502 if (*v == '-') { 1503 flag = 0; 1504 ++v; 1505 } 1506 for (e = v; light_isalpha(*e); ++e) ; 1507 switch ((int)(e-v)) { 1508 case 11: 1509 if (buffer_eq_icase_ssn(v, "Compression", 11)) { 1510 s->ssl_compression = flag; 1511 continue; 1512 } 1513 break; 1514 case 13: 1515 if (buffer_eq_icase_ssn(v, "SessionTicket", 13)) { 1516 /*(translates to "%NO_TICKETS" priority str if !flag)*/ 1517 s->ssl_session_ticket = flag; 1518 continue; 1519 } 1520 break; 1521 case 16: 1522 if (buffer_eq_icase_ssn(v, "ServerPreference", 16)) { 1523 /*(translates to "%SERVER_PRECEDENCE" priority string)*/ 1524 s->ssl_honor_cipher_order = flag; 1525 continue; 1526 } 1527 break; 1528 default: 1529 break; 1530 } 1531 /* warn if not explicitly handled or ignored above */ 1532 if (!flag) --v; 1533 log_error(srv->errh, __FILE__, __LINE__, 1534 "NSS: ssl.openssl.ssl-conf-cmd Options %.*s " 1535 "ignored", (int)(e-v), v); 1536 } 1537 } 1538 #if 0 1539 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("..."))) { 1540 } 1541 #endif 1542 else { 1543 /* warn if not explicitly handled or ignored above */ 1544 log_error(srv->errh, __FILE__, __LINE__, 1545 "NSS: ssl.openssl.ssl-conf-cmd %s ignored", 1546 ds->key.ptr); 1547 } 1548 } 1549 1550 if (minb || maxb) /*(if at least one was set)*/ 1551 mod_nss_ssl_conf_proto(srv, s, minb, maxb); 1552 1553 if (!mod_nss_ssl_conf_ciphersuites(srv, s, ciphersuites, cipherstring)) 1554 rc = -1; 1555 1556 if (curves) { 1557 if (!mod_nss_ssl_conf_curves(srv, s, curves)) 1558 rc = -1; 1559 } 1560 1561 return rc; 1562 } 1563 1564 1565 static int 1566 network_init_ssl (server *srv, plugin_config_socket *s, plugin_data *p) 1567 { 1568 UNUSED(p); 1569 1570 const int disable_sess_cache = 1571 srv->srvconf.feature_flags 1572 && !config_plugin_value_tobool( 1573 array_get_element_klen(srv->srvconf.feature_flags, 1574 CONST_STR_LEN("ssl.session-cache")), 0); 1575 if (!disable_sess_cache) /* undo disable from mod_nss_init_once_nss() */ 1576 SSL_OptionSetDefault(SSL_NO_CACHE, PR_FALSE); 1577 1578 /* use PR_CreateSocketPollFd() for dummy; 1579 * PR_CreateIOLayerStub() was resulting in crashes 1580 * when SSL_ImportFD() attempted ssl_DefGetpeername() */ 1581 s->model = PR_CreateSocketPollFd(-1); 1582 if (NULL == s->model) return -1; 1583 s->model->methods = PR_GetTCPMethods(); 1584 PRFileDesc *model = SSL_ImportFD(NULL, s->model); 1585 if (NULL == model) return -1; 1586 s->model = model; 1587 1588 if (!buffer_string_is_empty(s->ssl_cipher_list)) { 1589 if (!mod_nss_ssl_conf_ciphersuites(srv,s,NULL,s->ssl_cipher_list)) 1590 return -1; 1591 } 1592 1593 if (!buffer_string_is_empty(s->ssl_ec_curve)) { 1594 if (!mod_nss_ssl_conf_curves(srv, s, s->ssl_ec_curve)) 1595 return -1; 1596 } 1597 1598 if (!s->ssl_use_sslv3 && !s->ssl_use_sslv2) 1599 mod_nss_ssl_conf_proto(srv, s, NULL, NULL); /* set default range */ 1600 1601 if (s->ssl_conf_cmd && s->ssl_conf_cmd->used) { 1602 if (0 != mod_nss_ssl_conf_cmd(srv, s)) return -1; 1603 } 1604 1605 if (s->ssl_use_sslv3) 1606 s->protos.min = SSL_LIBRARY_VERSION_3_0; 1607 if (s->ssl_use_sslv2) 1608 s->protos.min = SSL_LIBRARY_VERSION_2; 1609 1610 /* future: add additional configuration of s->model here 1611 * rather than in mod_nss_handle_con_accept() */ 1612 1613 if (SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) < 0) { 1614 elog(srv->errh, __FILE__, __LINE__, "SSL_SECURITY"); 1615 return -1; 1616 } 1617 1618 if (SSL_VersionRangeSet(model, &s->protos)) { 1619 elog(srv->errh, __FILE__, __LINE__, "SSL_VersionRangeSet()"); 1620 return -1; 1621 } 1622 1623 if (s->protos.min == SSL_LIBRARY_VERSION_2 1624 && SSL_OptionSet(model, SSL_ENABLE_SSL2, PR_TRUE) < 0) { 1625 elog(srv->errh, __FILE__, __LINE__, "SSL_ENABLE_SSL2"); 1626 return -1; 1627 } 1628 1629 if (s->protos.min == SSL_LIBRARY_VERSION_3_0 1630 && SSL_OptionSet(model, SSL_ENABLE_SSL3, PR_TRUE) < 0) { 1631 elog(srv->errh, __FILE__, __LINE__, "SSL_ENABLE_SSL3"); 1632 return -1; 1633 } 1634 1635 if (!s->ssl_session_ticket 1636 && SSL_OptionSet(model, SSL_ENABLE_SESSION_TICKETS, PR_FALSE) < 0) { 1637 elog(srv->errh, __FILE__, __LINE__, "!SSL_ENABLE_SESSION_TICKETS"); 1638 return -1; 1639 } 1640 1641 if (SSL_OptionSet(model, SSL_ENABLE_DEFLATE, s->ssl_compression) < 0) { 1642 elog(srv->errh, __FILE__, __LINE__, "SSL_ENABLE_DEFLATE"); 1643 return HANDLER_ERROR; 1644 } 1645 1646 SSL_OptionSet(model, SSL_REQUEST_CERTIFICATE, PR_FALSE); 1647 SSL_OptionSet(model, SSL_REQUIRE_CERTIFICATE, SSL_REQUIRE_NEVER); 1648 1649 SECStatus rc = 1650 SSL_ConfigServerCert(model, s->pc->ssl_pemfile_x509, 1651 s->pc->ssl_pemfile_pkey, 1652 &s->pc->ssl_credex, 1653 sizeof(s->pc->ssl_credex)); 1654 if (rc < 0) { 1655 elogf(srv->errh, __FILE__, __LINE__, 1656 "failed to set default certificate for socket"); 1657 return -1; 1658 } 1659 1660 return 0; 1661 } 1662 1663 1664 static int 1665 mod_nss_set_defaults_sockets(server *srv, plugin_data *p) 1666 { 1667 static const config_plugin_keys_t cpk[] = { 1668 { CONST_STR_LEN("ssl.engine"), 1669 T_CONFIG_BOOL, 1670 T_CONFIG_SCOPE_CONNECTION } 1671 ,{ CONST_STR_LEN("ssl.cipher-list"), 1672 T_CONFIG_STRING, 1673 T_CONFIG_SCOPE_CONNECTION } 1674 ,{ CONST_STR_LEN("ssl.honor-cipher-order"), 1675 T_CONFIG_BOOL, 1676 T_CONFIG_SCOPE_CONNECTION } 1677 ,{ CONST_STR_LEN("ssl.dh-file"), 1678 T_CONFIG_STRING, 1679 T_CONFIG_SCOPE_CONNECTION } 1680 ,{ CONST_STR_LEN("ssl.ec-curve"), 1681 T_CONFIG_STRING, 1682 T_CONFIG_SCOPE_CONNECTION } 1683 ,{ CONST_STR_LEN("ssl.openssl.ssl-conf-cmd"), 1684 T_CONFIG_ARRAY_KVSTRING, 1685 T_CONFIG_SCOPE_CONNECTION } 1686 ,{ CONST_STR_LEN("ssl.pemfile"), /* included to process global scope */ 1687 T_CONFIG_STRING, 1688 T_CONFIG_SCOPE_CONNECTION } 1689 ,{ CONST_STR_LEN("ssl.empty-fragments"), 1690 T_CONFIG_BOOL, 1691 T_CONFIG_SCOPE_CONNECTION } 1692 ,{ CONST_STR_LEN("ssl.use-sslv2"), 1693 T_CONFIG_BOOL, 1694 T_CONFIG_SCOPE_CONNECTION } 1695 ,{ CONST_STR_LEN("ssl.use-sslv3"), 1696 T_CONFIG_BOOL, 1697 T_CONFIG_SCOPE_CONNECTION } 1698 ,{ CONST_STR_LEN("ssl.stek-file"), 1699 T_CONFIG_STRING, 1700 T_CONFIG_SCOPE_SERVER } 1701 ,{ NULL, 0, 1702 T_CONFIG_UNSET, 1703 T_CONFIG_SCOPE_UNSET } 1704 }; 1705 static const buffer default_ssl_cipher_list = { CONST_STR_LEN("HIGH"), 0 }; 1706 1707 p->ssl_ctxs = calloc(srv->config_context->used, sizeof(plugin_ssl_ctx)); 1708 force_assert(p->ssl_ctxs); 1709 1710 int rc = HANDLER_GO_ON; 1711 plugin_data_base srvplug; 1712 memset(&srvplug, 0, sizeof(srvplug)); 1713 plugin_data_base * const ps = &srvplug; 1714 if (!config_plugin_values_init(srv, ps, cpk, "mod_nss")) 1715 return HANDLER_ERROR; 1716 1717 plugin_config_socket defaults; 1718 memset(&defaults, 0, sizeof(defaults)); 1719 defaults.ssl_honor_cipher_order = 1; /* default server preference for PFS */ 1720 defaults.ssl_session_ticket = 1; /* enabled by default */ 1721 defaults.ssl_compression = 0; /* disable for security */ 1722 defaults.ssl_cipher_list = &default_ssl_cipher_list; 1723 1724 /* process and validate config directives for global and $SERVER["socket"] 1725 * (init i to 0 if global context; to 1 to skip empty global context) */ 1726 for (int i = !ps->cvlist[0].v.u2[1]; i < ps->nconfig; ++i) { 1727 config_cond_info cfginfo; 1728 config_get_config_cond_info(&cfginfo, (uint32_t)ps->cvlist[i].k_id); 1729 int is_socket_scope = (0 == i || cfginfo.comp == COMP_SERVER_SOCKET); 1730 int count_not_engine = 0; 1731 1732 plugin_config_socket conf; 1733 memcpy(&conf, &defaults, sizeof(conf)); 1734 1735 /*(preserve prior behavior; not inherited)*/ 1736 /*(forcing inheritance might break existing configs where SSL is enabled 1737 * by default in the global scope, but not $SERVER["socket"]=="*:80") */ 1738 conf.ssl_enabled = 0; 1739 1740 config_plugin_value_t *cpv = ps->cvlist + ps->cvlist[i].v.u2[0]; 1741 for (; -1 != cpv->k_id; ++cpv) { 1742 /* ignore ssl.pemfile (k_id=6); included to process global scope */ 1743 if (!is_socket_scope && cpv->k_id != 6) { 1744 log_error(srv->errh, __FILE__, __LINE__, 1745 "NSS: %s is valid only in global scope or " 1746 "$SERVER[\"socket\"] condition", cpk[cpv->k_id].k); 1747 continue; 1748 } 1749 ++count_not_engine; 1750 switch (cpv->k_id) { 1751 case 0: /* ssl.engine */ 1752 conf.ssl_enabled = (0 != cpv->v.u); 1753 --count_not_engine; 1754 break; 1755 case 1: /* ssl.cipher-list */ 1756 conf.ssl_cipher_list = cpv->v.b; 1757 break; 1758 case 2: /* ssl.honor-cipher-order */ 1759 conf.ssl_honor_cipher_order = (0 != cpv->v.u); 1760 break; 1761 case 3: /* ssl.dh-file */ 1762 log_error(srv->errh, __FILE__, __LINE__, 1763 "NSS: ignoring ssl.dh-file; not implemented" 1764 "obsoleted by RFC7919"); 1765 break; 1766 case 4: /* ssl.ec-curve */ 1767 conf.ssl_ec_curve = cpv->v.b; 1768 break; 1769 case 5: /* ssl.openssl.ssl-conf-cmd */ 1770 *(const array **)&conf.ssl_conf_cmd = cpv->v.a; 1771 break; 1772 case 6: /* ssl.pemfile */ 1773 /* ignore here; included to process global scope when 1774 * ssl.pemfile is set, but ssl.engine is not "enable" */ 1775 break; 1776 case 7: /* ssl.empty-fragments */ 1777 conf.ssl_empty_fragments = (0 != cpv->v.u); 1778 log_error(srv->errh, __FILE__, __LINE__, 1779 "NSS: ignoring ssl.empty-fragments; openssl-specific " 1780 "counter-measure against a SSL 3.0/TLS 1.0 protocol " 1781 "vulnerability affecting CBC ciphers, which cannot be handled" 1782 " by some broken (Microsoft) SSL implementations."); 1783 break; 1784 case 8: /* ssl.use-sslv2 */ 1785 conf.ssl_use_sslv2 = (0 != cpv->v.u); 1786 log_error(srv->errh, __FILE__, __LINE__, "NSS: " 1787 "ssl.use-sslv2 is deprecated and will soon be removed. " 1788 "Many modern TLS libraries no longer support SSLv2."); 1789 break; 1790 case 9: /* ssl.use-sslv3 */ 1791 conf.ssl_use_sslv3 = (0 != cpv->v.u); 1792 log_error(srv->errh, __FILE__, __LINE__, "NSS: " 1793 "ssl.use-sslv3 is deprecated and will soon be removed. " 1794 "Many modern TLS libraries no longer support SSLv3. " 1795 "If needed, use: " 1796 "ssl.openssl.ssl-conf-cmd = (\"MinProtocol\" => \"SSLv3\")"); 1797 break; 1798 case 10:/* ssl.stek-file */ 1799 log_error(srv->errh, __FILE__, __LINE__, "NSS: " 1800 "ssl.stek-file is not supported in mod_nss; ignoring."); 1801 break; 1802 default:/* should not happen */ 1803 break; 1804 } 1805 } 1806 if (HANDLER_GO_ON != rc) break; 1807 if (0 == i) memcpy(&defaults, &conf, sizeof(conf)); 1808 1809 if (0 != i && !conf.ssl_enabled) continue; 1810 1811 /* fill plugin_config_socket with global context then $SERVER["socket"] 1812 * only for directives directly in current $SERVER["socket"] condition*/ 1813 1814 /*conf.pc = p->defaults.pc;*/ 1815 conf.ssl_verifyclient = p->defaults.ssl_verifyclient; 1816 conf.ssl_verifyclient_enforce = p->defaults.ssl_verifyclient_enforce; 1817 conf.ssl_verifyclient_depth = p->defaults.ssl_verifyclient_depth; 1818 1819 int sidx = ps->cvlist[i].k_id; 1820 for (int j = !p->cvlist[0].v.u2[1]; j < p->nconfig; ++j) { 1821 if (p->cvlist[j].k_id != sidx) continue; 1822 /*if (0 == sidx) break;*//*(repeat to get ssl_pemfile,ssl_privkey)*/ 1823 cpv = p->cvlist + p->cvlist[j].v.u2[0]; 1824 for (; -1 != cpv->k_id; ++cpv) { 1825 ++count_not_engine; 1826 switch (cpv->k_id) { 1827 case 0: /* ssl.pemfile */ 1828 if (cpv->vtype == T_CONFIG_LOCAL) 1829 conf.pc = cpv->v.v; 1830 break; 1831 case 7: /* ssl.verifyclient.activate */ 1832 conf.ssl_verifyclient = (0 != cpv->v.u); 1833 break; 1834 case 8: /* ssl.verifyclient.enforce */ 1835 conf.ssl_verifyclient_enforce = (0 != cpv->v.u); 1836 break; 1837 case 9: /* ssl.verifyclient.depth */ 1838 conf.ssl_verifyclient_depth = (unsigned char)cpv->v.shrt; 1839 break; 1840 default: 1841 break; 1842 } 1843 } 1844 break; 1845 } 1846 1847 if (NULL == conf.pc) { 1848 if (0 == i && !conf.ssl_enabled) continue; 1849 if (0 != i) { 1850 /* inherit ssl settings from global scope 1851 * (if only ssl.engine = "enable" and no other ssl.* settings) 1852 * (This is for convenience when defining both IPv4 and IPv6 1853 * and desiring to inherit the ssl config from global context 1854 * without having to duplicate the directives)*/ 1855 if (count_not_engine 1856 || (conf.ssl_enabled && NULL == p->ssl_ctxs[0].model)) { 1857 log_error(srv->errh, __FILE__, __LINE__, 1858 "NSS: ssl.pemfile has to be set in same " 1859 "$SERVER[\"socket\"] scope as other ssl.* directives, " 1860 "unless only ssl.engine is set, inheriting ssl.* from " 1861 "global scope"); 1862 rc = HANDLER_ERROR; 1863 continue; 1864 } 1865 plugin_ssl_ctx * const s = p->ssl_ctxs + sidx; 1866 *s = *p->ssl_ctxs;/*(copy struct of ssl_ctx from global scope)*/ 1867 continue; 1868 } 1869 /* PEM file is required */ 1870 log_error(srv->errh, __FILE__, __LINE__, 1871 "NSS: ssl.pemfile has to be set when ssl.engine = \"enable\""); 1872 rc = HANDLER_ERROR; 1873 continue; 1874 } 1875 1876 /* (initialize once if module enabled) */ 1877 if (!mod_nss_init_once_nss()) { 1878 rc = HANDLER_ERROR; 1879 break; 1880 } 1881 1882 /* configure ssl_ctx for socket */ 1883 1884 /*conf.ssl_ctx = NULL;*//*(filled by network_init_ssl() even on error)*/ 1885 if (0 == network_init_ssl(srv, &conf, p)) { 1886 plugin_ssl_ctx * const s = p->ssl_ctxs + sidx; 1887 s->model = conf.model; 1888 s->protos = conf.protos; 1889 s->ssl_compression = conf.ssl_compression; 1890 s->ssl_session_ticket = conf.ssl_session_ticket; 1891 } 1892 else { 1893 if (conf.model) PR_Close(conf.model); 1894 rc = HANDLER_ERROR; 1895 } 1896 } 1897 1898 free(srvplug.cvlist); 1899 return rc; 1900 } 1901 1902 1903 SETDEFAULTS_FUNC(mod_nss_set_defaults) 1904 { 1905 static const config_plugin_keys_t cpk[] = { 1906 { CONST_STR_LEN("ssl.pemfile"), 1907 T_CONFIG_STRING, 1908 T_CONFIG_SCOPE_CONNECTION } 1909 ,{ CONST_STR_LEN("ssl.privkey"), 1910 T_CONFIG_STRING, 1911 T_CONFIG_SCOPE_CONNECTION } 1912 ,{ CONST_STR_LEN("ssl.ca-file"), 1913 T_CONFIG_STRING, 1914 T_CONFIG_SCOPE_CONNECTION } 1915 ,{ CONST_STR_LEN("ssl.ca-dn-file"), 1916 T_CONFIG_STRING, 1917 T_CONFIG_SCOPE_CONNECTION } 1918 ,{ CONST_STR_LEN("ssl.ca-crl-file"), 1919 T_CONFIG_STRING, 1920 T_CONFIG_SCOPE_CONNECTION } 1921 ,{ CONST_STR_LEN("ssl.read-ahead"), 1922 T_CONFIG_BOOL, 1923 T_CONFIG_SCOPE_CONNECTION } 1924 ,{ CONST_STR_LEN("ssl.disable-client-renegotiation"), 1925 T_CONFIG_BOOL, 1926 T_CONFIG_SCOPE_CONNECTION } 1927 ,{ CONST_STR_LEN("ssl.verifyclient.activate"), 1928 T_CONFIG_BOOL, 1929 T_CONFIG_SCOPE_CONNECTION } 1930 ,{ CONST_STR_LEN("ssl.verifyclient.enforce"), 1931 T_CONFIG_BOOL, 1932 T_CONFIG_SCOPE_CONNECTION } 1933 ,{ CONST_STR_LEN("ssl.verifyclient.depth"), 1934 T_CONFIG_SHORT, 1935 T_CONFIG_SCOPE_CONNECTION } 1936 ,{ CONST_STR_LEN("ssl.verifyclient.username"), 1937 T_CONFIG_STRING, 1938 T_CONFIG_SCOPE_CONNECTION } 1939 ,{ CONST_STR_LEN("ssl.verifyclient.exportcert"), 1940 T_CONFIG_BOOL, 1941 T_CONFIG_SCOPE_CONNECTION } 1942 ,{ CONST_STR_LEN("ssl.acme-tls-1"), 1943 T_CONFIG_STRING, 1944 T_CONFIG_SCOPE_CONNECTION } 1945 ,{ CONST_STR_LEN("ssl.stapling-file"), 1946 T_CONFIG_STRING, 1947 T_CONFIG_SCOPE_CONNECTION } 1948 ,{ CONST_STR_LEN("debug.log-ssl-noise"), 1949 T_CONFIG_SHORT, 1950 T_CONFIG_SCOPE_CONNECTION } 1951 ,{ CONST_STR_LEN("ssl.verifyclient.ca-file"), 1952 T_CONFIG_STRING, 1953 T_CONFIG_SCOPE_CONNECTION } 1954 ,{ CONST_STR_LEN("ssl.verifyclient.ca-dn-file"), 1955 T_CONFIG_STRING, 1956 T_CONFIG_SCOPE_CONNECTION } 1957 ,{ CONST_STR_LEN("ssl.verifyclient.ca-crl-file"), 1958 T_CONFIG_STRING, 1959 T_CONFIG_SCOPE_CONNECTION } 1960 ,{ NULL, 0, 1961 T_CONFIG_UNSET, 1962 T_CONFIG_SCOPE_UNSET } 1963 }; 1964 1965 plugin_data * const p = p_d; 1966 p->srv = srv; 1967 if (!config_plugin_values_init(srv, p, cpk, "mod_nss")) 1968 return HANDLER_ERROR; 1969 1970 /* process and validate config directives 1971 * (init i to 0 if global context; to 1 to skip empty global context) */ 1972 for (int i = !p->cvlist[0].v.u2[1]; i < p->nconfig; ++i) { 1973 config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0]; 1974 config_plugin_value_t *pemfile = NULL; 1975 config_plugin_value_t *privkey = NULL; 1976 const buffer *ssl_stapling_file = NULL; 1977 for (; -1 != cpv->k_id; ++cpv) { 1978 switch (cpv->k_id) { 1979 case 0: /* ssl.pemfile */ 1980 if (!buffer_string_is_empty(cpv->v.b)) pemfile = cpv; 1981 break; 1982 case 1: /* ssl.privkey */ 1983 if (!buffer_string_is_empty(cpv->v.b)) privkey = cpv; 1984 break; 1985 case 15:/* ssl.verifyclient.ca-file */ 1986 cpv->k_id = 2; 1987 __attribute_fallthrough__ 1988 case 2: /* ssl.ca-file */ 1989 if (!buffer_string_is_empty(cpv->v.b)) { 1990 CERTCertList *d = 1991 mod_nss_load_config_crts(cpv->v.b->ptr, srv->errh); 1992 if (d != NULL) { 1993 cpv->vtype = T_CONFIG_LOCAL; 1994 cpv->v.v = d; 1995 } 1996 else { 1997 log_error(srv->errh, __FILE__, __LINE__, 1998 "%s = %s", cpk[cpv->k_id].k, cpv->v.b->ptr); 1999 return HANDLER_ERROR; 2000 } 2001 } 2002 break; 2003 case 16:/* ssl.verifyclient.ca-dn-file */ 2004 cpv->k_id = 3; 2005 __attribute_fallthrough__ 2006 case 3: /* ssl.ca-dn-file */ 2007 if (!buffer_string_is_empty(cpv->v.b)) { 2008 CERTCertList *d = 2009 mod_nss_load_config_dncrts(cpv->v.b->ptr, srv->errh); 2010 if (d != NULL) { 2011 cpv->vtype = T_CONFIG_LOCAL; 2012 cpv->v.v = d; 2013 } 2014 else { 2015 log_error(srv->errh, __FILE__, __LINE__, 2016 "%s = %s", cpk[cpv->k_id].k, cpv->v.b->ptr); 2017 return HANDLER_ERROR; 2018 } 2019 } 2020 break; 2021 case 17:/* ssl.verifyclient.ca-crl-file */ 2022 cpv->k_id = 4; 2023 __attribute_fallthrough__ 2024 case 4: /* ssl.ca-crl-file */ 2025 if (!buffer_string_is_empty(cpv->v.b)) { 2026 CERTCertificateList *d = 2027 mod_nss_load_config_crls(cpv->v.b->ptr, srv->errh); 2028 if (d != NULL) { 2029 cpv->vtype = T_CONFIG_LOCAL; 2030 cpv->v.v = d; 2031 } 2032 else { 2033 log_error(srv->errh, __FILE__, __LINE__, 2034 "%s = %s", cpk[cpv->k_id].k, cpv->v.b->ptr); 2035 return HANDLER_ERROR; 2036 } 2037 } 2038 break; 2039 case 5: /* ssl.read-ahead */ 2040 case 6: /* ssl.disable-client-renegotiation */ 2041 case 7: /* ssl.verifyclient.activate */ 2042 case 8: /* ssl.verifyclient.enforce */ 2043 break; 2044 case 9: /* ssl.verifyclient.depth */ 2045 if (cpv->v.shrt > 255) { 2046 log_error(srv->errh, __FILE__, __LINE__, 2047 "NSS: %s is absurdly large (%hu); limiting to 255", 2048 cpk[cpv->k_id].k, cpv->v.shrt); 2049 cpv->v.shrt = 255; 2050 } 2051 break; 2052 case 10:/* ssl.verifyclient.username */ 2053 case 11:/* ssl.verifyclient.exportcert */ 2054 case 12:/* ssl.acme-tls-1 */ 2055 break; 2056 case 13:/* ssl.stapling-file */ 2057 ssl_stapling_file = cpv->v.b; 2058 break; 2059 case 14:/* debug.log-ssl-noise */ 2060 #if 0 /*(handled further above)*/ 2061 case 15:/* ssl.verifyclient.ca-file */ 2062 case 16:/* ssl.verifyclient.ca-dn-file */ 2063 case 17:/* ssl.verifyclient.ca-crl-file */ 2064 #endif 2065 break; 2066 default:/* should not happen */ 2067 break; 2068 } 2069 } 2070 2071 if (pemfile) { 2072 if (NULL == privkey) privkey = pemfile; 2073 pemfile->v.v = 2074 network_nss_load_pemfile(srv, pemfile->v.b, privkey->v.b, 2075 ssl_stapling_file); 2076 if (pemfile->v.v) 2077 pemfile->vtype = T_CONFIG_LOCAL; 2078 else 2079 return HANDLER_ERROR; 2080 } 2081 } 2082 2083 p->defaults.ssl_verifyclient = 0; 2084 p->defaults.ssl_verifyclient_enforce = 1; 2085 p->defaults.ssl_verifyclient_depth = 9; 2086 p->defaults.ssl_verifyclient_export_cert = 0; 2087 p->defaults.ssl_disable_client_renegotiation = 1; 2088 p->defaults.ssl_read_ahead = 0; 2089 2090 /* initialize p->defaults from global config context */ 2091 if (p->nconfig > 0 && p->cvlist->v.u2[1]) { 2092 const config_plugin_value_t *cpv = p->cvlist + p->cvlist->v.u2[0]; 2093 if (-1 != cpv->k_id) 2094 mod_nss_merge_config(&p->defaults, cpv); 2095 } 2096 2097 return mod_nss_set_defaults_sockets(srv, p); 2098 } 2099 2100 2101 /* local_send_buffer is a static buffer of size (LOCAL_SEND_BUFSIZE) 2102 * 2103 * buffer is allocated once, is NOT realloced (note: not thread-safe) 2104 * */ 2105 2106 /* copy small mem chunks into single large buffer 2107 * before PR_Write() to reduce number times write() called 2108 * underneath PR_Write() and potentially reduce number of packets 2109 * generated if TCP_NODELAY */ 2110 2111 2112 __attribute_cold__ 2113 static int 2114 mod_nss_write_err(connection *con, handler_ctx *hctx, size_t wr_len) 2115 { 2116 switch (PR_GetError()) { 2117 case PR_WOULD_BLOCK_ERROR: 2118 case PR_PENDING_INTERRUPT_ERROR: 2119 con->is_writable = -1; 2120 /* XXX: not handled: protocol might be blocked waiting on read */ 2121 /*if (0) con->is_readable = -1;*/ 2122 break; /* try again later */ 2123 case PR_CONNECT_RESET_ERROR: 2124 if (!hctx->conf.ssl_log_noise) return -1; 2125 __attribute_fallthrough__ 2126 default: 2127 elog(hctx->r->conf.errh, __FILE__, __LINE__, __func__); 2128 return -1; 2129 } 2130 2131 /* partial write; save attempted wr_len */ 2132 hctx->pending_write = wr_len; 2133 2134 return 0; /* try again later */ 2135 } 2136 2137 2138 __attribute_cold__ 2139 static int 2140 mod_nss_read_err(connection *con, handler_ctx *hctx) 2141 { 2142 switch (PR_GetError()) { 2143 case PR_WOULD_BLOCK_ERROR: 2144 case PR_PENDING_INTERRUPT_ERROR: 2145 /* XXX: not handled: protocol might be blocked waiting on write */ 2146 /*if (0) con->is_writable = -1;*/ 2147 con->is_readable = 0; 2148 return 0; 2149 case PR_CONNECT_ABORTED_ERROR: 2150 case PR_CONNECT_RESET_ERROR: 2151 if (!hctx->conf.ssl_log_noise) return -1; 2152 __attribute_fallthrough__ 2153 default: 2154 elog(hctx->errh, __FILE__, __LINE__, __func__); 2155 return -1; 2156 } 2157 } 2158 2159 2160 static int 2161 mod_nss_close_notify(handler_ctx *hctx); 2162 2163 2164 static int 2165 connection_write_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes) 2166 { 2167 handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id]; 2168 PRFileDesc *ssl = hctx->ssl; 2169 log_error_st * const errh = hctx->errh; 2170 2171 if (0 != hctx->close_notify) return mod_nss_close_notify(hctx); 2172 2173 chunkqueue_remove_finished_chunks(cq); 2174 2175 /* future: for efficiency/performance might consider using NSS 2176 * PR_Writev() PR_TransmitFile() PR_SendFile() 2177 */ 2178 2179 while (max_bytes > 0 && !chunkqueue_is_empty(cq)) { 2180 char *data = local_send_buffer; 2181 uint32_t data_len = LOCAL_SEND_BUFSIZE < max_bytes 2182 ? LOCAL_SEND_BUFSIZE 2183 : (uint32_t)max_bytes; 2184 int wr; 2185 2186 if (0 != chunkqueue_peek_data(cq, &data, &data_len, errh)) return -1; 2187 2188 /*(if partial write occurred, expect that subsequent writes will have 2189 * at least that much data available from chunkqueue_peek_data(), which 2190 * is what should happen, but is not checked here)*/ 2191 size_t lim = hctx->pending_write; 2192 if (lim && data_len > lim) data_len = lim; 2193 hctx->pending_write = 0; 2194 2195 /* 2196 * XXX: above comments modified from mod_mbedtls; should be verified 2197 */ 2198 2199 int wr_total = 0; 2200 do { 2201 size_t wr_len = data_len; 2202 wr = PR_Write(ssl, data, (PRInt32)wr_len); 2203 if (wr <= 0) { 2204 if (wr_total) chunkqueue_mark_written(cq, wr_total); 2205 return mod_nss_write_err(con, hctx, wr_len); 2206 } 2207 wr_total += wr; 2208 data += wr; 2209 } while ((data_len -= wr)); 2210 chunkqueue_mark_written(cq, wr_total); 2211 max_bytes -= wr_total; 2212 } 2213 2214 return 0; 2215 } 2216 2217 2218 static void 2219 mod_nss_SSLHandshakeCallback (PRFileDesc *fd, void *arg) 2220 { 2221 UNUSED(fd); 2222 handler_ctx *hctx = arg; 2223 hctx->handshake = 1; 2224 } 2225 2226 2227 static int 2228 connection_read_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes) 2229 { 2230 handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id]; 2231 2232 UNUSED(max_bytes); 2233 2234 if (0 != hctx->close_notify) return mod_nss_close_notify(hctx); 2235 2236 PRFileDesc *ssl = hctx->ssl; 2237 ssize_t len; 2238 char *mem = NULL; 2239 size_t mem_len = 0; 2240 do { 2241 int pend = SSL_DataPending(ssl); 2242 if (pend < 0) { 2243 len = pend; 2244 break; 2245 } 2246 mem_len = pend < 2048 ? 2048 : (uint32_t)pend; 2247 chunk * const ckpt = cq->last; 2248 mem = chunkqueue_get_memory(cq, &mem_len); 2249 2250 len = PR_Read(ssl, mem, (PRInt32)mem_len); 2251 if (len > 0) { 2252 chunkqueue_use_memory(cq, ckpt, len); 2253 con->bytes_read += len; 2254 } else { 2255 chunkqueue_use_memory(cq, ckpt, 0); 2256 } 2257 } while (len > 0); 2258 2259 if (hctx->alpn && hctx->handshake) { 2260 if (hctx->alpn == MOD_NSS_ALPN_ACME_TLS_1) { 2261 /* Once TLS handshake is complete, return -1 to result in 2262 * CON_STATE_ERROR so that socket connection is quickly closed */ 2263 return -1; 2264 } 2265 hctx->alpn = 0; 2266 } 2267 2268 if (len < 0) { 2269 return mod_nss_read_err(con, hctx); 2270 } else if (len == 0) { 2271 con->is_readable = 0; 2272 /* the other end closed the connection -> KEEP-ALIVE */ 2273 2274 return -2; 2275 #ifndef __COVERITY__ 2276 } else { 2277 return 0; 2278 #endif 2279 } 2280 } 2281 2282 2283 CONNECTION_FUNC(mod_nss_handle_con_accept) 2284 { 2285 server_socket *srv_sock = con->srv_socket; 2286 if (!srv_sock->is_ssl) return HANDLER_GO_ON; 2287 2288 plugin_data *p = p_d; 2289 handler_ctx * const hctx = handler_ctx_init(); 2290 request_st * const r = &con->request; 2291 hctx->r = r; 2292 hctx->con = con; 2293 hctx->tmp_buf = con->srv->tmp_buf; 2294 hctx->errh = r->conf.errh; 2295 con->plugin_ctx[p->id] = hctx; 2296 buffer_string_set_length(&r->uri.authority, 0); 2297 2298 plugin_ssl_ctx * const s = p->ssl_ctxs + srv_sock->sidx; 2299 hctx->ssl_session_ticket = s->ssl_session_ticket; 2300 2301 con->network_read = connection_read_cq_ssl; 2302 con->network_write = connection_write_cq_ssl; 2303 con->proto_default_port = 443; /* "https" */ 2304 mod_nss_patch_config(r, &hctx->conf); 2305 2306 hctx->ssl = mod_nss_io_ctor(con->fd, s->model, r->conf.errh); 2307 if (NULL == hctx->ssl) 2308 return HANDLER_ERROR; 2309 2310 /* future: move more config from here to config model in network_init_ssl(). 2311 * Callbacks need to be set here to be able to set callback arg to hctx */ 2312 2313 if (!hctx->conf.ssl_disable_client_renegotiation 2314 && SSL_OptionSet(hctx->ssl, SSL_ENABLE_RENEGOTIATION, 2315 SSL_RENEGOTIATE_REQUIRES_XTN) < 0) { 2316 elog(r->conf.errh, __FILE__, __LINE__, "SSL_ENABLE_RENEGOTIATION"); 2317 return HANDLER_ERROR; 2318 } 2319 2320 if (SSL_ResetHandshake(hctx->ssl, PR_TRUE) < 0) { 2321 elog(r->conf.errh, __FILE__, __LINE__, "SSL_ResetHandshake()"); 2322 return HANDLER_ERROR; 2323 } 2324 2325 if (SSL_HandshakeCallback(hctx->ssl, mod_nss_SSLHandshakeCallback, hctx)<0){ 2326 elog(r->conf.errh, __FILE__, __LINE__, "SSL_HandshakeCallback()"); 2327 return HANDLER_ERROR; 2328 } 2329 2330 if (SSL_SNISocketConfigHook(hctx->ssl, mod_nss_SNI, hctx) < 0) { 2331 elog(r->conf.errh, __FILE__, __LINE__, "SSL_SNISocketConfigHook()"); 2332 return HANDLER_ERROR; 2333 } 2334 2335 if (SSL_SetNextProtoCallback(hctx->ssl, mod_nss_alpn_select_cb, hctx) < 0) { 2336 elog(r->conf.errh, __FILE__, __LINE__, "SSL_SetNextProtoCallback()"); 2337 return HANDLER_ERROR; 2338 } 2339 2340 hctx->verify_status = -1; 2341 if (hctx->conf.ssl_verifyclient) { 2342 if (SSL_AuthCertificateHook(hctx->ssl, mod_nss_verify_cb, hctx) < 0) { 2343 elog(r->conf.errh, __FILE__, __LINE__, "SSL_AuthCertificateHook()"); 2344 return HANDLER_ERROR; 2345 } 2346 CERTCertList * const certList = hctx->conf.ssl_ca_dn_file 2347 ? hctx->conf.ssl_ca_dn_file 2348 : hctx->conf.ssl_ca_file; 2349 if (NULL == certList) { 2350 log_error(hctx->r->conf.errh, __FILE__, __LINE__, 2351 "NSS: can't verify client without ssl.verifyclient.ca-file " 2352 "for TLS server name %s", 2353 hctx->r->uri.authority.ptr); /*(might not be set yet if no SNI)*/ 2354 return hctx->conf.ssl_verifyclient_enforce 2355 ? HANDLER_ERROR 2356 : HANDLER_GO_ON; 2357 } 2358 if (SSL_SetTrustAnchors(hctx->ssl, certList) < 0) { 2359 elog(r->conf.errh, __FILE__, __LINE__, "SSL_SetTrustAnchors()"); 2360 return HANDLER_ERROR; 2361 } 2362 SSL_OptionSet(hctx->ssl, SSL_REQUEST_CERTIFICATE, PR_TRUE); 2363 SSL_OptionSet(hctx->ssl, SSL_REQUIRE_CERTIFICATE, 2364 hctx->conf.ssl_verifyclient_enforce 2365 ? SSL_REQUIRE_ALWAYS 2366 : SSL_REQUIRE_NEVER); 2367 } 2368 else { 2369 SSL_OptionSet(hctx->ssl, SSL_REQUEST_CERTIFICATE, PR_FALSE); 2370 SSL_OptionSet(hctx->ssl, SSL_REQUIRE_CERTIFICATE, SSL_REQUIRE_NEVER); 2371 } 2372 2373 return HANDLER_GO_ON; 2374 } 2375 2376 2377 static void 2378 mod_nss_detach(handler_ctx *hctx) 2379 { 2380 /* step aside from further SSL processing 2381 * (note: additional data might be buffered/discarded by this layer) 2382 * (used after handle_connection_shut_wr hook) */ 2383 /* future: might restore prior network_read and network_write fn ptrs */ 2384 mod_nss_io_detach(hctx->ssl); 2385 hctx->con->is_ssl_sock = 0; 2386 /* if called after handle_connection_shut_wr hook, shutdown SHUT_WR */ 2387 if (-1 == hctx->close_notify) shutdown(hctx->con->fd, SHUT_WR); 2388 hctx->close_notify = 1; 2389 } 2390 2391 2392 CONNECTION_FUNC(mod_nss_handle_con_shut_wr) 2393 { 2394 plugin_data *p = p_d; 2395 handler_ctx *hctx = con->plugin_ctx[p->id]; 2396 if (NULL == hctx) return HANDLER_GO_ON; 2397 2398 hctx->close_notify = -2; 2399 if (hctx->handshake) { 2400 mod_nss_close_notify(hctx); 2401 } 2402 else { 2403 mod_nss_detach(hctx); 2404 } 2405 2406 return HANDLER_GO_ON; 2407 } 2408 2409 2410 static int 2411 mod_nss_close_notify (handler_ctx *hctx) 2412 { 2413 if (1 == hctx->close_notify) return -2; 2414 2415 /* note: this sends close_notify TLS alert and calls shutdown() on fd */ 2416 switch (PR_Shutdown(hctx->ssl, PR_SHUTDOWN_SEND)) { 2417 case PR_SUCCESS: 2418 mod_nss_detach(hctx); 2419 return -2; 2420 case PR_FAILURE: 2421 default: 2422 if (PR_GetError() != PR_NOT_CONNECTED_ERROR) 2423 elog(hctx->r->conf.errh, __FILE__, __LINE__, "PR_Shutdown()"); 2424 mod_nss_detach(hctx); 2425 return -1; 2426 } 2427 } 2428 2429 2430 CONNECTION_FUNC(mod_nss_handle_con_close) 2431 { 2432 plugin_data *p = p_d; 2433 handler_ctx *hctx = con->plugin_ctx[p->id]; 2434 if (NULL != hctx) { 2435 con->plugin_ctx[p->id] = NULL; 2436 if (1 != hctx->close_notify) 2437 mod_nss_close_notify(hctx); /*(one final try)*/ 2438 handler_ctx_free(hctx); 2439 } 2440 2441 return HANDLER_GO_ON; 2442 } 2443 2444 2445 __attribute_noinline__ 2446 static void 2447 https_add_ssl_client_cert (request_st * const r, CERTCertificate *peer) 2448 { 2449 char *pem = NSSBase64_EncodeItem(NULL, NULL, 0, &peer->derCert); 2450 if (NULL == pem) return; 2451 uint32_t len = 0; 2452 for (uint32_t i = 0; pem[i]; ++i) { 2453 if (pem[i] != '\r') pem[len++] = pem[i]; /*(translate \r\n to \n)*/ 2454 } 2455 buffer_append_str3( 2456 http_header_env_set_ptr(r, CONST_STR_LEN("SSL_CLIENT_CERT")), 2457 CONST_STR_LEN(PEM_BEGIN_CERT"\n"), 2458 pem, len, 2459 CONST_STR_LEN("\n"PEM_END_CERT"\n")); 2460 PORT_Free(pem); 2461 } 2462 2463 2464 static void 2465 https_add_ssl_client_subject (request_st * const r, CERTName * const subj) 2466 { 2467 /* add components of client Subject DN */ 2468 /* not complete list; NSS does not expose enough of lib/certdb/alg1485.c 2469 * for friendly names, though we could consider using CERT_GetOidString() 2470 * and CERT_RFC1485_EscapeAndQuote() */ 2471 static const 2472 struct { const char *tag; uint32_t tlen; char *(*fn)(const CERTName *); } 2473 comp[] = { 2474 { CONST_STR_LEN("CN"), CERT_GetCommonName }, 2475 { CONST_STR_LEN("ST"), CERT_GetStateName }, 2476 { CONST_STR_LEN("O"), CERT_GetOrgName }, 2477 { CONST_STR_LEN("OU"), CERT_GetOrgUnitName }, 2478 { CONST_STR_LEN("C"), CERT_GetCountryName }, 2479 { CONST_STR_LEN("L"), CERT_GetLocalityName }, 2480 { CONST_STR_LEN("UID"), CERT_GetCertUid }, 2481 { CONST_STR_LEN("emailAddress"), CERT_GetCertEmailAddress }, 2482 { CONST_STR_LEN("DC"), CERT_GetDomainComponentName }, 2483 }; 2484 const size_t prelen = sizeof("SSL_CLIENT_S_DN_")-1; 2485 char key[64] = "SSL_CLIENT_S_DN_"; 2486 for (uint32_t i = 0; i < sizeof(comp)/sizeof(*comp); ++i) { 2487 char *s = comp[i].fn(subj); 2488 if (NULL == s) continue; 2489 2490 unsigned int n; 2491 unsigned char c; 2492 for (n = 0; (c = ((unsigned char *)s)[n]); ++n) { 2493 if (c < 32 || c == 127 || (c > 128 && c < 160)) s[n] = '?'; 2494 } 2495 2496 /*if (prelen+comp[i].tlen >= sizeof(key)) continue;*//*(not possible)*/ 2497 memcpy(key+prelen, comp[i].tag, comp[i].tlen); /*(not '\0'-terminated)*/ 2498 http_header_env_set(r, key, prelen+comp[i].tlen, s, n); 2499 2500 PR_Free(s); 2501 } 2502 } 2503 2504 2505 __attribute_cold__ 2506 static void 2507 https_add_ssl_client_verify_err (buffer * const b, unsigned int status) 2508 { 2509 const char *s = PR_ErrorToName(status); 2510 if (s) 2511 buffer_append_string_len(b, s, strlen(s)); 2512 buffer_append_string_len(b, CONST_STR_LEN(":")); 2513 s = PR_ErrorToString(status, PR_LANGUAGE_I_DEFAULT); 2514 buffer_append_string_len(b, s, strlen(s)); 2515 } 2516 2517 2518 __attribute_noinline__ 2519 static void 2520 https_add_ssl_client_entries (request_st * const r, handler_ctx * const hctx) 2521 { 2522 PRFileDesc *ssl = hctx->ssl; 2523 CERTCertificate *crt = NULL; 2524 buffer *vb = http_header_env_set_ptr(r, CONST_STR_LEN("SSL_CLIENT_VERIFY")); 2525 2526 if (hctx->verify_status != -1) 2527 crt = SSL_PeerCertificate(ssl); 2528 if (NULL == crt) { /* || hctx->verify_status == -1) */ 2529 /*(e.g. no cert, or verify result not available)*/ 2530 buffer_copy_string_len(vb, CONST_STR_LEN("NONE")); 2531 return; 2532 } 2533 else if (0 != hctx->verify_status) { 2534 buffer_copy_string_len(vb, CONST_STR_LEN("FAILED:")); 2535 https_add_ssl_client_verify_err(vb, hctx->verify_status); 2536 CERT_DestroyCertificate(crt); 2537 return; 2538 } 2539 else { 2540 buffer_copy_string_len(vb, CONST_STR_LEN("SUCCESS")); 2541 } 2542 2543 char *s = CERT_NameToAsciiInvertible(&crt->subject, CERT_N2A_STRICT); 2544 if (s) { 2545 http_header_env_set(r, 2546 CONST_STR_LEN("SSL_CLIENT_S_DN"), 2547 s, strlen(s)); 2548 PR_Free(s); 2549 } 2550 2551 https_add_ssl_client_subject(r, &crt->subject); 2552 2553 s = (char *)crt->serialNumber.data; 2554 size_t i = 0; /* skip leading 0's per Distinguished Encoding Rules (DER) */ 2555 while (i < crt->serialNumber.len && s[i] == 0) ++i; 2556 if (i == crt->serialNumber.len) --i; 2557 buffer_append_string_encoded_hex_uc( 2558 http_header_env_set_ptr(r, CONST_STR_LEN("SSL_CLIENT_M_SERIAL")), 2559 s+i, crt->serialNumber.len-i); 2560 2561 if (!buffer_string_is_empty(hctx->conf.ssl_verifyclient_username)) { 2562 /* pick one of the exported values as "REMOTE_USER", for example 2563 * ssl.verifyclient.username = "SSL_CLIENT_S_DN_UID" 2564 * or 2565 * ssl.verifyclient.username = "SSL_CLIENT_S_DN_emailAddress" 2566 */ 2567 const buffer *varname = hctx->conf.ssl_verifyclient_username; 2568 vb = http_header_env_get(r, CONST_BUF_LEN(varname)); 2569 if (vb) { /* same as http_auth.c:http_auth_setenv() */ 2570 http_header_env_set(r, 2571 CONST_STR_LEN("REMOTE_USER"), 2572 CONST_BUF_LEN(vb)); 2573 http_header_env_set(r, 2574 CONST_STR_LEN("AUTH_TYPE"), 2575 CONST_STR_LEN("SSL_CLIENT_VERIFY")); 2576 } 2577 } 2578 2579 if (hctx->conf.ssl_verifyclient_export_cert) 2580 https_add_ssl_client_cert(r, crt); 2581 2582 CERT_DestroyCertificate(crt); 2583 } 2584 2585 2586 static void 2587 http_cgi_ssl_env (request_st * const r, handler_ctx * const hctx) 2588 { 2589 PRFileDesc *ssl = hctx->ssl; 2590 2591 /* (quite a bit of work just to get protocol version) 2592 * (could not find better NSS interface) */ 2593 SSLChannelInfo inf; 2594 if (SSL_GetChannelInfo(ssl, &inf, sizeof(inf)) < 0) 2595 inf.protocolVersion = 0; 2596 2597 size_t n; 2598 const char *s = NULL; 2599 switch (inf.protocolVersion) { 2600 case SSL_LIBRARY_VERSION_TLS_1_3: s="TLSv1.3";n=sizeof("TLSv1.3")-1;break; 2601 case SSL_LIBRARY_VERSION_TLS_1_2: s="TLSv1.2";n=sizeof("TLSv1.2")-1;break; 2602 case SSL_LIBRARY_VERSION_TLS_1_1: s="TLSv1.1";n=sizeof("TLSv1.1")-1;break; 2603 case SSL_LIBRARY_VERSION_TLS_1_0: s="TLSv1.0";n=sizeof("TLSv1.0")-1;break; 2604 case SSL_LIBRARY_VERSION_3_0: s="SSLv3.0";n=sizeof("SSLv3.0")-1;break; 2605 case SSL_LIBRARY_VERSION_2: s="SSLv2.0";n=sizeof("SSLv2.0")-1;break; 2606 default: break; 2607 } 2608 if (s) http_header_env_set(r, CONST_STR_LEN("SSL_PROTOCOL"), s, n); 2609 2610 char *cipher; 2611 int algkeysize; 2612 int usekeysize; 2613 if (SSL_SecurityStatus(ssl, NULL, &cipher, &algkeysize, &usekeysize, 2614 NULL, NULL) < 0) 2615 return; 2616 2617 if (cipher) { 2618 n = strlen(cipher); 2619 http_header_env_set(r, CONST_STR_LEN("SSL_CIPHER"), cipher, n); 2620 PR_Free(cipher); 2621 } 2622 2623 /* SSL_CIPHER_ALGKEYSIZE - Number of cipher bits (possible) */ 2624 /* SSL_CIPHER_USEKEYSIZE - Number of cipher bits (actually used) */ 2625 char buf[LI_ITOSTRING_LENGTH]; 2626 http_header_env_set(r, CONST_STR_LEN("SSL_CIPHER_USEKEYSIZE"), 2627 buf, li_utostrn(buf, sizeof(buf), usekeysize)); 2628 http_header_env_set(r, CONST_STR_LEN("SSL_CIPHER_ALGKEYSIZE"), 2629 buf, li_utostrn(buf, sizeof(buf), algkeysize)); 2630 } 2631 2632 2633 REQUEST_FUNC(mod_nss_handle_request_env) 2634 { 2635 plugin_data *p = p_d; 2636 /* simple flag for request_env_patched */ 2637 if (r->plugin_ctx[p->id]) return HANDLER_GO_ON; 2638 handler_ctx *hctx = r->con->plugin_ctx[p->id]; 2639 if (NULL == hctx) return HANDLER_GO_ON; 2640 r->plugin_ctx[p->id] = (void *)(uintptr_t)1u; 2641 2642 http_cgi_ssl_env(r, hctx); 2643 if (hctx->conf.ssl_verifyclient) { 2644 https_add_ssl_client_entries(r, hctx); 2645 } 2646 2647 return HANDLER_GO_ON; 2648 } 2649 2650 2651 REQUEST_FUNC(mod_nss_handle_uri_raw) 2652 { 2653 /* mod_nss must be loaded prior to mod_auth 2654 * if mod_nss is configured to set REMOTE_USER based on client cert */ 2655 /* mod_nss must be loaded after mod_extforward 2656 * if mod_nss config is based on lighttpd.conf remote IP conditional 2657 * using remote IP address set by mod_extforward, *unless* PROXY protocol 2658 * is enabled with extforward.hap-PROXY = "enable", in which case the 2659 * reverse is true: mod_extforward must be loaded after mod_nss */ 2660 plugin_data *p = p_d; 2661 handler_ctx *hctx = r->con->plugin_ctx[p->id]; 2662 if (NULL == hctx) return HANDLER_GO_ON; 2663 2664 mod_nss_patch_config(r, &hctx->conf); 2665 if (hctx->conf.ssl_verifyclient) { 2666 mod_nss_handle_request_env(r, p); 2667 } 2668 2669 return HANDLER_GO_ON; 2670 } 2671 2672 2673 REQUEST_FUNC(mod_nss_handle_request_reset) 2674 { 2675 plugin_data *p = p_d; 2676 r->plugin_ctx[p->id] = NULL; /* simple flag for request_env_patched */ 2677 return HANDLER_GO_ON; 2678 } 2679 2680 2681 TRIGGER_FUNC(mod_nss_handle_trigger) { 2682 const plugin_data * const p = p_d; 2683 const time_t cur_ts = log_epoch_secs; 2684 if (cur_ts & 0x3f) return HANDLER_GO_ON; /*(continue once each 64 sec)*/ 2685 2686 mod_nss_refresh_stapling_files(srv, p, cur_ts); 2687 2688 return HANDLER_GO_ON; 2689 } 2690 2691 2692 int mod_nss_plugin_init (plugin *p); 2693 int mod_nss_plugin_init (plugin *p) 2694 { 2695 p->version = LIGHTTPD_VERSION_ID; 2696 p->name = "nss"; 2697 p->init = mod_nss_init; 2698 p->cleanup = mod_nss_free; 2699 p->priv_defaults= mod_nss_set_defaults; 2700 2701 p->handle_connection_accept = mod_nss_handle_con_accept; 2702 p->handle_connection_shut_wr = mod_nss_handle_con_shut_wr; 2703 p->handle_connection_close = mod_nss_handle_con_close; 2704 p->handle_uri_raw = mod_nss_handle_uri_raw; 2705 p->handle_request_env = mod_nss_handle_request_env; 2706 p->handle_request_reset = mod_nss_handle_request_reset; 2707 p->handle_trigger = mod_nss_handle_trigger; 2708 2709 return 0; 2710 } 2711 2712 2713 static int 2714 mod_nss_ssl_conf_curves(server *srv, plugin_config_socket *s, const buffer *curvelist) 2715 { 2716 log_error(srv->errh, __FILE__, __LINE__, 2717 "NSS: ignoring Curves/Groups; not implemented (%s)", 2718 curvelist->ptr); 2719 UNUSED(s); 2720 UNUSED(curvelist); 2721 2722 /* XXX: TODO: see ssl/sslt.h enum SSLNamedGroup */ 2723 2724 return 1; 2725 } 2726 2727 2728 static PRUint16 2729 mod_nss_ssl_conf_proto_val (server *srv, plugin_config_socket *s, const buffer *b, int max) 2730 { 2731 /* use of SSL v3 should be avoided, and SSL v2 is not supported here */ 2732 /*(choosing not to support s->ssl_use_sslv2 or SSL_LIBRARY_VERSION_2 here)*/ 2733 if (NULL == b) /* default: min TLSv1.2, max TLSv1.3 */ 2734 return max ? SSL_LIBRARY_VERSION_TLS_1_3 : SSL_LIBRARY_VERSION_TLS_1_2; 2735 else if (buffer_eq_icase_slen(b, CONST_STR_LEN("None"))) /*"disable" limit*/ 2736 return max 2737 ? SSL_LIBRARY_VERSION_TLS_1_3 2738 : (s->ssl_use_sslv3 2739 ? SSL_LIBRARY_VERSION_3_0 2740 : SSL_LIBRARY_VERSION_TLS_1_0); 2741 else if (buffer_eq_icase_slen(b, CONST_STR_LEN("SSLv3"))) 2742 return SSL_LIBRARY_VERSION_3_0; 2743 else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.0"))) 2744 return SSL_LIBRARY_VERSION_TLS_1_0; 2745 else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.1"))) 2746 return SSL_LIBRARY_VERSION_TLS_1_1; 2747 else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.2"))) 2748 return SSL_LIBRARY_VERSION_TLS_1_2; 2749 else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.3"))) 2750 return SSL_LIBRARY_VERSION_TLS_1_3; 2751 else { 2752 if (buffer_eq_icase_slen(b, CONST_STR_LEN("DTLSv1")) 2753 || buffer_eq_icase_slen(b, CONST_STR_LEN("DTLSv1.2"))) 2754 log_error(srv->errh, __FILE__, __LINE__, 2755 "NSS: ssl.openssl.ssl-conf-cmd %s %s ignored", 2756 max ? "MaxProtocol" : "MinProtocol", b->ptr); 2757 else 2758 log_error(srv->errh, __FILE__, __LINE__, 2759 "NSS: ssl.openssl.ssl-conf-cmd %s %s invalid; ignored", 2760 max ? "MaxProtocol" : "MinProtocol", b->ptr); 2761 } 2762 return max ? SSL_LIBRARY_VERSION_TLS_1_3 : SSL_LIBRARY_VERSION_TLS_1_2; 2763 } 2764 2765 2766 static void 2767 mod_nss_ssl_conf_proto (server *srv, plugin_config_socket *s, const buffer *minb, const buffer *maxb) 2768 { 2769 s->protos.min = mod_nss_ssl_conf_proto_val(srv, s, minb, 0); 2770 s->protos.max = mod_nss_ssl_conf_proto_val(srv, s, maxb, 1); 2771 /* XXX: could check values against SSL_VersionRangeGetSupported() */ 2772 } 2773 2774 2775 /** 2776 * Apache mod_nss 2777 * https://pagure.io/mod_nss.git 2778 * 2779 * (with minor modifications to compile in lighttpd) 2780 */ 2781 2782 #define ap_log_error(APLOG_MARK, APLOG_INFO, rc, errh, ...) \ 2783 log_error(errh, __FILE__, __LINE__, __VA_ARGS__) 2784 typedef log_error_st server_rec; 2785 2786 2787 /* 2788 * mod_nss/nss_engine_cipher.h 2789 */ 2790 2791 /* Copyright 2001-2004 The Apache Software Foundation 2792 * 2793 * Licensed under the Apache License, Version 2.0 (the "License"); 2794 * you may not use this file except in compliance with the License. 2795 * You may obtain a copy of the License at 2796 * 2797 * http://www.apache.org/licenses/LICENSE-2.0 2798 * 2799 * Unless required by applicable law or agreed to in writing, software 2800 * distributed under the License is distributed on an "AS IS" BASIS, 2801 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2802 * See the License for the specific language governing permissions and 2803 * limitations under the License. 2804 */ 2805 2806 /* 2807 * Cipher definitions 2808 */ 2809 typedef struct 2810 { 2811 const char *name; /* The mod_nss cipher name */ 2812 PRInt32 num; /* The cipher id */ 2813 const char *openssl_name; /* The OpenSSL cipher name */ 2814 PRInt32 attr; /* cipher attributes: algorithms, etc */ 2815 PRInt32 version; /* protocol version valid for this cipher */ 2816 PRInt32 strength; /* LOW, MEDIUM, HIGH */ 2817 PRInt32 bits; /* bits of strength */ 2818 PRInt32 alg_bits; /* bits of the algorithm */ 2819 const char *alias; /* Other names, usually typos. Right now a 2820 single string but could be CSV */ 2821 } cipher_properties; 2822 2823 /* OpenSSL-compatible cipher attributes */ 2824 #define SSL_kRSA 0x00000001L 2825 #define SSL_aRSA 0x00000002L 2826 #define SSL_aDSS 0x00000004L 2827 #define SSL_DSS SSL_aDSS 2828 #define SSL_eNULL 0x00000008L 2829 #define SSL_DES 0x00000010L 2830 #define SSL_3DES 0x00000020L 2831 #define SSL_RC4 0x00000040L 2832 #define SSL_RC2 0x00000080L 2833 #define SSL_MD5 0x00000200L 2834 #define SSL_SHA1 0x00000400L 2835 #define SSL_SHA SSL_SHA1 2836 #define SSL_RSA (SSL_kRSA) 2837 #define SSL_kEDH 0x00000800L 2838 #define SSL_EDH (SSL_kDHE) 2839 #define SSL_aNULL 0x00001000L 2840 #define SSL_kECDHE 0x00002000L 2841 #define SSL_AECDH 0x00004000L 2842 #define SSL_aECDSA 0x00008000L 2843 #define SSL_kECDHr 0x00010000L 2844 #define SSL_kEECDH 0x00020000L 2845 #define SSL_ECDH (SSL_kECDHE|SSL_kECDHr|SSL_kEECDH) 2846 #define SSL_EECDH (SSL_kEECDH) 2847 #define SSL_ADH (SSL_kEDH) 2848 #define SSL_kDHE 0x00040000L 2849 #define SSL_DHE (SSL_kDHE) 2850 2851 /* cipher strength */ 2852 #define SSL_STRONG_NONE 0x00000001L 2853 #define SSL_NULL 0x00000002L 2854 #define SSL_EXPORT40 0x00000004L 2855 #define SSL_EXPORT56 0x00000008L 2856 #define SSL_LOW 0x00000010L 2857 #define SSL_MEDIUM 0x00000020L 2858 #define SSL_HIGH 0x00000040L 2859 2860 #define SSL_CHACHA20POLY1305 0x00080000L 2861 #define SSL_AES128 0x00400000L 2862 #define SSL_AES256 0x00800000L 2863 #define SSL_CAMELLIA128 0x01000000L 2864 #define SSL_CAMELLIA256 0x02000000L 2865 #define SSL_AES128GCM 0x04000000L 2866 #define SSL_AES256GCM 0x08000000L 2867 #define SSL_SHA256 0x10000000L 2868 #define SSL_SHA384 0x20000000L 2869 #define SSL_AEAD 0x40000000L 2870 2871 #define SSL_AES (SSL_AES128|SSL_AES256|SSL_AES128GCM|SSL_AES256GCM) 2872 #define SSL_CAMELLIA (SSL_CAMELLIA128|SSL_CAMELLIA256) 2873 2874 /* Protocols */ 2875 #define SSLV2 0x00000001L 2876 #define SSLV3 0x00000002L 2877 #define TLSV1 SSLV3 2878 #define TLSV1_2 0x00000004L 2879 #define TLSV1_3 0x00000008L 2880 2881 #if 0 2882 /* the table itself is defined in nss_engine_cipher.c */ 2883 #if 0 2884 #ifdef NSS_ENABLE_ECC 2885 # ifdef ENABLE_SHA384 2886 # define ciphernum 54 2887 # else 2888 # define ciphernum 49 2889 # endif 2890 #else 2891 #define ciphernum 20 2892 #endif 2893 #endif 2894 2895 extern int ciphernum; 2896 2897 /* function prototypes */ 2898 int nss_parse_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum]); 2899 int countciphers(PRBool cipher_state[ciphernum], int version); 2900 #endif 2901 2902 /* I chose an arbitrary cipher to test the existence for to handle older 2903 * versions of NSS, at least back to 3.15.1 2904 */ 2905 #ifndef TLS_NULL_WITH_NULL_NULL 2906 #define TLS_NULL_WITH_NULL_NULL SSL_NULL_WITH_NULL_NULL 2907 #define TLS_RSA_WITH_NULL_MD5 SSL_RSA_WITH_NULL_MD5 2908 #define TLS_RSA_WITH_NULL_SHA SSL_RSA_WITH_NULL_SHA 2909 #define TLS_RSA_EXPORT_WITH_RC4_40_MD5 SSL_RSA_EXPORT_WITH_RC4_40_MD5 2910 #define TLS_RSA_WITH_RC4_128_MD5 SSL_RSA_WITH_RC4_128_MD5 2911 #define TLS_RSA_WITH_RC4_128_SHA SSL_RSA_WITH_RC4_128_SHA 2912 #define TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 2913 #define TLS_RSA_WITH_IDEA_CBC_SHA SSL_RSA_WITH_IDEA_CBC_SHA 2914 #define TLS_RSA_EXPORT_WITH_DES40_CBC_SHA SSL_RSA_EXPORT_WITH_DES40_CBC_SHA 2915 #define TLS_RSA_WITH_DES_CBC_SHA SSL_RSA_WITH_DES_CBC_SHA 2916 #define TLS_RSA_WITH_3DES_EDE_CBC_SHA SSL_RSA_WITH_3DES_EDE_CBC_SHA 2917 #endif 2918 2919 2920 /* 2921 * mod_nss/nss_engine_cipher.c 2922 */ 2923 2924 /* Copyright 2001-2004 The Apache Software Foundation 2925 * 2926 * Licensed under the Apache License, Version 2.0 (the "License"); 2927 * you may not use this file except in compliance with the License. 2928 * You may obtain a copy of the License at 2929 * 2930 * http://www.apache.org/licenses/LICENSE-2.0 2931 * 2932 * Unless required by applicable law or agreed to in writing, software 2933 * distributed under the License is distributed on an "AS IS" BASIS, 2934 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2935 * See the License for the specific language governing permissions and 2936 * limitations under the License. 2937 */ 2938 #include <sys/types.h> 2939 #include <string.h> 2940 #include <strings.h> 2941 #include <stdio.h> 2942 #include <stdlib.h> 2943 #ifndef NSS_VER_INCLUDE 2944 #include <nss/sslproto.h> 2945 #else 2946 #include <nss3/sslproto.h> 2947 #endif 2948 2949 /* Cipher actions */ 2950 #define PERMANENTLY_DISABLE_CIPHER -1 /* !CIPHER */ 2951 #define SUBTRACT_CIPHER 0 /* -CIPHER */ 2952 #define ENABLE_CIPHER 1 /* CIPHER */ 2953 #define REORDER_CIPHER 2 /* +CIPHER */ 2954 2955 ///* ciphernum is defined in nss_engine_cipher.h */ 2956 static const cipher_properties ciphers_def[] = 2957 { 2958 {"rsa_null_md5", TLS_RSA_WITH_NULL_MD5, "NULL-MD5", SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_MD5, SSLV3, SSL_STRONG_NONE, 0, 0, NULL}, 2959 {"rsa_null_sha", TLS_RSA_WITH_NULL_SHA, "NULL-SHA", SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_SHA1, SSLV3, SSL_STRONG_NONE, 0, 0, NULL}, 2960 {"rsa_rc4_40_md5", TLS_RSA_EXPORT_WITH_RC4_40_MD5, "EXP-RC4-MD5", SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSLV3, SSL_EXPORT40, 40, 128, NULL}, 2961 {"rsa_rc4_128_md5", TLS_RSA_WITH_RC4_128_MD5, "RC4-MD5", SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSLV3, SSL_MEDIUM, 128, 128, NULL}, 2962 {"rsa_rc4_128_sha", TLS_RSA_WITH_RC4_128_SHA, "RC4-SHA", SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA1, SSLV3, SSL_MEDIUM, 128, 128, NULL}, 2963 {"rsa_rc2_40_md5", TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, "EXP-RC2-CBC-MD5", SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSLV3, SSL_EXPORT40, 40, 128, NULL}, 2964 /* TLS_RSA_EXPORT_WITH_DES40_CBC_SHA not implemented 0x0008 */ 2965 {"rsa_des_sha", TLS_RSA_WITH_DES_CBC_SHA, "DES-CBC-SHA", SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1, SSLV3, SSL_LOW, 56, 56, NULL}, 2966 {"rsa_3des_sha", TLS_RSA_WITH_3DES_EDE_CBC_SHA, "DES-CBC3-SHA", SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_SHA1, SSLV3, SSL_MEDIUM, 168, 168, NULL}, 2967 //#ifdef ENABLE_SERVER_DHE 2968 {"dhe_rsa_des_sha", TLS_DHE_RSA_WITH_DES_CBC_SHA, "EDH-RSA-DES-CBC-SHA", SSL_kDHE|SSL_aRSA|SSL_DES|SSL_SHA1, SSLV3, SSL_LOW, 56, 56, NULL}, 2969 //#endif 2970 {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA, "AES128-SHA", SSL_kRSA|SSL_aRSA|SSL_AES128|SSL_SHA1, TLSV1, SSL_HIGH, 128, 128, NULL}, 2971 {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA, "AES256-SHA", SSL_kRSA|SSL_aRSA|SSL_AES256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256, NULL}, 2972 {"null_sha_256", TLS_RSA_WITH_NULL_SHA256, "NULL-SHA256", SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_SHA256, TLSV1_2, SSL_STRONG_NONE, 0, 0, NULL}, 2973 {"aes_128_sha_256", TLS_RSA_WITH_AES_128_CBC_SHA256, "AES128-SHA256", SSL_kRSA|SSL_aRSA|SSL_AES128|SSL_SHA256, TLSV1_2, SSL_HIGH, 128, 128, NULL}, 2974 {"aes_256_sha_256", TLS_RSA_WITH_AES_256_CBC_SHA256, "AES256-SHA256", SSL_kRSA|SSL_aRSA|SSL_AES256|SSL_SHA256, TLSV1_2, SSL_HIGH, 256, 256, NULL}, 2975 {"camellia_128_sha", TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "CAMELLIA128-SHA", SSL_kRSA|SSL_aRSA|SSL_CAMELLIA128|SSL_SHA1, TLSV1, SSL_HIGH, 128, 128, "camelia_128_sha"}, 2976 {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, "EXP1024-DES-CBC-SHA", SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1, TLSV1, SSL_EXPORT56, 56, 56, NULL}, 2977 {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, "EXP1024-RC4-SHA", SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA1, TLSV1, SSL_EXPORT56, 56, 128, NULL}, 2978 {"camellia_256_sha", TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "CAMELLIA256-SHA", SSL_kRSA|SSL_aRSA|SSL_CAMELLIA256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256, "camelia_256_sha"}, 2979 //#ifdef ENABLE_GCM 2980 {"rsa_aes_128_gcm_sha_256", TLS_RSA_WITH_AES_128_GCM_SHA256, "AES128-GCM-SHA256", SSL_kRSA|SSL_aRSA|SSL_AES128GCM|SSL_AEAD, TLSV1_2, SSL_HIGH, 128, 128, NULL}, 2981 //#endif 2982 //#ifdef ENABLE_SHA384 2983 {"rsa_aes_256_gcm_sha_384", TLS_RSA_WITH_AES_256_GCM_SHA384, "AES256-GCM-SHA384", SSL_kRSA|SSL_aRSA|SSL_AES256GCM|SSL_AEAD, TLSV1_2, SSL_HIGH, 256, 256, NULL}, 2984 //#endif 2985 {"fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, "FIPS-DES-CBC3-SHA", SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_SHA1, SSLV3, SSL_MEDIUM, 112, 168, NULL}, 2986 {"fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA, "FIPS-DES-CBC-SHA", SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1, SSLV3, SSL_LOW, 56, 56, NULL}, 2987 //#ifdef ENABLE_SERVER_DHE 2988 {"dhe_rsa_3des_sha", TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "DHE-RSA-DES-CBC3-SHA", SSL_kDHE|SSL_aRSA|SSL_3DES|SSL_SHA1, TLSV1, SSL_MEDIUM, 112, 168, NULL}, 2989 {"dhe_rsa_aes_128_sha", TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "DHE-RSA-AES128-SHA", SSL_kDHE|SSL_aRSA|SSL_AES128|SSL_SHA1, TLSV1, SSL_HIGH, 128, 128, NULL}, 2990 {"dhe_rsa_aes_256_sha", TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "DHE-RSA-AES256-SHA", SSL_kDHE|SSL_aRSA|SSL_AES256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256, NULL}, 2991 {"dhe_rsa_camellia_128_sha", TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "DHE-RSA-CAMELLIA128-SHA", SSL_kDHE|SSL_aRSA|SSL_CAMELLIA128|SSL_SHA1, TLSV1, SSL_HIGH, 128, 128, NULL}, 2992 {"dhe_rsa_camellia_256_sha", TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "DHE-RSA-CAMELLIA256-SHA", SSL_kDHE|SSL_aRSA|SSL_CAMELLIA256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256, NULL}, 2993 {"dhe_rsa_aes_128_sha_256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "DHE-RSA-AES128-SHA256", SSL_kDHE|SSL_aRSA|SSL_AES128|SSL_SHA256, TLSV1_2, SSL_HIGH, 128, 128, "dhe_rsa_aes_128_sha256"}, 2994 {"dhe_rsa_aes_256_sha_256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "DHE-RSA-AES256-SHA256", SSL_kDHE|SSL_aRSA|SSL_AES256|SSL_SHA256, TLSV1_2, SSL_HIGH, 256, 256, "dhe_rsa_aes_256_sha256"}, 2995 //#ifdef ENABLE_GCM 2996 {"dhe_rsa_aes_128_gcm_sha_256", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "DHE-RSA-AES128-GCM-SHA256", SSL_kDHE|SSL_aRSA|SSL_AES128GCM|SSL_AEAD, TLSV1_2, SSL_HIGH, 128, 128, NULL}, 2997 //#endif 2998 //#ifdef ENABLE_SHA384 2999 {"dhe_rsa_aes_256_gcm_sha_384", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "DHE-RSA-AES256-GCM-SHA384", SSL_kDHE|SSL_aRSA|SSL_AES256GCM|SSL_AEAD, TLSV1_2, SSL_HIGH, 256, 256, NULL}, 3000 //#endif 3001 //#endif /* ENABLE_SERVER_DHE */ 3002 //#ifdef NSS_ENABLE_ECC 3003 {"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA, "ECDH-ECDSA-NULL-SHA", SSL_kECDHE|SSL_AECDH|SSL_eNULL|SSL_SHA1, TLSV1, SSL_STRONG_NONE, 0, 0, NULL}, 3004 {"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "ECDH-ECDSA-RC4-SHA", SSL_kECDHE|SSL_AECDH|SSL_RC4|SSL_SHA1, TLSV1, SSL_MEDIUM, 128, 128, NULL}, 3005 {"ecdh_ecdsa_3des_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "ECDH-ECDSA-DES-CBC3-SHA", SSL_kECDHE|SSL_AECDH|SSL_3DES|SSL_SHA1, TLSV1, SSL_MEDIUM, 112, 168, NULL}, 3006 {"ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "ECDH-ECDSA-AES128-SHA", SSL_kECDHE|SSL_AECDH|SSL_AES128|SSL_SHA1, TLSV1, SSL_HIGH, 128, 128, NULL}, 3007 {"ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "ECDH-ECDSA-AES256-SHA", SSL_kECDHE|SSL_AECDH|SSL_AES256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256, NULL}, 3008 {"ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA, "ECDHE-ECDSA-NULL-SHA", SSL_kEECDH|SSL_aECDSA|SSL_eNULL|SSL_SHA1, TLSV1, SSL_STRONG_NONE, 0, 0, NULL}, 3009 {"ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "ECDHE-ECDSA-RC4-SHA", SSL_kEECDH|SSL_aECDSA|SSL_RC4|SSL_SHA1, TLSV1, SSL_MEDIUM, 128, 128, NULL}, 3010 {"ecdhe_ecdsa_3des_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "ECDHE-ECDSA-DES-CBC3-SHA", SSL_kEECDH|SSL_aECDSA|SSL_3DES|SSL_SHA1, TLSV1, SSL_MEDIUM, 112, 168, NULL}, 3011 {"ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "ECDHE-ECDSA-AES128-SHA", SSL_kEECDH|SSL_aECDSA|SSL_AES128|SSL_SHA1, TLSV1, SSL_HIGH, 128, 128, NULL}, 3012 {"ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "ECDHE-ECDSA-AES256-SHA", SSL_kEECDH|SSL_aECDSA|SSL_AES256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256, NULL}, 3013 {"ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA, "ECDH-RSA-NULL-SHA", SSL_kECDHr|SSL_AECDH|SSL_eNULL|SSL_SHA1, TLSV1, SSL_STRONG_NONE, 0, 0, NULL}, 3014 {"ecdh_rsa_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA, "ECDH-RSA-RC4-SHA", SSL_kECDHr|SSL_AECDH|SSL_RC4|SSL_SHA1, TLSV1, SSL_MEDIUM, 128, 128, NULL}, 3015 {"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "ECDH-RSA-DES-CBC3-SHA", SSL_kECDHr|SSL_AECDH|SSL_3DES|SSL_SHA1, TLSV1, SSL_MEDIUM, 112, 168, NULL}, 3016 {"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "ECDH-RSA-AES128-SHA", SSL_kECDHr|SSL_AECDH|SSL_AES128|SSL_SHA1, TLSV1, SSL_HIGH, 128, 128, NULL}, 3017 {"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "ECDH-RSA-AES256-SHA", SSL_kECDHr|SSL_AECDH|SSL_AES256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256, NULL}, 3018 {"ecdhe_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA, "ECDHE-RSA-NULL-SHA", SSL_kEECDH|SSL_aRSA|SSL_eNULL|SSL_SHA1, TLSV1, SSL_STRONG_NONE, 0, 0, NULL}, 3019 {"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA, "ECDHE-RSA-RC4-SHA", SSL_kEECDH|SSL_aRSA|SSL_RC4|SSL_SHA1, TLSV1, SSL_MEDIUM, 128, 128, NULL}, 3020 {"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "ECDHE-RSA-DES-CBC3-SHA", SSL_kEECDH|SSL_aRSA|SSL_3DES|SSL_SHA1, TLSV1, SSL_MEDIUM, 112, 168, NULL}, 3021 {"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "ECDHE-RSA-AES128-SHA", SSL_kEECDH|SSL_aRSA|SSL_AES128|SSL_SHA1, TLSV1, SSL_HIGH, 128, 128, NULL}, 3022 {"ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "ECDHE-RSA-AES256-SHA", SSL_kEECDH|SSL_aRSA|SSL_AES256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256, NULL}, 3023 {"ecdh_anon_null_sha", TLS_ECDH_anon_WITH_NULL_SHA, "AECDH-NULL-SHA", SSL_kEECDH|SSL_aNULL|SSL_eNULL|SSL_SHA1, TLSV1, SSL_STRONG_NONE, 0, 0, NULL}, 3024 {"ecdh_anon_rc4_128sha", TLS_ECDH_anon_WITH_RC4_128_SHA, "AECDH-RC4-SHA", SSL_kEECDH|SSL_aNULL|SSL_RC4|SSL_SHA1, TLSV1, SSL_MEDIUM, 128, 128, NULL}, 3025 {"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, "AECDH-DES-CBC3-SHA", SSL_kEECDH|SSL_aNULL|SSL_3DES|SSL_SHA1, TLSV1, SSL_MEDIUM, 112, 168, NULL}, 3026 {"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA, "AECDH-AES128-SHA", SSL_kEECDH|SSL_aNULL|SSL_AES128|SSL_SHA1, TLSV1, SSL_HIGH, 128, 128, NULL}, 3027 {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA, "AECDH-AES256-SHA", SSL_kEECDH|SSL_aNULL|SSL_AES256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256, NULL}, 3028 {"ecdhe_ecdsa_aes_128_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "ECDHE-ECDSA-AES128-SHA256", SSL_kEECDH|SSL_aECDSA|SSL_AES128|SSL_SHA256, TLSV1_2, SSL_HIGH, 128, 128, NULL}, 3029 {"ecdhe_rsa_aes_128_sha_256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "ECDHE-RSA-AES128-SHA256", SSL_kEECDH|SSL_aRSA|SSL_AES128|SSL_SHA256, TLSV1_2, SSL_HIGH, 128, 128, NULL}, 3030 //#ifdef ENABLE_GCM 3031 {"ecdhe_ecdsa_aes_128_gcm_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "ECDHE-ECDSA-AES128-GCM-SHA256", SSL_kEECDH|SSL_aECDSA|SSL_AES128GCM|SSL_AEAD, TLSV1_2, SSL_HIGH, 128, 128, NULL}, 3032 //#endif 3033 //#ifdef ENABLE_SHA384 3034 {"ecdhe_ecdsa_aes_256_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "ECDHE-ECDSA-AES256-SHA384", SSL_kEECDH|SSL_aECDSA|SSL_AES256|SSL_SHA384, TLSV1_2, SSL_HIGH, 256, 256, NULL}, 3035 {"ecdhe_rsa_aes_256_sha_384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "ECDHE-RSA-AES256-SHA384", SSL_kEECDH|SSL_aRSA|SSL_AES256|SSL_SHA384, TLSV1_2, SSL_HIGH, 256, 256, NULL}, 3036 {"ecdhe_ecdsa_aes_256_gcm_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "ECDHE-ECDSA-AES256-GCM-SHA384", SSL_kEECDH|SSL_aECDSA|SSL_AES256GCM|SSL_AEAD, TLSV1_2, SSL_HIGH, 256, 256, NULL}, 3037 {"ecdhe_rsa_aes_256_gcm_sha_384", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "ECDHE-RSA-AES256-GCM-SHA384", SSL_kEECDH|SSL_aRSA|SSL_AES256GCM|SSL_AEAD, TLSV1_2, SSL_HIGH, 256, 256, NULL}, 3038 //#endif 3039 //#ifdef ENABLE_GCM 3040 {"ecdhe_rsa_aes_128_gcm_sha_256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "ECDHE-RSA-AES128-GCM-SHA256", SSL_kEECDH|SSL_aRSA|SSL_AES128GCM|SSL_AEAD, TLSV1_2, SSL_HIGH, 128, 128, NULL}, 3041 //#endif 3042 /* TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 is not implemented */ 3043 /* TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 is not implemented */ 3044 /* TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 is not implemented */ 3045 /* TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 is not implemented */ 3046 //#endif 3047 //#ifdef ENABLE_CHACHA20 3048 {"ecdhe_rsa_chacha20_poly1305_sha_256", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, "ECDHE-RSA-CHACHA20-POLY1305", SSL_kEECDH|SSL_aRSA|SSL_CHACHA20POLY1305|SSL_AEAD, TLSV1_2, SSL_HIGH, 256, 256, NULL}, 3049 {"ecdhe_ecdsa_chacha20_poly1305_sha_256", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, "ECDHE-ECDSA-CHACHA20-POLY1305", SSL_kEECDH|SSL_aECDSA|SSL_CHACHA20POLY1305|SSL_AEAD, TLSV1_2, SSL_HIGH, 256, 256, NULL}, 3050 {"dhe_rsa_chacha20_poly1305_sha_256", TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, "DHE-RSA-CHACHA20-POLY1305", SSL_kDHE|SSL_aRSA|SSL_CHACHA20POLY1305|SSL_AEAD, TLSV1_2, SSL_HIGH, 256, 256, NULL}, 3051 //#endif 3052 //#ifdef NSS_SUPPORTS_TLS_1_3 3053 #ifdef TLS_AES_128_GCM_SHA256 3054 /* Special TLS 1.3 cipher suites that really just specify AEAD 3055 * TLS 1.3 ciphers don't specify key exchange and authentication. 3056 */ 3057 {"aes_128_gcm_sha_256", TLS_AES_128_GCM_SHA256, "TLS-AES-128-GCM-SHA256", SSL_AES128GCM|SSL_AEAD, TLSV1_3, SSL_HIGH, 128, 128, NULL}, 3058 {"aes_256_gcm_sha_384", TLS_AES_256_GCM_SHA384, "TLS-AES-256-GCM-SHA384", SSL_AES256GCM|SSL_AEAD, TLSV1_3, SSL_HIGH, 256, 256, NULL}, 3059 {"chacha20_poly1305_sha_256", TLS_CHACHA20_POLY1305_SHA256, "TLS-CHACHA20-POLY1305_SHA256", SSL_CHACHA20POLY1305|SSL_AEAD, TLSV1_3, SSL_HIGH, 256, 256, NULL}, 3060 #endif 3061 //#endif 3062 }; 3063 3064 #define CIPHERNUM sizeof(ciphers_def) / sizeof(cipher_properties) 3065 //static const int ciphernum = CIPHERNUM; 3066 #define ciphernum ((int)(CIPHERNUM)) 3067 3068 /* Some ciphers are optionally enabled in OpenSSL. For safety sake assume 3069 * they are not available. 3070 */ 3071 static const int skip_ciphers = 4; 3072 static const int ciphers_not_in_openssl[] = { 3073 SSL_RSA_FIPS_WITH_DES_CBC_SHA, 3074 SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, 3075 TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, 3076 TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, 3077 }; 3078 3079 static int parse_nss_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum]); 3080 static int parse_openssl_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum]); 3081 3082 static 3083 int countciphers(PRBool cipher_state[ciphernum], int version) { 3084 int ciphercount = 0; 3085 int i = 0; 3086 3087 for (i = 0; i < ciphernum; i++) 3088 { 3089 if ((cipher_state[i] == PR_TRUE) && 3090 (ciphers_def[i].version & version)) { 3091 ciphercount++; 3092 } 3093 } 3094 3095 return ciphercount; 3096 } 3097 3098 3099 static 3100 int nss_parse_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum]) 3101 { 3102 UNUSED(s); 3103 int rv = 0; 3104 3105 /* If the string has a colon we use the OpenSSL style. If it has a 3106 * comma then NSS. If it has neither we try both. */ 3107 if (strchr(ciphers, ':')) { 3108 rv = parse_openssl_ciphers(s, ciphers, cipher_list); 3109 } else if (strchr(ciphers, ',')) { 3110 rv = parse_nss_ciphers(s, ciphers, cipher_list); 3111 } else { 3112 rv = parse_openssl_ciphers(s, ciphers, cipher_list); 3113 if (rv == 0 && 0 == countciphers(cipher_list, SSLV3|TLSV1|TLSV1_2|TLSV1_3)) { 3114 rv = parse_nss_ciphers(s, ciphers, cipher_list); 3115 } 3116 } 3117 if (0 == countciphers(cipher_list, SSLV3|TLSV1|TLSV1_2|TLSV1_3)) { 3118 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, 3119 "no cipher match"); 3120 } 3121 3122 return rv; 3123 } 3124 3125 3126 /* Given a set of ciphers perform a given action on the indexed value. 3127 * 3128 * This is needed because the + action doesn't do anything in the NSS 3129 * context. In OpenSSL it will re-order the cipher list. 3130 */ 3131 static void set_cipher_value(PRBool cipher_list[ciphernum], int index, int action) 3132 { 3133 int i; 3134 3135 if (action == REORDER_CIPHER) 3136 /* NSS doesn't allow ordering so do nothing */ 3137 return; 3138 3139 for (i = 0; i < skip_ciphers; i++) { 3140 if (ciphers_def[index].num == ciphers_not_in_openssl[i]) { 3141 cipher_list[index] = PERMANENTLY_DISABLE_CIPHER; 3142 return; 3143 } 3144 } 3145 3146 if (cipher_list[index] != PERMANENTLY_DISABLE_CIPHER) 3147 cipher_list[index] = action; 3148 } 3149 3150 3151 static int parse_openssl_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum]) 3152 { 3153 UNUSED(s); 3154 char * cipher; 3155 int i, action; 3156 PRBool merge = PR_FALSE; 3157 PRBool found = PR_FALSE; 3158 PRBool first = PR_TRUE; 3159 3160 cipher = ciphers; 3161 while (ciphers && (strlen(ciphers))) 3162 { 3163 while ((*cipher) && (isspace(*(uint8_t *)cipher))) 3164 ++cipher; 3165 3166 action = ENABLE_CIPHER; /* default to enable */ 3167 switch(*cipher) 3168 { 3169 case '+': 3170 /* Cipher ordering is not supported in NSS */ 3171 action = REORDER_CIPHER; 3172 cipher++; 3173 break; 3174 case '-': 3175 action = SUBTRACT_CIPHER; 3176 cipher++; 3177 break; 3178 case '!': 3179 action = PERMANENTLY_DISABLE_CIPHER; 3180 cipher++; 3181 break; 3182 default: 3183 /* Add the cipher */ 3184 break; 3185 } 3186 3187 if ((ciphers = strchr(cipher, ':'))) { 3188 *ciphers++ = '\0'; 3189 merge = PR_FALSE; 3190 found = PR_FALSE; 3191 } 3192 3193 if (!strcmp(cipher, "ALL")) { 3194 found = PR_TRUE; 3195 for (i=0; i<ciphernum; i++) { 3196 if (!(ciphers_def[i].attr & SSL_eNULL)) 3197 set_cipher_value(cipher_list, i, action); 3198 } 3199 } else if (!strcmp(cipher, "COMPLEMENTOFALL")) { 3200 found = PR_TRUE; 3201 for (i=0; i<ciphernum; i++) { 3202 if ((ciphers_def[i].attr & SSL_eNULL)) 3203 set_cipher_value(cipher_list, i, action); 3204 } 3205 } else if (!strcmp(cipher, "DEFAULT")) { 3206 /* In OpenSSL the default cipher list is 3207 * ALL:!aNULL:!eNULL:!SSLv2 3208 * So we need to disable all the NULL ciphers too. 3209 */ 3210 int mask = SSL_aNULL | SSL_eNULL; 3211 found = PR_TRUE; 3212 for (i=0; i < ciphernum; i++) { 3213 if (cipher_list[i] != PERMANENTLY_DISABLE_CIPHER) 3214 SSL_CipherPrefGetDefault(ciphers_def[i].num, 3215 &cipher_list[i]); 3216 if (PR_TRUE == first) { 3217 if (ciphers_def[i].attr & mask) { 3218 set_cipher_value(cipher_list, i, 3219 PERMANENTLY_DISABLE_CIPHER); 3220 } 3221 } 3222 } 3223 } else if (!strcmp(cipher, "COMPLEMENTOFDEFAULT")) { 3224 found = PR_TRUE; 3225 /* no-op. In OpenSSL this is the ADH ciphers */ 3226 } else if (!strcmp(cipher, "@STRENGTH")) { 3227 /* No cipher ordering in NSS */ 3228 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, 3229 "Cipher ordering is not supported in NSS"); 3230 return -1; 3231 } else { 3232 int amask = 0; 3233 int amaskaction = 0; 3234 int mask = 0; 3235 int strength = 0; 3236 int protocol = 0; 3237 char *c; 3238 PRBool candidate_list[ciphernum]; 3239 PRBool temp_list[ciphernum]; 3240 3241 for (i = 0; i < ciphernum; i++) { 3242 candidate_list[i] = 1; 3243 } 3244 3245 c = cipher; 3246 while (c && (strlen(c))) { 3247 amask = 0; 3248 amaskaction = 0; 3249 mask = 0; 3250 strength = 0; 3251 protocol = 0; 3252 for (i = 0; i < ciphernum; i++) { 3253 temp_list[i] = 0; 3254 } 3255 3256 if ((c = strchr(cipher, '+'))) { 3257 *c++ = '\0'; 3258 } 3259 3260 if (!strcmp(cipher, "RSA")) { 3261 mask |= SSL_RSA; 3262 } else if (!strcmp(cipher, "kRSA")) { 3263 mask |= SSL_kRSA; 3264 } else if (!strcmp(cipher, "aRSA")) { 3265 mask |= SSL_aRSA; 3266 } else if (!strcmp(cipher, "EDH")) { 3267 /* Normally this is kEDH:-ADH but since we don't 3268 * support ADH this is sufficient. 3269 */ 3270 mask |= SSL_kEDH; 3271 } else if (!strcmp(cipher, "DH")) { 3272 /* non-ephemeral DH. The ciphers are defined 3273 * but not implemented in OpenSSL so manage 3274 * this here. 3275 */ 3276 mask |= SSL_kDHE; 3277 #if 0 3278 } else if (!strcmp(cipher, "ADH")) { 3279 mask |= SSL_ADH; 3280 #endif 3281 } else if (!strcmp(cipher, "ECDH")) { 3282 mask |= SSL_ECDH; 3283 } else if (!strcmp(cipher, "EECDH")) { 3284 mask |= SSL_kEECDH; 3285 amask = SSL_aNULL; 3286 amaskaction = 1; /* filter anonymous out */ 3287 } else if (!strcmp(cipher, "AECDH")) { 3288 mask |= SSL_kEECDH; 3289 amask = SSL_aNULL; /* require anonymous */ 3290 amaskaction = 0; /* keep these */ 3291 } else if (!strcmp(cipher, "kECDH")) { 3292 mask |= SSL_kECDHE | SSL_kECDHr; 3293 } else if (!strcmp(cipher, "kECDHE")) { 3294 mask |= SSL_kECDHE; 3295 } else if (!strcmp(cipher, "kECDHr")) { 3296 mask |= SSL_kECDHr; 3297 } else if (!strcmp(cipher, "kEECDH")) { 3298 mask |= SSL_kEECDH; 3299 } else if (!strcmp(cipher, "AECDH")) { 3300 mask |= SSL_AECDH; 3301 } else if (!strcmp(cipher, "ECDSA")) { 3302 mask |= SSL_aECDSA; 3303 } else if (!strcmp(cipher, "aECDSA")) { 3304 mask |= SSL_aECDSA; 3305 } else if ((!strcmp(cipher, "NULL")) || (!strcmp(cipher, "eNULL"))) { 3306 mask |= SSL_eNULL; 3307 } else if (!strcmp(cipher, "aNULL")) { 3308 mask |= SSL_aNULL; 3309 } else if (!strcmp(cipher, "AES")) { 3310 mask |= SSL_AES; 3311 } else if (!strcmp(cipher, "AESGCM")) { 3312 mask |= SSL_AES128GCM|SSL_AES256GCM; 3313 } else if (!strcmp(cipher, "AES128")) { 3314 mask |= SSL_AES128|SSL_AES128GCM; 3315 } else if (!strcmp(cipher, "AES256")) { 3316 mask |= SSL_AES256|SSL_AES256GCM; 3317 } else if (!strcmp(cipher, "CHACHA20")) { 3318 mask |= SSL_CHACHA20POLY1305; 3319 } else if (!strcmp(cipher, "CAMELLIA")) { 3320 mask |= SSL_CAMELLIA128|SSL_CAMELLIA256; 3321 } else if (!strcmp(cipher, "CAMELLIA128")) { 3322 mask |= SSL_CAMELLIA128; 3323 } else if (!strcmp(cipher, "CAMELLIA256")) { 3324 mask |= SSL_CAMELLIA256; 3325 } else if (!strcmp(cipher, "3DES")) { 3326 mask |= SSL_3DES; 3327 } else if (!strcmp(cipher, "DES")) { 3328 mask |= SSL_DES; 3329 } else if (!strcmp(cipher, "RC4")) { 3330 mask |= SSL_RC4; 3331 } else if (!strcmp(cipher, "RC2")) { 3332 mask |= SSL_RC2; 3333 } else if (!strcmp(cipher, "MD5")) { 3334 mask |= SSL_MD5; 3335 } else if ((!strcmp(cipher, "SHA")) || (!strcmp(cipher, "SHA1"))) { 3336 mask |= SSL_SHA1; 3337 } else if (!strcmp(cipher, "SHA256")) { 3338 mask |= SSL_SHA256; 3339 } else if (!strcmp(cipher, "SHA384")) { 3340 mask |= SSL_SHA384; 3341 } else if (!strcmp(cipher, "SSLv2")) { 3342 /* no-op */ 3343 } else if (!strcmp(cipher, "SSLv3")) { 3344 protocol |= SSLV3; 3345 } else if (!strcmp(cipher, "TLSv1")) { 3346 protocol |= TLSV1; 3347 } else if (!strcmp(cipher, "TLSv1.2")) { 3348 protocol |= TLSV1_2; 3349 } else if (!strcmp(cipher, "TLSv1.3")) { 3350 protocol |= TLSV1_3; 3351 } else if (!strcmp(cipher, "HIGH")) { 3352 strength |= SSL_HIGH; 3353 } else if (!strcmp(cipher, "MEDIUM")) { 3354 strength |= SSL_MEDIUM; 3355 } else if (!strcmp(cipher, "LOW")) { 3356 strength |= SSL_LOW; 3357 } else if ((!strcmp(cipher, "EXPORT")) || (!strcmp(cipher, "EXP"))) { 3358 strength |= SSL_EXPORT40|SSL_EXPORT56; 3359 } else if (!strcmp(cipher, "EXPORT40")) { 3360 strength |= SSL_EXPORT40; 3361 } else if (!strcmp(cipher, "EXPORT56")) { 3362 strength |= SSL_EXPORT56; 3363 } 3364 3365 if (c) 3366 cipher = c; 3367 3368 /* If we have a mask, apply it. If not then perhaps they 3369 * provided a specific cipher to enable. 3370 */ 3371 if (mask || strength || protocol) { 3372 merge = PR_TRUE; 3373 found = PR_TRUE; 3374 for (i=0; i<ciphernum; i++) { 3375 if (((ciphers_def[i].attr & mask) || 3376 (ciphers_def[i].strength & strength) || 3377 (ciphers_def[i].version & protocol)) && 3378 (cipher_list[i] != PERMANENTLY_DISABLE_CIPHER)) { 3379 if (amask != 0) { 3380 PRBool match = PR_FALSE; 3381 if (ciphers_def[i].attr & amask) { 3382 match = PR_TRUE; 3383 } 3384 if (amaskaction && match) 3385 continue; 3386 if (!amaskaction && !match) 3387 continue; 3388 } 3389 #if 0 3390 /* Enable the NULL ciphers only if explicity 3391 * requested */ 3392 if (ciphers_def[i].attr & SSL_eNULL) { 3393 if (mask & SSL_eNULL) 3394 temp_list[i] = 1; 3395 } else 3396 #endif 3397 temp_list[i] = 1; 3398 } 3399 } 3400 /* Merge the temp list into the candidate list */ 3401 for (i=0; i<ciphernum; i++) { 3402 if (!(candidate_list[i] & temp_list[i])) { 3403 candidate_list[i] = 0; 3404 } 3405 } 3406 } else if (!strcmp(cipher, "FIPS")) { 3407 SSLCipherSuiteInfo suite; 3408 for (i=0; i<ciphernum;i++) { 3409 if (SSL_GetCipherSuiteInfo(ciphers_def[i].num, 3410 &suite, sizeof suite) == SECSuccess) { 3411 if (suite.isFIPS) 3412 set_cipher_value(cipher_list, i, action); 3413 } 3414 } 3415 } else { 3416 for (i=0; i<ciphernum; i++) { 3417 if (!strcmp(ciphers_def[i].openssl_name, cipher)) 3418 set_cipher_value(cipher_list, i, action); 3419 } 3420 } 3421 } /* while */ 3422 if (PR_TRUE == merge) { 3423 first = PR_FALSE; 3424 /* Merge the candidate list into the cipher list */ 3425 for (i=0; i<ciphernum; i++) { 3426 if (candidate_list[i]) 3427 set_cipher_value(cipher_list, i, action); 3428 } 3429 merge = PR_FALSE; 3430 found = PR_FALSE; 3431 } 3432 } 3433 3434 if (ciphers) 3435 cipher = ciphers; 3436 3437 } 3438 if (found && 0 == countciphers(cipher_list, SSLV3|TLSV1|TLSV1_2|TLSV1_3)) 3439 return 1; /* no matching ciphers */ 3440 return 0; 3441 } 3442 3443 3444 static int parse_nss_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum]) 3445 { 3446 UNUSED(s); 3447 char * cipher; 3448 PRBool found; 3449 int i, active; 3450 3451 cipher = ciphers; 3452 3453 while (ciphers && (strlen(ciphers))) 3454 { 3455 while ((*cipher) && (isspace(*(uint8_t *)cipher))) 3456 ++cipher; 3457 3458 switch(*cipher++) 3459 { 3460 case '+': 3461 active = PR_TRUE; 3462 break; 3463 case '-': 3464 active = PR_FALSE; 3465 break; 3466 default: 3467 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, 3468 "invalid cipher string %s. Format is +cipher1,-cipher2...", cipher - 1); 3469 return -1; 3470 } 3471 3472 if ((ciphers = strchr(cipher, ','))) { 3473 *ciphers++ = '\0'; 3474 } 3475 3476 found = PR_FALSE; 3477 3478 for (i = 0; i < ciphernum; i++) 3479 { 3480 if (!strcasecmp(cipher, ciphers_def[i].name)) 3481 { 3482 cipher_list[i] = active; 3483 found = PR_TRUE; 3484 break; 3485 } else if ((ciphers_def[i].alias != NULL) && 3486 (!strcasecmp(cipher, ciphers_def[i].alias))) 3487 { 3488 cipher_list[i] = active; 3489 found = PR_TRUE; 3490 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, 3491 "Deprecated cipher name %s, use %s instead.", 3492 cipher, ciphers_def[i].name); 3493 break; 3494 } 3495 } 3496 3497 if (found == PR_FALSE) { 3498 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, 3499 "Unknown cipher %s\n", cipher); 3500 } 3501 3502 if (ciphers) { 3503 cipher = ciphers; 3504 } 3505 } 3506 3507 return 0; 3508 } 3509 3510 3511 static int 3512 mod_nss_ssl_conf_ciphersuites (server *srv, plugin_config_socket *s, buffer *ciphersuites, const buffer *cipherstring) 3513 { 3514 if (ciphersuites) 3515 /* XXX: not implemented; 3516 * could manually add support for short list of TLSv1.3 suites */ 3517 log_error(srv->errh, __FILE__, __LINE__, 3518 "Ciphersuite support not implemented for %s", 3519 ciphersuites->ptr); 3520 3521 if (buffer_string_is_empty(cipherstring)) 3522 return 1; /* nothing to do */ 3523 3524 /* 3525 * Apache mod_nss 3526 * https://pagure.io/mod_nss.git 3527 * 3528 * modified from mod_nss/nss_engine_init.c:nss_init_ctx_cipher_suite() 3529 */ 3530 3531 PRBool cipher_state[ciphernum]; 3532 3533 /* Disable all NSS supported cipher suites. This is to prevent any new 3534 * NSS cipher suites from getting automatically and unintentionally 3535 * enabled as a result of the NSS_SetDomesticPolicy() call. This way, 3536 * only the ciphers explicitly specified in the server configuration can 3537 * ever be enabled. 3538 */ 3539 for (int i = 0; i < SSL_NumImplementedCiphers; ++i) 3540 SSL_CipherPrefSet(s->model, SSL_ImplementedCiphers[i], SSL_NOT_ALLOWED); 3541 3542 /* initialize all known ciphers to false */ 3543 for (int i = 0; i < ciphernum; ++i) 3544 cipher_state[i] = PR_FALSE; 3545 3546 char *ciphers = strdup(cipherstring->ptr);/*(string modified during parse)*/ 3547 if (NULL == ciphers) return 0; 3548 3549 int rc = nss_parse_ciphers(srv->errh, ciphers, cipher_state); 3550 free(ciphers); 3551 if (-1 == rc) return 0; 3552 3553 if (((s->protos.min && s->protos.min <= SSL_LIBRARY_VERSION_3_0) 3554 || s->ssl_use_sslv3) 3555 && countciphers(cipher_state, SSLV3) == 0) { 3556 ap_log_error(APLOG_MARK, APLOG_ERR, 0, srv->errh, 3557 "NSSCipherSuite: SSL3 is enabled but no SSL3 ciphers are enabled."); 3558 return 0; 3559 } 3560 3561 if (s->protos.max >= SSL_LIBRARY_VERSION_TLS_1_0 3562 && countciphers(cipher_state, TLSV1|TLSV1_2|TLSV1_3) == 0) { 3563 ap_log_error(APLOG_MARK, APLOG_ERR, 0, srv->errh, 3564 "NSSCipherSuite: TLS is enabled but no TLS ciphers are enabled."); 3565 return 0; 3566 } 3567 3568 /* Finally actually enable the selected ciphers */ 3569 for (int i = 0; i < ciphernum; ++i) 3570 SSL_CipherPrefSet(s->model, ciphers_def[i].num, 3571 cipher_state[i] == ENABLE_CIPHER 3572 ? SSL_ALLOWED 3573 : SSL_NOT_ALLOWED); 3574 3575 return 1; 3576 } 3577