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