tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

tstclnt.c (84959B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 /*
      6 **
      7 ** Sample client side test program that uses SSL and NSS
      8 **
      9 */
     10 
     11 #include "secutil.h"
     12 #include "basicutil.h"
     13 
     14 #if defined(XP_UNIX)
     15 #include <unistd.h>
     16 #else
     17 #include <ctype.h> /* for isalpha() */
     18 #endif
     19 
     20 #include <stdio.h>
     21 #include <string.h>
     22 #include <stdlib.h>
     23 #include <errno.h>
     24 #include <fcntl.h>
     25 #include <stdarg.h>
     26 
     27 #include "nspr.h"
     28 #include "prio.h"
     29 #include "prnetdb.h"
     30 #include "nss.h"
     31 #include "nssb64.h"
     32 #include "ocsp.h"
     33 #include "ssl.h"
     34 #include "sslproto.h"
     35 #include "sslexp.h"
     36 #include "pk11func.h"
     37 #include "secmod.h"
     38 #include "plgetopt.h"
     39 #include "plstr.h"
     40 #include "zlib.h"
     41 
     42 #if defined(WIN32)
     43 #include <fcntl.h>
     44 #include <io.h>
     45 #endif
     46 
     47 #define PRINTF   \
     48    if (verbose) \
     49    printf
     50 #define FPRINTF  \
     51    if (verbose) \
     52    fprintf
     53 
     54 #define MAX_WAIT_FOR_SERVER 600
     55 #define WAIT_INTERVAL 100
     56 #define ZERO_RTT_MAX (2 << 16)
     57 
     58 #define EXIT_CODE_HANDSHAKE_FAILED 254
     59 
     60 #define EXIT_CODE_SIDECHANNELTEST_GOOD 0
     61 #define EXIT_CODE_SIDECHANNELTEST_BADCERT 1
     62 #define EXIT_CODE_SIDECHANNELTEST_NODATA 2
     63 #define EXIT_CODE_SIDECHANNELTEST_REVOKED 3
     64 
     65 PRIntervalTime maxInterval = PR_INTERVAL_NO_TIMEOUT;
     66 
     67 int ssl3CipherSuites[] = {
     68    -1,                                /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
     69    -1,                                /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA     * b */
     70    TLS_RSA_WITH_RC4_128_MD5,          /* c */
     71    TLS_RSA_WITH_3DES_EDE_CBC_SHA,     /* d */
     72    TLS_RSA_WITH_DES_CBC_SHA,          /* e */
     73    -1,                                /* TLS_RSA_EXPORT_WITH_RC4_40_MD5        * f */
     74    -1,                                /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5    * g */
     75    -1,                                /* SSL_FORTEZZA_DMS_WITH_NULL_SHA        * h */
     76    TLS_RSA_WITH_NULL_MD5,             /* i */
     77    -1,                                /* SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA    * j */
     78    -1,                                /* SSL_RSA_FIPS_WITH_DES_CBC_SHA         * k */
     79    -1,                                /* TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA   * l */
     80    -1,                                /* TLS_RSA_EXPORT1024_WITH_RC4_56_SHA    * m */
     81    TLS_RSA_WITH_RC4_128_SHA,          /* n */
     82    TLS_DHE_DSS_WITH_RC4_128_SHA,      /* o */
     83    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
     84    TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
     85    TLS_DHE_RSA_WITH_DES_CBC_SHA,      /* r */
     86    TLS_DHE_DSS_WITH_DES_CBC_SHA,      /* s */
     87    TLS_DHE_DSS_WITH_AES_128_CBC_SHA,  /* t */
     88    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,  /* u */
     89    TLS_RSA_WITH_AES_128_CBC_SHA,      /* v */
     90    TLS_DHE_DSS_WITH_AES_256_CBC_SHA,  /* w */
     91    TLS_DHE_RSA_WITH_AES_256_CBC_SHA,  /* x */
     92    TLS_RSA_WITH_AES_256_CBC_SHA,      /* y */
     93    TLS_RSA_WITH_NULL_SHA,             /* z */
     94    0
     95 };
     96 
     97 unsigned long __cmp_umuls;
     98 PRBool verbose;
     99 int dumpServerChain = 0;
    100 int renegotiationsToDo = 0;
    101 int renegotiationsDone = 0;
    102 PRBool initializedServerSessionCache = PR_FALSE;
    103 
    104 static char *progName;
    105 static const char *requestFile;
    106 
    107 secuPWData pwdata = { PW_NONE, 0 };
    108 
    109 SSLNamedGroup *enabledGroups = NULL;
    110 unsigned int enabledGroupsCount = 0;
    111 const SSLSignatureScheme *enabledSigSchemes = NULL;
    112 unsigned int enabledSigSchemeCount = 0;
    113 SECItem psk = { siBuffer, NULL, 0 };
    114 SECItem pskLabel = { siBuffer, NULL, 0 };
    115 
    116 void
    117 printSecurityInfo(PRFileDesc *fd)
    118 {
    119    CERTCertificate *cert;
    120    const SECItemArray *csa;
    121    const SECItem *scts;
    122    SSL3Statistics *ssl3stats = SSL_GetStatistics();
    123    SECStatus result;
    124    SSLChannelInfo channel;
    125    SSLCipherSuiteInfo suite;
    126 
    127    result = SSL_GetChannelInfo(fd, &channel, sizeof channel);
    128    if (result == SECSuccess &&
    129        channel.length == sizeof channel &&
    130        channel.cipherSuite) {
    131        result = SSL_GetCipherSuiteInfo(channel.cipherSuite,
    132                                        &suite, sizeof suite);
    133        if (result == SECSuccess) {
    134            FPRINTF(stderr,
    135                    "tstclnt: SSL version %d.%d using %d-bit %s with %d-bit %s MAC%s\n",
    136                    channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
    137                    suite.effectiveKeyBits, suite.symCipherName,
    138                    suite.macBits, suite.macAlgorithmName,
    139                    channel.isFIPS ? " FIPS" : "");
    140            FPRINTF(stderr,
    141                    "tstclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n"
    142                    "         Key Exchange Group: %s\n"
    143                    "         Compression: %s, Extended Master Secret: %s\n"
    144                    "         Signature Scheme: %s\n",
    145                    channel.authKeyBits, suite.authAlgorithmName,
    146                    channel.keaKeyBits, suite.keaTypeName,
    147                    SECU_NamedGroupToGroupName(channel.keaGroup),
    148                    channel.compressionMethodName,
    149                    channel.extendedMasterSecretUsed ? "Yes" : "No",
    150                    SECU_SignatureSchemeName(channel.signatureScheme));
    151        }
    152    }
    153    cert = SSL_RevealCert(fd);
    154    if (cert) {
    155        char *ip = CERT_NameToAscii(&cert->issuer);
    156        char *sp = CERT_NameToAscii(&cert->subject);
    157        if (sp) {
    158            fprintf(stderr, "subject DN: %s\n", sp);
    159            PORT_Free(sp);
    160        }
    161        if (ip) {
    162            fprintf(stderr, "issuer  DN: %s\n", ip);
    163            PORT_Free(ip);
    164        }
    165        CERT_DestroyCertificate(cert);
    166        cert = NULL;
    167    }
    168    fprintf(stderr,
    169            "%ld cache hits; %ld cache misses, %ld cache not reusable\n"
    170            "%ld stateless resumes\n",
    171            ssl3stats->hsh_sid_cache_hits, ssl3stats->hsh_sid_cache_misses,
    172            ssl3stats->hsh_sid_cache_not_ok, ssl3stats->hsh_sid_stateless_resumes);
    173 
    174    csa = SSL_PeerStapledOCSPResponses(fd);
    175    if (csa) {
    176        fprintf(stderr, "Received %d Cert Status items (OCSP stapled data)\n",
    177                csa->len);
    178    }
    179    scts = SSL_PeerSignedCertTimestamps(fd);
    180    if (scts && scts->len) {
    181        fprintf(stderr, "Received a Signed Certificate Timestamp of length"
    182                        " %u\n",
    183                scts->len);
    184    }
    185    if (channel.peerDelegCred) {
    186        fprintf(stderr, "Received a Delegated Credential\n");
    187    }
    188 }
    189 
    190 static void
    191 PrintUsageHeader()
    192 {
    193    fprintf(stderr,
    194            "Usage:  %s -h host [-a 1st_hs_name ] [-a 2nd_hs_name ] [-p port]\n"
    195            "  [-D | -d certdir] [-C] [-b | -R root-module] \n"
    196            "  [-n nickname] [-Bafosvx] [-c ciphers] [-Y] [-Z] [-E]\n"
    197            "  [-V [min-version]:[max-version]] [-K] [-T] [-U]\n"
    198            "  [-r N] [-w passwd] [-W pwfile] [-q [-t seconds]]\n"
    199            "  [-I groups] [-J signatureschemes]\n"
    200            "  [-A requestfile] [-L totalconnections] [-P {client,server}]\n"
    201            "  [-N echConfigs] [-Q] [-z externalPsk]\n"
    202            "  [-i echGreaseSize]\n"
    203            "  [--enable-rfc8701-grease] [--enable-ch-extension-permutation]\n"
    204            "  [--zlib-certificate-compression] \n"
    205            "\n",
    206            progName);
    207 }
    208 
    209 static void
    210 PrintParameterUsage()
    211 {
    212    fprintf(stderr, "%-20s Send different SNI name. 1st_hs_name - at first\n"
    213                    "%-20s handshake, 2nd_hs_name - at second handshake.\n"
    214                    "%-20s Default is host from the -h argument.\n",
    215            "-a name",
    216            "", "");
    217    fprintf(stderr, "%-20s Hostname to connect with\n", "-h host");
    218    fprintf(stderr, "%-20s Port number for SSL server\n", "-p port");
    219    fprintf(stderr,
    220            "%-20s Directory with cert database (default is ~/.netscape)\n",
    221            "-d certdir");
    222    fprintf(stderr, "%-20s Run without a cert database\n", "-D");
    223    fprintf(stderr, "%-20s Load the default \"builtins\" root CA module\n", "-b");
    224    fprintf(stderr, "%-20s Load the given root CA module\n", "-R");
    225    fprintf(stderr, "%-20s Print certificate chain information\n", "-C");
    226    fprintf(stderr, "%-20s (use -C twice to print more certificate details)\n", "");
    227    fprintf(stderr, "%-20s (use -C three times to include PEM format certificate dumps)\n", "");
    228    fprintf(stderr, "%-20s Nickname of key and cert\n",
    229            "-n nickname");
    230    fprintf(stderr,
    231            "%-20s Restricts the set of enabled SSL/TLS protocols versions.\n"
    232            "%-20s All versions are enabled by default.\n"
    233            "%-20s Possible values for min/max: ssl3 tls1.0 tls1.1 tls1.2 tls1.3\n"
    234            "%-20s Example: \"-V ssl3:\" enables SSL 3 and newer.\n",
    235            "-V [min]:[max]", "", "", "");
    236    fprintf(stderr, "%-20s Send TLS_FALLBACK_SCSV\n", "-K");
    237    fprintf(stderr, "%-20s Prints only payload data. Skips HTTP header.\n", "-S");
    238    fprintf(stderr, "%-20s Client speaks first. \n", "-f");
    239    fprintf(stderr, "%-20s Use synchronous certificate selection & validation\n", "-O");
    240    fprintf(stderr, "%-20s Override bad server cert. Make it OK.\n", "-o");
    241    fprintf(stderr, "%-20s Disable SSL socket locking.\n", "-s");
    242    fprintf(stderr, "%-20s Verbose progress reporting.\n", "-v");
    243    fprintf(stderr, "%-20s Ping the server and then exit.\n", "-q");
    244    fprintf(stderr, "%-20s Timeout for server ping (default: no timeout).\n", "-t seconds");
    245    fprintf(stderr, "%-20s Renegotiate N times (resuming session if N>1).\n", "-r N");
    246    fprintf(stderr, "%-20s Enable the session ticket extension.\n", "-u");
    247    fprintf(stderr, "%-20s Enable false start.\n", "-g");
    248    fprintf(stderr, "%-20s Enable the cert_status extension (OCSP stapling).\n", "-T");
    249    fprintf(stderr, "%-20s Enable the signed_certificate_timestamp extension.\n", "-U");
    250    fprintf(stderr, "%-20s Enable the delegated credentials extension.\n", "-B");
    251    fprintf(stderr, "%-20s Require fresh revocation info from side channel.\n"
    252                    "%-20s -F once means: require for server cert only\n"
    253                    "%-20s -F twice means: require for intermediates, too\n"
    254                    "%-20s (Connect, handshake with server, disable dynamic download\n"
    255                    "%-20s  of OCSP/CRL, verify cert using CERT_PKIXVerifyCert.)\n"
    256                    "%-20s Exit code:\n"
    257                    "%-20s 0: have fresh and valid revocation data, status good\n"
    258                    "%-20s 1: cert failed to verify, prior to revocation checking\n"
    259                    "%-20s 2: missing, old or invalid revocation data\n"
    260                    "%-20s 3: have fresh and valid revocation data, status revoked\n",
    261            "-F", "", "", "", "", "", "", "", "", "");
    262    fprintf(stderr, "%-20s Test -F allows 0=any (default), 1=only OCSP, 2=only CRL\n", "-M");
    263    fprintf(stderr, "%-20s Restrict ciphers\n", "-c ciphers");
    264    fprintf(stderr, "%-20s Print cipher values allowed for parameter -c and exit\n", "-Y");
    265    fprintf(stderr, "%-20s Enforce using an IPv4 destination address\n", "-4");
    266    fprintf(stderr, "%-20s Enforce using an IPv6 destination address\n", "-6");
    267    fprintf(stderr, "%-20s (Options -4 and -6 cannot be combined.)\n", "");
    268    fprintf(stderr, "%-20s Enable the extended master secret extension [RFC7627]\n", "-G");
    269    fprintf(stderr, "%-20s Require the use of FFDHE supported groups [RFC7919]\n", "-H");
    270    fprintf(stderr, "%-20s Read from a file instead of stdin\n", "-A");
    271    fprintf(stderr, "%-20s Allow 0-RTT data (TLS 1.3 only)\n", "-Z");
    272    fprintf(stderr, "%-20s Disconnect and reconnect up to N times total\n", "-L");
    273    fprintf(stderr, "%-20s Comma separated list of enabled groups for TLS key exchange.\n"
    274                    "%-20s The following values are valid",
    275            "-I", "");
    276    char comma = ':';
    277    const char *groupName;
    278    int total = SECU_MAX_COL_LEN;
    279    for (size_t i = 0; (groupName = SECU_NamedGroupGetNextName(i)) != NULL; i++) {
    280        int len = strlen(groupName);
    281        /* 2 represents a comma and a space */
    282        if ((total + len + 2) > SECU_MAX_COL_LEN) {
    283            fprintf(stderr, "%c\n%-20s %s", comma, "", groupName);
    284            /* 21 represents 21 spaces */
    285            total = len + 21;
    286        } else {
    287            fprintf(stderr, "%c %s", comma, groupName);
    288            /* 2 represents a comma and a space */
    289            total += len + 2;
    290        }
    291        comma = ',';
    292    }
    293    fprintf(stderr, "\n");
    294    fprintf(stderr, "%-20s Comma separated list of signature schemes in preference order.\n"
    295                    "%-20s The following values are valid",
    296            "-J", "");
    297 
    298    comma = ':';
    299    const char *schemeName;
    300    total = SECU_MAX_COL_LEN;
    301    for (size_t i = 0; (schemeName = SECU_SignatureSchemeGetNextScheme(i)) != NULL; i++) {
    302        int len = strlen(schemeName);
    303        /* 2 represents a comma and a space */
    304        if ((total + len + 2) > SECU_MAX_COL_LEN) {
    305            fprintf(stderr, "%c\n%-20s %s", comma, "", schemeName);
    306            /* 21 represents 21 spaces */
    307            total = len + 21;
    308        } else {
    309            fprintf(stderr, "%c %s", comma, schemeName);
    310            /* 2 represents a comma and a space */
    311            total += len + 2;
    312        }
    313        comma = ',';
    314    }
    315    fprintf(stderr, "\n");
    316    fprintf(stderr, "%-20s Use DTLS\n", "-P {client, server}");
    317    fprintf(stderr, "%-20s Exit after handshake\n", "-Q");
    318    fprintf(stderr, "%-20s Use Encrypted Client Hello with the given Base64-encoded ECHConfigs\n", "-N");
    319    fprintf(stderr, "%-20s Enable Encrypted Client Hello GREASEing with the given padding size (0-255) \n", "-i");
    320    fprintf(stderr, "%-20s Enable post-handshake authentication\n"
    321                    "%-20s for TLS 1.3; need to specify -n\n",
    322            "-E", "");
    323    fprintf(stderr, "%-20s Export and print keying material after successful handshake.\n"
    324                    "%-20s The argument is a comma separated list of exporters in the form:\n"
    325                    "%-20s   LABEL[:OUTPUT-LENGTH[:CONTEXT]]\n"
    326                    "%-20s where LABEL and CONTEXT can be either a free-form string or\n"
    327                    "%-20s a hex string if it is preceded by \"0x\"; OUTPUT-LENGTH\n"
    328                    "%-20s is a decimal integer.\n",
    329            "-x", "", "", "", "", "");
    330    fprintf(stderr,
    331            "%-20s Configure a TLS 1.3 External PSK with the given hex string for a key\n"
    332            "%-20s To specify a label, use ':' as a delimiter. For example\n"
    333            "%-20s 0xAAAABBBBCCCCDDDD:mylabel. Otherwise, the default label of\n"
    334            "%-20s 'Client_identity' will be used.\n",
    335            "-z externalPsk", "", "", "");
    336    fprintf(stderr, "%-20s Enable middlebox compatibility mode (TLS 1.3 only)\n", "-e");
    337 }
    338 
    339 static void
    340 Usage()
    341 {
    342    PrintUsageHeader();
    343    PrintParameterUsage();
    344    exit(1);
    345 }
    346 
    347 static void
    348 PrintCipherUsage()
    349 {
    350    PrintUsageHeader();
    351    fprintf(stderr, "%-20s Letter(s) chosen from the following list\n",
    352            "-c ciphers");
    353    fprintf(stderr,
    354            "c    SSL3 RSA WITH RC4 128 MD5\n"
    355            "d    SSL3 RSA WITH 3DES EDE CBC SHA\n"
    356            "e    SSL3 RSA WITH DES CBC SHA\n"
    357            "i    SSL3 RSA WITH NULL MD5\n"
    358            "n    SSL3 RSA WITH RC4 128 SHA\n"
    359            "o    SSL3 DHE DSS WITH RC4 128 SHA\n"
    360            "p    SSL3 DHE RSA WITH 3DES EDE CBC SHA\n"
    361            "q    SSL3 DHE DSS WITH 3DES EDE CBC SHA\n"
    362            "r    SSL3 DHE RSA WITH DES CBC SHA\n"
    363            "s    SSL3 DHE DSS WITH DES CBC SHA\n"
    364            "t    SSL3 DHE DSS WITH AES 128 CBC SHA\n"
    365            "u    SSL3 DHE RSA WITH AES 128 CBC SHA\n"
    366            "v    SSL3 RSA WITH AES 128 CBC SHA\n"
    367            "w    SSL3 DHE DSS WITH AES 256 CBC SHA\n"
    368            "x    SSL3 DHE RSA WITH AES 256 CBC SHA\n"
    369            "y    SSL3 RSA WITH AES 256 CBC SHA\n"
    370            "z    SSL3 RSA WITH NULL SHA\n"
    371            "\n"
    372            ":WXYZ  Use cipher with hex code { 0xWX , 0xYZ } in TLS\n");
    373    exit(1);
    374 }
    375 
    376 void
    377 milliPause(PRUint32 milli)
    378 {
    379    PRIntervalTime ticks = PR_MillisecondsToInterval(milli);
    380    PR_Sleep(ticks);
    381 }
    382 
    383 void
    384 disableAllSSLCiphers()
    385 {
    386    const PRUint16 *cipherSuites = SSL_GetImplementedCiphers();
    387    int i = SSL_GetNumImplementedCiphers();
    388    SECStatus rv;
    389 
    390    /* disable all the SSL3 cipher suites */
    391    while (--i >= 0) {
    392        PRUint16 suite = cipherSuites[i];
    393        rv = SSL_CipherPrefSetDefault(suite, PR_FALSE);
    394        if (rv != SECSuccess) {
    395            PRErrorCode err = PR_GetError();
    396            fprintf(stderr,
    397                    "SSL_CipherPrefSet didn't like value 0x%04x (i = %d): %s\n",
    398                    suite, i, SECU_Strerror(err));
    399            exit(2);
    400        }
    401    }
    402 }
    403 
    404 typedef struct
    405 {
    406    PRBool shouldPause; /* PR_TRUE if we should use asynchronous peer cert
    407                         * authentication */
    408    PRBool isPaused;    /* PR_TRUE if libssl is waiting for us to validate the
    409                         * peer's certificate and restart the handshake. */
    410    void *dbHandle;     /* Certificate database handle to use while
    411                         * authenticating the peer's certificate. */
    412    PRBool testFreshStatusFromSideChannel;
    413    PRErrorCode sideChannelRevocationTestResultCode;
    414    PRBool requireDataForIntermediates;
    415    PRBool allowOCSPSideChannelData;
    416    PRBool allowCRLSideChannelData;
    417 } ServerCertAuth;
    418 
    419 /*
    420 * Callback is called when incoming certificate is not valid.
    421 * Returns SECSuccess to accept the cert anyway, SECFailure to reject.
    422 */
    423 static SECStatus
    424 ownBadCertHandler(void *arg, PRFileDesc *socket)
    425 {
    426    PRErrorCode err = PR_GetError();
    427    /* can log invalid cert here */
    428    fprintf(stderr, "Bad server certificate: %d, %s\n", err,
    429            SECU_Strerror(err));
    430    return SECSuccess; /* override, say it's OK. */
    431 }
    432 
    433 #define EXIT_CODE_SIDECHANNELTEST_GOOD 0
    434 #define EXIT_CODE_SIDECHANNELTEST_BADCERT 1
    435 #define EXIT_CODE_SIDECHANNELTEST_NODATA 2
    436 #define EXIT_CODE_SIDECHANNELTEST_REVOKED 3
    437 
    438 static void
    439 verifyFromSideChannel(CERTCertificate *cert, ServerCertAuth *sca)
    440 {
    441    PRUint64 revDoNotUse =
    442        CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD;
    443 
    444    PRUint64 revUseLocalOnlyAndSoftFail =
    445        CERT_REV_M_TEST_USING_THIS_METHOD |
    446        CERT_REV_M_FORBID_NETWORK_FETCHING |
    447        CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE |
    448        CERT_REV_M_IGNORE_MISSING_FRESH_INFO |
    449        CERT_REV_M_STOP_TESTING_ON_FRESH_INFO;
    450 
    451    PRUint64 revUseLocalOnlyAndHardFail =
    452        CERT_REV_M_TEST_USING_THIS_METHOD |
    453        CERT_REV_M_FORBID_NETWORK_FETCHING |
    454        CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE |
    455        CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO |
    456        CERT_REV_M_STOP_TESTING_ON_FRESH_INFO;
    457 
    458    PRUint64 methodFlagsDoNotUse[2];
    459    PRUint64 methodFlagsCheckSoftFail[2];
    460    PRUint64 methodFlagsCheckHardFail[2];
    461    CERTRevocationTests revTestsDoNotCheck;
    462    CERTRevocationTests revTestsOverallSoftFail;
    463    CERTRevocationTests revTestsOverallHardFail;
    464    CERTRevocationFlags rev;
    465    CERTValInParam cvin[2];
    466    CERTValOutParam cvout[1];
    467    SECStatus rv;
    468 
    469    methodFlagsDoNotUse[cert_revocation_method_crl] = revDoNotUse;
    470    methodFlagsDoNotUse[cert_revocation_method_ocsp] = revDoNotUse;
    471 
    472    methodFlagsCheckSoftFail[cert_revocation_method_crl] =
    473        sca->allowCRLSideChannelData ? revUseLocalOnlyAndSoftFail : revDoNotUse;
    474    methodFlagsCheckSoftFail[cert_revocation_method_ocsp] =
    475        sca->allowOCSPSideChannelData ? revUseLocalOnlyAndSoftFail : revDoNotUse;
    476 
    477    methodFlagsCheckHardFail[cert_revocation_method_crl] =
    478        sca->allowCRLSideChannelData ? revUseLocalOnlyAndHardFail : revDoNotUse;
    479    methodFlagsCheckHardFail[cert_revocation_method_ocsp] =
    480        sca->allowOCSPSideChannelData ? revUseLocalOnlyAndHardFail : revDoNotUse;
    481 
    482    revTestsDoNotCheck.cert_rev_flags_per_method = methodFlagsDoNotUse;
    483    revTestsDoNotCheck.number_of_defined_methods = 2;
    484    revTestsDoNotCheck.number_of_preferred_methods = 0;
    485    revTestsDoNotCheck.cert_rev_method_independent_flags =
    486        CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST |
    487        CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT;
    488 
    489    revTestsOverallSoftFail.cert_rev_flags_per_method = 0; /* must define later */
    490    revTestsOverallSoftFail.number_of_defined_methods = 2;
    491    revTestsOverallSoftFail.number_of_preferred_methods = 0;
    492    revTestsOverallSoftFail.cert_rev_method_independent_flags =
    493        CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST |
    494        CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT;
    495 
    496    revTestsOverallHardFail.cert_rev_flags_per_method = 0; /* must define later */
    497    revTestsOverallHardFail.number_of_defined_methods = 2;
    498    revTestsOverallHardFail.number_of_preferred_methods = 0;
    499    revTestsOverallHardFail.cert_rev_method_independent_flags =
    500        CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST |
    501        CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE;
    502 
    503    rev.chainTests = revTestsDoNotCheck;
    504    rev.leafTests = revTestsDoNotCheck;
    505 
    506    cvin[0].type = cert_pi_revocationFlags;
    507    cvin[0].value.pointer.revocation = &rev;
    508    cvin[1].type = cert_pi_end;
    509 
    510    cvout[0].type = cert_po_end;
    511 
    512    /* Strategy:
    513     *
    514     * Verify with revocation checking disabled.
    515     * On failure return 1.
    516     *
    517     * if result if "good", then continue testing.
    518     *
    519     * Verify with CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO.
    520     * If result is good, return 0.
    521     *
    522     * On failure continue testing, find out why it failed.
    523     *
    524     * Verify with CERT_REV_M_IGNORE_MISSING_FRESH_INFO
    525     *
    526     * If result is "good", then our previous test failed,
    527     * because we don't have fresh revocation info, return 2.
    528     *
    529     * If result is still bad, we do have revocation info,
    530     * and it says "revoked" or something equivalent, return 3.
    531     */
    532 
    533    /* revocation checking disabled */
    534    rv = CERT_PKIXVerifyCert(cert, certificateUsageSSLServer,
    535                             cvin, cvout, NULL);
    536    if (rv != SECSuccess) {
    537        sca->sideChannelRevocationTestResultCode =
    538            EXIT_CODE_SIDECHANNELTEST_BADCERT;
    539        return;
    540    }
    541 
    542    /* revocation checking, hard fail */
    543    if (sca->allowOCSPSideChannelData && sca->allowCRLSideChannelData) {
    544        /* any method is allowed. use soft fail on individual checks,
    545         * but use hard fail on the overall check
    546         */
    547        revTestsOverallHardFail.cert_rev_flags_per_method = methodFlagsCheckSoftFail;
    548    } else {
    549        /* only one method is allowed. use hard fail on the individual checks.
    550         * hard/soft fail is irrelevant on overall flags.
    551         */
    552        revTestsOverallHardFail.cert_rev_flags_per_method = methodFlagsCheckHardFail;
    553    }
    554    rev.leafTests = revTestsOverallHardFail;
    555    rev.chainTests =
    556        sca->requireDataForIntermediates ? revTestsOverallHardFail : revTestsDoNotCheck;
    557    rv = CERT_PKIXVerifyCert(cert, certificateUsageSSLServer,
    558                             cvin, cvout, NULL);
    559    if (rv == SECSuccess) {
    560        sca->sideChannelRevocationTestResultCode =
    561            EXIT_CODE_SIDECHANNELTEST_GOOD;
    562        return;
    563    }
    564 
    565    /* revocation checking, soft fail */
    566    revTestsOverallSoftFail.cert_rev_flags_per_method = methodFlagsCheckSoftFail;
    567    rev.leafTests = revTestsOverallSoftFail;
    568    rev.chainTests =
    569        sca->requireDataForIntermediates ? revTestsOverallSoftFail : revTestsDoNotCheck;
    570    rv = CERT_PKIXVerifyCert(cert, certificateUsageSSLServer,
    571                             cvin, cvout, NULL);
    572    if (rv == SECSuccess) {
    573        sca->sideChannelRevocationTestResultCode =
    574            EXIT_CODE_SIDECHANNELTEST_NODATA;
    575        return;
    576    }
    577 
    578    sca->sideChannelRevocationTestResultCode =
    579        EXIT_CODE_SIDECHANNELTEST_REVOKED;
    580 }
    581 
    582 static void
    583 dumpCertificatePEM(CERTCertificate *cert)
    584 {
    585    char *asciiDER = BTOA_DataToAscii(cert->derCert.data, cert->derCert.len);
    586    if (asciiDER) {
    587        fprintf(stderr, "%s\n%s\n%s\n", NS_CERT_HEADER, asciiDER, NS_CERT_TRAILER);
    588        PORT_Free(asciiDER);
    589    }
    590 }
    591 
    592 static void
    593 dumpServerCertificateChain(PRFileDesc *fd)
    594 {
    595    CERTCertList *peerCertChain = NULL;
    596    CERTCertListNode *node = NULL;
    597    CERTCertificate *peerCert = NULL;
    598    CERTCertificateList *foundChain = NULL;
    599    SECU_PPFunc dumpFunction = NULL;
    600    PRBool dumpCertPEM = PR_FALSE;
    601 
    602    if (!dumpServerChain) {
    603        return;
    604    } else if (dumpServerChain == 1) {
    605        dumpFunction = SECU_PrintCertificateBasicInfo;
    606    } else {
    607        dumpFunction = SECU_PrintCertificate;
    608        if (dumpServerChain > 2) {
    609            dumpCertPEM = PR_TRUE;
    610        }
    611    }
    612 
    613    SECU_EnableWrap(PR_FALSE);
    614 
    615    fprintf(stderr, "==== certificate(s) sent by server: ====\n");
    616    peerCertChain = SSL_PeerCertificateChain(fd);
    617    if (peerCertChain) {
    618        node = CERT_LIST_HEAD(peerCertChain);
    619        while (!CERT_LIST_END(node, peerCertChain)) {
    620            CERTCertificate *cert = node->cert;
    621            SECU_PrintSignedContent(stderr, &cert->derCert, "Certificate", 0,
    622                                    dumpFunction);
    623            if (dumpCertPEM) {
    624                dumpCertificatePEM(cert);
    625            }
    626            node = CERT_LIST_NEXT(node);
    627        }
    628    }
    629 
    630    if (peerCertChain) {
    631        peerCert = SSL_RevealCert(fd);
    632        if (peerCert) {
    633            foundChain = CERT_CertChainFromCert(peerCert, certificateUsageSSLServer,
    634                                                PR_TRUE);
    635        }
    636        if (foundChain) {
    637            unsigned int count = 0;
    638            fprintf(stderr, "==== locally found issuer certificate(s): ====\n");
    639            for (count = 0; count < (unsigned int)foundChain->len; count++) {
    640                CERTCertificate *c;
    641                PRBool wasSentByServer = PR_FALSE;
    642                c = CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), &foundChain->certs[count]);
    643 
    644                node = CERT_LIST_HEAD(peerCertChain);
    645                while (!CERT_LIST_END(node, peerCertChain)) {
    646                    CERTCertificate *cert = node->cert;
    647                    if (CERT_CompareCerts(cert, c)) {
    648                        wasSentByServer = PR_TRUE;
    649                        break;
    650                    }
    651                    node = CERT_LIST_NEXT(node);
    652                }
    653 
    654                if (!wasSentByServer) {
    655                    SECU_PrintSignedContent(stderr, &c->derCert, "Certificate", 0,
    656                                            dumpFunction);
    657                    if (dumpCertPEM) {
    658                        dumpCertificatePEM(c);
    659                    }
    660                }
    661                CERT_DestroyCertificate(c);
    662            }
    663            CERT_DestroyCertificateList(foundChain);
    664        }
    665        if (peerCert) {
    666            CERT_DestroyCertificate(peerCert);
    667        }
    668 
    669        CERT_DestroyCertList(peerCertChain);
    670        peerCertChain = NULL;
    671    }
    672 
    673    fprintf(stderr, "==== end of certificate chain information ====\n");
    674    fflush(stderr);
    675 }
    676 
    677 static SECStatus
    678 ownAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
    679                   PRBool isServer)
    680 {
    681    ServerCertAuth *serverCertAuth = (ServerCertAuth *)arg;
    682 
    683    if (dumpServerChain) {
    684        dumpServerCertificateChain(fd);
    685    }
    686 
    687    if (!serverCertAuth->shouldPause) {
    688        CERTCertificate *cert;
    689        unsigned int i;
    690        const SECItemArray *csa;
    691 
    692        if (!serverCertAuth->testFreshStatusFromSideChannel) {
    693            return SSL_AuthCertificate(serverCertAuth->dbHandle,
    694                                       fd, checkSig, isServer);
    695        }
    696 
    697        /* No verification attempt must have happened before now,
    698         * to ensure revocation data has been actively retrieved yet,
    699         * or our test will produce incorrect results.
    700         */
    701 
    702        cert = SSL_RevealCert(fd);
    703        if (!cert) {
    704            exit(254);
    705        }
    706 
    707        csa = SSL_PeerStapledOCSPResponses(fd);
    708        if (csa) {
    709            for (i = 0; i < csa->len; ++i) {
    710                PORT_SetError(0);
    711                if (CERT_CacheOCSPResponseFromSideChannel(
    712                        serverCertAuth->dbHandle, cert, PR_Now(),
    713                        &csa->items[i], arg) != SECSuccess) {
    714                    PORT_Assert(PR_GetError() != 0);
    715                }
    716            }
    717        }
    718 
    719        verifyFromSideChannel(cert, serverCertAuth);
    720        CERT_DestroyCertificate(cert);
    721        /* return success to ensure our caller will continue and we will
    722         * reach the code that handles
    723         * serverCertAuth->sideChannelRevocationTestResultCode
    724         */
    725        return SECSuccess;
    726    }
    727 
    728    FPRINTF(stderr, "%s: using asynchronous certificate validation\n",
    729            progName);
    730 
    731    PORT_Assert(!serverCertAuth->isPaused);
    732    serverCertAuth->isPaused = PR_TRUE;
    733    return SECWouldBlock;
    734 }
    735 
    736 struct clientCertAsyncParamsStr {
    737    void *arg;                        /* The nickname used for selection, not owned */
    738    struct CERTDistNamesStr *caNames; /* CA Names specified by Server, owned. */
    739 };
    740 
    741 /* tstclnt can only have a single handshake in progress at any instant. */
    742 PRBool clientCertAsyncSelect = PR_TRUE; /* Async by default */
    743 PRBool clientCertIsBlocked = PR_FALSE;  /* Whether we waiting to finish ClientAuth */
    744 struct clientCertAsyncParamsStr *clientCertParams = NULL;
    745 
    746 SECStatus
    747 own_CompleteClientAuthData(PRFileDesc *fd, struct clientCertAsyncParamsStr *args)
    748 {
    749    SECStatus rv;
    750    CERTCertificate *pRetCert = NULL;
    751    SECKEYPrivateKey *pRetKey = NULL;
    752    rv = NSS_GetClientAuthData(args->arg, fd, args->caNames, &pRetCert, &pRetKey);
    753    if (rv != SECSuccess) {
    754        fprintf(stderr, "Failed to load a suitable client certificate \n");
    755    }
    756    return SSL_ClientCertCallbackComplete(fd, rv, pRetKey, pRetCert);
    757 }
    758 
    759 SECStatus
    760 restartHandshakeAfterClientCertIfNeeded(PRFileDesc *fd)
    761 {
    762    if (!clientCertIsBlocked) {
    763        return SECFailure;
    764    }
    765    clientCertIsBlocked = PR_FALSE;
    766    own_CompleteClientAuthData(fd, clientCertParams);
    767    CERT_FreeDistNames(clientCertParams->caNames);
    768    PORT_Free(clientCertParams);
    769    clientCertParams = NULL;
    770    return SECSuccess;
    771 }
    772 
    773 SECStatus
    774 own_GetClientAuthData(void *arg,
    775                      PRFileDesc *socket,
    776                      struct CERTDistNamesStr *caNames,
    777                      struct CERTCertificateStr **pRetCert,
    778                      struct SECKEYPrivateKeyStr **pRetKey)
    779 {
    780    if (clientCertAsyncSelect) {
    781        PR_ASSERT(!clientCertIsBlocked);
    782        PR_ASSERT(!clientCertParams);
    783 
    784        clientCertIsBlocked = PR_TRUE;
    785        clientCertParams = PORT_Alloc(sizeof(struct clientCertAsyncParamsStr));
    786        if (!clientCertParams) {
    787            fprintf(stderr, "Unable to allocate buffer for client cert callback\n");
    788            exit(1);
    789        }
    790 
    791        clientCertParams->arg = arg;
    792        clientCertParams->caNames = caNames ? CERT_DupDistNames(caNames) : NULL;
    793        if (caNames && !clientCertParams->caNames) {
    794            fprintf(stderr, "Unable to allocate buffer for client cert callback\n");
    795            exit(1);
    796        }
    797        return SECWouldBlock;
    798    }
    799 
    800    if (verbose > 1) {
    801        SECStatus rv;
    802        fprintf(stderr, "Server requested Client Authentication\n");
    803        if (caNames && caNames->nnames > 0) {
    804            PLArenaPool *arena = caNames->arena;
    805            if (!arena)
    806                arena = PORT_NewArena(2048);
    807            if (arena) {
    808                int i;
    809                for (i = 0; i < caNames->nnames; ++i) {
    810                    char *nameString;
    811                    CERTName dn;
    812                    rv = SEC_QuickDERDecodeItem(arena,
    813                                                &dn,
    814                                                SEC_ASN1_GET(CERT_NameTemplate),
    815                                                caNames->names + i);
    816                    if (rv != SECSuccess)
    817                        continue;
    818                    nameString = CERT_NameToAscii(&dn);
    819                    if (!nameString)
    820                        continue;
    821                    fprintf(stderr, "CA[%d]: %s\n", i + 1, nameString);
    822                    PORT_Free(nameString);
    823                }
    824                if (!caNames->arena) {
    825                    PORT_FreeArena(arena, PR_FALSE);
    826                }
    827            }
    828        }
    829        rv = NSS_GetClientAuthData(arg, socket, caNames, pRetCert, pRetKey);
    830        if (rv == SECSuccess && *pRetCert) {
    831            char *nameString = CERT_NameToAscii(&((*pRetCert)->subject));
    832            if (nameString) {
    833                fprintf(stderr, "sent cert: %s\n", nameString);
    834                PORT_Free(nameString);
    835            }
    836        } else {
    837            fprintf(stderr, "send no cert\n");
    838        }
    839        return rv;
    840    }
    841    return NSS_GetClientAuthData(arg, socket, caNames, pRetCert, pRetKey);
    842 }
    843 
    844 #if defined(WIN32)
    845 void
    846 thread_main(void *arg)
    847 {
    848    PRFileDesc *ps = (PRFileDesc *)arg;
    849    PRFileDesc *std_in;
    850    int wc, rc;
    851    char buf[256];
    852 
    853    if (requestFile) {
    854        std_in = PR_Open(requestFile, PR_RDONLY, 0);
    855    } else {
    856        std_in = PR_GetSpecialFD(PR_StandardInput);
    857    }
    858 
    859 #ifdef WIN32
    860    if (!requestFile) {
    861        /* Put stdin into O_BINARY mode
    862        ** or else incoming \r\n's will become \n's.
    863        */
    864        int smrv = _setmode(_fileno(stdin), _O_BINARY);
    865        if (smrv == -1) {
    866            fprintf(stderr,
    867                    "%s: Cannot change stdin to binary mode. Use -i option instead.\n",
    868                    progName);
    869            /* plow ahead anyway */
    870        }
    871    }
    872 #endif
    873 
    874    do {
    875        rc = PR_Read(std_in, buf, sizeof buf);
    876        if (rc <= 0)
    877            break;
    878        wc = PR_Send(ps, buf, rc, 0, maxInterval);
    879    } while (wc == rc);
    880    PR_Close(ps);
    881    if (requestFile) {
    882        PR_Close(std_in);
    883    }
    884 }
    885 
    886 #endif
    887 
    888 static void
    889 printHostNameAndAddr(const char *host, const PRNetAddr *addr)
    890 {
    891    PRUint16 port = PR_NetAddrInetPort(addr);
    892    char addrBuf[80];
    893    PRStatus st = PR_NetAddrToString(addr, addrBuf, sizeof addrBuf);
    894 
    895    if (st == PR_SUCCESS) {
    896        port = PR_ntohs(port);
    897        FPRINTF(stderr, "%s: connecting to %s:%hu (address=%s)\n",
    898                progName, host, port, addrBuf);
    899    }
    900 }
    901 
    902 /*
    903 *  Prints output according to skipProtoHeader flag. If skipProtoHeader
    904 *  is not set, prints without any changes, otherwise looking
    905 *  for \n\r\n(empty line sequence: HTTP header separator) and
    906 *  prints everything after it.
    907 */
    908 static void
    909 separateReqHeader(const PRFileDesc *outFd, const char *buf, const int nb,
    910                  PRBool *wrStarted, int *ptrnMatched)
    911 {
    912 
    913    /* it is sufficient to look for only "\n\r\n". Hopping that
    914     * HTTP response format satisfies the standard */
    915    char *ptrnStr = "\n\r\n";
    916    char *resPtr;
    917 
    918    if (nb == 0) {
    919        return;
    920    }
    921 
    922    if (*ptrnMatched > 0) {
    923        /* Get here only if previous separateReqHeader call found
    924         * only a fragment of "\n\r\n" in previous buffer. */
    925        PORT_Assert(*ptrnMatched < 3);
    926 
    927        /* the size of fragment of "\n\r\n" what we want to find in this
    928         * buffer is equal to *ptrnMatched */
    929        if (*ptrnMatched <= nb) {
    930            /* move the pointer to the beginning of the fragment */
    931            int strSize = *ptrnMatched;
    932            char *tmpPtrn = ptrnStr + (3 - strSize);
    933            if (PL_strncmp(buf, tmpPtrn, strSize) == 0) {
    934                /* print the rest of the buffer(without the fragment) */
    935                PR_Write((void *)outFd, buf + strSize, nb - strSize);
    936                *wrStarted = PR_TRUE;
    937                return;
    938            }
    939        } else {
    940            /* we are here only when nb == 1 && *ptrnMatched == 2 */
    941            if (*buf == '\r') {
    942                *ptrnMatched = 1;
    943            } else {
    944                *ptrnMatched = 0;
    945            }
    946            return;
    947        }
    948    }
    949    resPtr = PL_strnstr(buf, ptrnStr, nb);
    950    if (resPtr != NULL) {
    951        /* if "\n\r\n" was found in the buffer, calculate offset
    952         * and print the rest of the buffer */
    953        int newBn = nb - (resPtr - buf + 3); /* 3 is the length of "\n\r\n" */
    954 
    955        PR_Write((void *)outFd, resPtr + 3, newBn);
    956        *wrStarted = PR_TRUE;
    957        return;
    958    } else {
    959        /* try to find a fragment of "\n\r\n" at the end of the buffer.
    960         * if found, set *ptrnMatched to the number of chars left to find
    961         * in the next buffer.*/
    962        int i;
    963        for (i = 1; i < 3; i++) {
    964            char *bufPrt;
    965            int strSize = 3 - i;
    966 
    967            if (strSize > nb) {
    968                continue;
    969            }
    970            bufPrt = (char *)(buf + nb - strSize);
    971 
    972            if (PL_strncmp(bufPrt, ptrnStr, strSize) == 0) {
    973                *ptrnMatched = i;
    974                return;
    975            }
    976        }
    977    }
    978 }
    979 
    980 #define SSOCK_FD 0
    981 #define STDIN_FD 1
    982 
    983 #define HEXCHAR_TO_INT(c, i)                   \
    984    if (((c) >= '0') && ((c) <= '9')) {        \
    985        i = (c) - '0';                         \
    986    } else if (((c) >= 'a') && ((c) <= 'f')) { \
    987        i = (c) - 'a' + 10;                    \
    988    } else if (((c) >= 'A') && ((c) <= 'F')) { \
    989        i = (c) - 'A' + 10;                    \
    990    } else {                                   \
    991        Usage();                               \
    992    }
    993 
    994 static SECStatus
    995 restartHandshakeAfterServerCertIfNeeded(PRFileDesc *fd,
    996                                        ServerCertAuth *serverCertAuth,
    997                                        PRBool override)
    998 {
    999    SECStatus rv;
   1000    PRErrorCode error = 0;
   1001 
   1002    if (!serverCertAuth->isPaused || clientCertIsBlocked)
   1003        return SECSuccess;
   1004 
   1005    FPRINTF(stderr, "%s: handshake was paused by auth certificate hook\n",
   1006            progName);
   1007 
   1008    serverCertAuth->isPaused = PR_FALSE;
   1009    rv = SSL_AuthCertificate(serverCertAuth->dbHandle, fd, PR_TRUE, PR_FALSE);
   1010    if (rv != SECSuccess) {
   1011        error = PR_GetError();
   1012        if (error == 0) {
   1013            PR_NOT_REACHED("SSL_AuthCertificate return SECFailure without "
   1014                           "setting error code.");
   1015            error = PR_INVALID_STATE_ERROR;
   1016        } else if (override) {
   1017            rv = ownBadCertHandler(NULL, fd);
   1018        }
   1019    }
   1020    if (rv == SECSuccess) {
   1021        error = 0;
   1022    }
   1023 
   1024    if (SSL_AuthCertificateComplete(fd, error) != SECSuccess) {
   1025        rv = SECFailure;
   1026    } else {
   1027        /* restore the original error code, which could be reset by
   1028         * SSL_AuthCertificateComplete */
   1029        PORT_SetError(error);
   1030    }
   1031 
   1032    return rv;
   1033 }
   1034 
   1035 char *host = NULL;
   1036 char *nickname = NULL;
   1037 char *cipherString = NULL;
   1038 int multiplier = 0;
   1039 SSLVersionRange enabledVersions;
   1040 int disableLocking = 0;
   1041 int enableSessionTickets = 0;
   1042 int enableFalseStart = 0;
   1043 int enableCertStatus = 0;
   1044 int enableSignedCertTimestamps = 0;
   1045 int forceFallbackSCSV = 0;
   1046 int enableExtendedMasterSecret = 0;
   1047 PRBool requireDHNamedGroups = 0;
   1048 PRBool middleboxCompatMode = 0;
   1049 PRSocketOptionData opt;
   1050 PRNetAddr addr;
   1051 PRBool allowIPv4 = PR_TRUE;
   1052 PRBool allowIPv6 = PR_TRUE;
   1053 PRBool pingServerFirst = PR_FALSE;
   1054 int pingTimeoutSeconds = -1;
   1055 PRBool clientSpeaksFirst = PR_FALSE;
   1056 PRBool skipProtoHeader = PR_FALSE;
   1057 ServerCertAuth serverCertAuth;
   1058 char *hs1SniHostName = NULL;
   1059 char *hs2SniHostName = NULL;
   1060 PRUint16 portno = 443;
   1061 int override = 0;
   1062 PRBool enableZeroRtt = PR_FALSE;
   1063 PRUint8 *zeroRttData;
   1064 unsigned int zeroRttLen = 0;
   1065 PRBool enableAltServerHello = PR_FALSE;
   1066 PRBool useDTLS = PR_FALSE;
   1067 PRBool actAsServer = PR_FALSE;
   1068 PRBool stopAfterHandshake = PR_FALSE;
   1069 PRBool requestToExit = PR_FALSE;
   1070 char *versionString = NULL;
   1071 PRBool handshakeComplete = PR_FALSE;
   1072 char *echConfigs = NULL;
   1073 PRUint16 echGreaseSize = 0;
   1074 PRBool enablePostHandshakeAuth = PR_FALSE;
   1075 PRBool enableDelegatedCredentials = PR_FALSE;
   1076 const secuExporter *enabledExporters = NULL;
   1077 unsigned int enabledExporterCount = 0;
   1078 PRBool enableRfc8701Grease = PR_FALSE;
   1079 PRBool enableCHExtensionPermuation = PR_FALSE;
   1080 PRBool zlibCertificateCompression = PR_FALSE;
   1081 
   1082 static int
   1083 writeBytesToServer(PRFileDesc *s, const PRUint8 *buf, int nb)
   1084 {
   1085    SECStatus rv;
   1086    const PRUint8 *bufp = buf;
   1087    PRPollDesc pollDesc;
   1088 
   1089    pollDesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
   1090    pollDesc.out_flags = 0;
   1091    pollDesc.fd = s;
   1092 
   1093    FPRINTF(stderr, "%s: Writing %d bytes to server\n",
   1094            progName, nb);
   1095    do {
   1096        PRInt32 cc = PR_Send(s, bufp, nb, 0, maxInterval);
   1097        if (cc < 0) {
   1098            PRErrorCode err = PR_GetError();
   1099            if (err != PR_WOULD_BLOCK_ERROR) {
   1100                SECU_PrintError(progName, "write to SSL socket failed");
   1101                return 254;
   1102            }
   1103            cc = 0;
   1104        }
   1105        FPRINTF(stderr, "%s: %d bytes written\n", progName, cc);
   1106        if (enableZeroRtt && !handshakeComplete) {
   1107            if (zeroRttLen + cc > ZERO_RTT_MAX) {
   1108                SECU_PrintError(progName, "too much early data to save");
   1109                return -1;
   1110            }
   1111            PORT_Memcpy(zeroRttData + zeroRttLen, bufp, cc);
   1112            zeroRttLen += cc;
   1113        }
   1114        bufp += cc;
   1115        nb -= cc;
   1116        if (nb <= 0)
   1117            break;
   1118 
   1119        rv = restartHandshakeAfterServerCertIfNeeded(s,
   1120                                                     &serverCertAuth, override);
   1121        if (rv != SECSuccess) {
   1122            SECU_PrintError(progName, "authentication of server cert failed");
   1123            return EXIT_CODE_HANDSHAKE_FAILED;
   1124        }
   1125 
   1126        rv = restartHandshakeAfterClientCertIfNeeded(s);
   1127        if (rv == SECSuccess) {
   1128            continue;
   1129        }
   1130 
   1131        pollDesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
   1132        pollDesc.out_flags = 0;
   1133        FPRINTF(stderr,
   1134                "%s: about to call PR_Poll on writable socket !\n",
   1135                progName);
   1136        cc = PR_Poll(&pollDesc, 1, PR_INTERVAL_NO_TIMEOUT);
   1137        if (cc < 0) {
   1138            SECU_PrintError(progName, "PR_Poll failed");
   1139            return -1;
   1140        }
   1141        FPRINTF(stderr,
   1142                "%s: PR_Poll returned with writable socket !\n",
   1143                progName);
   1144    } while (1);
   1145 
   1146    return 0;
   1147 }
   1148 
   1149 void
   1150 handshakeCallback(PRFileDesc *fd, void *client_data)
   1151 {
   1152    const char *secondHandshakeName = (char *)client_data;
   1153    if (secondHandshakeName) {
   1154        SSL_SetURL(fd, secondHandshakeName);
   1155    }
   1156    printSecurityInfo(fd);
   1157    if (renegotiationsDone < renegotiationsToDo) {
   1158        SSL_ReHandshake(fd, (renegotiationsToDo < 2));
   1159        ++renegotiationsDone;
   1160    }
   1161    if (zeroRttLen) {
   1162        /* This data was sent in 0-RTT. */
   1163        SSLChannelInfo info;
   1164        SECStatus rv;
   1165 
   1166        rv = SSL_GetChannelInfo(fd, &info, sizeof(info));
   1167        if (rv != SECSuccess)
   1168            return;
   1169 
   1170        if (!info.earlyDataAccepted) {
   1171            FPRINTF(stderr, "Early data rejected. Re-sending %d bytes\n",
   1172                    zeroRttLen);
   1173            writeBytesToServer(fd, zeroRttData, zeroRttLen);
   1174            zeroRttLen = 0;
   1175        }
   1176    }
   1177    if (stopAfterHandshake) {
   1178        requestToExit = PR_TRUE;
   1179    }
   1180    handshakeComplete = PR_TRUE;
   1181 
   1182    if (enabledExporters) {
   1183        SECStatus rv;
   1184 
   1185        rv = exportKeyingMaterials(fd, enabledExporters, enabledExporterCount);
   1186        if (rv != SECSuccess) {
   1187            PRErrorCode err = PR_GetError();
   1188            FPRINTF(stderr,
   1189                    "couldn't export keying material: %s\n",
   1190                    SECU_Strerror(err));
   1191        }
   1192    }
   1193 }
   1194 
   1195 static SECStatus
   1196 installServerCertificate(PRFileDesc *s, char *nick)
   1197 {
   1198    CERTCertificate *cert;
   1199    SECKEYPrivateKey *privKey = NULL;
   1200 
   1201    if (!nick) {
   1202        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1203        return SECFailure;
   1204    }
   1205 
   1206    cert = PK11_FindCertFromNickname(nick, &pwdata);
   1207    if (cert == NULL) {
   1208        return SECFailure;
   1209    }
   1210 
   1211    privKey = PK11_FindKeyByAnyCert(cert, &pwdata);
   1212    if (privKey == NULL) {
   1213        return SECFailure;
   1214    }
   1215    if (SSL_ConfigServerCert(s, cert, privKey, NULL, 0) != SECSuccess) {
   1216        return SECFailure;
   1217    }
   1218    SECKEY_DestroyPrivateKey(privKey);
   1219    CERT_DestroyCertificate(cert);
   1220 
   1221    return SECSuccess;
   1222 }
   1223 
   1224 static SECStatus
   1225 bindToClient(PRFileDesc *s)
   1226 {
   1227    PRStatus status;
   1228    status = PR_Bind(s, &addr);
   1229    if (status != PR_SUCCESS) {
   1230        return SECFailure;
   1231    }
   1232 
   1233    for (;;) {
   1234        /* Bind the remote address on first packet. This must happen
   1235         * before we SSL-ize the socket because we need to get the
   1236         * peer's address before SSLizing. Recvfrom gives us that
   1237         * while not consuming any data. */
   1238        unsigned char tmp;
   1239        PRNetAddr remote;
   1240        int nb;
   1241 
   1242        nb = PR_RecvFrom(s, &tmp, 1, PR_MSG_PEEK,
   1243                         &remote, PR_INTERVAL_NO_TIMEOUT);
   1244        if (nb != 1)
   1245            continue;
   1246 
   1247        status = PR_Connect(s, &remote, PR_INTERVAL_NO_TIMEOUT);
   1248        if (status != PR_SUCCESS) {
   1249            SECU_PrintError(progName, "server bind to remote end failed");
   1250            return SECFailure;
   1251        }
   1252        return SECSuccess;
   1253    }
   1254 
   1255    /* Unreachable. */
   1256 }
   1257 
   1258 static SECStatus
   1259 connectToServer(PRFileDesc *s, PRPollDesc *pollset)
   1260 {
   1261    PRStatus status;
   1262    PRInt32 filesReady;
   1263 
   1264    status = PR_Connect(s, &addr, PR_INTERVAL_NO_TIMEOUT);
   1265    if (status != PR_SUCCESS) {
   1266        if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
   1267            if (verbose)
   1268                SECU_PrintError(progName, "connect");
   1269            milliPause(50 * multiplier);
   1270            pollset[SSOCK_FD].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
   1271            pollset[SSOCK_FD].out_flags = 0;
   1272            pollset[SSOCK_FD].fd = s;
   1273            while (1) {
   1274                FPRINTF(stderr,
   1275                        "%s: about to call PR_Poll for connect completion!\n",
   1276                        progName);
   1277                filesReady = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT);
   1278                if (filesReady < 0) {
   1279                    SECU_PrintError(progName, "unable to connect (poll)");
   1280                    return SECFailure;
   1281                }
   1282                FPRINTF(stderr,
   1283                        "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
   1284                        progName, pollset[SSOCK_FD].out_flags);
   1285                if (filesReady == 0) { /* shouldn't happen! */
   1286                    SECU_PrintError(progName, "%s: PR_Poll returned zero!\n");
   1287                    return SECFailure;
   1288                }
   1289                status = PR_GetConnectStatus(pollset);
   1290                if (status == PR_SUCCESS) {
   1291                    break;
   1292                }
   1293                if (PR_GetError() != PR_IN_PROGRESS_ERROR) {
   1294                    SECU_PrintError(progName, "unable to connect (poll)");
   1295                    return SECFailure;
   1296                }
   1297                SECU_PrintError(progName, "poll");
   1298                milliPause(50 * multiplier);
   1299            }
   1300        } else {
   1301            SECU_PrintError(progName, "unable to connect");
   1302            return SECFailure;
   1303        }
   1304    }
   1305 
   1306    return SECSuccess;
   1307 }
   1308 
   1309 static SECStatus
   1310 importPsk(PRFileDesc *s)
   1311 {
   1312    SECU_PrintAsHex(stdout, &psk, "Using External PSK", 0);
   1313    PK11SlotInfo *slot = NULL;
   1314    PK11SymKey *symKey = NULL;
   1315    slot = PK11_GetInternalSlot();
   1316    if (!slot) {
   1317        SECU_PrintError(progName, "PK11_GetInternalSlot failed");
   1318        return SECFailure;
   1319    }
   1320    symKey = PK11_ImportSymKey(slot, CKM_HKDF_KEY_GEN, PK11_OriginUnwrap,
   1321                               CKA_DERIVE, &psk, NULL);
   1322    PK11_FreeSlot(slot);
   1323    if (!symKey) {
   1324        SECU_PrintError(progName, "PK11_ImportSymKey failed");
   1325        return SECFailure;
   1326    }
   1327 
   1328    SECStatus rv = SSL_AddExternalPsk(s, symKey, (const PRUint8 *)pskLabel.data,
   1329                                      pskLabel.len, ssl_hash_sha256);
   1330    PK11_FreeSymKey(symKey);
   1331    return rv;
   1332 }
   1333 
   1334 static SECStatus
   1335 printEchRetryConfigs(PRFileDesc *s)
   1336 {
   1337    if (PORT_GetError() == SSL_ERROR_ECH_RETRY_WITH_ECH) {
   1338        SECItem retries = { siBuffer, NULL, 0 };
   1339        SECStatus rv = SSL_GetEchRetryConfigs(s, &retries);
   1340        if (rv != SECSuccess) {
   1341            SECU_PrintError(progName, "SSL_GetEchRetryConfigs failed");
   1342            return SECFailure;
   1343        }
   1344        char *retriesBase64 = NSSBase64_EncodeItem(NULL, NULL, 0, &retries);
   1345        if (!retriesBase64) {
   1346            SECU_PrintError(progName, "NSSBase64_EncodeItem on retry_configs failed");
   1347            SECITEM_FreeItem(&retries, PR_FALSE);
   1348            return SECFailure;
   1349        }
   1350 
   1351        // Remove the newline characters that NSSBase64_EncodeItem unhelpfully inserts.
   1352        char *newline = strstr(retriesBase64, "\r\n");
   1353        if (newline) {
   1354            memmove(newline, newline + 2, strlen(newline + 2) + 1);
   1355        }
   1356        fprintf(stderr, "Received ECH retry_configs: \n%s\n", retriesBase64);
   1357        PORT_Free(retriesBase64);
   1358        SECITEM_FreeItem(&retries, PR_FALSE);
   1359    }
   1360    return SECSuccess;
   1361 }
   1362 
   1363 static SECStatus
   1364 zlibCertificateEncode(const SECItem *input, SECItem *output)
   1365 {
   1366    if (!input || !input->data || input->len == 0 || !output) {
   1367        PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
   1368        return SECFailure;
   1369    }
   1370 
   1371    unsigned long maxCompressedLen = compressBound(input->len);
   1372    SECITEM_AllocItem(NULL, output, maxCompressedLen);
   1373 
   1374    unsigned long outputLenUL = output->len;
   1375    int ret = compress(output->data, &outputLenUL, input->data, input->len);
   1376    output->len = outputLenUL;
   1377    if (ret != Z_OK) {
   1378        PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
   1379        return SECFailure;
   1380    }
   1381 
   1382    return SECSuccess;
   1383 }
   1384 
   1385 static SECStatus
   1386 zlibCertificateDecode(const SECItem *input,
   1387                      unsigned char *output, size_t outputLen,
   1388                      size_t *usedLen)
   1389 {
   1390    if (!input || !input->data || input->len == 0 || !output || outputLen == 0) {
   1391        PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
   1392        return SECFailure;
   1393    }
   1394 
   1395    unsigned long outputLenUL = outputLen;
   1396    int ret = uncompress(output, &outputLenUL, input->data, input->len);
   1397    *usedLen = outputLenUL;
   1398    if (ret != Z_OK) {
   1399        PR_SetError(SEC_ERROR_BAD_DATA, 0);
   1400        return SECFailure;
   1401    }
   1402 
   1403    return SECSuccess;
   1404 }
   1405 
   1406 static int
   1407 run()
   1408 {
   1409    int headerSeparatorPtrnId = 0;
   1410    int error = 0;
   1411    SECStatus rv;
   1412    PRStatus status;
   1413    PRInt32 filesReady;
   1414    PRFileDesc *s = NULL;
   1415    PRFileDesc *std_out;
   1416    PRPollDesc pollset[2] = { { 0 }, { 0 } };
   1417    PRBool wrStarted = PR_FALSE;
   1418    SSLCertificateCompressionAlgorithm zlibCompressionAlg = { 1, "zlib", zlibCertificateEncode, zlibCertificateDecode };
   1419 
   1420    handshakeComplete = PR_FALSE;
   1421 
   1422    /* Create socket */
   1423    if (useDTLS) {
   1424        s = PR_OpenUDPSocket(addr.raw.family);
   1425    } else {
   1426        s = PR_OpenTCPSocket(addr.raw.family);
   1427    }
   1428 
   1429    if (s == NULL) {
   1430        SECU_PrintError(progName, "error creating socket");
   1431        error = 1;
   1432        goto done;
   1433    }
   1434 
   1435    if (actAsServer) {
   1436        if (bindToClient(s) != SECSuccess) {
   1437            return 1;
   1438        }
   1439    }
   1440    opt.option = PR_SockOpt_Nonblocking;
   1441    opt.value.non_blocking = PR_TRUE; /* default */
   1442    if (serverCertAuth.testFreshStatusFromSideChannel) {
   1443        opt.value.non_blocking = PR_FALSE;
   1444    }
   1445    status = PR_SetSocketOption(s, &opt);
   1446    if (status != PR_SUCCESS) {
   1447        SECU_PrintError(progName, "error setting socket options");
   1448        error = 1;
   1449        goto done;
   1450    }
   1451 
   1452    if (useDTLS) {
   1453        s = DTLS_ImportFD(NULL, s);
   1454    } else {
   1455        s = SSL_ImportFD(NULL, s);
   1456    }
   1457    if (s == NULL) {
   1458        SECU_PrintError(progName, "error importing socket");
   1459        error = 1;
   1460        goto done;
   1461    }
   1462    SSL_SetPKCS11PinArg(s, &pwdata);
   1463 
   1464    rv = SSL_OptionSet(s, SSL_SECURITY, 1);
   1465    if (rv != SECSuccess) {
   1466        SECU_PrintError(progName, "error enabling socket");
   1467        error = 1;
   1468        goto done;
   1469    }
   1470 
   1471    rv = SSL_OptionSet(s, actAsServer ? SSL_HANDSHAKE_AS_SERVER : SSL_HANDSHAKE_AS_CLIENT, 1);
   1472    if (rv != SECSuccess) {
   1473        SECU_PrintError(progName, "error enabling client handshake");
   1474        error = 1;
   1475        goto done;
   1476    }
   1477 
   1478    /* all SSL3 cipher suites are enabled by default. */
   1479    if (cipherString) {
   1480        char *cstringSaved = cipherString;
   1481        int ndx;
   1482 
   1483        while (0 != (ndx = *cipherString++)) {
   1484            int cipher = 0;
   1485 
   1486            if (ndx == ':') {
   1487                int ctmp = 0;
   1488 
   1489                HEXCHAR_TO_INT(*cipherString, ctmp)
   1490                cipher |= (ctmp << 12);
   1491                cipherString++;
   1492                HEXCHAR_TO_INT(*cipherString, ctmp)
   1493                cipher |= (ctmp << 8);
   1494                cipherString++;
   1495                HEXCHAR_TO_INT(*cipherString, ctmp)
   1496                cipher |= (ctmp << 4);
   1497                cipherString++;
   1498                HEXCHAR_TO_INT(*cipherString, ctmp)
   1499                cipher |= ctmp;
   1500                cipherString++;
   1501            } else {
   1502                if (!isalpha((unsigned char)ndx))
   1503                    Usage();
   1504                ndx = tolower((unsigned char)ndx) - 'a';
   1505                if (ndx < PR_ARRAY_SIZE(ssl3CipherSuites)) {
   1506                    cipher = ssl3CipherSuites[ndx];
   1507                }
   1508            }
   1509            if (cipher > 0) {
   1510                rv = SSL_CipherPrefSet(s, cipher, SSL_ALLOWED);
   1511                if (rv != SECSuccess) {
   1512                    SECU_PrintError(progName, "SSL_CipherPrefSet()");
   1513                    error = 1;
   1514                    goto done;
   1515                }
   1516            } else {
   1517                Usage();
   1518            }
   1519        }
   1520        PORT_Free(cstringSaved);
   1521    }
   1522 
   1523    rv = SSL_VersionRangeSet(s, &enabledVersions);
   1524    if (rv != SECSuccess) {
   1525        SECU_PrintError(progName, "error setting SSL/TLS version range ");
   1526        error = 1;
   1527        goto done;
   1528    }
   1529 
   1530    /* disable SSL socket locking */
   1531    rv = SSL_OptionSet(s, SSL_NO_LOCKS, disableLocking);
   1532    if (rv != SECSuccess) {
   1533        SECU_PrintError(progName, "error disabling SSL socket locking");
   1534        error = 1;
   1535        goto done;
   1536    }
   1537 
   1538    /* enable Session Ticket extension. */
   1539    rv = SSL_OptionSet(s, SSL_ENABLE_SESSION_TICKETS, enableSessionTickets);
   1540    if (rv != SECSuccess) {
   1541        SECU_PrintError(progName, "error enabling Session Ticket extension");
   1542        error = 1;
   1543        goto done;
   1544    }
   1545 
   1546    /* enable false start. */
   1547    rv = SSL_OptionSet(s, SSL_ENABLE_FALSE_START, enableFalseStart);
   1548    if (rv != SECSuccess) {
   1549        SECU_PrintError(progName, "error enabling false start");
   1550        error = 1;
   1551        goto done;
   1552    }
   1553 
   1554    if (forceFallbackSCSV) {
   1555        rv = SSL_OptionSet(s, SSL_ENABLE_FALLBACK_SCSV, PR_TRUE);
   1556        if (rv != SECSuccess) {
   1557            SECU_PrintError(progName, "error forcing fallback scsv");
   1558            error = 1;
   1559            goto done;
   1560        }
   1561    }
   1562 
   1563    /* enable cert status (OCSP stapling). */
   1564    rv = SSL_OptionSet(s, SSL_ENABLE_OCSP_STAPLING, enableCertStatus);
   1565    if (rv != SECSuccess) {
   1566        SECU_PrintError(progName, "error enabling cert status (OCSP stapling)");
   1567        error = 1;
   1568        goto done;
   1569    }
   1570 
   1571    /* enable negotiation of delegated credentials (draft-ietf-tls-subcerts) */
   1572    rv = SSL_OptionSet(s, SSL_ENABLE_DELEGATED_CREDENTIALS, enableDelegatedCredentials);
   1573    if (rv != SECSuccess) {
   1574        SECU_PrintError(progName, "error enabling delegated credentials");
   1575        error = 1;
   1576        goto done;
   1577    }
   1578 
   1579    /* enable extended master secret mode */
   1580    if (enableExtendedMasterSecret) {
   1581        rv = SSL_OptionSet(s, SSL_ENABLE_EXTENDED_MASTER_SECRET, PR_TRUE);
   1582        if (rv != SECSuccess) {
   1583            SECU_PrintError(progName, "error enabling extended master secret");
   1584            error = 1;
   1585            goto done;
   1586        }
   1587    }
   1588 
   1589    /* enable 0-RTT (TLS 1.3 only) */
   1590    if (enableZeroRtt) {
   1591        rv = SSL_OptionSet(s, SSL_ENABLE_0RTT_DATA, PR_TRUE);
   1592        if (rv != SECSuccess) {
   1593            SECU_PrintError(progName, "error enabling 0-RTT");
   1594            error = 1;
   1595            goto done;
   1596        }
   1597    }
   1598 
   1599    /* Alternate ServerHello content type (TLS 1.3 only) */
   1600    if (enableAltServerHello) {
   1601        rv = SSL_UseAltServerHelloType(s, PR_TRUE);
   1602        if (rv != SECSuccess) {
   1603            SECU_PrintError(progName, "error enabling alternate ServerHello type");
   1604            error = 1;
   1605            goto done;
   1606        }
   1607    }
   1608 
   1609    /* Middlebox compatibility mode (TLS 1.3 only) */
   1610    if (middleboxCompatMode) {
   1611        rv = SSL_OptionSet(s, SSL_ENABLE_TLS13_COMPAT_MODE, PR_TRUE);
   1612        if (rv != SECSuccess) {
   1613            SECU_PrintError(progName, "error enabling middlebox compatibility mode");
   1614            error = 1;
   1615            goto done;
   1616        }
   1617    }
   1618 
   1619    /* require the use of fixed finite-field DH groups */
   1620    if (requireDHNamedGroups) {
   1621        rv = SSL_OptionSet(s, SSL_REQUIRE_DH_NAMED_GROUPS, PR_TRUE);
   1622        if (rv != SECSuccess) {
   1623            SECU_PrintError(progName, "error in requiring the use of fixed finite-field DH groups");
   1624            error = 1;
   1625            goto done;
   1626        }
   1627    }
   1628 
   1629    /* enable Signed Certificate Timestamps. */
   1630    rv = SSL_OptionSet(s, SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
   1631                       enableSignedCertTimestamps);
   1632    if (rv != SECSuccess) {
   1633        SECU_PrintError(progName, "error enabling signed cert timestamps");
   1634        error = 1;
   1635        goto done;
   1636    }
   1637 
   1638    if (enablePostHandshakeAuth) {
   1639        rv = SSL_OptionSet(s, SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE);
   1640        if (rv != SECSuccess) {
   1641            SECU_PrintError(progName, "error enabling post-handshake auth");
   1642            error = 1;
   1643            goto done;
   1644        }
   1645    }
   1646 
   1647    if (enableRfc8701Grease) {
   1648        rv = SSL_OptionSet(s, SSL_ENABLE_GREASE, PR_TRUE);
   1649        if (rv != SECSuccess) {
   1650            SECU_PrintError(progName, "error enabling grease");
   1651            error = 1;
   1652            goto done;
   1653        }
   1654    }
   1655 
   1656    if (enableCHExtensionPermuation) {
   1657        rv = SSL_OptionSet(s, SSL_ENABLE_CH_EXTENSION_PERMUTATION, PR_TRUE);
   1658        if (rv != SECSuccess) {
   1659            SECU_PrintError(progName, "error enabling ch extension permutation");
   1660            error = 1;
   1661            goto done;
   1662        }
   1663    }
   1664 
   1665    if (zlibCertificateCompression) {
   1666        rv = SSL_SetCertificateCompressionAlgorithm(s, zlibCompressionAlg);
   1667        if (rv != SECSuccess) {
   1668            SECU_PrintError(progName, "error setting zlib certificate compression algorithm");
   1669            error = 1;
   1670            goto done;
   1671        }
   1672    }
   1673 
   1674    if (enabledGroups) {
   1675        rv = SSL_NamedGroupConfig(s, enabledGroups, enabledGroupsCount);
   1676        if (rv < 0) {
   1677            SECU_PrintError(progName, "SSL_NamedGroupConfig failed");
   1678            error = 1;
   1679            goto done;
   1680        }
   1681    }
   1682 
   1683    if (enabledSigSchemes) {
   1684        rv = SSL_SignatureSchemePrefSet(s, enabledSigSchemes, enabledSigSchemeCount);
   1685        if (rv < 0) {
   1686            SECU_PrintError(progName, "SSL_SignatureSchemePrefSet failed");
   1687            error = 1;
   1688            goto done;
   1689        }
   1690    }
   1691 
   1692    if (echConfigs) {
   1693        SECItem echConfigsBin = { siBuffer, NULL, 0 };
   1694 
   1695        if (!NSSBase64_DecodeBuffer(NULL, &echConfigsBin, echConfigs,
   1696                                    strlen(echConfigs))) {
   1697            SECU_PrintError(progName, "ECHConfigs record is invalid base64");
   1698            error = 1;
   1699            goto done;
   1700        }
   1701 
   1702        rv = SSL_SetClientEchConfigs(s, echConfigsBin.data, echConfigsBin.len);
   1703        SECITEM_FreeItem(&echConfigsBin, PR_FALSE);
   1704        if (rv < 0) {
   1705            SECU_PrintError(progName, "SSL_SetClientEchConfigs failed");
   1706            error = 1;
   1707            goto done;
   1708        }
   1709    }
   1710 
   1711    if (echGreaseSize) {
   1712        rv = SSL_EnableTls13GreaseEch(s, PR_TRUE);
   1713        if (rv != SECSuccess) {
   1714            SECU_PrintError(progName, "SSL_EnableTls13GreaseEch failed");
   1715            error = 1;
   1716            goto done;
   1717        }
   1718        rv = SSL_SetTls13GreaseEchSize(s, echGreaseSize);
   1719        if (rv != SECSuccess) {
   1720            SECU_PrintError(progName, "SSL_SetTls13GreaseEchSize failed");
   1721            error = 1;
   1722            goto done;
   1723        }
   1724    }
   1725 
   1726    if (psk.data) {
   1727        rv = importPsk(s);
   1728        if (rv != SECSuccess) {
   1729            SECU_PrintError(progName, "importPsk failed");
   1730            error = 1;
   1731            goto done;
   1732        }
   1733    }
   1734 
   1735    serverCertAuth.dbHandle = CERT_GetDefaultCertDB();
   1736 
   1737    SSL_AuthCertificateHook(s, ownAuthCertificate, &serverCertAuth);
   1738    if (override) {
   1739        SSL_BadCertHook(s, ownBadCertHandler, NULL);
   1740    }
   1741    if (actAsServer) {
   1742        rv = installServerCertificate(s, nickname);
   1743        if (rv != SECSuccess) {
   1744            SECU_PrintError(progName, "error installing server cert");
   1745            return 1;
   1746        }
   1747        rv = SSL_ConfigServerSessionIDCache(1024, 0, 0, ".");
   1748        if (rv != SECSuccess) {
   1749            SECU_PrintError(progName, "error configuring session cache");
   1750            return 1;
   1751        }
   1752        initializedServerSessionCache = PR_TRUE;
   1753    } else {
   1754        SSL_GetClientAuthDataHook(s, own_GetClientAuthData, (void *)nickname);
   1755    }
   1756    SSL_HandshakeCallback(s, handshakeCallback, hs2SniHostName);
   1757    if (hs1SniHostName) {
   1758        SSL_SetURL(s, hs1SniHostName);
   1759    } else {
   1760        SSL_SetURL(s, host);
   1761    }
   1762 
   1763    if (actAsServer) {
   1764        rv = SSL_ResetHandshake(s, PR_TRUE /* server */);
   1765        if (rv != SECSuccess) {
   1766            return 1;
   1767        }
   1768    } else {
   1769        /* Try to connect to the server */
   1770        rv = connectToServer(s, pollset);
   1771        if (rv != SECSuccess) {
   1772            error = 1;
   1773            goto done;
   1774        }
   1775    }
   1776 
   1777    pollset[SSOCK_FD].fd = s;
   1778    pollset[SSOCK_FD].in_flags = PR_POLL_EXCEPT;
   1779    if (!actAsServer)
   1780        pollset[SSOCK_FD].in_flags |= (clientSpeaksFirst ? 0 : PR_POLL_READ);
   1781    else
   1782        pollset[SSOCK_FD].in_flags |= PR_POLL_READ;
   1783    if (requestFile) {
   1784        pollset[STDIN_FD].fd = PR_Open(requestFile, PR_RDONLY, 0);
   1785        if (!pollset[STDIN_FD].fd) {
   1786            fprintf(stderr, "%s: unable to open input file: %s\n",
   1787                    progName, requestFile);
   1788            error = 1;
   1789            goto done;
   1790        }
   1791    } else {
   1792        pollset[STDIN_FD].fd = PR_GetSpecialFD(PR_StandardInput);
   1793    }
   1794    pollset[STDIN_FD].in_flags = PR_POLL_READ;
   1795    std_out = PR_GetSpecialFD(PR_StandardOutput);
   1796 
   1797 #if defined(WIN32)
   1798    /* PR_Poll cannot be used with stdin on Windows or OS/2.  (sigh).
   1799    ** But use of PR_Poll and non-blocking sockets is a major feature
   1800    ** of this program.  So, we simulate a pollable stdin with a
   1801    ** TCP socket pair and a  thread that reads stdin and writes to
   1802    ** that socket pair.
   1803    */
   1804    {
   1805        PRFileDesc *fds[2];
   1806        PRThread *thread;
   1807 
   1808        int nspr_rv = PR_NewTCPSocketPair(fds);
   1809        if (nspr_rv != PR_SUCCESS) {
   1810            SECU_PrintError(progName, "PR_NewTCPSocketPair failed");
   1811            error = 1;
   1812            goto done;
   1813        }
   1814        pollset[STDIN_FD].fd = fds[1];
   1815 
   1816        thread = PR_CreateThread(PR_USER_THREAD, thread_main, fds[0],
   1817                                 PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
   1818                                 PR_UNJOINABLE_THREAD, 0);
   1819        if (!thread) {
   1820            SECU_PrintError(progName, "PR_CreateThread failed");
   1821            error = 1;
   1822            goto done;
   1823        }
   1824    }
   1825 #endif
   1826 
   1827    if (serverCertAuth.testFreshStatusFromSideChannel) {
   1828        SSL_ForceHandshake(s);
   1829        error = serverCertAuth.sideChannelRevocationTestResultCode;
   1830        goto done;
   1831    }
   1832 
   1833    /*
   1834    ** Select on stdin and on the socket. Write data from stdin to
   1835    ** socket, read data from socket and write to stdout.
   1836    */
   1837    requestToExit = PR_FALSE;
   1838    FPRINTF(stderr, "%s: ready...\n", progName);
   1839    while (!requestToExit &&
   1840           (pollset[SSOCK_FD].in_flags || pollset[STDIN_FD].in_flags)) {
   1841        PRUint8 buf[4000]; /* buffer for stdin */
   1842        int nb;            /* num bytes read from stdin. */
   1843 
   1844        rv = restartHandshakeAfterServerCertIfNeeded(s, &serverCertAuth,
   1845                                                     override);
   1846        if (rv != SECSuccess) {
   1847            error = EXIT_CODE_HANDSHAKE_FAILED;
   1848            SECU_PrintError(progName, "authentication of server cert failed");
   1849            goto done;
   1850        }
   1851 
   1852        rv = restartHandshakeAfterClientCertIfNeeded(s);
   1853        if (rv == SECSuccess) {
   1854            continue;
   1855        }
   1856 
   1857        pollset[SSOCK_FD].out_flags = 0;
   1858        pollset[STDIN_FD].out_flags = 0;
   1859 
   1860        FPRINTF(stderr, "%s: about to call PR_Poll !\n", progName);
   1861        filesReady = PR_Poll(pollset, PR_ARRAY_SIZE(pollset),
   1862                             PR_INTERVAL_NO_TIMEOUT);
   1863        if (filesReady < 0) {
   1864            SECU_PrintError(progName, "select failed");
   1865            error = 1;
   1866            goto done;
   1867        }
   1868        if (filesReady == 0) { /* shouldn't happen! */
   1869            FPRINTF(stderr, "%s: PR_Poll returned zero!\n", progName);
   1870            error = 1;
   1871            goto done;
   1872        }
   1873        FPRINTF(stderr, "%s: PR_Poll returned!\n", progName);
   1874        if (pollset[STDIN_FD].in_flags) {
   1875            FPRINTF(stderr,
   1876                    "%s: PR_Poll returned 0x%02x for stdin out_flags.\n",
   1877                    progName, pollset[STDIN_FD].out_flags);
   1878        }
   1879        if (pollset[SSOCK_FD].in_flags) {
   1880            FPRINTF(stderr,
   1881                    "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
   1882                    progName, pollset[SSOCK_FD].out_flags);
   1883        }
   1884        if (pollset[STDIN_FD].out_flags & PR_POLL_READ) {
   1885            /* Read from stdin and write to socket */
   1886            nb = PR_Read(pollset[STDIN_FD].fd, buf, sizeof(buf));
   1887            FPRINTF(stderr, "%s: stdin read %d bytes\n", progName, nb);
   1888            if (nb < 0) {
   1889                if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
   1890                    SECU_PrintError(progName, "read from stdin failed");
   1891                    error = 1;
   1892                    break;
   1893                }
   1894            } else if (nb == 0) {
   1895                /* EOF on stdin, stop polling stdin for read. */
   1896                pollset[STDIN_FD].in_flags = 0;
   1897                if (actAsServer)
   1898                    requestToExit = PR_TRUE;
   1899            } else {
   1900                error = writeBytesToServer(s, buf, nb);
   1901                if (error) {
   1902                    if (echConfigs) {
   1903                        (void)printEchRetryConfigs(s);
   1904                    }
   1905                    goto done;
   1906                }
   1907                pollset[SSOCK_FD].in_flags = PR_POLL_READ;
   1908            }
   1909        }
   1910 
   1911        if (pollset[SSOCK_FD].in_flags) {
   1912            FPRINTF(stderr,
   1913                    "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
   1914                    progName, pollset[SSOCK_FD].out_flags);
   1915        }
   1916 #ifdef PR_POLL_HUP
   1917 #define POLL_RECV_FLAGS (PR_POLL_READ | PR_POLL_ERR | PR_POLL_HUP)
   1918 #else
   1919 #define POLL_RECV_FLAGS (PR_POLL_READ | PR_POLL_ERR)
   1920 #endif
   1921        if (pollset[SSOCK_FD].out_flags & POLL_RECV_FLAGS) {
   1922            /* Read from socket and write to stdout */
   1923            nb = PR_Recv(pollset[SSOCK_FD].fd, buf, sizeof buf, 0, maxInterval);
   1924            FPRINTF(stderr, "%s: Read from server %d bytes\n", progName, nb);
   1925            if (nb < 0) {
   1926                if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
   1927                    SECU_PrintError(progName, "read from socket failed");
   1928                    error = 1;
   1929                    goto done;
   1930                }
   1931            } else if (nb == 0) {
   1932                /* EOF from socket... stop polling socket for read */
   1933                pollset[SSOCK_FD].in_flags = 0;
   1934            } else {
   1935                if (skipProtoHeader != PR_TRUE || wrStarted == PR_TRUE) {
   1936                    PR_Write(std_out, buf, nb);
   1937                } else {
   1938                    separateReqHeader(std_out, (char *)buf, nb, &wrStarted,
   1939                                      &headerSeparatorPtrnId);
   1940                }
   1941                if (verbose)
   1942                    fputs("\n\n", stderr);
   1943            }
   1944        }
   1945        milliPause(50 * multiplier);
   1946    }
   1947 
   1948 done:
   1949    if (s) {
   1950        PR_Close(s);
   1951    }
   1952    if (requestFile && pollset[STDIN_FD].fd) {
   1953        PR_Close(pollset[STDIN_FD].fd);
   1954    }
   1955    return error;
   1956 }
   1957 
   1958 const char *cmdLineOptions = "46A:BCDEFGHI:J:KL:M:N:OP:QR:STUV:W:X:YZa:bc:d:efgh:i:m:n:op:qr:st:uvw:x:z:";
   1959 const PLLongOpt cmdLineLongOpts[] = {
   1960    { .longOptName = "enable-rfc8701-grease", .longOption = 0, .valueRequired = PR_FALSE },
   1961    { .longOptName = "enable-ch-extension-permutation", .longOption = 1, .valueRequired = PR_FALSE },
   1962    { .longOptName = "zlib-certificate-compression", .longOption = 2, .valueRequired = PR_FALSE },
   1963    { .longOptName = NULL },
   1964 };
   1965 
   1966 int
   1967 main(int argc, char **argv)
   1968 {
   1969    PLOptState *optstate;
   1970    PLOptStatus optstatus;
   1971    PRStatus status;
   1972    PRStatus prStatus;
   1973    int error = 0;
   1974    char *tmp;
   1975    SECStatus rv;
   1976    char *certDir = NULL;
   1977    PRBool openDB = PR_TRUE;
   1978    PRBool loadDefaultRootCAs = PR_FALSE;
   1979    char *rootModule = NULL;
   1980    int numConnections = 1;
   1981    PRFileDesc *s = NULL;
   1982 
   1983    serverCertAuth.shouldPause = PR_TRUE;
   1984    serverCertAuth.isPaused = PR_FALSE;
   1985    serverCertAuth.dbHandle = NULL;
   1986    serverCertAuth.testFreshStatusFromSideChannel = PR_FALSE;
   1987    serverCertAuth.sideChannelRevocationTestResultCode = EXIT_CODE_HANDSHAKE_FAILED;
   1988    serverCertAuth.requireDataForIntermediates = PR_FALSE;
   1989    serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
   1990    serverCertAuth.allowCRLSideChannelData = PR_TRUE;
   1991 
   1992    progName = strrchr(argv[0], '/');
   1993    if (!progName)
   1994        progName = strrchr(argv[0], '\\');
   1995    progName = progName ? progName + 1 : argv[0];
   1996 
   1997    tmp = PR_GetEnvSecure("NSS_DEBUG_TIMEOUT");
   1998    if (tmp && tmp[0]) {
   1999        int sec = PORT_Atoi(tmp);
   2000        if (sec > 0) {
   2001            maxInterval = PR_SecondsToInterval(sec);
   2002        }
   2003    }
   2004 
   2005    optstate = PL_CreateLongOptState(argc, argv, cmdLineOptions, cmdLineLongOpts);
   2006    while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
   2007        switch (optstate->longOption) {
   2008            case '?':
   2009            default:
   2010                Usage();
   2011                break;
   2012 
   2013            case 0:
   2014                enableRfc8701Grease = PR_TRUE;
   2015                break;
   2016 
   2017            case 1:
   2018                enableCHExtensionPermuation = PR_TRUE;
   2019                break;
   2020 
   2021            case 2:
   2022                zlibCertificateCompression = PR_TRUE;
   2023                break;
   2024 
   2025            case '4':
   2026                allowIPv6 = PR_FALSE;
   2027                if (!allowIPv4)
   2028                    Usage();
   2029                break;
   2030            case '6':
   2031                allowIPv4 = PR_FALSE;
   2032                if (!allowIPv6)
   2033                    Usage();
   2034                break;
   2035 
   2036            case 'A':
   2037                requestFile = PORT_Strdup(optstate->value);
   2038                break;
   2039 
   2040            case 'B':
   2041                enableDelegatedCredentials = PR_TRUE;
   2042                break;
   2043 
   2044            case 'C':
   2045                ++dumpServerChain;
   2046                break;
   2047 
   2048            case 'D':
   2049                openDB = PR_FALSE;
   2050                break;
   2051 
   2052            case 'E':
   2053                enablePostHandshakeAuth = PR_TRUE;
   2054                break;
   2055 
   2056            case 'F':
   2057                if (serverCertAuth.testFreshStatusFromSideChannel) {
   2058                    /* parameter given twice or more */
   2059                    serverCertAuth.requireDataForIntermediates = PR_TRUE;
   2060                }
   2061                serverCertAuth.testFreshStatusFromSideChannel = PR_TRUE;
   2062                break;
   2063 
   2064            case 'G':
   2065                enableExtendedMasterSecret = PR_TRUE;
   2066                break;
   2067 
   2068            case 'H':
   2069                requireDHNamedGroups = PR_TRUE;
   2070                break;
   2071 
   2072            case 'O':
   2073                clientCertAsyncSelect = PR_FALSE;
   2074                serverCertAuth.shouldPause = PR_FALSE;
   2075                break;
   2076 
   2077            case 'K':
   2078                forceFallbackSCSV = PR_TRUE;
   2079                break;
   2080 
   2081            case 'L':
   2082                numConnections = atoi(optstate->value);
   2083                break;
   2084 
   2085            case 'M':
   2086                switch (atoi(optstate->value)) {
   2087                    case 1:
   2088                        serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
   2089                        serverCertAuth.allowCRLSideChannelData = PR_FALSE;
   2090                        break;
   2091                    case 2:
   2092                        serverCertAuth.allowOCSPSideChannelData = PR_FALSE;
   2093                        serverCertAuth.allowCRLSideChannelData = PR_TRUE;
   2094                        break;
   2095                    case 0:
   2096                    default:
   2097                        serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
   2098                        serverCertAuth.allowCRLSideChannelData = PR_TRUE;
   2099                        break;
   2100                };
   2101                break;
   2102 
   2103            case 'N':
   2104                echConfigs = PORT_Strdup(optstate->value);
   2105                break;
   2106 
   2107            case 'i':
   2108                echGreaseSize = PORT_Atoi(optstate->value);
   2109                if (!echGreaseSize || echGreaseSize > 255) {
   2110                    fprintf(stderr, "ECH Grease size must be within 1..255 (inclusive).\n");
   2111                    exit(-1);
   2112                }
   2113                break;
   2114 
   2115            case 'P':
   2116                useDTLS = PR_TRUE;
   2117                if (!strcmp(optstate->value, "server")) {
   2118                    actAsServer = 1;
   2119                } else {
   2120                    if (strcmp(optstate->value, "client")) {
   2121                        Usage();
   2122                    }
   2123                }
   2124                break;
   2125 
   2126            case 'Q':
   2127                stopAfterHandshake = PR_TRUE;
   2128                break;
   2129 
   2130            case 'R':
   2131                rootModule = PORT_Strdup(optstate->value);
   2132                break;
   2133 
   2134            case 'S':
   2135                skipProtoHeader = PR_TRUE;
   2136                break;
   2137 
   2138            case 'T':
   2139                enableCertStatus = 1;
   2140                break;
   2141 
   2142            case 'U':
   2143                enableSignedCertTimestamps = 1;
   2144                break;
   2145 
   2146            case 'V':
   2147                versionString = PORT_Strdup(optstate->value);
   2148                break;
   2149 
   2150            case 'X':
   2151                if (!strcmp(optstate->value, "alt-server-hello")) {
   2152                    enableAltServerHello = PR_TRUE;
   2153                } else {
   2154                    Usage();
   2155                }
   2156                break;
   2157            case 'Y':
   2158                PrintCipherUsage();
   2159                exit(0);
   2160                break;
   2161 
   2162            case 'Z':
   2163                enableZeroRtt = PR_TRUE;
   2164                zeroRttData = PORT_ZAlloc(ZERO_RTT_MAX);
   2165                if (!zeroRttData) {
   2166                    fprintf(stderr, "Unable to allocate buffer for 0-RTT\n");
   2167                    exit(1);
   2168                }
   2169                break;
   2170 
   2171            case 'a':
   2172                if (!hs1SniHostName) {
   2173                    hs1SniHostName = PORT_Strdup(optstate->value);
   2174                } else if (!hs2SniHostName) {
   2175                    hs2SniHostName = PORT_Strdup(optstate->value);
   2176                } else {
   2177                    Usage();
   2178                }
   2179                break;
   2180 
   2181            case 'b':
   2182                loadDefaultRootCAs = PR_TRUE;
   2183                break;
   2184 
   2185            case 'c':
   2186                cipherString = PORT_Strdup(optstate->value);
   2187                break;
   2188 
   2189            case 'g':
   2190                enableFalseStart = 1;
   2191                break;
   2192 
   2193            case 'd':
   2194                certDir = PORT_Strdup(optstate->value);
   2195                break;
   2196 
   2197            case 'e':
   2198                middleboxCompatMode = PR_TRUE;
   2199                break;
   2200 
   2201            case 'f':
   2202                clientSpeaksFirst = PR_TRUE;
   2203                break;
   2204 
   2205            case 'h':
   2206                host = PORT_Strdup(optstate->value);
   2207                break;
   2208 
   2209            case 'm':
   2210                multiplier = atoi(optstate->value);
   2211                if (multiplier < 0)
   2212                    multiplier = 0;
   2213                break;
   2214 
   2215            case 'n':
   2216                nickname = PORT_Strdup(optstate->value);
   2217                break;
   2218 
   2219            case 'o':
   2220                override = 1;
   2221                break;
   2222 
   2223            case 'p':
   2224                portno = (PRUint16)atoi(optstate->value);
   2225                break;
   2226 
   2227            case 'q':
   2228                pingServerFirst = PR_TRUE;
   2229                break;
   2230 
   2231            case 's':
   2232                disableLocking = 1;
   2233                break;
   2234 
   2235            case 't':
   2236                pingTimeoutSeconds = atoi(optstate->value);
   2237                break;
   2238 
   2239            case 'u':
   2240                enableSessionTickets = PR_TRUE;
   2241                break;
   2242 
   2243            case 'v':
   2244                verbose++;
   2245                break;
   2246 
   2247            case 'r':
   2248                renegotiationsToDo = atoi(optstate->value);
   2249                break;
   2250 
   2251            case 'w':
   2252                pwdata.source = PW_PLAINTEXT;
   2253                pwdata.data = PORT_Strdup(optstate->value);
   2254                break;
   2255 
   2256            case 'W':
   2257                pwdata.source = PW_FROMFILE;
   2258                pwdata.data = PORT_Strdup(optstate->value);
   2259                break;
   2260 
   2261            case 'I':
   2262                rv = parseGroupList(optstate->value, &enabledGroups, &enabledGroupsCount);
   2263                if (rv != SECSuccess) {
   2264                    PL_DestroyOptState(optstate);
   2265                    fprintf(stderr, "Bad group specified.\n");
   2266                    Usage();
   2267                }
   2268                break;
   2269 
   2270            case 'J':
   2271                rv = parseSigSchemeList(optstate->value, &enabledSigSchemes, &enabledSigSchemeCount);
   2272                if (rv != SECSuccess) {
   2273                    PL_DestroyOptState(optstate);
   2274                    fprintf(stderr, "Bad signature scheme specified.\n");
   2275                    Usage();
   2276                }
   2277                break;
   2278 
   2279            case 'x':
   2280                rv = parseExporters(optstate->value,
   2281                                    &enabledExporters,
   2282                                    &enabledExporterCount);
   2283                if (rv != SECSuccess) {
   2284                    PL_DestroyOptState(optstate);
   2285                    fprintf(stderr, "Bad exporter specified.\n");
   2286                    Usage();
   2287                }
   2288                break;
   2289 
   2290            case 'z':
   2291                rv = readPSK(optstate->value, &psk, &pskLabel);
   2292                if (rv != SECSuccess) {
   2293                    PL_DestroyOptState(optstate);
   2294                    fprintf(stderr, "Bad PSK specified.\n");
   2295                    Usage();
   2296                }
   2297                break;
   2298        }
   2299    }
   2300    PL_DestroyOptState(optstate);
   2301 
   2302    SSL_VersionRangeGetSupported(useDTLS ? ssl_variant_datagram : ssl_variant_stream, &enabledVersions);
   2303 
   2304    if (versionString) {
   2305        if (SECU_ParseSSLVersionRangeString(versionString,
   2306                                            enabledVersions, &enabledVersions) !=
   2307            SECSuccess) {
   2308            fprintf(stderr, "Bad version specified.\n");
   2309            Usage();
   2310        }
   2311        PORT_Free(versionString);
   2312    }
   2313 
   2314    if (optstatus == PL_OPT_BAD) {
   2315        Usage();
   2316    }
   2317 
   2318    if (!host || !portno) {
   2319        fprintf(stderr, "%s: parameters -h and -p are mandatory\n", progName);
   2320        Usage();
   2321    }
   2322 
   2323    if (serverCertAuth.testFreshStatusFromSideChannel &&
   2324        serverCertAuth.shouldPause) {
   2325        fprintf(stderr, "%s: -F requires the use of -O\n", progName);
   2326        exit(1);
   2327    }
   2328 
   2329    if (certDir && !openDB) {
   2330        fprintf(stderr, "%s: Cannot combine parameters -D and -d\n", progName);
   2331        exit(1);
   2332    }
   2333 
   2334    if (rootModule && loadDefaultRootCAs) {
   2335        fprintf(stderr, "%s: Cannot combine parameters -b and -R\n", progName);
   2336        exit(1);
   2337    }
   2338 
   2339    if (enablePostHandshakeAuth && !nickname) {
   2340        fprintf(stderr, "%s: -E requires the use of -n\n", progName);
   2341        exit(1);
   2342    }
   2343 
   2344    PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
   2345 
   2346    PK11_SetPasswordFunc(SECU_GetModulePassword);
   2347    memset(&addr, 0, sizeof(addr));
   2348    status = PR_StringToNetAddr(host, &addr);
   2349    if (status == PR_SUCCESS) {
   2350        addr.inet.port = PR_htons(portno);
   2351    } else {
   2352        PRBool gotLoopbackIP = PR_FALSE;
   2353        if ((!strcmp(host, "localhost") || !strcmp(host, "localhost.localdomain"))
   2354            /* only check for preference if both types are allowed */
   2355            && allowIPv4 && allowIPv6) {
   2356            /* make a decision which IP to prefer */
   2357            status = PR_GetPrefLoopbackAddrInfo(&addr, portno);
   2358            if (status != PR_FAILURE) {
   2359                gotLoopbackIP = PR_TRUE;
   2360            }
   2361        }
   2362 
   2363        if (!gotLoopbackIP) {
   2364            /* Lookup host */
   2365            PRAddrInfo *addrInfo;
   2366            void *enumPtr = NULL;
   2367 
   2368            addrInfo = PR_GetAddrInfoByName(host, PR_AF_UNSPEC,
   2369                                            PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME);
   2370            if (!addrInfo) {
   2371                fprintf(stderr, "HOSTNAME=%s\n", host);
   2372                SECU_PrintError(progName, "error looking up host");
   2373                error = 1;
   2374                goto done;
   2375            }
   2376            for (;;) {
   2377                enumPtr = PR_EnumerateAddrInfo(enumPtr, addrInfo, portno, &addr);
   2378                if (enumPtr == NULL)
   2379                    break;
   2380                if (addr.raw.family == PR_AF_INET && allowIPv4)
   2381                    break;
   2382                if (addr.raw.family == PR_AF_INET6 && allowIPv6)
   2383                    break;
   2384            }
   2385            PR_FreeAddrInfo(addrInfo);
   2386            if (enumPtr == NULL) {
   2387                SECU_PrintError(progName, "error looking up host address");
   2388                error = 1;
   2389                goto done;
   2390            }
   2391        }
   2392    }
   2393 
   2394    printHostNameAndAddr(host, &addr);
   2395 
   2396    if (!certDir) {
   2397        certDir = SECU_DefaultSSLDir(); /* Look in $SSL_DIR */
   2398        certDir = SECU_ConfigDirectory(certDir);
   2399    } else {
   2400        char *certDirTmp = certDir;
   2401        certDir = SECU_ConfigDirectory(certDirTmp);
   2402        PORT_Free(certDirTmp);
   2403    }
   2404 
   2405    if (pingServerFirst) {
   2406        int iter = 0;
   2407        PRErrorCode err;
   2408 
   2409        int max_attempts = MAX_WAIT_FOR_SERVER;
   2410        if (pingTimeoutSeconds >= 0) {
   2411            /* If caller requested a timeout, let's try just twice. */
   2412            max_attempts = 2;
   2413        }
   2414        do {
   2415            PRIntervalTime timeoutInterval = PR_INTERVAL_NO_TIMEOUT;
   2416            s = PR_OpenTCPSocket(addr.raw.family);
   2417            if (s == NULL) {
   2418                SECU_PrintError(progName, "Failed to create a TCP socket");
   2419                error = 1;
   2420                goto done;
   2421            }
   2422            opt.option = PR_SockOpt_Nonblocking;
   2423            opt.value.non_blocking = PR_FALSE;
   2424            prStatus = PR_SetSocketOption(s, &opt);
   2425            if (prStatus != PR_SUCCESS) {
   2426                SECU_PrintError(progName,
   2427                                "Failed to set blocking socket option");
   2428                error = 1;
   2429                goto done;
   2430            }
   2431            if (pingTimeoutSeconds >= 0) {
   2432                timeoutInterval = PR_SecondsToInterval(pingTimeoutSeconds);
   2433            }
   2434            prStatus = PR_Connect(s, &addr, timeoutInterval);
   2435            if (prStatus == PR_SUCCESS) {
   2436                PR_Shutdown(s, PR_SHUTDOWN_BOTH);
   2437                goto done;
   2438            }
   2439            err = PR_GetError();
   2440            if ((err != PR_CONNECT_REFUSED_ERROR) &&
   2441                (err != PR_CONNECT_RESET_ERROR)) {
   2442                SECU_PrintError(progName, "TCP Connection failed");
   2443                error = 1;
   2444                goto done;
   2445            }
   2446            PR_Close(s);
   2447            s = NULL;
   2448            PR_Sleep(PR_MillisecondsToInterval(WAIT_INTERVAL));
   2449        } while (++iter < max_attempts);
   2450        SECU_PrintError(progName,
   2451                        "Client timed out while waiting for connection to server");
   2452        error = 1;
   2453        goto done;
   2454    }
   2455 
   2456    /* open the cert DB, the key DB, and the secmod DB. */
   2457    if (openDB) {
   2458        rv = NSS_Init(certDir);
   2459        if (rv != SECSuccess) {
   2460            SECU_PrintError(progName, "unable to open cert database");
   2461            error = 1;
   2462            goto done;
   2463        }
   2464    } else {
   2465        rv = NSS_NoDB_Init(NULL);
   2466        if (rv != SECSuccess) {
   2467            SECU_PrintError(progName, "failed to initialize NSS");
   2468            error = 1;
   2469            goto done;
   2470        }
   2471    }
   2472 
   2473    if (loadDefaultRootCAs) {
   2474        SECMOD_AddNewModule("Builtins",
   2475                            DLL_PREFIX "nssckbi." DLL_SUFFIX, 0, 0);
   2476    } else if (rootModule) {
   2477        SECMOD_AddNewModule("Builtins", rootModule, 0, 0);
   2478    }
   2479 
   2480    /* all SSL3 cipher suites are enabled by default. */
   2481    if (cipherString) {
   2482        /* disable all the ciphers, then enable the ones we want. */
   2483        disableAllSSLCiphers();
   2484    }
   2485 
   2486    while (numConnections--) {
   2487        error = run();
   2488        if (error) {
   2489            goto done;
   2490        }
   2491    }
   2492 
   2493 done:
   2494    if (s) {
   2495        PR_Close(s);
   2496    }
   2497 
   2498    PORT_Free((void *)requestFile);
   2499    PORT_Free(hs1SniHostName);
   2500    PORT_Free(hs2SniHostName);
   2501    PORT_Free(nickname);
   2502    PORT_Free(pwdata.data);
   2503    PORT_Free(host);
   2504    PORT_Free(zeroRttData);
   2505    PORT_Free(echConfigs);
   2506    SECITEM_ZfreeItem(&psk, PR_FALSE);
   2507    SECITEM_ZfreeItem(&pskLabel, PR_FALSE);
   2508 
   2509    if (enabledGroups) {
   2510        PORT_Free(enabledGroups);
   2511    }
   2512    if (NSS_IsInitialized()) {
   2513        SSL_ClearSessionCache();
   2514        if (initializedServerSessionCache) {
   2515            if (SSL_ShutdownServerSessionIDCache() != SECSuccess) {
   2516                error = 1;
   2517            }
   2518        }
   2519 
   2520        if (NSS_Shutdown() != SECSuccess) {
   2521            error = 1;
   2522        }
   2523    }
   2524 
   2525    FPRINTF(stderr, "tstclnt: exiting with return code %d\n", error);
   2526    PR_Cleanup();
   2527    return error;
   2528 }