diff --git a/mozilla/security/nss/cmd/vfyserv/Makefile b/mozilla/security/nss/cmd/vfyserv/Makefile new file mode 100644 index 00000000000..8a0332d89bd --- /dev/null +++ b/mozilla/security/nss/cmd/vfyserv/Makefile @@ -0,0 +1,82 @@ +#! gmake +# +# 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. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +include ../platlibs.mk + +ifeq (,$(filter-out WINNT WIN95 WIN16,$(OS_TARGET))) # omits WINCE +ifndef BUILD_OPT +LDFLAGS += /subsystem:console /profile /debug /machine:I386 /incremental:no +OS_CFLAGS += -D_CONSOLE +endif +endif + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + +#include ../platlibs.mk + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + +include ../platrules.mk + diff --git a/mozilla/security/nss/cmd/vfyserv/makefile.win b/mozilla/security/nss/cmd/vfyserv/makefile.win new file mode 100644 index 00000000000..6cf6c12cf1d --- /dev/null +++ b/mozilla/security/nss/cmd/vfyserv/makefile.win @@ -0,0 +1,130 @@ +# +# 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. +# + +VERBOSE = 1 +include + +#cannot define PROGRAM in manifest compatibly with NT and UNIX +PROGRAM = tstclnt +PROGRAM = ./$(OBJDIR)/$(PROGRAM).exe +include <$(DEPTH)\config\config.mak> + +# let manifest generate C_OBJS, it will prepend ./$(OBJDIR)/ +# rules.mak will append C_OBJS onto OBJS. +# OBJS = $(CSRCS:.c=.obj) + +# include files are looked for in $LINCS and $INCS. +# $LINCS is in manifest.mnw, computed from REQUIRES= +INCS = $(INCS) \ + -I$(DEPTH)/security/lib/cert \ + -I../include \ + $(NULL) + +IGNORE_ME = \ + -I$(DEPTH)/security/lib/key \ + -I$(DEPTH)/security/lib/util \ + $(NULL) + + +WINFE = $(DEPTH)/cmd/winfe/mkfiles$(MOZ_BITS)/x86Dbg + +# these files are the content of libdbm +DBM_LIB = \ + $(WINFE)/DB.obj \ + $(WINFE)/HASH.obj \ + $(WINFE)/H_BIGKEY.obj \ + $(WINFE)/H_PAGE.obj \ + $(WINFE)/H_LOG2.obj \ + $(WINFE)/H_FUNC.obj \ + $(WINFE)/HASH_BUF.obj \ + $(NULL) + +MOZ_LIBS = \ + $(WINFE)/ALLXPSTR.obj \ + $(WINFE)/XP_ERROR.obj \ + $(WINFE)/XPASSERT.obj \ + $(WINFE)/XP_REG.obj \ + $(WINFE)/XP_TRACE.obj \ + $(DBM_LIB) \ + $(WINFE)/XP_STR.obj \ + $(WINFE)/MKTEMP.obj \ + $(NULL) + +SEC_LIBS = \ + $(DIST)/lib/cert$(MOZ_BITS).lib \ + $(DIST)/lib/crypto$(MOZ_BITS).lib \ + $(DIST)/lib/hash$(MOZ_BITS).lib \ + $(DIST)/lib/key$(MOZ_BITS).lib \ + $(DIST)/lib/pkcs7$(MOZ_BITS).lib \ + $(DIST)/lib/secmod$(MOZ_BITS).lib \ + $(DIST)/lib/secutl$(MOZ_BITS).lib \ + $(DIST)/lib/ssl$(MOZ_BITS).lib \ + $(NULL) + +LLFLAGS = $(LLFLAGS) \ + ../lib/$(OBJDIR)/sectool$(MOZ_BITS).lib \ + $(SEC_LIBS) \ + $(MOZ_LIBS) \ + $(DEPTH)/nspr/src/$(OBJDIR)/getopt.obj \ + $(LIBNSPR) \ + $(NULL) + + +include <$(DEPTH)\config\rules.mak> + +INSTALL = $(MAKE_INSTALL) + +objs: $(OBJS) + +$(PROGRAM):: + $(INSTALL) $(DIST)/bin/pr3240.dll ./$(OBJDIR) + +programs: $(PROGRAM) + +install:: $(TARGETS) + $(INSTALL) $(TARGETS) $(DIST)/bin + + +symbols: + @echo "CSRCS = $(CSRCS)" + @echo "INCS = $(INCS)" + @echo "OBJS = $(OBJS)" + @echo "LIBRARY = $(LIBRARY)" + @echo "PROGRAM = $(PROGRAM)" + @echo "TARGETS = $(TARGETS)" + @echo "DIST = $(DIST)" + @echo "VERSION_NUMBER = $(VERSION_NUMBER)" + @echo "WINFE = $(WINFE)" + @echo "DBM_LIB = $(DBM_LIB)" + @echo "INSTALL = $(INSTALL)" + diff --git a/mozilla/security/nss/cmd/vfyserv/manifest.mn b/mozilla/security/nss/cmd/vfyserv/manifest.mn new file mode 100644 index 00000000000..f8de4dd9a5b --- /dev/null +++ b/mozilla/security/nss/cmd/vfyserv/manifest.mn @@ -0,0 +1,51 @@ +# +# 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. +# + +CORE_DEPTH = ../../.. + +# MODULE public and private header directories are implicitly REQUIRED. +MODULE = security + +# This next line is used by .mk files +# and gets translated into $LINCS in manifest.mnw +# The MODULE is always implicitly required. +# Listing it here in REQUIRES makes it appear twice in the cc command line. +REQUIRES = seccmd dbm + +# DIRS = + +CSRCS = vfyserv.c vfyutil.c +DEFINES += -DDLL_PREFIX=\"$(DLL_PREFIX)\" -DDLL_SUFFIX=\"$(DLL_SUFFIX)\" -I../SSLSample + +PROGRAM = vfyserv + diff --git a/mozilla/security/nss/cmd/vfyserv/vfyserv.c b/mozilla/security/nss/cmd/vfyserv/vfyserv.c new file mode 100644 index 00000000000..bab93749160 --- /dev/null +++ b/mozilla/security/nss/cmd/vfyserv/vfyserv.c @@ -0,0 +1,439 @@ +/* + * 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. + */ + +/**************************************************************************** + * SSL client program that tests a server for proper operation of SSL2, * + * SSL3, and TLS. Test propder certificate installation. * + * * + * This code was modified from the SSLSample code also kept in the NSS * + * directory. * + ****************************************************************************/ + +#include +#include + +#if defined(XP_UNIX) +#include +#endif + +#include "prerror.h" + +#include "pk11func.h" +#include "secmod.h" +#include "secitem.h" + + +#include +#include +#include +#include + +#include "nspr.h" +#include "plgetopt.h" +#include "prio.h" +#include "prnetdb.h" +#include "nss.h" + +#include "vfyserv.h" + +#define RD_BUF_SIZE (60 * 1024) + +extern int ssl2CipherSuites[]; +extern int ssl3CipherSuites[]; + +GlobalThreadMgr threadMGR; +char *certNickname = NULL; +char *hostName = NULL; +char *password = NULL; +unsigned short port = 0; + +static void +Usage(const char *progName) +{ + fprintf(stderr, + "Usage: %s [-p port] [-c connections] [-C cipher(s)] hostname\n", + progName); + exit(1); +} + +PRFileDesc * +setupSSLSocket(PRNetAddr *addr) +{ + PRFileDesc *tcpSocket; + PRFileDesc *sslSocket; + PRSocketOptionData socketOption; + PRStatus prStatus; + SECStatus secStatus; + + + tcpSocket = PR_NewTCPSocket(); + if (tcpSocket == NULL) { + errWarn("PR_NewTCPSocket"); + } + + /* Make the socket blocking. */ + socketOption.option = PR_SockOpt_Nonblocking; + socketOption.value.non_blocking = PR_FALSE; + + prStatus = PR_SetSocketOption(tcpSocket, &socketOption); + if (prStatus != PR_SUCCESS) { + errWarn("PR_SetSocketOption"); + goto loser; + } + + + /* Import the socket into the SSL layer. */ + sslSocket = SSL_ImportFD(NULL, tcpSocket); + if (!sslSocket) { + errWarn("SSL_ImportFD"); + goto loser; + } + + /* Set configuration options. */ + secStatus = SSL_OptionSet(sslSocket, SSL_SECURITY, PR_TRUE); + if (secStatus != SECSuccess) { + errWarn("SSL_OptionSet:SSL_SECURITY"); + goto loser; + } + + secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); + if (secStatus != SECSuccess) { + errWarn("SSL_OptionSet:SSL_HANDSHAKE_AS_CLIENT"); + goto loser; + } + + /* Set SSL callback routines. */ + secStatus = SSL_GetClientAuthDataHook(sslSocket, + (SSLGetClientAuthData)myGetClientAuthData, + (void *)certNickname); + if (secStatus != SECSuccess) { + errWarn("SSL_GetClientAuthDataHook"); + goto loser; + } + + secStatus = SSL_AuthCertificateHook(sslSocket, + (SSLAuthCertificate)myAuthCertificate, + (void *)CERT_GetDefaultCertDB()); + if (secStatus != SECSuccess) { + errWarn("SSL_AuthCertificateHook"); + goto loser; + } + + secStatus = SSL_BadCertHook(sslSocket, + (SSLBadCertHandler)myBadCertHandler, NULL); + if (secStatus != SECSuccess) { + errWarn("SSL_BadCertHook"); + goto loser; + } + + secStatus = SSL_HandshakeCallback(sslSocket, + (SSLHandshakeCallback)myHandshakeCallback, + NULL); + if (secStatus != SECSuccess) { + errWarn("SSL_HandshakeCallback"); + goto loser; + } + + return sslSocket; + +loser: + + PR_Close(tcpSocket); + return NULL; +} + + +const char requestString[] = {"GET /testfile HTTP/1.0\r\n\r\n" }; + +SECStatus +handle_connection(PRFileDesc *sslSocket, int connection) +{ + int countRead = 0; + PRInt32 numBytes; + char *readBuffer; + + readBuffer = PORT_Alloc(RD_BUF_SIZE); + if (!readBuffer) { + exitErr("PORT_Alloc"); + } + + /* compose the http request here. */ + + numBytes = PR_Write(sslSocket, requestString, strlen(requestString)); + if (numBytes <= 0) { + errWarn("PR_Write"); + PR_Free(readBuffer); + readBuffer = NULL; + return SECFailure; + } + + /* read until EOF */ + while (PR_TRUE) { + numBytes = PR_Read(sslSocket, readBuffer, RD_BUF_SIZE); + if (numBytes == 0) { + break; /* EOF */ + } + if (numBytes < 0) { + errWarn("PR_Read"); + break; + } + countRead += numBytes; + } + + printSecurityInfo(sslSocket); + + PR_Free(readBuffer); + readBuffer = NULL; + + /* Caller closes the socket. */ + + fprintf(stderr, + "***** 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. +*/ +SECStatus +do_connects(void *a, int connection) +{ + PRNetAddr *addr = (PRNetAddr *)a; + PRFileDesc *sslSocket; + PRHostEnt hostEntry; + char buffer[PR_NETDB_BUF_SIZE]; + PRStatus prStatus; + PRIntn hostenum; + SECStatus secStatus; + + /* Set up SSL secure socket. */ + sslSocket = setupSSLSocket(addr); + if (sslSocket == NULL) { + errWarn("setupSSLSocket"); + return SECFailure; + } + + secStatus = SSL_SetPKCS11PinArg(sslSocket, password); + if (secStatus != SECSuccess) { + errWarn("SSL_SetPKCS11PinArg"); + return secStatus; + } + + secStatus = SSL_SetURL(sslSocket, hostName); + if (secStatus != SECSuccess) { + errWarn("SSL_SetURL"); + return secStatus; + } + + /* Prepare and setup network connection. */ + prStatus = PR_GetHostByName(hostName, buffer, sizeof(buffer), &hostEntry); + if (prStatus != PR_SUCCESS) { + errWarn("PR_GetHostByName"); + return SECFailure; + } + + hostenum = PR_EnumerateHostEnt(0, &hostEntry, port, addr); + if (hostenum == -1) { + errWarn("PR_EnumerateHostEnt"); + return SECFailure; + } + +/* printf("Connecting to host %s (addr %d.%d.%d.%d) on port %d\n", + host, hostEntry,port); */ + + prStatus = PR_Connect(sslSocket, addr, PR_INTERVAL_NO_TIMEOUT); + if (prStatus != PR_SUCCESS) { + errWarn("PR_Connect"); + return SECFailure; + } + + /* Established SSL connection, ready to send data. */ +#if 0 + secStatus = SSL_ForceHandshake(sslSocket); + if (secStatus != SECSuccess) { + errWarn("SSL_ForceHandshake"); + return secStatus; + } +#endif + + secStatus = SSL_ResetHandshake(sslSocket, /* asServer */ PR_FALSE); + if (secStatus != SECSuccess) { + errWarn("SSL_ResetHandshake"); + prStatus = PR_Close(sslSocket); + if (prStatus != PR_SUCCESS) { + errWarn("PR_Close"); + } + return secStatus; + } + + secStatus = handle_connection(sslSocket, connection); + if (secStatus != SECSuccess) { + errWarn("handle_connection"); + return secStatus; + } + + PR_Close(sslSocket); + return SECSuccess; +} + +void +client_main(unsigned short port, + int connections, + const char * hostName) +{ + int i; + SECStatus secStatus; + PRStatus prStatus; + PRInt32 rv; + PRNetAddr addr; + PRHostEnt hostEntry; + char buffer[256]; + + /* Setup network connection. */ + prStatus = PR_GetHostByName(hostName, buffer, 256, &hostEntry); + if (prStatus != PR_SUCCESS) { + exitErr("PR_GetHostByName"); + } + + rv = PR_EnumerateHostEnt(0, &hostEntry, port, &addr); + if (rv < 0) { + exitErr("PR_EnumerateHostEnt"); + } + + secStatus = launch_thread(&threadMGR, do_connects, &addr, 1); + if (secStatus != SECSuccess) { + exitErr("launch_thread"); + } + + if (connections > 1) { + /* wait for the first connection to terminate, then launch the rest. */ + reap_threads(&threadMGR); + /* Start up the connections */ + for (i = 2; i <= connections; ++i) { + secStatus = launch_thread(&threadMGR, do_connects, &addr, i); + if (secStatus != SECSuccess) { + errWarn("launch_thread"); + } + } + } + + reap_threads(&threadMGR); + destroy_thread_data(&threadMGR); +} + +int +main(int argc, char **argv) +{ + char * progName = NULL; + int connections = 1; + char * cipherString = NULL; + SECStatus secStatus; + PLOptState * optstate; + PLOptStatus status; + + /* Call the NSPR initialization routines */ + PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); + + progName = PL_strdup(argv[0]); + + hostName = NULL; + optstate = PL_CreateOptState(argc, argv, "C:c:d:n:p:w:"); + while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { + switch(optstate->option) { + case 'C' : cipherString = PL_strdup(optstate->value); break; + case 'c' : connections = PORT_Atoi(optstate->value); break; + case 'p' : port = PORT_Atoi(optstate->value); break; + case '\0': hostName = PL_strdup(optstate->value); break; + default : Usage(progName); + } + } + + if (port == 0) { + port = 443; + } + + if (port == 0 || hostName == NULL) + Usage(progName); + + /* Set our password function callback. */ + PK11_SetPasswordFunc(myPasswd); + + /* Initialize the NSS libraries. */ + secStatus = NSS_NoDB_Init(NULL); + if (secStatus != SECSuccess) { + exitErr("Client Error NSS_Init"); + } + + secStatus = SECMOD_AddNewModule("Builtins", + DLL_PREFIX"nssckbi."DLL_SUFFIX, 0, 0); +#ifdef notdef + if (secStatus != SECSuccess) { + exitErr("Client Error accessing builtin roots"); + } +#endif + + /* All cipher suites except RSA_NULL_MD5 are enabled by Domestic Policy. */ + NSS_SetDomesticPolicy(); + SSL_CipherPrefSetDefault(SSL_RSA_WITH_NULL_MD5, PR_TRUE); + + /* 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(progName); + cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites; + for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; ) + /* do nothing */; + if (cipher) { + SSL_CipherPrefSetDefault(cipher, PR_TRUE); + } + } + } + + client_main(port, connections, hostName); + + NSS_Shutdown(); + PR_Cleanup(); + return 0; +} + diff --git a/mozilla/security/nss/cmd/vfyserv/vfyserv.h b/mozilla/security/nss/cmd/vfyserv/vfyserv.h new file mode 100644 index 00000000000..ca6b6a48968 --- /dev/null +++ b/mozilla/security/nss/cmd/vfyserv/vfyserv.h @@ -0,0 +1,178 @@ +/* + * 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. + */ + +#ifndef SSLSAMPLE_H +#define SSLSAMPLE_H + +/* Generic header files */ + +#include +#include + +/* NSPR header files */ + +#include "nspr.h" +#include "prerror.h" +#include "prnetdb.h" + +/* NSS header files */ + +#include "pk11func.h" +#include "secitem.h" +#include "ssl.h" +#include "certt.h" +#include "nss.h" +#include "secrng.h" +#include "secder.h" +#include "key.h" +#include "sslproto.h" + +/* Custom header files */ + +/* +#include "sslerror.h" +*/ + +#define BUFFER_SIZE 10240 + +/* Declare SSL cipher suites. */ + +extern int cipherSuites[]; +extern int ssl2CipherSuites[]; +extern int ssl3CipherSuites[]; + +/* Data buffer read from a socket. */ +typedef struct DataBufferStr { + char data[BUFFER_SIZE]; + int index; + int remaining; + int dataStart; + int dataEnd; +} DataBuffer; + +/* SSL callback routines. */ + +char * myPasswd(PK11SlotInfo *info, PRBool retry, void *arg); + +SECStatus myAuthCertificate(void *arg, PRFileDesc *socket, + PRBool checksig, PRBool isServer); + +SECStatus myBadCertHandler(void *arg, PRFileDesc *socket); + +SECStatus myHandshakeCallback(PRFileDesc *socket, void *arg); + +SECStatus myGetClientAuthData(void *arg, PRFileDesc *socket, + struct CERTDistNamesStr *caNames, + struct CERTCertificateStr **pRetCert, + struct SECKEYPrivateKeyStr **pRetKey); + +/* Disable all v2/v3 SSL ciphers. */ + +void disableAllSSLCiphers(void); + + +/* Error and information utilities. */ + +void errWarn(char *function); + +void exitErr(char *function); + +void printSecurityInfo(PRFileDesc *fd); + +/* Some simple thread management routines. */ + +#define MAX_THREADS 32 + +typedef SECStatus startFn(void *a, int b); + +typedef enum { rs_idle = 0, rs_running = 1, rs_zombie = 2 } runState; + +typedef struct perThreadStr { + PRFileDesc *a; + int b; + int rv; + startFn *startFunc; + PRThread *prThread; + PRBool inUse; + runState running; +} perThread; + +typedef struct GlobalThreadMgrStr { + PRLock *threadLock; + PRCondVar *threadStartQ; + PRCondVar *threadEndQ; + perThread threads[MAX_THREADS]; + int index; + int numUsed; + int numRunning; +} GlobalThreadMgr; + +void thread_wrapper(void * arg); + +SECStatus launch_thread(GlobalThreadMgr *threadMGR, + startFn *startFunc, void *a, int b); + +SECStatus reap_threads(GlobalThreadMgr *threadMGR); + +void destroy_thread_data(GlobalThreadMgr *threadMGR); + +/* Management of locked variables. */ + +struct lockedVarsStr { + PRLock * lock; + int count; + int waiters; + PRCondVar * condVar; +}; + +typedef struct lockedVarsStr lockedVars; + +void lockedVars_Init(lockedVars *lv); + +void lockedVars_Destroy(lockedVars *lv); + +void lockedVars_WaitForDone(lockedVars *lv); + +int lockedVars_AddToCount(lockedVars *lv, int addend); + +/* Buffer stuff. */ + +static const char stopCmd[] = { "GET /stop " }; +static const char defaultHeader[] = { + "HTTP/1.0 200 OK\r\n" + "Server: SSL sample server\r\n" + "Content-type: text/plain\r\n" + "\r\n" +}; + +#endif diff --git a/mozilla/security/nss/cmd/vfyserv/vfyutil.c b/mozilla/security/nss/cmd/vfyserv/vfyutil.c new file mode 100644 index 00000000000..b92a1853c1f --- /dev/null +++ b/mozilla/security/nss/cmd/vfyserv/vfyutil.c @@ -0,0 +1,588 @@ +/* + * 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 "vfyserv.h" +#include "sslerror.h" /* go find the real one in libutil! */ + +/* Declare SSL cipher suites. */ + +int ssl2CipherSuites[] = { + SSL_EN_RC4_128_WITH_MD5, /* A */ + SSL_EN_RC4_128_EXPORT40_WITH_MD5, /* B */ + SSL_EN_RC2_128_CBC_WITH_MD5, /* C */ + SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, /* D */ + SSL_EN_DES_64_CBC_WITH_MD5, /* E */ + SSL_EN_DES_192_EDE3_CBC_WITH_MD5, /* F */ + 0 +}; + +int ssl3CipherSuites[] = { + 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 */ + 0 +}; + +/************************************************************************** +** +** SSL callback routines. +** +**************************************************************************/ + +/* Function: char * myPasswd() + * + * Purpose: This function is our custom password handler that is called by + * SSL when retreiving private certs and keys from the database. Returns a + * pointer to a string that with a password for the database. Password pointer + * should point to dynamically allocated memory that will be freed later. + */ +char * +myPasswd(PK11SlotInfo *info, PRBool retry, void *arg) +{ + char * passwd = NULL; + + if ( (!retry) && arg ) { + passwd = PORT_Strdup((char *)arg); + } + + return passwd; +} + +/* Function: SECStatus myAuthCertificate() + * + * Purpose: This function is our custom certificate authentication handler. + * + * Note: This implementation is essentially the same as the default + * SSL_AuthCertificate(). + */ +SECStatus +myAuthCertificate(void *arg, PRFileDesc *socket, + PRBool checksig, PRBool isServer) +{ + + SECCertUsage certUsage; + CERTCertificate * cert; + void * pinArg; + char * hostName; + SECStatus secStatus; + + if (!arg || !socket) { + errWarn("myAuthCertificate"); + return SECFailure; + } + + /* Define how the cert is being used based upon the isServer flag. */ + + certUsage = isServer ? certUsageSSLClient : certUsageSSLServer; + + cert = SSL_PeerCertificate(socket); + + pinArg = SSL_RevealPinArg(socket); + + secStatus = CERT_VerifyCertNow((CERTCertDBHandle *)arg, + cert, + checksig, + certUsage, + pinArg); + + /* If this is a server, we're finished. */ + if (isServer || secStatus != SECSuccess) { + CERT_DestroyCertificate(cert); + return secStatus; + } + + /* Certificate is OK. Since this is the client side of an SSL + * connection, we need to verify that the name field in the cert + * matches the desired hostname. This is our defense against + * man-in-the-middle attacks. + */ + + /* SSL_RevealURL returns a hostName, not an URL. */ + hostName = SSL_RevealURL(socket); + + if (hostName && hostName[0]) { + secStatus = CERT_VerifyCertName(cert, hostName); + } else { + PR_SetError(SSL_ERROR_BAD_CERT_DOMAIN, 0); + secStatus = SECFailure; + } + + if (hostName) + PR_Free(hostName); + + CERT_DestroyCertificate(cert); + return secStatus; +} + +/* Function: SECStatus myBadCertHandler() + * + * Purpose: This callback is called when the incoming certificate is not + * valid. We define a certain set of parameters that still cause the + * certificate to be "valid" for this session, and return SECSuccess to cause + * the server to continue processing the request when any of these conditions + * are met. Otherwise, SECFailure is return and the server rejects the + * request. + */ +SECStatus +myBadCertHandler(void *arg, PRFileDesc *socket) +{ + + SECStatus secStatus = SECFailure; + PRErrorCode err; + + /* log invalid cert here */ + + if (!arg) { + return secStatus; + } + + *(PRErrorCode *)arg = err = PORT_GetError(); + + /* If any of the cases in the switch are met, then we will proceed */ + /* with the processing of the request anyway. Otherwise, the default */ + /* case will be reached and we will reject the request. */ + + switch (err) { + case SEC_ERROR_INVALID_AVA: + case SEC_ERROR_INVALID_TIME: + case SEC_ERROR_BAD_SIGNATURE: + case SEC_ERROR_EXPIRED_CERTIFICATE: + case SEC_ERROR_UNKNOWN_ISSUER: + case SEC_ERROR_UNTRUSTED_CERT: + case SEC_ERROR_CERT_VALID: + case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: + case SEC_ERROR_CRL_EXPIRED: + case SEC_ERROR_CRL_BAD_SIGNATURE: + case SEC_ERROR_EXTENSION_VALUE_INVALID: + case SEC_ERROR_CA_CERT_INVALID: + case SEC_ERROR_CERT_USAGES_INVALID: + case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION: + secStatus = SECSuccess; + break; + default: + secStatus = SECFailure; + break; + } + + printf("Bad certificate: %d, %s\n", err, SSL_Strerror(err)); + + return secStatus; +} + +/* Function: SECStatus ownGetClientAuthData() + * + * Purpose: This callback is used by SSL to pull client certificate + * information upon server request. + */ +SECStatus +myGetClientAuthData(void *arg, + PRFileDesc *socket, + struct CERTDistNamesStr *caNames, + struct CERTCertificateStr **pRetCert, + struct SECKEYPrivateKeyStr **pRetKey) +{ + + CERTCertificate * cert; + SECKEYPrivateKey * privKey; + char * chosenNickName = (char *)arg; + void * proto_win = NULL; + SECStatus secStatus = SECFailure; + + proto_win = SSL_RevealPinArg(socket); + + if (chosenNickName) { + cert = PK11_FindCertFromNickname(chosenNickName, proto_win); + if (cert) { + privKey = PK11_FindKeyByAnyCert(cert, proto_win); + if (privKey) { + secStatus = SECSuccess; + } else { + CERT_DestroyCertificate(cert); + } + } + } else { /* no nickname given, automatically find the right cert */ + CERTCertNicknames *names; + int i; + + names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(), + SEC_CERT_NICKNAMES_USER, proto_win); + + if (names != NULL) { + for(i = 0; i < names->numnicknames; i++ ) { + + cert = PK11_FindCertFromNickname(names->nicknames[i], + proto_win); + if (!cert) { + continue; + } + + /* Only check unexpired certs */ + if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE) + != secCertTimeValid ) { + CERT_DestroyCertificate(cert); + continue; + } + + secStatus = NSS_CmpCertChainWCANames(cert, caNames); + if (secStatus == SECSuccess) { + privKey = PK11_FindKeyByAnyCert(cert, proto_win); + if (privKey) { + break; + } + secStatus = SECFailure; + break; + } + CERT_FreeNicknames(names); + } /* for loop */ + } + } + + if (secStatus == SECSuccess) { + *pRetCert = cert; + *pRetKey = privKey; + } + + return secStatus; +} + +/* Function: SECStatus myHandshakeCallback() + * + * Purpose: Called by SSL to inform application that the handshake is + * complete. This function is mostly used on the server side of an SSL + * connection, although it is provided for a client as well. + * Useful when a non-blocking SSL_ReHandshake or SSL_ResetHandshake + * is used to initiate a handshake. + * + * A typical scenario would be: + * + * 1. Server accepts an SSL connection from the client without client auth. + * 2. Client sends a request. + * 3. Server determines that to service request it needs to authenticate the + * client and initiates another handshake requesting client auth. + * 4. While handshake is in progress, server can do other work or spin waiting + * for the handshake to complete. + * 5. Server is notified that handshake has been successfully completed by + * the custom handshake callback function and it can service the client's + * request. + * + * Note: This function is not implemented in this sample, as we are using + * blocking sockets. + */ +SECStatus +myHandshakeCallback(PRFileDesc *socket, void *arg) +{ + printf("Handshake has completed, ready to send data securely.\n"); + return SECSuccess; +} + + +/************************************************************************** +** +** 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); + } + } +} + +/************************************************************************** +** +** Error and information routines. +** +**************************************************************************/ + +void +errWarn(char *function) +{ + PRErrorCode errorNumber = PR_GetError(); + const char * errorString = SSL_Strerror(errorNumber); + + printf("Error in function %s: %d\n - %s\n", + function, errorNumber, errorString); +} + +void +exitErr(char *function) +{ + errWarn(function); + /* Exit gracefully. */ + NSS_Shutdown(); + PR_Cleanup(); + exit(1); +} + +void +printSecurityInfo(PRFileDesc *fd) +{ + char * cp; /* bulk cipher name */ + char * ip; /* cert issuer DN */ + char * sp; /* cert subject DN */ + int op; /* High, Low, Off */ + int kp0; /* total key bits */ + int kp1; /* secret key bits */ + int result; + SSL3Statistics * ssl3stats = SSL_GetStatistics(); + + result = SSL_SecurityStatus(fd, &op, &cp, &kp0, &kp1, &ip, &sp); + if (result != SECSuccess) + return; + printf("bulk cipher %s, %d secret key bits, %d key bits, status: %d\n" + "subject DN: %s\n" + "issuer DN: %s\n", cp, kp1, kp0, op, sp, ip); + PR_Free(cp); + PR_Free(ip); + PR_Free(sp); + + printf("%ld cache hits; %ld cache misses, %ld cache not reusable\n", + ssl3stats->hch_sid_cache_hits, ssl3stats->hch_sid_cache_misses, + ssl3stats->hch_sid_cache_not_ok); + +} + + +/************************************************************************** +** Begin thread management routines and data. +**************************************************************************/ + +void +thread_wrapper(void * arg) +{ + GlobalThreadMgr *threadMGR = (GlobalThreadMgr *)arg; + perThread *slot = &threadMGR->threads[threadMGR->index]; + + /* wait for parent to finish launching us before proceeding. */ + PR_Lock(threadMGR->threadLock); + PR_Unlock(threadMGR->threadLock); + + slot->rv = (* slot->startFunc)(slot->a, slot->b); + + PR_Lock(threadMGR->threadLock); + slot->running = rs_zombie; + + /* notify the thread exit handler. */ + PR_NotifyCondVar(threadMGR->threadEndQ); + + PR_Unlock(threadMGR->threadLock); +} + +SECStatus +launch_thread(GlobalThreadMgr *threadMGR, + startFn *startFunc, + void *a, + int b) +{ + perThread *slot; + int i; + + if (!threadMGR->threadStartQ) { + threadMGR->threadLock = PR_NewLock(); + threadMGR->threadStartQ = PR_NewCondVar(threadMGR->threadLock); + threadMGR->threadEndQ = PR_NewCondVar(threadMGR->threadLock); + } + PR_Lock(threadMGR->threadLock); + while (threadMGR->numRunning >= MAX_THREADS) { + PR_WaitCondVar(threadMGR->threadStartQ, PR_INTERVAL_NO_TIMEOUT); + } + for (i = 0; i < threadMGR->numUsed; ++i) { + slot = &threadMGR->threads[i]; + if (slot->running == rs_idle) + break; + } + if (i >= threadMGR->numUsed) { + if (i >= MAX_THREADS) { + /* something's really wrong here. */ + PORT_Assert(i < MAX_THREADS); + PR_Unlock(threadMGR->threadLock); + return SECFailure; + } + ++(threadMGR->numUsed); + PORT_Assert(threadMGR->numUsed == i + 1); + slot = &threadMGR->threads[i]; + } + + slot->a = a; + slot->b = b; + slot->startFunc = startFunc; + + threadMGR->index = i; + + slot->prThread = PR_CreateThread(PR_USER_THREAD, + thread_wrapper, threadMGR, + PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, + PR_JOINABLE_THREAD, 0); + + if (slot->prThread == NULL) { + PR_Unlock(threadMGR->threadLock); + printf("Failed to launch thread!\n"); + return SECFailure; + } + + slot->inUse = 1; + slot->running = 1; + ++(threadMGR->numRunning); + PR_Unlock(threadMGR->threadLock); + + return SECSuccess; +} + +SECStatus +reap_threads(GlobalThreadMgr *threadMGR) +{ + perThread * slot; + int i; + + if (!threadMGR->threadLock) + return 0; + PR_Lock(threadMGR->threadLock); + while (threadMGR->numRunning > 0) { + PR_WaitCondVar(threadMGR->threadEndQ, PR_INTERVAL_NO_TIMEOUT); + for (i = 0; i < threadMGR->numUsed; ++i) { + slot = &threadMGR->threads[i]; + if (slot->running == rs_zombie) { + /* Handle cleanup of thread here. */ + + /* Now make sure the thread has ended OK. */ + PR_JoinThread(slot->prThread); + slot->running = rs_idle; + --threadMGR->numRunning; + + /* notify the thread launcher. */ + PR_NotifyCondVar(threadMGR->threadStartQ); + } + } + } + + /* Safety Sam sez: make sure count is right. */ + for (i = 0; i < threadMGR->numUsed; ++i) { + slot = &threadMGR->threads[i]; + if (slot->running != rs_idle) { + fprintf(stderr, "Thread in slot %d is in state %d!\n", + i, slot->running); + } + } + PR_Unlock(threadMGR->threadLock); + return 0; +} + +void +destroy_thread_data(GlobalThreadMgr *threadMGR) +{ + PORT_Memset(threadMGR->threads, 0, sizeof(threadMGR->threads)); + + if (threadMGR->threadEndQ) { + PR_DestroyCondVar(threadMGR->threadEndQ); + threadMGR->threadEndQ = NULL; + } + if (threadMGR->threadStartQ) { + PR_DestroyCondVar(threadMGR->threadStartQ); + threadMGR->threadStartQ = NULL; + } + if (threadMGR->threadLock) { + PR_DestroyLock(threadMGR->threadLock); + threadMGR->threadLock = NULL; + } +} + +/************************************************************************** +** End thread management routines. +**************************************************************************/ + +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; +}