summaryrefslogtreecommitdiff
path: root/security/nss/cmd/strsclnt/strsclnt.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/cmd/strsclnt/strsclnt.c')
-rw-r--r--security/nss/cmd/strsclnt/strsclnt.c1350
1 files changed, 0 insertions, 1350 deletions
diff --git a/security/nss/cmd/strsclnt/strsclnt.c b/security/nss/cmd/strsclnt/strsclnt.c
deleted file mode 100644
index 81972d139..000000000
--- a/security/nss/cmd/strsclnt/strsclnt.c
+++ /dev/null
@@ -1,1350 +0,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1994-2000 Netscape Communications Corporation. All
- * Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- */
-#include <stdio.h>
-#include <string.h>
-
-#include "secutil.h"
-
-#if defined(XP_UNIX)
-#include <unistd.h>
-#endif
-#include <stdlib.h>
-#if !defined(_WIN32_WCE)
-#include <errno.h>
-#include <fcntl.h>
-#endif
-#include <stdarg.h>
-
-#include "plgetopt.h"
-
-#include "nspr.h"
-#include "prio.h"
-#include "prnetdb.h"
-#include "prerror.h"
-
-#include "pk11func.h"
-#include "secitem.h"
-#include "sslproto.h"
-#include "nss.h"
-#include "ssl.h"
-
-#ifndef PORT_Sprintf
-#define PORT_Sprintf sprintf
-#endif
-
-#ifndef PORT_Strstr
-#define PORT_Strstr strstr
-#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
- * 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 */
-#ifdef NSS_ENABLE_ECC
- /* NOTE: Since no new SSL2 ciphersuites are being
- * invented, and we've run out of lowercase letters
- * for SSL3 ciphers, we use letters G and beyond
- * for new SSL3 ciphers.
- */
- TLS_ECDH_ECDSA_WITH_NULL_SHA, /* G */
- TLS_ECDH_ECDSA_WITH_RC4_128_SHA, /* H */
- TLS_ECDH_ECDSA_WITH_DES_CBC_SHA, /* I */
- TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, /* J */
- TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, /* K */
- TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, /* L */
- TLS_ECDH_RSA_WITH_NULL_SHA, /* M */
- TLS_ECDH_RSA_WITH_RC4_128_SHA, /* N */
- TLS_ECDH_RSA_WITH_DES_CBC_SHA, /* O */
- TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, /* P */
- TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, /* Q */
- TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, /* R */
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, /* S */
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, /* T */
-#endif /* NSS_ENABLE_ECC */
- 0
-};
-
-int ssl3CipherSuites[] = {
- SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, /* a */
- SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, /* b */
- SSL_RSA_WITH_RC4_128_MD5, /* c */
- SSL_RSA_WITH_3DES_EDE_CBC_SHA, /* d */
- SSL_RSA_WITH_DES_CBC_SHA, /* e */
- SSL_RSA_EXPORT_WITH_RC4_40_MD5, /* f */
- SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* g */
- SSL_FORTEZZA_DMS_WITH_NULL_SHA, /* h */
- SSL_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 */
- SSL_RSA_WITH_RC4_128_SHA, /* n */
- TLS_DHE_DSS_WITH_RC4_128_SHA, /* o */
- SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
- SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
- SSL_DHE_RSA_WITH_DES_CBC_SHA, /* r */
- SSL_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 */
- 0
-};
-
-/* This global string is so that client main can see
- * which ciphers to use.
- */
-
-static const char *cipherString;
-
-static int certsTested;
-static int MakeCertOK;
-static int NoReuse;
-static PRBool NoDelay;
-static PRBool QuitOnTimeout = PR_FALSE;
-
-static SSL3Statistics * ssl3stats;
-
-static int failed_already = 0;
-static PRBool disableSSL3 = PR_FALSE;
-static PRBool disableTLS = PR_FALSE;
-
-
-char * ownPasswd( PK11SlotInfo *slot, PRBool retry, void *arg)
-{
- char *passwd = NULL;
-
- if ( (!retry) && arg ) {
- passwd = PL_strdup((char *)arg);
- }
-
- return passwd;
-}
-
-int stopping;
-int verbose;
-SECItem bigBuf;
-
-#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"
- " [-3DNTovq] [-2 filename]\n"
- " [-w dbpasswd] [-C cipher(s)] [-t threads] hostname\n"
- " where -v means verbose\n"
- " -o means override server certificate validation\n"
- " -D means no TCP delays\n"
- " -q means quit when server gone (timeout rather than retry forever)\n"
- " -N means no session reuse\n",
- progName);
- exit(1);
-}
-
-
-static void
-errWarn(char * funcString)
-{
- PRErrorCode perr = PR_GetError();
- const char * errString = SECU_Strerror(perr);
-
- fprintf(stderr, "strsclnt: %s returned error %d:\n%s\n",
- funcString, perr, errString);
-}
-
-static void
-errExit(char * funcString)
-{
- errWarn(funcString);
- exit(1);
-}
-
-/**************************************************************************
-**
-** Routines for disabling SSL ciphers.
-**
-**************************************************************************/
-
-void
-disableAllSSLCiphers(void)
-{
- const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
- int i = SSL_NumImplementedCiphers;
- 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);
- }
- }
-}
-
-static SECStatus
-myGoodSSLAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
- PRBool isServer)
-{
- return SECSuccess;
-}
-
-/* This invokes the "default" AuthCert handler in libssl.
-** 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;
-
- peerCert = SSL_PeerCertificate(fd);
-
- PRINTF("strsclnt: Subject: %s\nstrsclnt: Issuer : %s\n",
- peerCert->subjectName, peerCert->issuerName);
- /* invoke the "default" AuthCert handler. */
- rv = SSL_AuthCertificate(arg, fd, checkSig, isServer);
-
- ++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)
-{
- int 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;
-
- static int only_once;
-
- 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",
- channel.authKeyBits, suite.authAlgorithmName,
- channel.keaKeyBits, suite.keaTypeName);
- }
- }
-
- 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 (cert) {
- CERT_DestroyCertificate(cert);
- cert = NULL;
- }
- fprintf(stderr,
- "strsclnt: %ld cache hits; %ld cache misses, %ld cache not reusable\n",
- ssl3stats->hsh_sid_cache_hits,
- ssl3stats->hsh_sid_cache_misses,
- ssl3stats->hsh_sid_cache_not_ok);
-
-}
-
-/**************************************************************************
-** Begin thread management routines and data.
-**************************************************************************/
-
-#define MAX_THREADS 128
-
-typedef int startFn(void *a, void *b, int c);
-
-PRLock * threadLock;
-PRCondVar * threadStartQ;
-PRCondVar * threadEndQ;
-
-int numUsed;
-int numRunning;
-PRInt32 numConnected;
-int max_threads = 8; /* default much less than max. */
-
-typedef enum { rs_idle = 0, rs_running = 1, rs_zombie = 2 } runState;
-
-typedef struct perThreadStr {
- void * a;
- void * b;
- int c;
- int rv;
- startFn * startFunc;
- PRThread * prThread;
- PRBool inUse;
- runState running;
-} perThread;
-
-perThread threads[MAX_THREADS];
-
-void
-thread_wrapper(void * arg)
-{
- perThread * slot = (perThread *)arg;
-
- /* wait for parent to finish launching us before proceeding. */
- PR_Lock(threadLock);
- PR_Unlock(threadLock);
-
- slot->rv = (* slot->startFunc)(slot->a, slot->b, slot->c);
-
- /* Handle cleanup of thread here. */
- PRINTF("strsclnt: Thread in slot %d returned %d\n",
- slot - threads, slot->rv);
-
- PR_Lock(threadLock);
- slot->running = rs_idle;
- --numRunning;
-
- /* notify the thread launcher. */
- PR_NotifyCondVar(threadStartQ);
-
- PR_Unlock(threadLock);
-}
-
-SECStatus
-launch_thread(
- startFn * startFunc,
- void * a,
- void * b,
- int c)
-{
- perThread * slot;
- int i;
-
- if (!threadStartQ) {
- threadLock = PR_NewLock();
- threadStartQ = PR_NewCondVar(threadLock);
- threadEndQ = PR_NewCondVar(threadLock);
- }
- PR_Lock(threadLock);
- while (numRunning >= max_threads) {
- PR_WaitCondVar(threadStartQ, PR_INTERVAL_NO_TIMEOUT);
- }
- for (i = 0; i < numUsed; ++i) {
- if (threads[i].running == rs_idle)
- break;
- }
- if (i >= numUsed) {
- if (i >= MAX_THREADS) {
- /* something's really wrong here. */
- PORT_Assert(i < MAX_THREADS);
- PR_Unlock(threadLock);
- return SECFailure;
- }
- ++numUsed;
- PORT_Assert(numUsed == i + 1);
- }
-
- slot = threads + i;
- slot->a = a;
- slot->b = b;
- slot->c = c;
-
- slot->startFunc = startFunc;
-
- slot->prThread = PR_CreateThread(PR_USER_THREAD,
- thread_wrapper, slot,
- PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
- PR_UNJOINABLE_THREAD, 0);
- if (slot->prThread == NULL) {
- PR_Unlock(threadLock);
- printf("strsclnt: Failed to launch thread!\n");
- return SECFailure;
- }
-
- slot->inUse = 1;
- slot->running = 1;
- ++numRunning;
- PR_Unlock(threadLock);
- PRINTF("strsclnt: Launched thread in slot %d \n", i);
-
- return SECSuccess;
-}
-
-/* Wait until numRunning == 0 */
-int
-reap_threads(void)
-{
- perThread * slot;
- int i;
-
- if (!threadLock)
- return 0;
- PR_Lock(threadLock);
- while (numRunning > 0) {
- PR_WaitCondVar(threadStartQ, PR_INTERVAL_NO_TIMEOUT);
- }
-
- /* Safety Sam sez: make sure count is right. */
- for (i = 0; i < numUsed; ++i) {
- slot = threads + i;
- if (slot->running != rs_idle) {
- FPRINTF(stderr, "strsclnt: Thread in slot %d is in state %d!\n",
- i, slot->running);
- }
- }
- PR_Unlock(threadLock);
- return 0;
-}
-
-void
-destroy_thread_data(void)
-{
- PORT_Memset(threads, 0, sizeof threads);
-
- if (threadEndQ) {
- PR_DestroyCondVar(threadEndQ);
- threadEndQ = NULL;
- }
- if (threadStartQ) {
- PR_DestroyCondVar(threadStartQ);
- threadStartQ = NULL;
- }
- if (threadLock) {
- PR_DestroyLock(threadLock);
- threadLock = NULL;
- }
-}
-
-/**************************************************************************
-** End thread management routines.
-**************************************************************************/
-
-PRBool useModelSocket = PR_TRUE;
-
-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"
-};
-
-struct lockedVarsStr {
- 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_Destroy( lockedVars * lv)
-{
- PR_DestroyCondVar(lv->condVar);
- lv->condVar = 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);
-}
-
-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;
-}
-
-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) {
-
- count = PR_Write(ssl_sock, bigBuf.data + sent, bigBuf.len - sent);
- if (count < 0) {
- errWarn("PR_Write bigBuf");
- break;
- }
- FPRINTF(stderr, "strsclnt: PR_Write 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_Read(ssl_sock, buf, RD_BUF_SIZE);
- if (count < 0) {
- errWarn("PR_Read");
- 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 connection)
-{
- int countRead = 0;
- PRInt32 rv;
- char *buf;
-
- buf = PR_Malloc(RD_BUF_SIZE);
- if (!buf)
- return SECFailure;
-
- /* compose the http request here. */
-
- rv = PR_Write(ssl_sock, request, strlen(request));
- if (rv <= 0) {
- errWarn("PR_Write");
- PR_Free(buf);
- buf = 0;
- failed_already = 1;
- return SECFailure;
- }
- printSecurityInfo(ssl_sock);
-
- /* read until EOF */
- while (1) {
- rv = PR_Read(ssl_sock, buf, RD_BUF_SIZE);
- if (rv == 0) {
- break; /* EOF */
- }
- if (rv < 0) {
- errWarn("PR_Read");
- break;
- }
-
- countRead += rv;
- FPRINTF(stderr, "strsclnt: connection %d read %d bytes (%d total).\n",
- connection, rv, countRead );
- }
- PR_Free(buf);
- buf = 0;
-
- /* Caller closes the socket. */
-
- FPRINTF(stderr,
- "strsclnt: connection %d read %d bytes total. -----------------------\n",
- connection, countRead);
-
- return SECSuccess; /* success */
-}
-
-/* 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 connection)
-{
- 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_NewTCPSocket();
- if (tcp_sock == NULL) {
- errExit("PR_NewTCPSocket");
- }
-
- 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();
- if ((err == PR_CONNECT_REFUSED_ERROR) ||
- (err == PR_CONNECT_RESET_ERROR) ) {
- int connections = numConnected;
-
- PR_Close(tcp_sock);
- if (connections > 2 && max_threads >= connections) {
- max_threads = connections - 1;
- fprintf(stderr,"max_threads set down to %d\n", max_threads);
- }
- 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;
- }
-
- 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;
- }
-
- rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 0);
- if (rv != SECSuccess) {
- errWarn("SSL_ResetHandshake");
- goto done;
- }
-
- PR_AtomicIncrement(&numConnected);
-
- if (bigBuf.data != NULL) {
- result = handle_fdx_connection( ssl_sock, connection);
- } else {
- result = handle_connection( ssl_sock, connection);
- }
-
- PR_AtomicDecrement(&numConnected);
-
-done:
- if (ssl_sock) {
- PR_Close(ssl_sock);
- } else if (tcp_sock) {
- PR_Close(tcp_sock);
- }
- return SECSuccess;
-}
-
-/* Returns IP address for hostname as PRUint32 in Host Byte Order.
-** Since the value returned is an integer (not a string of bytes),
-** it is inherently in Host Byte Order.
-*/
-PRUint32
-getIPAddress(const char * hostName)
-{
- const unsigned char *p;
- PRStatus prStatus;
- PRUint32 rv;
- PRHostEnt prHostEnt;
- char scratch[PR_NETDB_BUF_SIZE];
-
- prStatus = PR_GetHostByName(hostName, scratch, sizeof scratch, &prHostEnt);
- if (prStatus != PR_SUCCESS)
- errExit("PR_GetHostByName");
-
-#undef h_addr
-#define h_addr h_addr_list[0] /* address, for backward compatibility */
-
- p = (const unsigned char *)(prHostEnt.h_addr); /* in Network Byte order */
- FPRINTF(stderr, "strsclnt: %s -> %d.%d.%d.%d\n", hostName,
- p[0], p[1], p[2], p[3]);
- rv = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
- return rv;
-}
-
-typedef struct {
- PRLock* lock;
- char* nickname;
- CERTCertificate* cert;
- SECKEYPrivateKey* key;
- char* password;
-} 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->password);
- if (Cert_And_Key->cert) {
- Cert_And_Key->key = PK11_FindKeyByAnyCert(Cert_And_Key->cert, Cert_And_Key->password);
- }
- 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;
- SECStatus rv = SECSuccess;
- 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 */
- int timeout = 0;
- CERTCertificate* oldcert = NULL;
- SECKEYPrivateKey* oldkey = NULL;
-
- /* 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;
- SECStatus rv = SECFailure;
-
- if (Cert_And_Key) {
- proto_win = Cert_And_Key->password;
- }
-
- 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;
- }
-}
-
-void
-client_main(
- unsigned short port,
- int connections,
- cert_and_key* Cert_And_Key,
- const char * hostName)
-{
- PRFileDesc *model_sock = NULL;
- int i;
- int rv;
- PRUint32 ipAddress; /* in host byte order */
- PRNetAddr addr;
-
- /* Assemble NetAddr struct for connections. */
- ipAddress = getIPAddress(hostName);
-
- addr.inet.family = PR_AF_INET;
- addr.inet.port = PR_htons(port);
- addr.inet.ip = PR_htonl(ipAddress);
-
- /* 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++)) {
- int *cptr;
- int cipher;
-
- if (! isalpha(ndx))
- Usage("strsclnt");
- cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
- for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; )
- /* do nothing */;
- if (cipher) {
- SECStatus rv;
- rv = SSL_CipherPrefSetDefault(cipher, PR_TRUE);
- if (rv != SECSuccess) {
- fprintf(stderr,
- "strsclnt: SSL_CipherPrefSetDefault failed with value 0x%04x\n",
- cipher);
- exit(1);
- }
- }
- }
- }
-
- /* configure model SSL socket. */
-
- model_sock = PR_NewTCPSocket();
- if (model_sock == NULL) {
- errExit("PR_NewTCPSocket on 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, 1);
- if (rv < 0) {
- errExit("SSL_OptionSet SSL_SECURITY");
- }
-
- rv = SSL_OptionSet(model_sock, SSL_ENABLE_SSL3, !disableSSL3);
- if (rv != SECSuccess) {
- errExit("error enabling SSLv3 ");
- }
-
- rv = SSL_OptionSet(model_sock, SSL_ENABLE_TLS, !disableTLS);
- if (rv != SECSuccess) {
- errExit("error enabling TLS ");
- }
-
- 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");
- }
- }
-
- 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);
-
- /* I'm not going to set the HandshakeCallback function. */
-
- /* end of ssl configuration. */
-
- i = 1;
- if (!NoReuse) {
- rv = launch_thread(do_connects, &addr, model_sock, i);
- --connections;
- ++i;
- /* wait for the first connection to terminate, then launch the rest. */
- reap_threads();
- }
- if (connections > 0) {
- /* Start up the connections */
- do {
- rv = launch_thread(do_connects, &addr, model_sock, i);
- ++i;
- } while (--connections > 0);
- 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 * progName = NULL;
- char * tmp = NULL;
- char * passwd = NULL;
- int connections = 1;
- int exitVal;
- int tmpInt;
- unsigned short port = 443;
- SECStatus rv;
- PLOptState * optstate;
- PLOptStatus status;
- cert_and_key Cert_And_Key;
-
- /* Call the NSPR initialization routines */
- PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
-
- tmp = strrchr(argv[0], '/');
- tmp = tmp ? tmp + 1 : argv[0];
- progName = strrchr(tmp, '\\');
- progName = progName ? progName + 1 : tmp;
-
-
- optstate = PL_CreateOptState(argc, argv, "2:3C:DNTc:d:n:op:qt:vw:");
- while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
- switch(optstate->option) {
-
- case '2': fileName = optstate->value; break;
-
- case '3': disableSSL3 = PR_TRUE; break;
-
- case 'C': cipherString = optstate->value; break;
-
- case 'D': NoDelay = PR_TRUE; break;
-
- case 'N': NoReuse = 1; break;
-
- case 'T': disableTLS = PR_TRUE; break;
-
- case 'c': connections = PORT_Atoi(optstate->value); break;
-
- case 'd': dir = optstate->value; break;
-
- case 'n': nickName = PL_strdup(optstate->value); break;
-
- case 'o': MakeCertOK = 1; break;
-
- case 'p': port = PORT_Atoi(optstate->value); break;
-
- case 'q': QuitOnTimeout = PR_TRUE; break;
-
- case 't':
- tmpInt = PORT_Atoi(optstate->value);
- if (tmpInt > 0 && tmpInt < MAX_THREADS)
- max_threads = tmpInt;
- break;
-
- case 'v': verbose++; break;
-
- case 'w': passwd = PL_strdup(optstate->value); break;
-
- case 0: /* positional parameter */
- if (hostName) {
- Usage(progName);
- }
- hostName = PL_strdup(optstate->value);
- break;
-
- default:
- case '?':
- Usage(progName);
- break;
-
- }
- }
- if (!hostName || status == PL_OPT_BAD)
- Usage(progName);
-
- if (port == 0)
- Usage(progName);
-
- if (fileName)
- readBigFile(fileName);
-
- /* set our password function */
- if ( passwd ) {
- PK11_SetPasswordFunc(ownPasswd);
- } else {
- PK11_SetPasswordFunc(SECU_GetModulePassword);
- }
-
- /* Call the libsec 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.password = passwd;
- 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);
-
- /* 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);
-
- /* some final stats. */
- if (ssl3stats->hsh_sid_cache_hits + ssl3stats->hsh_sid_cache_misses +
- ssl3stats->hsh_sid_cache_not_ok == 0) {
- /* presumably we were testing SSL2. */
- printf("strsclnt: %d server certificates tested.\n", certsTested);
- } else {
- printf(
- "strsclnt: %ld cache hits; %ld cache misses, %ld cache not reusable\n",
- ssl3stats->hsh_sid_cache_hits,
- ssl3stats->hsh_sid_cache_misses,
- ssl3stats->hsh_sid_cache_not_ok);
- }
-
- if (!NoReuse)
- exitVal = (ssl3stats->hsh_sid_cache_misses > 1) ||
- (ssl3stats->hsh_sid_cache_not_ok != 0) ||
- (certsTested > 1);
- else
- exitVal = (ssl3stats->hsh_sid_cache_misses != connections) ||
- (certsTested != connections);
-
- exitVal = ( exitVal || failed_already );
- SSL_ClearSessionCache();
- if (NSS_Shutdown() != SECSuccess) {
- exit(1);
- }
-
- PR_Cleanup();
- return exitVal;
-}
-