strsclnt.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,128 行 · 第 1/2 页
C
1,128 行
/* * 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>#include <errno.h>#include <fcntl.h>#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 */ 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};/* This global string is so that client main can see * which ciphers to use. */const char *cipherString;int certsTested;int MakeCertOK;voiddisableSSL2Ciphers(void){ int i; /* disable all the SSL2 cipher suites */ for (i = 0; ssl2CipherSuites[i] != 0; ++i) { SECStatus rv; rv = SSL_EnableCipher(ssl2CipherSuites[i], SSL_NOT_ALLOWED); if (rv != SECSuccess) { fprintf(stderr, "strsclnt: SSL_EnableCipher failed with value 0x%04x\n", ssl2CipherSuites[i]); exit(1); } }}voiddisableSSL3Ciphers(void){ int i; /* disable all the SSL3 cipher suites */ for (i = 0; ssl3CipherSuites[i] != 0; ++i) { SECStatus rv; rv = SSL_EnableCipher(ssl3CipherSuites[i], SSL_NOT_ALLOWED); if (rv != SECSuccess) { fprintf(stderr, "strsclnt: SSL_EnableCipher failed with value 0x%04x\n", ssl3CipherSuites[i]); exit(1); } }}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) fprintfstatic voidUsage(const char *progName){ fprintf(stderr, "Usage: %s [-n rsa_nickname] [-p port] [-d dbdir] [-c connections]\n" " [-v] [-f fortezza_nickname] [-2 filename]\n" " [-w dbpasswd] [-C cipher(s)] hostname\n", progName); exit(1);}static voidnetworkStart(void){#if defined(XP_WIN) && !defined(NSPR20) WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(1, 1); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { /* Tell the user that we couldn't find a useable winsock.dll. */ fputs("WSAStartup failed!\n", stderr); exit(1); }/* Confirm that the Windows Sockets DLL supports 1.1.*/ /* Note that if the DLL supports versions greater */ /* than 1.1 in addition to 1.1, it will still return */ /* 1.1 in wVersion since that is the version we */ /* requested. */ if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { /* Tell the user that we couldn't find a useable winsock.dll. */ fputs("wrong winsock version\n", stderr); WSACleanup(); exit(1); } /* The Windows Sockets DLL is acceptable. Proceed. */ #endif}static voidnetworkEnd(void){#if defined(XP_WIN) && !defined(NSPR20) WSACleanup();#endif}static voiderrWarn(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 voiderrExit(char * funcString){#if defined (XP_WIN) && !defined(NSPR20) int err; LPVOID lpMsgBuf; err = WSAGetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); /* Display the string. */ /*MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION ); */ fprintf(stderr, "%s\n", lpMsgBuf); /* Free the buffer. */ LocalFree( lpMsgBuf );#endif errWarn(funcString); exit(1);}/* 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 intmySSLAuthCertificate(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); } /* error, if any, will be displayed by the Bad Cert Handler. */ return rv; }static int /* should be SECStatus but public prototype says int. */myBadCertHandler( void *arg, PRFileDesc *fd){ int err = PR_GetError(); fprintf(stderr, "strsclnt: -- SSL: Server Certificate Invalid, err %d.\n%s\n", err, SECU_Strerror(err)); return (MakeCertOK ? SECSuccess : SECFailure);}/* statistics from ssl3_SendClientHello (sch) */extern long ssl3_sch_sid_cache_hits;extern long ssl3_sch_sid_cache_misses;extern long ssl3_sch_sid_cache_not_ok;/* statistics from ssl3_HandleServerHello (hsh) */extern long ssl3_hsh_sid_cache_hits;extern long ssl3_hsh_sid_cache_misses;extern long ssl3_hsh_sid_cache_not_ok;/* statistics from ssl3_HandleClientHello (hch) */extern long ssl3_hch_sid_cache_hits;extern long ssl3_hch_sid_cache_misses;extern long ssl3_hch_sid_cache_not_ok;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; static int only_once; if (! only_once++ && fd) { result = SSL_SecurityStatus(fd, &op, &cp, &kp0, &kp1, &ip, &sp); if (result != SECSuccess) return; PRINTF( "strsclnt: cipher %s, %d secret key bits, %d key bits, status: %d\n", cp, kp1, kp0, op); PR_Free(cp); PR_Free(ip); PR_Free(sp); } PRINTF( "strsclnt: %ld cache hits; %ld cache misses, %ld cache not reusable\n", ssl3_hsh_sid_cache_hits, ssl3_hsh_sid_cache_misses, ssl3_hsh_sid_cache_not_ok);}/**************************************************************************** Begin thread management routines and data.**************************************************************************/#define MAX_THREADS 32typedef int startFn(void *a, void *b, int c);PRLock * threadLock;PRCondVar * threadStartQ;PRCondVar * threadEndQ;int numUsed;int numRunning;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];voidthread_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);}SECStatuslaunch_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) { slot = threads + i; if (slot->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 num_running == 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;}voiddestroy_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);}voidlockedVars_Destroy( lockedVars * lv){ PR_DestroyCondVar(lv->condVar); lv->condVar = NULL; PR_DestroyLock(lv->lock); lv->lock = NULL;}voidlockedVars_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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?