security/nss/cmd/tstclnt/tstclnt.c

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

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;
  1007 	PR_FreeAddrInfo(addrInfo);
  1008 	if (enumPtr == NULL) {
  1009 	    SECU_PrintError(progName, "error looking up host address");
  1010 	    return 1;
  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;
  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");
  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;
  1039             if (pingTimeoutSeconds >= 0) {
  1040               timeoutInterval = PR_SecondsToInterval(pingTimeoutSeconds);
  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;
  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;
  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;
  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);
  1072     rv = NSS_Init(certDir);
  1073     if (rv != SECSuccess) {
  1074         SECU_PrintError(progName, "unable to open cert database");
  1075         return 1;
  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();
  1090     /* Create socket */
  1091     s = PR_OpenTCPSocket(addr.raw.family);
  1092     if (s == NULL) {
  1093 	SECU_PrintError(progName, "error creating socket");
  1094 	return 1;
  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;
  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;
  1111     rv = SSL_OptionSet(s, SSL_SECURITY, 1);
  1112     if (rv != SECSuccess) {
  1113         SECU_PrintError(progName, "error enabling socket");
  1114 	return 1;
  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;
  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 */;
  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);
  1165 	PORT_Free(cstringSaved);
  1168     rv = SSL_VersionRangeSet(s, &enabledVersions);
  1169     if (rv != SECSuccess) {
  1170         SECU_PrintError(progName, "error setting SSL/TLS version range ");
  1171         return 1;
  1174     rv = SSL_OptionSet(s, SSL_ENABLE_SSL2, enableSSL2);
  1175     if (rv != SECSuccess) {
  1176        SECU_PrintError(progName, "error enabling SSLv2 ");
  1177        return 1;
  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;
  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;
  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;
  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;
  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;
  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;
  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;
  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);
  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);
  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;
  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;
  1270 		status = PR_GetConnectStatus(pollset);
  1271 		if (status == PR_SUCCESS) {
  1272 		    break;
  1274 		if (PR_GetError() != PR_IN_PROGRESS_ERROR) {
  1275 		    SECU_PrintError(progName, "unable to connect (poll)");
  1276 		    return 1;
  1278 		SECU_PrintError(progName, "poll");
  1279 		milliPause(50 * multiplier);
  1281 	} else {
  1282 	    SECU_PrintError(progName, "unable to connect");
  1283 	    return 1;
  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     */
  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;
  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;
  1323 #endif
  1325     if (serverCertAuth.testFreshStatusFromSideChannel) {
  1326         SSL_ForceHandshake(s);
  1327         error = serverCertAuth.sideChannelRevocationTestResultCode;
  1328         goto done;
  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;
  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;
  1359 	if (filesReady == 0) {	/* shouldn't happen! */
  1360 	    FPRINTF(stderr, "%s: PR_Poll returned zero!\n", progName);
  1361 	    return 1;
  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);
  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);
  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;
  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;
  1401 			cc = 0;
  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;
  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;
  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);
  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;
  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);
  1460 		if (verbose)
  1461 		    fputs("\n\n", stderr);
  1464 	milliPause(50 * multiplier);
  1467   done:
  1468     if (hs1SniHostName) {
  1469         PORT_Free(hs1SniHostName);
  1471     if (hs2SniHostName) {
  1472         PORT_Free(hs2SniHostName);
  1474     if (nickname) {
  1475         PORT_Free(nickname);
  1477     if (pwdata.data) {
  1478         PORT_Free(pwdata.data);
  1480     PORT_Free(host);
  1482     PR_Close(s);
  1483     SSL_ClearSessionCache();
  1484     if (NSS_Shutdown() != SECSuccess) {
  1485         exit(1);
  1488     FPRINTF(stderr, "tstclnt: exiting with return code %d\n", error);
  1489     PR_Cleanup();
  1490     return error;

mercurial