Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
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/. */
5 /*
6 **
7 ** Sample client side test program that uses SSL and NSS
8 **
9 */
11 #include "secutil.h"
12 #include "basicutil.h"
14 #if defined(XP_UNIX)
15 #include <unistd.h>
16 #else
17 #include <ctype.h> /* for isalpha() */
18 #endif
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <stdarg.h>
27 #include "nspr.h"
28 #include "prio.h"
29 #include "prnetdb.h"
30 #include "nss.h"
31 #include "ocsp.h"
32 #include "ssl.h"
33 #include "sslproto.h"
34 #include "pk11func.h"
35 #include "plgetopt.h"
36 #include "plstr.h"
38 #if defined(WIN32)
39 #include <fcntl.h>
40 #include <io.h>
41 #endif
43 #define PRINTF if (verbose) printf
44 #define FPRINTF if (verbose) fprintf
46 #define MAX_WAIT_FOR_SERVER 600
47 #define WAIT_INTERVAL 100
49 #define EXIT_CODE_HANDSHAKE_FAILED 254
51 #define EXIT_CODE_SIDECHANNELTEST_GOOD 0
52 #define EXIT_CODE_SIDECHANNELTEST_BADCERT 1
53 #define EXIT_CODE_SIDECHANNELTEST_NODATA 2
54 #define EXIT_CODE_SIDECHANNELTEST_REVOKED 3
56 PRIntervalTime maxInterval = PR_INTERVAL_NO_TIMEOUT;
58 int ssl2CipherSuites[] = {
59 SSL_EN_RC4_128_WITH_MD5, /* A */
60 SSL_EN_RC4_128_EXPORT40_WITH_MD5, /* B */
61 SSL_EN_RC2_128_CBC_WITH_MD5, /* C */
62 SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, /* D */
63 SSL_EN_DES_64_CBC_WITH_MD5, /* E */
64 SSL_EN_DES_192_EDE3_CBC_WITH_MD5, /* F */
65 0
66 };
68 int ssl3CipherSuites[] = {
69 -1, /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
70 -1, /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, * b */
71 TLS_RSA_WITH_RC4_128_MD5, /* c */
72 TLS_RSA_WITH_3DES_EDE_CBC_SHA, /* d */
73 TLS_RSA_WITH_DES_CBC_SHA, /* e */
74 TLS_RSA_EXPORT_WITH_RC4_40_MD5, /* f */
75 TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* g */
76 -1, /* SSL_FORTEZZA_DMS_WITH_NULL_SHA, * h */
77 TLS_RSA_WITH_NULL_MD5, /* i */
78 SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, /* j */
79 SSL_RSA_FIPS_WITH_DES_CBC_SHA, /* k */
80 TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, /* l */
81 TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, /* m */
82 TLS_RSA_WITH_RC4_128_SHA, /* n */
83 TLS_DHE_DSS_WITH_RC4_128_SHA, /* o */
84 TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
85 TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
86 TLS_DHE_RSA_WITH_DES_CBC_SHA, /* r */
87 TLS_DHE_DSS_WITH_DES_CBC_SHA, /* s */
88 TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* t */
89 TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* u */
90 TLS_RSA_WITH_AES_128_CBC_SHA, /* v */
91 TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* w */
92 TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* x */
93 TLS_RSA_WITH_AES_256_CBC_SHA, /* y */
94 TLS_RSA_WITH_NULL_SHA, /* z */
95 0
96 };
98 unsigned long __cmp_umuls;
99 PRBool verbose;
100 int renegotiationsToDo = 0;
101 int renegotiationsDone = 0;
103 static char *progName;
105 secuPWData pwdata = { PW_NONE, 0 };
107 void printSecurityInfo(PRFileDesc *fd)
108 {
109 CERTCertificate * cert;
110 const SECItemArray *csa;
111 SSL3Statistics * ssl3stats = SSL_GetStatistics();
112 SECStatus result;
113 SSLChannelInfo channel;
114 SSLCipherSuiteInfo suite;
116 result = SSL_GetChannelInfo(fd, &channel, sizeof channel);
117 if (result == SECSuccess &&
118 channel.length == sizeof channel &&
119 channel.cipherSuite) {
120 result = SSL_GetCipherSuiteInfo(channel.cipherSuite,
121 &suite, sizeof suite);
122 if (result == SECSuccess) {
123 FPRINTF(stderr,
124 "tstclnt: SSL version %d.%d using %d-bit %s with %d-bit %s MAC\n",
125 channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
126 suite.effectiveKeyBits, suite.symCipherName,
127 suite.macBits, suite.macAlgorithmName);
128 FPRINTF(stderr,
129 "tstclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n"
130 " Compression: %s\n",
131 channel.authKeyBits, suite.authAlgorithmName,
132 channel.keaKeyBits, suite.keaTypeName,
133 channel.compressionMethodName);
134 }
135 }
136 cert = SSL_RevealCert(fd);
137 if (cert) {
138 char * ip = CERT_NameToAscii(&cert->issuer);
139 char * sp = CERT_NameToAscii(&cert->subject);
140 if (sp) {
141 fprintf(stderr, "subject DN: %s\n", sp);
142 PORT_Free(sp);
143 }
144 if (ip) {
145 fprintf(stderr, "issuer DN: %s\n", ip);
146 PORT_Free(ip);
147 }
148 CERT_DestroyCertificate(cert);
149 cert = NULL;
150 }
151 fprintf(stderr,
152 "%ld cache hits; %ld cache misses, %ld cache not reusable\n"
153 "%ld stateless resumes\n",
154 ssl3stats->hsh_sid_cache_hits, ssl3stats->hsh_sid_cache_misses,
155 ssl3stats->hsh_sid_cache_not_ok, ssl3stats->hsh_sid_stateless_resumes);
157 csa = SSL_PeerStapledOCSPResponses(fd);
158 if (csa) {
159 fprintf(stderr, "Received %d Cert Status items (OCSP stapled data)\n",
160 csa->len);
161 }
162 }
164 void
165 handshakeCallback(PRFileDesc *fd, void *client_data)
166 {
167 const char *secondHandshakeName = (char *)client_data;
168 if (secondHandshakeName) {
169 SSL_SetURL(fd, secondHandshakeName);
170 }
171 printSecurityInfo(fd);
172 if (renegotiationsDone < renegotiationsToDo) {
173 SSL_ReHandshake(fd, (renegotiationsToDo < 2));
174 ++renegotiationsDone;
175 }
176 }
178 static void PrintUsageHeader(const char *progName)
179 {
180 fprintf(stderr,
181 "Usage: %s -h host [-a 1st_hs_name ] [-a 2nd_hs_name ] [-p port]\n"
182 "[-d certdir] [-n nickname] [-Bafosvx] [-c ciphers] [-Y]\n"
183 "[-V [min-version]:[max-version]] [-T]\n"
184 "[-r N] [-w passwd] [-W pwfile] [-q [-t seconds]]\n",
185 progName);
186 }
188 static void PrintParameterUsage(void)
189 {
190 fprintf(stderr, "%-20s Send different SNI name. 1st_hs_name - at first\n"
191 "%-20s handshake, 2nd_hs_name - at second handshake.\n"
192 "%-20s Default is host from the -h argument.\n", "-a name",
193 "", "");
194 fprintf(stderr, "%-20s Hostname to connect with\n", "-h host");
195 fprintf(stderr, "%-20s Port number for SSL server\n", "-p port");
196 fprintf(stderr,
197 "%-20s Directory with cert database (default is ~/.netscape)\n",
198 "-d certdir");
199 fprintf(stderr, "%-20s Nickname of key and cert for client auth\n",
200 "-n nickname");
201 fprintf(stderr,
202 "%-20s Bypass PKCS11 layer for SSL encryption and MACing.\n", "-B");
203 fprintf(stderr,
204 "%-20s Restricts the set of enabled SSL/TLS protocols versions.\n"
205 "%-20s All versions are enabled by default.\n"
206 "%-20s Possible values for min/max: ssl2 ssl3 tls1.0 tls1.1 tls1.2\n"
207 "%-20s Example: \"-V ssl3:\" enables SSL 3 and newer.\n",
208 "-V [min]:[max]", "", "", "");
209 fprintf(stderr, "%-20s Prints only payload data. Skips HTTP header.\n", "-S");
210 fprintf(stderr, "%-20s Client speaks first. \n", "-f");
211 fprintf(stderr, "%-20s Use synchronous certificate validation "
212 "(required for SSL2)\n", "-O");
213 fprintf(stderr, "%-20s Override bad server cert. Make it OK.\n", "-o");
214 fprintf(stderr, "%-20s Disable SSL socket locking.\n", "-s");
215 fprintf(stderr, "%-20s Verbose progress reporting.\n", "-v");
216 fprintf(stderr, "%-20s Use export policy.\n", "-x");
217 fprintf(stderr, "%-20s Ping the server and then exit.\n", "-q");
218 fprintf(stderr, "%-20s Timeout for server ping (default: no timeout).\n", "-t seconds");
219 fprintf(stderr, "%-20s Renegotiate N times (resuming session if N>1).\n", "-r N");
220 fprintf(stderr, "%-20s Enable the session ticket extension.\n", "-u");
221 fprintf(stderr, "%-20s Enable compression.\n", "-z");
222 fprintf(stderr, "%-20s Enable false start.\n", "-g");
223 fprintf(stderr, "%-20s Enable the cert_status extension (OCSP stapling).\n", "-T");
224 fprintf(stderr, "%-20s Require fresh revocation info from side channel.\n"
225 "%-20s -F once means: require for server cert only\n"
226 "%-20s -F twice means: require for intermediates, too\n"
227 "%-20s (Connect, handshake with server, disable dynamic download\n"
228 "%-20s of OCSP/CRL, verify cert using CERT_PKIXVerifyCert.)\n"
229 "%-20s Exit code:\n"
230 "%-20s 0: have fresh and valid revocation data, status good\n"
231 "%-20s 1: cert failed to verify, prior to revocation checking\n"
232 "%-20s 2: missing, old or invalid revocation data\n"
233 "%-20s 3: have fresh and valid revocation data, status revoked\n",
234 "-F", "", "", "", "", "", "", "", "", "");
235 fprintf(stderr, "%-20s Test -F allows 0=any (default), 1=only OCSP, 2=only CRL\n", "-M");
236 fprintf(stderr, "%-20s Restrict ciphers\n", "-c ciphers");
237 fprintf(stderr, "%-20s Print cipher values allowed for parameter -c and exit\n", "-Y");
238 fprintf(stderr, "%-20s Enforce using an IPv4 destination address\n", "-4");
239 fprintf(stderr, "%-20s Enforce using an IPv6 destination address\n", "-6");
240 fprintf(stderr, "%-20s (Options -4 and -6 cannot be combined.)\n", "");
241 }
243 static void Usage(const char *progName)
244 {
245 PrintUsageHeader(progName);
246 PrintParameterUsage();
247 exit(1);
248 }
250 static void PrintCipherUsage(const char *progName)
251 {
252 PrintUsageHeader(progName);
253 fprintf(stderr, "%-20s Letter(s) chosen from the following list\n",
254 "-c ciphers");
255 fprintf(stderr,
256 "A SSL2 RC4 128 WITH MD5\n"
257 "B SSL2 RC4 128 EXPORT40 WITH MD5\n"
258 "C SSL2 RC2 128 CBC WITH MD5\n"
259 "D SSL2 RC2 128 CBC EXPORT40 WITH MD5\n"
260 "E SSL2 DES 64 CBC WITH MD5\n"
261 "F SSL2 DES 192 EDE3 CBC WITH MD5\n"
262 "\n"
263 "c SSL3 RSA WITH RC4 128 MD5\n"
264 "d SSL3 RSA WITH 3DES EDE CBC SHA\n"
265 "e SSL3 RSA WITH DES CBC SHA\n"
266 "f SSL3 RSA EXPORT WITH RC4 40 MD5\n"
267 "g SSL3 RSA EXPORT WITH RC2 CBC 40 MD5\n"
268 "i SSL3 RSA WITH NULL MD5\n"
269 "j SSL3 RSA FIPS WITH 3DES EDE CBC SHA\n"
270 "k SSL3 RSA FIPS WITH DES CBC SHA\n"
271 "l SSL3 RSA EXPORT WITH DES CBC SHA\t(new)\n"
272 "m SSL3 RSA EXPORT WITH RC4 56 SHA\t(new)\n"
273 "n SSL3 RSA WITH RC4 128 SHA\n"
274 "o SSL3 DHE DSS WITH RC4 128 SHA\n"
275 "p SSL3 DHE RSA WITH 3DES EDE CBC SHA\n"
276 "q SSL3 DHE DSS WITH 3DES EDE CBC SHA\n"
277 "r SSL3 DHE RSA WITH DES CBC SHA\n"
278 "s SSL3 DHE DSS WITH DES CBC SHA\n"
279 "t SSL3 DHE DSS WITH AES 128 CBC SHA\n"
280 "u SSL3 DHE RSA WITH AES 128 CBC SHA\n"
281 "v SSL3 RSA WITH AES 128 CBC SHA\n"
282 "w SSL3 DHE DSS WITH AES 256 CBC SHA\n"
283 "x SSL3 DHE RSA WITH AES 256 CBC SHA\n"
284 "y SSL3 RSA WITH AES 256 CBC SHA\n"
285 "z SSL3 RSA WITH NULL SHA\n"
286 "\n"
287 ":WXYZ Use cipher with hex code { 0xWX , 0xYZ } in TLS\n"
288 );
289 exit(1);
290 }
292 void
293 milliPause(PRUint32 milli)
294 {
295 PRIntervalTime ticks = PR_MillisecondsToInterval(milli);
296 PR_Sleep(ticks);
297 }
299 void
300 disableAllSSLCiphers(void)
301 {
302 const PRUint16 *cipherSuites = SSL_GetImplementedCiphers();
303 int i = SSL_GetNumImplementedCiphers();
304 SECStatus rv;
306 /* disable all the SSL3 cipher suites */
307 while (--i >= 0) {
308 PRUint16 suite = cipherSuites[i];
309 rv = SSL_CipherPrefSetDefault(suite, PR_FALSE);
310 if (rv != SECSuccess) {
311 PRErrorCode err = PR_GetError();
312 fprintf(stderr,
313 "SSL_CipherPrefSet didn't like value 0x%04x (i = %d): %s\n",
314 suite, i, SECU_Strerror(err));
315 exit(2);
316 }
317 }
318 }
320 typedef struct
321 {
322 PRBool shouldPause; /* PR_TRUE if we should use asynchronous peer cert
323 * authentication */
324 PRBool isPaused; /* PR_TRUE if libssl is waiting for us to validate the
325 * peer's certificate and restart the handshake. */
326 void * dbHandle; /* Certificate database handle to use while
327 * authenticating the peer's certificate. */
328 PRBool testFreshStatusFromSideChannel;
329 PRErrorCode sideChannelRevocationTestResultCode;
330 PRBool requireDataForIntermediates;
331 PRBool allowOCSPSideChannelData;
332 PRBool allowCRLSideChannelData;
333 } ServerCertAuth;
336 /*
337 * Callback is called when incoming certificate is not valid.
338 * Returns SECSuccess to accept the cert anyway, SECFailure to reject.
339 */
340 static SECStatus
341 ownBadCertHandler(void * arg, PRFileDesc * socket)
342 {
343 PRErrorCode err = PR_GetError();
344 /* can log invalid cert here */
345 fprintf(stderr, "Bad server certificate: %d, %s\n", err,
346 SECU_Strerror(err));
347 return SECSuccess; /* override, say it's OK. */
348 }
352 #define EXIT_CODE_SIDECHANNELTEST_GOOD 0
353 #define EXIT_CODE_SIDECHANNELTEST_BADCERT 1
354 #define EXIT_CODE_SIDECHANNELTEST_NODATA 2
355 #define EXIT_CODE_SIDECHANNELTEST_REVOKED 3
357 static void
358 verifyFromSideChannel(CERTCertificate *cert, ServerCertAuth *sca)
359 {
360 PRUint64 revDoNotUse =
361 CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD;
363 PRUint64 revUseLocalOnlyAndSoftFail =
364 CERT_REV_M_TEST_USING_THIS_METHOD
365 | CERT_REV_M_FORBID_NETWORK_FETCHING
366 | CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE
367 | CERT_REV_M_IGNORE_MISSING_FRESH_INFO
368 | CERT_REV_M_STOP_TESTING_ON_FRESH_INFO;
370 PRUint64 revUseLocalOnlyAndHardFail =
371 CERT_REV_M_TEST_USING_THIS_METHOD
372 | CERT_REV_M_FORBID_NETWORK_FETCHING
373 | CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE
374 | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
375 | CERT_REV_M_STOP_TESTING_ON_FRESH_INFO;
377 PRUint64 methodFlagsDoNotUse[2];
378 PRUint64 methodFlagsCheckSoftFail[2];
379 PRUint64 methodFlagsCheckHardFail[2];
380 CERTRevocationTests revTestsDoNotCheck;
381 CERTRevocationTests revTestsOverallSoftFail;
382 CERTRevocationTests revTestsOverallHardFail;
383 CERTRevocationFlags rev;
384 CERTValInParam cvin[2];
385 CERTValOutParam cvout[1];
386 SECStatus rv;
388 methodFlagsDoNotUse[cert_revocation_method_crl] = revDoNotUse;
389 methodFlagsDoNotUse[cert_revocation_method_ocsp] = revDoNotUse;
391 methodFlagsCheckSoftFail[cert_revocation_method_crl] =
392 sca->allowCRLSideChannelData ? revUseLocalOnlyAndSoftFail : revDoNotUse;
393 methodFlagsCheckSoftFail[cert_revocation_method_ocsp] =
394 sca->allowOCSPSideChannelData ? revUseLocalOnlyAndSoftFail : revDoNotUse;
396 methodFlagsCheckHardFail[cert_revocation_method_crl] =
397 sca->allowCRLSideChannelData ? revUseLocalOnlyAndHardFail : revDoNotUse;
398 methodFlagsCheckHardFail[cert_revocation_method_ocsp] =
399 sca->allowOCSPSideChannelData ? revUseLocalOnlyAndHardFail : revDoNotUse;
401 revTestsDoNotCheck.cert_rev_flags_per_method = methodFlagsDoNotUse;
402 revTestsDoNotCheck.number_of_defined_methods = 2;
403 revTestsDoNotCheck.number_of_preferred_methods = 0;
404 revTestsDoNotCheck.cert_rev_method_independent_flags =
405 CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST
406 | CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT;
408 revTestsOverallSoftFail.cert_rev_flags_per_method = 0; /* must define later */
409 revTestsOverallSoftFail.number_of_defined_methods = 2;
410 revTestsOverallSoftFail.number_of_preferred_methods = 0;
411 revTestsOverallSoftFail.cert_rev_method_independent_flags =
412 CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST
413 | CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT;
415 revTestsOverallHardFail.cert_rev_flags_per_method = 0; /* must define later */
416 revTestsOverallHardFail.number_of_defined_methods = 2;
417 revTestsOverallHardFail.number_of_preferred_methods = 0;
418 revTestsOverallHardFail.cert_rev_method_independent_flags =
419 CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST
420 | CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE;
422 rev.chainTests = revTestsDoNotCheck;
423 rev.leafTests = revTestsDoNotCheck;
425 cvin[0].type = cert_pi_revocationFlags;
426 cvin[0].value.pointer.revocation = &rev;
427 cvin[1].type = cert_pi_end;
429 cvout[0].type = cert_po_end;
431 /* Strategy:
432 *
433 * Verify with revocation checking disabled.
434 * On failure return 1.
435 *
436 * if result if "good", then continue testing.
437 *
438 * Verify with CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO.
439 * If result is good, return 0.
440 *
441 * On failure continue testing, find out why it failed.
442 *
443 * Verify with CERT_REV_M_IGNORE_MISSING_FRESH_INFO
444 *
445 * If result is "good", then our previous test failed,
446 * because we don't have fresh revocation info, return 2.
447 *
448 * If result is still bad, we do have revocation info,
449 * and it says "revoked" or something equivalent, return 3.
450 */
452 /* revocation checking disabled */
453 rv = CERT_PKIXVerifyCert(cert, certificateUsageSSLServer,
454 cvin, cvout, NULL);
455 if (rv != SECSuccess) {
456 sca->sideChannelRevocationTestResultCode =
457 EXIT_CODE_SIDECHANNELTEST_BADCERT;
458 return;
459 }
461 /* revocation checking, hard fail */
462 if (sca->allowOCSPSideChannelData && sca->allowCRLSideChannelData) {
463 /* any method is allowed. use soft fail on individual checks,
464 * but use hard fail on the overall check
465 */
466 revTestsOverallHardFail.cert_rev_flags_per_method = methodFlagsCheckSoftFail;
467 }
468 else {
469 /* only one method is allowed. use hard fail on the individual checks.
470 * hard/soft fail is irrelevant on overall flags.
471 */
472 revTestsOverallHardFail.cert_rev_flags_per_method = methodFlagsCheckHardFail;
473 }
474 rev.leafTests = revTestsOverallHardFail;
475 rev.chainTests =
476 sca->requireDataForIntermediates ? revTestsOverallHardFail : revTestsDoNotCheck;
477 rv = CERT_PKIXVerifyCert(cert, certificateUsageSSLServer,
478 cvin, cvout, NULL);
479 if (rv == SECSuccess) {
480 sca->sideChannelRevocationTestResultCode =
481 EXIT_CODE_SIDECHANNELTEST_GOOD;
482 return;
483 }
485 /* revocation checking, soft fail */
486 revTestsOverallSoftFail.cert_rev_flags_per_method = methodFlagsCheckSoftFail;
487 rev.leafTests = revTestsOverallSoftFail;
488 rev.chainTests =
489 sca->requireDataForIntermediates ? revTestsOverallSoftFail : revTestsDoNotCheck;
490 rv = CERT_PKIXVerifyCert(cert, certificateUsageSSLServer,
491 cvin, cvout, NULL);
492 if (rv == SECSuccess) {
493 sca->sideChannelRevocationTestResultCode =
494 EXIT_CODE_SIDECHANNELTEST_NODATA;
495 return;
496 }
498 sca->sideChannelRevocationTestResultCode =
499 EXIT_CODE_SIDECHANNELTEST_REVOKED;
500 }
502 static SECStatus
503 ownAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
504 PRBool isServer)
505 {
506 ServerCertAuth * serverCertAuth = (ServerCertAuth *) arg;
508 if (!serverCertAuth->shouldPause) {
509 CERTCertificate *cert;
510 int i;
511 const SECItemArray *csa;
513 if (!serverCertAuth->testFreshStatusFromSideChannel) {
514 return SSL_AuthCertificate(serverCertAuth->dbHandle,
515 fd, checkSig, isServer);
516 }
518 /* No verification attempt must have happened before now,
519 * to ensure revocation data has been actively retrieved yet,
520 * or our test will produce incorrect results.
521 */
523 cert = SSL_RevealCert(fd);
524 if (!cert) {
525 exit(254);
526 }
528 csa = SSL_PeerStapledOCSPResponses(fd);
529 if (csa) {
530 for (i = 0; i < csa->len; ++i) {
531 PORT_SetError(0);
532 if (CERT_CacheOCSPResponseFromSideChannel(
533 serverCertAuth->dbHandle, cert, PR_Now(),
534 &csa->items[i], arg) != SECSuccess) {
535 PRErrorCode error = PR_GetError();
536 PORT_Assert(error != 0);
537 }
538 }
539 }
541 verifyFromSideChannel(cert, serverCertAuth);
542 CERT_DestroyCertificate(cert);
543 /* return success to ensure our caller will continue and we will
544 * reach the code that handles
545 * serverCertAuth->sideChannelRevocationTestResultCode
546 */
547 return SECSuccess;
548 }
550 FPRINTF(stderr, "%s: using asynchronous certificate validation\n",
551 progName);
553 PORT_Assert(!serverCertAuth->isPaused);
554 serverCertAuth->isPaused = PR_TRUE;
555 return SECWouldBlock;
556 }
558 SECStatus
559 own_GetClientAuthData(void * arg,
560 PRFileDesc * socket,
561 struct CERTDistNamesStr * caNames,
562 struct CERTCertificateStr ** pRetCert,
563 struct SECKEYPrivateKeyStr **pRetKey)
564 {
565 if (verbose > 1) {
566 SECStatus rv;
567 fprintf(stderr, "Server requested Client Authentication\n");
568 if (caNames && caNames->nnames > 0) {
569 PLArenaPool *arena = caNames->arena;
570 if (!arena)
571 arena = PORT_NewArena(2048);
572 if (arena) {
573 int i;
574 for (i = 0; i < caNames->nnames; ++i) {
575 char *nameString;
576 CERTName dn;
577 rv = SEC_QuickDERDecodeItem(arena,
578 &dn,
579 SEC_ASN1_GET(CERT_NameTemplate),
580 caNames->names + i);
581 if (rv != SECSuccess)
582 continue;
583 nameString = CERT_NameToAscii(&dn);
584 if (!nameString)
585 continue;
586 fprintf(stderr, "CA[%d]: %s\n", i + 1, nameString);
587 PORT_Free(nameString);
588 }
589 if (!caNames->arena) {
590 PORT_FreeArena(arena, PR_FALSE);
591 }
592 }
593 }
594 rv = NSS_GetClientAuthData(arg, socket, caNames, pRetCert, pRetKey);
595 if (rv == SECSuccess && *pRetCert) {
596 char *nameString = CERT_NameToAscii(&((*pRetCert)->subject));
597 if (nameString) {
598 fprintf(stderr, "sent cert: %s\n", nameString);
599 PORT_Free(nameString);
600 }
601 } else {
602 fprintf(stderr, "send no cert\n");
603 }
604 return rv;
605 }
606 return NSS_GetClientAuthData(arg, socket, caNames, pRetCert, pRetKey);
607 }
609 #if defined(WIN32) || defined(OS2)
610 void
611 thread_main(void * arg)
612 {
613 PRFileDesc * ps = (PRFileDesc *)arg;
614 PRFileDesc * std_in = PR_GetSpecialFD(PR_StandardInput);
615 int wc, rc;
616 char buf[256];
618 #ifdef WIN32
619 {
620 /* Put stdin into O_BINARY mode
621 ** or else incoming \r\n's will become \n's.
622 */
623 int smrv = _setmode(_fileno(stdin), _O_BINARY);
624 if (smrv == -1) {
625 fprintf(stderr,
626 "%s: Cannot change stdin to binary mode. Use -i option instead.\n",
627 progName);
628 /* plow ahead anyway */
629 }
630 }
631 #endif
633 do {
634 rc = PR_Read(std_in, buf, sizeof buf);
635 if (rc <= 0)
636 break;
637 wc = PR_Send(ps, buf, rc, 0, maxInterval);
638 } while (wc == rc);
639 PR_Close(ps);
640 }
642 #endif
644 static void
645 printHostNameAndAddr(const char * host, const PRNetAddr * addr)
646 {
647 PRUint16 port = PR_NetAddrInetPort(addr);
648 char addrBuf[80];
649 PRStatus st = PR_NetAddrToString(addr, addrBuf, sizeof addrBuf);
651 if (st == PR_SUCCESS) {
652 port = PR_ntohs(port);
653 FPRINTF(stderr, "%s: connecting to %s:%hu (address=%s)\n",
654 progName, host, port, addrBuf);
655 }
656 }
658 /*
659 * Prints output according to skipProtoHeader flag. If skipProtoHeader
660 * is not set, prints without any changes, otherwise looking
661 * for \n\r\n(empty line sequence: HTTP header separator) and
662 * prints everything after it.
663 */
664 static void
665 separateReqHeader(const PRFileDesc* outFd, const char* buf, const int nb,
666 PRBool *wrStarted, int *ptrnMatched) {
668 /* it is sufficient to look for only "\n\r\n". Hopping that
669 * HTTP response format satisfies the standard */
670 char *ptrnStr = "\n\r\n";
671 char *resPtr;
673 if (nb == 0) {
674 return;
675 }
677 if (*ptrnMatched > 0) {
678 /* Get here only if previous separateReqHeader call found
679 * only a fragment of "\n\r\n" in previous buffer. */
680 PORT_Assert(*ptrnMatched < 3);
682 /* the size of fragment of "\n\r\n" what we want to find in this
683 * buffer is equal to *ptrnMatched */
684 if (*ptrnMatched <= nb) {
685 /* move the pointer to the beginning of the fragment */
686 int strSize = *ptrnMatched;
687 char *tmpPtrn = ptrnStr + (3 - strSize);
688 if (PL_strncmp(buf, tmpPtrn, strSize) == 0) {
689 /* print the rest of the buffer(without the fragment) */
690 PR_Write((void*)outFd, buf + strSize, nb - strSize);
691 *wrStarted = PR_TRUE;
692 return;
693 }
694 } else {
695 /* we are here only when nb == 1 && *ptrnMatched == 2 */
696 if (*buf == '\r') {
697 *ptrnMatched = 1;
698 } else {
699 *ptrnMatched = 0;
700 }
701 return;
702 }
703 }
704 resPtr = PL_strnstr(buf, ptrnStr, nb);
705 if (resPtr != NULL) {
706 /* if "\n\r\n" was found in the buffer, calculate offset
707 * and print the rest of the buffer */
708 int newBn = nb - (resPtr - buf + 3); /* 3 is the length of "\n\r\n" */
710 PR_Write((void*)outFd, resPtr + 3, newBn);
711 *wrStarted = PR_TRUE;
712 return;
713 } else {
714 /* try to find a fragment of "\n\r\n" at the end of the buffer.
715 * if found, set *ptrnMatched to the number of chars left to find
716 * in the next buffer.*/
717 int i;
718 for(i = 1 ;i < 3;i++) {
719 char *bufPrt;
720 int strSize = 3 - i;
722 if (strSize > nb) {
723 continue;
724 }
725 bufPrt = (char*)(buf + nb - strSize);
727 if (PL_strncmp(bufPrt, ptrnStr, strSize) == 0) {
728 *ptrnMatched = i;
729 return;
730 }
731 }
732 }
733 }
735 #define SSOCK_FD 0
736 #define STDIN_FD 1
738 #define HEXCHAR_TO_INT(c, i) \
739 if (((c) >= '0') && ((c) <= '9')) { \
740 i = (c) - '0'; \
741 } else if (((c) >= 'a') && ((c) <= 'f')) { \
742 i = (c) - 'a' + 10; \
743 } else if (((c) >= 'A') && ((c) <= 'F')) { \
744 i = (c) - 'A' + 10; \
745 } else { \
746 Usage(progName); \
747 }
749 static SECStatus
750 restartHandshakeAfterServerCertIfNeeded(PRFileDesc * fd,
751 ServerCertAuth * serverCertAuth,
752 PRBool override)
753 {
754 SECStatus rv;
755 PRErrorCode error;
757 if (!serverCertAuth->isPaused)
758 return SECSuccess;
760 FPRINTF(stderr, "%s: handshake was paused by auth certificate hook\n",
761 progName);
763 serverCertAuth->isPaused = PR_FALSE;
764 rv = SSL_AuthCertificate(serverCertAuth->dbHandle, fd, PR_TRUE, PR_FALSE);
765 if (rv != SECSuccess) {
766 error = PR_GetError();
767 if (error == 0) {
768 PR_NOT_REACHED("SSL_AuthCertificate return SECFailure without "
769 "setting error code.");
770 error = PR_INVALID_STATE_ERROR;
771 } else if (override) {
772 rv = ownBadCertHandler(NULL, fd);
773 }
774 }
775 if (rv == SECSuccess) {
776 error = 0;
777 }
779 if (SSL_AuthCertificateComplete(fd, error) != SECSuccess) {
780 rv = SECFailure;
781 }
783 return rv;
784 }
786 int main(int argc, char **argv)
787 {
788 PRFileDesc * s;
789 PRFileDesc * std_out;
790 char * host = NULL;
791 char * certDir = NULL;
792 char * nickname = NULL;
793 char * cipherString = NULL;
794 char * tmp;
795 int multiplier = 0;
796 SECStatus rv;
797 PRStatus status;
798 PRInt32 filesReady;
799 int npds;
800 int override = 0;
801 SSLVersionRange enabledVersions;
802 PRBool enableSSL2 = PR_TRUE;
803 int bypassPKCS11 = 0;
804 int disableLocking = 0;
805 int useExportPolicy = 0;
806 int enableSessionTickets = 0;
807 int enableCompression = 0;
808 int enableFalseStart = 0;
809 int enableCertStatus = 0;
810 PRSocketOptionData opt;
811 PRNetAddr addr;
812 PRPollDesc pollset[2];
813 PRBool allowIPv4 = PR_TRUE;
814 PRBool allowIPv6 = PR_TRUE;
815 PRBool pingServerFirst = PR_FALSE;
816 int pingTimeoutSeconds = -1;
817 PRBool clientSpeaksFirst = PR_FALSE;
818 PRBool wrStarted = PR_FALSE;
819 PRBool skipProtoHeader = PR_FALSE;
820 ServerCertAuth serverCertAuth;
821 int headerSeparatorPtrnId = 0;
822 int error = 0;
823 PRUint16 portno = 443;
824 char * hs1SniHostName = NULL;
825 char * hs2SniHostName = NULL;
826 PLOptState *optstate;
827 PLOptStatus optstatus;
828 PRStatus prStatus;
830 serverCertAuth.shouldPause = PR_TRUE;
831 serverCertAuth.isPaused = PR_FALSE;
832 serverCertAuth.dbHandle = NULL;
833 serverCertAuth.testFreshStatusFromSideChannel = PR_FALSE;
834 serverCertAuth.sideChannelRevocationTestResultCode = EXIT_CODE_HANDSHAKE_FAILED;
835 serverCertAuth.requireDataForIntermediates = PR_FALSE;
836 serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
837 serverCertAuth.allowCRLSideChannelData = PR_TRUE;
839 progName = strrchr(argv[0], '/');
840 if (!progName)
841 progName = strrchr(argv[0], '\\');
842 progName = progName ? progName+1 : argv[0];
844 tmp = PR_GetEnv("NSS_DEBUG_TIMEOUT");
845 if (tmp && tmp[0]) {
846 int sec = PORT_Atoi(tmp);
847 if (sec > 0) {
848 maxInterval = PR_SecondsToInterval(sec);
849 }
850 }
852 SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions);
854 optstate = PL_CreateOptState(argc, argv,
855 "46BFM:OSTV:W:Ya:c:d:fgh:m:n:op:qr:st:uvw:xz");
856 while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
857 switch (optstate->option) {
858 case '?':
859 default : Usage(progName); break;
861 case '4': allowIPv6 = PR_FALSE; if (!allowIPv4) Usage(progName); break;
862 case '6': allowIPv4 = PR_FALSE; if (!allowIPv6) Usage(progName); break;
864 case 'B': bypassPKCS11 = 1; break;
866 case 'F': if (serverCertAuth.testFreshStatusFromSideChannel) {
867 /* parameter given twice or more */
868 serverCertAuth.requireDataForIntermediates = PR_TRUE;
869 }
870 serverCertAuth.testFreshStatusFromSideChannel = PR_TRUE;
871 break;
873 case 'I': /* reserved for OCSP multi-stapling */ break;
875 case 'O': serverCertAuth.shouldPause = PR_FALSE; break;
877 case 'M': switch (atoi(optstate->value)) {
878 case 1:
879 serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
880 serverCertAuth.allowCRLSideChannelData = PR_FALSE;
881 break;
882 case 2:
883 serverCertAuth.allowOCSPSideChannelData = PR_FALSE;
884 serverCertAuth.allowCRLSideChannelData = PR_TRUE;
885 break;
886 case 0:
887 default:
888 serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
889 serverCertAuth.allowCRLSideChannelData = PR_TRUE;
890 break;
891 };
892 break;
894 case 'S': skipProtoHeader = PR_TRUE; break;
896 case 'T': enableCertStatus = 1; break;
898 case 'V': if (SECU_ParseSSLVersionRangeString(optstate->value,
899 enabledVersions, enableSSL2,
900 &enabledVersions, &enableSSL2) != SECSuccess) {
901 Usage(progName);
902 }
903 break;
905 case 'Y': PrintCipherUsage(progName); exit(0); break;
907 case 'a': if (!hs1SniHostName) {
908 hs1SniHostName = PORT_Strdup(optstate->value);
909 } else if (!hs2SniHostName) {
910 hs2SniHostName = PORT_Strdup(optstate->value);
911 } else {
912 Usage(progName);
913 }
914 break;
916 case 'c': cipherString = PORT_Strdup(optstate->value); break;
918 case 'g': enableFalseStart = 1; break;
920 case 'd': certDir = PORT_Strdup(optstate->value); break;
922 case 'f': clientSpeaksFirst = PR_TRUE; break;
924 case 'h': host = PORT_Strdup(optstate->value); break;
926 case 'm':
927 multiplier = atoi(optstate->value);
928 if (multiplier < 0)
929 multiplier = 0;
930 break;
932 case 'n': nickname = PORT_Strdup(optstate->value); break;
934 case 'o': override = 1; break;
936 case 'p': portno = (PRUint16)atoi(optstate->value); break;
938 case 'q': pingServerFirst = PR_TRUE; break;
940 case 's': disableLocking = 1; break;
942 case 't': pingTimeoutSeconds = atoi(optstate->value); break;
944 case 'u': enableSessionTickets = PR_TRUE; break;
946 case 'v': verbose++; break;
948 case 'r': renegotiationsToDo = atoi(optstate->value); break;
950 case 'w':
951 pwdata.source = PW_PLAINTEXT;
952 pwdata.data = PORT_Strdup(optstate->value);
953 break;
955 case 'W':
956 pwdata.source = PW_FROMFILE;
957 pwdata.data = PORT_Strdup(optstate->value);
958 break;
960 case 'x': useExportPolicy = 1; break;
962 case 'z': enableCompression = 1; break;
963 }
964 }
966 PL_DestroyOptState(optstate);
968 if (optstatus == PL_OPT_BAD)
969 Usage(progName);
971 if (!host || !portno)
972 Usage(progName);
974 if (serverCertAuth.testFreshStatusFromSideChannel
975 && serverCertAuth.shouldPause) {
976 fprintf(stderr, "%s: -F requires the use of -O\n", progName);
977 exit(1);
978 }
980 PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
982 PK11_SetPasswordFunc(SECU_GetModulePassword);
984 status = PR_StringToNetAddr(host, &addr);
985 if (status == PR_SUCCESS) {
986 addr.inet.port = PR_htons(portno);
987 } else {
988 /* Lookup host */
989 PRAddrInfo *addrInfo;
990 void *enumPtr = NULL;
992 addrInfo = PR_GetAddrInfoByName(host, PR_AF_UNSPEC,
993 PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME);
994 if (!addrInfo) {
995 SECU_PrintError(progName, "error looking up host");
996 return 1;
997 }
998 for (;;) {
999 enumPtr = PR_EnumerateAddrInfo(enumPtr, addrInfo, portno, &addr);
1000 if (enumPtr == NULL)
1001 break;
1002 if (addr.raw.family == PR_AF_INET && allowIPv4)
1003 break;
1004 if (addr.raw.family == PR_AF_INET6 && allowIPv6)
1005 break;
1006 }
1007 PR_FreeAddrInfo(addrInfo);
1008 if (enumPtr == NULL) {
1009 SECU_PrintError(progName, "error looking up host address");
1010 return 1;
1011 }
1012 }
1014 printHostNameAndAddr(host, &addr);
1016 if (pingServerFirst) {
1017 int iter = 0;
1018 PRErrorCode err;
1019 int max_attempts = MAX_WAIT_FOR_SERVER;
1020 if (pingTimeoutSeconds >= 0) {
1021 /* If caller requested a timeout, let's try just twice. */
1022 max_attempts = 2;
1023 }
1024 do {
1025 PRIntervalTime timeoutInterval = PR_INTERVAL_NO_TIMEOUT;
1026 s = PR_OpenTCPSocket(addr.raw.family);
1027 if (s == NULL) {
1028 SECU_PrintError(progName, "Failed to create a TCP socket");
1029 }
1030 opt.option = PR_SockOpt_Nonblocking;
1031 opt.value.non_blocking = PR_FALSE;
1032 prStatus = PR_SetSocketOption(s, &opt);
1033 if (prStatus != PR_SUCCESS) {
1034 PR_Close(s);
1035 SECU_PrintError(progName,
1036 "Failed to set blocking socket option");
1037 return 1;
1038 }
1039 if (pingTimeoutSeconds >= 0) {
1040 timeoutInterval = PR_SecondsToInterval(pingTimeoutSeconds);
1041 }
1042 prStatus = PR_Connect(s, &addr, timeoutInterval);
1043 if (prStatus == PR_SUCCESS) {
1044 PR_Shutdown(s, PR_SHUTDOWN_BOTH);
1045 PR_Close(s);
1046 PR_Cleanup();
1047 return 0;
1048 }
1049 err = PR_GetError();
1050 if ((err != PR_CONNECT_REFUSED_ERROR) &&
1051 (err != PR_CONNECT_RESET_ERROR)) {
1052 SECU_PrintError(progName, "TCP Connection failed");
1053 return 1;
1054 }
1055 PR_Close(s);
1056 PR_Sleep(PR_MillisecondsToInterval(WAIT_INTERVAL));
1057 } while (++iter < max_attempts);
1058 SECU_PrintError(progName,
1059 "Client timed out while waiting for connection to server");
1060 return 1;
1061 }
1063 /* open the cert DB, the key DB, and the secmod DB. */
1064 if (!certDir) {
1065 certDir = SECU_DefaultSSLDir(); /* Look in $SSL_DIR */
1066 certDir = SECU_ConfigDirectory(certDir);
1067 } else {
1068 char *certDirTmp = certDir;
1069 certDir = SECU_ConfigDirectory(certDirTmp);
1070 PORT_Free(certDirTmp);
1071 }
1072 rv = NSS_Init(certDir);
1073 if (rv != SECSuccess) {
1074 SECU_PrintError(progName, "unable to open cert database");
1075 return 1;
1076 }
1078 /* set the policy bits true for all the cipher suites. */
1079 if (useExportPolicy)
1080 NSS_SetExportPolicy();
1081 else
1082 NSS_SetDomesticPolicy();
1084 /* all the SSL2 and SSL3 cipher suites are enabled by default. */
1085 if (cipherString) {
1086 /* disable all the ciphers, then enable the ones we want. */
1087 disableAllSSLCiphers();
1088 }
1090 /* Create socket */
1091 s = PR_OpenTCPSocket(addr.raw.family);
1092 if (s == NULL) {
1093 SECU_PrintError(progName, "error creating socket");
1094 return 1;
1095 }
1097 opt.option = PR_SockOpt_Nonblocking;
1098 opt.value.non_blocking = PR_TRUE; /* default */
1099 if (serverCertAuth.testFreshStatusFromSideChannel) {
1100 opt.value.non_blocking = PR_FALSE;
1101 }
1102 PR_SetSocketOption(s, &opt);
1103 /*PR_SetSocketOption(PR_GetSpecialFD(PR_StandardInput), &opt);*/
1105 s = SSL_ImportFD(NULL, s);
1106 if (s == NULL) {
1107 SECU_PrintError(progName, "error importing socket");
1108 return 1;
1109 }
1111 rv = SSL_OptionSet(s, SSL_SECURITY, 1);
1112 if (rv != SECSuccess) {
1113 SECU_PrintError(progName, "error enabling socket");
1114 return 1;
1115 }
1117 rv = SSL_OptionSet(s, SSL_HANDSHAKE_AS_CLIENT, 1);
1118 if (rv != SECSuccess) {
1119 SECU_PrintError(progName, "error enabling client handshake");
1120 return 1;
1121 }
1123 /* all the SSL2 and SSL3 cipher suites are enabled by default. */
1124 if (cipherString) {
1125 char *cstringSaved = cipherString;
1126 int ndx;
1128 while (0 != (ndx = *cipherString++)) {
1129 int cipher;
1131 if (ndx == ':') {
1132 int ctmp;
1134 cipher = 0;
1135 HEXCHAR_TO_INT(*cipherString, ctmp)
1136 cipher |= (ctmp << 12);
1137 cipherString++;
1138 HEXCHAR_TO_INT(*cipherString, ctmp)
1139 cipher |= (ctmp << 8);
1140 cipherString++;
1141 HEXCHAR_TO_INT(*cipherString, ctmp)
1142 cipher |= (ctmp << 4);
1143 cipherString++;
1144 HEXCHAR_TO_INT(*cipherString, ctmp)
1145 cipher |= ctmp;
1146 cipherString++;
1147 } else {
1148 const int *cptr;
1150 if (! isalpha(ndx))
1151 Usage(progName);
1152 cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
1153 for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; )
1154 /* do nothing */;
1155 }
1156 if (cipher > 0) {
1157 SECStatus status;
1158 status = SSL_CipherPrefSet(s, cipher, SSL_ALLOWED);
1159 if (status != SECSuccess)
1160 SECU_PrintError(progName, "SSL_CipherPrefSet()");
1161 } else {
1162 Usage(progName);
1163 }
1164 }
1165 PORT_Free(cstringSaved);
1166 }
1168 rv = SSL_VersionRangeSet(s, &enabledVersions);
1169 if (rv != SECSuccess) {
1170 SECU_PrintError(progName, "error setting SSL/TLS version range ");
1171 return 1;
1172 }
1174 rv = SSL_OptionSet(s, SSL_ENABLE_SSL2, enableSSL2);
1175 if (rv != SECSuccess) {
1176 SECU_PrintError(progName, "error enabling SSLv2 ");
1177 return 1;
1178 }
1180 rv = SSL_OptionSet(s, SSL_V2_COMPATIBLE_HELLO, enableSSL2);
1181 if (rv != SECSuccess) {
1182 SECU_PrintError(progName, "error enabling SSLv2 compatible hellos ");
1183 return 1;
1184 }
1186 /* enable PKCS11 bypass */
1187 rv = SSL_OptionSet(s, SSL_BYPASS_PKCS11, bypassPKCS11);
1188 if (rv != SECSuccess) {
1189 SECU_PrintError(progName, "error enabling PKCS11 bypass");
1190 return 1;
1191 }
1193 /* disable SSL socket locking */
1194 rv = SSL_OptionSet(s, SSL_NO_LOCKS, disableLocking);
1195 if (rv != SECSuccess) {
1196 SECU_PrintError(progName, "error disabling SSL socket locking");
1197 return 1;
1198 }
1200 /* enable Session Ticket extension. */
1201 rv = SSL_OptionSet(s, SSL_ENABLE_SESSION_TICKETS, enableSessionTickets);
1202 if (rv != SECSuccess) {
1203 SECU_PrintError(progName, "error enabling Session Ticket extension");
1204 return 1;
1205 }
1207 /* enable compression. */
1208 rv = SSL_OptionSet(s, SSL_ENABLE_DEFLATE, enableCompression);
1209 if (rv != SECSuccess) {
1210 SECU_PrintError(progName, "error enabling compression");
1211 return 1;
1212 }
1214 /* enable false start. */
1215 rv = SSL_OptionSet(s, SSL_ENABLE_FALSE_START, enableFalseStart);
1216 if (rv != SECSuccess) {
1217 SECU_PrintError(progName, "error enabling false start");
1218 return 1;
1219 }
1221 /* enable cert status (OCSP stapling). */
1222 rv = SSL_OptionSet(s, SSL_ENABLE_OCSP_STAPLING, enableCertStatus);
1223 if (rv != SECSuccess) {
1224 SECU_PrintError(progName, "error enabling cert status (OCSP stapling)");
1225 return 1;
1226 }
1228 SSL_SetPKCS11PinArg(s, &pwdata);
1230 serverCertAuth.dbHandle = CERT_GetDefaultCertDB();
1232 SSL_AuthCertificateHook(s, ownAuthCertificate, &serverCertAuth);
1233 if (override) {
1234 SSL_BadCertHook(s, ownBadCertHandler, NULL);
1235 }
1236 SSL_GetClientAuthDataHook(s, own_GetClientAuthData, (void *)nickname);
1237 SSL_HandshakeCallback(s, handshakeCallback, hs2SniHostName);
1238 if (hs1SniHostName) {
1239 SSL_SetURL(s, hs1SniHostName);
1240 } else {
1241 SSL_SetURL(s, host);
1242 }
1244 /* Try to connect to the server */
1245 status = PR_Connect(s, &addr, PR_INTERVAL_NO_TIMEOUT);
1246 if (status != PR_SUCCESS) {
1247 if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
1248 if (verbose)
1249 SECU_PrintError(progName, "connect");
1250 milliPause(50 * multiplier);
1251 pollset[SSOCK_FD].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
1252 pollset[SSOCK_FD].out_flags = 0;
1253 pollset[SSOCK_FD].fd = s;
1254 while(1) {
1255 FPRINTF(stderr,
1256 "%s: about to call PR_Poll for connect completion!\n",
1257 progName);
1258 filesReady = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT);
1259 if (filesReady < 0) {
1260 SECU_PrintError(progName, "unable to connect (poll)");
1261 return 1;
1262 }
1263 FPRINTF(stderr,
1264 "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
1265 progName, pollset[SSOCK_FD].out_flags);
1266 if (filesReady == 0) { /* shouldn't happen! */
1267 FPRINTF(stderr, "%s: PR_Poll returned zero!\n", progName);
1268 return 1;
1269 }
1270 status = PR_GetConnectStatus(pollset);
1271 if (status == PR_SUCCESS) {
1272 break;
1273 }
1274 if (PR_GetError() != PR_IN_PROGRESS_ERROR) {
1275 SECU_PrintError(progName, "unable to connect (poll)");
1276 return 1;
1277 }
1278 SECU_PrintError(progName, "poll");
1279 milliPause(50 * multiplier);
1280 }
1281 } else {
1282 SECU_PrintError(progName, "unable to connect");
1283 return 1;
1284 }
1285 }
1287 pollset[SSOCK_FD].fd = s;
1288 pollset[SSOCK_FD].in_flags = PR_POLL_EXCEPT |
1289 (clientSpeaksFirst ? 0 : PR_POLL_READ);
1290 pollset[STDIN_FD].fd = PR_GetSpecialFD(PR_StandardInput);
1291 pollset[STDIN_FD].in_flags = PR_POLL_READ;
1292 npds = 2;
1293 std_out = PR_GetSpecialFD(PR_StandardOutput);
1295 #if defined(WIN32) || defined(OS2)
1296 /* PR_Poll cannot be used with stdin on Windows or OS/2. (sigh).
1297 ** But use of PR_Poll and non-blocking sockets is a major feature
1298 ** of this program. So, we simulate a pollable stdin with a
1299 ** TCP socket pair and a thread that reads stdin and writes to
1300 ** that socket pair.
1301 */
1302 {
1303 PRFileDesc * fds[2];
1304 PRThread * thread;
1306 int nspr_rv = PR_NewTCPSocketPair(fds);
1307 if (nspr_rv != PR_SUCCESS) {
1308 SECU_PrintError(progName, "PR_NewTCPSocketPair failed");
1309 error = 1;
1310 goto done;
1311 }
1312 pollset[STDIN_FD].fd = fds[1];
1314 thread = PR_CreateThread(PR_USER_THREAD, thread_main, fds[0],
1315 PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
1316 PR_UNJOINABLE_THREAD, 0);
1317 if (!thread) {
1318 SECU_PrintError(progName, "PR_CreateThread failed");
1319 error = 1;
1320 goto done;
1321 }
1322 }
1323 #endif
1325 if (serverCertAuth.testFreshStatusFromSideChannel) {
1326 SSL_ForceHandshake(s);
1327 error = serverCertAuth.sideChannelRevocationTestResultCode;
1328 goto done;
1329 }
1331 /*
1332 ** Select on stdin and on the socket. Write data from stdin to
1333 ** socket, read data from socket and write to stdout.
1334 */
1335 FPRINTF(stderr, "%s: ready...\n", progName);
1337 while (pollset[SSOCK_FD].in_flags | pollset[STDIN_FD].in_flags) {
1338 char buf[4000]; /* buffer for stdin */
1339 int nb; /* num bytes read from stdin. */
1341 rv = restartHandshakeAfterServerCertIfNeeded(s, &serverCertAuth,
1342 override);
1343 if (rv != SECSuccess) {
1344 error = EXIT_CODE_HANDSHAKE_FAILED;
1345 SECU_PrintError(progName, "authentication of server cert failed");
1346 goto done;
1347 }
1349 pollset[SSOCK_FD].out_flags = 0;
1350 pollset[STDIN_FD].out_flags = 0;
1352 FPRINTF(stderr, "%s: about to call PR_Poll !\n", progName);
1353 filesReady = PR_Poll(pollset, npds, PR_INTERVAL_NO_TIMEOUT);
1354 if (filesReady < 0) {
1355 SECU_PrintError(progName, "select failed");
1356 error = 1;
1357 goto done;
1358 }
1359 if (filesReady == 0) { /* shouldn't happen! */
1360 FPRINTF(stderr, "%s: PR_Poll returned zero!\n", progName);
1361 return 1;
1362 }
1363 FPRINTF(stderr, "%s: PR_Poll returned!\n", progName);
1364 if (pollset[STDIN_FD].in_flags) {
1365 FPRINTF(stderr,
1366 "%s: PR_Poll returned 0x%02x for stdin out_flags.\n",
1367 progName, pollset[STDIN_FD].out_flags);
1368 }
1369 if (pollset[SSOCK_FD].in_flags) {
1370 FPRINTF(stderr,
1371 "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
1372 progName, pollset[SSOCK_FD].out_flags);
1373 }
1374 if (pollset[STDIN_FD].out_flags & PR_POLL_READ) {
1375 /* Read from stdin and write to socket */
1376 nb = PR_Read(pollset[STDIN_FD].fd, buf, sizeof(buf));
1377 FPRINTF(stderr, "%s: stdin read %d bytes\n", progName, nb);
1378 if (nb < 0) {
1379 if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
1380 SECU_PrintError(progName, "read from stdin failed");
1381 error = 1;
1382 break;
1383 }
1384 } else if (nb == 0) {
1385 /* EOF on stdin, stop polling stdin for read. */
1386 pollset[STDIN_FD].in_flags = 0;
1387 } else {
1388 char * bufp = buf;
1389 FPRINTF(stderr, "%s: Writing %d bytes to server\n",
1390 progName, nb);
1391 do {
1392 PRInt32 cc = PR_Send(s, bufp, nb, 0, maxInterval);
1393 if (cc < 0) {
1394 PRErrorCode err = PR_GetError();
1395 if (err != PR_WOULD_BLOCK_ERROR) {
1396 SECU_PrintError(progName,
1397 "write to SSL socket failed");
1398 error = 254;
1399 goto done;
1400 }
1401 cc = 0;
1402 }
1403 bufp += cc;
1404 nb -= cc;
1405 if (nb <= 0)
1406 break;
1408 rv = restartHandshakeAfterServerCertIfNeeded(s,
1409 &serverCertAuth, override);
1410 if (rv != SECSuccess) {
1411 error = EXIT_CODE_HANDSHAKE_FAILED;
1412 SECU_PrintError(progName, "authentication of server cert failed");
1413 goto done;
1414 }
1416 pollset[SSOCK_FD].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
1417 pollset[SSOCK_FD].out_flags = 0;
1418 FPRINTF(stderr,
1419 "%s: about to call PR_Poll on writable socket !\n",
1420 progName);
1421 cc = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT);
1422 FPRINTF(stderr,
1423 "%s: PR_Poll returned with writable socket !\n",
1424 progName);
1425 } while (1);
1426 pollset[SSOCK_FD].in_flags = PR_POLL_READ;
1427 }
1428 }
1430 if (pollset[SSOCK_FD].in_flags) {
1431 FPRINTF(stderr,
1432 "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
1433 progName, pollset[SSOCK_FD].out_flags);
1434 }
1435 if ( (pollset[SSOCK_FD].out_flags & PR_POLL_READ)
1436 || (pollset[SSOCK_FD].out_flags & PR_POLL_ERR)
1437 #ifdef PR_POLL_HUP
1438 || (pollset[SSOCK_FD].out_flags & PR_POLL_HUP)
1439 #endif
1440 ) {
1441 /* Read from socket and write to stdout */
1442 nb = PR_Recv(pollset[SSOCK_FD].fd, buf, sizeof buf, 0, maxInterval);
1443 FPRINTF(stderr, "%s: Read from server %d bytes\n", progName, nb);
1444 if (nb < 0) {
1445 if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
1446 SECU_PrintError(progName, "read from socket failed");
1447 error = 1;
1448 goto done;
1449 }
1450 } else if (nb == 0) {
1451 /* EOF from socket... stop polling socket for read */
1452 pollset[SSOCK_FD].in_flags = 0;
1453 } else {
1454 if (skipProtoHeader != PR_TRUE || wrStarted == PR_TRUE) {
1455 PR_Write(std_out, buf, nb);
1456 } else {
1457 separateReqHeader(std_out, buf, nb, &wrStarted,
1458 &headerSeparatorPtrnId);
1459 }
1460 if (verbose)
1461 fputs("\n\n", stderr);
1462 }
1463 }
1464 milliPause(50 * multiplier);
1465 }
1467 done:
1468 if (hs1SniHostName) {
1469 PORT_Free(hs1SniHostName);
1470 }
1471 if (hs2SniHostName) {
1472 PORT_Free(hs2SniHostName);
1473 }
1474 if (nickname) {
1475 PORT_Free(nickname);
1476 }
1477 if (pwdata.data) {
1478 PORT_Free(pwdata.data);
1479 }
1480 PORT_Free(host);
1482 PR_Close(s);
1483 SSL_ClearSessionCache();
1484 if (NSS_Shutdown() != SECSuccess) {
1485 exit(1);
1486 }
1488 FPRINTF(stderr, "tstclnt: exiting with return code %d\n", error);
1489 PR_Cleanup();
1490 return error;
1491 }