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