security/nss/cmd/strsclnt/strsclnt.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     4 #include <stdio.h>
     5 #include <string.h>
     7 #include "secutil.h"
     8 #include "basicutil.h"
    10 #if defined(XP_UNIX)
    11 #include <unistd.h>
    12 #endif
    13 #include <stdlib.h>
    14 #include <errno.h>
    15 #include <fcntl.h>
    16 #include <stdarg.h>
    18 #include "plgetopt.h"
    20 #include "nspr.h"
    21 #include "prio.h"
    22 #include "prnetdb.h"
    23 #include "prerror.h"
    25 #include "pk11func.h"
    26 #include "secitem.h"
    27 #include "sslproto.h"
    28 #include "nss.h"
    29 #include "ssl.h"
    31 #ifndef PORT_Sprintf
    32 #define PORT_Sprintf sprintf
    33 #endif
    35 #ifndef PORT_Strstr
    36 #define PORT_Strstr strstr
    37 #endif
    39 #ifndef PORT_Malloc
    40 #define PORT_Malloc PR_Malloc
    41 #endif
    43 #define RD_BUF_SIZE (60 * 1024)
    45 /* Include these cipher suite arrays to re-use tstclnt's 
    46  * cipher selection code.
    47  */
    49 int ssl2CipherSuites[] = {
    50     SSL_EN_RC4_128_WITH_MD5,                    /* A */
    51     SSL_EN_RC4_128_EXPORT40_WITH_MD5,           /* B */
    52     SSL_EN_RC2_128_CBC_WITH_MD5,                /* C */
    53     SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5,       /* D */
    54     SSL_EN_DES_64_CBC_WITH_MD5,                 /* E */
    55     SSL_EN_DES_192_EDE3_CBC_WITH_MD5,           /* F */
    56     0
    57 };
    59 int ssl3CipherSuites[] = {
    60     -1, /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
    61     -1, /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA     * b */
    62     TLS_RSA_WITH_RC4_128_MD5,                   /* c */
    63     TLS_RSA_WITH_3DES_EDE_CBC_SHA,              /* d */
    64     TLS_RSA_WITH_DES_CBC_SHA,                   /* e */
    65     TLS_RSA_EXPORT_WITH_RC4_40_MD5,             /* f */
    66     TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,         /* g */
    67     -1, /* SSL_FORTEZZA_DMS_WITH_NULL_SHA        * h */
    68     TLS_RSA_WITH_NULL_MD5,                      /* i */
    69     SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,         /* j */
    70     SSL_RSA_FIPS_WITH_DES_CBC_SHA,              /* k */
    71     TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, 	/* l */
    72     TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,		/* m */
    73     TLS_RSA_WITH_RC4_128_SHA,                   /* n */
    74     TLS_DHE_DSS_WITH_RC4_128_SHA,		/* o */
    75     TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,		/* p */
    76     TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,		/* q */
    77     TLS_DHE_RSA_WITH_DES_CBC_SHA,		/* r */
    78     TLS_DHE_DSS_WITH_DES_CBC_SHA,		/* s */
    79     TLS_DHE_DSS_WITH_AES_128_CBC_SHA, 	    	/* t */
    80     TLS_DHE_RSA_WITH_AES_128_CBC_SHA,       	/* u */
    81     TLS_RSA_WITH_AES_128_CBC_SHA,     	    	/* v */
    82     TLS_DHE_DSS_WITH_AES_256_CBC_SHA, 	    	/* w */
    83     TLS_DHE_RSA_WITH_AES_256_CBC_SHA,       	/* x */
    84     TLS_RSA_WITH_AES_256_CBC_SHA,     	    	/* y */
    85     TLS_RSA_WITH_NULL_SHA,			/* z */
    86     0
    87 };
    89 #define NO_FULLHS_PERCENTAGE -1
    91 /* This global string is so that client main can see 
    92  * which ciphers to use. 
    93  */
    95 static const char *cipherString;
    97 static PRInt32 certsTested;
    98 static int MakeCertOK;
    99 static int NoReuse;
   100 static int fullhs = NO_FULLHS_PERCENTAGE; /* percentage of full handshakes to
   101                                           ** perform */
   102 static PRInt32 globalconid = 0; /* atomically set */
   103 static int total_connections;  /* total number of connections to perform */
   104 static int total_connections_rounded_down_to_hundreds;
   105 static int total_connections_modulo_100;
   107 static PRBool NoDelay;
   108 static PRBool QuitOnTimeout = PR_FALSE;
   109 static PRBool ThrottleUp = PR_FALSE;
   111 static PRLock    * threadLock; /* protects the global variables below */
   112 static PRTime lastConnectFailure;
   113 static PRTime lastConnectSuccess;
   114 static PRTime lastThrottleUp;
   115 static PRInt32 remaining_connections;  /* number of connections left */
   116 static int active_threads = 8; /* number of threads currently trying to
   117                                ** connect */
   118 static PRInt32 numUsed;
   119 /* end of variables protected by threadLock */
   121 static SSL3Statistics * ssl3stats;
   123 static int failed_already = 0;
   124 static SSLVersionRange enabledVersions;
   125 static PRBool enableSSL2      = PR_TRUE;
   126 static PRBool bypassPKCS11    = PR_FALSE;
   127 static PRBool disableLocking  = PR_FALSE;
   128 static PRBool ignoreErrors    = PR_FALSE;
   129 static PRBool enableSessionTickets = PR_FALSE;
   130 static PRBool enableCompression    = PR_FALSE;
   131 static PRBool enableFalseStart     = PR_FALSE;
   132 static PRBool enableCertStatus     = PR_FALSE;
   134 PRIntervalTime maxInterval    = PR_INTERVAL_NO_TIMEOUT;
   136 char * progName;
   138 secuPWData pwdata = { PW_NONE, 0 };
   140 int	stopping;
   141 int	verbose;
   142 SECItem	bigBuf;
   144 #define PRINTF  if (verbose)  printf
   145 #define FPRINTF if (verbose) fprintf
   147 static void
   148 Usage(const char *progName)
   149 {
   150     fprintf(stderr, 
   151     	"Usage: %s [-n nickname] [-p port] [-d dbdir] [-c connections]\n"
   152  	"          [-BDNovqs] [-f filename] [-N | -P percentage]\n"
   153 	"          [-w dbpasswd] [-C cipher(s)] [-t threads] [-W pwfile]\n"
   154         "          [-V [min-version]:[max-version]] [-a sniHostName] hostname\n"
   155 	" where -v means verbose\n"
   156         "       -o flag is interpreted as follows:\n"
   157         "          1 -o   means override the result of server certificate validation.\n"
   158         "          2 -o's mean skip server certificate validation altogether.\n"
   159 	"       -D means no TCP delays\n"
   160 	"       -q means quit when server gone (timeout rather than retry forever)\n"
   161 	"       -s means disable SSL socket locking\n"
   162 	"       -N means no session reuse\n"
   163 	"       -P means do a specified percentage of full handshakes (0-100)\n"
   164         "       -V [min]:[max] restricts the set of enabled SSL/TLS protocols versions.\n"
   165         "          All versions are enabled by default.\n"
   166         "          Possible values for min/max: ssl2 ssl3 tls1.0 tls1.1 tls1.2\n"
   167         "          Example: \"-V ssl3:\" enables SSL 3 and newer.\n"
   168         "       -U means enable throttling up threads\n"
   169 	"       -B bypasses the PKCS11 layer for SSL encryption and MACing\n"
   170 	"       -T enable the cert_status extension (OCSP stapling)\n"
   171 	"       -u enable TLS Session Ticket extension\n"
   172 	"       -z enable compression\n"
   173 	"       -g enable false start\n",
   174 	progName);
   175     exit(1);
   176 }
   179 static void
   180 errWarn(char * funcString)
   181 {
   182     PRErrorCode  perr      = PR_GetError();
   183     PRInt32      oserr     = PR_GetOSError();
   184     const char * errString = SECU_Strerror(perr);
   186     fprintf(stderr, "strsclnt: %s returned error %d, OS error %d: %s\n",
   187             funcString, perr, oserr, errString);
   188 }
   190 static void
   191 errExit(char * funcString)
   192 {
   193     errWarn(funcString);
   194     exit(1);
   195 }
   197 /**************************************************************************
   198 ** 
   199 ** Routines for disabling SSL ciphers.
   200 **
   201 **************************************************************************/
   203 void
   204 disableAllSSLCiphers(void)
   205 {
   206     const PRUint16 *cipherSuites = SSL_GetImplementedCiphers();
   207     int             i            = SSL_GetNumImplementedCiphers();
   208     SECStatus       rv;
   210     /* disable all the SSL3 cipher suites */
   211     while (--i >= 0) {
   212 	PRUint16 suite = cipherSuites[i];
   213         rv = SSL_CipherPrefSetDefault(suite, PR_FALSE);
   214 	if (rv != SECSuccess) {
   215 	    printf("SSL_CipherPrefSetDefault didn't like value 0x%04x (i = %d)\n",
   216 	    	   suite, i);
   217 	    errWarn("SSL_CipherPrefSetDefault");
   218 	    exit(2);
   219 	}
   220     }
   221 }
   223 /* This invokes the "default" AuthCert handler in libssl.
   224 ** The only reason to use this one is that it prints out info as it goes. 
   225 */
   226 static SECStatus
   227 mySSLAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
   228 		     PRBool isServer)
   229 {
   230     SECStatus rv;
   231     CERTCertificate *    peerCert;
   232     const SECItemArray *csa;
   234     if (MakeCertOK>=2) {
   235         return SECSuccess;
   236     }
   237     peerCert = SSL_PeerCertificate(fd);
   239     PRINTF("strsclnt: Subject: %s\nstrsclnt: Issuer : %s\n", 
   240            peerCert->subjectName, peerCert->issuerName); 
   241     csa = SSL_PeerStapledOCSPResponses(fd);
   242     if (csa) {
   243         PRINTF("Received %d Cert Status items (OCSP stapled data)\n",
   244                csa->len);
   245     }
   246     /* invoke the "default" AuthCert handler. */
   247     rv = SSL_AuthCertificate(arg, fd, checkSig, isServer);
   249     PR_ATOMIC_INCREMENT(&certsTested);
   250     if (rv == SECSuccess) {
   251 	fputs("strsclnt: -- SSL: Server Certificate Validated.\n", stderr);
   252     }
   253     CERT_DestroyCertificate(peerCert);
   254     /* error, if any, will be displayed by the Bad Cert Handler. */
   255     return rv;  
   256 }
   258 static SECStatus
   259 myBadCertHandler( void *arg, PRFileDesc *fd)
   260 {
   261     PRErrorCode err = PR_GetError();
   262     if (!MakeCertOK)
   263 	fprintf(stderr, 
   264 	    "strsclnt: -- SSL: Server Certificate Invalid, err %d.\n%s\n", 
   265             err, SECU_Strerror(err));
   266     return (MakeCertOK ? SECSuccess : SECFailure);
   267 }
   269 void 
   270 printSecurityInfo(PRFileDesc *fd)
   271 {
   272     CERTCertificate * cert = NULL;
   273     SSL3Statistics * ssl3stats = SSL_GetStatistics();
   274     SECStatus result;
   275     SSLChannelInfo    channel;
   276     SSLCipherSuiteInfo suite;
   278     static int only_once;
   280     if (only_once && verbose < 2)
   281     	return;
   282     only_once = 1;
   284     result = SSL_GetChannelInfo(fd, &channel, sizeof channel);
   285     if (result == SECSuccess && 
   286         channel.length == sizeof channel && 
   287 	channel.cipherSuite) {
   288 	result = SSL_GetCipherSuiteInfo(channel.cipherSuite, 
   289 					&suite, sizeof suite);
   290 	if (result == SECSuccess) {
   291 	    FPRINTF(stderr, 
   292 	    "strsclnt: SSL version %d.%d using %d-bit %s with %d-bit %s MAC\n",
   293 	       channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
   294 	       suite.effectiveKeyBits, suite.symCipherName, 
   295 	       suite.macBits, suite.macAlgorithmName);
   296 	    FPRINTF(stderr, 
   297 	    "strsclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n"
   298 	    "          Compression: %s\n",
   299 	       channel.authKeyBits, suite.authAlgorithmName,
   300 	       channel.keaKeyBits,  suite.keaTypeName,
   301 	       channel.compressionMethodName);
   302     	}
   303     }
   305     cert = SSL_LocalCertificate(fd);
   306     if (!cert)
   307 	cert = SSL_PeerCertificate(fd);
   309     if (verbose && cert) {
   310 	char * ip = CERT_NameToAscii(&cert->issuer);
   311 	char * sp = CERT_NameToAscii(&cert->subject);
   312         if (sp) {
   313 	    fprintf(stderr, "strsclnt: subject DN: %s\n", sp);
   314 	    PORT_Free(sp);
   315 	}
   316         if (ip) {
   317 	    fprintf(stderr, "strsclnt: issuer  DN: %s\n", ip);
   318 	    PORT_Free(ip);
   319 	}
   320     }
   321     if (cert) {
   322 	CERT_DestroyCertificate(cert);
   323 	cert = NULL;
   324     }
   325     fprintf(stderr,
   326     	"strsclnt: %ld cache hits; %ld cache misses, %ld cache not reusable\n"
   327 	"          %ld stateless resumes\n",
   328     	ssl3stats->hsh_sid_cache_hits, 
   329 	ssl3stats->hsh_sid_cache_misses,
   330 	ssl3stats->hsh_sid_cache_not_ok,
   331 	ssl3stats->hsh_sid_stateless_resumes);
   333 }
   335 /**************************************************************************
   336 ** Begin thread management routines and data.
   337 **************************************************************************/
   339 #define MAX_THREADS 128
   341 typedef int startFn(void *a, void *b, int c);
   344 static PRInt32     numConnected;
   345 static int         max_threads;    /* peak threads allowed */
   347 typedef struct perThreadStr {
   348     void *	a;
   349     void *	b;
   350     int         tid;
   351     int         rv;
   352     startFn  *  startFunc;
   353     PRThread *  prThread;
   354     PRBool	inUse;
   355 } perThread;
   357 perThread threads[MAX_THREADS];
   359 void
   360 thread_wrapper(void * arg)
   361 {
   362     perThread * slot = (perThread *)arg;
   363     PRBool done = PR_FALSE;
   365     do {
   366         PRBool doop = PR_FALSE;
   367         PRBool dosleep = PR_FALSE;
   368         PRTime now = PR_Now();
   370         PR_Lock(threadLock);
   371         if (! (slot->tid < active_threads)) {
   372             /* this thread isn't supposed to be running */
   373             if (!ThrottleUp) {
   374                 /* we'll never need this thread again, so abort it */
   375                 done = PR_TRUE;
   376             } else if (remaining_connections > 0) {
   377                 /* we may still need this thread, so just sleep for 1s */
   378                 dosleep = PR_TRUE;
   379                 /* the conditions to trigger a throttle up are :
   380                 ** 1. last PR_Connect failure must have happened more than
   381                 **    10s ago
   382                 ** 2. last throttling up must have happened more than 0.5s ago
   383                 ** 3. there must be a more recent PR_Connect success than
   384                 **    failure
   385                 */
   386                 if ( (now - lastConnectFailure > 10 * PR_USEC_PER_SEC) &&
   387                     ( (!lastThrottleUp) || ( (now - lastThrottleUp) >=
   388                                              (PR_USEC_PER_SEC/2)) ) &&
   389                     (lastConnectSuccess > lastConnectFailure) ) {
   390                     /* try throttling up by one thread */
   391                     active_threads = PR_MIN(max_threads, active_threads+1);
   392                     fprintf(stderr,"active_threads set up to %d\n",
   393                             active_threads);
   394                     lastThrottleUp = PR_MAX(now, lastThrottleUp);
   395                 }
   396             } else {
   397                 /* no more connections left, we are done */
   398                 done = PR_TRUE;
   399             }
   400         } else {
   401             /* this thread should run */
   402             if (--remaining_connections >= 0) { /* protected by threadLock */
   403                 doop = PR_TRUE;
   404             } else {
   405                 done = PR_TRUE;
   406             }
   407         }
   408         PR_Unlock(threadLock);
   409         if (doop) {
   410             slot->rv = (* slot->startFunc)(slot->a, slot->b, slot->tid);
   411             PRINTF("strsclnt: Thread in slot %d returned %d\n", 
   412                    slot->tid, slot->rv);
   413         }
   414         if (dosleep) {
   415             PR_Sleep(PR_SecondsToInterval(1));
   416         }
   417     } while (!done && (!failed_already || ignoreErrors));
   418 }
   420 SECStatus
   421 launch_thread(
   422     startFn *	startFunc,
   423     void *	a,
   424     void *	b,
   425     int         tid)
   426 {
   427     PRUint32 i;
   428     perThread * slot;
   430     PR_Lock(threadLock);
   432     PORT_Assert(numUsed < MAX_THREADS);
   433     if (! (numUsed < MAX_THREADS)) {
   434         PR_Unlock(threadLock);
   435         return SECFailure;
   436     }
   438     i = numUsed++;
   439     slot = &threads[i];
   440     slot->a = a;
   441     slot->b = b;
   442     slot->tid = tid;
   444     slot->startFunc = startFunc;
   446     slot->prThread      = PR_CreateThread(PR_USER_THREAD,
   447                                       thread_wrapper, slot,
   448 				      PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
   449 				      PR_JOINABLE_THREAD, 0);
   450     if (slot->prThread == NULL) {
   451 	PR_Unlock(threadLock);
   452 	printf("strsclnt: Failed to launch thread!\n");
   453 	return SECFailure;
   454     } 
   456     slot->inUse   = 1;
   457     PR_Unlock(threadLock);
   458     PRINTF("strsclnt: Launched thread in slot %d \n", i);
   460     return SECSuccess;
   461 }
   463 /* join all the threads */
   464 int 
   465 reap_threads(void)
   466 {
   467     int         i;
   469     for (i = 0; i < MAX_THREADS; ++i) {
   470         if (threads[i].prThread) {
   471             PR_JoinThread(threads[i].prThread);
   472             threads[i].prThread = NULL;
   473         }
   474     }
   475     return 0;
   476 }
   478 void
   479 destroy_thread_data(void)
   480 {
   481     PORT_Memset(threads, 0, sizeof threads);
   483     if (threadLock) {
   484     	PR_DestroyLock(threadLock);
   485 	threadLock = NULL;
   486     }
   487 }
   489 void
   490 init_thread_data(void)
   491 {
   492     threadLock = PR_NewLock();
   493 }
   495 /**************************************************************************
   496 ** End   thread management routines.
   497 **************************************************************************/
   499 PRBool useModelSocket = PR_TRUE;
   501 static const char stopCmd[] = { "GET /stop " };
   502 static const char outHeader[] = {
   503     "HTTP/1.0 200 OK\r\n"
   504     "Server: Netscape-Enterprise/2.0a\r\n"
   505     "Date: Tue, 26 Aug 1997 22:10:05 GMT\r\n"
   506     "Content-type: text/plain\r\n"
   507     "\r\n"
   508 };
   510 struct lockedVarsStr {
   511     PRLock *	lock;
   512     int		count;
   513     int		waiters;
   514     PRCondVar *	condVar;
   515 };
   517 typedef struct lockedVarsStr lockedVars;
   519 void 
   520 lockedVars_Init( lockedVars * lv)
   521 {
   522     lv->count   = 0;
   523     lv->waiters = 0;
   524     lv->lock    = PR_NewLock();
   525     lv->condVar = PR_NewCondVar(lv->lock);
   526 }
   528 void
   529 lockedVars_Destroy( lockedVars * lv)
   530 {
   531     PR_DestroyCondVar(lv->condVar);
   532     lv->condVar = NULL;
   534     PR_DestroyLock(lv->lock);
   535     lv->lock = NULL;
   536 }
   538 void
   539 lockedVars_WaitForDone(lockedVars * lv)
   540 {
   541     PR_Lock(lv->lock);
   542     while (lv->count > 0) {
   543     	PR_WaitCondVar(lv->condVar, PR_INTERVAL_NO_TIMEOUT);
   544     }
   545     PR_Unlock(lv->lock);
   546 }
   548 int	/* returns count */
   549 lockedVars_AddToCount(lockedVars * lv, int addend)
   550 {
   551     int rv;
   553     PR_Lock(lv->lock);
   554     rv = lv->count += addend;
   555     if (rv <= 0) {
   556 	PR_NotifyCondVar(lv->condVar);
   557     }
   558     PR_Unlock(lv->lock);
   559     return rv;
   560 }
   562 int
   563 do_writes(
   564     void *       a,
   565     void *       b,
   566     int          c)
   567 {
   568     PRFileDesc *	ssl_sock	= (PRFileDesc *)a;
   569     lockedVars *	lv 		= (lockedVars *)b;
   570     int			sent  		= 0;
   571     int 		count		= 0;
   573     while (sent < bigBuf.len) {
   575 	count = PR_Send(ssl_sock, bigBuf.data + sent, bigBuf.len - sent, 
   576 	                0, maxInterval);
   577 	if (count < 0) {
   578 	    errWarn("PR_Send bigBuf");
   579 	    break;
   580 	}
   581 	FPRINTF(stderr, "strsclnt: PR_Send wrote %d bytes from bigBuf\n", 
   582 		count );
   583 	sent += count;
   584     }
   585     if (count >= 0) {	/* last write didn't fail. */
   586     	PR_Shutdown(ssl_sock, PR_SHUTDOWN_SEND);
   587     }
   589     /* notify the reader that we're done. */
   590     lockedVars_AddToCount(lv, -1);
   591     return (sent < bigBuf.len) ? SECFailure : SECSuccess;
   592 }
   594 int 
   595 handle_fdx_connection( PRFileDesc * ssl_sock, int connection)
   596 {
   597     SECStatus          result;
   598     int                firstTime = 1;
   599     int                countRead = 0;
   600     lockedVars         lv;
   601     char               *buf;
   604     lockedVars_Init(&lv);
   605     lockedVars_AddToCount(&lv, 1);
   607     /* Attempt to launch the writer thread. */
   608     result = launch_thread(do_writes, ssl_sock, &lv, connection);
   610     if (result != SECSuccess) 
   611     	goto cleanup;
   613     buf = PR_Malloc(RD_BUF_SIZE);
   615     if (buf) {
   616 	do {
   617 	    /* do reads here. */
   618 	    PRInt32 count;
   620 	    count = PR_Recv(ssl_sock, buf, RD_BUF_SIZE, 0, maxInterval);
   621 	    if (count < 0) {
   622 		errWarn("PR_Recv");
   623 		break;
   624 	    }
   625 	    countRead += count;
   626 	    FPRINTF(stderr, 
   627 		    "strsclnt: connection %d read %d bytes (%d total).\n", 
   628 		    connection, count, countRead );
   629 	    if (firstTime) {
   630 		firstTime = 0;
   631 		printSecurityInfo(ssl_sock);
   632 	    }
   633 	} while (lockedVars_AddToCount(&lv, 0) > 0);
   634 	PR_Free(buf);
   635 	buf = 0;
   636     }
   638     /* Wait for writer to finish */
   639     lockedVars_WaitForDone(&lv);
   640     lockedVars_Destroy(&lv);
   642     FPRINTF(stderr, 
   643     "strsclnt: connection %d read %d bytes total. -----------------------\n", 
   644     	    connection, countRead);
   646 cleanup:
   647     /* Caller closes the socket. */
   649     return SECSuccess;
   650 }
   652 const char request[] = {"GET /abc HTTP/1.0\r\n\r\n" };
   654 SECStatus
   655 handle_connection( PRFileDesc *ssl_sock, int tid)
   656 {
   657     int	    countRead = 0;
   658     PRInt32 rv;
   659     char    *buf;
   661     buf = PR_Malloc(RD_BUF_SIZE);
   662     if (!buf)
   663 	return SECFailure;
   665     /* compose the http request here. */
   667     rv = PR_Send(ssl_sock, request, strlen(request), 0, maxInterval);
   668     if (rv <= 0) {
   669 	errWarn("PR_Send");
   670 	PR_Free(buf);
   671 	buf = 0;
   672         failed_already = 1;
   673 	return SECFailure;
   674     }
   675     printSecurityInfo(ssl_sock);
   677     /* read until EOF */
   678     while (1) {
   679 	rv = PR_Recv(ssl_sock, buf, RD_BUF_SIZE, 0, maxInterval);
   680 	if (rv == 0) {
   681 	    break;	/* EOF */
   682 	}
   683 	if (rv < 0) {
   684 	    errWarn("PR_Recv");
   685 	    failed_already = 1;
   686 	    break;
   687 	}
   689 	countRead += rv;
   690 	FPRINTF(stderr,
   691                 "strsclnt: connection on thread %d read %d bytes (%d total).\n",
   692 		tid, rv, countRead );
   693     }
   694     PR_Free(buf);
   695     buf = 0;
   697     /* Caller closes the socket. */
   699     FPRINTF(stderr, 
   700     "strsclnt: connection on thread %d read %d bytes total. ---------\n", 
   701     	    tid, countRead);
   703     return SECSuccess;	/* success */
   704 }
   706 #define USE_SOCK_PEER_ID 1
   708 #ifdef USE_SOCK_PEER_ID
   710 PRInt32 lastFullHandshakePeerID;
   712 void
   713 myHandshakeCallback(PRFileDesc *socket, void *arg) 
   714 {
   715     PR_ATOMIC_SET(&lastFullHandshakePeerID, (PRInt32) arg);
   716 }
   718 #endif
   720 /* one copy of this function is launched in a separate thread for each
   721 ** connection to be made.
   722 */
   723 int
   724 do_connects(
   725     void *	a,
   726     void *	b,
   727     int         tid)
   728 {
   729     PRNetAddr  *        addr		= (PRNetAddr *)  a;
   730     PRFileDesc *        model_sock	= (PRFileDesc *) b;
   731     PRFileDesc *        ssl_sock	= 0;
   732     PRFileDesc *        tcp_sock	= 0;
   733     PRStatus	        prStatus;
   734     PRUint32            sleepInterval	= 50; /* milliseconds */
   735     SECStatus   	result;
   736     int                 rv 		= SECSuccess;
   737     PRSocketOptionData  opt;
   739 retry:
   741     tcp_sock = PR_OpenTCPSocket(addr->raw.family);
   742     if (tcp_sock == NULL) {
   743 	errExit("PR_OpenTCPSocket");
   744     }
   746     opt.option             = PR_SockOpt_Nonblocking;
   747     opt.value.non_blocking = PR_FALSE;
   748     prStatus = PR_SetSocketOption(tcp_sock, &opt);
   749     if (prStatus != PR_SUCCESS) {
   750 	errWarn("PR_SetSocketOption(PR_SockOpt_Nonblocking, PR_FALSE)");
   751     	PR_Close(tcp_sock);
   752 	return SECSuccess;
   753     } 
   755     if (NoDelay) {
   756 	opt.option         = PR_SockOpt_NoDelay;
   757 	opt.value.no_delay = PR_TRUE;
   758 	prStatus = PR_SetSocketOption(tcp_sock, &opt);
   759 	if (prStatus != PR_SUCCESS) {
   760 	    errWarn("PR_SetSocketOption(PR_SockOpt_NoDelay, PR_TRUE)");
   761 	    PR_Close(tcp_sock);
   762 	    return SECSuccess;
   763 	} 
   764     }
   766     prStatus = PR_Connect(tcp_sock, addr, PR_INTERVAL_NO_TIMEOUT);
   767     if (prStatus != PR_SUCCESS) {
   768         PRErrorCode err = PR_GetError(); /* save error code */
   769         PRInt32 oserr = PR_GetOSError();
   770         if (ThrottleUp) {
   771             PRTime now = PR_Now();
   772             PR_Lock(threadLock);
   773             lastConnectFailure = PR_MAX(now, lastConnectFailure);
   774             PR_Unlock(threadLock);
   775             PR_SetError(err, oserr); /* restore error code */
   776         }
   777         if ((err == PR_CONNECT_REFUSED_ERROR) || 
   778 	    (err == PR_CONNECT_RESET_ERROR)      ) {
   779 	    int connections = numConnected;
   781 	    PR_Close(tcp_sock);
   782             PR_Lock(threadLock);
   783             if (connections > 2 && active_threads >= connections) {
   784                 active_threads = connections - 1;
   785                 fprintf(stderr,"active_threads set down to %d\n",
   786                         active_threads);
   787             }
   788             PR_Unlock(threadLock);
   790             if (QuitOnTimeout && sleepInterval > 40000) {
   791                 fprintf(stderr,
   792 	            "strsclnt: Client timed out waiting for connection to server.\n");
   793                 exit(1);
   794             }
   795 	    PR_Sleep(PR_MillisecondsToInterval(sleepInterval));
   796 	    sleepInterval <<= 1;
   797 	    goto retry;
   798 	}
   799 	errWarn("PR_Connect");
   800 	rv = SECFailure;
   801 	goto done;
   802     } else {
   803         if (ThrottleUp) {
   804             PRTime now = PR_Now();
   805             PR_Lock(threadLock);
   806             lastConnectSuccess = PR_MAX(now, lastConnectSuccess);
   807             PR_Unlock(threadLock);
   808         }
   809     }
   811     ssl_sock = SSL_ImportFD(model_sock, tcp_sock);
   812     /* XXX if this import fails, close tcp_sock and return. */
   813     if (!ssl_sock) {
   814     	PR_Close(tcp_sock);
   815 	return SECSuccess;
   816     }
   817     if (fullhs != NO_FULLHS_PERCENTAGE) {
   818 #ifdef USE_SOCK_PEER_ID
   819         char sockPeerIDString[512];
   820         static PRInt32 sockPeerID = 0; /* atomically incremented */
   821         PRInt32 thisPeerID;
   822 #endif
   823         PRInt32 savid = PR_ATOMIC_INCREMENT(&globalconid);
   824         PRInt32 conid = 1 + (savid - 1) % 100;
   825         /* don't change peer ID on the very first handshake, which is always
   826            a full, so the session gets stored into the client cache */
   827         if ( (savid != 1) &&
   828             ( ( (savid <= total_connections_rounded_down_to_hundreds) &&
   829                 (conid <= fullhs) ) ||
   830               (conid*100 <= total_connections_modulo_100*fullhs ) ) ) 
   831 #ifdef USE_SOCK_PEER_ID
   832         {
   833             /* force a full handshake by changing the socket peer ID */
   834             thisPeerID = PR_ATOMIC_INCREMENT(&sockPeerID);
   835         } else {
   836             /* reuse previous sockPeerID for restart handhsake */
   837             thisPeerID = lastFullHandshakePeerID;
   838         }
   839         PR_snprintf(sockPeerIDString, sizeof(sockPeerIDString), "ID%d",
   840                     thisPeerID);
   841         SSL_SetSockPeerID(ssl_sock, sockPeerIDString);
   842         SSL_HandshakeCallback(ssl_sock, myHandshakeCallback, (void*)thisPeerID);
   843 #else
   844             /* force a full handshake by setting the no cache option */
   845             SSL_OptionSet(ssl_sock, SSL_NO_CACHE, 1);
   846 #endif
   847     }
   848     rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 0);
   849     if (rv != SECSuccess) {
   850 	errWarn("SSL_ResetHandshake");
   851 	goto done;
   852     }
   854     PR_ATOMIC_INCREMENT(&numConnected);
   856     if (bigBuf.data != NULL) {
   857 	result = handle_fdx_connection( ssl_sock, tid);
   858     } else {
   859 	result = handle_connection( ssl_sock, tid);
   860     }
   862     PR_ATOMIC_DECREMENT(&numConnected);
   864 done:
   865     if (ssl_sock) {
   866 	PR_Close(ssl_sock);
   867     } else if (tcp_sock) {
   868 	PR_Close(tcp_sock);
   869     }
   870     return SECSuccess;
   871 }
   874 typedef struct {
   875     PRLock* lock;
   876     char* nickname;
   877     CERTCertificate* cert;
   878     SECKEYPrivateKey* key;
   879     void* wincx;
   880 } cert_and_key;
   882 PRBool FindCertAndKey(cert_and_key* Cert_And_Key)
   883 {
   884     if ( (NULL == Cert_And_Key->nickname) || (0 == strcmp(Cert_And_Key->nickname,"none"))) {
   885         return PR_TRUE;
   886     }
   887     Cert_And_Key->cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
   888                             Cert_And_Key->nickname, certUsageSSLClient,
   889                             PR_FALSE, Cert_And_Key->wincx);
   890     if (Cert_And_Key->cert) {
   891         Cert_And_Key->key = PK11_FindKeyByAnyCert(Cert_And_Key->cert, Cert_And_Key->wincx);
   892     }
   893     if (Cert_And_Key->cert && Cert_And_Key->key) {
   894         return PR_TRUE;
   895     } else {
   896         return PR_FALSE;
   897     }
   898 }
   900 PRBool LoggedIn(CERTCertificate* cert, SECKEYPrivateKey* key)
   901 {
   902     if ( (cert->slot) && (key->pkcs11Slot) &&
   903          (PR_TRUE == PK11_IsLoggedIn(cert->slot, NULL)) &&
   904          (PR_TRUE == PK11_IsLoggedIn(key->pkcs11Slot, NULL)) ) {
   905         return PR_TRUE;
   906     }
   908     return PR_FALSE;
   909 }
   911 SECStatus 
   912 StressClient_GetClientAuthData(void * arg,
   913                       PRFileDesc * socket,
   914 		      struct CERTDistNamesStr * caNames,
   915 		      struct CERTCertificateStr ** pRetCert,
   916 		      struct SECKEYPrivateKeyStr **pRetKey)
   917 {
   918     cert_and_key* Cert_And_Key = (cert_and_key*) arg;
   920     if (!pRetCert || !pRetKey) {
   921         /* bad pointers, can't return a cert or key */
   922         return SECFailure;
   923     }
   925     *pRetCert = NULL;
   926     *pRetKey = NULL;
   928     if (Cert_And_Key && Cert_And_Key->nickname) {
   929         while (PR_TRUE) {
   930             if (Cert_And_Key && Cert_And_Key->lock) {
   931                 int timeout = 0;
   932                 PR_Lock(Cert_And_Key->lock);
   934                 if (Cert_And_Key->cert) {
   935                     *pRetCert = CERT_DupCertificate(Cert_And_Key->cert);
   936                 }
   938                 if (Cert_And_Key->key) {
   939                     *pRetKey = SECKEY_CopyPrivateKey(Cert_And_Key->key);
   940                 }
   941                 PR_Unlock(Cert_And_Key->lock);
   942                 if (!*pRetCert || !*pRetKey) {
   943                     /* one or both of them failed to copy. Either the source was NULL, or there was
   944                     ** an out of memory condition. Free any allocated copy and fail */
   945                     if (*pRetCert) {
   946                         CERT_DestroyCertificate(*pRetCert);
   947                         *pRetCert = NULL;
   948                     }
   949                     if (*pRetKey) {
   950                         SECKEY_DestroyPrivateKey(*pRetKey);
   951                         *pRetKey = NULL;
   952                     }
   953                     break;
   954                 }
   955                 /* now check if those objects are valid */
   956                 if ( PR_FALSE == LoggedIn(*pRetCert, *pRetKey) ) {
   957                     /* token is no longer logged in, it was removed */
   959                     /* first, delete and clear our invalid local objects */
   960                     CERT_DestroyCertificate(*pRetCert);
   961                     SECKEY_DestroyPrivateKey(*pRetKey);
   962                     *pRetCert = NULL;
   963                     *pRetKey = NULL;
   965                     PR_Lock(Cert_And_Key->lock);
   966                     /* check if another thread already logged back in */
   967                     if (PR_TRUE == LoggedIn(Cert_And_Key->cert, Cert_And_Key->key)) {
   968                         /* yes : try again */
   969                         PR_Unlock(Cert_And_Key->lock);
   970                         continue;
   971                     }
   972                     /* this is the thread to retry */
   973                     CERT_DestroyCertificate(Cert_And_Key->cert);
   974                     SECKEY_DestroyPrivateKey(Cert_And_Key->key);
   975                     Cert_And_Key->cert = NULL;
   976                     Cert_And_Key->key = NULL;
   979                     /* now look up the cert and key again */
   980                     while (PR_FALSE == FindCertAndKey(Cert_And_Key) ) {
   981                         PR_Sleep(PR_SecondsToInterval(1));
   982                         timeout++;
   983                         if (timeout>=60) {
   984                             printf("\nToken pulled and not reinserted early enough : aborting.\n");
   985                             exit(1);
   986                         }
   987                     }
   988                     PR_Unlock(Cert_And_Key->lock);
   989                     continue;
   990                     /* try again to reduce code size */
   991                 }
   992                 return SECSuccess;
   993             }
   994         }
   995         *pRetCert = NULL;
   996         *pRetKey = NULL;
   997         return SECFailure;
   998     } else {
   999         /* no cert configured, automatically find the right cert. */
  1000         CERTCertificate *  cert = NULL;
  1001         SECKEYPrivateKey * privkey = NULL;
  1002         CERTCertNicknames * names;
  1003         int                 i;
  1004         void *             proto_win = NULL;
  1005         SECStatus          rv         = SECFailure;
  1007         if (Cert_And_Key) {
  1008             proto_win = Cert_And_Key->wincx;
  1011         names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(),
  1012                                       SEC_CERT_NICKNAMES_USER, proto_win);
  1013         if (names != NULL) {
  1014             for (i = 0; i < names->numnicknames; i++) {
  1015                 cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
  1016                             names->nicknames[i], certUsageSSLClient,
  1017                             PR_FALSE, proto_win);	
  1018                 if ( !cert )
  1019                     continue;
  1020                 /* Only check unexpired certs */
  1021                 if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_TRUE) != 
  1022                                              secCertTimeValid ) {
  1023                     CERT_DestroyCertificate(cert);
  1024                     continue;
  1026                 rv = NSS_CmpCertChainWCANames(cert, caNames);
  1027                 if ( rv == SECSuccess ) {
  1028                     privkey = PK11_FindKeyByAnyCert(cert, proto_win);
  1029                     if ( privkey )
  1030                         break;
  1032                 rv = SECFailure;
  1033                 CERT_DestroyCertificate(cert);
  1035             CERT_FreeNicknames(names);
  1037         if (rv == SECSuccess) {
  1038             *pRetCert = cert;
  1039             *pRetKey  = privkey;
  1041         return rv;
  1045 int 
  1046 hexchar_to_int(int c) 
  1048     if (((c) >= '0') && ((c) <= '9'))
  1049 	return (c) - '0'; 
  1050     if (((c) >= 'a') && ((c) <= 'f'))
  1051 	return (c) - 'a' + 10;
  1052     if (((c) >= 'A') && ((c) <= 'F'))
  1053 	return (c) - 'A' + 10; 
  1054     failed_already = 1;
  1055     return -1;
  1058 void
  1059 client_main(
  1060     unsigned short      port, 
  1061     int                 connections,
  1062     cert_and_key* Cert_And_Key,
  1063     const char *	hostName,
  1064     const char *	sniHostName)
  1066     PRFileDesc *model_sock	= NULL;
  1067     int         i;
  1068     int         rv;
  1069     PRStatus    status;
  1070     PRNetAddr   addr;
  1072     status = PR_StringToNetAddr(hostName, &addr);
  1073     if (status == PR_SUCCESS) {
  1074     	addr.inet.port = PR_htons(port);
  1075     } else {
  1076 	/* Lookup host */
  1077 	PRAddrInfo *addrInfo;
  1078 	void       *enumPtr   = NULL;
  1080 	addrInfo = PR_GetAddrInfoByName(hostName, PR_AF_UNSPEC, 
  1081 	                                PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME);
  1082 	if (!addrInfo) {
  1083 	    SECU_PrintError(progName, "error looking up host");
  1084 	    return;
  1086 	do {
  1087 	    enumPtr = PR_EnumerateAddrInfo(enumPtr, addrInfo, port, &addr);
  1088 	} while (enumPtr != NULL &&
  1089 		 addr.raw.family != PR_AF_INET &&
  1090 		 addr.raw.family != PR_AF_INET6);
  1091 	PR_FreeAddrInfo(addrInfo);
  1092 	if (enumPtr == NULL) {
  1093 	    SECU_PrintError(progName, "error looking up host address");
  1094 	    return;
  1098     /* all suites except RSA_NULL_MD5 are enabled by Domestic Policy */
  1099     NSS_SetDomesticPolicy();
  1101     /* all the SSL2 and SSL3 cipher suites are enabled by default. */
  1102     if (cipherString) {
  1103         int ndx;
  1105         /* disable all the ciphers, then enable the ones we want. */
  1106         disableAllSSLCiphers();
  1108         while (0 != (ndx = *cipherString)) {
  1109 	    const char * startCipher = cipherString++;
  1110             int  cipher = 0;
  1111 	    SECStatus rv;
  1113 	    if (ndx == ':') {
  1114 		cipher  = hexchar_to_int(*cipherString++);
  1115 		cipher <<= 4;
  1116 		cipher |= hexchar_to_int(*cipherString++);
  1117 		cipher <<= 4;
  1118 		cipher |= hexchar_to_int(*cipherString++);
  1119 		cipher <<= 4;
  1120 		cipher |= hexchar_to_int(*cipherString++);
  1121 		if (cipher <= 0) {
  1122 		    fprintf(stderr, "strsclnt: Invalid cipher value: %-5.5s\n",
  1123 		                    startCipher);
  1124 		    failed_already = 1;
  1125 		    return;
  1127 	    } else {
  1128 		if (isalpha(ndx)) {
  1129 		    const int *cptr;
  1131 		    cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
  1132 		    for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; ) 
  1133 			/* do nothing */;
  1135 	    	if (cipher <= 0) {
  1136 		    fprintf(stderr, "strsclnt: Invalid cipher letter: %c\n", 
  1137 		                    *startCipher);
  1138 		    failed_already = 1;
  1139 		    return;
  1142 	    rv = SSL_CipherPrefSetDefault(cipher, PR_TRUE);
  1143 	    if (rv != SECSuccess) {
  1144 		fprintf(stderr, 
  1145 			"strsclnt: SSL_CipherPrefSetDefault(0x%04x) failed\n",
  1146 			cipher);
  1147 		failed_already = 1;
  1148 		return;
  1153     /* configure model SSL socket. */
  1155     model_sock = PR_OpenTCPSocket(addr.raw.family);
  1156     if (model_sock == NULL) {
  1157 	errExit("PR_OpenTCPSocket for model socket");
  1160     model_sock = SSL_ImportFD(NULL, model_sock);
  1161     if (model_sock == NULL) {
  1162 	errExit("SSL_ImportFD");
  1165     /* do SSL configuration. */
  1167     rv = SSL_OptionSet(model_sock, SSL_SECURITY,
  1168                        enableSSL2 || enabledVersions.min != 0);
  1169     if (rv < 0) {
  1170 	errExit("SSL_OptionSet SSL_SECURITY");
  1173     rv = SSL_VersionRangeSet(model_sock, &enabledVersions);
  1174     if (rv != SECSuccess) {
  1175         errExit("error setting SSL/TLS version range ");
  1178     rv = SSL_OptionSet(model_sock, SSL_ENABLE_SSL2, enableSSL2);
  1179     if (rv != SECSuccess) {
  1180        errExit("error enabling SSLv2 ");
  1183     rv = SSL_OptionSet(model_sock, SSL_V2_COMPATIBLE_HELLO, enableSSL2);
  1184     if (rv != SECSuccess) {
  1185         errExit("error enabling SSLv2 compatible hellos ");
  1188     if (bigBuf.data) { /* doing FDX */
  1189 	rv = SSL_OptionSet(model_sock, SSL_ENABLE_FDX, 1);
  1190 	if (rv < 0) {
  1191 	    errExit("SSL_OptionSet SSL_ENABLE_FDX");
  1195     if (NoReuse) {
  1196 	rv = SSL_OptionSet(model_sock, SSL_NO_CACHE, 1);
  1197 	if (rv < 0) {
  1198 	    errExit("SSL_OptionSet SSL_NO_CACHE");
  1202     if (bypassPKCS11) {
  1203 	rv = SSL_OptionSet(model_sock, SSL_BYPASS_PKCS11, 1);
  1204 	if (rv < 0) {
  1205 	    errExit("SSL_OptionSet SSL_BYPASS_PKCS11");
  1209     if (disableLocking) {
  1210         rv = SSL_OptionSet(model_sock, SSL_NO_LOCKS, 1);
  1211 	if (rv < 0) {
  1212 	    errExit("SSL_OptionSet SSL_NO_LOCKS");
  1216     if (enableSessionTickets) {
  1217 	rv = SSL_OptionSet(model_sock, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
  1218 	if (rv != SECSuccess)
  1219 	    errExit("SSL_OptionSet SSL_ENABLE_SESSION_TICKETS");
  1222     if (enableCompression) {
  1223 	rv = SSL_OptionSet(model_sock, SSL_ENABLE_DEFLATE, PR_TRUE);
  1224 	if (rv != SECSuccess)
  1225 	    errExit("SSL_OptionSet SSL_ENABLE_DEFLATE");
  1228     if (enableFalseStart) {
  1229 	rv = SSL_OptionSet(model_sock, SSL_ENABLE_FALSE_START, PR_TRUE);
  1230 	if (rv != SECSuccess)
  1231 	    errExit("SSL_OptionSet SSL_ENABLE_FALSE_START");
  1234     if (enableCertStatus) {
  1235 	rv = SSL_OptionSet(model_sock, SSL_ENABLE_OCSP_STAPLING, PR_TRUE);
  1236 	if (rv != SECSuccess)
  1237 	    errExit("SSL_OptionSet SSL_ENABLE_OCSP_STAPLING");
  1240     SSL_SetPKCS11PinArg(model_sock, &pwdata);
  1242     SSL_SetURL(model_sock, hostName);
  1244     SSL_AuthCertificateHook(model_sock, mySSLAuthCertificate, 
  1245 			(void *)CERT_GetDefaultCertDB());
  1246     SSL_BadCertHook(model_sock, myBadCertHandler, NULL);
  1248     SSL_GetClientAuthDataHook(model_sock, StressClient_GetClientAuthData, (void*)Cert_And_Key);
  1250     if (sniHostName) {
  1251         SSL_SetURL(model_sock, sniHostName);
  1253     /* I'm not going to set the HandshakeCallback function. */
  1255     /* end of ssl configuration. */
  1257     init_thread_data();
  1259     remaining_connections = total_connections = connections;
  1260     total_connections_modulo_100 = total_connections % 100;
  1261     total_connections_rounded_down_to_hundreds =
  1262         total_connections - total_connections_modulo_100;
  1264     if (!NoReuse) {
  1265         remaining_connections = 1;
  1266 	rv = launch_thread(do_connects, &addr, model_sock, 0);
  1267 	/* wait for the first connection to terminate, then launch the rest. */
  1268 	reap_threads();
  1269         remaining_connections = total_connections - 1 ;
  1271     if (remaining_connections > 0) {
  1272         active_threads  = PR_MIN(active_threads, remaining_connections);
  1273 	/* Start up the threads */
  1274 	for (i=0;i<active_threads;i++) {
  1275 	    rv = launch_thread(do_connects, &addr, model_sock, i);
  1277 	reap_threads();
  1279     destroy_thread_data();
  1281     PR_Close(model_sock);
  1284 SECStatus
  1285 readBigFile(const char * fileName)
  1287     PRFileInfo  info;
  1288     PRStatus	status;
  1289     SECStatus	rv	= SECFailure;
  1290     int		count;
  1291     int		hdrLen;
  1292     PRFileDesc *local_file_fd = NULL;
  1294     status = PR_GetFileInfo(fileName, &info);
  1296     if (status == PR_SUCCESS &&
  1297 	info.type == PR_FILE_FILE &&
  1298 	info.size > 0 &&
  1299 	NULL != (local_file_fd = PR_Open(fileName, PR_RDONLY, 0))) {
  1301 	hdrLen      = PORT_Strlen(outHeader);
  1302 	bigBuf.len  = hdrLen + info.size;
  1303 	bigBuf.data = PORT_Malloc(bigBuf.len + 4095);
  1304 	if (!bigBuf.data) {
  1305 	    errWarn("PORT_Malloc");
  1306 	    goto done;
  1309 	PORT_Memcpy(bigBuf.data, outHeader, hdrLen);
  1311 	count = PR_Read(local_file_fd, bigBuf.data + hdrLen, info.size);
  1312 	if (count != info.size) {
  1313 	    errWarn("PR_Read local file");
  1314 	    goto done;
  1316 	rv = SECSuccess;
  1317 done:
  1318 	PR_Close(local_file_fd);
  1320     return rv;
  1323 int
  1324 main(int argc, char **argv)
  1326     const char *         dir         = ".";
  1327     const char *         fileName    = NULL;
  1328     char *               hostName    = NULL;
  1329     char *               nickName    = NULL;
  1330     char *               tmp         = NULL;
  1331     int                  connections = 1;
  1332     int                  exitVal;
  1333     int                  tmpInt;
  1334     unsigned short       port        = 443;
  1335     SECStatus            rv;
  1336     PLOptState *         optstate;
  1337     PLOptStatus          status;
  1338     cert_and_key         Cert_And_Key;
  1339     char *               sniHostName = NULL;
  1341     /* Call the NSPR initialization routines */
  1342     PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
  1343     SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions);
  1345     tmp      = strrchr(argv[0], '/');
  1346     tmp      = tmp ? tmp + 1 : argv[0];
  1347     progName = strrchr(tmp, '\\');
  1348     progName = progName ? progName + 1 : tmp;
  1351     optstate = PL_CreateOptState(argc, argv,
  1352                                  "BC:DNP:TUV:W:a:c:d:f:gin:op:qst:uvw:z");
  1353     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
  1354 	switch(optstate->option) {
  1355 	case 'B': bypassPKCS11 = PR_TRUE; break;
  1357 	case 'C': cipherString = optstate->value; break;
  1359 	case 'D': NoDelay = PR_TRUE; break;
  1361 	case 'I': /* reserved for OCSP multi-stapling */ break;
  1363 	case 'N': NoReuse = 1; break;
  1365 	case 'P': fullhs = PORT_Atoi(optstate->value); break;
  1367 	case 'T': enableCertStatus = PR_TRUE; break;
  1369 	case 'U': ThrottleUp = PR_TRUE; break;
  1371         case 'V': if (SECU_ParseSSLVersionRangeString(optstate->value,
  1372                           enabledVersions, enableSSL2,
  1373                           &enabledVersions, &enableSSL2) != SECSuccess) {
  1374                       Usage(progName);
  1376                   break;
  1378 	case 'a': sniHostName = PL_strdup(optstate->value); break;
  1380 	case 'c': connections = PORT_Atoi(optstate->value); break;
  1382 	case 'd': dir = optstate->value; break;
  1384 	case 'f': fileName = optstate->value; break;
  1386 	case 'g': enableFalseStart = PR_TRUE; break;
  1388 	case 'i': ignoreErrors = PR_TRUE; break;
  1390         case 'n': nickName = PL_strdup(optstate->value); break;
  1392 	case 'o': MakeCertOK++; break;
  1394 	case 'p': port = PORT_Atoi(optstate->value); break;
  1396 	case 'q': QuitOnTimeout = PR_TRUE; break;
  1398 	case 's': disableLocking = PR_TRUE; break;
  1400 	case 't':
  1401 	    tmpInt = PORT_Atoi(optstate->value);
  1402 	    if (tmpInt > 0 && tmpInt < MAX_THREADS) 
  1403 	        max_threads = active_threads = tmpInt;
  1404 	    break;
  1406 	case 'u': enableSessionTickets = PR_TRUE; break;
  1408 	case 'v': verbose++; break;
  1410         case 'w':
  1411             pwdata.source = PW_PLAINTEXT;
  1412             pwdata.data = PL_strdup(optstate->value);
  1413             break;
  1415         case 'W':
  1416             pwdata.source = PW_FROMFILE;
  1417             pwdata.data = PL_strdup(optstate->value);
  1418             break;
  1420 	case 'z': enableCompression = PR_TRUE; break;
  1422 	case 0:   /* positional parameter */
  1423 	    if (hostName) {
  1424 		Usage(progName);
  1426 	    hostName = PL_strdup(optstate->value);
  1427 	    break;
  1429 	default:
  1430 	case '?':
  1431 	    Usage(progName);
  1432 	    break;
  1436     PL_DestroyOptState(optstate);
  1438     if (!hostName || status == PL_OPT_BAD)
  1439     	Usage(progName);
  1441     if (fullhs!= NO_FULLHS_PERCENTAGE && (fullhs < 0 || fullhs>100 || NoReuse) )
  1442         Usage(progName);
  1444     if (port == 0)
  1445 	Usage(progName);
  1447     if (fileName)
  1448     	readBigFile(fileName);
  1450     PK11_SetPasswordFunc(SECU_GetModulePassword);
  1452     tmp = PR_GetEnv("NSS_DEBUG_TIMEOUT");
  1453     if (tmp && tmp[0]) {
  1454         int sec = PORT_Atoi(tmp);
  1455 	if (sec > 0) {
  1456 	    maxInterval = PR_SecondsToInterval(sec);
  1460     /* Call the NSS initialization routines */
  1461     rv = NSS_Initialize(dir, "", "", SECMOD_DB, NSS_INIT_READONLY);
  1462     if (rv != SECSuccess) {
  1463     	fputs("NSS_Init failed.\n", stderr);
  1464 	exit(1);
  1466     ssl3stats = SSL_GetStatistics();
  1467     Cert_And_Key.lock = PR_NewLock();
  1468     Cert_And_Key.nickname = nickName;
  1469     Cert_And_Key.wincx = &pwdata;
  1470     Cert_And_Key.cert = NULL;
  1471     Cert_And_Key.key = NULL;
  1473     if (PR_FALSE == FindCertAndKey(&Cert_And_Key)) {
  1475 	if (Cert_And_Key.cert == NULL) {
  1476 	    fprintf(stderr, "strsclnt: Can't find certificate %s\n", Cert_And_Key.nickname);
  1477 	    exit(1);
  1480 	if (Cert_And_Key.key == NULL) {
  1481 	    fprintf(stderr, "strsclnt: Can't find Private Key for cert %s\n", 
  1482 		    Cert_And_Key.nickname);
  1483 	    exit(1);
  1488     client_main(port, connections, &Cert_And_Key, hostName,
  1489                 sniHostName);
  1491     /* clean up */
  1492     if (Cert_And_Key.cert) {
  1493 	CERT_DestroyCertificate(Cert_And_Key.cert);
  1495     if (Cert_And_Key.key) {
  1496 	SECKEY_DestroyPrivateKey(Cert_And_Key.key);
  1499     PR_DestroyLock(Cert_And_Key.lock);
  1501     if (pwdata.data) {
  1502         PL_strfree(pwdata.data);
  1504     if (Cert_And_Key.nickname) {
  1505         PL_strfree(Cert_And_Key.nickname);
  1507     if (sniHostName) {
  1508         PL_strfree(sniHostName);
  1511     PL_strfree(hostName);
  1513     /* some final stats. */
  1514     if (ssl3stats->hsh_sid_cache_hits +
  1515 	ssl3stats->hsh_sid_cache_misses +
  1516 	ssl3stats->hsh_sid_cache_not_ok +
  1517 	ssl3stats->hsh_sid_stateless_resumes == 0) {
  1518 	/* presumably we were testing SSL2. */
  1519 	printf("strsclnt: SSL2 - %d server certificates tested.\n",
  1520                certsTested);
  1521     } else {
  1522 	printf(
  1523 	"strsclnt: %ld cache hits; %ld cache misses, %ld cache not reusable\n"
  1524 	"          %ld stateless resumes\n",
  1525 	    ssl3stats->hsh_sid_cache_hits, 
  1526 	    ssl3stats->hsh_sid_cache_misses,
  1527 	    ssl3stats->hsh_sid_cache_not_ok,
  1528 	    ssl3stats->hsh_sid_stateless_resumes);
  1531     if (!NoReuse) {
  1532 	if (enableSessionTickets)
  1533 	    exitVal = (ssl3stats->hsh_sid_stateless_resumes == 0);
  1534 	else
  1535 	    exitVal = (ssl3stats->hsh_sid_cache_misses > 1) ||
  1536 		      (ssl3stats->hsh_sid_stateless_resumes != 0);
  1537 	if (!exitVal)
  1538 	    exitVal = (ssl3stats->hsh_sid_cache_not_ok != 0) ||
  1539 		      (certsTested > 1);
  1540     } else {
  1541 	printf("strsclnt: NoReuse - %d server certificates tested.\n",
  1542                certsTested);
  1543         if (ssl3stats->hsh_sid_cache_hits +
  1544             ssl3stats->hsh_sid_cache_misses +
  1545             ssl3stats->hsh_sid_cache_not_ok +
  1546             ssl3stats->hsh_sid_stateless_resumes > 0) {
  1547             exitVal = (ssl3stats->hsh_sid_cache_misses != connections) ||
  1548                 (ssl3stats->hsh_sid_stateless_resumes != 0) ||
  1549                 (certsTested != connections);
  1550         } else {                /* ssl2 connections */
  1551             exitVal = (certsTested != connections);
  1555     exitVal = ( exitVal || failed_already );
  1556     SSL_ClearSessionCache();
  1557     if (NSS_Shutdown() != SECSuccess) {
  1558         printf("strsclnt: NSS_Shutdown() failed.\n");
  1559         exit(1);
  1562     PR_Cleanup();
  1563     return exitVal;

mercurial