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