tor-browser

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

selfserv.c (103902B)


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