summaryrefslogtreecommitdiff
path: root/nss/cmd/tstclnt/tstclnt.c
diff options
context:
space:
mode:
Diffstat (limited to 'nss/cmd/tstclnt/tstclnt.c')
-rw-r--r--nss/cmd/tstclnt/tstclnt.c2228
1 files changed, 1231 insertions, 997 deletions
diff --git a/nss/cmd/tstclnt/tstclnt.c b/nss/cmd/tstclnt/tstclnt.c
index 93a7022..eb114e9 100644
--- a/nss/cmd/tstclnt/tstclnt.c
+++ b/nss/cmd/tstclnt/tstclnt.c
@@ -14,7 +14,7 @@
#if defined(XP_UNIX)
#include <unistd.h>
#else
-#include <ctype.h> /* for isalpha() */
+#include <ctype.h> /* for isalpha() */
#endif
#include <stdio.h>
@@ -41,11 +41,15 @@
#include <io.h>
#endif
-#define PRINTF if (verbose) printf
-#define FPRINTF if (verbose) fprintf
+#define PRINTF \
+ if (verbose) \
+ printf
+#define FPRINTF \
+ if (verbose) \
+ fprintf
#define MAX_WAIT_FOR_SERVER 600
-#define WAIT_INTERVAL 100
+#define WAIT_INTERVAL 100
#define EXIT_CODE_HANDSHAKE_FAILED 254
@@ -54,45 +58,35 @@
#define EXIT_CODE_SIDECHANNELTEST_NODATA 2
#define EXIT_CODE_SIDECHANNELTEST_REVOKED 3
-PRIntervalTime maxInterval = PR_INTERVAL_NO_TIMEOUT;
-
-int ssl2CipherSuites[] = {
- SSL_EN_RC4_128_WITH_MD5, /* A */
- SSL_EN_RC4_128_EXPORT40_WITH_MD5, /* B */
- SSL_EN_RC2_128_CBC_WITH_MD5, /* C */
- SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, /* D */
- SSL_EN_DES_64_CBC_WITH_MD5, /* E */
- SSL_EN_DES_192_EDE3_CBC_WITH_MD5, /* F */
- 0
-};
+PRIntervalTime maxInterval = PR_INTERVAL_NO_TIMEOUT;
int ssl3CipherSuites[] = {
- -1, /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
- -1, /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, * b */
- TLS_RSA_WITH_RC4_128_MD5, /* c */
- TLS_RSA_WITH_3DES_EDE_CBC_SHA, /* d */
- TLS_RSA_WITH_DES_CBC_SHA, /* e */
- TLS_RSA_EXPORT_WITH_RC4_40_MD5, /* f */
- TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* g */
- -1, /* SSL_FORTEZZA_DMS_WITH_NULL_SHA, * h */
- TLS_RSA_WITH_NULL_MD5, /* i */
- SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, /* j */
- SSL_RSA_FIPS_WITH_DES_CBC_SHA, /* k */
- TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, /* l */
- TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, /* m */
- TLS_RSA_WITH_RC4_128_SHA, /* n */
- TLS_DHE_DSS_WITH_RC4_128_SHA, /* o */
- TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
- TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
- TLS_DHE_RSA_WITH_DES_CBC_SHA, /* r */
- TLS_DHE_DSS_WITH_DES_CBC_SHA, /* s */
- TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* t */
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* u */
- TLS_RSA_WITH_AES_128_CBC_SHA, /* v */
- TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* w */
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* x */
- TLS_RSA_WITH_AES_256_CBC_SHA, /* y */
- TLS_RSA_WITH_NULL_SHA, /* z */
+ -1, /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
+ -1, /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA * b */
+ TLS_RSA_WITH_RC4_128_MD5, /* c */
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA, /* d */
+ TLS_RSA_WITH_DES_CBC_SHA, /* e */
+ -1, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 * f */
+ -1, /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 * g */
+ -1, /* SSL_FORTEZZA_DMS_WITH_NULL_SHA * h */
+ TLS_RSA_WITH_NULL_MD5, /* i */
+ -1, /* SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA * j */
+ -1, /* SSL_RSA_FIPS_WITH_DES_CBC_SHA * k */
+ -1, /* TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA * l */
+ -1, /* TLS_RSA_EXPORT1024_WITH_RC4_56_SHA * m */
+ TLS_RSA_WITH_RC4_128_SHA, /* n */
+ TLS_DHE_DSS_WITH_RC4_128_SHA, /* o */
+ TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
+ TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
+ TLS_DHE_RSA_WITH_DES_CBC_SHA, /* r */
+ TLS_DHE_DSS_WITH_DES_CBC_SHA, /* s */
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* t */
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* u */
+ TLS_RSA_WITH_AES_128_CBC_SHA, /* v */
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* w */
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* x */
+ TLS_RSA_WITH_AES_256_CBC_SHA, /* y */
+ TLS_RSA_WITH_NULL_SHA, /* z */
0
};
@@ -104,64 +98,75 @@ int renegotiationsDone = 0;
static char *progName;
-secuPWData pwdata = { PW_NONE, 0 };
+secuPWData pwdata = { PW_NONE, 0 };
+
+SSLNamedGroup *enabledGroups = NULL;
+unsigned int enabledGroupsCount = 0;
-void printSecurityInfo(PRFileDesc *fd)
+void
+printSecurityInfo(PRFileDesc *fd)
{
- CERTCertificate * cert;
+ CERTCertificate *cert;
const SECItemArray *csa;
- SSL3Statistics * ssl3stats = SSL_GetStatistics();
+ const SECItem *scts;
+ SSL3Statistics *ssl3stats = SSL_GetStatistics();
SECStatus result;
- SSLChannelInfo channel;
+ SSLChannelInfo channel;
SSLCipherSuiteInfo suite;
result = SSL_GetChannelInfo(fd, &channel, sizeof channel);
- if (result == SECSuccess &&
- channel.length == sizeof channel &&
- channel.cipherSuite) {
- result = SSL_GetCipherSuiteInfo(channel.cipherSuite,
- &suite, sizeof suite);
- if (result == SECSuccess) {
- FPRINTF(stderr,
- "tstclnt: SSL version %d.%d using %d-bit %s with %d-bit %s MAC\n",
- channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
- suite.effectiveKeyBits, suite.symCipherName,
- suite.macBits, suite.macAlgorithmName);
- FPRINTF(stderr,
- "tstclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n"
- " Compression: %s, Extended Master Secret: %s\n",
- channel.authKeyBits, suite.authAlgorithmName,
- channel.keaKeyBits, suite.keaTypeName,
- channel.compressionMethodName,
- channel.extendedMasterSecretUsed ? "Yes": "No");
- }
+ if (result == SECSuccess &&
+ channel.length == sizeof channel &&
+ channel.cipherSuite) {
+ result = SSL_GetCipherSuiteInfo(channel.cipherSuite,
+ &suite, sizeof suite);
+ if (result == SECSuccess) {
+ FPRINTF(stderr,
+ "tstclnt: SSL version %d.%d using %d-bit %s with %d-bit %s MAC\n",
+ channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
+ suite.effectiveKeyBits, suite.symCipherName,
+ suite.macBits, suite.macAlgorithmName);
+ FPRINTF(stderr,
+ "tstclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n"
+ " Compression: %s, Extended Master Secret: %s\n",
+ channel.authKeyBits, suite.authAlgorithmName,
+ channel.keaKeyBits, suite.keaTypeName,
+ channel.compressionMethodName,
+ channel.extendedMasterSecretUsed ? "Yes" : "No");
+ }
}
cert = SSL_RevealCert(fd);
if (cert) {
- char * ip = CERT_NameToAscii(&cert->issuer);
- char * sp = CERT_NameToAscii(&cert->subject);
+ char *ip = CERT_NameToAscii(&cert->issuer);
+ char *sp = CERT_NameToAscii(&cert->subject);
if (sp) {
- fprintf(stderr, "subject DN: %s\n", sp);
- PORT_Free(sp);
- }
+ fprintf(stderr, "subject DN: %s\n", sp);
+ PORT_Free(sp);
+ }
if (ip) {
- fprintf(stderr, "issuer DN: %s\n", ip);
- PORT_Free(ip);
- }
- CERT_DestroyCertificate(cert);
- cert = NULL;
+ fprintf(stderr, "issuer DN: %s\n", ip);
+ PORT_Free(ip);
+ }
+ CERT_DestroyCertificate(cert);
+ cert = NULL;
}
fprintf(stderr,
- "%ld cache hits; %ld cache misses, %ld cache not reusable\n"
- "%ld stateless resumes\n",
- ssl3stats->hsh_sid_cache_hits, ssl3stats->hsh_sid_cache_misses,
- ssl3stats->hsh_sid_cache_not_ok, ssl3stats->hsh_sid_stateless_resumes);
+ "%ld cache hits; %ld cache misses, %ld cache not reusable\n"
+ "%ld stateless resumes\n",
+ ssl3stats->hsh_sid_cache_hits, ssl3stats->hsh_sid_cache_misses,
+ ssl3stats->hsh_sid_cache_not_ok, ssl3stats->hsh_sid_stateless_resumes);
csa = SSL_PeerStapledOCSPResponses(fd);
if (csa) {
fprintf(stderr, "Received %d Cert Status items (OCSP stapled data)\n",
csa->len);
}
+ scts = SSL_PeerSignedCertTimestamps(fd);
+ if (scts && scts->len) {
+ fprintf(stderr, "Received a Signed Certificate Timestamp of length"
+ " %u\n",
+ scts->len);
+ }
}
void
@@ -173,58 +178,58 @@ handshakeCallback(PRFileDesc *fd, void *client_data)
}
printSecurityInfo(fd);
if (renegotiationsDone < renegotiationsToDo) {
- SSL_ReHandshake(fd, (renegotiationsToDo < 2));
- ++renegotiationsDone;
+ SSL_ReHandshake(fd, (renegotiationsToDo < 2));
+ ++renegotiationsDone;
}
}
-static void PrintUsageHeader(const char *progName)
+static void
+PrintUsageHeader(const char *progName)
{
- fprintf(stderr,
-"Usage: %s -h host [-a 1st_hs_name ] [-a 2nd_hs_name ] [-p port]\n"
- "[-D | -d certdir] [-C] [-b | -R root-module] \n"
- "[-n nickname] [-Bafosvx] [-c ciphers] [-Y]\n"
- "[-V [min-version]:[max-version]] [-K] [-T]\n"
- "[-r N] [-w passwd] [-W pwfile] [-q [-t seconds]]\n",
+ fprintf(stderr,
+ "Usage: %s -h host [-a 1st_hs_name ] [-a 2nd_hs_name ] [-p port]\n"
+ "[-D | -d certdir] [-C] [-b | -R root-module] \n"
+ "[-n nickname] [-Bafosvx] [-c ciphers] [-Y] [-Z]\n"
+ "[-V [min-version]:[max-version]] [-K] [-T] [-U]\n"
+ "[-r N] [-w passwd] [-W pwfile] [-q [-t seconds]] [-I groups]\n"
+ "[-A requestfile] [-L totalconnections]",
progName);
}
-static void PrintParameterUsage(void)
+static void
+PrintParameterUsage(void)
{
fprintf(stderr, "%-20s Send different SNI name. 1st_hs_name - at first\n"
"%-20s handshake, 2nd_hs_name - at second handshake.\n"
- "%-20s Default is host from the -h argument.\n", "-a name",
- "", "");
+ "%-20s Default is host from the -h argument.\n",
+ "-a name",
+ "", "");
fprintf(stderr, "%-20s Hostname to connect with\n", "-h host");
fprintf(stderr, "%-20s Port number for SSL server\n", "-p port");
- fprintf(stderr,
+ fprintf(stderr,
"%-20s Directory with cert database (default is ~/.netscape)\n",
- "-d certdir");
+ "-d certdir");
fprintf(stderr, "%-20s Run without a cert database\n", "-D");
fprintf(stderr, "%-20s Load the default \"builtins\" root CA module\n", "-b");
fprintf(stderr, "%-20s Load the given root CA module\n", "-R");
fprintf(stderr, "%-20s Print certificate chain information\n", "-C");
fprintf(stderr, "%-20s (use -C twice to print more certificate details)\n", "");
fprintf(stderr, "%-20s (use -C three times to include PEM format certificate dumps)\n", "");
- fprintf(stderr, "%-20s Nickname of key and cert for client auth\n",
- "-n nickname");
- fprintf(stderr,
- "%-20s Bypass PKCS11 layer for SSL encryption and MACing.\n", "-B");
- fprintf(stderr,
+ fprintf(stderr, "%-20s Nickname of key and cert for client auth\n",
+ "-n nickname");
+ fprintf(stderr,
"%-20s Restricts the set of enabled SSL/TLS protocols versions.\n"
"%-20s All versions are enabled by default.\n"
- "%-20s Possible values for min/max: ssl2 ssl3 tls1.0 tls1.1 tls1.2\n"
+ "%-20s Possible values for min/max: ssl3 tls1.0 tls1.1 tls1.2 tls1.3\n"
"%-20s Example: \"-V ssl3:\" enables SSL 3 and newer.\n",
"-V [min]:[max]", "", "", "");
fprintf(stderr, "%-20s Send TLS_FALLBACK_SCSV\n", "-K");
fprintf(stderr, "%-20s Prints only payload data. Skips HTTP header.\n", "-S");
fprintf(stderr, "%-20s Client speaks first. \n", "-f");
- fprintf(stderr, "%-20s Use synchronous certificate validation "
- "(required for SSL2)\n", "-O");
+ fprintf(stderr, "%-20s Use synchronous certificate validation\n", "-O");
fprintf(stderr, "%-20s Override bad server cert. Make it OK.\n", "-o");
fprintf(stderr, "%-20s Disable SSL socket locking.\n", "-s");
fprintf(stderr, "%-20s Verbose progress reporting.\n", "-v");
- fprintf(stderr, "%-20s Use export policy.\n", "-x");
fprintf(stderr, "%-20s Ping the server and then exit.\n", "-q");
fprintf(stderr, "%-20s Timeout for server ping (default: no timeout).\n", "-t seconds");
fprintf(stderr, "%-20s Renegotiate N times (resuming session if N>1).\n", "-r N");
@@ -232,7 +237,7 @@ static void PrintParameterUsage(void)
fprintf(stderr, "%-20s Enable compression.\n", "-z");
fprintf(stderr, "%-20s Enable false start.\n", "-g");
fprintf(stderr, "%-20s Enable the cert_status extension (OCSP stapling).\n", "-T");
- fprintf(stderr, "%-20s Enable the extended master secret extension (session hash).\n", "-G");
+ fprintf(stderr, "%-20s Enable the signed_certificate_timestamp extension.\n", "-U");
fprintf(stderr, "%-20s Require fresh revocation info from side channel.\n"
"%-20s -F once means: require for server cert only\n"
"%-20s -F twice means: require for intermediates, too\n"
@@ -243,61 +248,60 @@ static void PrintParameterUsage(void)
"%-20s 1: cert failed to verify, prior to revocation checking\n"
"%-20s 2: missing, old or invalid revocation data\n"
"%-20s 3: have fresh and valid revocation data, status revoked\n",
- "-F", "", "", "", "", "", "", "", "", "");
+ "-F", "", "", "", "", "", "", "", "", "");
fprintf(stderr, "%-20s Test -F allows 0=any (default), 1=only OCSP, 2=only CRL\n", "-M");
fprintf(stderr, "%-20s Restrict ciphers\n", "-c ciphers");
fprintf(stderr, "%-20s Print cipher values allowed for parameter -c and exit\n", "-Y");
fprintf(stderr, "%-20s Enforce using an IPv4 destination address\n", "-4");
fprintf(stderr, "%-20s Enforce using an IPv6 destination address\n", "-6");
fprintf(stderr, "%-20s (Options -4 and -6 cannot be combined.)\n", "");
+ fprintf(stderr, "%-20s Enable the extended master secret extension [RFC7627]\n", "-G");
+ fprintf(stderr, "%-20s Require the use of FFDHE supported groups "
+ "[I-D.ietf-tls-negotiated-ff-dhe]\n",
+ "-H");
+ fprintf(stderr, "%-20s Read from a file instead of stdin\n", "-A");
+ fprintf(stderr, "%-20s Allow 0-RTT data (TLS 1.3 only)\n", "-Z");
+ fprintf(stderr, "%-20s Disconnect and reconnect up to N times total\n", "-L");
+ fprintf(stderr, "%-20s Comma separated list of enabled groups for TLS key exchange.\n"
+ "%-20s The following values are valid:\n"
+ "%-20s P256, P384, P521, x25519, FF2048, FF3072, FF4096, FF6144, FF8192\n",
+ "-I", "", "");
}
-static void Usage(const char *progName)
+static void
+Usage(const char *progName)
{
PrintUsageHeader(progName);
PrintParameterUsage();
exit(1);
}
-static void PrintCipherUsage(const char *progName)
+static void
+PrintCipherUsage(const char *progName)
{
PrintUsageHeader(progName);
- fprintf(stderr, "%-20s Letter(s) chosen from the following list\n",
- "-c ciphers");
- fprintf(stderr,
-"A SSL2 RC4 128 WITH MD5\n"
-"B SSL2 RC4 128 EXPORT40 WITH MD5\n"
-"C SSL2 RC2 128 CBC WITH MD5\n"
-"D SSL2 RC2 128 CBC EXPORT40 WITH MD5\n"
-"E SSL2 DES 64 CBC WITH MD5\n"
-"F SSL2 DES 192 EDE3 CBC WITH MD5\n"
-"\n"
-"c SSL3 RSA WITH RC4 128 MD5\n"
-"d SSL3 RSA WITH 3DES EDE CBC SHA\n"
-"e SSL3 RSA WITH DES CBC SHA\n"
-"f SSL3 RSA EXPORT WITH RC4 40 MD5\n"
-"g SSL3 RSA EXPORT WITH RC2 CBC 40 MD5\n"
-"i SSL3 RSA WITH NULL MD5\n"
-"j SSL3 RSA FIPS WITH 3DES EDE CBC SHA\n"
-"k SSL3 RSA FIPS WITH DES CBC SHA\n"
-"l SSL3 RSA EXPORT WITH DES CBC SHA\t(new)\n"
-"m SSL3 RSA EXPORT WITH RC4 56 SHA\t(new)\n"
-"n SSL3 RSA WITH RC4 128 SHA\n"
-"o SSL3 DHE DSS WITH RC4 128 SHA\n"
-"p SSL3 DHE RSA WITH 3DES EDE CBC SHA\n"
-"q SSL3 DHE DSS WITH 3DES EDE CBC SHA\n"
-"r SSL3 DHE RSA WITH DES CBC SHA\n"
-"s SSL3 DHE DSS WITH DES CBC SHA\n"
-"t SSL3 DHE DSS WITH AES 128 CBC SHA\n"
-"u SSL3 DHE RSA WITH AES 128 CBC SHA\n"
-"v SSL3 RSA WITH AES 128 CBC SHA\n"
-"w SSL3 DHE DSS WITH AES 256 CBC SHA\n"
-"x SSL3 DHE RSA WITH AES 256 CBC SHA\n"
-"y SSL3 RSA WITH AES 256 CBC SHA\n"
-"z SSL3 RSA WITH NULL SHA\n"
-"\n"
-":WXYZ Use cipher with hex code { 0xWX , 0xYZ } in TLS\n"
- );
+ fprintf(stderr, "%-20s Letter(s) chosen from the following list\n",
+ "-c ciphers");
+ fprintf(stderr,
+ "c SSL3 RSA WITH RC4 128 MD5\n"
+ "d SSL3 RSA WITH 3DES EDE CBC SHA\n"
+ "e SSL3 RSA WITH DES CBC SHA\n"
+ "i SSL3 RSA WITH NULL MD5\n"
+ "n SSL3 RSA WITH RC4 128 SHA\n"
+ "o SSL3 DHE DSS WITH RC4 128 SHA\n"
+ "p SSL3 DHE RSA WITH 3DES EDE CBC SHA\n"
+ "q SSL3 DHE DSS WITH 3DES EDE CBC SHA\n"
+ "r SSL3 DHE RSA WITH DES CBC SHA\n"
+ "s SSL3 DHE DSS WITH DES CBC SHA\n"
+ "t SSL3 DHE DSS WITH AES 128 CBC SHA\n"
+ "u SSL3 DHE RSA WITH AES 128 CBC SHA\n"
+ "v SSL3 RSA WITH AES 128 CBC SHA\n"
+ "w SSL3 DHE DSS WITH AES 256 CBC SHA\n"
+ "x SSL3 DHE RSA WITH AES 256 CBC SHA\n"
+ "y SSL3 RSA WITH AES 256 CBC SHA\n"
+ "z SSL3 RSA WITH NULL SHA\n"
+ "\n"
+ ":WXYZ Use cipher with hex code { 0xWX , 0xYZ } in TLS\n");
exit(1);
}
@@ -312,55 +316,52 @@ void
disableAllSSLCiphers(void)
{
const PRUint16 *cipherSuites = SSL_GetImplementedCiphers();
- int i = SSL_GetNumImplementedCiphers();
- SECStatus rv;
+ int i = SSL_GetNumImplementedCiphers();
+ SECStatus rv;
/* disable all the SSL3 cipher suites */
while (--i >= 0) {
- PRUint16 suite = cipherSuites[i];
+ PRUint16 suite = cipherSuites[i];
rv = SSL_CipherPrefSetDefault(suite, PR_FALSE);
- if (rv != SECSuccess) {
- PRErrorCode err = PR_GetError();
- fprintf(stderr,
- "SSL_CipherPrefSet didn't like value 0x%04x (i = %d): %s\n",
- suite, i, SECU_Strerror(err));
- exit(2);
- }
+ if (rv != SECSuccess) {
+ PRErrorCode err = PR_GetError();
+ fprintf(stderr,
+ "SSL_CipherPrefSet didn't like value 0x%04x (i = %d): %s\n",
+ suite, i, SECU_Strerror(err));
+ exit(2);
+ }
}
}
typedef struct
{
- PRBool shouldPause; /* PR_TRUE if we should use asynchronous peer cert
+ PRBool shouldPause; /* PR_TRUE if we should use asynchronous peer cert
* authentication */
- PRBool isPaused; /* PR_TRUE if libssl is waiting for us to validate the
+ PRBool isPaused; /* PR_TRUE if libssl is waiting for us to validate the
* peer's certificate and restart the handshake. */
- void * dbHandle; /* Certificate database handle to use while
+ void *dbHandle; /* Certificate database handle to use while
* authenticating the peer's certificate. */
- PRBool testFreshStatusFromSideChannel;
- PRErrorCode sideChannelRevocationTestResultCode;
- PRBool requireDataForIntermediates;
- PRBool allowOCSPSideChannelData;
- PRBool allowCRLSideChannelData;
+ PRBool testFreshStatusFromSideChannel;
+ PRErrorCode sideChannelRevocationTestResultCode;
+ PRBool requireDataForIntermediates;
+ PRBool allowOCSPSideChannelData;
+ PRBool allowCRLSideChannelData;
} ServerCertAuth;
-
/*
* Callback is called when incoming certificate is not valid.
* Returns SECSuccess to accept the cert anyway, SECFailure to reject.
*/
-static SECStatus
-ownBadCertHandler(void * arg, PRFileDesc * socket)
+static SECStatus
+ownBadCertHandler(void *arg, PRFileDesc *socket)
{
PRErrorCode err = PR_GetError();
/* can log invalid cert here */
- fprintf(stderr, "Bad server certificate: %d, %s\n", err,
+ fprintf(stderr, "Bad server certificate: %d, %s\n", err,
SECU_Strerror(err));
- return SECSuccess; /* override, say it's OK. */
+ return SECSuccess; /* override, say it's OK. */
}
-
-
#define EXIT_CODE_SIDECHANNELTEST_GOOD 0
#define EXIT_CODE_SIDECHANNELTEST_BADCERT 1
#define EXIT_CODE_SIDECHANNELTEST_NODATA 2
@@ -369,23 +370,23 @@ ownBadCertHandler(void * arg, PRFileDesc * socket)
static void
verifyFromSideChannel(CERTCertificate *cert, ServerCertAuth *sca)
{
- PRUint64 revDoNotUse =
- CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD;
-
- PRUint64 revUseLocalOnlyAndSoftFail =
- CERT_REV_M_TEST_USING_THIS_METHOD
- | CERT_REV_M_FORBID_NETWORK_FETCHING
- | CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE
- | CERT_REV_M_IGNORE_MISSING_FRESH_INFO
- | CERT_REV_M_STOP_TESTING_ON_FRESH_INFO;
-
- PRUint64 revUseLocalOnlyAndHardFail =
- CERT_REV_M_TEST_USING_THIS_METHOD
- | CERT_REV_M_FORBID_NETWORK_FETCHING
- | CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE
- | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
- | CERT_REV_M_STOP_TESTING_ON_FRESH_INFO;
-
+ PRUint64 revDoNotUse =
+ CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD;
+
+ PRUint64 revUseLocalOnlyAndSoftFail =
+ CERT_REV_M_TEST_USING_THIS_METHOD |
+ CERT_REV_M_FORBID_NETWORK_FETCHING |
+ CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE |
+ CERT_REV_M_IGNORE_MISSING_FRESH_INFO |
+ CERT_REV_M_STOP_TESTING_ON_FRESH_INFO;
+
+ PRUint64 revUseLocalOnlyAndHardFail =
+ CERT_REV_M_TEST_USING_THIS_METHOD |
+ CERT_REV_M_FORBID_NETWORK_FETCHING |
+ CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE |
+ CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO |
+ CERT_REV_M_STOP_TESTING_ON_FRESH_INFO;
+
PRUint64 methodFlagsDoNotUse[2];
PRUint64 methodFlagsCheckSoftFail[2];
PRUint64 methodFlagsCheckHardFail[2];
@@ -396,52 +397,52 @@ verifyFromSideChannel(CERTCertificate *cert, ServerCertAuth *sca)
CERTValInParam cvin[2];
CERTValOutParam cvout[1];
SECStatus rv;
-
+
methodFlagsDoNotUse[cert_revocation_method_crl] = revDoNotUse;
methodFlagsDoNotUse[cert_revocation_method_ocsp] = revDoNotUse;
-
- methodFlagsCheckSoftFail[cert_revocation_method_crl] =
+
+ methodFlagsCheckSoftFail[cert_revocation_method_crl] =
sca->allowCRLSideChannelData ? revUseLocalOnlyAndSoftFail : revDoNotUse;
- methodFlagsCheckSoftFail[cert_revocation_method_ocsp] =
+ methodFlagsCheckSoftFail[cert_revocation_method_ocsp] =
sca->allowOCSPSideChannelData ? revUseLocalOnlyAndSoftFail : revDoNotUse;
-
- methodFlagsCheckHardFail[cert_revocation_method_crl] =
+
+ methodFlagsCheckHardFail[cert_revocation_method_crl] =
sca->allowCRLSideChannelData ? revUseLocalOnlyAndHardFail : revDoNotUse;
- methodFlagsCheckHardFail[cert_revocation_method_ocsp] =
+ methodFlagsCheckHardFail[cert_revocation_method_ocsp] =
sca->allowOCSPSideChannelData ? revUseLocalOnlyAndHardFail : revDoNotUse;
revTestsDoNotCheck.cert_rev_flags_per_method = methodFlagsDoNotUse;
revTestsDoNotCheck.number_of_defined_methods = 2;
revTestsDoNotCheck.number_of_preferred_methods = 0;
revTestsDoNotCheck.cert_rev_method_independent_flags =
- CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST
- | CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT;
-
+ CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST |
+ CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT;
+
revTestsOverallSoftFail.cert_rev_flags_per_method = 0; /* must define later */
revTestsOverallSoftFail.number_of_defined_methods = 2;
revTestsOverallSoftFail.number_of_preferred_methods = 0;
revTestsOverallSoftFail.cert_rev_method_independent_flags =
- CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST
- | CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT;
-
+ CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST |
+ CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT;
+
revTestsOverallHardFail.cert_rev_flags_per_method = 0; /* must define later */
revTestsOverallHardFail.number_of_defined_methods = 2;
revTestsOverallHardFail.number_of_preferred_methods = 0;
revTestsOverallHardFail.cert_rev_method_independent_flags =
- CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST
- | CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE;
+ CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST |
+ CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE;
rev.chainTests = revTestsDoNotCheck;
rev.leafTests = revTestsDoNotCheck;
-
+
cvin[0].type = cert_pi_revocationFlags;
cvin[0].value.pointer.revocation = &rev;
cvin[1].type = cert_pi_end;
cvout[0].type = cert_po_end;
-
+
/* Strategy:
- *
+ *
* Verify with revocation checking disabled.
* On failure return 1.
*
@@ -458,68 +459,66 @@ verifyFromSideChannel(CERTCertificate *cert, ServerCertAuth *sca)
* because we don't have fresh revocation info, return 2.
*
* If result is still bad, we do have revocation info,
- * and it says "revoked" or something equivalent, return 3.
+ * and it says "revoked" or something equivalent, return 3.
*/
-
+
/* revocation checking disabled */
rv = CERT_PKIXVerifyCert(cert, certificateUsageSSLServer,
cvin, cvout, NULL);
if (rv != SECSuccess) {
- sca->sideChannelRevocationTestResultCode =
+ sca->sideChannelRevocationTestResultCode =
EXIT_CODE_SIDECHANNELTEST_BADCERT;
return;
}
-
+
/* revocation checking, hard fail */
if (sca->allowOCSPSideChannelData && sca->allowCRLSideChannelData) {
/* any method is allowed. use soft fail on individual checks,
* but use hard fail on the overall check
*/
revTestsOverallHardFail.cert_rev_flags_per_method = methodFlagsCheckSoftFail;
- }
- else {
+ } else {
/* only one method is allowed. use hard fail on the individual checks.
* hard/soft fail is irrelevant on overall flags.
*/
revTestsOverallHardFail.cert_rev_flags_per_method = methodFlagsCheckHardFail;
}
rev.leafTests = revTestsOverallHardFail;
- rev.chainTests =
+ rev.chainTests =
sca->requireDataForIntermediates ? revTestsOverallHardFail : revTestsDoNotCheck;
rv = CERT_PKIXVerifyCert(cert, certificateUsageSSLServer,
cvin, cvout, NULL);
if (rv == SECSuccess) {
- sca->sideChannelRevocationTestResultCode =
+ sca->sideChannelRevocationTestResultCode =
EXIT_CODE_SIDECHANNELTEST_GOOD;
return;
}
-
+
/* revocation checking, soft fail */
revTestsOverallSoftFail.cert_rev_flags_per_method = methodFlagsCheckSoftFail;
rev.leafTests = revTestsOverallSoftFail;
- rev.chainTests =
+ rev.chainTests =
sca->requireDataForIntermediates ? revTestsOverallSoftFail : revTestsDoNotCheck;
rv = CERT_PKIXVerifyCert(cert, certificateUsageSSLServer,
cvin, cvout, NULL);
if (rv == SECSuccess) {
- sca->sideChannelRevocationTestResultCode =
+ sca->sideChannelRevocationTestResultCode =
EXIT_CODE_SIDECHANNELTEST_NODATA;
return;
}
-
- sca->sideChannelRevocationTestResultCode =
+
+ sca->sideChannelRevocationTestResultCode =
EXIT_CODE_SIDECHANNELTEST_REVOKED;
}
-
static void
dumpCertificatePEM(CERTCertificate *cert)
{
SECItem data;
data.data = cert->derCert.data;
data.len = cert->derCert.len;
- fprintf(stderr, "%s\n%s\n%s\n", NS_CERT_HEADER,
- BTOA_DataToAscii(data.data, data.len), NS_CERT_TRAILER);
+ fprintf(stderr, "%s\n%s\n%s\n", NS_CERT_HEADER,
+ BTOA_DataToAscii(data.data, data.len), NS_CERT_TRAILER);
}
static void
@@ -533,15 +532,14 @@ dumpServerCertificateChain(PRFileDesc *fd)
PRBool dumpCertPEM = PR_FALSE;
if (!dumpServerChain) {
- return;
- }
- else if (dumpServerChain == 1) {
- dumpFunction = (SECU_PPFunc)SECU_PrintCertificateBasicInfo;
+ return;
+ } else if (dumpServerChain == 1) {
+ dumpFunction = (SECU_PPFunc)SECU_PrintCertificateBasicInfo;
} else {
- dumpFunction = (SECU_PPFunc)SECU_PrintCertificate;
- if (dumpServerChain > 2) {
- dumpCertPEM = PR_TRUE;
- }
+ dumpFunction = (SECU_PPFunc)SECU_PrintCertificate;
+ if (dumpServerChain > 2) {
+ dumpCertPEM = PR_TRUE;
+ }
}
SECU_EnableWrap(PR_FALSE);
@@ -550,82 +548,81 @@ dumpServerCertificateChain(PRFileDesc *fd)
peerCertChain = SSL_PeerCertificateChain(fd);
if (peerCertChain) {
node = CERT_LIST_HEAD(peerCertChain);
- while ( ! CERT_LIST_END(node, peerCertChain) ) {
+ while (!CERT_LIST_END(node, peerCertChain)) {
CERTCertificate *cert = node->cert;
SECU_PrintSignedContent(stderr, &cert->derCert, "Certificate", 0,
dumpFunction);
- if (dumpCertPEM) {
- dumpCertificatePEM(cert);
- }
- node = CERT_LIST_NEXT(node);
+ if (dumpCertPEM) {
+ dumpCertificatePEM(cert);
+ }
+ node = CERT_LIST_NEXT(node);
}
}
if (peerCertChain) {
- peerCert = SSL_RevealCert(fd);
- if (peerCert) {
- foundChain = CERT_CertChainFromCert(peerCert, certificateUsageSSLServer,
- PR_TRUE);
- }
- if (foundChain) {
- unsigned int count = 0;
- fprintf(stderr, "==== locally found issuer certificate(s): ====\n");
- for(count = 0; count < (unsigned int)foundChain->len; count++) {
- CERTCertificate *c;
- PRBool wasSentByServer = PR_FALSE;
- c = CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), &foundChain->certs[count]);
-
- node = CERT_LIST_HEAD(peerCertChain);
- while ( ! CERT_LIST_END(node, peerCertChain) ) {
- CERTCertificate *cert = node->cert;
- if (CERT_CompareCerts(cert, c)) {
- wasSentByServer = PR_TRUE;
- break;
- }
- node = CERT_LIST_NEXT(node);
- }
-
- if (!wasSentByServer) {
- SECU_PrintSignedContent(stderr, &c->derCert, "Certificate", 0,
- dumpFunction);
- if (dumpCertPEM) {
- dumpCertificatePEM(c);
- }
- }
- CERT_DestroyCertificate(c);
- }
- CERT_DestroyCertificateList(foundChain);
- }
- if (peerCert) {
- CERT_DestroyCertificate(peerCert);
- }
-
- CERT_DestroyCertList(peerCertChain);
- peerCertChain = NULL;
+ peerCert = SSL_RevealCert(fd);
+ if (peerCert) {
+ foundChain = CERT_CertChainFromCert(peerCert, certificateUsageSSLServer,
+ PR_TRUE);
+ }
+ if (foundChain) {
+ unsigned int count = 0;
+ fprintf(stderr, "==== locally found issuer certificate(s): ====\n");
+ for (count = 0; count < (unsigned int)foundChain->len; count++) {
+ CERTCertificate *c;
+ PRBool wasSentByServer = PR_FALSE;
+ c = CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), &foundChain->certs[count]);
+
+ node = CERT_LIST_HEAD(peerCertChain);
+ while (!CERT_LIST_END(node, peerCertChain)) {
+ CERTCertificate *cert = node->cert;
+ if (CERT_CompareCerts(cert, c)) {
+ wasSentByServer = PR_TRUE;
+ break;
+ }
+ node = CERT_LIST_NEXT(node);
+ }
+
+ if (!wasSentByServer) {
+ SECU_PrintSignedContent(stderr, &c->derCert, "Certificate", 0,
+ dumpFunction);
+ if (dumpCertPEM) {
+ dumpCertificatePEM(c);
+ }
+ }
+ CERT_DestroyCertificate(c);
+ }
+ CERT_DestroyCertificateList(foundChain);
+ }
+ if (peerCert) {
+ CERT_DestroyCertificate(peerCert);
+ }
+
+ CERT_DestroyCertList(peerCertChain);
+ peerCertChain = NULL;
}
fprintf(stderr, "==== end of certificate chain information ====\n");
fflush(stderr);
}
-static SECStatus
+static SECStatus
ownAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
- PRBool isServer)
+ PRBool isServer)
{
- ServerCertAuth * serverCertAuth = (ServerCertAuth *) arg;
+ ServerCertAuth *serverCertAuth = (ServerCertAuth *)arg;
if (dumpServerChain) {
- dumpServerCertificateChain(fd);
+ dumpServerCertificateChain(fd);
}
-
if (!serverCertAuth->shouldPause) {
CERTCertificate *cert;
unsigned int i;
const SECItemArray *csa;
if (!serverCertAuth->testFreshStatusFromSideChannel) {
- return SSL_AuthCertificate(serverCertAuth->dbHandle,
+ return SSL_AuthCertificate(serverCertAuth->dbHandle,
fd, checkSig, isServer);
}
@@ -642,26 +639,26 @@ ownAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
csa = SSL_PeerStapledOCSPResponses(fd);
if (csa) {
for (i = 0; i < csa->len; ++i) {
- PORT_SetError(0);
- if (CERT_CacheOCSPResponseFromSideChannel(
- serverCertAuth->dbHandle, cert, PR_Now(),
- &csa->items[i], arg) != SECSuccess) {
- PORT_Assert(PR_GetError() != 0);
- }
+ PORT_SetError(0);
+ if (CERT_CacheOCSPResponseFromSideChannel(
+ serverCertAuth->dbHandle, cert, PR_Now(),
+ &csa->items[i], arg) != SECSuccess) {
+ PORT_Assert(PR_GetError() != 0);
+ }
}
}
-
+
verifyFromSideChannel(cert, serverCertAuth);
CERT_DestroyCertificate(cert);
- /* return success to ensure our caller will continue and we will
- * reach the code that handles
+ /* return success to ensure our caller will continue and we will
+ * reach the code that handles
* serverCertAuth->sideChannelRevocationTestResultCode
*/
return SECSuccess;
}
-
+
FPRINTF(stderr, "%s: using asynchronous certificate validation\n",
- progName);
+ progName);
PORT_Assert(!serverCertAuth->isPaused);
serverCertAuth->isPaused = PR_TRUE;
@@ -669,85 +666,85 @@ ownAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
}
SECStatus
-own_GetClientAuthData(void * arg,
- PRFileDesc * socket,
- struct CERTDistNamesStr * caNames,
- struct CERTCertificateStr ** pRetCert,
+own_GetClientAuthData(void *arg,
+ PRFileDesc *socket,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
struct SECKEYPrivateKeyStr **pRetKey)
{
if (verbose > 1) {
- SECStatus rv;
+ SECStatus rv;
fprintf(stderr, "Server requested Client Authentication\n");
- if (caNames && caNames->nnames > 0) {
- PLArenaPool *arena = caNames->arena;
- if (!arena)
- arena = PORT_NewArena(2048);
- if (arena) {
- int i;
- for (i = 0; i < caNames->nnames; ++i) {
- char *nameString;
- CERTName dn;
- rv = SEC_QuickDERDecodeItem(arena,
- &dn,
- SEC_ASN1_GET(CERT_NameTemplate),
- caNames->names + i);
- if (rv != SECSuccess)
- continue;
- nameString = CERT_NameToAscii(&dn);
- if (!nameString)
- continue;
- fprintf(stderr, "CA[%d]: %s\n", i + 1, nameString);
- PORT_Free(nameString);
- }
- if (!caNames->arena) {
- PORT_FreeArena(arena, PR_FALSE);
- }
- }
- }
- rv = NSS_GetClientAuthData(arg, socket, caNames, pRetCert, pRetKey);
- if (rv == SECSuccess && *pRetCert) {
- char *nameString = CERT_NameToAscii(&((*pRetCert)->subject));
- if (nameString) {
- fprintf(stderr, "sent cert: %s\n", nameString);
- PORT_Free(nameString);
- }
- } else {
- fprintf(stderr, "send no cert\n");
- }
- return rv;
+ if (caNames && caNames->nnames > 0) {
+ PLArenaPool *arena = caNames->arena;
+ if (!arena)
+ arena = PORT_NewArena(2048);
+ if (arena) {
+ int i;
+ for (i = 0; i < caNames->nnames; ++i) {
+ char *nameString;
+ CERTName dn;
+ rv = SEC_QuickDERDecodeItem(arena,
+ &dn,
+ SEC_ASN1_GET(CERT_NameTemplate),
+ caNames->names + i);
+ if (rv != SECSuccess)
+ continue;
+ nameString = CERT_NameToAscii(&dn);
+ if (!nameString)
+ continue;
+ fprintf(stderr, "CA[%d]: %s\n", i + 1, nameString);
+ PORT_Free(nameString);
+ }
+ if (!caNames->arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ }
+ }
+ rv = NSS_GetClientAuthData(arg, socket, caNames, pRetCert, pRetKey);
+ if (rv == SECSuccess && *pRetCert) {
+ char *nameString = CERT_NameToAscii(&((*pRetCert)->subject));
+ if (nameString) {
+ fprintf(stderr, "sent cert: %s\n", nameString);
+ PORT_Free(nameString);
+ }
+ } else {
+ fprintf(stderr, "send no cert\n");
+ }
+ return rv;
}
return NSS_GetClientAuthData(arg, socket, caNames, pRetCert, pRetKey);
}
#if defined(WIN32) || defined(OS2)
void
-thread_main(void * arg)
+thread_main(void *arg)
{
- PRFileDesc * ps = (PRFileDesc *)arg;
- PRFileDesc * std_in = PR_GetSpecialFD(PR_StandardInput);
+ PRFileDesc *ps = (PRFileDesc *)arg;
+ PRFileDesc *std_in = PR_GetSpecialFD(PR_StandardInput);
int wc, rc;
char buf[256];
#ifdef WIN32
{
- /* Put stdin into O_BINARY mode
- ** or else incoming \r\n's will become \n's.
- */
- int smrv = _setmode(_fileno(stdin), _O_BINARY);
- if (smrv == -1) {
- fprintf(stderr,
- "%s: Cannot change stdin to binary mode. Use -i option instead.\n",
- progName);
- /* plow ahead anyway */
- }
+ /* Put stdin into O_BINARY mode
+ ** or else incoming \r\n's will become \n's.
+ */
+ int smrv = _setmode(_fileno(stdin), _O_BINARY);
+ if (smrv == -1) {
+ fprintf(stderr,
+ "%s: Cannot change stdin to binary mode. Use -i option instead.\n",
+ progName);
+ /* plow ahead anyway */
+ }
}
#endif
do {
- rc = PR_Read(std_in, buf, sizeof buf);
- if (rc <= 0)
- break;
- wc = PR_Send(ps, buf, rc, 0, maxInterval);
+ rc = PR_Read(std_in, buf, sizeof buf);
+ if (rc <= 0)
+ break;
+ wc = PR_Send(ps, buf, rc, 0, maxInterval);
} while (wc == rc);
PR_Close(ps);
}
@@ -755,16 +752,16 @@ thread_main(void * arg)
#endif
static void
-printHostNameAndAddr(const char * host, const PRNetAddr * addr)
+printHostNameAndAddr(const char *host, const PRNetAddr *addr)
{
PRUint16 port = PR_NetAddrInetPort(addr);
char addrBuf[80];
PRStatus st = PR_NetAddrToString(addr, addrBuf, sizeof addrBuf);
if (st == PR_SUCCESS) {
- port = PR_ntohs(port);
- FPRINTF(stderr, "%s: connecting to %s:%hu (address=%s)\n",
- progName, host, port, addrBuf);
+ port = PR_ntohs(port);
+ FPRINTF(stderr, "%s: connecting to %s:%hu (address=%s)\n",
+ progName, host, port, addrBuf);
}
}
@@ -775,8 +772,9 @@ printHostNameAndAddr(const char * host, const PRNetAddr * addr)
* prints everything after it.
*/
static void
-separateReqHeader(const PRFileDesc* outFd, const char* buf, const int nb,
- PRBool *wrStarted, int *ptrnMatched) {
+separateReqHeader(const PRFileDesc *outFd, const char *buf, const int nb,
+ PRBool *wrStarted, int *ptrnMatched)
+{
/* it is sufficient to look for only "\n\r\n". Hopping that
* HTTP response format satisfies the standard */
@@ -800,7 +798,7 @@ separateReqHeader(const PRFileDesc* outFd, const char* buf, const int nb,
char *tmpPtrn = ptrnStr + (3 - strSize);
if (PL_strncmp(buf, tmpPtrn, strSize) == 0) {
/* print the rest of the buffer(without the fragment) */
- PR_Write((void*)outFd, buf + strSize, nb - strSize);
+ PR_Write((void *)outFd, buf + strSize, nb - strSize);
*wrStarted = PR_TRUE;
return;
}
@@ -820,7 +818,7 @@ separateReqHeader(const PRFileDesc* outFd, const char* buf, const int nb,
* and print the rest of the buffer */
int newBn = nb - (resPtr - buf + 3); /* 3 is the length of "\n\r\n" */
- PR_Write((void*)outFd, resPtr + 3, newBn);
+ PR_Write((void *)outFd, resPtr + 3, newBn);
*wrStarted = PR_TRUE;
return;
} else {
@@ -828,15 +826,15 @@ separateReqHeader(const PRFileDesc* outFd, const char* buf, const int nb,
* if found, set *ptrnMatched to the number of chars left to find
* in the next buffer.*/
int i;
- for(i = 1 ;i < 3;i++) {
+ for (i = 1; i < 3; i++) {
char *bufPrt;
int strSize = 3 - i;
-
+
if (strSize > nb) {
continue;
}
- bufPrt = (char*)(buf + nb - strSize);
-
+ bufPrt = (char *)(buf + nb - strSize);
+
if (PL_strncmp(bufPrt, ptrnStr, strSize) == 0) {
*ptrnMatched = i;
return;
@@ -848,28 +846,28 @@ separateReqHeader(const PRFileDesc* outFd, const char* buf, const int nb,
#define SSOCK_FD 0
#define STDIN_FD 1
-#define HEXCHAR_TO_INT(c, i) \
- if (((c) >= '0') && ((c) <= '9')) { \
- i = (c) - '0'; \
+#define HEXCHAR_TO_INT(c, i) \
+ if (((c) >= '0') && ((c) <= '9')) { \
+ i = (c) - '0'; \
} else if (((c) >= 'a') && ((c) <= 'f')) { \
- i = (c) - 'a' + 10; \
+ i = (c) - 'a' + 10; \
} else if (((c) >= 'A') && ((c) <= 'F')) { \
- i = (c) - 'A' + 10; \
- } else { \
- Usage(progName); \
+ i = (c) - 'A' + 10; \
+ } else { \
+ Usage(progName); \
}
static SECStatus
-restartHandshakeAfterServerCertIfNeeded(PRFileDesc * fd,
- ServerCertAuth * serverCertAuth,
+restartHandshakeAfterServerCertIfNeeded(PRFileDesc *fd,
+ ServerCertAuth *serverCertAuth,
PRBool override)
{
SECStatus rv;
PRErrorCode error;
-
+
if (!serverCertAuth->isPaused)
- return SECSuccess;
-
+ return SECSuccess;
+
FPRINTF(stderr, "%s: handshake was paused by auth certificate hook\n",
progName);
@@ -895,55 +893,572 @@ restartHandshakeAfterServerCertIfNeeded(PRFileDesc * fd,
return rv;
}
-
-int main(int argc, char **argv)
+
+char *host = NULL;
+char *nickname = NULL;
+char *cipherString = NULL;
+int multiplier = 0;
+SSLVersionRange enabledVersions;
+int disableLocking = 0;
+int enableSessionTickets = 0;
+int enableCompression = 0;
+int enableFalseStart = 0;
+int enableCertStatus = 0;
+int enableSignedCertTimestamps = 0;
+int forceFallbackSCSV = 0;
+int enableExtendedMasterSecret = 0;
+PRBool requireDHNamedGroups = 0;
+PRSocketOptionData opt;
+PRNetAddr addr;
+PRBool allowIPv4 = PR_TRUE;
+PRBool allowIPv6 = PR_TRUE;
+PRBool pingServerFirst = PR_FALSE;
+int pingTimeoutSeconds = -1;
+PRBool clientSpeaksFirst = PR_FALSE;
+PRBool skipProtoHeader = PR_FALSE;
+ServerCertAuth serverCertAuth;
+char *hs1SniHostName = NULL;
+char *hs2SniHostName = NULL;
+PRUint16 portno = 443;
+int override = 0;
+char *requestString = NULL;
+PRInt32 requestStringLen = 0;
+PRBool enableZeroRtt = PR_FALSE;
+
+static int
+writeBytesToServer(PRFileDesc *s, PRPollDesc *pollset, const char *buf, int nb)
+{
+ SECStatus rv;
+ const char *bufp = buf;
+
+ FPRINTF(stderr, "%s: Writing %d bytes to server\n",
+ progName, nb);
+ do {
+ PRInt32 cc = PR_Send(s, bufp, nb, 0, maxInterval);
+ if (cc < 0) {
+ PRErrorCode err = PR_GetError();
+ if (err != PR_WOULD_BLOCK_ERROR) {
+ SECU_PrintError(progName,
+ "write to SSL socket failed");
+ return 254;
+ }
+ cc = 0;
+ }
+ bufp += cc;
+ nb -= cc;
+ if (nb <= 0)
+ break;
+
+ rv = restartHandshakeAfterServerCertIfNeeded(s,
+ &serverCertAuth, override);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "authentication of server cert failed");
+ return EXIT_CODE_HANDSHAKE_FAILED;
+ }
+
+ pollset[SSOCK_FD].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ pollset[SSOCK_FD].out_flags = 0;
+ FPRINTF(stderr,
+ "%s: about to call PR_Poll on writable socket !\n",
+ progName);
+ cc = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (cc < 0) {
+ SECU_PrintError(progName,
+ "PR_Poll failed");
+ return -1;
+ }
+ FPRINTF(stderr,
+ "%s: PR_Poll returned with writable socket !\n",
+ progName);
+ } while (1);
+
+ return 0;
+}
+
+static int
+run_client(void)
+{
+ int headerSeparatorPtrnId = 0;
+ int error = 0;
+ SECStatus rv;
+ PRStatus status;
+ PRInt32 filesReady;
+ int npds;
+ PRFileDesc *s = NULL;
+ PRFileDesc *std_out;
+ PRPollDesc pollset[2];
+ PRBool wrStarted = PR_FALSE;
+ char *requestStringInt = requestString;
+
+ /* Create socket */
+ s = PR_OpenTCPSocket(addr.raw.family);
+ if (s == NULL) {
+ SECU_PrintError(progName, "error creating socket");
+ error = 1;
+ goto done;
+ }
+
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_TRUE; /* default */
+ if (serverCertAuth.testFreshStatusFromSideChannel) {
+ opt.value.non_blocking = PR_FALSE;
+ }
+ status = PR_SetSocketOption(s, &opt);
+ if (status != PR_SUCCESS) {
+ SECU_PrintError(progName, "error setting socket options");
+ error = 1;
+ goto done;
+ }
+
+ s = SSL_ImportFD(NULL, s);
+ if (s == NULL) {
+ SECU_PrintError(progName, "error importing socket");
+ error = 1;
+ goto done;
+ }
+
+ SSL_SetPKCS11PinArg(s, &pwdata);
+
+ rv = SSL_OptionSet(s, SSL_SECURITY, 1);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling socket");
+ error = 1;
+ goto done;
+ }
+
+ rv = SSL_OptionSet(s, SSL_HANDSHAKE_AS_CLIENT, 1);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling client handshake");
+ error = 1;
+ goto done;
+ }
+
+ /* all SSL3 cipher suites are enabled by default. */
+ if (cipherString) {
+ char *cstringSaved = cipherString;
+ int ndx;
+
+ while (0 != (ndx = *cipherString++)) {
+ int cipher = 0;
+
+ if (ndx == ':') {
+ int ctmp = 0;
+
+ HEXCHAR_TO_INT(*cipherString, ctmp)
+ cipher |= (ctmp << 12);
+ cipherString++;
+ HEXCHAR_TO_INT(*cipherString, ctmp)
+ cipher |= (ctmp << 8);
+ cipherString++;
+ HEXCHAR_TO_INT(*cipherString, ctmp)
+ cipher |= (ctmp << 4);
+ cipherString++;
+ HEXCHAR_TO_INT(*cipherString, ctmp)
+ cipher |= ctmp;
+ cipherString++;
+ } else {
+ if (!isalpha(ndx))
+ Usage(progName);
+ ndx = tolower(ndx) - 'a';
+ if (ndx < PR_ARRAY_SIZE(ssl3CipherSuites)) {
+ cipher = ssl3CipherSuites[ndx];
+ }
+ }
+ if (cipher > 0) {
+ SECStatus status;
+ status = SSL_CipherPrefSet(s, cipher, SSL_ALLOWED);
+ if (status != SECSuccess)
+ SECU_PrintError(progName, "SSL_CipherPrefSet()");
+ } else {
+ Usage(progName);
+ }
+ }
+ PORT_Free(cstringSaved);
+ }
+
+ rv = SSL_VersionRangeSet(s, &enabledVersions);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error setting SSL/TLS version range ");
+ error = 1;
+ goto done;
+ }
+
+ /* disable SSL socket locking */
+ rv = SSL_OptionSet(s, SSL_NO_LOCKS, disableLocking);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error disabling SSL socket locking");
+ error = 1;
+ goto done;
+ }
+
+ /* enable Session Ticket extension. */
+ rv = SSL_OptionSet(s, SSL_ENABLE_SESSION_TICKETS, enableSessionTickets);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling Session Ticket extension");
+ error = 1;
+ goto done;
+ }
+
+ /* enable compression. */
+ rv = SSL_OptionSet(s, SSL_ENABLE_DEFLATE, enableCompression);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling compression");
+ error = 1;
+ goto done;
+ }
+
+ /* enable false start. */
+ rv = SSL_OptionSet(s, SSL_ENABLE_FALSE_START, enableFalseStart);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling false start");
+ error = 1;
+ goto done;
+ }
+
+ if (forceFallbackSCSV) {
+ rv = SSL_OptionSet(s, SSL_ENABLE_FALLBACK_SCSV, PR_TRUE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error forcing fallback scsv");
+ error = 1;
+ goto done;
+ }
+ }
+
+ /* enable cert status (OCSP stapling). */
+ rv = SSL_OptionSet(s, SSL_ENABLE_OCSP_STAPLING, enableCertStatus);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling cert status (OCSP stapling)");
+ error = 1;
+ goto done;
+ }
+
+ /* enable extended master secret mode */
+ if (enableExtendedMasterSecret) {
+ rv = SSL_OptionSet(s, SSL_ENABLE_EXTENDED_MASTER_SECRET, PR_TRUE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling extended master secret");
+ error = 1;
+ goto done;
+ }
+ }
+
+ /* enable 0-RTT (TLS 1.3 only) */
+ if (enableZeroRtt) {
+ rv = SSL_OptionSet(s, SSL_ENABLE_0RTT_DATA, PR_TRUE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling 0-RTT");
+ error = 1;
+ goto done;
+ }
+ }
+
+ /* require the use of fixed finite-field DH groups */
+ if (requireDHNamedGroups) {
+ rv = SSL_OptionSet(s, SSL_REQUIRE_DH_NAMED_GROUPS, PR_TRUE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error in requiring the use of fixed finite-field DH groups");
+ error = 1;
+ goto done;
+ }
+ }
+
+ /* enable Signed Certificate Timestamps. */
+ rv = SSL_OptionSet(s, SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
+ enableSignedCertTimestamps);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling signed cert timestamps");
+ error = 1;
+ goto done;
+ }
+
+ if (enabledGroups) {
+ rv = SSL_NamedGroupConfig(s, enabledGroups, enabledGroupsCount);
+ if (rv < 0) {
+ SECU_PrintError(progName, "SSL_NamedGroupConfig failed");
+ error = 1;
+ goto done;
+ }
+ }
+
+ serverCertAuth.dbHandle = CERT_GetDefaultCertDB();
+
+ SSL_AuthCertificateHook(s, ownAuthCertificate, &serverCertAuth);
+ if (override) {
+ SSL_BadCertHook(s, ownBadCertHandler, NULL);
+ }
+ SSL_GetClientAuthDataHook(s, own_GetClientAuthData, (void *)nickname);
+ SSL_HandshakeCallback(s, handshakeCallback, hs2SniHostName);
+ if (hs1SniHostName) {
+ SSL_SetURL(s, hs1SniHostName);
+ } else {
+ SSL_SetURL(s, host);
+ }
+
+ /* Try to connect to the server */
+ status = PR_Connect(s, &addr, PR_INTERVAL_NO_TIMEOUT);
+ if (status != PR_SUCCESS) {
+ if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
+ if (verbose)
+ SECU_PrintError(progName, "connect");
+ milliPause(50 * multiplier);
+ pollset[SSOCK_FD].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ pollset[SSOCK_FD].out_flags = 0;
+ pollset[SSOCK_FD].fd = s;
+ while (1) {
+ FPRINTF(stderr,
+ "%s: about to call PR_Poll for connect completion!\n",
+ progName);
+ filesReady = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (filesReady < 0) {
+ SECU_PrintError(progName, "unable to connect (poll)");
+ error = 1;
+ goto done;
+ }
+ FPRINTF(stderr,
+ "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
+ progName, pollset[SSOCK_FD].out_flags);
+ if (filesReady == 0) { /* shouldn't happen! */
+ FPRINTF(stderr, "%s: PR_Poll returned zero!\n", progName);
+ error = 1;
+ goto done;
+ }
+ status = PR_GetConnectStatus(pollset);
+ if (status == PR_SUCCESS) {
+ break;
+ }
+ if (PR_GetError() != PR_IN_PROGRESS_ERROR) {
+ SECU_PrintError(progName, "unable to connect (poll)");
+ error = 1;
+ goto done;
+ }
+ SECU_PrintError(progName, "poll");
+ milliPause(50 * multiplier);
+ }
+ } else {
+ SECU_PrintError(progName, "unable to connect");
+ error = 1;
+ goto done;
+ }
+ }
+
+ pollset[SSOCK_FD].fd = s;
+ pollset[SSOCK_FD].in_flags = PR_POLL_EXCEPT |
+ (clientSpeaksFirst ? 0 : PR_POLL_READ);
+ pollset[STDIN_FD].fd = PR_GetSpecialFD(PR_StandardInput);
+ if (!requestStringInt) {
+ pollset[STDIN_FD].in_flags = PR_POLL_READ;
+ npds = 2;
+ } else {
+ npds = 1;
+ }
+ std_out = PR_GetSpecialFD(PR_StandardOutput);
+
+#if defined(WIN32) || defined(OS2)
+ /* PR_Poll cannot be used with stdin on Windows or OS/2. (sigh).
+ ** But use of PR_Poll and non-blocking sockets is a major feature
+ ** of this program. So, we simulate a pollable stdin with a
+ ** TCP socket pair and a thread that reads stdin and writes to
+ ** that socket pair.
+ */
+ {
+ PRFileDesc *fds[2];
+ PRThread *thread;
+
+ int nspr_rv = PR_NewTCPSocketPair(fds);
+ if (nspr_rv != PR_SUCCESS) {
+ SECU_PrintError(progName, "PR_NewTCPSocketPair failed");
+ error = 1;
+ goto done;
+ }
+ pollset[STDIN_FD].fd = fds[1];
+
+ thread = PR_CreateThread(PR_USER_THREAD, thread_main, fds[0],
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ if (!thread) {
+ SECU_PrintError(progName, "PR_CreateThread failed");
+ error = 1;
+ goto done;
+ }
+ }
+#endif
+
+ if (serverCertAuth.testFreshStatusFromSideChannel) {
+ SSL_ForceHandshake(s);
+ error = serverCertAuth.sideChannelRevocationTestResultCode;
+ goto done;
+ }
+
+ /*
+ ** Select on stdin and on the socket. Write data from stdin to
+ ** socket, read data from socket and write to stdout.
+ */
+ FPRINTF(stderr, "%s: ready...\n", progName);
+ while ((pollset[SSOCK_FD].in_flags | pollset[STDIN_FD].in_flags) ||
+ requestStringInt) {
+ char buf[4000]; /* buffer for stdin */
+ int nb; /* num bytes read from stdin. */
+
+ rv = restartHandshakeAfterServerCertIfNeeded(s, &serverCertAuth,
+ override);
+ if (rv != SECSuccess) {
+ error = EXIT_CODE_HANDSHAKE_FAILED;
+ SECU_PrintError(progName, "authentication of server cert failed");
+ goto done;
+ }
+
+ pollset[SSOCK_FD].out_flags = 0;
+ pollset[STDIN_FD].out_flags = 0;
+
+ FPRINTF(stderr, "%s: about to call PR_Poll !\n", progName);
+ filesReady = PR_Poll(pollset, npds, PR_INTERVAL_NO_TIMEOUT);
+ if (filesReady < 0) {
+ SECU_PrintError(progName, "select failed");
+ error = 1;
+ goto done;
+ }
+ if (filesReady == 0) { /* shouldn't happen! */
+ FPRINTF(stderr, "%s: PR_Poll returned zero!\n", progName);
+ error = 1;
+ goto done;
+ }
+ FPRINTF(stderr, "%s: PR_Poll returned!\n", progName);
+ if (pollset[STDIN_FD].in_flags) {
+ FPRINTF(stderr,
+ "%s: PR_Poll returned 0x%02x for stdin out_flags.\n",
+ progName, pollset[STDIN_FD].out_flags);
+ }
+ if (pollset[SSOCK_FD].in_flags) {
+ FPRINTF(stderr,
+ "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
+ progName, pollset[SSOCK_FD].out_flags);
+ }
+ if (requestStringInt) {
+ error = writeBytesToServer(s, pollset,
+ requestStringInt, requestStringLen);
+ if (error) {
+ goto done;
+ }
+ requestStringInt = NULL;
+ pollset[SSOCK_FD].in_flags = PR_POLL_READ;
+ }
+ if (pollset[STDIN_FD].out_flags & PR_POLL_READ) {
+ /* Read from stdin and write to socket */
+ nb = PR_Read(pollset[STDIN_FD].fd, buf, sizeof(buf));
+ FPRINTF(stderr, "%s: stdin read %d bytes\n", progName, nb);
+ if (nb < 0) {
+ if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
+ SECU_PrintError(progName, "read from stdin failed");
+ error = 1;
+ break;
+ }
+ } else if (nb == 0) {
+ /* EOF on stdin, stop polling stdin for read. */
+ pollset[STDIN_FD].in_flags = 0;
+ } else {
+ error = writeBytesToServer(s, pollset, buf, nb);
+ if (error) {
+ goto done;
+ }
+ pollset[SSOCK_FD].in_flags = PR_POLL_READ;
+ }
+ }
+
+ if (pollset[SSOCK_FD].in_flags) {
+ FPRINTF(stderr,
+ "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
+ progName, pollset[SSOCK_FD].out_flags);
+ }
+ if ((pollset[SSOCK_FD].out_flags & PR_POLL_READ) ||
+ (pollset[SSOCK_FD].out_flags & PR_POLL_ERR)
+#ifdef PR_POLL_HUP
+ || (pollset[SSOCK_FD].out_flags & PR_POLL_HUP)
+#endif
+ ) {
+ /* Read from socket and write to stdout */
+ nb = PR_Recv(pollset[SSOCK_FD].fd, buf, sizeof buf, 0, maxInterval);
+ FPRINTF(stderr, "%s: Read from server %d bytes\n", progName, nb);
+ if (nb < 0) {
+ if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
+ SECU_PrintError(progName, "read from socket failed");
+ error = 1;
+ goto done;
+ }
+ } else if (nb == 0) {
+ /* EOF from socket... stop polling socket for read */
+ pollset[SSOCK_FD].in_flags = 0;
+ } else {
+ if (skipProtoHeader != PR_TRUE || wrStarted == PR_TRUE) {
+ PR_Write(std_out, buf, nb);
+ } else {
+ separateReqHeader(std_out, buf, nb, &wrStarted,
+ &headerSeparatorPtrnId);
+ }
+ if (verbose)
+ fputs("\n\n", stderr);
+ }
+ }
+ milliPause(50 * multiplier);
+ }
+
+done:
+ if (s) {
+ PR_Close(s);
+ }
+
+ return error;
+}
+
+PRInt32
+ReadFile(const char *filename, char **data)
+{
+ char *ret = NULL;
+ char buf[8192];
+ unsigned int len = 0;
+ PRStatus rv;
+
+ PRFileDesc *fd = PR_Open(filename, PR_RDONLY, 0);
+ if (!fd)
+ return -1;
+
+ for (;;) {
+ rv = PR_Read(fd, buf, sizeof(buf));
+ if (rv < 0) {
+ PR_Free(ret);
+ return rv;
+ }
+
+ if (!rv)
+ break;
+
+ ret = PR_Realloc(ret, len + rv);
+ if (!ret) {
+ return -1;
+ }
+ PORT_Memcpy(ret + len, buf, rv);
+ len += rv;
+ }
+
+ *data = ret;
+ return len;
+}
+
+int
+main(int argc, char **argv)
{
- PRFileDesc * s;
- PRFileDesc * std_out;
- char * host = NULL;
- char * certDir = NULL;
- char * nickname = NULL;
- char * cipherString = NULL;
- char * tmp;
- int multiplier = 0;
- SECStatus rv;
- PRStatus status;
- PRInt32 filesReady;
- int npds;
- int override = 0;
- SSLVersionRange enabledVersions;
- PRBool enableSSL2 = PR_TRUE;
- int bypassPKCS11 = 0;
- int disableLocking = 0;
- int useExportPolicy = 0;
- int enableSessionTickets = 0;
- int enableCompression = 0;
- int enableFalseStart = 0;
- int enableCertStatus = 0;
- int forceFallbackSCSV = 0;
- int enableExtendedMasterSecret = 0;
- PRSocketOptionData opt;
- PRNetAddr addr;
- PRPollDesc pollset[2];
- PRBool allowIPv4 = PR_TRUE;
- PRBool allowIPv6 = PR_TRUE;
- PRBool pingServerFirst = PR_FALSE;
- int pingTimeoutSeconds = -1;
- PRBool clientSpeaksFirst = PR_FALSE;
- PRBool wrStarted = PR_FALSE;
- PRBool skipProtoHeader = PR_FALSE;
- ServerCertAuth serverCertAuth;
- int headerSeparatorPtrnId = 0;
- int error = 0;
- PRUint16 portno = 443;
- char * hs1SniHostName = NULL;
- char * hs2SniHostName = NULL;
PLOptState *optstate;
PLOptStatus optstatus;
+ PRStatus status;
PRStatus prStatus;
+ int error = 0;
+ char *tmp;
+ SECStatus rv;
+ char *certDir = NULL;
PRBool openDB = PR_TRUE;
PRBool loadDefaultRootCAs = PR_FALSE;
char *rootModule = NULL;
+ int numConnections = 1;
+ PRFileDesc *s = NULL;
serverCertAuth.shouldPause = PR_TRUE;
serverCertAuth.isPaused = PR_FALSE;
@@ -956,155 +1471,250 @@ int main(int argc, char **argv)
progName = strrchr(argv[0], '/');
if (!progName)
- progName = strrchr(argv[0], '\\');
- progName = progName ? progName+1 : argv[0];
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName + 1 : argv[0];
- tmp = PR_GetEnv("NSS_DEBUG_TIMEOUT");
+ tmp = PR_GetEnvSecure("NSS_DEBUG_TIMEOUT");
if (tmp && tmp[0]) {
- int sec = PORT_Atoi(tmp);
- if (sec > 0) {
- maxInterval = PR_SecondsToInterval(sec);
- }
+ int sec = PORT_Atoi(tmp);
+ if (sec > 0) {
+ maxInterval = PR_SecondsToInterval(sec);
+ }
}
SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions);
+ /* XXX: 'B' was used in the past but removed in 3.28,
+ * please leave some time before resuing it. */
optstate = PL_CreateOptState(argc, argv,
- "46BCDFGKM:OR:STV:W:Ya:bc:d:fgh:m:n:op:qr:st:uvw:xz");
+ "46A:CDFGHI:KL:M:OR:STUV:WYZa:bc:d:fgh:m:n:op:qr:st:uvw:z");
while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
- switch (optstate->option) {
- case '?':
- default : Usage(progName); break;
+ switch (optstate->option) {
+ case '?':
+ default:
+ Usage(progName);
+ break;
- case '4': allowIPv6 = PR_FALSE; if (!allowIPv4) Usage(progName); break;
- case '6': allowIPv4 = PR_FALSE; if (!allowIPv6) Usage(progName); break;
+ case '4':
+ allowIPv6 = PR_FALSE;
+ if (!allowIPv4)
+ Usage(progName);
+ break;
+ case '6':
+ allowIPv4 = PR_FALSE;
+ if (!allowIPv6)
+ Usage(progName);
+ break;
- case 'B': bypassPKCS11 = 1; break;
+ case 'A':
+ requestStringLen = ReadFile(optstate->value, &requestString);
+ if (requestStringLen < 0) {
+ fprintf(stderr, "Couldn't read file %s\n", optstate->value);
+ exit(1);
+ }
+ break;
- case 'C': ++dumpServerChain; break;
+ case 'C':
+ ++dumpServerChain;
+ break;
- case 'D': openDB = PR_FALSE; break;
+ case 'D':
+ openDB = PR_FALSE;
+ break;
- case 'F': if (serverCertAuth.testFreshStatusFromSideChannel) {
- /* parameter given twice or more */
- serverCertAuth.requireDataForIntermediates = PR_TRUE;
- }
- serverCertAuth.testFreshStatusFromSideChannel = PR_TRUE;
- break;
+ case 'F':
+ if (serverCertAuth.testFreshStatusFromSideChannel) {
+ /* parameter given twice or more */
+ serverCertAuth.requireDataForIntermediates = PR_TRUE;
+ }
+ serverCertAuth.testFreshStatusFromSideChannel = PR_TRUE;
+ break;
- case 'G': enableExtendedMasterSecret = PR_TRUE; break;
-
- case 'I': /* reserved for OCSP multi-stapling */ break;
-
- case 'O': serverCertAuth.shouldPause = PR_FALSE; break;
-
- case 'K': forceFallbackSCSV = PR_TRUE; break;
-
- case 'M': switch (atoi(optstate->value)) {
- case 1:
- serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
- serverCertAuth.allowCRLSideChannelData = PR_FALSE;
- break;
- case 2:
- serverCertAuth.allowOCSPSideChannelData = PR_FALSE;
- serverCertAuth.allowCRLSideChannelData = PR_TRUE;
- break;
- case 0:
- default:
- serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
- serverCertAuth.allowCRLSideChannelData = PR_TRUE;
- break;
- };
- break;
+ case 'G':
+ enableExtendedMasterSecret = PR_TRUE;
+ break;
- case 'R': rootModule = PORT_Strdup(optstate->value); break;
+ case 'H':
+ requireDHNamedGroups = PR_TRUE;
+ break;
- case 'S': skipProtoHeader = PR_TRUE; break;
+ case 'O':
+ serverCertAuth.shouldPause = PR_FALSE;
+ break;
- case 'T': enableCertStatus = 1; break;
+ case 'K':
+ forceFallbackSCSV = PR_TRUE;
+ break;
- case 'V': if (SECU_ParseSSLVersionRangeString(optstate->value,
- enabledVersions, enableSSL2,
- &enabledVersions, &enableSSL2) != SECSuccess) {
- Usage(progName);
- }
- break;
+ case 'L':
+ numConnections = atoi(optstate->value);
+ break;
- case 'Y': PrintCipherUsage(progName); exit(0); break;
+ case 'M':
+ switch (atoi(optstate->value)) {
+ case 1:
+ serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
+ serverCertAuth.allowCRLSideChannelData = PR_FALSE;
+ break;
+ case 2:
+ serverCertAuth.allowOCSPSideChannelData = PR_FALSE;
+ serverCertAuth.allowCRLSideChannelData = PR_TRUE;
+ break;
+ case 0:
+ default:
+ serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
+ serverCertAuth.allowCRLSideChannelData = PR_TRUE;
+ break;
+ };
+ break;
- case 'a': if (!hs1SniHostName) {
- hs1SniHostName = PORT_Strdup(optstate->value);
- } else if (!hs2SniHostName) {
- hs2SniHostName = PORT_Strdup(optstate->value);
- } else {
- Usage(progName);
- }
- break;
+ case 'R':
+ rootModule = PORT_Strdup(optstate->value);
+ break;
+
+ case 'S':
+ skipProtoHeader = PR_TRUE;
+ break;
+
+ case 'T':
+ enableCertStatus = 1;
+ break;
- case 'b': loadDefaultRootCAs = PR_TRUE; break;
+ case 'U':
+ enableSignedCertTimestamps = 1;
+ break;
- case 'c': cipherString = PORT_Strdup(optstate->value); break;
+ case 'V':
+ if (SECU_ParseSSLVersionRangeString(optstate->value,
+ enabledVersions, &enabledVersions) !=
+ SECSuccess) {
+ Usage(progName);
+ }
+ break;
- case 'g': enableFalseStart = 1; break;
+ case 'Y':
+ PrintCipherUsage(progName);
+ exit(0);
+ break;
- case 'd': certDir = PORT_Strdup(optstate->value); break;
+ case 'Z':
+ enableZeroRtt = PR_TRUE;
+ break;
- case 'f': clientSpeaksFirst = PR_TRUE; break;
+ case 'a':
+ if (!hs1SniHostName) {
+ hs1SniHostName = PORT_Strdup(optstate->value);
+ } else if (!hs2SniHostName) {
+ hs2SniHostName = PORT_Strdup(optstate->value);
+ } else {
+ Usage(progName);
+ }
+ break;
- case 'h': host = PORT_Strdup(optstate->value); break;
+ case 'b':
+ loadDefaultRootCAs = PR_TRUE;
+ break;
- case 'm':
- multiplier = atoi(optstate->value);
- if (multiplier < 0)
- multiplier = 0;
- break;
+ case 'c':
+ cipherString = PORT_Strdup(optstate->value);
+ break;
- case 'n': nickname = PORT_Strdup(optstate->value); break;
+ case 'g':
+ enableFalseStart = 1;
+ break;
- case 'o': override = 1; break;
+ case 'd':
+ certDir = PORT_Strdup(optstate->value);
+ break;
- case 'p': portno = (PRUint16)atoi(optstate->value); break;
+ case 'f':
+ clientSpeaksFirst = PR_TRUE;
+ break;
- case 'q': pingServerFirst = PR_TRUE; break;
+ case 'h':
+ host = PORT_Strdup(optstate->value);
+ break;
- case 's': disableLocking = 1; break;
-
- case 't': pingTimeoutSeconds = atoi(optstate->value); break;
+ case 'm':
+ multiplier = atoi(optstate->value);
+ if (multiplier < 0)
+ multiplier = 0;
+ break;
- case 'u': enableSessionTickets = PR_TRUE; break;
+ case 'n':
+ nickname = PORT_Strdup(optstate->value);
+ break;
- case 'v': verbose++; break;
+ case 'o':
+ override = 1;
+ break;
- case 'r': renegotiationsToDo = atoi(optstate->value); break;
+ case 'p':
+ portno = (PRUint16)atoi(optstate->value);
+ break;
- case 'w':
+ case 'q':
+ pingServerFirst = PR_TRUE;
+ break;
+
+ case 's':
+ disableLocking = 1;
+ break;
+
+ case 't':
+ pingTimeoutSeconds = atoi(optstate->value);
+ break;
+
+ case 'u':
+ enableSessionTickets = PR_TRUE;
+ break;
+
+ case 'v':
+ verbose++;
+ break;
+
+ case 'r':
+ renegotiationsToDo = atoi(optstate->value);
+ break;
+
+ case 'w':
pwdata.source = PW_PLAINTEXT;
- pwdata.data = PORT_Strdup(optstate->value);
- break;
+ pwdata.data = PORT_Strdup(optstate->value);
+ break;
- case 'W':
+ case 'W':
pwdata.source = PW_FROMFILE;
pwdata.data = PORT_Strdup(optstate->value);
break;
- case 'x': useExportPolicy = 1; break;
+ case 'z':
+ enableCompression = 1;
+ break;
- case 'z': enableCompression = 1; break;
- }
+ case 'I':
+ rv = parseGroupList(optstate->value, &enabledGroups, &enabledGroupsCount);
+ if (rv != SECSuccess) {
+ PL_DestroyOptState(optstate);
+ fprintf(stderr, "Bad group specified.\n");
+ Usage(progName);
+ }
+ break;
+ }
}
PL_DestroyOptState(optstate);
- if (optstatus == PL_OPT_BAD)
- Usage(progName);
+ if (optstatus == PL_OPT_BAD) {
+ Usage(progName);
+ }
if (!host || !portno) {
fprintf(stderr, "%s: parameters -h and -p are mandatory\n", progName);
- Usage(progName);
+ Usage(progName);
}
- if (serverCertAuth.testFreshStatusFromSideChannel
- && serverCertAuth.shouldPause) {
+ if (serverCertAuth.testFreshStatusFromSideChannel &&
+ serverCertAuth.shouldPause) {
fprintf(stderr, "%s: -F requires the use of -O\n", progName);
exit(1);
}
@@ -1119,527 +1729,146 @@ int main(int argc, char **argv)
exit(1);
}
- PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
PK11_SetPasswordFunc(SECU_GetModulePassword);
status = PR_StringToNetAddr(host, &addr);
if (status == PR_SUCCESS) {
- addr.inet.port = PR_htons(portno);
+ addr.inet.port = PR_htons(portno);
} else {
- /* Lookup host */
- PRAddrInfo *addrInfo;
- void *enumPtr = NULL;
-
- addrInfo = PR_GetAddrInfoByName(host, PR_AF_UNSPEC,
- PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME);
- if (!addrInfo) {
- SECU_PrintError(progName, "error looking up host");
- return 1;
- }
- for (;;) {
- enumPtr = PR_EnumerateAddrInfo(enumPtr, addrInfo, portno, &addr);
- if (enumPtr == NULL)
- break;
- if (addr.raw.family == PR_AF_INET && allowIPv4)
- break;
- if (addr.raw.family == PR_AF_INET6 && allowIPv6)
- break;
- }
- PR_FreeAddrInfo(addrInfo);
- if (enumPtr == NULL) {
- SECU_PrintError(progName, "error looking up host address");
- return 1;
- }
+ /* Lookup host */
+ PRAddrInfo *addrInfo;
+ void *enumPtr = NULL;
+
+ addrInfo = PR_GetAddrInfoByName(host, PR_AF_UNSPEC,
+ PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME);
+ if (!addrInfo) {
+ SECU_PrintError(progName, "error looking up host");
+ error = 1;
+ goto done;
+ }
+ for (;;) {
+ enumPtr = PR_EnumerateAddrInfo(enumPtr, addrInfo, portno, &addr);
+ if (enumPtr == NULL)
+ break;
+ if (addr.raw.family == PR_AF_INET && allowIPv4)
+ break;
+ if (addr.raw.family == PR_AF_INET6 && allowIPv6)
+ break;
+ }
+ PR_FreeAddrInfo(addrInfo);
+ if (enumPtr == NULL) {
+ SECU_PrintError(progName, "error looking up host address");
+ error = 1;
+ goto done;
+ }
}
printHostNameAndAddr(host, &addr);
+ if (!certDir) {
+ certDir = SECU_DefaultSSLDir(); /* Look in $SSL_DIR */
+ certDir = SECU_ConfigDirectory(certDir);
+ } else {
+ char *certDirTmp = certDir;
+ certDir = SECU_ConfigDirectory(certDirTmp);
+ PORT_Free(certDirTmp);
+ }
+
if (pingServerFirst) {
- int iter = 0;
- PRErrorCode err;
+ int iter = 0;
+ PRErrorCode err;
+
int max_attempts = MAX_WAIT_FOR_SERVER;
if (pingTimeoutSeconds >= 0) {
- /* If caller requested a timeout, let's try just twice. */
- max_attempts = 2;
+ /* If caller requested a timeout, let's try just twice. */
+ max_attempts = 2;
}
- do {
+ do {
PRIntervalTime timeoutInterval = PR_INTERVAL_NO_TIMEOUT;
- s = PR_OpenTCPSocket(addr.raw.family);
- if (s == NULL) {
- SECU_PrintError(progName, "Failed to create a TCP socket");
- }
- opt.option = PR_SockOpt_Nonblocking;
- opt.value.non_blocking = PR_FALSE;
- prStatus = PR_SetSocketOption(s, &opt);
- if (prStatus != PR_SUCCESS) {
- PR_Close(s);
- SECU_PrintError(progName,
- "Failed to set blocking socket option");
- return 1;
- }
+ s = PR_OpenTCPSocket(addr.raw.family);
+ if (s == NULL) {
+ SECU_PrintError(progName, "Failed to create a TCP socket");
+ error = 1;
+ goto done;
+ }
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ prStatus = PR_SetSocketOption(s, &opt);
+ if (prStatus != PR_SUCCESS) {
+ SECU_PrintError(progName,
+ "Failed to set blocking socket option");
+ error = 1;
+ goto done;
+ }
if (pingTimeoutSeconds >= 0) {
- timeoutInterval = PR_SecondsToInterval(pingTimeoutSeconds);
+ timeoutInterval = PR_SecondsToInterval(pingTimeoutSeconds);
+ }
+ prStatus = PR_Connect(s, &addr, timeoutInterval);
+ if (prStatus == PR_SUCCESS) {
+ PR_Shutdown(s, PR_SHUTDOWN_BOTH);
+ goto done;
}
- prStatus = PR_Connect(s, &addr, timeoutInterval);
- if (prStatus == PR_SUCCESS) {
- PR_Shutdown(s, PR_SHUTDOWN_BOTH);
- PR_Close(s);
- PR_Cleanup();
- return 0;
- }
- err = PR_GetError();
- if ((err != PR_CONNECT_REFUSED_ERROR) &&
- (err != PR_CONNECT_RESET_ERROR)) {
- SECU_PrintError(progName, "TCP Connection failed");
- return 1;
- }
- PR_Close(s);
- PR_Sleep(PR_MillisecondsToInterval(WAIT_INTERVAL));
- } while (++iter < max_attempts);
- SECU_PrintError(progName,
- "Client timed out while waiting for connection to server");
- return 1;
+ err = PR_GetError();
+ if ((err != PR_CONNECT_REFUSED_ERROR) &&
+ (err != PR_CONNECT_RESET_ERROR)) {
+ SECU_PrintError(progName, "TCP Connection failed");
+ error = 1;
+ goto done;
+ }
+ PR_Close(s);
+ s = NULL;
+ PR_Sleep(PR_MillisecondsToInterval(WAIT_INTERVAL));
+ } while (++iter < max_attempts);
+ SECU_PrintError(progName,
+ "Client timed out while waiting for connection to server");
+ error = 1;
+ goto done;
}
/* open the cert DB, the key DB, and the secmod DB. */
- if (!certDir) {
- certDir = SECU_DefaultSSLDir(); /* Look in $SSL_DIR */
- certDir = SECU_ConfigDirectory(certDir);
- } else {
- char *certDirTmp = certDir;
- certDir = SECU_ConfigDirectory(certDirTmp);
- PORT_Free(certDirTmp);
- }
-
if (openDB) {
- rv = NSS_Init(certDir);
- if (rv != SECSuccess) {
- SECU_PrintError(progName, "unable to open cert database");
- return 1;
- }
+ rv = NSS_Init(certDir);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "unable to open cert database");
+ error = 1;
+ goto done;
+ }
} else {
- rv = NSS_NoDB_Init(NULL);
- if (rv != SECSuccess) {
- SECU_PrintError(progName, "failed to initialize NSS");
- return 1;
- }
+ rv = NSS_NoDB_Init(NULL);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "failed to initialize NSS");
+ error = 1;
+ goto done;
+ }
}
if (loadDefaultRootCAs) {
- SECMOD_AddNewModule("Builtins",
- DLL_PREFIX"nssckbi."DLL_SUFFIX, 0, 0);
+ SECMOD_AddNewModule("Builtins",
+ DLL_PREFIX "nssckbi." DLL_SUFFIX, 0, 0);
} else if (rootModule) {
- SECMOD_AddNewModule("Builtins", rootModule, 0, 0);
+ SECMOD_AddNewModule("Builtins", rootModule, 0, 0);
}
- /* set the policy bits true for all the cipher suites. */
- if (useExportPolicy)
- NSS_SetExportPolicy();
- else
- NSS_SetDomesticPolicy();
-
- /* all the SSL2 and SSL3 cipher suites are enabled by default. */
+ /* all SSL3 cipher suites are enabled by default. */
if (cipherString) {
/* disable all the ciphers, then enable the ones we want. */
disableAllSSLCiphers();
}
- /* Create socket */
- s = PR_OpenTCPSocket(addr.raw.family);
- if (s == NULL) {
- SECU_PrintError(progName, "error creating socket");
- return 1;
- }
-
- opt.option = PR_SockOpt_Nonblocking;
- opt.value.non_blocking = PR_TRUE; /* default */
- if (serverCertAuth.testFreshStatusFromSideChannel) {
- opt.value.non_blocking = PR_FALSE;
- }
- PR_SetSocketOption(s, &opt);
- /*PR_SetSocketOption(PR_GetSpecialFD(PR_StandardInput), &opt);*/
-
- s = SSL_ImportFD(NULL, s);
- if (s == NULL) {
- SECU_PrintError(progName, "error importing socket");
- return 1;
- }
-
- rv = SSL_OptionSet(s, SSL_SECURITY, 1);
- if (rv != SECSuccess) {
- SECU_PrintError(progName, "error enabling socket");
- return 1;
- }
-
- rv = SSL_OptionSet(s, SSL_HANDSHAKE_AS_CLIENT, 1);
- if (rv != SECSuccess) {
- SECU_PrintError(progName, "error enabling client handshake");
- return 1;
- }
-
- /* all the SSL2 and SSL3 cipher suites are enabled by default. */
- if (cipherString) {
- char *cstringSaved = cipherString;
- int ndx;
-
- while (0 != (ndx = *cipherString++)) {
- int cipher;
-
- if (ndx == ':') {
- int ctmp = 0;
-
- cipher = 0;
- HEXCHAR_TO_INT(*cipherString, ctmp)
- cipher |= (ctmp << 12);
- cipherString++;
- HEXCHAR_TO_INT(*cipherString, ctmp)
- cipher |= (ctmp << 8);
- cipherString++;
- HEXCHAR_TO_INT(*cipherString, ctmp)
- cipher |= (ctmp << 4);
- cipherString++;
- HEXCHAR_TO_INT(*cipherString, ctmp)
- cipher |= ctmp;
- cipherString++;
- } else {
- const int *cptr;
-
- if (! isalpha(ndx))
- Usage(progName);
- cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
- for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; )
- /* do nothing */;
- }
- if (cipher > 0) {
- SECStatus status;
- status = SSL_CipherPrefSet(s, cipher, SSL_ALLOWED);
- if (status != SECSuccess)
- SECU_PrintError(progName, "SSL_CipherPrefSet()");
- } else {
- Usage(progName);
- }
- }
- PORT_Free(cstringSaved);
- }
-
- rv = SSL_VersionRangeSet(s, &enabledVersions);
- if (rv != SECSuccess) {
- SECU_PrintError(progName, "error setting SSL/TLS version range ");
- return 1;
- }
-
- rv = SSL_OptionSet(s, SSL_ENABLE_SSL2, enableSSL2);
- if (rv != SECSuccess) {
- SECU_PrintError(progName, "error enabling SSLv2 ");
- return 1;
- }
-
- rv = SSL_OptionSet(s, SSL_V2_COMPATIBLE_HELLO, enableSSL2);
- if (rv != SECSuccess) {
- SECU_PrintError(progName, "error enabling SSLv2 compatible hellos ");
- return 1;
- }
-
- /* enable PKCS11 bypass */
- rv = SSL_OptionSet(s, SSL_BYPASS_PKCS11, bypassPKCS11);
- if (rv != SECSuccess) {
- SECU_PrintError(progName, "error enabling PKCS11 bypass");
- return 1;
- }
-
- /* disable SSL socket locking */
- rv = SSL_OptionSet(s, SSL_NO_LOCKS, disableLocking);
- if (rv != SECSuccess) {
- SECU_PrintError(progName, "error disabling SSL socket locking");
- return 1;
- }
-
- /* enable Session Ticket extension. */
- rv = SSL_OptionSet(s, SSL_ENABLE_SESSION_TICKETS, enableSessionTickets);
- if (rv != SECSuccess) {
- SECU_PrintError(progName, "error enabling Session Ticket extension");
- return 1;
- }
-
- /* enable compression. */
- rv = SSL_OptionSet(s, SSL_ENABLE_DEFLATE, enableCompression);
- if (rv != SECSuccess) {
- SECU_PrintError(progName, "error enabling compression");
- return 1;
- }
-
- /* enable false start. */
- rv = SSL_OptionSet(s, SSL_ENABLE_FALSE_START, enableFalseStart);
- if (rv != SECSuccess) {
- SECU_PrintError(progName, "error enabling false start");
- return 1;
- }
-
- if (forceFallbackSCSV) {
- rv = SSL_OptionSet(s, SSL_ENABLE_FALLBACK_SCSV, PR_TRUE);
- if (rv != SECSuccess) {
- SECU_PrintError(progName, "error forcing fallback scsv");
- return 1;
+ while (numConnections--) {
+ error = run_client();
+ if (error) {
+ goto done;
}
}
- /* enable cert status (OCSP stapling). */
- rv = SSL_OptionSet(s, SSL_ENABLE_OCSP_STAPLING, enableCertStatus);
- if (rv != SECSuccess) {
- SECU_PrintError(progName, "error enabling cert status (OCSP stapling)");
- return 1;
+done:
+ if (s) {
+ PR_Close(s);
}
- /* enable extended master secret mode */
- if (enableExtendedMasterSecret) {
- rv = SSL_OptionSet(s, SSL_ENABLE_EXTENDED_MASTER_SECRET, PR_TRUE);
- if (rv != SECSuccess) {
- SECU_PrintError(progName, "error enabling extended master secret");
- return 1;
- }
- }
-
- SSL_SetPKCS11PinArg(s, &pwdata);
-
- serverCertAuth.dbHandle = CERT_GetDefaultCertDB();
-
- SSL_AuthCertificateHook(s, ownAuthCertificate, &serverCertAuth);
- if (override) {
- SSL_BadCertHook(s, ownBadCertHandler, NULL);
- }
- SSL_GetClientAuthDataHook(s, own_GetClientAuthData, (void *)nickname);
- SSL_HandshakeCallback(s, handshakeCallback, hs2SniHostName);
- if (hs1SniHostName) {
- SSL_SetURL(s, hs1SniHostName);
- } else {
- SSL_SetURL(s, host);
- }
-
- /* Try to connect to the server */
- status = PR_Connect(s, &addr, PR_INTERVAL_NO_TIMEOUT);
- if (status != PR_SUCCESS) {
- if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
- if (verbose)
- SECU_PrintError(progName, "connect");
- milliPause(50 * multiplier);
- pollset[SSOCK_FD].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
- pollset[SSOCK_FD].out_flags = 0;
- pollset[SSOCK_FD].fd = s;
- while(1) {
- FPRINTF(stderr,
- "%s: about to call PR_Poll for connect completion!\n",
- progName);
- filesReady = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT);
- if (filesReady < 0) {
- SECU_PrintError(progName, "unable to connect (poll)");
- return 1;
- }
- FPRINTF(stderr,
- "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
- progName, pollset[SSOCK_FD].out_flags);
- if (filesReady == 0) { /* shouldn't happen! */
- FPRINTF(stderr, "%s: PR_Poll returned zero!\n", progName);
- return 1;
- }
- status = PR_GetConnectStatus(pollset);
- if (status == PR_SUCCESS) {
- break;
- }
- if (PR_GetError() != PR_IN_PROGRESS_ERROR) {
- SECU_PrintError(progName, "unable to connect (poll)");
- return 1;
- }
- SECU_PrintError(progName, "poll");
- milliPause(50 * multiplier);
- }
- } else {
- SECU_PrintError(progName, "unable to connect");
- return 1;
- }
- }
-
- pollset[SSOCK_FD].fd = s;
- pollset[SSOCK_FD].in_flags = PR_POLL_EXCEPT |
- (clientSpeaksFirst ? 0 : PR_POLL_READ);
- pollset[STDIN_FD].fd = PR_GetSpecialFD(PR_StandardInput);
- pollset[STDIN_FD].in_flags = PR_POLL_READ;
- npds = 2;
- std_out = PR_GetSpecialFD(PR_StandardOutput);
-
-#if defined(WIN32) || defined(OS2)
- /* PR_Poll cannot be used with stdin on Windows or OS/2. (sigh).
- ** But use of PR_Poll and non-blocking sockets is a major feature
- ** of this program. So, we simulate a pollable stdin with a
- ** TCP socket pair and a thread that reads stdin and writes to
- ** that socket pair.
- */
- {
- PRFileDesc * fds[2];
- PRThread * thread;
-
- int nspr_rv = PR_NewTCPSocketPair(fds);
- if (nspr_rv != PR_SUCCESS) {
- SECU_PrintError(progName, "PR_NewTCPSocketPair failed");
- error = 1;
- goto done;
- }
- pollset[STDIN_FD].fd = fds[1];
-
- thread = PR_CreateThread(PR_USER_THREAD, thread_main, fds[0],
- PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
- PR_UNJOINABLE_THREAD, 0);
- if (!thread) {
- SECU_PrintError(progName, "PR_CreateThread failed");
- error = 1;
- goto done;
- }
- }
-#endif
-
- if (serverCertAuth.testFreshStatusFromSideChannel) {
- SSL_ForceHandshake(s);
- error = serverCertAuth.sideChannelRevocationTestResultCode;
- goto done;
- }
-
- /*
- ** Select on stdin and on the socket. Write data from stdin to
- ** socket, read data from socket and write to stdout.
- */
- FPRINTF(stderr, "%s: ready...\n", progName);
-
- while (pollset[SSOCK_FD].in_flags | pollset[STDIN_FD].in_flags) {
- char buf[4000]; /* buffer for stdin */
- int nb; /* num bytes read from stdin. */
-
- rv = restartHandshakeAfterServerCertIfNeeded(s, &serverCertAuth,
- override);
- if (rv != SECSuccess) {
- error = EXIT_CODE_HANDSHAKE_FAILED;
- SECU_PrintError(progName, "authentication of server cert failed");
- goto done;
- }
-
- pollset[SSOCK_FD].out_flags = 0;
- pollset[STDIN_FD].out_flags = 0;
-
- FPRINTF(stderr, "%s: about to call PR_Poll !\n", progName);
- filesReady = PR_Poll(pollset, npds, PR_INTERVAL_NO_TIMEOUT);
- if (filesReady < 0) {
- SECU_PrintError(progName, "select failed");
- error = 1;
- goto done;
- }
- if (filesReady == 0) { /* shouldn't happen! */
- FPRINTF(stderr, "%s: PR_Poll returned zero!\n", progName);
- return 1;
- }
- FPRINTF(stderr, "%s: PR_Poll returned!\n", progName);
- if (pollset[STDIN_FD].in_flags) {
- FPRINTF(stderr,
- "%s: PR_Poll returned 0x%02x for stdin out_flags.\n",
- progName, pollset[STDIN_FD].out_flags);
- }
- if (pollset[SSOCK_FD].in_flags) {
- FPRINTF(stderr,
- "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
- progName, pollset[SSOCK_FD].out_flags);
- }
- if (pollset[STDIN_FD].out_flags & PR_POLL_READ) {
- /* Read from stdin and write to socket */
- nb = PR_Read(pollset[STDIN_FD].fd, buf, sizeof(buf));
- FPRINTF(stderr, "%s: stdin read %d bytes\n", progName, nb);
- if (nb < 0) {
- if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
- SECU_PrintError(progName, "read from stdin failed");
- error = 1;
- break;
- }
- } else if (nb == 0) {
- /* EOF on stdin, stop polling stdin for read. */
- pollset[STDIN_FD].in_flags = 0;
- } else {
- char * bufp = buf;
- FPRINTF(stderr, "%s: Writing %d bytes to server\n",
- progName, nb);
- do {
- PRInt32 cc = PR_Send(s, bufp, nb, 0, maxInterval);
- if (cc < 0) {
- PRErrorCode err = PR_GetError();
- if (err != PR_WOULD_BLOCK_ERROR) {
- SECU_PrintError(progName,
- "write to SSL socket failed");
- error = 254;
- goto done;
- }
- cc = 0;
- }
- bufp += cc;
- nb -= cc;
- if (nb <= 0)
- break;
-
- rv = restartHandshakeAfterServerCertIfNeeded(s,
- &serverCertAuth, override);
- if (rv != SECSuccess) {
- error = EXIT_CODE_HANDSHAKE_FAILED;
- SECU_PrintError(progName, "authentication of server cert failed");
- goto done;
- }
-
- pollset[SSOCK_FD].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
- pollset[SSOCK_FD].out_flags = 0;
- FPRINTF(stderr,
- "%s: about to call PR_Poll on writable socket !\n",
- progName);
- cc = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT);
- FPRINTF(stderr,
- "%s: PR_Poll returned with writable socket !\n",
- progName);
- } while (1);
- pollset[SSOCK_FD].in_flags = PR_POLL_READ;
- }
- }
-
- if (pollset[SSOCK_FD].in_flags) {
- FPRINTF(stderr,
- "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
- progName, pollset[SSOCK_FD].out_flags);
- }
- if ( (pollset[SSOCK_FD].out_flags & PR_POLL_READ)
- || (pollset[SSOCK_FD].out_flags & PR_POLL_ERR)
-#ifdef PR_POLL_HUP
- || (pollset[SSOCK_FD].out_flags & PR_POLL_HUP)
-#endif
- ) {
- /* Read from socket and write to stdout */
- nb = PR_Recv(pollset[SSOCK_FD].fd, buf, sizeof buf, 0, maxInterval);
- FPRINTF(stderr, "%s: Read from server %d bytes\n", progName, nb);
- if (nb < 0) {
- if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
- SECU_PrintError(progName, "read from socket failed");
- error = 1;
- goto done;
- }
- } else if (nb == 0) {
- /* EOF from socket... stop polling socket for read */
- pollset[SSOCK_FD].in_flags = 0;
- } else {
- if (skipProtoHeader != PR_TRUE || wrStarted == PR_TRUE) {
- PR_Write(std_out, buf, nb);
- } else {
- separateReqHeader(std_out, buf, nb, &wrStarted,
- &headerSeparatorPtrnId);
- }
- if (verbose)
- fputs("\n\n", stderr);
- }
- }
- milliPause(50 * multiplier);
- }
-
- done:
if (hs1SniHostName) {
PORT_Free(hs1SniHostName);
}
@@ -1653,11 +1882,16 @@ int main(int argc, char **argv)
PORT_Free(pwdata.data);
}
PORT_Free(host);
+ PORT_Free(requestString);
- PR_Close(s);
- SSL_ClearSessionCache();
- if (NSS_Shutdown() != SECSuccess) {
- exit(1);
+ if (enabledGroups) {
+ PORT_Free(enabledGroups);
+ }
+ if (NSS_IsInitialized()) {
+ SSL_ClearSessionCache();
+ if (NSS_Shutdown() != SECSuccess) {
+ error = 1;
+ }
}
FPRINTF(stderr, "tstclnt: exiting with return code %d\n", error);