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