selfserv.c (103902B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /* -r flag is interepreted as follows: 6 * 1 -r means request, not require, on initial handshake. 7 * 2 -r's mean request and require, on initial handshake. 8 * 3 -r's mean request, not require, on second handshake. 9 * 4 -r's mean request and require, on second handshake. 10 */ 11 #include <stdio.h> 12 #include <string.h> 13 14 #include "secutil.h" 15 16 #if defined(XP_UNIX) 17 #include <unistd.h> 18 #endif 19 20 #if defined(_WINDOWS) 21 #include <process.h> /* for getpid() */ 22 #endif 23 24 #include <signal.h> 25 #include <stdlib.h> 26 #include <errno.h> 27 #include <fcntl.h> 28 #include <stdarg.h> 29 30 #include "nspr.h" 31 #include "prio.h" 32 #include "prerror.h" 33 #include "prnetdb.h" 34 #include "prclist.h" 35 #include "plgetopt.h" 36 #include "pk11func.h" 37 #include "secitem.h" 38 #include "nss.h" 39 #include "ssl.h" 40 #include "sslproto.h" 41 #include "sslexp.h" 42 #include "cert.h" 43 #include "certt.h" 44 #include "ocsp.h" 45 #include "nssb64.h" 46 #include "zlib.h" 47 48 #ifndef PORT_Strstr 49 #define PORT_Strstr strstr 50 #endif 51 52 #ifndef PORT_Malloc 53 #define PORT_Malloc PR_Malloc 54 #endif 55 56 int NumSidCacheEntries = 1024; 57 58 static int handle_connection(PRFileDesc *, PRFileDesc *); 59 60 static const char envVarName[] = { SSL_ENV_VAR_NAME }; 61 static const char inheritableSockName[] = { "SELFSERV_LISTEN_SOCKET" }; 62 63 #define MAX_VIRT_SERVER_NAME_ARRAY_INDEX 10 64 #define MAX_CERT_NICKNAME_ARRAY_INDEX 10 65 66 #define DEFAULT_BULK_TEST 16384 67 #define MAX_BULK_TEST 1048576 /* 1 MB */ 68 static PRBool testBulk; 69 static PRUint32 testBulkSize = DEFAULT_BULK_TEST; 70 static PRInt32 testBulkTotal; 71 static char *testBulkBuf; 72 static PRDescIdentity log_layer_id = PR_INVALID_IO_LAYER; 73 static PRFileDesc *loggingFD; 74 static PRIOMethods loggingMethods; 75 76 static PRBool logStats; 77 static PRBool loggingLayer; 78 static int logPeriod = 30; 79 static PRInt32 loggerOps; 80 static PRInt32 loggerBytes; 81 static PRInt32 loggerBytesTCP; 82 static PRInt32 bulkSentChunks; 83 static enum ocspStaplingModeEnum { 84 osm_disabled, /* server doesn't support stapling */ 85 osm_good, /* supply a signed good status */ 86 osm_revoked, /* supply a signed revoked status */ 87 osm_unknown, /* supply a signed unknown status */ 88 osm_failure, /* supply a unsigned failure status, "try later" */ 89 osm_badsig, /* supply a good status response with a bad signature */ 90 osm_corrupted, /* supply a corrupted data block as the status */ 91 osm_random, /* use a random response for each connection */ 92 osm_ocsp /* retrieve ocsp status from external ocsp server, 93 use empty status if server is unavailable */ 94 } ocspStaplingMode = osm_disabled; 95 typedef enum ocspStaplingModeEnum ocspStaplingModeType; 96 static char *ocspStaplingCA = NULL; 97 static SECItemArray *certStatus[MAX_CERT_NICKNAME_ARRAY_INDEX] = { NULL }; 98 99 const int ssl3CipherSuites[] = { 100 -1, /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */ 101 -1, /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA * b */ 102 TLS_RSA_WITH_RC4_128_MD5, /* c */ 103 TLS_RSA_WITH_3DES_EDE_CBC_SHA, /* d */ 104 TLS_RSA_WITH_DES_CBC_SHA, /* e */ 105 -1, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 * f */ 106 -1, /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 * g */ 107 -1, /* SSL_FORTEZZA_DMS_WITH_NULL_SHA * h */ 108 TLS_RSA_WITH_NULL_MD5, /* i */ 109 -1, /* SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA * j */ 110 -1, /* SSL_RSA_FIPS_WITH_DES_CBC_SHA * k */ 111 -1, /* TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA * l */ 112 -1, /* TLS_RSA_EXPORT1024_WITH_RC4_56_SHA * m */ 113 TLS_RSA_WITH_RC4_128_SHA, /* n */ 114 TLS_DHE_DSS_WITH_RC4_128_SHA, /* o */ 115 TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */ 116 TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */ 117 TLS_DHE_RSA_WITH_DES_CBC_SHA, /* r */ 118 TLS_DHE_DSS_WITH_DES_CBC_SHA, /* s */ 119 TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* t */ 120 TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* u */ 121 TLS_RSA_WITH_AES_128_CBC_SHA, /* v */ 122 TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* w */ 123 TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* x */ 124 TLS_RSA_WITH_AES_256_CBC_SHA, /* y */ 125 TLS_RSA_WITH_NULL_SHA, /* z */ 126 0 127 }; 128 129 /* data and structures for shutdown */ 130 static int stopping; 131 132 static PRBool noDelay; 133 static int requestCert; 134 static int verbose; 135 static SECItem bigBuf; 136 static int configureDHE = -1; /* -1: don't configure, 0 disable, >=1 enable*/ 137 static int configureReuseECDHE = -1; /* -1: don't configure, 0 refresh, >=1 reuse*/ 138 static int configureWeakDHE = -1; /* -1: don't configure, 0 disable, >=1 enable*/ 139 SECItem psk = { siBuffer, NULL, 0 }; 140 SECItem pskLabel = { siBuffer, NULL, 0 }; 141 char *echParamsStr = NULL; 142 143 static PRThread *acceptorThread; 144 145 static PRLogModuleInfo *lm; 146 147 #define PRINTF \ 148 if (verbose) \ 149 printf 150 #define FPRINTF \ 151 if (verbose) \ 152 fprintf 153 #define FLUSH \ 154 if (verbose) { \ 155 fflush(stdout); \ 156 fflush(stderr); \ 157 } 158 #define VLOG(arg) PR_LOG(lm, PR_LOG_DEBUG, arg) 159 160 static void 161 PrintUsageHeader(const char *progName) 162 { 163 fprintf(stderr, 164 "Usage: %s -n rsa_nickname -p port [-BDENRZbjlmrsuvx] [-w password]\n" 165 " [-t threads] [-i pid_file] [-c ciphers] [-Y] [-d dbdir] [-g numblocks]\n" 166 " [-f password_file] [-L [seconds]] [-M maxProcs] [-P dbprefix]\n" 167 " [-V [min-version]:[max-version]] [-a sni_name]\n" 168 " [ T <good|revoked|unknown|badsig|corrupted|none|ocsp>] [-A ca]\n" 169 " [-C SSLCacheEntries] [-S dsa_nickname] [-Q]\n" 170 " [-I groups] [-J signatureschemes] [-e ec_nickname]\n" 171 " -U [0|1] -H [0|1|2] -W [0|1] [-z externalPsk] -q\n" 172 "\n", 173 progName); 174 } 175 176 static void 177 PrintParameterUsage() 178 { 179 fputs( 180 "-V [min]:[max] restricts the set of enabled SSL/TLS protocol versions.\n" 181 " All versions are enabled by default.\n" 182 " Possible values for min/max: ssl3 tls1.0 tls1.1 tls1.2 tls1.3\n" 183 " Example: \"-V ssl3:\" enables SSL 3 and newer.\n" 184 "-D means disable Nagle delays in TCP\n" 185 "-R means disable detection of rollback from TLS to SSL3\n" 186 "-a configure server for SNI.\n" 187 "-k expected name negotiated on server sockets\n" 188 "-b means try binding to the port and exit\n" 189 "-m means test the model-socket feature of SSL_ImportFD.\n" 190 "-r flag is interepreted as follows:\n" 191 " 1 -r means request, not require, cert on initial handshake.\n" 192 " 2 -r's mean request and require, cert on initial handshake.\n" 193 " 3 -r's mean request, not require, cert on second handshake.\n" 194 " 4 -r's mean request and require, cert on second handshake.\n" 195 "-s means disable SSL socket locking for performance\n" 196 "-u means enable Session Ticket extension for TLS.\n" 197 "-v means verbose output\n" 198 "-L seconds means log statistics every 'seconds' seconds (default=30).\n" 199 "-M maxProcs tells how many processes to run in a multi-process server\n" 200 "-N means do NOT use the server session cache. Incompatible with -M.\n" 201 "-t threads -- specify the number of threads to use for connections.\n" 202 "-i pid_file file to write the process id of selfserve\n" 203 "-l means use local threads instead of global threads\n" 204 "-g numblocks means test throughput by sending total numblocks chunks\n" 205 " of size 16kb to the client, 0 means unlimited (default=0)\n" 206 "-j means measure TCP throughput (for use with -g option)\n" 207 "-C SSLCacheEntries sets the maximum number of entries in the SSL\n" 208 " session cache\n" 209 "-T <mode> enable OCSP stapling. Possible modes:\n" 210 " none: don't send cert status (default)\n" 211 " good, revoked, unknown: Include locally signed response. Requires: -A\n" 212 " failure: return a failure response (try later, unsigned)\n" 213 " badsig: use a good status but with an invalid signature\n" 214 " corrupted: stapled cert status is an invalid block of data\n" 215 " random: each connection uses a random status from this list:\n" 216 " good, revoked, unknown, failure, badsig, corrupted\n" 217 " ocsp: fetch from external OCSP server using AIA, or none\n" 218 "-A <ca> Nickname of a CA used to sign a stapled cert status\n" 219 "-U override default ECDHE ephemeral key reuse, 0: refresh, 1: reuse\n" 220 "-H override default DHE server support, 0: disable, 1: enable, " 221 " 2: require DH named groups [RFC7919]\n" 222 "-W override default DHE server weak parameters support, 0: disable, 1: enable\n" 223 "-c Restrict ciphers\n" 224 "-Y prints cipher values allowed for parameter -c and exits\n" 225 "-G enables the extended master secret extension [RFC7627]\n" 226 "-Q enables ALPN for HTTP/1.1 [RFC7301]\n" 227 "-I comma separated list of enabled groups for TLS key exchange.\n" 228 " The following values are valid", 229 stderr); 230 char comma = ':'; 231 const char *groupName; 232 int total = SECU_MAX_COL_LEN; 233 for (size_t i = 0; (groupName = SECU_NamedGroupGetNextName(i)) != NULL; i++) { 234 int len = strlen(groupName); 235 /* 2 represents a comma and a space */ 236 if ((total + len + 2) > SECU_MAX_COL_LEN) { 237 fprintf(stderr, "%c\n %s", comma, groupName); 238 /* 5 represents 5 spaces */ 239 total = len + 5; 240 } else { 241 fprintf(stderr, "%c %s", comma, groupName); 242 /* 2 represents a comma and a space */ 243 total += len + 2; 244 } 245 comma = ','; 246 } 247 fprintf(stderr, "\n"); 248 fputs( 249 "-J comma separated list of enabled signature schemes in preference order.\n" 250 " The following values are valid", 251 stderr); 252 comma = ':'; 253 const char *schemeName; 254 total = SECU_MAX_COL_LEN; 255 for (size_t i = 0; (schemeName = SECU_SignatureSchemeGetNextScheme(i)) != NULL; i++) { 256 int len = strlen(schemeName); 257 /* 2 represents a comma and a space */ 258 if ((total + len + 2) > SECU_MAX_COL_LEN) { 259 fprintf(stderr, "%c\n %s", comma, schemeName); 260 /* 5 represents 5 spaces */ 261 total = len + 5; 262 } else { 263 fprintf(stderr, "%c %s", comma, schemeName); 264 /* 2 represents a comma and a space */ 265 total += len + 2; 266 } 267 comma = ','; 268 } 269 fprintf(stderr, "\n"); 270 fputs( 271 "-Z enable 0-RTT (for TLS 1.3; also use -u)\n" 272 "-E enable post-handshake authentication\n" 273 " (for TLS 1.3; only has an effect with 3 or more -r options)\n" 274 "-x Export and print keying material after successful handshake\n" 275 " The argument is a comma separated list of exporters in the form:\n" 276 " LABEL[:OUTPUT-LENGTH[:CONTEXT]]\n" 277 " where LABEL and CONTEXT can be either a free-form string or\n" 278 " a hex string if it is preceded by \"0x\"; OUTPUT-LENGTH\n" 279 " is a decimal integer.\n" 280 "-z Configure a TLS 1.3 External PSK with the given hex string for a key.\n" 281 " To specify a label, use ':' as a delimiter. For example:\n" 282 " 0xAAAABBBBCCCCDDDD:mylabel. Otherwise, the default label of\n" 283 " 'Client_identity' will be used.\n" 284 "-X Configure the server for ECH via the given <ECHParams>. ECHParams\n" 285 " are expected in one of two formats:\n" 286 " 1. A string containing the ECH public name prefixed by the substring\n" 287 " \"publicname:\". For example, \"publicname:example.com\". In this mode,\n" 288 " an ephemeral ECH keypair is generated and ECHConfigs are printed to stdout.\n" 289 " 2. As a Base64 tuple of <ECHRawPrivateKey> || <ECHConfigs>. In this mode, the\n" 290 " raw private key is used to bootstrap the HPKE context.\n" 291 "-q Enable zlib certificate compression\n", 292 stderr); 293 } 294 295 static void 296 Usage(const char *progName) 297 { 298 PrintUsageHeader(progName); 299 PrintParameterUsage(); 300 } 301 302 static void 303 PrintCipherUsage(const char *progName) 304 { 305 PrintUsageHeader(progName); 306 fputs( 307 "-c ciphers Letter(s) chosen from the following list\n" 308 "c SSL3 RSA WITH RC4 128 MD5\n" 309 "d SSL3 RSA WITH 3DES EDE CBC SHA\n" 310 "e SSL3 RSA WITH DES CBC SHA\n" 311 "f SSL3 RSA EXPORT WITH RC4 40 MD5\n" 312 "g SSL3 RSA EXPORT WITH RC2 CBC 40 MD5\n" 313 "i SSL3 RSA WITH NULL MD5\n" 314 "j SSL3 RSA FIPS WITH 3DES EDE CBC SHA\n" 315 "k SSL3 RSA FIPS WITH DES CBC SHA\n" 316 "l SSL3 RSA EXPORT WITH DES CBC SHA\t(new)\n" 317 "m SSL3 RSA EXPORT WITH RC4 56 SHA\t(new)\n" 318 "n SSL3 RSA WITH RC4 128 SHA\n" 319 "o TLS_DHE_DSS_WITH_RC4_128_SHA\n" 320 "p TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA\n" 321 "q TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA\n" 322 "r TLS_DHE_RSA_WITH_DES_CBC_SHA\n" 323 "s TLS_DHE_DSS_WITH_DES_CBC_SHA\n" 324 "t TLS_DHE_DSS_WITH_AES_128_CBC_SHA\n" 325 "u TLS_DHE_RSA_WITH_AES_128_CBC_SHA\n" 326 "v SSL3 RSA WITH AES 128 CBC SHA\n" 327 "w TLS_DHE_DSS_WITH_AES_256_CBC_SHA\n" 328 "x TLS_DHE_RSA_WITH_AES_256_CBC_SHA\n" 329 "y SSL3 RSA WITH AES 256 CBC SHA\n" 330 "z SSL3 RSA WITH NULL SHA\n" 331 "\n" 332 ":WXYZ Use cipher with hex code { 0xWX , 0xYZ } in TLS\n", 333 stderr); 334 } 335 336 static const char * 337 errWarn(char *funcString) 338 { 339 PRErrorCode perr = PR_GetError(); 340 const char *errString = SECU_Strerror(perr); 341 342 fprintf(stderr, "selfserv: %s returned error %d:\n%s\n", 343 funcString, perr, errString); 344 return errString; 345 } 346 347 static void 348 errExit(char *funcString) 349 { 350 errWarn(funcString); 351 exit(3); 352 } 353 354 /************************************************************************** 355 ** 356 ** Routines for disabling SSL ciphers. 357 ** 358 **************************************************************************/ 359 360 /* disable all the SSL cipher suites */ 361 void 362 disableAllSSLCiphers(void) 363 { 364 const PRUint16 *cipherSuites = SSL_ImplementedCiphers; 365 int i = SSL_NumImplementedCiphers; 366 SECStatus rv; 367 368 while (--i >= 0) { 369 PRUint16 suite = cipherSuites[i]; 370 rv = SSL_CipherPrefSetDefault(suite, PR_FALSE); 371 if (rv != SECSuccess) { 372 printf("SSL_CipherPrefSetDefault rejected suite 0x%04x (i = %d)\n", 373 suite, i); 374 errWarn("SSL_CipherPrefSetDefault"); 375 } 376 } 377 } 378 379 static SECStatus 380 mySSLAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, 381 PRBool isServer) 382 { 383 SECStatus rv; 384 CERTCertificate *peerCert; 385 386 peerCert = SSL_PeerCertificate(fd); 387 388 if (peerCert) { 389 PRINTF("selfserv: Subject: %s\nselfserv: Issuer : %s\n", 390 peerCert->subjectName, peerCert->issuerName); 391 CERT_DestroyCertificate(peerCert); 392 } 393 394 rv = SSL_AuthCertificate(arg, fd, checkSig, isServer); 395 396 if (rv == SECSuccess) { 397 PRINTF("selfserv: -- SSL3: Certificate Validated.\n"); 398 } else { 399 int err = PR_GetError(); 400 FPRINTF(stderr, "selfserv: -- SSL3: Certificate Invalid, err %d.\n%s\n", 401 err, SECU_Strerror(err)); 402 } 403 FLUSH; 404 return rv; 405 } 406 407 void 408 printSSLStatistics() 409 { 410 SSL3Statistics *ssl3stats = SSL_GetStatistics(); 411 412 printf( 413 "selfserv: %ld cache hits; %ld cache misses, %ld cache not reusable\n" 414 " %ld stateless resumes, %ld ticket parse failures\n", 415 ssl3stats->hch_sid_cache_hits, ssl3stats->hch_sid_cache_misses, 416 ssl3stats->hch_sid_cache_not_ok, ssl3stats->hch_sid_stateless_resumes, 417 ssl3stats->hch_sid_ticket_parse_failures); 418 } 419 420 void 421 printSecurityInfo(PRFileDesc *fd) 422 { 423 CERTCertificate *cert = NULL; 424 SECStatus result; 425 SSLChannelInfo channel; 426 SSLCipherSuiteInfo suite; 427 428 if (verbose) 429 printSSLStatistics(); 430 431 result = SSL_GetChannelInfo(fd, &channel, sizeof channel); 432 if (result == SECSuccess && 433 channel.length == sizeof channel && 434 channel.cipherSuite) { 435 result = SSL_GetCipherSuiteInfo(channel.cipherSuite, 436 &suite, sizeof suite); 437 if (result == SECSuccess) { 438 FPRINTF(stderr, 439 "selfserv: SSL version %d.%d using %d-bit %s with %d-bit %s MAC%s\n", 440 channel.protocolVersion >> 8, channel.protocolVersion & 0xff, 441 suite.effectiveKeyBits, suite.symCipherName, 442 suite.macBits, suite.macAlgorithmName, 443 channel.isFIPS ? " FIPS" : ""); 444 FPRINTF(stderr, 445 "selfserv: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n" 446 " Key Exchange Group: %s\n" 447 " Compression: %s, Extended Master Secret: %s\n" 448 " Signature Scheme: %s\n", 449 channel.authKeyBits, suite.authAlgorithmName, 450 channel.keaKeyBits, suite.keaTypeName, 451 SECU_NamedGroupToGroupName(channel.keaGroup), 452 channel.compressionMethodName, 453 channel.extendedMasterSecretUsed ? "Yes" : "No", 454 SECU_SignatureSchemeName(channel.signatureScheme)); 455 } 456 } 457 if (verbose) { 458 SECItem *hostInfo = SSL_GetNegotiatedHostInfo(fd); 459 if (hostInfo) { 460 char namePref[] = "selfserv: Negotiated server name: "; 461 462 fprintf(stderr, "%s", namePref); 463 fwrite(hostInfo->data, hostInfo->len, 1, stderr); 464 SECITEM_FreeItem(hostInfo, PR_TRUE); 465 hostInfo = NULL; 466 fprintf(stderr, "\n"); 467 } 468 } 469 if (requestCert) 470 cert = SSL_PeerCertificate(fd); 471 else 472 cert = SSL_LocalCertificate(fd); 473 if (cert) { 474 char *ip = CERT_NameToAscii(&cert->issuer); 475 char *sp = CERT_NameToAscii(&cert->subject); 476 if (sp) { 477 FPRINTF(stderr, "selfserv: subject DN: %s\n", sp); 478 PORT_Free(sp); 479 } 480 if (ip) { 481 FPRINTF(stderr, "selfserv: issuer DN: %s\n", ip); 482 PORT_Free(ip); 483 } 484 CERT_DestroyCertificate(cert); 485 cert = NULL; 486 } 487 FLUSH; 488 } 489 490 static int MakeCertOK; 491 492 static SECStatus 493 myBadCertHandler(void *arg, PRFileDesc *fd) 494 { 495 int err = PR_GetError(); 496 if (!MakeCertOK) 497 fprintf(stderr, 498 "selfserv: -- SSL: Client Certificate Invalid, err %d.\n%s\n", 499 err, SECU_Strerror(err)); 500 return (MakeCertOK ? SECSuccess : SECFailure); 501 } 502 503 /* Simple SNI socket config function that does not use SSL_ReconfigFD. 504 * Only uses one server name but verifies that the names match. */ 505 PRInt32 506 mySSLSNISocketConfig(PRFileDesc *fd, const SECItem *sniNameArr, 507 PRUint32 sniNameArrSize, void *arg) 508 { 509 PRInt32 i = 0; 510 const SECItem *current = sniNameArr; 511 const char **nameArr = (const char **)arg; 512 secuPWData *pwdata; 513 CERTCertificate *cert = NULL; 514 SECKEYPrivateKey *privKey = NULL; 515 516 PORT_Assert(fd && sniNameArr); 517 if (!fd || !sniNameArr) { 518 return SSL_SNI_SEND_ALERT; 519 } 520 521 pwdata = SSL_RevealPinArg(fd); 522 523 for (; current && (PRUint32)i < sniNameArrSize; i++) { 524 unsigned int j = 0; 525 for (; j < MAX_VIRT_SERVER_NAME_ARRAY_INDEX && nameArr[j]; j++) { 526 if (!PORT_Strncmp(nameArr[j], 527 (const char *)current[i].data, 528 current[i].len) && 529 PORT_Strlen(nameArr[j]) == current[i].len) { 530 const char *nickName = nameArr[j]; 531 if (j == 0) { 532 /* default cert */ 533 return 0; 534 } 535 /* if pwdata is NULL, then we would not get the key and 536 * return an error status. */ 537 cert = PK11_FindCertFromNickname(nickName, &pwdata); 538 if (cert == NULL) { 539 goto loser; /* Send alert */ 540 } 541 privKey = PK11_FindKeyByAnyCert(cert, &pwdata); 542 if (privKey == NULL) { 543 goto loser; /* Send alert */ 544 } 545 if (SSL_ConfigServerCert(fd, cert, privKey, NULL, 0) != SECSuccess) { 546 goto loser; /* Send alert */ 547 } 548 SECKEY_DestroyPrivateKey(privKey); 549 CERT_DestroyCertificate(cert); 550 return i; 551 } 552 } 553 } 554 loser: 555 if (privKey) { 556 SECKEY_DestroyPrivateKey(privKey); 557 } 558 if (cert) { 559 CERT_DestroyCertificate(cert); 560 } 561 return SSL_SNI_SEND_ALERT; 562 } 563 564 /************************************************************************** 565 ** Begin thread management routines and data. 566 **************************************************************************/ 567 #define MIN_THREADS 3 568 #define DEFAULT_THREADS 8 569 #define MAX_THREADS 4096 570 #define MAX_PROCS 25 571 static int maxThreads = DEFAULT_THREADS; 572 573 typedef struct jobStr { 574 PRCList link; 575 PRFileDesc *tcp_sock; 576 PRFileDesc *model_sock; 577 } JOB; 578 579 static PZLock *qLock; /* this lock protects all data immediately below */ 580 static PRLock *lastLoadedCrlLock; /* this lock protects lastLoadedCrl variable */ 581 static PZCondVar *jobQNotEmptyCv; 582 static PZCondVar *freeListNotEmptyCv; 583 static PZCondVar *threadCountChangeCv; 584 static int threadCount; 585 static PRCList jobQ; 586 static PRCList freeJobs; 587 static JOB *jobTable; 588 589 SECStatus 590 setupJobs(int maxJobs) 591 { 592 int i; 593 594 jobTable = (JOB *)PR_Calloc(maxJobs, sizeof(JOB)); 595 if (!jobTable) 596 return SECFailure; 597 598 PR_INIT_CLIST(&jobQ); 599 PR_INIT_CLIST(&freeJobs); 600 601 for (i = 0; i < maxJobs; ++i) { 602 JOB *pJob = jobTable + i; 603 PR_APPEND_LINK(&pJob->link, &freeJobs); 604 } 605 return SECSuccess; 606 } 607 608 typedef int startFn(PRFileDesc *a, PRFileDesc *b); 609 610 typedef enum { rs_idle = 0, 611 rs_running = 1, 612 rs_zombie = 2 } runState; 613 614 typedef struct perThreadStr { 615 PRFileDesc *a; 616 PRFileDesc *b; 617 int rv; 618 startFn *startFunc; 619 PRThread *prThread; 620 runState state; 621 } perThread; 622 623 static perThread *threads; 624 625 void 626 thread_wrapper(void *arg) 627 { 628 perThread *slot = (perThread *)arg; 629 630 slot->rv = (*slot->startFunc)(slot->a, slot->b); 631 632 /* notify the thread exit handler. */ 633 PZ_Lock(qLock); 634 slot->state = rs_zombie; 635 --threadCount; 636 PZ_NotifyAllCondVar(threadCountChangeCv); 637 PZ_Unlock(qLock); 638 } 639 640 int 641 jobLoop(PRFileDesc *a, PRFileDesc *b) 642 { 643 PRCList *myLink = 0; 644 JOB *myJob; 645 646 PZ_Lock(qLock); 647 do { 648 myLink = 0; 649 while (PR_CLIST_IS_EMPTY(&jobQ) && !stopping) { 650 PZ_WaitCondVar(jobQNotEmptyCv, PR_INTERVAL_NO_TIMEOUT); 651 } 652 if (!PR_CLIST_IS_EMPTY(&jobQ)) { 653 myLink = PR_LIST_HEAD(&jobQ); 654 PR_REMOVE_AND_INIT_LINK(myLink); 655 } 656 PZ_Unlock(qLock); 657 myJob = (JOB *)myLink; 658 /* myJob will be null when stopping is true and jobQ is empty */ 659 if (!myJob) 660 break; 661 handle_connection(myJob->tcp_sock, myJob->model_sock); 662 PZ_Lock(qLock); 663 PR_APPEND_LINK(myLink, &freeJobs); 664 PZ_NotifyCondVar(freeListNotEmptyCv); 665 } while (PR_TRUE); 666 return 0; 667 } 668 669 SECStatus 670 launch_threads( 671 startFn *startFunc, 672 PRFileDesc *a, 673 PRFileDesc *b, 674 PRBool local) 675 { 676 int i; 677 SECStatus rv = SECSuccess; 678 679 /* create the thread management serialization structs */ 680 qLock = PZ_NewLock(nssILockSelfServ); 681 jobQNotEmptyCv = PZ_NewCondVar(qLock); 682 freeListNotEmptyCv = PZ_NewCondVar(qLock); 683 threadCountChangeCv = PZ_NewCondVar(qLock); 684 685 /* create monitor for crl reload procedure */ 686 lastLoadedCrlLock = PR_NewLock(); 687 688 /* allocate the array of thread slots */ 689 threads = PR_Calloc(maxThreads, sizeof(perThread)); 690 if (NULL == threads) { 691 fprintf(stderr, "Oh Drat! Can't allocate the perThread array\n"); 692 return SECFailure; 693 } 694 /* 5 is a little extra, intended to keep the jobQ from underflowing. 695 ** That is, from going empty while not stopping and clients are still 696 ** trying to contact us. 697 */ 698 rv = setupJobs(maxThreads + 5); 699 if (rv != SECSuccess) 700 return rv; 701 702 PZ_Lock(qLock); 703 for (i = 0; i < maxThreads; ++i) { 704 perThread *slot = threads + i; 705 706 slot->state = rs_running; 707 slot->a = a; 708 slot->b = b; 709 slot->startFunc = startFunc; 710 slot->prThread = PR_CreateThread(PR_USER_THREAD, 711 thread_wrapper, slot, PR_PRIORITY_NORMAL, 712 (PR_TRUE == 713 local) 714 ? PR_LOCAL_THREAD 715 : PR_GLOBAL_THREAD, 716 PR_JOINABLE_THREAD, 0); 717 if (slot->prThread == NULL) { 718 printf("selfserv: Failed to launch thread!\n"); 719 slot->state = rs_idle; 720 rv = SECFailure; 721 break; 722 } 723 724 ++threadCount; 725 } 726 PZ_Unlock(qLock); 727 728 return rv; 729 } 730 731 #define DESTROY_CONDVAR(name) \ 732 if (name) { \ 733 PZ_DestroyCondVar(name); \ 734 name = NULL; \ 735 } 736 #define DESTROY_LOCK(name) \ 737 if (name) { \ 738 PZ_DestroyLock(name); \ 739 name = NULL; \ 740 } 741 742 void 743 terminateWorkerThreads(void) 744 { 745 int i; 746 747 VLOG(("selfserv: server_thread: waiting on stopping")); 748 PZ_Lock(qLock); 749 PZ_NotifyAllCondVar(jobQNotEmptyCv); 750 PZ_Unlock(qLock); 751 752 /* Wait for worker threads to terminate. */ 753 for (i = 0; i < maxThreads; ++i) { 754 perThread *slot = threads + i; 755 if (slot->prThread) { 756 PR_JoinThread(slot->prThread); 757 } 758 } 759 760 /* The worker threads empty the jobQ before they terminate. */ 761 PZ_Lock(qLock); 762 PORT_Assert(threadCount == 0); 763 PORT_Assert(PR_CLIST_IS_EMPTY(&jobQ)); 764 PZ_Unlock(qLock); 765 766 DESTROY_CONDVAR(jobQNotEmptyCv); 767 DESTROY_CONDVAR(freeListNotEmptyCv); 768 DESTROY_CONDVAR(threadCountChangeCv); 769 770 PR_DestroyLock(lastLoadedCrlLock); 771 DESTROY_LOCK(qLock); 772 PR_Free(jobTable); 773 PR_Free(threads); 774 } 775 776 static void 777 logger(void *arg) 778 { 779 PRFloat64 seconds; 780 PRFloat64 opsPerSec; 781 PRIntervalTime period; 782 PRIntervalTime previousTime; 783 PRIntervalTime latestTime; 784 PRInt32 previousOps; 785 PRInt32 ops; 786 PRIntervalTime logPeriodTicks = PR_TicksPerSecond(); 787 PRFloat64 secondsPerTick = 1.0 / (PRFloat64)logPeriodTicks; 788 int iterations = 0; 789 int secondsElapsed = 0; 790 static PRInt64 totalPeriodBytes = 0; 791 static PRInt64 totalPeriodBytesTCP = 0; 792 793 previousOps = loggerOps; 794 previousTime = PR_IntervalNow(); 795 796 for (;;) { 797 /* OK, implementing a new sleep algorithm here... always sleep 798 * for 1 second but print out info at the user-specified interval. 799 * This way, we don't overflow all of our PR_Atomic* functions and 800 * we don't have to use locks. 801 */ 802 PR_Sleep(logPeriodTicks); 803 secondsElapsed++; 804 totalPeriodBytes += PR_ATOMIC_SET(&loggerBytes, 0); 805 totalPeriodBytesTCP += PR_ATOMIC_SET(&loggerBytesTCP, 0); 806 if (secondsElapsed != logPeriod) { 807 continue; 808 } 809 /* when we reach the user-specified logging interval, print out all 810 * data 811 */ 812 secondsElapsed = 0; 813 latestTime = PR_IntervalNow(); 814 ops = loggerOps; 815 period = latestTime - previousTime; 816 seconds = (PRFloat64)period * secondsPerTick; 817 opsPerSec = (ops - previousOps) / seconds; 818 819 if (testBulk) { 820 if (iterations == 0) { 821 if (loggingLayer == PR_TRUE) { 822 printf("Conn.--------App Data--------TCP Data\n"); 823 } else { 824 printf("Conn.--------App Data\n"); 825 } 826 } 827 if (loggingLayer == PR_TRUE) { 828 printf("%4.d %5.3f MB/s %5.3f MB/s\n", ops, 829 totalPeriodBytes / (seconds * 1048576.0), 830 totalPeriodBytesTCP / (seconds * 1048576.0)); 831 } else { 832 printf("%4.d %5.3f MB/s\n", ops, 833 totalPeriodBytes / (seconds * 1048576.0)); 834 } 835 totalPeriodBytes = 0; 836 totalPeriodBytesTCP = 0; 837 /* Print the "legend" every 20 iterations */ 838 iterations = (iterations + 1) % 20; 839 } else { 840 printf("%.2f ops/second, %d threads\n", opsPerSec, threadCount); 841 } 842 843 fflush(stdout); 844 previousOps = ops; 845 previousTime = latestTime; 846 if (stopping) { 847 break; 848 } 849 } 850 } 851 852 /************************************************************************** 853 ** End thread management routines. 854 **************************************************************************/ 855 856 PRBool useModelSocket = PR_FALSE; 857 static SSLVersionRange enabledVersions; 858 PRBool disableRollBack = PR_FALSE; 859 PRBool NoReuse = PR_FALSE; 860 PRBool hasSidCache = PR_FALSE; 861 PRBool disableLocking = PR_FALSE; 862 PRBool enableSessionTickets = PR_FALSE; 863 PRBool enableZlibCertificateCompression = PR_FALSE; 864 PRBool failedToNegotiateName = PR_FALSE; 865 PRBool enableExtendedMasterSecret = PR_FALSE; 866 PRBool zeroRTT = PR_FALSE; 867 SSLAntiReplayContext *antiReplay = NULL; 868 PRBool enableALPN = PR_FALSE; 869 PRBool enablePostHandshakeAuth = PR_FALSE; 870 SSLNamedGroup *enabledGroups = NULL; 871 unsigned int enabledGroupsCount = 0; 872 const SSLSignatureScheme *enabledSigSchemes = NULL; 873 unsigned int enabledSigSchemeCount = 0; 874 const secuExporter *enabledExporters = NULL; 875 unsigned int enabledExporterCount = 0; 876 877 static char *virtServerNameArray[MAX_VIRT_SERVER_NAME_ARRAY_INDEX]; 878 static int virtServerNameIndex = 1; 879 880 static char *certNicknameArray[MAX_CERT_NICKNAME_ARRAY_INDEX]; 881 static int certNicknameIndex = 0; 882 883 static const char stopCmd[] = { "GET /stop " }; 884 static const char getCmd[] = { "GET " }; 885 static const char EOFmsg[] = { "EOF\r\n\r\n\r\n" }; 886 static const char outHeader[] = { 887 "HTTP/1.0 200 OK\r\n" 888 "Server: Generic Web Server\r\n" 889 "Date: Tue, 26 Aug 1997 22:10:05 GMT\r\n" 890 "Content-type: text/plain\r\n" 891 "\r\n" 892 }; 893 static const char crlCacheErr[] = { "CRL ReCache Error: " }; 894 895 PRUint16 cipherlist[100]; 896 int nciphers; 897 898 void 899 savecipher(int c) 900 { 901 if (nciphers < sizeof cipherlist / sizeof(cipherlist[0])) 902 cipherlist[nciphers++] = (PRUint16)c; 903 } 904 905 #ifdef FULL_DUPLEX_CAPABLE 906 907 struct lockedVarsStr { 908 PZLock *lock; 909 int count; 910 int waiters; 911 PZCondVar *condVar; 912 }; 913 914 typedef struct lockedVarsStr lockedVars; 915 916 void 917 lockedVars_Init(lockedVars *lv) 918 { 919 lv->count = 0; 920 lv->waiters = 0; 921 lv->lock = PZ_NewLock(nssILockSelfServ); 922 lv->condVar = PZ_NewCondVar(lv->lock); 923 } 924 925 void 926 lockedVars_Destroy(lockedVars *lv) 927 { 928 PZ_DestroyCondVar(lv->condVar); 929 lv->condVar = NULL; 930 931 PZ_DestroyLock(lv->lock); 932 lv->lock = NULL; 933 } 934 935 void 936 lockedVars_WaitForDone(lockedVars *lv) 937 { 938 PZ_Lock(lv->lock); 939 while (lv->count > 0) { 940 PZ_WaitCondVar(lv->condVar, PR_INTERVAL_NO_TIMEOUT); 941 } 942 PZ_Unlock(lv->lock); 943 } 944 945 int /* returns count */ 946 lockedVars_AddToCount(lockedVars *lv, int addend) 947 { 948 int rv; 949 950 PZ_Lock(lv->lock); 951 rv = lv->count += addend; 952 if (rv <= 0) { 953 PZ_NotifyCondVar(lv->condVar); 954 } 955 PZ_Unlock(lv->lock); 956 return rv; 957 } 958 959 int 960 do_writes( 961 PRFileDesc *ssl_sock, 962 PRFileDesc *model_sock) 963 { 964 int sent = 0; 965 int count = 0; 966 lockedVars *lv = (lockedVars *)model_sock; 967 968 VLOG(("selfserv: do_writes: starting")); 969 while (sent < bigBuf.len) { 970 971 count = PR_Write(ssl_sock, bigBuf.data + sent, bigBuf.len - sent); 972 if (count < 0) { 973 errWarn("PR_Write bigBuf"); 974 break; 975 } 976 FPRINTF(stderr, "selfserv: PR_Write wrote %d bytes from bigBuf\n", count); 977 sent += count; 978 } 979 if (count >= 0) { /* last write didn't fail. */ 980 PR_Shutdown(ssl_sock, PR_SHUTDOWN_SEND); 981 } 982 983 /* notify the reader that we're done. */ 984 lockedVars_AddToCount(lv, -1); 985 FLUSH; 986 VLOG(("selfserv: do_writes: exiting")); 987 return (sent < bigBuf.len) ? SECFailure : SECSuccess; 988 } 989 990 static int 991 handle_fdx_connection( 992 PRFileDesc *tcp_sock, 993 PRFileDesc *model_sock) 994 { 995 PRFileDesc *ssl_sock = NULL; 996 SECStatus result; 997 int firstTime = 1; 998 lockedVars lv; 999 PRSocketOptionData opt; 1000 char buf[10240]; 1001 1002 VLOG(("selfserv: handle_fdx_connection: starting")); 1003 opt.option = PR_SockOpt_Nonblocking; 1004 opt.value.non_blocking = PR_FALSE; 1005 PR_SetSocketOption(tcp_sock, &opt); 1006 1007 if (useModelSocket && model_sock) { 1008 SECStatus rv; 1009 ssl_sock = SSL_ImportFD(model_sock, tcp_sock); 1010 if (!ssl_sock) { 1011 errWarn("SSL_ImportFD with model"); 1012 goto cleanup; 1013 } 1014 rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 1); 1015 if (rv != SECSuccess) { 1016 errWarn("SSL_ResetHandshake"); 1017 goto cleanup; 1018 } 1019 } else { 1020 ssl_sock = tcp_sock; 1021 } 1022 1023 lockedVars_Init(&lv); 1024 lockedVars_AddToCount(&lv, 1); 1025 1026 /* Attempt to launch the writer thread. */ 1027 result = launch_thread(do_writes, ssl_sock, (PRFileDesc *)&lv); 1028 1029 if (result == SECSuccess) 1030 do { 1031 /* do reads here. */ 1032 int count; 1033 count = PR_Read(ssl_sock, buf, sizeof buf); 1034 if (count < 0) { 1035 errWarn("FDX PR_Read"); 1036 break; 1037 } 1038 FPRINTF(stderr, "selfserv: FDX PR_Read read %d bytes.\n", count); 1039 if (firstTime) { 1040 firstTime = 0; 1041 printSecurityInfo(ssl_sock); 1042 } 1043 } while (lockedVars_AddToCount(&lv, 0) > 0); 1044 1045 /* Wait for writer to finish */ 1046 lockedVars_WaitForDone(&lv); 1047 lockedVars_Destroy(&lv); 1048 FLUSH; 1049 1050 cleanup: 1051 if (ssl_sock) { 1052 PR_Close(ssl_sock); 1053 } else if (tcp_sock) { 1054 PR_Close(tcp_sock); 1055 } 1056 1057 VLOG(("selfserv: handle_fdx_connection: exiting")); 1058 return SECSuccess; 1059 } 1060 1061 #endif 1062 1063 static SECItem *lastLoadedCrl = NULL; 1064 1065 static SECStatus 1066 reload_crl(PRFileDesc *crlFile) 1067 { 1068 SECItem *crlDer; 1069 CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB(); 1070 SECStatus rv; 1071 1072 /* Read in the entire file specified with the -f argument */ 1073 crlDer = PORT_Malloc(sizeof(SECItem)); 1074 if (!crlDer) { 1075 errWarn("Can not allocate memory."); 1076 return SECFailure; 1077 } 1078 1079 rv = SECU_ReadDERFromFile(crlDer, crlFile, PR_FALSE, PR_FALSE); 1080 if (rv != SECSuccess) { 1081 errWarn("Unable to read input file."); 1082 PORT_Free(crlDer); 1083 return SECFailure; 1084 } 1085 1086 PR_Lock(lastLoadedCrlLock); 1087 rv = CERT_CacheCRL(certHandle, crlDer); 1088 if (rv == SECSuccess) { 1089 SECItem *tempItem = crlDer; 1090 if (lastLoadedCrl != NULL) { 1091 rv = CERT_UncacheCRL(certHandle, lastLoadedCrl); 1092 if (rv != SECSuccess) { 1093 errWarn("Unable to uncache crl."); 1094 goto loser; 1095 } 1096 crlDer = lastLoadedCrl; 1097 } else { 1098 crlDer = NULL; 1099 } 1100 lastLoadedCrl = tempItem; 1101 } 1102 1103 loser: 1104 PR_Unlock(lastLoadedCrlLock); 1105 SECITEM_FreeItem(crlDer, PR_TRUE); 1106 return rv; 1107 } 1108 1109 void 1110 stop_server() 1111 { 1112 stopping = 1; 1113 PR_Interrupt(acceptorThread); 1114 PZ_TraceFlush(); 1115 } 1116 1117 SECItemArray * 1118 makeTryLaterOCSPResponse(PLArenaPool *arena) 1119 { 1120 SECItemArray *result = NULL; 1121 SECItem *ocspResponse = NULL; 1122 1123 ocspResponse = CERT_CreateEncodedOCSPErrorResponse(arena, 1124 SEC_ERROR_OCSP_TRY_SERVER_LATER); 1125 if (!ocspResponse) 1126 errExit("cannot created ocspResponse"); 1127 1128 result = SECITEM_AllocArray(arena, NULL, 1); 1129 if (!result) 1130 errExit("cannot allocate multiOcspResponses"); 1131 1132 result->items[0].data = ocspResponse->data; 1133 result->items[0].len = ocspResponse->len; 1134 1135 return result; 1136 } 1137 1138 SECItemArray * 1139 makeCorruptedOCSPResponse(PLArenaPool *arena) 1140 { 1141 SECItemArray *result = NULL; 1142 SECItem *ocspResponse = NULL; 1143 1144 ocspResponse = SECITEM_AllocItem(arena, NULL, 1); 1145 if (!ocspResponse) 1146 errExit("cannot created ocspResponse"); 1147 1148 result = SECITEM_AllocArray(arena, NULL, 1); 1149 if (!result) 1150 errExit("cannot allocate multiOcspResponses"); 1151 1152 result->items[0].data = ocspResponse->data; 1153 result->items[0].len = ocspResponse->len; 1154 1155 return result; 1156 } 1157 1158 SECItemArray * 1159 makeSignedOCSPResponse(PLArenaPool *arena, 1160 CERTCertificate *cert, secuPWData *pwdata) 1161 { 1162 SECItemArray *result = NULL; 1163 SECItem *ocspResponse = NULL; 1164 CERTOCSPSingleResponse **singleResponses; 1165 CERTOCSPSingleResponse *sr = NULL; 1166 CERTOCSPCertID *cid = NULL; 1167 CERTCertificate *ca; 1168 PRTime now = PR_Now(); 1169 PRTime nextUpdate; 1170 1171 PORT_Assert(cert != NULL); 1172 1173 ca = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), ocspStaplingCA); 1174 if (!ca) 1175 errExit("cannot find CA"); 1176 1177 cid = CERT_CreateOCSPCertID(cert, now); 1178 if (!cid) 1179 errExit("cannot created cid"); 1180 1181 nextUpdate = now + (PRTime)60 * 60 * 24 * PR_USEC_PER_SEC; /* plus 1 day */ 1182 1183 switch (ocspStaplingMode) { 1184 case osm_good: 1185 case osm_badsig: 1186 sr = CERT_CreateOCSPSingleResponseGood(arena, cid, now, 1187 &nextUpdate); 1188 break; 1189 case osm_unknown: 1190 sr = CERT_CreateOCSPSingleResponseUnknown(arena, cid, now, 1191 &nextUpdate); 1192 break; 1193 case osm_revoked: 1194 sr = CERT_CreateOCSPSingleResponseRevoked(arena, cid, now, 1195 &nextUpdate, 1196 now - (PRTime)60 * 60 * 24 * PR_USEC_PER_SEC, /* minus 1 day */ 1197 NULL); 1198 break; 1199 default: 1200 PORT_Assert(0); 1201 break; 1202 } 1203 1204 if (!sr) 1205 errExit("cannot create sr"); 1206 1207 /* meaning of value 2: one entry + one end marker */ 1208 singleResponses = PORT_ArenaNewArray(arena, CERTOCSPSingleResponse *, 2); 1209 if (singleResponses == NULL) 1210 errExit("cannot allocate singleResponses"); 1211 1212 singleResponses[0] = sr; 1213 singleResponses[1] = NULL; 1214 1215 ocspResponse = CERT_CreateEncodedOCSPSuccessResponse(arena, 1216 (ocspStaplingMode == osm_badsig) 1217 ? NULL 1218 : ca, 1219 ocspResponderID_byName, now, singleResponses, 1220 &pwdata); 1221 if (!ocspResponse) 1222 errExit("cannot created ocspResponse"); 1223 1224 CERT_DestroyCertificate(ca); 1225 ca = NULL; 1226 1227 result = SECITEM_AllocArray(arena, NULL, 1); 1228 if (!result) 1229 errExit("cannot allocate multiOcspResponses"); 1230 1231 result->items[0].data = ocspResponse->data; 1232 result->items[0].len = ocspResponse->len; 1233 1234 CERT_DestroyOCSPCertID(cid); 1235 cid = NULL; 1236 1237 return result; 1238 } 1239 1240 void 1241 setupCertStatus(PLArenaPool *arena, 1242 CERTCertificate *cert, int index, secuPWData *pwdata) 1243 { 1244 if (ocspStaplingMode == osm_random) { 1245 /* 6 different responses */ 1246 int r = rand() % 6; 1247 switch (r) { 1248 case 0: 1249 ocspStaplingMode = osm_good; 1250 break; 1251 case 1: 1252 ocspStaplingMode = osm_revoked; 1253 break; 1254 case 2: 1255 ocspStaplingMode = osm_unknown; 1256 break; 1257 case 3: 1258 ocspStaplingMode = osm_badsig; 1259 break; 1260 case 4: 1261 ocspStaplingMode = osm_corrupted; 1262 break; 1263 case 5: 1264 ocspStaplingMode = osm_failure; 1265 break; 1266 default: 1267 PORT_Assert(0); 1268 break; 1269 } 1270 } 1271 if (ocspStaplingMode != osm_disabled) { 1272 SECItemArray *multiOcspResponses = NULL; 1273 switch (ocspStaplingMode) { 1274 case osm_good: 1275 case osm_revoked: 1276 case osm_unknown: 1277 case osm_badsig: 1278 multiOcspResponses = 1279 makeSignedOCSPResponse(arena, cert, 1280 pwdata); 1281 break; 1282 case osm_corrupted: 1283 multiOcspResponses = makeCorruptedOCSPResponse(arena); 1284 break; 1285 case osm_failure: 1286 multiOcspResponses = makeTryLaterOCSPResponse(arena); 1287 break; 1288 case osm_ocsp: 1289 errExit("stapling mode \"ocsp\" not implemented"); 1290 break; 1291 break; 1292 default: 1293 break; 1294 } 1295 if (multiOcspResponses) { 1296 certStatus[index] = multiOcspResponses; 1297 } 1298 } 1299 } 1300 1301 int 1302 handle_connection(PRFileDesc *tcp_sock, PRFileDesc *model_sock) 1303 { 1304 PRFileDesc *ssl_sock = NULL; 1305 PRFileDesc *local_file_fd = NULL; 1306 char *post; 1307 char *pBuf; /* unused space at end of buf */ 1308 const char *errString; 1309 PRStatus status; 1310 int bufRem; /* unused bytes at end of buf */ 1311 int bufDat; /* characters received in buf */ 1312 int newln = 0; /* # of consecutive newlns */ 1313 int firstTime = 1; 1314 int reqLen; 1315 int rv; 1316 int numIOVs; 1317 PRSocketOptionData opt; 1318 PRIOVec iovs[16]; 1319 char msgBuf[160]; 1320 char buf[10240] = { 0 }; 1321 char fileName[513]; 1322 char proto[128]; 1323 PRDescIdentity aboveLayer = PR_INVALID_IO_LAYER; 1324 1325 pBuf = buf; 1326 bufRem = sizeof buf; 1327 1328 VLOG(("selfserv: handle_connection: starting")); 1329 opt.option = PR_SockOpt_Nonblocking; 1330 opt.value.non_blocking = PR_FALSE; 1331 PR_SetSocketOption(tcp_sock, &opt); 1332 1333 VLOG(("selfserv: handle_connection: starting\n")); 1334 if (useModelSocket && model_sock) { 1335 ssl_sock = SSL_ImportFD(model_sock, tcp_sock); 1336 if (!ssl_sock) { 1337 errWarn("SSL_ImportFD with model"); 1338 goto cleanup; 1339 } 1340 rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 1); 1341 if (rv != SECSuccess) { 1342 errWarn("SSL_ResetHandshake"); 1343 goto cleanup; 1344 } 1345 } else { 1346 ssl_sock = tcp_sock; 1347 } 1348 1349 if (loggingLayer) { 1350 /* find the layer where our new layer is to be pushed */ 1351 aboveLayer = PR_GetLayersIdentity(ssl_sock->lower); 1352 if (aboveLayer == PR_INVALID_IO_LAYER) { 1353 errExit("PRGetUniqueIdentity"); 1354 } 1355 /* create the new layer - this is a very cheap operation */ 1356 loggingFD = PR_CreateIOLayerStub(log_layer_id, &loggingMethods); 1357 if (!loggingFD) 1358 errExit("PR_CreateIOLayerStub"); 1359 /* push the layer below ssl but above TCP */ 1360 rv = PR_PushIOLayer(ssl_sock, aboveLayer, loggingFD); 1361 if (rv != PR_SUCCESS) { 1362 errExit("PR_PushIOLayer"); 1363 } 1364 } 1365 1366 if (noDelay) { 1367 opt.option = PR_SockOpt_NoDelay; 1368 opt.value.no_delay = PR_TRUE; 1369 status = PR_SetSocketOption(ssl_sock, &opt); 1370 if (status != PR_SUCCESS) { 1371 errWarn("PR_SetSocketOption(PR_SockOpt_NoDelay, PR_TRUE)"); 1372 if (ssl_sock) { 1373 PR_Close(ssl_sock); 1374 } 1375 return SECFailure; 1376 } 1377 } 1378 1379 while (1) { 1380 newln = 0; 1381 reqLen = 0; 1382 rv = PR_Read(ssl_sock, pBuf, bufRem - 1); 1383 if (rv == 0 || 1384 (rv < 0 && PR_END_OF_FILE_ERROR == PR_GetError())) { 1385 if (verbose) 1386 errWarn("HDX PR_Read hit EOF"); 1387 break; 1388 } 1389 if (rv < 0) { 1390 errWarn("HDX PR_Read"); 1391 goto cleanup; 1392 } 1393 /* NULL termination */ 1394 pBuf[rv] = 0; 1395 if (firstTime) { 1396 firstTime = 0; 1397 printSecurityInfo(ssl_sock); 1398 } 1399 1400 pBuf += rv; 1401 bufRem -= rv; 1402 bufDat = pBuf - buf; 1403 /* Parse the input, starting at the beginning of the buffer. 1404 * Stop when we detect two consecutive \n's (or \r\n's) 1405 * as this signifies the end of the GET or POST portion. 1406 * The posted data follows. 1407 */ 1408 while (reqLen < bufDat && newln < 2) { 1409 int octet = buf[reqLen++]; 1410 if (octet == '\n') { 1411 newln++; 1412 } else if (octet != '\r') { 1413 newln = 0; 1414 } 1415 } 1416 1417 /* came to the end of the buffer, or second newln 1418 * If we didn't get an empty line (CRLFCRLF) then keep on reading. 1419 */ 1420 if (newln < 2) 1421 continue; 1422 1423 /* we're at the end of the HTTP request. 1424 * If the request is a POST, then there will be one more 1425 * line of data. 1426 * This parsing is a hack, but ok for SSL test purposes. 1427 */ 1428 post = PORT_Strstr(buf, "POST "); 1429 if (!post || *post != 'P') 1430 break; 1431 1432 /* It's a post, so look for the next and final CR/LF. */ 1433 /* We should parse content length here, but ... */ 1434 while (reqLen < bufDat && newln < 3) { 1435 int octet = buf[reqLen++]; 1436 if (octet == '\n') { 1437 newln++; 1438 } 1439 } 1440 if (newln == 3) 1441 break; 1442 } /* read loop */ 1443 1444 bufDat = pBuf - buf; 1445 if (bufDat) 1446 do { /* just close if no data */ 1447 /* Have either (a) a complete get, (b) a complete post, (c) EOF */ 1448 if (reqLen > 0 && !strncmp(buf, getCmd, sizeof getCmd - 1)) { 1449 char *fnBegin = buf + 4; 1450 char *fnEnd; 1451 PRFileInfo info; 1452 /* try to open the file named. 1453 * If successful, then write it to the client. 1454 */ 1455 fnEnd = strpbrk(fnBegin, " \r\n"); 1456 if (fnEnd) { 1457 int fnLen = fnEnd - fnBegin; 1458 if (fnLen < sizeof fileName) { 1459 char *real_fileName = fileName; 1460 char *protoEnd = NULL; 1461 strncpy(fileName, fnBegin, fnLen); 1462 fileName[fnLen] = 0; /* null terminate */ 1463 if ((protoEnd = strstr(fileName, "://")) != NULL) { 1464 int protoLen = PR_MIN(protoEnd - fileName, sizeof(proto) - 1); 1465 PL_strncpy(proto, fileName, protoLen); 1466 proto[protoLen] = 0; 1467 real_fileName = protoEnd + 3; 1468 } else { 1469 proto[0] = 0; 1470 } 1471 status = PR_GetFileInfo(real_fileName, &info); 1472 if (status == PR_SUCCESS && 1473 info.type == PR_FILE_FILE && 1474 info.size >= 0) { 1475 local_file_fd = PR_Open(real_fileName, PR_RDONLY, 0); 1476 } 1477 } 1478 } 1479 } 1480 /* if user has requested client auth in a subsequent handshake, 1481 * do it here. 1482 */ 1483 if (requestCert > 2) { /* request cert was 3 or 4 */ 1484 CERTCertificate *cert = SSL_PeerCertificate(ssl_sock); 1485 if (cert) { 1486 CERT_DestroyCertificate(cert); 1487 } else { 1488 rv = SSL_OptionSet(ssl_sock, SSL_REQUEST_CERTIFICATE, 1); 1489 if (rv < 0) { 1490 errWarn("second SSL_OptionSet SSL_REQUEST_CERTIFICATE"); 1491 break; 1492 } 1493 rv = SSL_OptionSet(ssl_sock, SSL_REQUIRE_CERTIFICATE, 1494 (requestCert == 4)); 1495 if (rv < 0) { 1496 errWarn("second SSL_OptionSet SSL_REQUIRE_CERTIFICATE"); 1497 break; 1498 } 1499 if (enablePostHandshakeAuth) { 1500 rv = SSL_SendCertificateRequest(ssl_sock); 1501 if (rv != SECSuccess) { 1502 errWarn("SSL_SendCertificateRequest"); 1503 break; 1504 } 1505 rv = SSL_ForceHandshake(ssl_sock); 1506 if (rv != SECSuccess) { 1507 errWarn("SSL_ForceHandshake"); 1508 break; 1509 } 1510 } else { 1511 rv = SSL_ReHandshake(ssl_sock, PR_TRUE); 1512 if (rv != 0) { 1513 errWarn("SSL_ReHandshake"); 1514 break; 1515 } 1516 rv = SSL_ForceHandshake(ssl_sock); 1517 if (rv < 0) { 1518 errWarn("SSL_ForceHandshake"); 1519 break; 1520 } 1521 } 1522 } 1523 } 1524 1525 numIOVs = 0; 1526 1527 iovs[numIOVs].iov_base = (char *)outHeader; 1528 iovs[numIOVs].iov_len = (sizeof(outHeader)) - 1; 1529 numIOVs++; 1530 1531 if (local_file_fd) { 1532 PRInt32 bytes; 1533 int errLen; 1534 if (!PL_strlen(proto) || !PL_strcmp(proto, "file")) { 1535 bytes = PR_TransmitFile(ssl_sock, local_file_fd, outHeader, 1536 sizeof outHeader - 1, 1537 PR_TRANSMITFILE_KEEP_OPEN, 1538 PR_INTERVAL_NO_TIMEOUT); 1539 if (bytes >= 0) { 1540 bytes -= sizeof outHeader - 1; 1541 FPRINTF(stderr, 1542 "selfserv: PR_TransmitFile wrote %d bytes from %s\n", 1543 bytes, fileName); 1544 break; 1545 } 1546 errString = errWarn("PR_TransmitFile"); 1547 errLen = PORT_Strlen(errString); 1548 errLen = PR_MIN(errLen, sizeof msgBuf - 1); 1549 PORT_Memcpy(msgBuf, errString, errLen); 1550 msgBuf[errLen] = 0; 1551 1552 iovs[numIOVs].iov_base = msgBuf; 1553 iovs[numIOVs].iov_len = PORT_Strlen(msgBuf); 1554 numIOVs++; 1555 } 1556 if (!PL_strcmp(proto, "crl")) { 1557 if (reload_crl(local_file_fd) == SECFailure) { 1558 errString = errWarn("CERT_CacheCRL"); 1559 if (!errString) 1560 errString = "Unknow error"; 1561 PR_snprintf(msgBuf, sizeof(msgBuf), "%s%s ", 1562 crlCacheErr, errString); 1563 1564 iovs[numIOVs].iov_base = msgBuf; 1565 iovs[numIOVs].iov_len = PORT_Strlen(msgBuf); 1566 numIOVs++; 1567 } else { 1568 FPRINTF(stderr, 1569 "selfserv: CRL %s reloaded.\n", 1570 fileName); 1571 break; 1572 } 1573 } 1574 } else if (reqLen <= 0) { /* hit eof */ 1575 snprintf(msgBuf, sizeof(msgBuf), "Get or Post incomplete after %d bytes.\r\n", 1576 bufDat); 1577 1578 iovs[numIOVs].iov_base = msgBuf; 1579 iovs[numIOVs].iov_len = PORT_Strlen(msgBuf); 1580 numIOVs++; 1581 } else if (reqLen < bufDat) { 1582 snprintf(msgBuf, sizeof(msgBuf), "Discarded %d characters.\r\n", 1583 bufDat - reqLen); 1584 1585 iovs[numIOVs].iov_base = msgBuf; 1586 iovs[numIOVs].iov_len = PORT_Strlen(msgBuf); 1587 numIOVs++; 1588 } 1589 1590 if (reqLen > 0) { 1591 if (verbose > 1) 1592 fwrite(buf, 1, reqLen, stdout); /* display it */ 1593 1594 iovs[numIOVs].iov_base = buf; 1595 iovs[numIOVs].iov_len = reqLen; 1596 numIOVs++; 1597 } 1598 1599 /* Don't add the EOF if we want to test bulk encryption */ 1600 if (!testBulk) { 1601 iovs[numIOVs].iov_base = (char *)EOFmsg; 1602 iovs[numIOVs].iov_len = sizeof EOFmsg - 1; 1603 numIOVs++; 1604 } 1605 1606 rv = PR_Writev(ssl_sock, iovs, numIOVs, PR_INTERVAL_NO_TIMEOUT); 1607 if (rv < 0) { 1608 errWarn("PR_Writev"); 1609 break; 1610 } 1611 1612 /* Send testBulkTotal chunks to the client. Unlimited if 0. */ 1613 if (testBulk) { 1614 while (0 < (rv = PR_Write(ssl_sock, testBulkBuf, testBulkSize))) { 1615 PR_ATOMIC_ADD(&loggerBytes, rv); 1616 PR_ATOMIC_INCREMENT(&bulkSentChunks); 1617 if ((bulkSentChunks > testBulkTotal) && (testBulkTotal != 0)) 1618 break; 1619 } 1620 1621 /* There was a write error, so close this connection. */ 1622 if (bulkSentChunks <= testBulkTotal) { 1623 errWarn("PR_Write"); 1624 } 1625 PR_ATOMIC_DECREMENT(&loggerOps); 1626 break; 1627 } 1628 } while (0); 1629 1630 cleanup: 1631 if (ssl_sock) { 1632 PR_Close(ssl_sock); 1633 } else if (tcp_sock) { 1634 PR_Close(tcp_sock); 1635 } 1636 if (local_file_fd) 1637 PR_Close(local_file_fd); 1638 VLOG(("selfserv: handle_connection: exiting\n")); 1639 1640 /* do a nice shutdown if asked. */ 1641 if (!strncmp(buf, stopCmd, sizeof stopCmd - 1)) { 1642 VLOG(("selfserv: handle_connection: stop command")); 1643 stop_server(); 1644 } 1645 VLOG(("selfserv: handle_connection: exiting")); 1646 return SECSuccess; /* success */ 1647 } 1648 1649 #ifdef XP_UNIX 1650 1651 void 1652 sigusr1_handler(int sig) 1653 { 1654 VLOG(("selfserv: sigusr1_handler: stop server")); 1655 stop_server(); 1656 } 1657 1658 #endif 1659 1660 SECStatus 1661 do_accepts( 1662 PRFileDesc *listen_sock, 1663 PRFileDesc *model_sock) 1664 { 1665 PRNetAddr addr; 1666 PRErrorCode perr; 1667 #ifdef XP_UNIX 1668 struct sigaction act; 1669 #endif 1670 1671 VLOG(("selfserv: do_accepts: starting")); 1672 PR_SetThreadPriority(PR_GetCurrentThread(), PR_PRIORITY_HIGH); 1673 1674 acceptorThread = PR_GetCurrentThread(); 1675 #ifdef XP_UNIX 1676 /* set up the signal handler */ 1677 act.sa_handler = sigusr1_handler; 1678 sigemptyset(&act.sa_mask); 1679 act.sa_flags = 0; 1680 if (sigaction(SIGUSR1, &act, NULL)) { 1681 fprintf(stderr, "Error installing signal handler.\n"); 1682 exit(1); 1683 } 1684 #endif 1685 while (!stopping) { 1686 PRFileDesc *tcp_sock; 1687 PRCList *myLink; 1688 1689 FPRINTF(stderr, "\n\n\nselfserv: About to call accept.\n"); 1690 tcp_sock = PR_Accept(listen_sock, &addr, PR_INTERVAL_NO_TIMEOUT); 1691 if (tcp_sock == NULL) { 1692 perr = PR_GetError(); 1693 if ((perr != PR_CONNECT_RESET_ERROR && 1694 perr != PR_PENDING_INTERRUPT_ERROR) || 1695 verbose) { 1696 errWarn("PR_Accept"); 1697 } 1698 if (perr == PR_CONNECT_RESET_ERROR) { 1699 FPRINTF(stderr, 1700 "Ignoring PR_CONNECT_RESET_ERROR error - continue\n"); 1701 continue; 1702 } 1703 stopping = 1; 1704 break; 1705 } 1706 1707 VLOG(("selfserv: do_accept: Got connection\n")); 1708 1709 if (logStats) { 1710 PR_ATOMIC_INCREMENT(&loggerOps); 1711 } 1712 1713 PZ_Lock(qLock); 1714 while (PR_CLIST_IS_EMPTY(&freeJobs) && !stopping) { 1715 PZ_WaitCondVar(freeListNotEmptyCv, PR_INTERVAL_NO_TIMEOUT); 1716 } 1717 if (stopping) { 1718 PZ_Unlock(qLock); 1719 if (tcp_sock) { 1720 PR_Close(tcp_sock); 1721 } 1722 break; 1723 } 1724 myLink = PR_LIST_HEAD(&freeJobs); 1725 PR_REMOVE_AND_INIT_LINK(myLink); 1726 /* could release qLock here and reaquire it 7 lines below, but 1727 ** why bother for 4 assignment statements? 1728 */ 1729 { 1730 JOB *myJob = (JOB *)myLink; 1731 myJob->tcp_sock = tcp_sock; 1732 myJob->model_sock = model_sock; 1733 } 1734 1735 PR_APPEND_LINK(myLink, &jobQ); 1736 PZ_NotifyCondVar(jobQNotEmptyCv); 1737 PZ_Unlock(qLock); 1738 } 1739 1740 FPRINTF(stderr, "selfserv: Closing listen socket.\n"); 1741 VLOG(("selfserv: do_accepts: exiting")); 1742 if (listen_sock) { 1743 PR_Close(listen_sock); 1744 } 1745 return SECSuccess; 1746 } 1747 1748 PRFileDesc * 1749 getBoundListenSocket(unsigned short port) 1750 { 1751 PRFileDesc *listen_sock = NULL; 1752 int listenQueueDepth = 5 + (2 * maxThreads); 1753 PRStatus prStatus; 1754 PRNetAddr addr; 1755 PRSocketOptionData opt; 1756 1757 // We want to listen on the IP family that tstclnt will use. 1758 // tstclnt uses PR_GetPrefLoopbackAddrInfo to decide, if it's 1759 // asked to connect to localhost. 1760 1761 prStatus = PR_GetPrefLoopbackAddrInfo(&addr, port); 1762 if (prStatus == PR_FAILURE) { 1763 addr.inet.family = PR_AF_INET; 1764 addr.inet.ip = PR_htonl(PR_INADDR_ANY); 1765 addr.inet.port = PR_htons(port); 1766 } 1767 1768 if (addr.inet.family == PR_AF_INET6) { 1769 listen_sock = PR_OpenTCPSocket(PR_AF_INET6); 1770 } else if (addr.inet.family == PR_AF_INET) { 1771 listen_sock = PR_NewTCPSocket(); 1772 } 1773 if (listen_sock == NULL) { 1774 errExit("Couldn't create socket"); 1775 } 1776 1777 opt.option = PR_SockOpt_Nonblocking; 1778 opt.value.non_blocking = PR_FALSE; 1779 prStatus = PR_SetSocketOption(listen_sock, &opt); 1780 if (prStatus < 0) { 1781 PR_Close(listen_sock); 1782 errExit("PR_SetSocketOption(PR_SockOpt_Nonblocking)"); 1783 } 1784 1785 opt.option = PR_SockOpt_Reuseaddr; 1786 opt.value.reuse_addr = PR_TRUE; 1787 prStatus = PR_SetSocketOption(listen_sock, &opt); 1788 if (prStatus < 0) { 1789 PR_Close(listen_sock); 1790 errExit("PR_SetSocketOption(PR_SockOpt_Reuseaddr)"); 1791 } 1792 1793 /* Set PR_SockOpt_Linger because it helps prevent a server bind issue 1794 * after clean shutdown . See bug 331413 . 1795 */ 1796 opt.option = PR_SockOpt_Linger; 1797 opt.value.linger.polarity = PR_TRUE; 1798 opt.value.linger.linger = PR_SecondsToInterval(1); 1799 prStatus = PR_SetSocketOption(listen_sock, &opt); 1800 if (prStatus < 0) { 1801 PR_Close(listen_sock); 1802 errExit("PR_SetSocketOption(PR_SockOpt_Linger)"); 1803 } 1804 1805 prStatus = PR_Bind(listen_sock, &addr); 1806 if (prStatus < 0) { 1807 PR_Close(listen_sock); 1808 errExit("PR_Bind"); 1809 } 1810 1811 prStatus = PR_Listen(listen_sock, listenQueueDepth); 1812 if (prStatus < 0) { 1813 PR_Close(listen_sock); 1814 errExit("PR_Listen"); 1815 } 1816 return listen_sock; 1817 } 1818 1819 PRInt32 PR_CALLBACK 1820 logWritev( 1821 PRFileDesc *fd, 1822 const PRIOVec *iov, 1823 PRInt32 size, 1824 PRIntervalTime timeout) 1825 { 1826 PRInt32 rv = (fd->lower->methods->writev)(fd->lower, iov, size, 1827 timeout); 1828 /* Add the amount written, but not if there's an error */ 1829 if (rv > 0) 1830 PR_ATOMIC_ADD(&loggerBytesTCP, rv); 1831 return rv; 1832 } 1833 1834 PRInt32 PR_CALLBACK 1835 logWrite( 1836 PRFileDesc *fd, 1837 const void *buf, 1838 PRInt32 amount) 1839 { 1840 PRInt32 rv = (fd->lower->methods->write)(fd->lower, buf, amount); 1841 /* Add the amount written, but not if there's an error */ 1842 if (rv > 0) 1843 PR_ATOMIC_ADD(&loggerBytesTCP, rv); 1844 1845 return rv; 1846 } 1847 1848 PRInt32 PR_CALLBACK 1849 logSend( 1850 PRFileDesc *fd, 1851 const void *buf, 1852 PRInt32 amount, 1853 PRIntn flags, 1854 PRIntervalTime timeout) 1855 { 1856 PRInt32 rv = (fd->lower->methods->send)(fd->lower, buf, amount, 1857 flags, timeout); 1858 /* Add the amount written, but not if there's an error */ 1859 if (rv > 0) 1860 PR_ATOMIC_ADD(&loggerBytesTCP, rv); 1861 return rv; 1862 } 1863 1864 void 1865 initLoggingLayer(void) 1866 { 1867 /* get a new layer ID */ 1868 log_layer_id = PR_GetUniqueIdentity("Selfserv Logging"); 1869 if (log_layer_id == PR_INVALID_IO_LAYER) 1870 errExit("PR_GetUniqueIdentity"); 1871 1872 /* setup the default IO methods with my custom write methods */ 1873 memcpy(&loggingMethods, PR_GetDefaultIOMethods(), sizeof(PRIOMethods)); 1874 loggingMethods.writev = logWritev; 1875 loggingMethods.write = logWrite; 1876 loggingMethods.send = logSend; 1877 } 1878 1879 void 1880 handshakeCallback(PRFileDesc *fd, void *client_data) 1881 { 1882 const char *handshakeName = (const char *)client_data; 1883 if (handshakeName && !failedToNegotiateName) { 1884 SECItem *hostInfo = SSL_GetNegotiatedHostInfo(fd); 1885 if (!hostInfo || PORT_Strncmp(handshakeName, (char *)hostInfo->data, 1886 hostInfo->len)) { 1887 failedToNegotiateName = PR_TRUE; 1888 } 1889 if (hostInfo) { 1890 SECITEM_FreeItem(hostInfo, PR_TRUE); 1891 } 1892 } 1893 if (enabledExporters) { 1894 SECStatus rv = exportKeyingMaterials(fd, enabledExporters, enabledExporterCount); 1895 if (rv != SECSuccess) { 1896 PRErrorCode err = PR_GetError(); 1897 fprintf(stderr, 1898 "couldn't export keying material: %s\n", 1899 SECU_Strerror(err)); 1900 } 1901 } 1902 } 1903 1904 static SECStatus 1905 importPsk(PRFileDesc *model_sock) 1906 { 1907 SECU_PrintAsHex(stdout, &psk, "Using External PSK", 0); 1908 PK11SlotInfo *slot = NULL; 1909 PK11SymKey *symKey = NULL; 1910 slot = PK11_GetInternalSlot(); 1911 if (!slot) { 1912 errWarn("PK11_GetInternalSlot failed"); 1913 return SECFailure; 1914 } 1915 symKey = PK11_ImportSymKey(slot, CKM_HKDF_KEY_GEN, PK11_OriginUnwrap, 1916 CKA_DERIVE, &psk, NULL); 1917 PK11_FreeSlot(slot); 1918 if (!symKey) { 1919 errWarn("PK11_ImportSymKey failed\n"); 1920 return SECFailure; 1921 } 1922 1923 SECStatus rv = SSL_AddExternalPsk(model_sock, symKey, 1924 (const PRUint8 *)pskLabel.data, 1925 pskLabel.len, ssl_hash_sha256); 1926 PK11_FreeSymKey(symKey); 1927 return rv; 1928 } 1929 1930 static SECStatus 1931 configureEchWithPublicName(PRFileDesc *model_sock, const char *public_name) 1932 { 1933 SECStatus rv; 1934 1935 #define OID_LEN 65 1936 unsigned char paramBuf[OID_LEN]; 1937 SECItem ecParams = { siBuffer, paramBuf, sizeof(paramBuf) }; 1938 SECKEYPublicKey *pubKey = NULL; 1939 SECKEYPrivateKey *privKey = NULL; 1940 SECOidData *oidData; 1941 char *echConfigBase64 = NULL; 1942 PRUint8 configId = 0; 1943 PRUint8 configBuf[1000]; 1944 unsigned int len = 0; 1945 HpkeSymmetricSuite echCipherSuite = { HpkeKdfHkdfSha256, 1946 HpkeAeadChaCha20Poly1305 }; 1947 1948 PK11SlotInfo *slot = PK11_GetInternalKeySlot(); 1949 if (!slot) { 1950 errWarn("PK11_GetInternalKeySlot failed"); 1951 return SECFailure; 1952 } 1953 1954 if (PK11_GenerateRandom(&configId, sizeof(configId)) != SECSuccess) { 1955 errWarn("Failed to generate random configId"); 1956 goto loser; 1957 } 1958 1959 oidData = SECOID_FindOIDByTag(SEC_OID_CURVE25519); 1960 if (oidData && (2 + oidData->oid.len) < sizeof(paramBuf)) { 1961 ecParams.data[0] = SEC_ASN1_OBJECT_ID; 1962 ecParams.data[1] = oidData->oid.len; 1963 memcpy(ecParams.data + 2, oidData->oid.data, oidData->oid.len); 1964 ecParams.len = oidData->oid.len + 2; 1965 } else { 1966 errWarn("SECOID_FindOIDByTag failed"); 1967 goto loser; 1968 } 1969 privKey = PK11_GenerateKeyPair(slot, CKM_EC_KEY_PAIR_GEN, &ecParams, 1970 &pubKey, PR_FALSE, PR_FALSE, NULL); 1971 if (!privKey || !pubKey) { 1972 errWarn("Failed to generate ECH keypair"); 1973 goto loser; 1974 } 1975 1976 rv = SSL_EncodeEchConfigId(configId, public_name, 100, 1977 HpkeDhKemX25519Sha256, pubKey, 1978 &echCipherSuite, 1, 1979 configBuf, &len, sizeof(configBuf)); 1980 if (rv != SECSuccess) { 1981 errWarn("SSL_EncodeEchConfigId failed"); 1982 goto loser; 1983 } 1984 1985 rv = SSL_SetServerEchConfigs(model_sock, pubKey, privKey, configBuf, len); 1986 if (rv != SECSuccess) { 1987 errWarn("SSL_SetServerEchConfigs failed"); 1988 goto loser; 1989 } 1990 1991 SECItem echConfigItem = { siBuffer, configBuf, len }; 1992 echConfigBase64 = NSSBase64_EncodeItem(NULL, NULL, 0, &echConfigItem); 1993 if (!echConfigBase64) { 1994 errWarn("NSSBase64_EncodeItem failed"); 1995 goto loser; 1996 } 1997 1998 // Remove the newline characters that NSSBase64_EncodeItem unhelpfully inserts. 1999 char *newline = strstr(echConfigBase64, "\r\n"); 2000 if (newline) { 2001 memmove(newline, newline + 2, strlen(newline + 2) + 1); 2002 } 2003 2004 printf("%s\n", echConfigBase64); 2005 PORT_Free(echConfigBase64); 2006 SECKEY_DestroyPrivateKey(privKey); 2007 SECKEY_DestroyPublicKey(pubKey); 2008 PK11_FreeSlot(slot); 2009 return SECSuccess; 2010 2011 loser: 2012 PORT_Free(echConfigBase64); 2013 SECKEY_DestroyPrivateKey(privKey); 2014 SECKEY_DestroyPublicKey(pubKey); 2015 PK11_FreeSlot(slot); 2016 return SECFailure; 2017 } 2018 2019 static SECStatus 2020 configureEchWithData(PRFileDesc *model_sock) 2021 { 2022 /* The input should be a Base64-encoded ECHKey struct: 2023 * struct { 2024 * opaque pkcs8_ech_keypair<0..2^16-1>; 2025 * ECHConfigs configs<0..2^16>; // draft-ietf-tls-esni-09 2026 * } ECHKey; 2027 * 2028 * This is not a standardized format, rather it's designed for 2029 * interoperability with https://github.com/xvzcf/tls-interop-runner. 2030 * It is the user's responsibility to ensure that the PKCS8 keypair 2031 * corresponds to the public key embedded in the ECHConfigs. 2032 */ 2033 2034 #define REMAINING_BYTES(rdr, buf) \ 2035 buf->len - (rdr - buf->data) 2036 2037 SECStatus rv; 2038 size_t len; 2039 unsigned char *reader; 2040 PK11SlotInfo *slot = NULL; 2041 SECItem *decoded = NULL; 2042 SECKEYPublicKey *pk = NULL; 2043 SECKEYPrivateKey *sk = NULL; 2044 SECItem pkcs8Key = { siBuffer, NULL, 0 }; 2045 2046 decoded = NSSBase64_DecodeBuffer(NULL, NULL, echParamsStr, PORT_Strlen(echParamsStr)); 2047 if (!decoded || decoded->len < 2) { 2048 errWarn("Couldn't decode ECHParams"); 2049 goto loser; 2050 }; 2051 reader = decoded->data; 2052 2053 len = (*(reader++) << 8); 2054 len |= *(reader++); 2055 if (len > (REMAINING_BYTES(reader, decoded) - 2)) { 2056 errWarn("Bad ECHParams encoding"); 2057 goto loser; 2058 } 2059 pkcs8Key.data = reader; 2060 pkcs8Key.len = len; 2061 reader += len; 2062 2063 /* Convert the key bytes to key handles */ 2064 slot = PK11_GetInternalKeySlot(); 2065 rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( 2066 slot, &pkcs8Key, NULL, NULL, PR_FALSE, PR_FALSE, KU_ALL, &sk, NULL); 2067 if (rv != SECSuccess || !sk) { 2068 errWarn("ECH key import failed"); 2069 goto loser; 2070 } 2071 pk = SECKEY_ConvertToPublicKey(sk); 2072 if (!pk) { 2073 errWarn("ECH key conversion failed"); 2074 goto loser; 2075 } 2076 2077 /* Remainder is the ECHConfigs. */ 2078 rv = SSL_SetServerEchConfigs(model_sock, pk, sk, reader, 2079 REMAINING_BYTES(reader, decoded)); 2080 if (rv != SECSuccess) { 2081 errWarn("SSL_SetServerEchConfigs failed"); 2082 goto loser; 2083 } 2084 2085 PK11_FreeSlot(slot); 2086 SECKEY_DestroyPrivateKey(sk); 2087 SECKEY_DestroyPublicKey(pk); 2088 SECITEM_FreeItem(decoded, PR_TRUE); 2089 return SECSuccess; 2090 loser: 2091 if (slot) { 2092 PK11_FreeSlot(slot); 2093 } 2094 SECKEY_DestroyPrivateKey(sk); 2095 SECKEY_DestroyPublicKey(pk); 2096 SECITEM_FreeItem(decoded, PR_TRUE); 2097 return SECFailure; 2098 } 2099 2100 static SECStatus 2101 configureEch(PRFileDesc *model_sock) 2102 { 2103 if (!PORT_Strncmp(echParamsStr, "publicname:", PORT_Strlen("publicname:"))) { 2104 return configureEchWithPublicName(model_sock, 2105 &echParamsStr[PORT_Strlen("publicname:")]); 2106 } 2107 return configureEchWithData(model_sock); 2108 } 2109 2110 static SECStatus 2111 zlibCertificateDecode(const SECItem *input, 2112 unsigned char *output, size_t outputLen, 2113 size_t *usedLen) 2114 { 2115 if (!input || !input->data || input->len == 0 || !output || outputLen == 0) { 2116 PR_SetError(SEC_ERROR_INVALID_ARGS, 0); 2117 return SECFailure; 2118 } 2119 2120 unsigned long outputLenUL = outputLen; 2121 int ret = uncompress(output, &outputLenUL, input->data, input->len); 2122 *usedLen = outputLenUL; 2123 if (ret != Z_OK) { 2124 PR_SetError(SEC_ERROR_BAD_DATA, 0); 2125 return SECFailure; 2126 } 2127 2128 return SECSuccess; 2129 } 2130 2131 static SECStatus 2132 zlibCertificateEncode(const SECItem *input, SECItem *output) 2133 { 2134 if (!input || !input->data || input->len == 0 || !output) { 2135 PR_SetError(SEC_ERROR_INVALID_ARGS, 0); 2136 return SECFailure; 2137 } 2138 2139 unsigned long maxCompressedLen = compressBound(input->len); 2140 SECITEM_AllocItem(NULL, output, maxCompressedLen); 2141 2142 unsigned long outputLenUL = output->len; 2143 int ret = compress(output->data, &outputLenUL, input->data, input->len); 2144 output->len = outputLenUL; 2145 if (ret != Z_OK) { 2146 PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0); 2147 return SECFailure; 2148 } 2149 2150 return SECSuccess; 2151 } 2152 2153 static SECStatus 2154 configureZlibCompression(PRFileDesc *model_sock) 2155 { 2156 SSLCertificateCompressionAlgorithm zlibAlg = { 1, "zlib", 2157 zlibCertificateEncode, 2158 zlibCertificateDecode }; 2159 2160 return SSL_SetCertificateCompressionAlgorithm(model_sock, zlibAlg); 2161 } 2162 2163 void 2164 server_main( 2165 PRFileDesc *listen_sock, 2166 SECKEYPrivateKey **privKey, 2167 CERTCertificate **cert, 2168 const char *expectedHostNameVal) 2169 { 2170 int i; 2171 PRFileDesc *model_sock = NULL; 2172 int rv; 2173 SECStatus secStatus; 2174 2175 if (useModelSocket) { 2176 model_sock = PR_NewTCPSocket(); 2177 if (model_sock == NULL) { 2178 errExit("PR_NewTCPSocket on model socket"); 2179 } 2180 model_sock = SSL_ImportFD(NULL, model_sock); 2181 if (model_sock == NULL) { 2182 errExit("SSL_ImportFD"); 2183 } 2184 } else { 2185 model_sock = listen_sock = SSL_ImportFD(NULL, listen_sock); 2186 if (listen_sock == NULL) { 2187 errExit("SSL_ImportFD"); 2188 } 2189 } 2190 2191 /* do SSL configuration. */ 2192 rv = SSL_OptionSet(model_sock, SSL_SECURITY, enabledVersions.min != 0); 2193 if (rv < 0) { 2194 errExit("SSL_OptionSet SSL_SECURITY"); 2195 } 2196 2197 rv = SSL_VersionRangeSet(model_sock, &enabledVersions); 2198 if (rv != SECSuccess) { 2199 errExit("error setting SSL/TLS version range "); 2200 } 2201 2202 rv = SSL_OptionSet(model_sock, SSL_ROLLBACK_DETECTION, !disableRollBack); 2203 if (rv != SECSuccess) { 2204 errExit("error enabling RollBack detection "); 2205 } 2206 if (disableLocking) { 2207 rv = SSL_OptionSet(model_sock, SSL_NO_LOCKS, PR_TRUE); 2208 if (rv != SECSuccess) { 2209 errExit("error disabling SSL socket locking "); 2210 } 2211 } 2212 if (enableSessionTickets) { 2213 rv = SSL_OptionSet(model_sock, SSL_ENABLE_SESSION_TICKETS, PR_TRUE); 2214 if (rv != SECSuccess) { 2215 errExit("error enabling Session Ticket extension "); 2216 } 2217 } 2218 2219 if (enableZlibCertificateCompression) { 2220 rv = configureZlibCompression(model_sock); 2221 if (rv != SECSuccess) { 2222 errExit("error enabling Zlib Certificate Compression"); 2223 } 2224 } 2225 2226 if (virtServerNameIndex > 1) { 2227 rv = SSL_SNISocketConfigHook(model_sock, mySSLSNISocketConfig, 2228 (void *)&virtServerNameArray); 2229 if (rv != SECSuccess) { 2230 errExit("error enabling SNI extension "); 2231 } 2232 } 2233 2234 if (configureDHE > -1) { 2235 rv = SSL_OptionSet(model_sock, SSL_ENABLE_SERVER_DHE, (configureDHE > 0)); 2236 if (rv != SECSuccess) { 2237 errExit("error configuring server side DHE support"); 2238 } 2239 rv = SSL_OptionSet(model_sock, SSL_REQUIRE_DH_NAMED_GROUPS, (configureDHE > 1)); 2240 if (rv != SECSuccess) { 2241 errExit("error configuring server side FFDHE support"); 2242 } 2243 PORT_Assert(configureDHE <= 2); 2244 } 2245 2246 if (configureReuseECDHE > -1) { 2247 rv = SSL_OptionSet(model_sock, SSL_REUSE_SERVER_ECDHE_KEY, (configureReuseECDHE > 0)); 2248 if (rv != SECSuccess) { 2249 errExit("error configuring server side reuse of ECDHE key"); 2250 } 2251 } 2252 2253 if (configureWeakDHE > -1) { 2254 rv = SSL_EnableWeakDHEPrimeGroup(model_sock, (configureWeakDHE > 0)); 2255 if (rv != SECSuccess) { 2256 errExit("error configuring weak DHE prime group"); 2257 } 2258 } 2259 2260 if (enableExtendedMasterSecret) { 2261 rv = SSL_OptionSet(model_sock, SSL_ENABLE_EXTENDED_MASTER_SECRET, PR_TRUE); 2262 if (rv != SECSuccess) { 2263 errExit("error enabling extended master secret "); 2264 } 2265 } 2266 2267 /* This uses the legacy certificate API. See mySSLSNISocketConfig() for the 2268 * new, prefered API. */ 2269 for (i = 0; i < certNicknameIndex; i++) { 2270 if (cert[i] != NULL) { 2271 const SSLExtraServerCertData ocspData = { 2272 ssl_auth_null, NULL, certStatus[i], NULL, NULL, NULL 2273 }; 2274 2275 secStatus = SSL_ConfigServerCert(model_sock, cert[i], 2276 privKey[i], &ocspData, 2277 sizeof(ocspData)); 2278 if (secStatus != SECSuccess) 2279 errExit("SSL_ConfigServerCert"); 2280 } 2281 } 2282 2283 if (bigBuf.data) { /* doing FDX */ 2284 rv = SSL_OptionSet(model_sock, SSL_ENABLE_FDX, 1); 2285 if (rv < 0) { 2286 errExit("SSL_OptionSet SSL_ENABLE_FDX"); 2287 } 2288 } 2289 2290 if (NoReuse) { 2291 rv = SSL_OptionSet(model_sock, SSL_NO_CACHE, 1); 2292 if (rv < 0) { 2293 errExit("SSL_OptionSet SSL_NO_CACHE"); 2294 } 2295 } 2296 2297 if (zeroRTT) { 2298 if (enabledVersions.max < SSL_LIBRARY_VERSION_TLS_1_3) { 2299 errExit("You tried enabling 0RTT without enabling TLS 1.3!"); 2300 } 2301 rv = SSL_SetAntiReplayContext(model_sock, antiReplay); 2302 if (rv != SECSuccess) { 2303 errExit("error configuring anti-replay "); 2304 } 2305 rv = SSL_OptionSet(model_sock, SSL_ENABLE_0RTT_DATA, PR_TRUE); 2306 if (rv != SECSuccess) { 2307 errExit("error enabling 0RTT "); 2308 } 2309 } 2310 2311 if (enablePostHandshakeAuth) { 2312 if (enabledVersions.max < SSL_LIBRARY_VERSION_TLS_1_3) { 2313 errExit("You tried enabling post-handshake auth without enabling TLS 1.3!"); 2314 } 2315 rv = SSL_OptionSet(model_sock, SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE); 2316 if (rv != SECSuccess) { 2317 errExit("error enabling post-handshake auth"); 2318 } 2319 } 2320 2321 if (enableALPN) { 2322 PRUint8 alpnVal[] = { 0x08, 2323 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 }; 2324 rv = SSL_OptionSet(model_sock, SSL_ENABLE_ALPN, PR_TRUE); 2325 if (rv != SECSuccess) { 2326 errExit("error enabling ALPN"); 2327 } 2328 2329 rv = SSL_SetNextProtoNego(model_sock, alpnVal, sizeof(alpnVal)); 2330 if (rv != SECSuccess) { 2331 errExit("error enabling ALPN"); 2332 } 2333 } 2334 2335 if (enabledGroups) { 2336 rv = SSL_NamedGroupConfig(model_sock, enabledGroups, enabledGroupsCount); 2337 if (rv < 0) { 2338 errExit("SSL_NamedGroupConfig failed"); 2339 } 2340 } 2341 2342 if (enabledSigSchemes) { 2343 rv = SSL_SignatureSchemePrefSet(model_sock, enabledSigSchemes, enabledSigSchemeCount); 2344 if (rv < 0) { 2345 errExit("SSL_SignatureSchemePrefSet failed"); 2346 } 2347 } 2348 2349 /* This cipher is not on by default. The Acceptance test 2350 * would like it to be. Turn this cipher on. 2351 */ 2352 2353 secStatus = SSL_CipherPrefSetDefault(TLS_RSA_WITH_NULL_MD5, PR_TRUE); 2354 if (secStatus != SECSuccess) { 2355 errExit("SSL_CipherPrefSetDefault:TLS_RSA_WITH_NULL_MD5"); 2356 } 2357 2358 if (expectedHostNameVal || enabledExporters) { 2359 SSL_HandshakeCallback(model_sock, handshakeCallback, 2360 (void *)expectedHostNameVal); 2361 } 2362 2363 if (requestCert) { 2364 SSL_AuthCertificateHook(model_sock, mySSLAuthCertificate, 2365 (void *)CERT_GetDefaultCertDB()); 2366 if (requestCert <= 2) { 2367 rv = SSL_OptionSet(model_sock, SSL_REQUEST_CERTIFICATE, 1); 2368 if (rv < 0) { 2369 errExit("first SSL_OptionSet SSL_REQUEST_CERTIFICATE"); 2370 } 2371 rv = SSL_OptionSet(model_sock, SSL_REQUIRE_CERTIFICATE, 2372 (requestCert == 2)); 2373 if (rv < 0) { 2374 errExit("first SSL_OptionSet SSL_REQUIRE_CERTIFICATE"); 2375 } 2376 } 2377 } 2378 2379 if (psk.data) { 2380 rv = importPsk(model_sock); 2381 if (rv != SECSuccess) { 2382 errExit("importPsk failed"); 2383 } 2384 } 2385 2386 if (echParamsStr) { 2387 rv = configureEch(model_sock); 2388 if (rv != SECSuccess) { 2389 errExit("configureEch failed"); 2390 } 2391 } 2392 2393 if (MakeCertOK) 2394 SSL_BadCertHook(model_sock, myBadCertHandler, NULL); 2395 2396 /* end of ssl configuration. */ 2397 2398 /* Now, do the accepting, here in the main thread. */ 2399 rv = do_accepts(listen_sock, model_sock); 2400 2401 terminateWorkerThreads(); 2402 2403 if (useModelSocket && model_sock) { 2404 if (model_sock) { 2405 PR_Close(model_sock); 2406 } 2407 } 2408 } 2409 2410 SECStatus 2411 readBigFile(const char *fileName) 2412 { 2413 PRFileInfo info; 2414 PRStatus status; 2415 SECStatus rv = SECFailure; 2416 int count; 2417 int hdrLen; 2418 PRFileDesc *local_file_fd = NULL; 2419 2420 status = PR_GetFileInfo(fileName, &info); 2421 2422 if (status == PR_SUCCESS && 2423 info.type == PR_FILE_FILE && 2424 info.size > 0 && 2425 NULL != (local_file_fd = PR_Open(fileName, PR_RDONLY, 0))) { 2426 2427 hdrLen = PORT_Strlen(outHeader); 2428 bigBuf.len = hdrLen + info.size; 2429 bigBuf.data = PORT_Malloc(bigBuf.len + 4095); 2430 if (!bigBuf.data) { 2431 errWarn("PORT_Malloc"); 2432 goto done; 2433 } 2434 2435 PORT_Memcpy(bigBuf.data, outHeader, hdrLen); 2436 2437 count = PR_Read(local_file_fd, bigBuf.data + hdrLen, info.size); 2438 if (count != info.size) { 2439 errWarn("PR_Read local file"); 2440 goto done; 2441 } 2442 rv = SECSuccess; 2443 done: 2444 if (local_file_fd) { 2445 PR_Close(local_file_fd); 2446 } 2447 } 2448 return rv; 2449 } 2450 2451 int numChildren; 2452 PRProcess *child[MAX_PROCS]; 2453 2454 PRProcess * 2455 haveAChild(int argc, char **argv, PRProcessAttr *attr) 2456 { 2457 PRProcess *newProcess; 2458 2459 newProcess = PR_CreateProcess(argv[0], argv, NULL, attr); 2460 if (!newProcess) { 2461 errWarn("Can't create new process."); 2462 } else { 2463 child[numChildren++] = newProcess; 2464 } 2465 return newProcess; 2466 } 2467 2468 #ifdef XP_UNIX 2469 void 2470 sigusr1_parent_handler(int sig) 2471 { 2472 PRProcess *process; 2473 int i; 2474 fprintf(stderr, "SIG_USER: Parent got sig_user, killing children (%d).\n", numChildren); 2475 for (i = 0; i < numChildren; i++) { 2476 process = child[i]; 2477 PR_KillProcess(process); /* it would be nice to kill with a sigusr signal */ 2478 } 2479 } 2480 #endif 2481 2482 void 2483 beAGoodParent(int argc, char **argv, int maxProcs, PRFileDesc *listen_sock) 2484 { 2485 PRProcess *newProcess; 2486 PRProcessAttr *attr; 2487 int i; 2488 PRInt32 exitCode; 2489 PRStatus rv; 2490 2491 #ifdef XP_UNIX 2492 struct sigaction act; 2493 2494 /* set up the signal handler */ 2495 act.sa_handler = sigusr1_parent_handler; 2496 sigemptyset(&act.sa_mask); 2497 act.sa_flags = 0; 2498 if (sigaction(SIGUSR1, &act, NULL)) { 2499 fprintf(stderr, "Error installing signal handler.\n"); 2500 exit(1); 2501 } 2502 #endif 2503 2504 rv = PR_SetFDInheritable(listen_sock, PR_TRUE); 2505 if (rv != PR_SUCCESS) 2506 errExit("PR_SetFDInheritable"); 2507 2508 attr = PR_NewProcessAttr(); 2509 if (!attr) 2510 errExit("PR_NewProcessAttr"); 2511 2512 rv = PR_ProcessAttrSetInheritableFD(attr, listen_sock, inheritableSockName); 2513 if (rv != PR_SUCCESS) 2514 errExit("PR_ProcessAttrSetInheritableFD"); 2515 2516 for (i = 0; i < maxProcs; ++i) { 2517 newProcess = haveAChild(argc, argv, attr); 2518 if (!newProcess) 2519 break; 2520 } 2521 2522 rv = PR_SetFDInheritable(listen_sock, PR_FALSE); 2523 if (rv != PR_SUCCESS) 2524 errExit("PR_SetFDInheritable"); 2525 2526 while (numChildren > 0) { 2527 newProcess = child[numChildren - 1]; 2528 PR_WaitProcess(newProcess, &exitCode); 2529 fprintf(stderr, "Child %d exited with exit code %x\n", 2530 numChildren, exitCode); 2531 numChildren--; 2532 } 2533 exit(0); 2534 } 2535 2536 #define HEXCHAR_TO_INT(c, i) \ 2537 if (((c) >= '0') && ((c) <= '9')) { \ 2538 i = (c) - '0'; \ 2539 } else if (((c) >= 'a') && ((c) <= 'f')) { \ 2540 i = (c) - 'a' + 10; \ 2541 } else if (((c) >= 'A') && ((c) <= 'F')) { \ 2542 i = (c) - 'A' + 10; \ 2543 } else if ((c) == '\0') { \ 2544 fprintf(stderr, "Invalid length of cipher string (-c :WXYZ).\n"); \ 2545 exit(9); \ 2546 } else { \ 2547 fprintf(stderr, "Non-hex char in cipher string (-c :WXYZ).\n"); \ 2548 exit(9); \ 2549 } 2550 2551 SECStatus 2552 enableOCSPStapling(const char *mode) 2553 { 2554 if (!strcmp(mode, "good")) { 2555 ocspStaplingMode = osm_good; 2556 return SECSuccess; 2557 } 2558 if (!strcmp(mode, "unknown")) { 2559 ocspStaplingMode = osm_unknown; 2560 return SECSuccess; 2561 } 2562 if (!strcmp(mode, "revoked")) { 2563 ocspStaplingMode = osm_revoked; 2564 return SECSuccess; 2565 } 2566 if (!strcmp(mode, "badsig")) { 2567 ocspStaplingMode = osm_badsig; 2568 return SECSuccess; 2569 } 2570 if (!strcmp(mode, "corrupted")) { 2571 ocspStaplingMode = osm_corrupted; 2572 return SECSuccess; 2573 } 2574 if (!strcmp(mode, "failure")) { 2575 ocspStaplingMode = osm_failure; 2576 return SECSuccess; 2577 } 2578 if (!strcmp(mode, "random")) { 2579 ocspStaplingMode = osm_random; 2580 return SECSuccess; 2581 } 2582 if (!strcmp(mode, "ocsp")) { 2583 ocspStaplingMode = osm_ocsp; 2584 return SECSuccess; 2585 } 2586 return SECFailure; 2587 } 2588 2589 int 2590 main(int argc, char **argv) 2591 { 2592 char *progName = NULL; 2593 const char *fileName = NULL; 2594 char *cipherString = NULL; 2595 const char *dir = "."; 2596 char *passwd = NULL; 2597 char *pwfile = NULL; 2598 const char *pidFile = NULL; 2599 char *tmp; 2600 char *envString; 2601 PRFileDesc *listen_sock; 2602 CERTCertificate *cert[MAX_CERT_NICKNAME_ARRAY_INDEX] = { NULL }; 2603 SECKEYPrivateKey *privKey[MAX_CERT_NICKNAME_ARRAY_INDEX] = { NULL }; 2604 int optionsFound = 0; 2605 int maxProcs = 1; 2606 unsigned short port = 0; 2607 SECStatus rv = SECSuccess; 2608 PRStatus prStatus; 2609 PRBool bindOnly = PR_FALSE; 2610 PRBool useLocalThreads = PR_FALSE; 2611 PLOptState *optstate; 2612 PLOptStatus status; 2613 PRThread *loggerThread = NULL; 2614 PRBool debugCache = PR_FALSE; /* bug 90518 */ 2615 char emptyString[] = { "" }; 2616 char *certPrefix = emptyString; 2617 SSL3Statistics *ssl3stats; 2618 PRUint32 i; 2619 secuPWData pwdata = { PW_NONE, 0 }; 2620 char *expectedHostNameVal = NULL; 2621 PLArenaPool *certStatusArena = NULL; 2622 2623 tmp = strrchr(argv[0], '/'); 2624 tmp = tmp ? tmp + 1 : argv[0]; 2625 progName = strrchr(tmp, '\\'); 2626 progName = progName ? progName + 1 : tmp; 2627 2628 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); 2629 SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions); 2630 2631 /* please keep this list of options in ASCII collating sequence. 2632 ** numbers, then capital letters, then lower case, alphabetical. 2633 ** XXX: 'B', and 'q' were used in the past but removed 2634 ** in 3.28, please leave some time before resuing those. */ 2635 optstate = PL_CreateOptState(argc, argv, 2636 "2:A:C:DEGH:I:J:L:M:NP:QRS:T:U:V:W:X:YZa:bc:d:e:f:g:hi:jk:lmn:op:qrst:uvw:x:yz:"); 2637 while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { 2638 ++optionsFound; 2639 switch (optstate->option) { 2640 case '2': 2641 fileName = optstate->value; 2642 break; 2643 2644 case 'A': 2645 ocspStaplingCA = PORT_Strdup(optstate->value); 2646 break; 2647 2648 case 'C': 2649 if (optstate->value) 2650 NumSidCacheEntries = PORT_Atoi(optstate->value); 2651 break; 2652 2653 case 'D': 2654 noDelay = PR_TRUE; 2655 break; 2656 2657 case 'E': 2658 enablePostHandshakeAuth = PR_TRUE; 2659 break; 2660 2661 case 'H': 2662 configureDHE = (PORT_Atoi(optstate->value) != 0); 2663 break; 2664 2665 case 'G': 2666 enableExtendedMasterSecret = PR_TRUE; 2667 break; 2668 2669 case 'L': 2670 logStats = PR_TRUE; 2671 if (optstate->value == NULL) { 2672 logPeriod = 30; 2673 } else { 2674 logPeriod = PORT_Atoi(optstate->value); 2675 if (logPeriod <= 0) 2676 logPeriod = 30; 2677 } 2678 break; 2679 2680 case 'M': 2681 maxProcs = PORT_Atoi(optstate->value); 2682 if (maxProcs < 1) 2683 maxProcs = 1; 2684 if (maxProcs > MAX_PROCS) 2685 maxProcs = MAX_PROCS; 2686 break; 2687 2688 case 'N': 2689 NoReuse = PR_TRUE; 2690 break; 2691 2692 case 'R': 2693 disableRollBack = PR_TRUE; 2694 break; 2695 2696 case 'S': 2697 if (certNicknameIndex >= MAX_CERT_NICKNAME_ARRAY_INDEX) { 2698 Usage(progName); 2699 break; 2700 } 2701 certNicknameArray[certNicknameIndex++] = PORT_Strdup(optstate->value); 2702 break; 2703 2704 case 'T': 2705 if (enableOCSPStapling(optstate->value) != SECSuccess) { 2706 fprintf(stderr, "Invalid OCSP stapling mode.\n"); 2707 fprintf(stderr, "Run '%s -h' for usage information.\n", progName); 2708 exit(53); 2709 } 2710 break; 2711 2712 case 'U': 2713 configureReuseECDHE = (PORT_Atoi(optstate->value) != 0); 2714 break; 2715 2716 case 'V': 2717 if (SECU_ParseSSLVersionRangeString(optstate->value, 2718 enabledVersions, &enabledVersions) != 2719 SECSuccess) { 2720 fprintf(stderr, "Bad version specified.\n"); 2721 Usage(progName); 2722 exit(1); 2723 } 2724 break; 2725 2726 case 'W': 2727 configureWeakDHE = (PORT_Atoi(optstate->value) != 0); 2728 break; 2729 2730 case 'Y': 2731 PrintCipherUsage(progName); 2732 exit(0); 2733 break; 2734 2735 case 'a': 2736 if (virtServerNameIndex >= MAX_VIRT_SERVER_NAME_ARRAY_INDEX) { 2737 Usage(progName); 2738 break; 2739 } 2740 virtServerNameArray[virtServerNameIndex++] = 2741 PORT_Strdup(optstate->value); 2742 break; 2743 2744 case 'b': 2745 bindOnly = PR_TRUE; 2746 break; 2747 2748 case 'c': 2749 cipherString = PORT_Strdup(optstate->value); 2750 break; 2751 2752 case 'd': 2753 dir = optstate->value; 2754 break; 2755 2756 case 'e': 2757 if (certNicknameIndex >= MAX_CERT_NICKNAME_ARRAY_INDEX) { 2758 Usage(progName); 2759 break; 2760 } 2761 certNicknameArray[certNicknameIndex++] = PORT_Strdup(optstate->value); 2762 break; 2763 2764 case 'f': 2765 pwdata.source = PW_FROMFILE; 2766 pwdata.data = pwfile = PORT_Strdup(optstate->value); 2767 break; 2768 2769 case 'g': 2770 testBulk = PR_TRUE; 2771 testBulkTotal = PORT_Atoi(optstate->value); 2772 break; 2773 2774 case 'h': 2775 Usage(progName); 2776 exit(0); 2777 break; 2778 2779 case 'i': 2780 pidFile = optstate->value; 2781 break; 2782 2783 case 'j': 2784 initLoggingLayer(); 2785 loggingLayer = PR_TRUE; 2786 break; 2787 2788 case 'k': 2789 expectedHostNameVal = PORT_Strdup(optstate->value); 2790 break; 2791 2792 case 'l': 2793 useLocalThreads = PR_TRUE; 2794 break; 2795 2796 case 'm': 2797 useModelSocket = PR_TRUE; 2798 break; 2799 2800 case 'n': 2801 if (certNicknameIndex >= MAX_CERT_NICKNAME_ARRAY_INDEX) { 2802 Usage(progName); 2803 break; 2804 } 2805 certNicknameArray[certNicknameIndex++] = PORT_Strdup(optstate->value); 2806 virtServerNameArray[0] = PORT_Strdup(optstate->value); 2807 break; 2808 2809 case 'P': 2810 certPrefix = PORT_Strdup(optstate->value); 2811 break; 2812 2813 case 'o': 2814 MakeCertOK = 1; 2815 break; 2816 2817 case 'p': 2818 port = PORT_Atoi(optstate->value); 2819 break; 2820 2821 case 'q': 2822 enableZlibCertificateCompression = PR_TRUE; 2823 break; 2824 2825 case 'r': 2826 ++requestCert; 2827 break; 2828 2829 case 's': 2830 disableLocking = PR_TRUE; 2831 break; 2832 2833 case 't': 2834 maxThreads = PORT_Atoi(optstate->value); 2835 if (maxThreads > MAX_THREADS) 2836 maxThreads = MAX_THREADS; 2837 if (maxThreads < MIN_THREADS) 2838 maxThreads = MIN_THREADS; 2839 break; 2840 2841 case 'u': 2842 enableSessionTickets = PR_TRUE; 2843 break; 2844 2845 case 'v': 2846 verbose++; 2847 break; 2848 2849 case 'w': 2850 pwdata.source = PW_PLAINTEXT; 2851 pwdata.data = passwd = PORT_Strdup(optstate->value); 2852 break; 2853 2854 case 'y': 2855 debugCache = PR_TRUE; 2856 break; 2857 2858 case 'Z': 2859 zeroRTT = PR_TRUE; 2860 break; 2861 2862 case 'z': 2863 rv = readPSK(optstate->value, &psk, &pskLabel); 2864 if (rv != SECSuccess) { 2865 PL_DestroyOptState(optstate); 2866 fprintf(stderr, "Bad PSK specified.\n"); 2867 Usage(progName); 2868 exit(1); 2869 } 2870 break; 2871 2872 case 'Q': 2873 enableALPN = PR_TRUE; 2874 break; 2875 2876 case 'I': 2877 rv = parseGroupList(optstate->value, &enabledGroups, &enabledGroupsCount); 2878 if (rv != SECSuccess) { 2879 PL_DestroyOptState(optstate); 2880 fprintf(stderr, "Bad group specified.\n"); 2881 fprintf(stderr, "Run '%s -h' for usage information.\n", progName); 2882 exit(5); 2883 } 2884 break; 2885 2886 case 'J': 2887 rv = parseSigSchemeList(optstate->value, &enabledSigSchemes, &enabledSigSchemeCount); 2888 if (rv != SECSuccess) { 2889 PL_DestroyOptState(optstate); 2890 fprintf(stderr, "Bad signature scheme specified.\n"); 2891 fprintf(stderr, "Run '%s -h' for usage information.\n", progName); 2892 exit(5); 2893 } 2894 break; 2895 2896 case 'x': 2897 rv = parseExporters(optstate->value, 2898 &enabledExporters, &enabledExporterCount); 2899 if (rv != SECSuccess) { 2900 PL_DestroyOptState(optstate); 2901 fprintf(stderr, "Bad exporter specified.\n"); 2902 fprintf(stderr, "Run '%s -h' for usage information.\n", progName); 2903 exit(5); 2904 } 2905 break; 2906 2907 case 'X': 2908 echParamsStr = PORT_Strdup(optstate->value); 2909 if (echParamsStr == NULL) { 2910 PL_DestroyOptState(optstate); 2911 fprintf(stderr, "echParamsStr copy failed.\n"); 2912 exit(5); 2913 } 2914 break; 2915 default: 2916 case '?': 2917 fprintf(stderr, "Unrecognized or bad option specified: %c\n", optstate->option); 2918 fprintf(stderr, "Run '%s -h' for usage information.\n", progName); 2919 exit(4); 2920 break; 2921 } 2922 } 2923 PL_DestroyOptState(optstate); 2924 if (status == PL_OPT_BAD) { 2925 fprintf(stderr, "Unrecognized or bad option specified.\n"); 2926 fprintf(stderr, "Run '%s -h' for usage information.\n", progName); 2927 exit(5); 2928 } 2929 if (!optionsFound) { 2930 Usage(progName); 2931 exit(51); 2932 } 2933 switch (ocspStaplingMode) { 2934 case osm_good: 2935 case osm_revoked: 2936 case osm_unknown: 2937 case osm_random: 2938 if (!ocspStaplingCA) { 2939 fprintf(stderr, "Selected stapling response requires the -A parameter.\n"); 2940 fprintf(stderr, "Run '%s -h' for usage information.\n", progName); 2941 exit(52); 2942 } 2943 break; 2944 default: 2945 break; 2946 } 2947 2948 /* The -b (bindOnly) option is only used by the ssl.sh test 2949 * script on Linux to determine whether a previous selfserv 2950 * process has fully died and freed the port. (Bug 129701) 2951 */ 2952 if (bindOnly) { 2953 listen_sock = getBoundListenSocket(port); 2954 if (!listen_sock) { 2955 exit(1); 2956 } 2957 if (listen_sock) { 2958 PR_Close(listen_sock); 2959 } 2960 exit(0); 2961 } 2962 2963 if (certNicknameIndex == 0) { 2964 fprintf(stderr, "Must specify at least one certificate nickname using '-n' (RSA), '-S' (DSA), or 'e' (EC).\n"); 2965 fprintf(stderr, "Run '%s -h' for usage information.\n", progName); 2966 exit(6); 2967 } 2968 2969 if (port == 0) { 2970 fprintf(stderr, "Required argument 'port' must be non-zero value\n"); 2971 exit(7); 2972 } 2973 2974 if (NoReuse && maxProcs > 1) { 2975 fprintf(stderr, "-M and -N options are mutually exclusive.\n"); 2976 exit(14); 2977 } 2978 2979 envString = PR_GetEnvSecure(envVarName); 2980 if (!envString && pidFile) { 2981 FILE *tmpfile = fopen(pidFile, "w+"); 2982 2983 if (tmpfile) { 2984 fprintf(tmpfile, "%d", getpid()); 2985 fclose(tmpfile); 2986 } 2987 } 2988 2989 /* allocate and initialize app data for bulk encryption testing */ 2990 if (testBulk) { 2991 testBulkBuf = PORT_Malloc(testBulkSize); 2992 if (testBulkBuf == NULL) 2993 errExit("Out of memory: testBulkBuf"); 2994 for (i = 0; i < testBulkSize; i++) 2995 testBulkBuf[i] = i; 2996 } 2997 2998 envString = PR_GetEnvSecure(envVarName); 2999 tmp = PR_GetEnvSecure("TMP"); 3000 if (!tmp) 3001 tmp = PR_GetEnvSecure("TMPDIR"); 3002 if (!tmp) 3003 tmp = PR_GetEnvSecure("TEMP"); 3004 3005 if (envString) { 3006 /* we're one of the children in a multi-process server. */ 3007 listen_sock = PR_GetInheritedFD(inheritableSockName); 3008 if (!listen_sock) 3009 errExit("PR_GetInheritedFD"); 3010 #ifndef WINNT 3011 /* we can't do this on NT because it breaks NSPR and 3012 PR_Accept will fail on the socket in the child process if 3013 the socket state is change to non inheritable 3014 It is however a security issue to leave it accessible, 3015 but it is OK for a test server such as selfserv. 3016 NSPR should fix it eventually . see bugzilla 101617 3017 and 102077 3018 */ 3019 prStatus = PR_SetFDInheritable(listen_sock, PR_FALSE); 3020 if (prStatus != PR_SUCCESS) 3021 errExit("PR_SetFDInheritable"); 3022 #endif 3023 rv = SSL_InheritMPServerSIDCache(envString); 3024 if (rv != SECSuccess) 3025 errExit("SSL_InheritMPServerSIDCache"); 3026 hasSidCache = PR_TRUE; 3027 /* Call the NSS initialization routines */ 3028 rv = NSS_Initialize(dir, certPrefix, certPrefix, SECMOD_DB, NSS_INIT_READONLY); 3029 if (rv != SECSuccess) { 3030 fputs("NSS_Init failed.\n", stderr); 3031 exit(8); 3032 } 3033 } else if (maxProcs > 1) { 3034 /* we're going to be the parent in a multi-process server. */ 3035 listen_sock = getBoundListenSocket(port); 3036 rv = SSL_ConfigMPServerSIDCache(NumSidCacheEntries, 0, 0, tmp); 3037 if (rv != SECSuccess) 3038 errExit("SSL_ConfigMPServerSIDCache"); 3039 hasSidCache = PR_TRUE; 3040 beAGoodParent(argc, argv, maxProcs, listen_sock); 3041 exit(99); /* should never get here */ 3042 } else { 3043 /* Call the NSS initialization routines */ 3044 rv = NSS_Initialize(dir, certPrefix, certPrefix, SECMOD_DB, NSS_INIT_READONLY); 3045 if (rv != SECSuccess) { 3046 fputs("NSS_Init failed.\n", stderr); 3047 exit(8); 3048 } 3049 /* we're an ordinary single process server. */ 3050 listen_sock = getBoundListenSocket(port); 3051 prStatus = PR_SetFDInheritable(listen_sock, PR_FALSE); 3052 if (prStatus != PR_SUCCESS) 3053 errExit("PR_SetFDInheritable"); 3054 if (!NoReuse) { 3055 rv = SSL_ConfigServerSessionIDCache(NumSidCacheEntries, 3056 0, 0, tmp); 3057 if (rv != SECSuccess) 3058 errExit("SSL_ConfigServerSessionIDCache"); 3059 hasSidCache = PR_TRUE; 3060 } 3061 } 3062 3063 lm = PR_NewLogModule("TestCase"); 3064 3065 if (fileName) 3066 readBigFile(fileName); 3067 3068 /* set our password function */ 3069 PK11_SetPasswordFunc(SECU_GetModulePassword); 3070 3071 /* all SSL3 cipher suites are enabled by default. */ 3072 if (cipherString) { 3073 char *cstringSaved = cipherString; 3074 int ndx; 3075 3076 /* disable all the ciphers, then enable the ones we want. */ 3077 disableAllSSLCiphers(); 3078 3079 while (0 != (ndx = *cipherString++)) { 3080 int cipher = 0; 3081 3082 if (ndx == ':') { 3083 int ctmp; 3084 3085 HEXCHAR_TO_INT(*cipherString, ctmp) 3086 cipher |= (ctmp << 12); 3087 cipherString++; 3088 HEXCHAR_TO_INT(*cipherString, ctmp) 3089 cipher |= (ctmp << 8); 3090 cipherString++; 3091 HEXCHAR_TO_INT(*cipherString, ctmp) 3092 cipher |= (ctmp << 4); 3093 cipherString++; 3094 HEXCHAR_TO_INT(*cipherString, ctmp) 3095 cipher |= ctmp; 3096 cipherString++; 3097 } else { 3098 if (!isalpha((unsigned char)ndx)) { 3099 fprintf(stderr, 3100 "Non-alphabetic char in cipher string (-c arg).\n"); 3101 exit(9); 3102 } 3103 ndx = tolower((unsigned char)ndx) - 'a'; 3104 if (ndx < PR_ARRAY_SIZE(ssl3CipherSuites)) { 3105 cipher = ssl3CipherSuites[ndx]; 3106 } 3107 } 3108 if (cipher > 0) { 3109 rv = SSL_CipherPrefSetDefault(cipher, SSL_ALLOWED); 3110 if (rv != SECSuccess) { 3111 SECU_PrintError(progName, "SSL_CipherPrefSetDefault()"); 3112 exit(9); 3113 } 3114 } else { 3115 fprintf(stderr, 3116 "Invalid cipher specification (-c arg).\n"); 3117 exit(9); 3118 } 3119 } 3120 PORT_Free(cstringSaved); 3121 } 3122 3123 certStatusArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 3124 if (!certStatusArena) 3125 errExit("cannot allocate certStatusArena"); 3126 3127 for (i = 0; i < certNicknameIndex; i++) { 3128 cert[i] = PK11_FindCertFromNickname(certNicknameArray[i], &pwdata); 3129 if (cert[i] == NULL) { 3130 fprintf(stderr, "selfserv: Can't find certificate %s\n", certNicknameArray[i]); 3131 exit(10); 3132 } 3133 privKey[i] = PK11_FindKeyByAnyCert(cert[i], &pwdata); 3134 if (privKey[i] == NULL) { 3135 fprintf(stderr, "selfserv: Can't find Private Key for cert %s\n", 3136 certNicknameArray[i]); 3137 exit(11); 3138 } 3139 if (privKey[i]->keyType != ecKey) 3140 setupCertStatus(certStatusArena, cert[i], i, &pwdata); 3141 } 3142 3143 if (configureWeakDHE > 0) { 3144 fprintf(stderr, "selfserv: Creating dynamic weak DH parameters\n"); 3145 rv = SSL_EnableWeakDHEPrimeGroup(NULL, PR_TRUE); 3146 if (rv != SECSuccess) { 3147 goto cleanup; 3148 } 3149 fprintf(stderr, "selfserv: Done creating dynamic weak DH parameters\n"); 3150 } 3151 if (zeroRTT) { 3152 rv = SSL_CreateAntiReplayContext(PR_Now(), 10L * PR_USEC_PER_SEC, 7, 14, &antiReplay); 3153 if (rv != SECSuccess) { 3154 errExit("Unable to create anti-replay context for 0-RTT."); 3155 } 3156 } 3157 3158 /* allocate the array of thread slots, and launch the worker threads. */ 3159 rv = launch_threads(&jobLoop, 0, 0, useLocalThreads); 3160 3161 if (rv == SECSuccess && logStats) { 3162 loggerThread = PR_CreateThread(PR_SYSTEM_THREAD, 3163 logger, NULL, PR_PRIORITY_NORMAL, 3164 useLocalThreads ? PR_LOCAL_THREAD 3165 : PR_GLOBAL_THREAD, 3166 PR_JOINABLE_THREAD, 0); 3167 if (loggerThread == NULL) { 3168 fprintf(stderr, "selfserv: Failed to launch logger thread!\n"); 3169 rv = SECFailure; 3170 } 3171 } 3172 3173 if (rv == SECSuccess) { 3174 server_main(listen_sock, privKey, cert, 3175 expectedHostNameVal); 3176 } 3177 3178 VLOG(("selfserv: server_thread: exiting")); 3179 3180 cleanup: 3181 printSSLStatistics(); 3182 ssl3stats = SSL_GetStatistics(); 3183 if (ssl3stats->hch_sid_ticket_parse_failures != 0) { 3184 fprintf(stderr, "selfserv: Experienced ticket parse failure(s)\n"); 3185 exit(1); 3186 } 3187 if (failedToNegotiateName) { 3188 fprintf(stderr, "selfserv: Failed properly negotiate server name\n"); 3189 exit(1); 3190 } 3191 3192 { 3193 for (i = 0; i < certNicknameIndex; i++) { 3194 if (cert[i]) { 3195 CERT_DestroyCertificate(cert[i]); 3196 } 3197 if (privKey[i]) { 3198 SECKEY_DestroyPrivateKey(privKey[i]); 3199 } 3200 PORT_Free(certNicknameArray[i]); 3201 } 3202 for (i = 0; virtServerNameArray[i]; i++) { 3203 PORT_Free(virtServerNameArray[i]); 3204 } 3205 } 3206 3207 if (debugCache) { 3208 nss_DumpCertificateCacheInfo(); 3209 } 3210 if (expectedHostNameVal) { 3211 PORT_Free(expectedHostNameVal); 3212 } 3213 if (passwd) { 3214 PORT_Free(passwd); 3215 } 3216 if (pwfile) { 3217 PORT_Free(pwfile); 3218 } 3219 if (certPrefix && certPrefix != emptyString) { 3220 PORT_Free(certPrefix); 3221 } 3222 3223 if (hasSidCache) { 3224 SSL_ShutdownServerSessionIDCache(); 3225 } 3226 if (certStatusArena) { 3227 PORT_FreeArena(certStatusArena, PR_FALSE); 3228 } 3229 if (enabledGroups) { 3230 PORT_Free(enabledGroups); 3231 } 3232 if (antiReplay) { 3233 SSL_ReleaseAntiReplayContext(antiReplay); 3234 } 3235 SECITEM_ZfreeItem(&psk, PR_FALSE); 3236 SECITEM_ZfreeItem(&pskLabel, PR_FALSE); 3237 PORT_Free(echParamsStr); 3238 if (NSS_Shutdown() != SECSuccess) { 3239 SECU_PrintError(progName, "NSS_Shutdown"); 3240 if (loggerThread) { 3241 PR_JoinThread(loggerThread); 3242 } 3243 PR_Cleanup(); 3244 exit(1); 3245 } 3246 PR_Cleanup(); 3247 printf("selfserv: normal termination\n"); 3248 return 0; 3249 }