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