1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Mozilla Public License Version
5
* 1.1 (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
7
* http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* The Original Code is the Netscape security libraries.
16
* The Initial Developer of the Original Code is
17
* Netscape Communications Corporation.
18
* Portions created by the Initial Developer are Copyright (C) 1994-2000
19
* the Initial Developer. All Rights Reserved.
23
* Alternatively, the contents of this file may be used under the terms of
24
* either the GNU General Public License Version 2 or later (the "GPL"), or
25
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26
* in which case the provisions of the GPL or the LGPL are applicable instead
27
* of those above. If you wish to allow use of your version of this file only
28
* under the terms of either the GPL or the LGPL, and not to allow others to
29
* use your version of this file under the terms of the MPL, indicate your
30
* decision by deleting the provisions above and replace them with the notice
31
* and other provisions required by the GPL or the LGPL. If you do not delete
32
* the provisions above, a recipient may use your version of this file under
33
* the terms of any one of the MPL, the GPL or the LGPL.
35
* ***** END LICENSE BLOCK ***** */
45
#if !defined(_WIN32_WCE)
65
#define PORT_Sprintf sprintf
69
#define PORT_Strstr strstr
73
#define PORT_Malloc PR_Malloc
76
#define RD_BUF_SIZE (60 * 1024)
78
/* Include these cipher suite arrays to re-use tstclnt's
79
* cipher selection code.
82
int ssl2CipherSuites[] = {
83
SSL_EN_RC4_128_WITH_MD5, /* A */
84
SSL_EN_RC4_128_EXPORT40_WITH_MD5, /* B */
85
SSL_EN_RC2_128_CBC_WITH_MD5, /* C */
86
SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, /* D */
87
SSL_EN_DES_64_CBC_WITH_MD5, /* E */
88
SSL_EN_DES_192_EDE3_CBC_WITH_MD5, /* F */
92
int ssl3CipherSuites[] = {
93
-1, /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
94
-1, /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA * b */
95
SSL_RSA_WITH_RC4_128_MD5, /* c */
96
SSL_RSA_WITH_3DES_EDE_CBC_SHA, /* d */
97
SSL_RSA_WITH_DES_CBC_SHA, /* e */
98
SSL_RSA_EXPORT_WITH_RC4_40_MD5, /* f */
99
SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* g */
100
-1, /* SSL_FORTEZZA_DMS_WITH_NULL_SHA * h */
101
SSL_RSA_WITH_NULL_MD5, /* i */
102
SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, /* j */
103
SSL_RSA_FIPS_WITH_DES_CBC_SHA, /* k */
104
TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, /* l */
105
TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, /* m */
106
SSL_RSA_WITH_RC4_128_SHA, /* n */
107
TLS_DHE_DSS_WITH_RC4_128_SHA, /* o */
108
SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
109
SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
110
SSL_DHE_RSA_WITH_DES_CBC_SHA, /* r */
111
SSL_DHE_DSS_WITH_DES_CBC_SHA, /* s */
112
TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* t */
113
TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* u */
114
TLS_RSA_WITH_AES_128_CBC_SHA, /* v */
115
TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* w */
116
TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* x */
117
TLS_RSA_WITH_AES_256_CBC_SHA, /* y */
121
#define NO_FULLHS_PERCENTAGE -1
123
/* This global string is so that client main can see
124
* which ciphers to use.
127
static const char *cipherString;
129
static PRInt32 certsTested;
130
static int MakeCertOK;
132
static int fullhs = NO_FULLHS_PERCENTAGE; /* percentage of full handshakes to
134
static PRInt32 globalconid = 0; /* atomically set */
135
static int total_connections; /* total number of connections to perform */
136
static int total_connections_rounded_down_to_hundreds;
137
static int total_connections_modulo_100;
139
static PRBool NoDelay;
140
static PRBool QuitOnTimeout = PR_FALSE;
141
static PRBool ThrottleUp = PR_FALSE;
143
static PRLock * threadLock; /* protects the global variables below */
144
static PRTime lastConnectFailure;
145
static PRTime lastConnectSuccess;
146
static PRTime lastThrottleUp;
147
static PRInt32 remaining_connections; /* number of connections left */
148
static int active_threads = 8; /* number of threads currently trying to
150
static PRInt32 numUsed;
151
/* end of variables protected by threadLock */
153
static SSL3Statistics * ssl3stats;
155
static int failed_already = 0;
156
static PRBool disableSSL2 = PR_FALSE;
157
static PRBool disableSSL3 = PR_FALSE;
158
static PRBool disableTLS = PR_FALSE;
159
static PRBool bypassPKCS11 = PR_FALSE;
160
static PRBool disableLocking = PR_FALSE;
161
static PRBool ignoreErrors = PR_FALSE;
163
PRIntervalTime maxInterval = PR_INTERVAL_NO_TIMEOUT;
165
char * ownPasswd( PK11SlotInfo *slot, PRBool retry, void *arg)
169
if ( (!retry) && arg ) {
170
passwd = PL_strdup((char *)arg);
180
#define PRINTF if (verbose) printf
181
#define FPRINTF if (verbose) fprintf
184
Usage(const char *progName)
187
"Usage: %s [-n nickname] [-p port] [-d dbdir] [-c connections]\n"
188
" [-23BDNTovqs] [-f filename] [-N | -P percentage]\n"
189
" [-w dbpasswd] [-C cipher(s)] [-t threads] hostname\n"
190
" where -v means verbose\n"
191
" -o flag is interpreted as follows:\n"
192
" 1 -o means override the result of server certificate validation.\n"
193
" 2 -o's mean skip server certificate validation altogether.\n"
194
" -D means no TCP delays\n"
195
" -q means quit when server gone (timeout rather than retry forever)\n"
196
" -s means disable SSL socket locking\n"
197
" -N means no session reuse\n"
198
" -P means do a specified percentage of full handshakes (0-100)\n"
199
" -2 means disable SSL2\n"
200
" -3 means disable SSL3\n"
201
" -T means disable TLS\n"
202
" -U means enable throttling up threads\n"
203
" -B bypasses the PKCS11 layer for SSL encryption and MACing\n",
210
errWarn(char * funcString)
212
PRErrorCode perr = PR_GetError();
213
const char * errString = SECU_Strerror(perr);
215
fprintf(stderr, "strsclnt: %s returned error %d:\n%s\n",
216
funcString, perr, errString);
220
errExit(char * funcString)
226
/**************************************************************************
228
** Routines for disabling SSL ciphers.
230
**************************************************************************/
233
disableAllSSLCiphers(void)
235
const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
236
int i = SSL_NumImplementedCiphers;
239
/* disable all the SSL3 cipher suites */
241
PRUint16 suite = cipherSuites[i];
242
rv = SSL_CipherPrefSetDefault(suite, PR_FALSE);
243
if (rv != SECSuccess) {
244
printf("SSL_CipherPrefSetDefault didn't like value 0x%04x (i = %d)\n",
246
errWarn("SSL_CipherPrefSetDefault");
253
myGoodSSLAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
259
/* This invokes the "default" AuthCert handler in libssl.
260
** The only reason to use this one is that it prints out info as it goes.
263
mySSLAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
267
CERTCertificate * peerCert;
272
peerCert = SSL_PeerCertificate(fd);
274
PRINTF("strsclnt: Subject: %s\nstrsclnt: Issuer : %s\n",
275
peerCert->subjectName, peerCert->issuerName);
276
/* invoke the "default" AuthCert handler. */
277
rv = SSL_AuthCertificate(arg, fd, checkSig, isServer);
279
PR_AtomicIncrement(&certsTested);
280
if (rv == SECSuccess) {
281
fputs("strsclnt: -- SSL: Server Certificate Validated.\n", stderr);
283
CERT_DestroyCertificate(peerCert);
284
/* error, if any, will be displayed by the Bad Cert Handler. */
289
myBadCertHandler( void *arg, PRFileDesc *fd)
291
int err = PR_GetError();
294
"strsclnt: -- SSL: Server Certificate Invalid, err %d.\n%s\n",
295
err, SECU_Strerror(err));
296
return (MakeCertOK ? SECSuccess : SECFailure);
300
printSecurityInfo(PRFileDesc *fd)
302
CERTCertificate * cert = NULL;
303
SSL3Statistics * ssl3stats = SSL_GetStatistics();
305
SSLChannelInfo channel;
306
SSLCipherSuiteInfo suite;
308
static int only_once;
310
if (only_once && verbose < 2)
314
result = SSL_GetChannelInfo(fd, &channel, sizeof channel);
315
if (result == SECSuccess &&
316
channel.length == sizeof channel &&
317
channel.cipherSuite) {
318
result = SSL_GetCipherSuiteInfo(channel.cipherSuite,
319
&suite, sizeof suite);
320
if (result == SECSuccess) {
322
"strsclnt: SSL version %d.%d using %d-bit %s with %d-bit %s MAC\n",
323
channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
324
suite.effectiveKeyBits, suite.symCipherName,
325
suite.macBits, suite.macAlgorithmName);
327
"strsclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n",
328
channel.authKeyBits, suite.authAlgorithmName,
329
channel.keaKeyBits, suite.keaTypeName);
333
cert = SSL_LocalCertificate(fd);
335
cert = SSL_PeerCertificate(fd);
337
if (verbose && cert) {
338
char * ip = CERT_NameToAscii(&cert->issuer);
339
char * sp = CERT_NameToAscii(&cert->subject);
341
fprintf(stderr, "strsclnt: subject DN: %s\n", sp);
345
fprintf(stderr, "strsclnt: issuer DN: %s\n", ip);
350
CERT_DestroyCertificate(cert);
354
"strsclnt: %ld cache hits; %ld cache misses, %ld cache not reusable\n",
355
ssl3stats->hsh_sid_cache_hits,
356
ssl3stats->hsh_sid_cache_misses,
357
ssl3stats->hsh_sid_cache_not_ok);
361
/**************************************************************************
362
** Begin thread management routines and data.
363
**************************************************************************/
365
#define MAX_THREADS 128
367
typedef int startFn(void *a, void *b, int c);
370
static PRInt32 numConnected;
371
static int max_threads; /* peak threads allowed */
373
typedef struct perThreadStr {
383
perThread threads[MAX_THREADS];
386
thread_wrapper(void * arg)
388
perThread * slot = (perThread *)arg;
389
PRBool done = PR_FALSE;
392
PRBool doop = PR_FALSE;
393
PRBool dosleep = PR_FALSE;
394
PRTime now = PR_Now();
397
if (! (slot->tid < active_threads)) {
398
/* this thread isn't supposed to be running */
400
/* we'll never need this thread again, so abort it */
402
} else if (remaining_connections > 0) {
403
/* we may still need this thread, so just sleep for 1s */
405
/* the conditions to trigger a throttle up are :
406
** 1. last PR_Connect failure must have happened more than
408
** 2. last throttling up must have happened more than 0.5s ago
409
** 3. there must be a more recent PR_Connect success than
412
if ( (now - lastConnectFailure > 10 * PR_USEC_PER_SEC) &&
413
( (!lastThrottleUp) || ( (now - lastThrottleUp) >=
414
(PR_USEC_PER_SEC/2)) ) &&
415
(lastConnectSuccess > lastConnectFailure) ) {
416
/* try throttling up by one thread */
417
active_threads = PR_MIN(max_threads, active_threads+1);
418
fprintf(stderr,"active_threads set up to %d\n",
420
lastThrottleUp = PR_MAX(now, lastThrottleUp);
423
/* no more connections left, we are done */
427
/* this thread should run */
428
if (--remaining_connections >= 0) { /* protected by threadLock */
434
PR_Unlock(threadLock);
436
slot->rv = (* slot->startFunc)(slot->a, slot->b, slot->tid);
437
PRINTF("strsclnt: Thread in slot %d returned %d\n",
438
slot->tid, slot->rv);
441
PR_Sleep(PR_SecondsToInterval(1));
443
} while (!done && (!failed_already || ignoreErrors));
458
PORT_Assert(numUsed < MAX_THREADS);
459
if (! (numUsed < MAX_THREADS)) {
460
PR_Unlock(threadLock);
470
slot->startFunc = startFunc;
472
slot->prThread = PR_CreateThread(PR_USER_THREAD,
473
thread_wrapper, slot,
474
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
475
PR_JOINABLE_THREAD, 0);
476
if (slot->prThread == NULL) {
477
PR_Unlock(threadLock);
478
printf("strsclnt: Failed to launch thread!\n");
483
PR_Unlock(threadLock);
484
PRINTF("strsclnt: Launched thread in slot %d \n", i);
489
/* join all the threads */
495
for (i = 0; i < MAX_THREADS; ++i) {
496
if (threads[i].prThread) {
497
PR_JoinThread(threads[i].prThread);
498
threads[i].prThread = NULL;
505
destroy_thread_data(void)
507
PORT_Memset(threads, 0, sizeof threads);
510
PR_DestroyLock(threadLock);
516
init_thread_data(void)
518
threadLock = PR_NewLock();
521
/**************************************************************************
522
** End thread management routines.
523
**************************************************************************/
525
PRBool useModelSocket = PR_TRUE;
527
static const char stopCmd[] = { "GET /stop " };
528
static const char outHeader[] = {
529
"HTTP/1.0 200 OK\r\n"
530
"Server: Netscape-Enterprise/2.0a\r\n"
531
"Date: Tue, 26 Aug 1997 22:10:05 GMT\r\n"
532
"Content-type: text/plain\r\n"
536
struct lockedVarsStr {
543
typedef struct lockedVarsStr lockedVars;
546
lockedVars_Init( lockedVars * lv)
550
lv->lock = PR_NewLock();
551
lv->condVar = PR_NewCondVar(lv->lock);
555
lockedVars_Destroy( lockedVars * lv)
557
PR_DestroyCondVar(lv->condVar);
560
PR_DestroyLock(lv->lock);
565
lockedVars_WaitForDone(lockedVars * lv)
568
while (lv->count > 0) {
569
PR_WaitCondVar(lv->condVar, PR_INTERVAL_NO_TIMEOUT);
574
int /* returns count */
575
lockedVars_AddToCount(lockedVars * lv, int addend)
580
rv = lv->count += addend;
582
PR_NotifyCondVar(lv->condVar);
594
PRFileDesc * ssl_sock = (PRFileDesc *)a;
595
lockedVars * lv = (lockedVars *)b;
599
while (sent < bigBuf.len) {
601
count = PR_Send(ssl_sock, bigBuf.data + sent, bigBuf.len - sent,
604
errWarn("PR_Send bigBuf");
607
FPRINTF(stderr, "strsclnt: PR_Send wrote %d bytes from bigBuf\n",
611
if (count >= 0) { /* last write didn't fail. */
612
PR_Shutdown(ssl_sock, PR_SHUTDOWN_SEND);
615
/* notify the reader that we're done. */
616
lockedVars_AddToCount(lv, -1);
617
return (sent < bigBuf.len) ? SECFailure : SECSuccess;
621
handle_fdx_connection( PRFileDesc * ssl_sock, int connection)
630
lockedVars_Init(&lv);
631
lockedVars_AddToCount(&lv, 1);
633
/* Attempt to launch the writer thread. */
634
result = launch_thread(do_writes, ssl_sock, &lv, connection);
636
if (result != SECSuccess)
639
buf = PR_Malloc(RD_BUF_SIZE);
646
count = PR_Recv(ssl_sock, buf, RD_BUF_SIZE, 0, maxInterval);
653
"strsclnt: connection %d read %d bytes (%d total).\n",
654
connection, count, countRead );
657
printSecurityInfo(ssl_sock);
659
} while (lockedVars_AddToCount(&lv, 0) > 0);
664
/* Wait for writer to finish */
665
lockedVars_WaitForDone(&lv);
666
lockedVars_Destroy(&lv);
669
"strsclnt: connection %d read %d bytes total. -----------------------\n",
670
connection, countRead);
673
/* Caller closes the socket. */
678
const char request[] = {"GET /abc HTTP/1.0\r\n\r\n" };
681
handle_connection( PRFileDesc *ssl_sock, int tid)
687
buf = PR_Malloc(RD_BUF_SIZE);
691
/* compose the http request here. */
693
rv = PR_Send(ssl_sock, request, strlen(request), 0, maxInterval);
701
printSecurityInfo(ssl_sock);
705
rv = PR_Recv(ssl_sock, buf, RD_BUF_SIZE, 0, maxInterval);
717
"strsclnt: connection on thread %d read %d bytes (%d total).\n",
718
tid, rv, countRead );
723
/* Caller closes the socket. */
726
"strsclnt: connection on thread %d read %d bytes total. ---------\n",
729
return SECSuccess; /* success */
732
#define USE_SOCK_PEER_ID 1
734
#ifdef USE_SOCK_PEER_ID
736
PRInt32 lastFullHandshakePeerID;
739
myHandshakeCallback(PRFileDesc *socket, void *arg)
741
PR_AtomicSet(&lastFullHandshakePeerID, (PRInt32) arg);
747
/* one copy of this function is launched in a separate thread for each
748
** connection to be made.
756
PRNetAddr * addr = (PRNetAddr *) a;
757
PRFileDesc * model_sock = (PRFileDesc *) b;
758
PRFileDesc * ssl_sock = 0;
759
PRFileDesc * tcp_sock = 0;
761
PRUint32 sleepInterval = 50; /* milliseconds */
764
PRSocketOptionData opt;
768
tcp_sock = PR_NewTCPSocket();
769
if (tcp_sock == NULL) {
770
errExit("PR_NewTCPSocket");
773
opt.option = PR_SockOpt_Nonblocking;
774
opt.value.non_blocking = PR_FALSE;
775
prStatus = PR_SetSocketOption(tcp_sock, &opt);
776
if (prStatus != PR_SUCCESS) {
777
errWarn("PR_SetSocketOption(PR_SockOpt_Nonblocking, PR_FALSE)");
783
opt.option = PR_SockOpt_NoDelay;
784
opt.value.no_delay = PR_TRUE;
785
prStatus = PR_SetSocketOption(tcp_sock, &opt);
786
if (prStatus != PR_SUCCESS) {
787
errWarn("PR_SetSocketOption(PR_SockOpt_NoDelay, PR_TRUE)");
793
prStatus = PR_Connect(tcp_sock, addr, PR_INTERVAL_NO_TIMEOUT);
794
if (prStatus != PR_SUCCESS) {
795
PRErrorCode err = PR_GetError(); /* save error code */
797
PRTime now = PR_Now();
799
lastConnectFailure = PR_MAX(now, lastConnectFailure);
800
PR_Unlock(threadLock);
802
if ((err == PR_CONNECT_REFUSED_ERROR) ||
803
(err == PR_CONNECT_RESET_ERROR) ) {
804
int connections = numConnected;
808
if (connections > 2 && active_threads >= connections) {
809
active_threads = connections - 1;
810
fprintf(stderr,"active_threads set down to %d\n",
813
PR_Unlock(threadLock);
815
if (QuitOnTimeout && sleepInterval > 40000) {
817
"strsclnt: Client timed out waiting for connection to server.\n");
820
PR_Sleep(PR_MillisecondsToInterval(sleepInterval));
824
errWarn("PR_Connect");
829
PRTime now = PR_Now();
831
lastConnectSuccess = PR_MAX(now, lastConnectSuccess);
832
PR_Unlock(threadLock);
836
ssl_sock = SSL_ImportFD(model_sock, tcp_sock);
837
/* XXX if this import fails, close tcp_sock and return. */
842
if (fullhs != NO_FULLHS_PERCENTAGE) {
843
#ifdef USE_SOCK_PEER_ID
844
char sockPeerIDString[512];
845
static PRInt32 sockPeerID = 0; /* atomically incremented */
848
PRInt32 savid = PR_AtomicIncrement(&globalconid);
849
PRInt32 conid = 1 + (savid - 1) % 100;
850
/* don't change peer ID on the very first handshake, which is always
851
a full, so the session gets stored into the client cache */
853
( ( (savid <= total_connections_rounded_down_to_hundreds) &&
854
(conid <= fullhs) ) ||
855
(conid*100 <= total_connections_modulo_100*fullhs ) ) ) {
856
#ifdef USE_SOCK_PEER_ID
857
/* force a full handshake by changing the socket peer ID */
858
thisPeerID = PR_AtomicIncrement(&sockPeerID);
860
/* reuse previous sockPeerID for restart handhsake */
861
thisPeerID = lastFullHandshakePeerID;
863
PR_snprintf(sockPeerIDString, sizeof(sockPeerIDString), "ID%d",
865
SSL_SetSockPeerID(ssl_sock, sockPeerIDString);
866
SSL_HandshakeCallback(ssl_sock, myHandshakeCallback, (void*)thisPeerID);
868
/* force a full handshake by setting the no cache option */
869
SSL_OptionSet(ssl_sock, SSL_NO_CACHE, 1);
873
rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 0);
874
if (rv != SECSuccess) {
875
errWarn("SSL_ResetHandshake");
879
PR_AtomicIncrement(&numConnected);
881
if (bigBuf.data != NULL) {
882
result = handle_fdx_connection( ssl_sock, tid);
884
result = handle_connection( ssl_sock, tid);
887
PR_AtomicDecrement(&numConnected);
892
} else if (tcp_sock) {
898
/* Returns IP address for hostname as PRUint32 in Host Byte Order.
899
** Since the value returned is an integer (not a string of bytes),
900
** it is inherently in Host Byte Order.
903
getIPAddress(const char * hostName)
905
const unsigned char *p;
909
char scratch[PR_NETDB_BUF_SIZE];
911
prStatus = PR_GetHostByName(hostName, scratch, sizeof scratch, &prHostEnt);
912
if (prStatus != PR_SUCCESS)
913
errExit("PR_GetHostByName");
916
#define h_addr h_addr_list[0] /* address, for backward compatibility */
918
p = (const unsigned char *)(prHostEnt.h_addr); /* in Network Byte order */
919
FPRINTF(stderr, "strsclnt: %s -> %d.%d.%d.%d\n", hostName,
920
p[0], p[1], p[2], p[3]);
921
rv = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
928
CERTCertificate* cert;
929
SECKEYPrivateKey* key;
933
PRBool FindCertAndKey(cert_and_key* Cert_And_Key)
935
if ( (NULL == Cert_And_Key->nickname) || (0 == strcmp(Cert_And_Key->nickname,"none"))) {
938
Cert_And_Key->cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
939
Cert_And_Key->nickname, certUsageSSLClient,
940
PR_FALSE, Cert_And_Key->password);
941
if (Cert_And_Key->cert) {
942
Cert_And_Key->key = PK11_FindKeyByAnyCert(Cert_And_Key->cert, Cert_And_Key->password);
944
if (Cert_And_Key->cert && Cert_And_Key->key) {
951
PRBool LoggedIn(CERTCertificate* cert, SECKEYPrivateKey* key)
953
if ( (cert->slot) && (key->pkcs11Slot) &&
954
(PR_TRUE == PK11_IsLoggedIn(cert->slot, NULL)) &&
955
(PR_TRUE == PK11_IsLoggedIn(key->pkcs11Slot, NULL)) ) {
963
StressClient_GetClientAuthData(void * arg,
965
struct CERTDistNamesStr * caNames,
966
struct CERTCertificateStr ** pRetCert,
967
struct SECKEYPrivateKeyStr **pRetKey)
969
cert_and_key* Cert_And_Key = (cert_and_key*) arg;
971
if (!pRetCert || !pRetKey) {
972
/* bad pointers, can't return a cert or key */
979
if (Cert_And_Key && Cert_And_Key->nickname) {
981
if (Cert_And_Key && Cert_And_Key->lock) {
983
PR_Lock(Cert_And_Key->lock);
985
if (Cert_And_Key->cert) {
986
*pRetCert = CERT_DupCertificate(Cert_And_Key->cert);
989
if (Cert_And_Key->key) {
990
*pRetKey = SECKEY_CopyPrivateKey(Cert_And_Key->key);
992
PR_Unlock(Cert_And_Key->lock);
993
if (!*pRetCert || !*pRetKey) {
994
/* one or both of them failed to copy. Either the source was NULL, or there was
995
** an out of memory condition. Free any allocated copy and fail */
997
CERT_DestroyCertificate(*pRetCert);
1001
SECKEY_DestroyPrivateKey(*pRetKey);
1006
/* now check if those objects are valid */
1007
if ( PR_FALSE == LoggedIn(*pRetCert, *pRetKey) ) {
1008
/* token is no longer logged in, it was removed */
1010
/* first, delete and clear our invalid local objects */
1011
CERT_DestroyCertificate(*pRetCert);
1012
SECKEY_DestroyPrivateKey(*pRetKey);
1016
PR_Lock(Cert_And_Key->lock);
1017
/* check if another thread already logged back in */
1018
if (PR_TRUE == LoggedIn(Cert_And_Key->cert, Cert_And_Key->key)) {
1019
/* yes : try again */
1020
PR_Unlock(Cert_And_Key->lock);
1023
/* this is the thread to retry */
1024
CERT_DestroyCertificate(Cert_And_Key->cert);
1025
SECKEY_DestroyPrivateKey(Cert_And_Key->key);
1026
Cert_And_Key->cert = NULL;
1027
Cert_And_Key->key = NULL;
1030
/* now look up the cert and key again */
1031
while (PR_FALSE == FindCertAndKey(Cert_And_Key) ) {
1032
PR_Sleep(PR_SecondsToInterval(1));
1035
printf("\nToken pulled and not reinserted early enough : aborting.\n");
1039
PR_Unlock(Cert_And_Key->lock);
1041
/* try again to reduce code size */
1050
/* no cert configured, automatically find the right cert. */
1051
CERTCertificate * cert = NULL;
1052
SECKEYPrivateKey * privkey = NULL;
1053
CERTCertNicknames * names;
1055
void * proto_win = NULL;
1056
SECStatus rv = SECFailure;
1059
proto_win = Cert_And_Key->password;
1062
names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(),
1063
SEC_CERT_NICKNAMES_USER, proto_win);
1064
if (names != NULL) {
1065
for (i = 0; i < names->numnicknames; i++) {
1066
cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
1067
names->nicknames[i], certUsageSSLClient,
1068
PR_FALSE, proto_win);
1071
/* Only check unexpired certs */
1072
if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_TRUE) !=
1073
secCertTimeValid ) {
1074
CERT_DestroyCertificate(cert);
1077
rv = NSS_CmpCertChainWCANames(cert, caNames);
1078
if ( rv == SECSuccess ) {
1079
privkey = PK11_FindKeyByAnyCert(cert, proto_win);
1084
CERT_DestroyCertificate(cert);
1086
CERT_FreeNicknames(names);
1088
if (rv == SECSuccess) {
1096
#define HEXCHAR_TO_INT(c, i) \
1097
if (((c) >= '0') && ((c) <= '9')) { \
1099
} else if (((c) >= 'a') && ((c) <= 'f')) { \
1100
i = (c) - 'a' + 10; \
1101
} else if (((c) >= 'A') && ((c) <= 'F')) { \
1102
i = (c) - 'A' + 10; \
1104
Usage("strsclnt"); \
1109
unsigned short port,
1111
cert_and_key* Cert_And_Key,
1112
const char * hostName)
1114
PRFileDesc *model_sock = NULL;
1117
PRUint32 ipAddress; /* in host byte order */
1120
/* Assemble NetAddr struct for connections. */
1121
ipAddress = getIPAddress(hostName);
1123
addr.inet.family = PR_AF_INET;
1124
addr.inet.port = PR_htons(port);
1125
addr.inet.ip = PR_htonl(ipAddress);
1127
/* all suites except RSA_NULL_MD5 are enabled by Domestic Policy */
1128
NSS_SetDomesticPolicy();
1130
/* all the SSL2 and SSL3 cipher suites are enabled by default. */
1134
/* disable all the ciphers, then enable the ones we want. */
1135
disableAllSSLCiphers();
1137
while (0 != (ndx = *cipherString++)) {
1144
HEXCHAR_TO_INT(*cipherString, ctmp)
1145
cipher |= (ctmp << 12);
1147
HEXCHAR_TO_INT(*cipherString, ctmp)
1148
cipher |= (ctmp << 8);
1150
HEXCHAR_TO_INT(*cipherString, ctmp)
1151
cipher |= (ctmp << 4);
1153
HEXCHAR_TO_INT(*cipherString, ctmp)
1161
cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
1162
for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; )
1167
rv = SSL_CipherPrefSetDefault(cipher, PR_TRUE);
1168
if (rv != SECSuccess) {
1170
"strsclnt: SSL_CipherPrefSetDefault failed with value 0x%04x\n",
1180
/* configure model SSL socket. */
1182
model_sock = PR_NewTCPSocket();
1183
if (model_sock == NULL) {
1184
errExit("PR_NewTCPSocket on model socket");
1187
model_sock = SSL_ImportFD(NULL, model_sock);
1188
if (model_sock == NULL) {
1189
errExit("SSL_ImportFD");
1192
/* do SSL configuration. */
1194
rv = SSL_OptionSet(model_sock, SSL_SECURITY, 1);
1196
errExit("SSL_OptionSet SSL_SECURITY");
1199
/* disabling SSL2 compatible hellos also disables SSL2 */
1200
rv = SSL_OptionSet(model_sock, SSL_V2_COMPATIBLE_HELLO, !disableSSL2);
1201
if (rv != SECSuccess) {
1202
errExit("error enabling SSLv2 compatible hellos ");
1205
rv = SSL_OptionSet(model_sock, SSL_ENABLE_SSL3, !disableSSL3);
1206
if (rv != SECSuccess) {
1207
errExit("error enabling SSLv3 ");
1210
rv = SSL_OptionSet(model_sock, SSL_ENABLE_TLS, !disableTLS);
1211
if (rv != SECSuccess) {
1212
errExit("error enabling TLS ");
1215
if (bigBuf.data) { /* doing FDX */
1216
rv = SSL_OptionSet(model_sock, SSL_ENABLE_FDX, 1);
1218
errExit("SSL_OptionSet SSL_ENABLE_FDX");
1223
rv = SSL_OptionSet(model_sock, SSL_NO_CACHE, 1);
1225
errExit("SSL_OptionSet SSL_NO_CACHE");
1230
rv = SSL_OptionSet(model_sock, SSL_BYPASS_PKCS11, 1);
1232
errExit("SSL_OptionSet SSL_BYPASS_PKCS11");
1236
if (disableLocking) {
1237
rv = SSL_OptionSet(model_sock, SSL_NO_LOCKS, 1);
1239
errExit("SSL_OptionSet SSL_NO_LOCKS");
1243
SSL_SetURL(model_sock, hostName);
1245
SSL_AuthCertificateHook(model_sock, mySSLAuthCertificate,
1246
(void *)CERT_GetDefaultCertDB());
1247
SSL_BadCertHook(model_sock, myBadCertHandler, NULL);
1249
SSL_GetClientAuthDataHook(model_sock, StressClient_GetClientAuthData, (void*)Cert_And_Key);
1251
/* I'm not going to set the HandshakeCallback function. */
1253
/* end of ssl configuration. */
1257
remaining_connections = total_connections = connections;
1258
total_connections_modulo_100 = total_connections % 100;
1259
total_connections_rounded_down_to_hundreds =
1260
total_connections - total_connections_modulo_100;
1263
remaining_connections = 1;
1264
rv = launch_thread(do_connects, &addr, model_sock, 0);
1265
/* wait for the first connection to terminate, then launch the rest. */
1267
remaining_connections = total_connections - 1 ;
1269
if (remaining_connections > 0) {
1270
active_threads = PR_MIN(active_threads, remaining_connections);
1271
/* Start up the threads */
1272
for (i=0;i<active_threads;i++) {
1273
rv = launch_thread(do_connects, &addr, model_sock, i);
1277
destroy_thread_data();
1279
PR_Close(model_sock);
1283
readBigFile(const char * fileName)
1287
SECStatus rv = SECFailure;
1290
PRFileDesc *local_file_fd = NULL;
1292
status = PR_GetFileInfo(fileName, &info);
1294
if (status == PR_SUCCESS &&
1295
info.type == PR_FILE_FILE &&
1297
NULL != (local_file_fd = PR_Open(fileName, PR_RDONLY, 0))) {
1299
hdrLen = PORT_Strlen(outHeader);
1300
bigBuf.len = hdrLen + info.size;
1301
bigBuf.data = PORT_Malloc(bigBuf.len + 4095);
1303
errWarn("PORT_Malloc");
1307
PORT_Memcpy(bigBuf.data, outHeader, hdrLen);
1309
count = PR_Read(local_file_fd, bigBuf.data + hdrLen, info.size);
1310
if (count != info.size) {
1311
errWarn("PR_Read local file");
1316
PR_Close(local_file_fd);
1322
main(int argc, char **argv)
1324
const char * dir = ".";
1325
const char * fileName = NULL;
1326
char * hostName = NULL;
1327
char * nickName = NULL;
1328
char * progName = NULL;
1330
char * passwd = NULL;
1331
int connections = 1;
1334
unsigned short port = 443;
1336
PLOptState * optstate;
1338
cert_and_key Cert_And_Key;
1340
/* Call the NSPR initialization routines */
1341
PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
1343
tmp = strrchr(argv[0], '/');
1344
tmp = tmp ? tmp + 1 : argv[0];
1345
progName = strrchr(tmp, '\\');
1346
progName = progName ? progName + 1 : tmp;
1349
optstate = PL_CreateOptState(argc, argv, "23BC:DNP:TUc:d:f:in:op:qst:vw:");
1350
while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
1351
switch(optstate->option) {
1353
case '2': disableSSL2 = PR_TRUE; break;
1355
case '3': disableSSL3 = PR_TRUE; break;
1357
case 'B': bypassPKCS11 = PR_TRUE; break;
1359
case 'C': cipherString = optstate->value; break;
1361
case 'D': NoDelay = PR_TRUE; break;
1363
case 'N': NoReuse = 1; break;
1365
case 'P': fullhs = PORT_Atoi(optstate->value); break;
1367
case 'T': disableTLS = PR_TRUE; break;
1369
case 'U': ThrottleUp = PR_TRUE; break;
1371
case 'c': connections = PORT_Atoi(optstate->value); break;
1373
case 'd': dir = optstate->value; break;
1375
case 'f': fileName = optstate->value; break;
1377
case 'i': ignoreErrors = PR_TRUE; break;
1379
case 'n': nickName = PL_strdup(optstate->value); break;
1381
case 'o': MakeCertOK++; break;
1383
case 'p': port = PORT_Atoi(optstate->value); break;
1385
case 'q': QuitOnTimeout = PR_TRUE; break;
1387
case 's': disableLocking = PR_TRUE; break;
1390
tmpInt = PORT_Atoi(optstate->value);
1391
if (tmpInt > 0 && tmpInt < MAX_THREADS)
1392
max_threads = active_threads = tmpInt;
1395
case 'v': verbose++; break;
1397
case 'w': passwd = PL_strdup(optstate->value); break;
1399
case 0: /* positional parameter */
1403
hostName = PL_strdup(optstate->value);
1413
if (!hostName || status == PL_OPT_BAD)
1416
if (fullhs!= NO_FULLHS_PERCENTAGE && (fullhs < 0 || fullhs>100 || NoReuse) )
1423
readBigFile(fileName);
1425
/* set our password function */
1427
PK11_SetPasswordFunc(ownPasswd);
1429
PK11_SetPasswordFunc(SECU_GetModulePassword);
1432
tmp = PR_GetEnv("NSS_DEBUG_TIMEOUT");
1433
if (tmp && tmp[0]) {
1434
int sec = PORT_Atoi(tmp);
1436
maxInterval = PR_SecondsToInterval(sec);
1440
/* Call the libsec initialization routines */
1441
rv = NSS_Initialize(dir, "", "", SECMOD_DB, NSS_INIT_READONLY);
1442
if (rv != SECSuccess) {
1443
fputs("NSS_Init failed.\n", stderr);
1446
ssl3stats = SSL_GetStatistics();
1447
Cert_And_Key.lock = PR_NewLock();
1448
Cert_And_Key.nickname = nickName;
1449
Cert_And_Key.password = passwd;
1450
Cert_And_Key.cert = NULL;
1451
Cert_And_Key.key = NULL;
1453
if (PR_FALSE == FindCertAndKey(&Cert_And_Key)) {
1455
if (Cert_And_Key.cert == NULL) {
1456
fprintf(stderr, "strsclnt: Can't find certificate %s\n", Cert_And_Key.nickname);
1460
if (Cert_And_Key.key == NULL) {
1461
fprintf(stderr, "strsclnt: Can't find Private Key for cert %s\n",
1462
Cert_And_Key.nickname);
1468
client_main(port, connections, &Cert_And_Key, hostName);
1471
if (Cert_And_Key.cert) {
1472
CERT_DestroyCertificate(Cert_And_Key.cert);
1474
if (Cert_And_Key.key) {
1475
SECKEY_DestroyPrivateKey(Cert_And_Key.key);
1477
PR_DestroyLock(Cert_And_Key.lock);
1479
/* some final stats. */
1480
if (ssl3stats->hsh_sid_cache_hits + ssl3stats->hsh_sid_cache_misses +
1481
ssl3stats->hsh_sid_cache_not_ok == 0) {
1482
/* presumably we were testing SSL2. */
1483
printf("strsclnt: SSL2 - %d server certificates tested.\n",
1487
"strsclnt: %ld cache hits; %ld cache misses, %ld cache not reusable\n",
1488
ssl3stats->hsh_sid_cache_hits,
1489
ssl3stats->hsh_sid_cache_misses,
1490
ssl3stats->hsh_sid_cache_not_ok);
1494
exitVal = (ssl3stats->hsh_sid_cache_misses > 1) ||
1495
(ssl3stats->hsh_sid_cache_not_ok != 0) ||
1498
printf("strsclnt: NoReuse - %d server certificates tested.\n",
1500
if (ssl3stats->hsh_sid_cache_hits + ssl3stats->hsh_sid_cache_misses +
1501
ssl3stats->hsh_sid_cache_not_ok > 0) {
1502
exitVal = (ssl3stats->hsh_sid_cache_misses != connections) ||
1503
(certsTested != connections);
1504
} else { /* ssl2 connections */
1505
exitVal = (certsTested != connections);
1509
exitVal = ( exitVal || failed_already );
1510
SSL_ClearSessionCache();
1511
if (NSS_Shutdown() != SECSuccess) {
1512
printf("strsclnt: NSS_Shutdown() failed.\n");