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