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