Index: cmd/strsclnt/strsclnt.c |
=================================================================== |
--- a/cmd/strsclnt/strsclnt.c |
+++ b/cmd/strsclnt/strsclnt.c |
@@ -37,1529 +37,1466 @@ |
#endif |
#ifndef PORT_Malloc |
#define PORT_Malloc PR_Malloc |
#endif |
#define RD_BUF_SIZE (60 * 1024) |
-/* Include these cipher suite arrays to re-use tstclnt's |
+/* Include these cipher suite arrays to re-use tstclnt's |
* cipher selection code. |
*/ |
-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 |
-}; |
+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}; |
-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 */ |
- 0 |
-}; |
+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 */ |
+ 0}; |
#define NO_FULLHS_PERCENTAGE -1 |
-/* This global string is so that client main can see |
- * which ciphers to use. |
+/* This global string is so that client main can see |
+ * which ciphers to use. |
*/ |
static const char *cipherString; |
static PRInt32 certsTested; |
static int MakeCertOK; |
static int NoReuse; |
static int fullhs = NO_FULLHS_PERCENTAGE; /* percentage of full handshakes to |
** perform */ |
static PRInt32 globalconid = 0; /* atomically set */ |
-static int total_connections; /* total number of connections to perform */ |
+static int total_connections; /* total number of connections to perform */ |
static int total_connections_rounded_down_to_hundreds; |
static int total_connections_modulo_100; |
static PRBool NoDelay; |
static PRBool QuitOnTimeout = PR_FALSE; |
static PRBool ThrottleUp = PR_FALSE; |
-static PRLock * threadLock; /* protects the global variables below */ |
+static PRLock *threadLock; /* protects the global variables below */ |
static PRTime lastConnectFailure; |
static PRTime lastConnectSuccess; |
static PRTime lastThrottleUp; |
-static PRInt32 remaining_connections; /* number of connections left */ |
-static int active_threads = 8; /* number of threads currently trying to |
- ** connect */ |
+static PRInt32 remaining_connections; /* number of connections left */ |
+static int active_threads = 8; /* number of threads currently trying to |
+ ** connect */ |
static PRInt32 numUsed; |
/* end of variables protected by threadLock */ |
-static SSL3Statistics * ssl3stats; |
+static SSL3Statistics *ssl3stats; |
static int failed_already = 0; |
static SSLVersionRange enabledVersions; |
-static PRBool enableSSL2 = PR_TRUE; |
-static PRBool bypassPKCS11 = PR_FALSE; |
-static PRBool disableLocking = PR_FALSE; |
-static PRBool ignoreErrors = PR_FALSE; |
+static PRBool enableSSL2 = PR_TRUE; |
+static PRBool bypassPKCS11 = PR_FALSE; |
+static PRBool disableLocking = PR_FALSE; |
+static PRBool ignoreErrors = PR_FALSE; |
static PRBool enableSessionTickets = PR_FALSE; |
-static PRBool enableCompression = PR_FALSE; |
-static PRBool enableFalseStart = PR_FALSE; |
-static PRBool enableCertStatus = PR_FALSE; |
+static PRBool enableCompression = PR_FALSE; |
+static PRBool enableFalseStart = PR_FALSE; |
+static PRBool enableCertStatus = PR_FALSE; |
-PRIntervalTime maxInterval = PR_INTERVAL_NO_TIMEOUT; |
+PRIntervalTime maxInterval = PR_INTERVAL_NO_TIMEOUT; |
-char * progName; |
+char *progName; |
-secuPWData pwdata = { PW_NONE, 0 }; |
+secuPWData pwdata = {PW_NONE, 0}; |
-int stopping; |
-int verbose; |
-SECItem bigBuf; |
+int stopping; |
+int verbose; |
+SECItem bigBuf; |
-#define PRINTF if (verbose) printf |
-#define FPRINTF if (verbose) fprintf |
+#define PRINTF \ |
+ if (verbose) printf |
+#define FPRINTF \ |
+ if (verbose) fprintf |
-static void |
-Usage(const char *progName) |
-{ |
- fprintf(stderr, |
- "Usage: %s [-n nickname] [-p port] [-d dbdir] [-c connections]\n" |
- " [-BDNovqs] [-f filename] [-N | -P percentage]\n" |
- " [-w dbpasswd] [-C cipher(s)] [-t threads] [-W pwfile]\n" |
- " [-V [min-version]:[max-version]] [-a sniHostName] hostname\n" |
- " where -v means verbose\n" |
- " -o flag is interpreted as follows:\n" |
- " 1 -o means override the result of server certificate validation.\n" |
- " 2 -o's mean skip server certificate validation altogether.\n" |
- " -D means no TCP delays\n" |
- " -q means quit when server gone (timeout rather than retry forever)\n" |
- " -s means disable SSL socket locking\n" |
- " -N means no session reuse\n" |
- " -P means do a specified percentage of full handshakes (0-100)\n" |
- " -V [min]:[max] restricts the set of enabled SSL/TLS protocols versions.\n" |
- " All versions are enabled by default.\n" |
- " Possible values for min/max: ssl2 ssl3 tls1.0 tls1.1 tls1.2\n" |
- " Example: \"-V ssl3:\" enables SSL 3 and newer.\n" |
- " -U means enable throttling up threads\n" |
- " -B bypasses the PKCS11 layer for SSL encryption and MACing\n" |
- " -T enable the cert_status extension (OCSP stapling)\n" |
- " -u enable TLS Session Ticket extension\n" |
- " -z enable compression\n" |
- " -g enable false start\n", |
- progName); |
- exit(1); |
+static void Usage(const char *progName) { |
+ fprintf( |
+ stderr, |
+ "Usage: %s [-n nickname] [-p port] [-d dbdir] [-c connections]\n" |
+ " [-BDNovqs] [-f filename] [-N | -P percentage]\n" |
+ " [-w dbpasswd] [-C cipher(s)] [-t threads] [-W pwfile]\n" |
+ " [-V [min-version]:[max-version]] [-a sniHostName] hostname\n" |
+ " where -v means verbose\n" |
+ " -o flag is interpreted as follows:\n" |
+ " 1 -o means override the result of server certificate " |
+ "validation.\n" |
+ " 2 -o's mean skip server certificate validation altogether.\n" |
+ " -D means no TCP delays\n" |
+ " -q means quit when server gone (timeout rather than retry " |
+ "forever)\n" |
+ " -s means disable SSL socket locking\n" |
+ " -N means no session reuse\n" |
+ " -P means do a specified percentage of full handshakes (0-100)\n" |
+ " -V [min]:[max] restricts the set of enabled SSL/TLS protocols " |
+ "versions.\n" |
+ " All versions are enabled by default.\n" |
+ " Possible values for min/max: ssl2 ssl3 tls1.0 tls1.1 tls1.2\n" |
+ " Example: \"-V ssl3:\" enables SSL 3 and newer.\n" |
+ " -U means enable throttling up threads\n" |
+ " -B bypasses the PKCS11 layer for SSL encryption and MACing\n" |
+ " -T enable the cert_status extension (OCSP stapling)\n" |
+ " -u enable TLS Session Ticket extension\n" |
+ " -z enable compression\n" |
+ " -g enable false start\n", |
+ progName); |
+ exit(1); |
} |
+static void errWarn(char *funcString) { |
+ PRErrorCode perr = PR_GetError(); |
+ PRInt32 oserr = PR_GetOSError(); |
+ const char *errString = SECU_Strerror(perr); |
-static void |
-errWarn(char * funcString) |
-{ |
- PRErrorCode perr = PR_GetError(); |
- PRInt32 oserr = PR_GetOSError(); |
- const char * errString = SECU_Strerror(perr); |
- |
- fprintf(stderr, "strsclnt: %s returned error %d, OS error %d: %s\n", |
- funcString, perr, oserr, errString); |
+ fprintf(stderr, "strsclnt: %s returned error %d, OS error %d: %s\n", |
+ funcString, perr, oserr, errString); |
} |
-static void |
-errExit(char * funcString) |
-{ |
- errWarn(funcString); |
- exit(1); |
+static void errExit(char *funcString) { |
+ errWarn(funcString); |
+ exit(1); |
} |
/************************************************************************** |
-** |
+** |
** Routines for disabling SSL ciphers. |
** |
**************************************************************************/ |
-void |
-disableAllSSLCiphers(void) |
-{ |
- const PRUint16 *cipherSuites = SSL_GetImplementedCiphers(); |
- int i = SSL_GetNumImplementedCiphers(); |
- SECStatus rv; |
+void disableAllSSLCiphers(void) { |
+ const PRUint16 *cipherSuites = SSL_GetImplementedCiphers(); |
+ int i = SSL_GetNumImplementedCiphers(); |
+ SECStatus rv; |
- /* disable all the SSL3 cipher suites */ |
- while (--i >= 0) { |
- PRUint16 suite = cipherSuites[i]; |
- rv = SSL_CipherPrefSetDefault(suite, PR_FALSE); |
- if (rv != SECSuccess) { |
- printf("SSL_CipherPrefSetDefault didn't like value 0x%04x (i = %d)\n", |
- suite, i); |
- errWarn("SSL_CipherPrefSetDefault"); |
- exit(2); |
- } |
+ /* disable all the SSL3 cipher suites */ |
+ while (--i >= 0) { |
+ PRUint16 suite = cipherSuites[i]; |
+ rv = SSL_CipherPrefSetDefault(suite, PR_FALSE); |
+ if (rv != SECSuccess) { |
+ printf("SSL_CipherPrefSetDefault didn't like value 0x%04x (i = %d)\n", |
+ suite, i); |
+ errWarn("SSL_CipherPrefSetDefault"); |
+ exit(2); |
} |
+ } |
} |
/* This invokes the "default" AuthCert handler in libssl. |
-** The only reason to use this one is that it prints out info as it goes. |
+** The only reason to use this one is that it prints out info as it goes. |
*/ |
-static SECStatus |
-mySSLAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, |
- PRBool isServer) |
-{ |
- SECStatus rv; |
- CERTCertificate * peerCert; |
- const SECItemArray *csa; |
+static SECStatus mySSLAuthCertificate(void *arg, PRFileDesc *fd, |
+ PRBool checkSig, PRBool isServer) { |
+ SECStatus rv; |
+ CERTCertificate *peerCert; |
+ const SECItemArray *csa; |
- if (MakeCertOK>=2) { |
- return SECSuccess; |
- } |
- peerCert = SSL_PeerCertificate(fd); |
+ if (MakeCertOK >= 2) { |
+ return SECSuccess; |
+ } |
+ peerCert = SSL_PeerCertificate(fd); |
- PRINTF("strsclnt: Subject: %s\nstrsclnt: Issuer : %s\n", |
- peerCert->subjectName, peerCert->issuerName); |
- csa = SSL_PeerStapledOCSPResponses(fd); |
- if (csa) { |
- PRINTF("Received %d Cert Status items (OCSP stapled data)\n", |
- csa->len); |
- } |
- /* invoke the "default" AuthCert handler. */ |
- rv = SSL_AuthCertificate(arg, fd, checkSig, isServer); |
+ PRINTF("strsclnt: Subject: %s\nstrsclnt: Issuer : %s\n", |
+ peerCert->subjectName, peerCert->issuerName); |
+ csa = SSL_PeerStapledOCSPResponses(fd); |
+ if (csa) { |
+ PRINTF("Received %d Cert Status items (OCSP stapled data)\n", csa->len); |
+ } |
+ /* invoke the "default" AuthCert handler. */ |
+ rv = SSL_AuthCertificate(arg, fd, checkSig, isServer); |
- PR_ATOMIC_INCREMENT(&certsTested); |
- if (rv == SECSuccess) { |
- fputs("strsclnt: -- SSL: Server Certificate Validated.\n", stderr); |
- } |
- CERT_DestroyCertificate(peerCert); |
- /* error, if any, will be displayed by the Bad Cert Handler. */ |
- return rv; |
+ PR_ATOMIC_INCREMENT(&certsTested); |
+ if (rv == SECSuccess) { |
+ fputs("strsclnt: -- SSL: Server Certificate Validated.\n", stderr); |
+ } |
+ CERT_DestroyCertificate(peerCert); |
+ /* error, if any, will be displayed by the Bad Cert Handler. */ |
+ return rv; |
} |
-static SECStatus |
-myBadCertHandler( void *arg, PRFileDesc *fd) |
-{ |
- PRErrorCode err = PR_GetError(); |
- if (!MakeCertOK) |
- fprintf(stderr, |
- "strsclnt: -- SSL: Server Certificate Invalid, err %d.\n%s\n", |
- err, SECU_Strerror(err)); |
- return (MakeCertOK ? SECSuccess : SECFailure); |
+static SECStatus myBadCertHandler(void *arg, PRFileDesc *fd) { |
+ PRErrorCode err = PR_GetError(); |
+ if (!MakeCertOK) |
+ fprintf(stderr, |
+ "strsclnt: -- SSL: Server Certificate Invalid, err %d.\n%s\n", err, |
+ SECU_Strerror(err)); |
+ return (MakeCertOK ? SECSuccess : SECFailure); |
} |
-void |
-printSecurityInfo(PRFileDesc *fd) |
-{ |
- CERTCertificate * cert = NULL; |
- SSL3Statistics * ssl3stats = SSL_GetStatistics(); |
- SECStatus result; |
- SSLChannelInfo channel; |
- SSLCipherSuiteInfo suite; |
+void printSecurityInfo(PRFileDesc *fd) { |
+ CERTCertificate *cert = NULL; |
+ SSL3Statistics *ssl3stats = SSL_GetStatistics(); |
+ SECStatus result; |
+ SSLChannelInfo channel; |
+ SSLCipherSuiteInfo suite; |
- static int only_once; |
+ static int only_once; |
- if (only_once && verbose < 2) |
- return; |
- only_once = 1; |
+ if (only_once && verbose < 2) return; |
+ only_once = 1; |
- 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, |
- "strsclnt: 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, |
- "strsclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n" |
- " Compression: %s\n", |
- channel.authKeyBits, suite.authAlgorithmName, |
- channel.keaKeyBits, suite.keaTypeName, |
- channel.compressionMethodName); |
- } |
+ 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, |
+ "strsclnt: 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, |
+ "strsclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n" |
+ " Compression: %s\n", |
+ channel.authKeyBits, suite.authAlgorithmName, channel.keaKeyBits, |
+ suite.keaTypeName, channel.compressionMethodName); |
} |
+ } |
- cert = SSL_LocalCertificate(fd); |
- if (!cert) |
- cert = SSL_PeerCertificate(fd); |
+ cert = SSL_LocalCertificate(fd); |
+ if (!cert) cert = SSL_PeerCertificate(fd); |
- if (verbose && cert) { |
- char * ip = CERT_NameToAscii(&cert->issuer); |
- char * sp = CERT_NameToAscii(&cert->subject); |
- if (sp) { |
- fprintf(stderr, "strsclnt: subject DN: %s\n", sp); |
- PORT_Free(sp); |
- } |
- if (ip) { |
- fprintf(stderr, "strsclnt: issuer DN: %s\n", ip); |
- PORT_Free(ip); |
- } |
+ if (verbose && cert) { |
+ char *ip = CERT_NameToAscii(&cert->issuer); |
+ char *sp = CERT_NameToAscii(&cert->subject); |
+ if (sp) { |
+ fprintf(stderr, "strsclnt: subject DN: %s\n", sp); |
+ PORT_Free(sp); |
} |
- if (cert) { |
- CERT_DestroyCertificate(cert); |
- cert = NULL; |
+ if (ip) { |
+ fprintf(stderr, "strsclnt: issuer DN: %s\n", ip); |
+ PORT_Free(ip); |
} |
- fprintf(stderr, |
- "strsclnt: %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); |
- |
+ } |
+ if (cert) { |
+ CERT_DestroyCertificate(cert); |
+ cert = NULL; |
+ } |
+ fprintf(stderr, |
+ "strsclnt: %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); |
} |
/************************************************************************** |
** Begin thread management routines and data. |
**************************************************************************/ |
#define MAX_THREADS 128 |
typedef int startFn(void *a, void *b, int c); |
- |
-static PRInt32 numConnected; |
-static int max_threads; /* peak threads allowed */ |
+static PRInt32 numConnected; |
+static int max_threads; /* peak threads allowed */ |
typedef struct perThreadStr { |
- void * a; |
- void * b; |
- int tid; |
- int rv; |
- startFn * startFunc; |
- PRThread * prThread; |
- PRBool inUse; |
+ void *a; |
+ void *b; |
+ int tid; |
+ int rv; |
+ startFn *startFunc; |
+ PRThread *prThread; |
+ PRBool inUse; |
} perThread; |
perThread threads[MAX_THREADS]; |
-void |
-thread_wrapper(void * arg) |
-{ |
- perThread * slot = (perThread *)arg; |
- PRBool done = PR_FALSE; |
+void thread_wrapper(void *arg) { |
+ perThread *slot = (perThread *)arg; |
+ PRBool done = PR_FALSE; |
- do { |
- PRBool doop = PR_FALSE; |
- PRBool dosleep = PR_FALSE; |
- PRTime now = PR_Now(); |
+ do { |
+ PRBool doop = PR_FALSE; |
+ PRBool dosleep = PR_FALSE; |
+ PRTime now = PR_Now(); |
- PR_Lock(threadLock); |
- if (! (slot->tid < active_threads)) { |
- /* this thread isn't supposed to be running */ |
- if (!ThrottleUp) { |
- /* we'll never need this thread again, so abort it */ |
- done = PR_TRUE; |
- } else if (remaining_connections > 0) { |
- /* we may still need this thread, so just sleep for 1s */ |
- dosleep = PR_TRUE; |
- /* the conditions to trigger a throttle up are : |
- ** 1. last PR_Connect failure must have happened more than |
- ** 10s ago |
- ** 2. last throttling up must have happened more than 0.5s ago |
- ** 3. there must be a more recent PR_Connect success than |
- ** failure |
- */ |
- if ( (now - lastConnectFailure > 10 * PR_USEC_PER_SEC) && |
- ( (!lastThrottleUp) || ( (now - lastThrottleUp) >= |
- (PR_USEC_PER_SEC/2)) ) && |
- (lastConnectSuccess > lastConnectFailure) ) { |
- /* try throttling up by one thread */ |
- active_threads = PR_MIN(max_threads, active_threads+1); |
- fprintf(stderr,"active_threads set up to %d\n", |
- active_threads); |
- lastThrottleUp = PR_MAX(now, lastThrottleUp); |
- } |
- } else { |
- /* no more connections left, we are done */ |
- done = PR_TRUE; |
- } |
- } else { |
- /* this thread should run */ |
- if (--remaining_connections >= 0) { /* protected by threadLock */ |
- doop = PR_TRUE; |
- } else { |
- done = PR_TRUE; |
- } |
+ PR_Lock(threadLock); |
+ if (!(slot->tid < active_threads)) { |
+ /* this thread isn't supposed to be running */ |
+ if (!ThrottleUp) { |
+ /* we'll never need this thread again, so abort it */ |
+ done = PR_TRUE; |
+ } else if (remaining_connections > 0) { |
+ /* we may still need this thread, so just sleep for 1s */ |
+ dosleep = PR_TRUE; |
+ /* the conditions to trigger a throttle up are : |
+ ** 1. last PR_Connect failure must have happened more than |
+ ** 10s ago |
+ ** 2. last throttling up must have happened more than 0.5s ago |
+ ** 3. there must be a more recent PR_Connect success than |
+ ** failure |
+ */ |
+ if ((now - lastConnectFailure > 10 * PR_USEC_PER_SEC) && |
+ ((!lastThrottleUp) || |
+ ((now - lastThrottleUp) >= (PR_USEC_PER_SEC / 2))) && |
+ (lastConnectSuccess > lastConnectFailure)) { |
+ /* try throttling up by one thread */ |
+ active_threads = PR_MIN(max_threads, active_threads + 1); |
+ fprintf(stderr, "active_threads set up to %d\n", active_threads); |
+ lastThrottleUp = PR_MAX(now, lastThrottleUp); |
} |
- PR_Unlock(threadLock); |
- if (doop) { |
- slot->rv = (* slot->startFunc)(slot->a, slot->b, slot->tid); |
- PRINTF("strsclnt: Thread in slot %d returned %d\n", |
- slot->tid, slot->rv); |
- } |
- if (dosleep) { |
- PR_Sleep(PR_SecondsToInterval(1)); |
- } |
- } while (!done && (!failed_already || ignoreErrors)); |
+ } else { |
+ /* no more connections left, we are done */ |
+ done = PR_TRUE; |
+ } |
+ } else { |
+ /* this thread should run */ |
+ if (--remaining_connections >= 0) {/* protected by threadLock */ |
+ doop = PR_TRUE; |
+ } else { |
+ done = PR_TRUE; |
+ } |
+ } |
+ PR_Unlock(threadLock); |
+ if (doop) { |
+ slot->rv = (*slot->startFunc)(slot->a, slot->b, slot->tid); |
+ PRINTF("strsclnt: Thread in slot %d returned %d\n", slot->tid, slot->rv); |
+ } |
+ if (dosleep) { |
+ PR_Sleep(PR_SecondsToInterval(1)); |
+ } |
+ } while (!done && (!failed_already || ignoreErrors)); |
} |
-SECStatus |
-launch_thread( |
- startFn * startFunc, |
- void * a, |
- void * b, |
- int tid) |
-{ |
- PRUint32 i; |
- perThread * slot; |
+SECStatus launch_thread(startFn *startFunc, void *a, void *b, int tid) { |
+ PRUint32 i; |
+ perThread *slot; |
- PR_Lock(threadLock); |
+ PR_Lock(threadLock); |
- PORT_Assert(numUsed < MAX_THREADS); |
- if (! (numUsed < MAX_THREADS)) { |
- PR_Unlock(threadLock); |
- return SECFailure; |
- } |
+ PORT_Assert(numUsed < MAX_THREADS); |
+ if (!(numUsed < MAX_THREADS)) { |
+ PR_Unlock(threadLock); |
+ return SECFailure; |
+ } |
- i = numUsed++; |
- slot = &threads[i]; |
- slot->a = a; |
- slot->b = b; |
- slot->tid = tid; |
+ i = numUsed++; |
+ slot = &threads[i]; |
+ slot->a = a; |
+ slot->b = b; |
+ slot->tid = tid; |
- slot->startFunc = startFunc; |
+ slot->startFunc = startFunc; |
- slot->prThread = PR_CreateThread(PR_USER_THREAD, |
- thread_wrapper, slot, |
- PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, |
- PR_JOINABLE_THREAD, 0); |
- if (slot->prThread == NULL) { |
- PR_Unlock(threadLock); |
- printf("strsclnt: Failed to launch thread!\n"); |
- return SECFailure; |
- } |
+ slot->prThread = |
+ PR_CreateThread(PR_USER_THREAD, thread_wrapper, slot, PR_PRIORITY_NORMAL, |
+ PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); |
+ if (slot->prThread == NULL) { |
+ PR_Unlock(threadLock); |
+ printf("strsclnt: Failed to launch thread!\n"); |
+ return SECFailure; |
+ } |
- slot->inUse = 1; |
- PR_Unlock(threadLock); |
- PRINTF("strsclnt: Launched thread in slot %d \n", i); |
+ slot->inUse = 1; |
+ PR_Unlock(threadLock); |
+ PRINTF("strsclnt: Launched thread in slot %d \n", i); |
- return SECSuccess; |
+ return SECSuccess; |
} |
/* join all the threads */ |
-int |
-reap_threads(void) |
-{ |
- int i; |
+int reap_threads(void) { |
+ int i; |
- for (i = 0; i < MAX_THREADS; ++i) { |
- if (threads[i].prThread) { |
- PR_JoinThread(threads[i].prThread); |
- threads[i].prThread = NULL; |
- } |
+ for (i = 0; i < MAX_THREADS; ++i) { |
+ if (threads[i].prThread) { |
+ PR_JoinThread(threads[i].prThread); |
+ threads[i].prThread = NULL; |
} |
- return 0; |
+ } |
+ return 0; |
} |
-void |
-destroy_thread_data(void) |
-{ |
- PORT_Memset(threads, 0, sizeof threads); |
+void destroy_thread_data(void) { |
+ PORT_Memset(threads, 0, sizeof threads); |
- if (threadLock) { |
- PR_DestroyLock(threadLock); |
- threadLock = NULL; |
- } |
+ if (threadLock) { |
+ PR_DestroyLock(threadLock); |
+ threadLock = NULL; |
+ } |
} |
-void |
-init_thread_data(void) |
-{ |
- threadLock = PR_NewLock(); |
-} |
+void init_thread_data(void) { threadLock = PR_NewLock(); } |
/************************************************************************** |
** End thread management routines. |
**************************************************************************/ |
PRBool useModelSocket = PR_TRUE; |
-static const char stopCmd[] = { "GET /stop " }; |
+static const char stopCmd[] = {"GET /stop "}; |
static const char outHeader[] = { |
"HTTP/1.0 200 OK\r\n" |
"Server: Netscape-Enterprise/2.0a\r\n" |
"Date: Tue, 26 Aug 1997 22:10:05 GMT\r\n" |
"Content-type: text/plain\r\n" |
- "\r\n" |
-}; |
+ "\r\n"}; |
struct lockedVarsStr { |
- PRLock * lock; |
- int count; |
- int waiters; |
- PRCondVar * condVar; |
+ PRLock *lock; |
+ int count; |
+ int waiters; |
+ PRCondVar *condVar; |
}; |
typedef struct lockedVarsStr lockedVars; |
-void |
-lockedVars_Init( lockedVars * lv) |
-{ |
- lv->count = 0; |
- lv->waiters = 0; |
- lv->lock = PR_NewLock(); |
- lv->condVar = PR_NewCondVar(lv->lock); |
+void lockedVars_Init(lockedVars *lv) { |
+ lv->count = 0; |
+ lv->waiters = 0; |
+ lv->lock = PR_NewLock(); |
+ lv->condVar = PR_NewCondVar(lv->lock); |
} |
-void |
-lockedVars_Destroy( lockedVars * lv) |
-{ |
- PR_DestroyCondVar(lv->condVar); |
- lv->condVar = NULL; |
+void lockedVars_Destroy(lockedVars *lv) { |
+ PR_DestroyCondVar(lv->condVar); |
+ lv->condVar = NULL; |
- PR_DestroyLock(lv->lock); |
- lv->lock = NULL; |
+ PR_DestroyLock(lv->lock); |
+ lv->lock = NULL; |
} |
-void |
-lockedVars_WaitForDone(lockedVars * lv) |
-{ |
- PR_Lock(lv->lock); |
- while (lv->count > 0) { |
- PR_WaitCondVar(lv->condVar, PR_INTERVAL_NO_TIMEOUT); |
- } |
- PR_Unlock(lv->lock); |
+void lockedVars_WaitForDone(lockedVars *lv) { |
+ PR_Lock(lv->lock); |
+ while (lv->count > 0) { |
+ PR_WaitCondVar(lv->condVar, PR_INTERVAL_NO_TIMEOUT); |
+ } |
+ PR_Unlock(lv->lock); |
} |
-int /* returns count */ |
-lockedVars_AddToCount(lockedVars * lv, int addend) |
-{ |
- int rv; |
+int /* returns count */ |
+ lockedVars_AddToCount(lockedVars *lv, int addend) { |
+ int rv; |
- PR_Lock(lv->lock); |
- rv = lv->count += addend; |
- if (rv <= 0) { |
- PR_NotifyCondVar(lv->condVar); |
- } |
- PR_Unlock(lv->lock); |
- return rv; |
+ PR_Lock(lv->lock); |
+ rv = lv->count += addend; |
+ if (rv <= 0) { |
+ PR_NotifyCondVar(lv->condVar); |
+ } |
+ PR_Unlock(lv->lock); |
+ return rv; |
} |
-int |
-do_writes( |
- void * a, |
- void * b, |
- int c) |
-{ |
- PRFileDesc * ssl_sock = (PRFileDesc *)a; |
- lockedVars * lv = (lockedVars *)b; |
- int sent = 0; |
- int count = 0; |
+int do_writes(void *a, void *b, int c) { |
+ PRFileDesc *ssl_sock = (PRFileDesc *)a; |
+ lockedVars *lv = (lockedVars *)b; |
+ int sent = 0; |
+ int count = 0; |
- while (sent < bigBuf.len) { |
+ while (sent < bigBuf.len) { |
- count = PR_Send(ssl_sock, bigBuf.data + sent, bigBuf.len - sent, |
- 0, maxInterval); |
- if (count < 0) { |
- errWarn("PR_Send bigBuf"); |
- break; |
- } |
- FPRINTF(stderr, "strsclnt: PR_Send wrote %d bytes from bigBuf\n", |
- count ); |
- sent += count; |
+ count = PR_Send(ssl_sock, bigBuf.data + sent, bigBuf.len - sent, 0, |
+ maxInterval); |
+ if (count < 0) { |
+ errWarn("PR_Send bigBuf"); |
+ break; |
} |
- if (count >= 0) { /* last write didn't fail. */ |
- PR_Shutdown(ssl_sock, PR_SHUTDOWN_SEND); |
+ FPRINTF(stderr, "strsclnt: PR_Send wrote %d bytes from bigBuf\n", count); |
+ sent += count; |
+ } |
+ if (count >= 0) {/* last write didn't fail. */ |
+ PR_Shutdown(ssl_sock, PR_SHUTDOWN_SEND); |
+ } |
+ |
+ /* notify the reader that we're done. */ |
+ lockedVars_AddToCount(lv, -1); |
+ return (sent < bigBuf.len) ? SECFailure : SECSuccess; |
+} |
+ |
+int handle_fdx_connection(PRFileDesc *ssl_sock, int connection) { |
+ SECStatus result; |
+ int firstTime = 1; |
+ int countRead = 0; |
+ lockedVars lv; |
+ char *buf; |
+ |
+ lockedVars_Init(&lv); |
+ lockedVars_AddToCount(&lv, 1); |
+ |
+ /* Attempt to launch the writer thread. */ |
+ result = launch_thread(do_writes, ssl_sock, &lv, connection); |
+ |
+ if (result != SECSuccess) goto cleanup; |
+ |
+ buf = PR_Malloc(RD_BUF_SIZE); |
+ |
+ if (buf) { |
+ do { |
+ /* do reads here. */ |
+ PRInt32 count; |
+ |
+ count = PR_Recv(ssl_sock, buf, RD_BUF_SIZE, 0, maxInterval); |
+ if (count < 0) { |
+ errWarn("PR_Recv"); |
+ break; |
+ } |
+ countRead += count; |
+ FPRINTF(stderr, "strsclnt: connection %d read %d bytes (%d total).\n", |
+ connection, count, countRead); |
+ if (firstTime) { |
+ firstTime = 0; |
+ printSecurityInfo(ssl_sock); |
+ } |
+ } while (lockedVars_AddToCount(&lv, 0) > 0); |
+ PR_Free(buf); |
+ buf = 0; |
+ } |
+ |
+ /* Wait for writer to finish */ |
+ lockedVars_WaitForDone(&lv); |
+ lockedVars_Destroy(&lv); |
+ |
+ FPRINTF( |
+ stderr, |
+ "strsclnt: connection %d read %d bytes total. -----------------------\n", |
+ connection, countRead); |
+ |
+cleanup: |
+ /* Caller closes the socket. */ |
+ |
+ return SECSuccess; |
+} |
+ |
+const char request[] = {"GET /abc HTTP/1.0\r\n\r\n"}; |
+ |
+SECStatus handle_connection(PRFileDesc *ssl_sock, int tid) { |
+ int countRead = 0; |
+ PRInt32 rv; |
+ char *buf; |
+ |
+ buf = PR_Malloc(RD_BUF_SIZE); |
+ if (!buf) return SECFailure; |
+ |
+ /* compose the http request here. */ |
+ |
+ rv = PR_Send(ssl_sock, request, strlen(request), 0, maxInterval); |
+ if (rv <= 0) { |
+ errWarn("PR_Send"); |
+ PR_Free(buf); |
+ buf = 0; |
+ failed_already = 1; |
+ return SECFailure; |
+ } |
+ printSecurityInfo(ssl_sock); |
+ |
+ /* read until EOF */ |
+ while (1) { |
+ rv = PR_Recv(ssl_sock, buf, RD_BUF_SIZE, 0, maxInterval); |
+ if (rv == 0) { |
+ break; /* EOF */ |
+ } |
+ if (rv < 0) { |
+ errWarn("PR_Recv"); |
+ failed_already = 1; |
+ break; |
} |
- /* notify the reader that we're done. */ |
- lockedVars_AddToCount(lv, -1); |
- return (sent < bigBuf.len) ? SECFailure : SECSuccess; |
-} |
+ countRead += rv; |
+ FPRINTF(stderr, |
+ "strsclnt: connection on thread %d read %d bytes (%d total).\n", |
+ tid, rv, countRead); |
+ } |
+ PR_Free(buf); |
+ buf = 0; |
-int |
-handle_fdx_connection( PRFileDesc * ssl_sock, int connection) |
-{ |
- SECStatus result; |
- int firstTime = 1; |
- int countRead = 0; |
- lockedVars lv; |
- char *buf; |
+ /* Caller closes the socket. */ |
+ FPRINTF(stderr, |
+ "strsclnt: connection on thread %d read %d bytes total. ---------\n", |
+ tid, countRead); |
- lockedVars_Init(&lv); |
- lockedVars_AddToCount(&lv, 1); |
- |
- /* Attempt to launch the writer thread. */ |
- result = launch_thread(do_writes, ssl_sock, &lv, connection); |
- |
- if (result != SECSuccess) |
- goto cleanup; |
- |
- buf = PR_Malloc(RD_BUF_SIZE); |
- |
- if (buf) { |
- do { |
- /* do reads here. */ |
- PRInt32 count; |
- |
- count = PR_Recv(ssl_sock, buf, RD_BUF_SIZE, 0, maxInterval); |
- if (count < 0) { |
- errWarn("PR_Recv"); |
- break; |
- } |
- countRead += count; |
- FPRINTF(stderr, |
- "strsclnt: connection %d read %d bytes (%d total).\n", |
- connection, count, countRead ); |
- if (firstTime) { |
- firstTime = 0; |
- printSecurityInfo(ssl_sock); |
- } |
- } while (lockedVars_AddToCount(&lv, 0) > 0); |
- PR_Free(buf); |
- buf = 0; |
- } |
- |
- /* Wait for writer to finish */ |
- lockedVars_WaitForDone(&lv); |
- lockedVars_Destroy(&lv); |
- |
- FPRINTF(stderr, |
- "strsclnt: connection %d read %d bytes total. -----------------------\n", |
- connection, countRead); |
- |
-cleanup: |
- /* Caller closes the socket. */ |
- |
- return SECSuccess; |
-} |
- |
-const char request[] = {"GET /abc HTTP/1.0\r\n\r\n" }; |
- |
-SECStatus |
-handle_connection( PRFileDesc *ssl_sock, int tid) |
-{ |
- int countRead = 0; |
- PRInt32 rv; |
- char *buf; |
- |
- buf = PR_Malloc(RD_BUF_SIZE); |
- if (!buf) |
- return SECFailure; |
- |
- /* compose the http request here. */ |
- |
- rv = PR_Send(ssl_sock, request, strlen(request), 0, maxInterval); |
- if (rv <= 0) { |
- errWarn("PR_Send"); |
- PR_Free(buf); |
- buf = 0; |
- failed_already = 1; |
- return SECFailure; |
- } |
- printSecurityInfo(ssl_sock); |
- |
- /* read until EOF */ |
- while (1) { |
- rv = PR_Recv(ssl_sock, buf, RD_BUF_SIZE, 0, maxInterval); |
- if (rv == 0) { |
- break; /* EOF */ |
- } |
- if (rv < 0) { |
- errWarn("PR_Recv"); |
- failed_already = 1; |
- break; |
- } |
- |
- countRead += rv; |
- FPRINTF(stderr, |
- "strsclnt: connection on thread %d read %d bytes (%d total).\n", |
- tid, rv, countRead ); |
- } |
- PR_Free(buf); |
- buf = 0; |
- |
- /* Caller closes the socket. */ |
- |
- FPRINTF(stderr, |
- "strsclnt: connection on thread %d read %d bytes total. ---------\n", |
- tid, countRead); |
- |
- return SECSuccess; /* success */ |
+ return SECSuccess; /* success */ |
} |
#define USE_SOCK_PEER_ID 1 |
#ifdef USE_SOCK_PEER_ID |
PRInt32 lastFullHandshakePeerID; |
-void |
-myHandshakeCallback(PRFileDesc *socket, void *arg) |
-{ |
- PR_ATOMIC_SET(&lastFullHandshakePeerID, (PRInt32) arg); |
+void myHandshakeCallback(PRFileDesc *socket, void *arg) { |
+ PR_ATOMIC_SET(&lastFullHandshakePeerID, (PRInt32)arg); |
} |
#endif |
/* one copy of this function is launched in a separate thread for each |
** connection to be made. |
*/ |
-int |
-do_connects( |
- void * a, |
- void * b, |
- int tid) |
-{ |
- PRNetAddr * addr = (PRNetAddr *) a; |
- PRFileDesc * model_sock = (PRFileDesc *) b; |
- PRFileDesc * ssl_sock = 0; |
- PRFileDesc * tcp_sock = 0; |
- PRStatus prStatus; |
- PRUint32 sleepInterval = 50; /* milliseconds */ |
- SECStatus result; |
- int rv = SECSuccess; |
- PRSocketOptionData opt; |
+int do_connects(void *a, void *b, int tid) { |
+ PRNetAddr *addr = (PRNetAddr *)a; |
+ PRFileDesc *model_sock = (PRFileDesc *)b; |
+ PRFileDesc *ssl_sock = 0; |
+ PRFileDesc *tcp_sock = 0; |
+ PRStatus prStatus; |
+ PRUint32 sleepInterval = 50; /* milliseconds */ |
+ SECStatus result; |
+ int rv = SECSuccess; |
+ PRSocketOptionData opt; |
retry: |
- tcp_sock = PR_OpenTCPSocket(addr->raw.family); |
- if (tcp_sock == NULL) { |
- errExit("PR_OpenTCPSocket"); |
+ tcp_sock = PR_OpenTCPSocket(addr->raw.family); |
+ if (tcp_sock == NULL) { |
+ errExit("PR_OpenTCPSocket"); |
+ } |
+ |
+ opt.option = PR_SockOpt_Nonblocking; |
+ opt.value.non_blocking = PR_FALSE; |
+ prStatus = PR_SetSocketOption(tcp_sock, &opt); |
+ if (prStatus != PR_SUCCESS) { |
+ errWarn("PR_SetSocketOption(PR_SockOpt_Nonblocking, PR_FALSE)"); |
+ PR_Close(tcp_sock); |
+ return SECSuccess; |
+ } |
+ |
+ if (NoDelay) { |
+ opt.option = PR_SockOpt_NoDelay; |
+ opt.value.no_delay = PR_TRUE; |
+ prStatus = PR_SetSocketOption(tcp_sock, &opt); |
+ if (prStatus != PR_SUCCESS) { |
+ errWarn("PR_SetSocketOption(PR_SockOpt_NoDelay, PR_TRUE)"); |
+ PR_Close(tcp_sock); |
+ return SECSuccess; |
+ } |
+ } |
+ |
+ prStatus = PR_Connect(tcp_sock, addr, PR_INTERVAL_NO_TIMEOUT); |
+ if (prStatus != PR_SUCCESS) { |
+ PRErrorCode err = PR_GetError(); /* save error code */ |
+ PRInt32 oserr = PR_GetOSError(); |
+ if (ThrottleUp) { |
+ PRTime now = PR_Now(); |
+ PR_Lock(threadLock); |
+ lastConnectFailure = PR_MAX(now, lastConnectFailure); |
+ PR_Unlock(threadLock); |
+ PR_SetError(err, oserr); /* restore error code */ |
+ } |
+ if ((err == PR_CONNECT_REFUSED_ERROR) || (err == PR_CONNECT_RESET_ERROR)) { |
+ int connections = numConnected; |
+ |
+ PR_Close(tcp_sock); |
+ PR_Lock(threadLock); |
+ if (connections > 2 && active_threads >= connections) { |
+ active_threads = connections - 1; |
+ fprintf(stderr, "active_threads set down to %d\n", active_threads); |
+ } |
+ PR_Unlock(threadLock); |
+ |
+ if (QuitOnTimeout && sleepInterval > 40000) { |
+ fprintf( |
+ stderr, |
+ "strsclnt: Client timed out waiting for connection to server.\n"); |
+ exit(1); |
+ } |
+ PR_Sleep(PR_MillisecondsToInterval(sleepInterval)); |
+ sleepInterval <<= 1; |
+ goto retry; |
+ } |
+ errWarn("PR_Connect"); |
+ rv = SECFailure; |
+ goto done; |
+ } else { |
+ if (ThrottleUp) { |
+ PRTime now = PR_Now(); |
+ PR_Lock(threadLock); |
+ lastConnectSuccess = PR_MAX(now, lastConnectSuccess); |
+ PR_Unlock(threadLock); |
+ } |
+ } |
+ |
+ ssl_sock = SSL_ImportFD(model_sock, tcp_sock); |
+ /* XXX if this import fails, close tcp_sock and return. */ |
+ if (!ssl_sock) { |
+ PR_Close(tcp_sock); |
+ return SECSuccess; |
+ } |
+ if (fullhs != NO_FULLHS_PERCENTAGE) { |
+#ifdef USE_SOCK_PEER_ID |
+ char sockPeerIDString[512]; |
+ static PRInt32 sockPeerID = 0; /* atomically incremented */ |
+ PRInt32 thisPeerID; |
+#endif |
+ PRInt32 savid = PR_ATOMIC_INCREMENT(&globalconid); |
+ PRInt32 conid = 1 + (savid - 1) % 100; |
+ /* don't change peer ID on the very first handshake, which is always |
+ a full, so the session gets stored into the client cache */ |
+ if ((savid != 1) && |
+ (((savid <= total_connections_rounded_down_to_hundreds) && |
+ (conid <= fullhs)) || |
+ (conid * 100 <= total_connections_modulo_100 * fullhs))) |
+#ifdef USE_SOCK_PEER_ID |
+ { |
+ /* force a full handshake by changing the socket peer ID */ |
+ thisPeerID = PR_ATOMIC_INCREMENT(&sockPeerID); |
+ } else { |
+ /* reuse previous sockPeerID for restart handhsake */ |
+ thisPeerID = lastFullHandshakePeerID; |
+ } |
+ PR_snprintf(sockPeerIDString, sizeof(sockPeerIDString), "ID%d", thisPeerID); |
+ SSL_SetSockPeerID(ssl_sock, sockPeerIDString); |
+ SSL_HandshakeCallback(ssl_sock, myHandshakeCallback, (void *)thisPeerID); |
+#else |
+ /* force a full handshake by setting the no cache option */ |
+ SSL_OptionSet(ssl_sock, SSL_NO_CACHE, 1); |
+#endif |
+ } |
+ rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 0); |
+ if (rv != SECSuccess) { |
+ errWarn("SSL_ResetHandshake"); |
+ goto done; |
+ } |
+ |
+ PR_ATOMIC_INCREMENT(&numConnected); |
+ |
+ if (bigBuf.data != NULL) { |
+ result = handle_fdx_connection(ssl_sock, tid); |
+ } else { |
+ result = handle_connection(ssl_sock, tid); |
+ } |
+ |
+ PR_ATOMIC_DECREMENT(&numConnected); |
+ |
+done: |
+ if (ssl_sock) { |
+ PR_Close(ssl_sock); |
+ } else if (tcp_sock) { |
+ PR_Close(tcp_sock); |
+ } |
+ return SECSuccess; |
+} |
+ |
+typedef struct { |
+ PRLock *lock; |
+ char *nickname; |
+ CERTCertificate *cert; |
+ SECKEYPrivateKey *key; |
+ void *wincx; |
+} cert_and_key; |
+ |
+PRBool FindCertAndKey(cert_and_key *Cert_And_Key) { |
+ if ((NULL == Cert_And_Key->nickname) || |
+ (0 == strcmp(Cert_And_Key->nickname, "none"))) { |
+ return PR_TRUE; |
+ } |
+ Cert_And_Key->cert = CERT_FindUserCertByUsage( |
+ CERT_GetDefaultCertDB(), Cert_And_Key->nickname, certUsageSSLClient, |
+ PR_FALSE, Cert_And_Key->wincx); |
+ if (Cert_And_Key->cert) { |
+ Cert_And_Key->key = |
+ PK11_FindKeyByAnyCert(Cert_And_Key->cert, Cert_And_Key->wincx); |
+ } |
+ if (Cert_And_Key->cert && Cert_And_Key->key) { |
+ return PR_TRUE; |
+ } else { |
+ return PR_FALSE; |
+ } |
+} |
+ |
+PRBool LoggedIn(CERTCertificate *cert, SECKEYPrivateKey *key) { |
+ if ((cert->slot) && (key->pkcs11Slot) && |
+ (PR_TRUE == PK11_IsLoggedIn(cert->slot, NULL)) && |
+ (PR_TRUE == PK11_IsLoggedIn(key->pkcs11Slot, NULL))) { |
+ return PR_TRUE; |
+ } |
+ |
+ return PR_FALSE; |
+} |
+ |
+SECStatus StressClient_GetClientAuthData(void *arg, PRFileDesc *socket, |
+ struct CERTDistNamesStr *caNames, |
+ struct CERTCertificateStr **pRetCert, |
+ struct SECKEYPrivateKeyStr **pRetKey) { |
+ cert_and_key *Cert_And_Key = (cert_and_key *)arg; |
+ |
+ if (!pRetCert || !pRetKey) { |
+ /* bad pointers, can't return a cert or key */ |
+ return SECFailure; |
+ } |
+ |
+ *pRetCert = NULL; |
+ *pRetKey = NULL; |
+ |
+ if (Cert_And_Key && Cert_And_Key->nickname) { |
+ while (PR_TRUE) { |
+ if (Cert_And_Key && Cert_And_Key->lock) { |
+ int timeout = 0; |
+ PR_Lock(Cert_And_Key->lock); |
+ |
+ if (Cert_And_Key->cert) { |
+ *pRetCert = CERT_DupCertificate(Cert_And_Key->cert); |
+ } |
+ |
+ if (Cert_And_Key->key) { |
+ *pRetKey = SECKEY_CopyPrivateKey(Cert_And_Key->key); |
+ } |
+ PR_Unlock(Cert_And_Key->lock); |
+ if (!*pRetCert || !*pRetKey) { |
+ /* one or both of them failed to copy. Either the source was NULL, or |
+ *there was |
+ ** an out of memory condition. Free any allocated copy and fail */ |
+ if (*pRetCert) { |
+ CERT_DestroyCertificate(*pRetCert); |
+ *pRetCert = NULL; |
+ } |
+ if (*pRetKey) { |
+ SECKEY_DestroyPrivateKey(*pRetKey); |
+ *pRetKey = NULL; |
+ } |
+ break; |
+ } |
+ /* now check if those objects are valid */ |
+ if (PR_FALSE == LoggedIn(*pRetCert, *pRetKey)) { |
+ /* token is no longer logged in, it was removed */ |
+ |
+ /* first, delete and clear our invalid local objects */ |
+ CERT_DestroyCertificate(*pRetCert); |
+ SECKEY_DestroyPrivateKey(*pRetKey); |
+ *pRetCert = NULL; |
+ *pRetKey = NULL; |
+ |
+ PR_Lock(Cert_And_Key->lock); |
+ /* check if another thread already logged back in */ |
+ if (PR_TRUE == LoggedIn(Cert_And_Key->cert, Cert_And_Key->key)) { |
+ /* yes : try again */ |
+ PR_Unlock(Cert_And_Key->lock); |
+ continue; |
+ } |
+ /* this is the thread to retry */ |
+ CERT_DestroyCertificate(Cert_And_Key->cert); |
+ SECKEY_DestroyPrivateKey(Cert_And_Key->key); |
+ Cert_And_Key->cert = NULL; |
+ Cert_And_Key->key = NULL; |
+ |
+ /* now look up the cert and key again */ |
+ while (PR_FALSE == FindCertAndKey(Cert_And_Key)) { |
+ PR_Sleep(PR_SecondsToInterval(1)); |
+ timeout++; |
+ if (timeout >= 60) { |
+ printf( |
+ "\nToken pulled and not reinserted early enough : " |
+ "aborting.\n"); |
+ exit(1); |
+ } |
+ } |
+ PR_Unlock(Cert_And_Key->lock); |
+ continue; |
+ /* try again to reduce code size */ |
+ } |
+ return SECSuccess; |
+ } |
+ } |
+ *pRetCert = NULL; |
+ *pRetKey = NULL; |
+ return SECFailure; |
+ } else { |
+ /* no cert configured, automatically find the right cert. */ |
+ CERTCertificate *cert = NULL; |
+ SECKEYPrivateKey *privkey = NULL; |
+ CERTCertNicknames *names; |
+ int i; |
+ void *proto_win = NULL; |
+ SECStatus rv = SECFailure; |
+ |
+ if (Cert_And_Key) { |
+ proto_win = Cert_And_Key->wincx; |
} |
- opt.option = PR_SockOpt_Nonblocking; |
- opt.value.non_blocking = PR_FALSE; |
- prStatus = PR_SetSocketOption(tcp_sock, &opt); |
- if (prStatus != PR_SUCCESS) { |
- errWarn("PR_SetSocketOption(PR_SockOpt_Nonblocking, PR_FALSE)"); |
- PR_Close(tcp_sock); |
- return SECSuccess; |
- } |
+ names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(), |
+ SEC_CERT_NICKNAMES_USER, proto_win); |
+ if (names != NULL) { |
+ for (i = 0; i < names->numnicknames; i++) { |
+ cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(), |
+ names->nicknames[i], certUsageSSLClient, |
+ PR_FALSE, proto_win); |
+ if (!cert) continue; |
+ /* Only check unexpired certs */ |
+ if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_TRUE) != |
+ secCertTimeValid) { |
+ CERT_DestroyCertificate(cert); |
+ continue; |
+ } |
+ rv = NSS_CmpCertChainWCANames(cert, caNames); |
+ if (rv == SECSuccess) { |
+ privkey = PK11_FindKeyByAnyCert(cert, proto_win); |
+ if (privkey) break; |
+ } |
+ rv = SECFailure; |
+ CERT_DestroyCertificate(cert); |
+ } |
+ CERT_FreeNicknames(names); |
+ } |
+ if (rv == SECSuccess) { |
+ *pRetCert = cert; |
+ *pRetKey = privkey; |
+ } |
+ return rv; |
+ } |
+} |
- if (NoDelay) { |
- opt.option = PR_SockOpt_NoDelay; |
- opt.value.no_delay = PR_TRUE; |
- prStatus = PR_SetSocketOption(tcp_sock, &opt); |
- if (prStatus != PR_SUCCESS) { |
- errWarn("PR_SetSocketOption(PR_SockOpt_NoDelay, PR_TRUE)"); |
- PR_Close(tcp_sock); |
- return SECSuccess; |
- } |
+int hexchar_to_int(int c) { |
+ if (((c) >= '0') && ((c) <= '9')) return (c) - '0'; |
+ if (((c) >= 'a') && ((c) <= 'f')) return (c) - 'a' + 10; |
+ if (((c) >= 'A') && ((c) <= 'F')) return (c) - 'A' + 10; |
+ failed_already = 1; |
+ return -1; |
+} |
+ |
+void client_main(unsigned short port, int connections, |
+ cert_and_key *Cert_And_Key, const char *hostName, |
+ const char *sniHostName) { |
+ PRFileDesc *model_sock = NULL; |
+ int i; |
+ int rv; |
+ PRStatus status; |
+ PRNetAddr addr; |
+ |
+ status = PR_StringToNetAddr(hostName, &addr); |
+ if (status == PR_SUCCESS) { |
+ addr.inet.port = PR_htons(port); |
+ } else { |
+ /* Lookup host */ |
+ PRAddrInfo *addrInfo; |
+ void *enumPtr = NULL; |
+ |
+ addrInfo = PR_GetAddrInfoByName(hostName, PR_AF_UNSPEC, |
+ PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME); |
+ if (!addrInfo) { |
+ SECU_PrintError(progName, "error looking up host"); |
+ return; |
+ } |
+ do { |
+ enumPtr = PR_EnumerateAddrInfo(enumPtr, addrInfo, port, &addr); |
+ } while (enumPtr != NULL && addr.raw.family != PR_AF_INET && |
+ addr.raw.family != PR_AF_INET6); |
+ PR_FreeAddrInfo(addrInfo); |
+ if (enumPtr == NULL) { |
+ SECU_PrintError(progName, "error looking up host address"); |
+ return; |
+ } |
+ } |
+ |
+ /* all suites except RSA_NULL_MD5 are enabled by Domestic Policy */ |
+ NSS_SetDomesticPolicy(); |
+ |
+ /* all the SSL2 and SSL3 cipher suites are enabled by default. */ |
+ if (cipherString) { |
+ int ndx; |
+ |
+ /* disable all the ciphers, then enable the ones we want. */ |
+ disableAllSSLCiphers(); |
+ |
+ while (0 != (ndx = *cipherString)) { |
+ const char *startCipher = cipherString++; |
+ int cipher = 0; |
+ SECStatus rv; |
+ |
+ if (ndx == ':') { |
+ cipher = hexchar_to_int(*cipherString++); |
+ cipher <<= 4; |
+ cipher |= hexchar_to_int(*cipherString++); |
+ cipher <<= 4; |
+ cipher |= hexchar_to_int(*cipherString++); |
+ cipher <<= 4; |
+ cipher |= hexchar_to_int(*cipherString++); |
+ if (cipher <= 0) { |
+ fprintf(stderr, "strsclnt: Invalid cipher value: %-5.5s\n", |
+ startCipher); |
+ failed_already = 1; |
+ return; |
+ } |
+ } else { |
+ if (isalpha(ndx)) { |
+ const int *cptr; |
+ |
+ cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites; |
+ for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0;) |
+ /* do nothing */; |
+ } |
+ if (cipher <= 0) { |
+ fprintf(stderr, "strsclnt: Invalid cipher letter: %c\n", |
+ *startCipher); |
+ failed_already = 1; |
+ return; |
+ } |
+ } |
+ rv = SSL_CipherPrefSetDefault(cipher, PR_TRUE); |
+ if (rv != SECSuccess) { |
+ fprintf(stderr, "strsclnt: SSL_CipherPrefSetDefault(0x%04x) failed\n", |
+ cipher); |
+ failed_already = 1; |
+ return; |
+ } |
+ } |
+ } |
+ |
+ /* configure model SSL socket. */ |
+ |
+ model_sock = PR_OpenTCPSocket(addr.raw.family); |
+ if (model_sock == NULL) { |
+ errExit("PR_OpenTCPSocket for model socket"); |
+ } |
+ |
+ model_sock = SSL_ImportFD(NULL, model_sock); |
+ if (model_sock == NULL) { |
+ errExit("SSL_ImportFD"); |
+ } |
+ |
+ /* do SSL configuration. */ |
+ |
+ rv = SSL_OptionSet(model_sock, SSL_SECURITY, |
+ enableSSL2 || enabledVersions.min != 0); |
+ if (rv < 0) { |
+ errExit("SSL_OptionSet SSL_SECURITY"); |
+ } |
+ |
+ rv = SSL_VersionRangeSet(model_sock, &enabledVersions); |
+ if (rv != SECSuccess) { |
+ errExit("error setting SSL/TLS version range "); |
+ } |
+ |
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_SSL2, enableSSL2); |
+ if (rv != SECSuccess) { |
+ errExit("error enabling SSLv2 "); |
+ } |
+ |
+ rv = SSL_OptionSet(model_sock, SSL_V2_COMPATIBLE_HELLO, enableSSL2); |
+ if (rv != SECSuccess) { |
+ errExit("error enabling SSLv2 compatible hellos "); |
+ } |
+ |
+ if (bigBuf.data) {/* doing FDX */ |
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_FDX, 1); |
+ if (rv < 0) { |
+ errExit("SSL_OptionSet SSL_ENABLE_FDX"); |
+ } |
+ } |
+ |
+ if (NoReuse) { |
+ rv = SSL_OptionSet(model_sock, SSL_NO_CACHE, 1); |
+ if (rv < 0) { |
+ errExit("SSL_OptionSet SSL_NO_CACHE"); |
+ } |
+ } |
+ |
+ if (bypassPKCS11) { |
+ rv = SSL_OptionSet(model_sock, SSL_BYPASS_PKCS11, 1); |
+ if (rv < 0) { |
+ errExit("SSL_OptionSet SSL_BYPASS_PKCS11"); |
+ } |
+ } |
+ |
+ if (disableLocking) { |
+ rv = SSL_OptionSet(model_sock, SSL_NO_LOCKS, 1); |
+ if (rv < 0) { |
+ errExit("SSL_OptionSet SSL_NO_LOCKS"); |
+ } |
+ } |
+ |
+ if (enableSessionTickets) { |
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_SESSION_TICKETS, PR_TRUE); |
+ if (rv != SECSuccess) errExit("SSL_OptionSet SSL_ENABLE_SESSION_TICKETS"); |
+ } |
+ |
+ if (enableCompression) { |
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_DEFLATE, PR_TRUE); |
+ if (rv != SECSuccess) errExit("SSL_OptionSet SSL_ENABLE_DEFLATE"); |
+ } |
+ |
+ if (enableFalseStart) { |
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_FALSE_START, PR_TRUE); |
+ if (rv != SECSuccess) errExit("SSL_OptionSet SSL_ENABLE_FALSE_START"); |
+ } |
+ |
+ if (enableCertStatus) { |
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_OCSP_STAPLING, PR_TRUE); |
+ if (rv != SECSuccess) errExit("SSL_OptionSet SSL_ENABLE_OCSP_STAPLING"); |
+ } |
+ |
+ SSL_SetPKCS11PinArg(model_sock, &pwdata); |
+ |
+ SSL_SetURL(model_sock, hostName); |
+ |
+ SSL_AuthCertificateHook(model_sock, mySSLAuthCertificate, |
+ (void *)CERT_GetDefaultCertDB()); |
+ SSL_BadCertHook(model_sock, myBadCertHandler, NULL); |
+ |
+ SSL_GetClientAuthDataHook(model_sock, StressClient_GetClientAuthData, |
+ (void *)Cert_And_Key); |
+ |
+ if (sniHostName) { |
+ SSL_SetURL(model_sock, sniHostName); |
+ } |
+ /* I'm not going to set the HandshakeCallback function. */ |
+ |
+ /* end of ssl configuration. */ |
+ |
+ init_thread_data(); |
+ |
+ remaining_connections = total_connections = connections; |
+ total_connections_modulo_100 = total_connections % 100; |
+ total_connections_rounded_down_to_hundreds = |
+ total_connections - total_connections_modulo_100; |
+ |
+ if (!NoReuse) { |
+ remaining_connections = 1; |
+ rv = launch_thread(do_connects, &addr, model_sock, 0); |
+ /* wait for the first connection to terminate, then launch the rest. */ |
+ reap_threads(); |
+ remaining_connections = total_connections - 1; |
+ } |
+ if (remaining_connections > 0) { |
+ active_threads = PR_MIN(active_threads, remaining_connections); |
+ /* Start up the threads */ |
+ for (i = 0; i < active_threads; i++) { |
+ rv = launch_thread(do_connects, &addr, model_sock, i); |
+ } |
+ reap_threads(); |
+ } |
+ destroy_thread_data(); |
+ |
+ PR_Close(model_sock); |
+} |
+ |
+SECStatus readBigFile(const char *fileName) { |
+ PRFileInfo info; |
+ PRStatus status; |
+ SECStatus rv = SECFailure; |
+ int count; |
+ int hdrLen; |
+ PRFileDesc *local_file_fd = NULL; |
+ |
+ status = PR_GetFileInfo(fileName, &info); |
+ |
+ if (status == PR_SUCCESS && info.type == PR_FILE_FILE && info.size > 0 && |
+ NULL != (local_file_fd = PR_Open(fileName, PR_RDONLY, 0))) { |
+ |
+ hdrLen = PORT_Strlen(outHeader); |
+ bigBuf.len = hdrLen + info.size; |
+ bigBuf.data = PORT_Malloc(bigBuf.len + 4095); |
+ if (!bigBuf.data) { |
+ errWarn("PORT_Malloc"); |
+ goto done; |
} |
- prStatus = PR_Connect(tcp_sock, addr, PR_INTERVAL_NO_TIMEOUT); |
- if (prStatus != PR_SUCCESS) { |
- PRErrorCode err = PR_GetError(); /* save error code */ |
- PRInt32 oserr = PR_GetOSError(); |
- if (ThrottleUp) { |
- PRTime now = PR_Now(); |
- PR_Lock(threadLock); |
- lastConnectFailure = PR_MAX(now, lastConnectFailure); |
- PR_Unlock(threadLock); |
- PR_SetError(err, oserr); /* restore error code */ |
+ PORT_Memcpy(bigBuf.data, outHeader, hdrLen); |
+ |
+ count = PR_Read(local_file_fd, bigBuf.data + hdrLen, info.size); |
+ if (count != info.size) { |
+ errWarn("PR_Read local file"); |
+ goto done; |
+ } |
+ rv = SECSuccess; |
+ done: |
+ PR_Close(local_file_fd); |
+ } |
+ return rv; |
+} |
+ |
+int main(int argc, char **argv) { |
+ const char *dir = "."; |
+ const char *fileName = NULL; |
+ char *hostName = NULL; |
+ char *nickName = NULL; |
+ char *tmp = NULL; |
+ int connections = 1; |
+ int exitVal; |
+ int tmpInt; |
+ unsigned short port = 443; |
+ SECStatus rv; |
+ PLOptState *optstate; |
+ PLOptStatus status; |
+ cert_and_key Cert_And_Key; |
+ char *sniHostName = NULL; |
+ |
+ /* Call the NSPR initialization routines */ |
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); |
+ SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions); |
+ |
+ tmp = strrchr(argv[0], '/'); |
+ tmp = tmp ? tmp + 1 : argv[0]; |
+ progName = strrchr(tmp, '\\'); |
+ progName = progName ? progName + 1 : tmp; |
+ |
+ optstate = |
+ PL_CreateOptState(argc, argv, "BC:DNP:TUV:W:a:c:d:f:gin:op:qst:uvw:z"); |
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { |
+ switch (optstate->option) { |
+ case 'B': |
+ bypassPKCS11 = PR_TRUE; |
+ break; |
+ |
+ case 'C': |
+ cipherString = optstate->value; |
+ break; |
+ |
+ case 'D': |
+ NoDelay = PR_TRUE; |
+ break; |
+ |
+ case 'I': /* reserved for OCSP multi-stapling */ |
+ break; |
+ |
+ case 'N': |
+ NoReuse = 1; |
+ break; |
+ |
+ case 'P': |
+ fullhs = PORT_Atoi(optstate->value); |
+ break; |
+ |
+ case 'T': |
+ enableCertStatus = PR_TRUE; |
+ break; |
+ |
+ case 'U': |
+ ThrottleUp = PR_TRUE; |
+ break; |
+ |
+ case 'V': |
+ if (SECU_ParseSSLVersionRangeString(optstate->value, enabledVersions, |
+ enableSSL2, &enabledVersions, |
+ &enableSSL2) != SECSuccess) { |
+ Usage(progName); |
} |
- if ((err == PR_CONNECT_REFUSED_ERROR) || |
- (err == PR_CONNECT_RESET_ERROR) ) { |
- int connections = numConnected; |
+ break; |
- PR_Close(tcp_sock); |
- PR_Lock(threadLock); |
- if (connections > 2 && active_threads >= connections) { |
- active_threads = connections - 1; |
- fprintf(stderr,"active_threads set down to %d\n", |
- active_threads); |
- } |
- PR_Unlock(threadLock); |
+ case 'a': |
+ sniHostName = PL_strdup(optstate->value); |
+ break; |
- if (QuitOnTimeout && sleepInterval > 40000) { |
- fprintf(stderr, |
- "strsclnt: Client timed out waiting for connection to server.\n"); |
- exit(1); |
- } |
- PR_Sleep(PR_MillisecondsToInterval(sleepInterval)); |
- sleepInterval <<= 1; |
- goto retry; |
- } |
- errWarn("PR_Connect"); |
- rv = SECFailure; |
- goto done; |
- } else { |
- if (ThrottleUp) { |
- PRTime now = PR_Now(); |
- PR_Lock(threadLock); |
- lastConnectSuccess = PR_MAX(now, lastConnectSuccess); |
- PR_Unlock(threadLock); |
+ case 'c': |
+ connections = PORT_Atoi(optstate->value); |
+ break; |
+ |
+ case 'd': |
+ dir = optstate->value; |
+ break; |
+ |
+ case 'f': |
+ fileName = optstate->value; |
+ break; |
+ |
+ case 'g': |
+ enableFalseStart = PR_TRUE; |
+ break; |
+ |
+ case 'i': |
+ ignoreErrors = PR_TRUE; |
+ break; |
+ |
+ case 'n': |
+ nickName = PL_strdup(optstate->value); |
+ break; |
+ |
+ case 'o': |
+ MakeCertOK++; |
+ break; |
+ |
+ case 'p': |
+ port = PORT_Atoi(optstate->value); |
+ break; |
+ |
+ case 'q': |
+ QuitOnTimeout = PR_TRUE; |
+ break; |
+ |
+ case 's': |
+ disableLocking = PR_TRUE; |
+ break; |
+ |
+ case 't': |
+ tmpInt = PORT_Atoi(optstate->value); |
+ if (tmpInt > 0 && tmpInt < MAX_THREADS) |
+ max_threads = active_threads = tmpInt; |
+ break; |
+ |
+ case 'u': |
+ enableSessionTickets = PR_TRUE; |
+ break; |
+ |
+ case 'v': |
+ verbose++; |
+ break; |
+ |
+ case 'w': |
+ pwdata.source = PW_PLAINTEXT; |
+ pwdata.data = PL_strdup(optstate->value); |
+ break; |
+ |
+ case 'W': |
+ pwdata.source = PW_FROMFILE; |
+ pwdata.data = PL_strdup(optstate->value); |
+ break; |
+ |
+ case 'z': |
+ enableCompression = PR_TRUE; |
+ break; |
+ |
+ case 0: /* positional parameter */ |
+ if (hostName) { |
+ Usage(progName); |
} |
+ hostName = PL_strdup(optstate->value); |
+ break; |
+ |
+ default: |
+ case '?': |
+ Usage(progName); |
+ break; |
+ } |
+ } |
+ PL_DestroyOptState(optstate); |
+ |
+ if (!hostName || status == PL_OPT_BAD) Usage(progName); |
+ |
+ if (fullhs != NO_FULLHS_PERCENTAGE && (fullhs < 0 || fullhs > 100 || NoReuse)) |
+ Usage(progName); |
+ |
+ if (port == 0) Usage(progName); |
+ |
+ if (fileName) readBigFile(fileName); |
+ |
+ PK11_SetPasswordFunc(SECU_GetModulePassword); |
+ |
+ tmp = PR_GetEnv("NSS_DEBUG_TIMEOUT"); |
+ if (tmp && tmp[0]) { |
+ int sec = PORT_Atoi(tmp); |
+ if (sec > 0) { |
+ maxInterval = PR_SecondsToInterval(sec); |
+ } |
+ } |
+ |
+ /* Call the NSS initialization routines */ |
+ rv = NSS_Initialize(dir, "", "", SECMOD_DB, NSS_INIT_READONLY); |
+ if (rv != SECSuccess) { |
+ fputs("NSS_Init failed.\n", stderr); |
+ exit(1); |
+ } |
+ ssl3stats = SSL_GetStatistics(); |
+ Cert_And_Key.lock = PR_NewLock(); |
+ Cert_And_Key.nickname = nickName; |
+ Cert_And_Key.wincx = &pwdata; |
+ Cert_And_Key.cert = NULL; |
+ Cert_And_Key.key = NULL; |
+ |
+ if (PR_FALSE == FindCertAndKey(&Cert_And_Key)) { |
+ |
+ if (Cert_And_Key.cert == NULL) { |
+ fprintf(stderr, "strsclnt: Can't find certificate %s\n", |
+ Cert_And_Key.nickname); |
+ exit(1); |
} |
- ssl_sock = SSL_ImportFD(model_sock, tcp_sock); |
- /* XXX if this import fails, close tcp_sock and return. */ |
- if (!ssl_sock) { |
- PR_Close(tcp_sock); |
- return SECSuccess; |
+ if (Cert_And_Key.key == NULL) { |
+ fprintf(stderr, "strsclnt: Can't find Private Key for cert %s\n", |
+ Cert_And_Key.nickname); |
+ exit(1); |
} |
- if (fullhs != NO_FULLHS_PERCENTAGE) { |
-#ifdef USE_SOCK_PEER_ID |
- char sockPeerIDString[512]; |
- static PRInt32 sockPeerID = 0; /* atomically incremented */ |
- PRInt32 thisPeerID; |
-#endif |
- PRInt32 savid = PR_ATOMIC_INCREMENT(&globalconid); |
- PRInt32 conid = 1 + (savid - 1) % 100; |
- /* don't change peer ID on the very first handshake, which is always |
- a full, so the session gets stored into the client cache */ |
- if ( (savid != 1) && |
- ( ( (savid <= total_connections_rounded_down_to_hundreds) && |
- (conid <= fullhs) ) || |
- (conid*100 <= total_connections_modulo_100*fullhs ) ) ) |
-#ifdef USE_SOCK_PEER_ID |
- { |
- /* force a full handshake by changing the socket peer ID */ |
- thisPeerID = PR_ATOMIC_INCREMENT(&sockPeerID); |
- } else { |
- /* reuse previous sockPeerID for restart handhsake */ |
- thisPeerID = lastFullHandshakePeerID; |
- } |
- PR_snprintf(sockPeerIDString, sizeof(sockPeerIDString), "ID%d", |
- thisPeerID); |
- SSL_SetSockPeerID(ssl_sock, sockPeerIDString); |
- SSL_HandshakeCallback(ssl_sock, myHandshakeCallback, (void*)thisPeerID); |
-#else |
- /* force a full handshake by setting the no cache option */ |
- SSL_OptionSet(ssl_sock, SSL_NO_CACHE, 1); |
-#endif |
- } |
- rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 0); |
- if (rv != SECSuccess) { |
- errWarn("SSL_ResetHandshake"); |
- goto done; |
- } |
+ } |
- PR_ATOMIC_INCREMENT(&numConnected); |
+ client_main(port, connections, &Cert_And_Key, hostName, sniHostName); |
- if (bigBuf.data != NULL) { |
- result = handle_fdx_connection( ssl_sock, tid); |
- } else { |
- result = handle_connection( ssl_sock, tid); |
- } |
+ /* clean up */ |
+ if (Cert_And_Key.cert) { |
+ CERT_DestroyCertificate(Cert_And_Key.cert); |
+ } |
+ if (Cert_And_Key.key) { |
+ SECKEY_DestroyPrivateKey(Cert_And_Key.key); |
+ } |
- PR_ATOMIC_DECREMENT(&numConnected); |
+ PR_DestroyLock(Cert_And_Key.lock); |
-done: |
- if (ssl_sock) { |
- PR_Close(ssl_sock); |
- } else if (tcp_sock) { |
- PR_Close(tcp_sock); |
- } |
- return SECSuccess; |
-} |
+ if (pwdata.data) { |
+ PL_strfree(pwdata.data); |
+ } |
+ if (Cert_And_Key.nickname) { |
+ PL_strfree(Cert_And_Key.nickname); |
+ } |
+ if (sniHostName) { |
+ PL_strfree(sniHostName); |
+ } |
+ PL_strfree(hostName); |
-typedef struct { |
- PRLock* lock; |
- char* nickname; |
- CERTCertificate* cert; |
- SECKEYPrivateKey* key; |
- void* wincx; |
-} cert_and_key; |
+ /* some final stats. */ |
+ if (ssl3stats->hsh_sid_cache_hits + ssl3stats->hsh_sid_cache_misses + |
+ ssl3stats->hsh_sid_cache_not_ok + |
+ ssl3stats->hsh_sid_stateless_resumes == |
+ 0) { |
+ /* presumably we were testing SSL2. */ |
+ printf("strsclnt: SSL2 - %d server certificates tested.\n", certsTested); |
+ } else { |
+ printf( |
+ "strsclnt: %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); |
+ } |
-PRBool FindCertAndKey(cert_and_key* Cert_And_Key) |
-{ |
- if ( (NULL == Cert_And_Key->nickname) || (0 == strcmp(Cert_And_Key->nickname,"none"))) { |
- return PR_TRUE; |
- } |
- Cert_And_Key->cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(), |
- Cert_And_Key->nickname, certUsageSSLClient, |
- PR_FALSE, Cert_And_Key->wincx); |
- if (Cert_And_Key->cert) { |
- Cert_And_Key->key = PK11_FindKeyByAnyCert(Cert_And_Key->cert, Cert_And_Key->wincx); |
- } |
- if (Cert_And_Key->cert && Cert_And_Key->key) { |
- return PR_TRUE; |
- } else { |
- return PR_FALSE; |
- } |
-} |
- |
-PRBool LoggedIn(CERTCertificate* cert, SECKEYPrivateKey* key) |
-{ |
- if ( (cert->slot) && (key->pkcs11Slot) && |
- (PR_TRUE == PK11_IsLoggedIn(cert->slot, NULL)) && |
- (PR_TRUE == PK11_IsLoggedIn(key->pkcs11Slot, NULL)) ) { |
- return PR_TRUE; |
- } |
- |
- return PR_FALSE; |
-} |
- |
-SECStatus |
-StressClient_GetClientAuthData(void * arg, |
- PRFileDesc * socket, |
- struct CERTDistNamesStr * caNames, |
- struct CERTCertificateStr ** pRetCert, |
- struct SECKEYPrivateKeyStr **pRetKey) |
-{ |
- cert_and_key* Cert_And_Key = (cert_and_key*) arg; |
- |
- if (!pRetCert || !pRetKey) { |
- /* bad pointers, can't return a cert or key */ |
- return SECFailure; |
- } |
- |
- *pRetCert = NULL; |
- *pRetKey = NULL; |
- |
- if (Cert_And_Key && Cert_And_Key->nickname) { |
- while (PR_TRUE) { |
- if (Cert_And_Key && Cert_And_Key->lock) { |
- int timeout = 0; |
- PR_Lock(Cert_And_Key->lock); |
- |
- if (Cert_And_Key->cert) { |
- *pRetCert = CERT_DupCertificate(Cert_And_Key->cert); |
- } |
- |
- if (Cert_And_Key->key) { |
- *pRetKey = SECKEY_CopyPrivateKey(Cert_And_Key->key); |
- } |
- PR_Unlock(Cert_And_Key->lock); |
- if (!*pRetCert || !*pRetKey) { |
- /* one or both of them failed to copy. Either the source was NULL, or there was |
- ** an out of memory condition. Free any allocated copy and fail */ |
- if (*pRetCert) { |
- CERT_DestroyCertificate(*pRetCert); |
- *pRetCert = NULL; |
- } |
- if (*pRetKey) { |
- SECKEY_DestroyPrivateKey(*pRetKey); |
- *pRetKey = NULL; |
- } |
- break; |
- } |
- /* now check if those objects are valid */ |
- if ( PR_FALSE == LoggedIn(*pRetCert, *pRetKey) ) { |
- /* token is no longer logged in, it was removed */ |
- |
- /* first, delete and clear our invalid local objects */ |
- CERT_DestroyCertificate(*pRetCert); |
- SECKEY_DestroyPrivateKey(*pRetKey); |
- *pRetCert = NULL; |
- *pRetKey = NULL; |
- |
- PR_Lock(Cert_And_Key->lock); |
- /* check if another thread already logged back in */ |
- if (PR_TRUE == LoggedIn(Cert_And_Key->cert, Cert_And_Key->key)) { |
- /* yes : try again */ |
- PR_Unlock(Cert_And_Key->lock); |
- continue; |
- } |
- /* this is the thread to retry */ |
- CERT_DestroyCertificate(Cert_And_Key->cert); |
- SECKEY_DestroyPrivateKey(Cert_And_Key->key); |
- Cert_And_Key->cert = NULL; |
- Cert_And_Key->key = NULL; |
- |
- |
- /* now look up the cert and key again */ |
- while (PR_FALSE == FindCertAndKey(Cert_And_Key) ) { |
- PR_Sleep(PR_SecondsToInterval(1)); |
- timeout++; |
- if (timeout>=60) { |
- printf("\nToken pulled and not reinserted early enough : aborting.\n"); |
- exit(1); |
- } |
- } |
- PR_Unlock(Cert_And_Key->lock); |
- continue; |
- /* try again to reduce code size */ |
- } |
- return SECSuccess; |
- } |
- } |
- *pRetCert = NULL; |
- *pRetKey = NULL; |
- return SECFailure; |
- } else { |
- /* no cert configured, automatically find the right cert. */ |
- CERTCertificate * cert = NULL; |
- SECKEYPrivateKey * privkey = NULL; |
- CERTCertNicknames * names; |
- int i; |
- void * proto_win = NULL; |
- SECStatus rv = SECFailure; |
- |
- if (Cert_And_Key) { |
- proto_win = Cert_And_Key->wincx; |
- } |
- |
- names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(), |
- SEC_CERT_NICKNAMES_USER, proto_win); |
- if (names != NULL) { |
- for (i = 0; i < names->numnicknames; i++) { |
- cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(), |
- names->nicknames[i], certUsageSSLClient, |
- PR_FALSE, proto_win); |
- if ( !cert ) |
- continue; |
- /* Only check unexpired certs */ |
- if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_TRUE) != |
- secCertTimeValid ) { |
- CERT_DestroyCertificate(cert); |
- continue; |
- } |
- rv = NSS_CmpCertChainWCANames(cert, caNames); |
- if ( rv == SECSuccess ) { |
- privkey = PK11_FindKeyByAnyCert(cert, proto_win); |
- if ( privkey ) |
- break; |
- } |
- rv = SECFailure; |
- CERT_DestroyCertificate(cert); |
- } |
- CERT_FreeNicknames(names); |
- } |
- if (rv == SECSuccess) { |
- *pRetCert = cert; |
- *pRetKey = privkey; |
- } |
- return rv; |
- } |
-} |
- |
-int |
-hexchar_to_int(int c) |
-{ |
- if (((c) >= '0') && ((c) <= '9')) |
- return (c) - '0'; |
- if (((c) >= 'a') && ((c) <= 'f')) |
- return (c) - 'a' + 10; |
- if (((c) >= 'A') && ((c) <= 'F')) |
- return (c) - 'A' + 10; |
- failed_already = 1; |
- return -1; |
-} |
- |
-void |
-client_main( |
- unsigned short port, |
- int connections, |
- cert_and_key* Cert_And_Key, |
- const char * hostName, |
- const char * sniHostName) |
-{ |
- PRFileDesc *model_sock = NULL; |
- int i; |
- int rv; |
- PRStatus status; |
- PRNetAddr addr; |
- |
- status = PR_StringToNetAddr(hostName, &addr); |
- if (status == PR_SUCCESS) { |
- addr.inet.port = PR_htons(port); |
- } else { |
- /* Lookup host */ |
- PRAddrInfo *addrInfo; |
- void *enumPtr = NULL; |
- |
- addrInfo = PR_GetAddrInfoByName(hostName, PR_AF_UNSPEC, |
- PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME); |
- if (!addrInfo) { |
- SECU_PrintError(progName, "error looking up host"); |
- return; |
- } |
- do { |
- enumPtr = PR_EnumerateAddrInfo(enumPtr, addrInfo, port, &addr); |
- } while (enumPtr != NULL && |
- addr.raw.family != PR_AF_INET && |
- addr.raw.family != PR_AF_INET6); |
- PR_FreeAddrInfo(addrInfo); |
- if (enumPtr == NULL) { |
- SECU_PrintError(progName, "error looking up host address"); |
- return; |
- } |
- } |
- |
- /* all suites except RSA_NULL_MD5 are enabled by Domestic Policy */ |
- NSS_SetDomesticPolicy(); |
- |
- /* all the SSL2 and SSL3 cipher suites are enabled by default. */ |
- if (cipherString) { |
- int ndx; |
- |
- /* disable all the ciphers, then enable the ones we want. */ |
- disableAllSSLCiphers(); |
- |
- while (0 != (ndx = *cipherString)) { |
- const char * startCipher = cipherString++; |
- int cipher = 0; |
- SECStatus rv; |
- |
- if (ndx == ':') { |
- cipher = hexchar_to_int(*cipherString++); |
- cipher <<= 4; |
- cipher |= hexchar_to_int(*cipherString++); |
- cipher <<= 4; |
- cipher |= hexchar_to_int(*cipherString++); |
- cipher <<= 4; |
- cipher |= hexchar_to_int(*cipherString++); |
- if (cipher <= 0) { |
- fprintf(stderr, "strsclnt: Invalid cipher value: %-5.5s\n", |
- startCipher); |
- failed_already = 1; |
- return; |
- } |
- } else { |
- if (isalpha(ndx)) { |
- const int *cptr; |
- |
- cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites; |
- for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; ) |
- /* do nothing */; |
- } |
- if (cipher <= 0) { |
- fprintf(stderr, "strsclnt: Invalid cipher letter: %c\n", |
- *startCipher); |
- failed_already = 1; |
- return; |
- } |
- } |
- rv = SSL_CipherPrefSetDefault(cipher, PR_TRUE); |
- if (rv != SECSuccess) { |
- fprintf(stderr, |
- "strsclnt: SSL_CipherPrefSetDefault(0x%04x) failed\n", |
- cipher); |
- failed_already = 1; |
- return; |
- } |
- } |
- } |
- |
- /* configure model SSL socket. */ |
- |
- model_sock = PR_OpenTCPSocket(addr.raw.family); |
- if (model_sock == NULL) { |
- errExit("PR_OpenTCPSocket for model socket"); |
- } |
- |
- model_sock = SSL_ImportFD(NULL, model_sock); |
- if (model_sock == NULL) { |
- errExit("SSL_ImportFD"); |
- } |
- |
- /* do SSL configuration. */ |
- |
- rv = SSL_OptionSet(model_sock, SSL_SECURITY, |
- enableSSL2 || enabledVersions.min != 0); |
- if (rv < 0) { |
- errExit("SSL_OptionSet SSL_SECURITY"); |
- } |
- |
- rv = SSL_VersionRangeSet(model_sock, &enabledVersions); |
- if (rv != SECSuccess) { |
- errExit("error setting SSL/TLS version range "); |
- } |
- |
- rv = SSL_OptionSet(model_sock, SSL_ENABLE_SSL2, enableSSL2); |
- if (rv != SECSuccess) { |
- errExit("error enabling SSLv2 "); |
- } |
- |
- rv = SSL_OptionSet(model_sock, SSL_V2_COMPATIBLE_HELLO, enableSSL2); |
- if (rv != SECSuccess) { |
- errExit("error enabling SSLv2 compatible hellos "); |
- } |
- |
- if (bigBuf.data) { /* doing FDX */ |
- rv = SSL_OptionSet(model_sock, SSL_ENABLE_FDX, 1); |
- if (rv < 0) { |
- errExit("SSL_OptionSet SSL_ENABLE_FDX"); |
- } |
- } |
- |
- if (NoReuse) { |
- rv = SSL_OptionSet(model_sock, SSL_NO_CACHE, 1); |
- if (rv < 0) { |
- errExit("SSL_OptionSet SSL_NO_CACHE"); |
- } |
- } |
- |
- if (bypassPKCS11) { |
- rv = SSL_OptionSet(model_sock, SSL_BYPASS_PKCS11, 1); |
- if (rv < 0) { |
- errExit("SSL_OptionSet SSL_BYPASS_PKCS11"); |
- } |
- } |
- |
- if (disableLocking) { |
- rv = SSL_OptionSet(model_sock, SSL_NO_LOCKS, 1); |
- if (rv < 0) { |
- errExit("SSL_OptionSet SSL_NO_LOCKS"); |
- } |
- } |
- |
- if (enableSessionTickets) { |
- rv = SSL_OptionSet(model_sock, SSL_ENABLE_SESSION_TICKETS, PR_TRUE); |
- if (rv != SECSuccess) |
- errExit("SSL_OptionSet SSL_ENABLE_SESSION_TICKETS"); |
- } |
- |
- if (enableCompression) { |
- rv = SSL_OptionSet(model_sock, SSL_ENABLE_DEFLATE, PR_TRUE); |
- if (rv != SECSuccess) |
- errExit("SSL_OptionSet SSL_ENABLE_DEFLATE"); |
- } |
- |
- if (enableFalseStart) { |
- rv = SSL_OptionSet(model_sock, SSL_ENABLE_FALSE_START, PR_TRUE); |
- if (rv != SECSuccess) |
- errExit("SSL_OptionSet SSL_ENABLE_FALSE_START"); |
- } |
- |
- if (enableCertStatus) { |
- rv = SSL_OptionSet(model_sock, SSL_ENABLE_OCSP_STAPLING, PR_TRUE); |
- if (rv != SECSuccess) |
- errExit("SSL_OptionSet SSL_ENABLE_OCSP_STAPLING"); |
- } |
- |
- SSL_SetPKCS11PinArg(model_sock, &pwdata); |
- |
- SSL_SetURL(model_sock, hostName); |
- |
- SSL_AuthCertificateHook(model_sock, mySSLAuthCertificate, |
- (void *)CERT_GetDefaultCertDB()); |
- SSL_BadCertHook(model_sock, myBadCertHandler, NULL); |
- |
- SSL_GetClientAuthDataHook(model_sock, StressClient_GetClientAuthData, (void*)Cert_And_Key); |
- |
- if (sniHostName) { |
- SSL_SetURL(model_sock, sniHostName); |
- } |
- /* I'm not going to set the HandshakeCallback function. */ |
- |
- /* end of ssl configuration. */ |
- |
- init_thread_data(); |
- |
- remaining_connections = total_connections = connections; |
- total_connections_modulo_100 = total_connections % 100; |
- total_connections_rounded_down_to_hundreds = |
- total_connections - total_connections_modulo_100; |
- |
- if (!NoReuse) { |
- remaining_connections = 1; |
- rv = launch_thread(do_connects, &addr, model_sock, 0); |
- /* wait for the first connection to terminate, then launch the rest. */ |
- reap_threads(); |
- remaining_connections = total_connections - 1 ; |
- } |
- if (remaining_connections > 0) { |
- active_threads = PR_MIN(active_threads, remaining_connections); |
- /* Start up the threads */ |
- for (i=0;i<active_threads;i++) { |
- rv = launch_thread(do_connects, &addr, model_sock, i); |
- } |
- reap_threads(); |
- } |
- destroy_thread_data(); |
- |
- PR_Close(model_sock); |
-} |
- |
-SECStatus |
-readBigFile(const char * fileName) |
-{ |
- PRFileInfo info; |
- PRStatus status; |
- SECStatus rv = SECFailure; |
- int count; |
- int hdrLen; |
- PRFileDesc *local_file_fd = NULL; |
- |
- status = PR_GetFileInfo(fileName, &info); |
- |
- if (status == PR_SUCCESS && |
- info.type == PR_FILE_FILE && |
- info.size > 0 && |
- NULL != (local_file_fd = PR_Open(fileName, PR_RDONLY, 0))) { |
- |
- hdrLen = PORT_Strlen(outHeader); |
- bigBuf.len = hdrLen + info.size; |
- bigBuf.data = PORT_Malloc(bigBuf.len + 4095); |
- if (!bigBuf.data) { |
- errWarn("PORT_Malloc"); |
- goto done; |
- } |
- |
- PORT_Memcpy(bigBuf.data, outHeader, hdrLen); |
- |
- count = PR_Read(local_file_fd, bigBuf.data + hdrLen, info.size); |
- if (count != info.size) { |
- errWarn("PR_Read local file"); |
- goto done; |
- } |
- rv = SECSuccess; |
-done: |
- PR_Close(local_file_fd); |
- } |
- return rv; |
-} |
- |
-int |
-main(int argc, char **argv) |
-{ |
- const char * dir = "."; |
- const char * fileName = NULL; |
- char * hostName = NULL; |
- char * nickName = NULL; |
- char * tmp = NULL; |
- int connections = 1; |
- int exitVal; |
- int tmpInt; |
- unsigned short port = 443; |
- SECStatus rv; |
- PLOptState * optstate; |
- PLOptStatus status; |
- cert_and_key Cert_And_Key; |
- char * sniHostName = NULL; |
- |
- /* Call the NSPR initialization routines */ |
- PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); |
- SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions); |
- |
- tmp = strrchr(argv[0], '/'); |
- tmp = tmp ? tmp + 1 : argv[0]; |
- progName = strrchr(tmp, '\\'); |
- progName = progName ? progName + 1 : tmp; |
- |
- |
- optstate = PL_CreateOptState(argc, argv, |
- "BC:DNP:TUV:W:a:c:d:f:gin:op:qst:uvw:z"); |
- while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { |
- switch(optstate->option) { |
- case 'B': bypassPKCS11 = PR_TRUE; break; |
- |
- case 'C': cipherString = optstate->value; break; |
- |
- case 'D': NoDelay = PR_TRUE; break; |
- |
- case 'I': /* reserved for OCSP multi-stapling */ break; |
- |
- case 'N': NoReuse = 1; break; |
- |
- case 'P': fullhs = PORT_Atoi(optstate->value); break; |
- |
- case 'T': enableCertStatus = PR_TRUE; break; |
- |
- case 'U': ThrottleUp = PR_TRUE; break; |
- |
- case 'V': if (SECU_ParseSSLVersionRangeString(optstate->value, |
- enabledVersions, enableSSL2, |
- &enabledVersions, &enableSSL2) != SECSuccess) { |
- Usage(progName); |
- } |
- break; |
- |
- case 'a': sniHostName = PL_strdup(optstate->value); break; |
- |
- case 'c': connections = PORT_Atoi(optstate->value); break; |
- |
- case 'd': dir = optstate->value; break; |
- |
- case 'f': fileName = optstate->value; break; |
- |
- case 'g': enableFalseStart = PR_TRUE; break; |
- |
- case 'i': ignoreErrors = PR_TRUE; break; |
- |
- case 'n': nickName = PL_strdup(optstate->value); break; |
- |
- case 'o': MakeCertOK++; break; |
- |
- case 'p': port = PORT_Atoi(optstate->value); break; |
- |
- case 'q': QuitOnTimeout = PR_TRUE; break; |
- |
- case 's': disableLocking = PR_TRUE; break; |
- |
- case 't': |
- tmpInt = PORT_Atoi(optstate->value); |
- if (tmpInt > 0 && tmpInt < MAX_THREADS) |
- max_threads = active_threads = tmpInt; |
- break; |
- |
- case 'u': enableSessionTickets = PR_TRUE; break; |
- |
- case 'v': verbose++; break; |
- |
- case 'w': |
- pwdata.source = PW_PLAINTEXT; |
- pwdata.data = PL_strdup(optstate->value); |
- break; |
- |
- case 'W': |
- pwdata.source = PW_FROMFILE; |
- pwdata.data = PL_strdup(optstate->value); |
- break; |
- |
- case 'z': enableCompression = PR_TRUE; break; |
- |
- case 0: /* positional parameter */ |
- if (hostName) { |
- Usage(progName); |
- } |
- hostName = PL_strdup(optstate->value); |
- break; |
- |
- default: |
- case '?': |
- Usage(progName); |
- break; |
- |
- } |
- } |
- PL_DestroyOptState(optstate); |
- |
- if (!hostName || status == PL_OPT_BAD) |
- Usage(progName); |
- |
- if (fullhs!= NO_FULLHS_PERCENTAGE && (fullhs < 0 || fullhs>100 || NoReuse) ) |
- Usage(progName); |
- |
- if (port == 0) |
- Usage(progName); |
- |
- if (fileName) |
- readBigFile(fileName); |
- |
- PK11_SetPasswordFunc(SECU_GetModulePassword); |
- |
- tmp = PR_GetEnv("NSS_DEBUG_TIMEOUT"); |
- if (tmp && tmp[0]) { |
- int sec = PORT_Atoi(tmp); |
- if (sec > 0) { |
- maxInterval = PR_SecondsToInterval(sec); |
- } |
- } |
- |
- /* Call the NSS initialization routines */ |
- rv = NSS_Initialize(dir, "", "", SECMOD_DB, NSS_INIT_READONLY); |
- if (rv != SECSuccess) { |
- fputs("NSS_Init failed.\n", stderr); |
- exit(1); |
- } |
- ssl3stats = SSL_GetStatistics(); |
- Cert_And_Key.lock = PR_NewLock(); |
- Cert_And_Key.nickname = nickName; |
- Cert_And_Key.wincx = &pwdata; |
- Cert_And_Key.cert = NULL; |
- Cert_And_Key.key = NULL; |
- |
- if (PR_FALSE == FindCertAndKey(&Cert_And_Key)) { |
- |
- if (Cert_And_Key.cert == NULL) { |
- fprintf(stderr, "strsclnt: Can't find certificate %s\n", Cert_And_Key.nickname); |
- exit(1); |
- } |
- |
- if (Cert_And_Key.key == NULL) { |
- fprintf(stderr, "strsclnt: Can't find Private Key for cert %s\n", |
- Cert_And_Key.nickname); |
- exit(1); |
- } |
- |
- } |
- |
- client_main(port, connections, &Cert_And_Key, hostName, |
- sniHostName); |
- |
- /* clean up */ |
- if (Cert_And_Key.cert) { |
- CERT_DestroyCertificate(Cert_And_Key.cert); |
- } |
- if (Cert_And_Key.key) { |
- SECKEY_DestroyPrivateKey(Cert_And_Key.key); |
- } |
- |
- PR_DestroyLock(Cert_And_Key.lock); |
- |
- if (pwdata.data) { |
- PL_strfree(pwdata.data); |
- } |
- if (Cert_And_Key.nickname) { |
- PL_strfree(Cert_And_Key.nickname); |
- } |
- if (sniHostName) { |
- PL_strfree(sniHostName); |
- } |
- |
- PL_strfree(hostName); |
- |
- /* some final stats. */ |
- if (ssl3stats->hsh_sid_cache_hits + |
- ssl3stats->hsh_sid_cache_misses + |
- ssl3stats->hsh_sid_cache_not_ok + |
- ssl3stats->hsh_sid_stateless_resumes == 0) { |
- /* presumably we were testing SSL2. */ |
- printf("strsclnt: SSL2 - %d server certificates tested.\n", |
- certsTested); |
- } else { |
- printf( |
- "strsclnt: %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); |
- } |
- |
- if (!NoReuse) { |
- if (enableSessionTickets) |
- exitVal = (ssl3stats->hsh_sid_stateless_resumes == 0); |
- else |
- exitVal = (ssl3stats->hsh_sid_cache_misses > 1) || |
- (ssl3stats->hsh_sid_stateless_resumes != 0); |
- if (!exitVal) |
- exitVal = (ssl3stats->hsh_sid_cache_not_ok != 0) || |
- (certsTested > 1); |
- } else { |
- printf("strsclnt: NoReuse - %d server certificates tested.\n", |
- certsTested); |
- if (ssl3stats->hsh_sid_cache_hits + |
- ssl3stats->hsh_sid_cache_misses + |
+ if (!NoReuse) { |
+ if (enableSessionTickets) |
+ exitVal = (ssl3stats->hsh_sid_stateless_resumes == 0); |
+ else |
+ exitVal = (ssl3stats->hsh_sid_cache_misses > 1) || |
+ (ssl3stats->hsh_sid_stateless_resumes != 0); |
+ if (!exitVal) |
+ exitVal = (ssl3stats->hsh_sid_cache_not_ok != 0) || (certsTested > 1); |
+ } else { |
+ printf("strsclnt: NoReuse - %d server certificates tested.\n", certsTested); |
+ if (ssl3stats->hsh_sid_cache_hits + ssl3stats->hsh_sid_cache_misses + |
ssl3stats->hsh_sid_cache_not_ok + |
- ssl3stats->hsh_sid_stateless_resumes > 0) { |
- exitVal = (ssl3stats->hsh_sid_cache_misses != connections) || |
+ ssl3stats->hsh_sid_stateless_resumes > |
+ 0) { |
+ exitVal = (ssl3stats->hsh_sid_cache_misses != connections) || |
(ssl3stats->hsh_sid_stateless_resumes != 0) || |
(certsTested != connections); |
- } else { /* ssl2 connections */ |
- exitVal = (certsTested != connections); |
- } |
+ } else {/* ssl2 connections */ |
+ exitVal = (certsTested != connections); |
} |
+ } |
- exitVal = ( exitVal || failed_already ); |
- SSL_ClearSessionCache(); |
- if (NSS_Shutdown() != SECSuccess) { |
- printf("strsclnt: NSS_Shutdown() failed.\n"); |
- exit(1); |
- } |
+ exitVal = (exitVal || failed_already); |
+ SSL_ClearSessionCache(); |
+ if (NSS_Shutdown() != SECSuccess) { |
+ printf("strsclnt: NSS_Shutdown() failed.\n"); |
+ exit(1); |
+ } |
- PR_Cleanup(); |
- return exitVal; |
+ PR_Cleanup(); |
+ return exitVal; |
} |
- |