client.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 452 行

C
452
字号
/* * 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 sets up a connection to SSL server, transmits   * *  some data and then reads the reply                                      * ****************************************************************************/ #include <stdio.h>#include <string.h>#if defined(XP_UNIX)#include <unistd.h>#endif#include "prerror.h"#include "pk11func.h"#include "secitem.h"#include <stdlib.h>#include <errno.h>#include <fcntl.h>#include <stdarg.h>#include "nspr.h"#include "plgetopt.h"#include "prio.h"#include "prnetdb.h"#include "nss.h"#include "sslsample.h"#define RD_BUF_SIZE (60 * 1024)extern int cipherSuites[];extern int ssl2CipherSuites[];extern int ssl3CipherSuites[];GlobalThreadMgr threadMGR;char *certNickname = NULL;char *hostName = NULL;char *password = NULL;unsigned short port = 0;static voidUsage(const char *progName){	fprintf(stderr, 	  "Usage: %s [-n rsa_nickname] [-p port] [-d dbdir] [-c connections]\n"	  "          [-w dbpasswd] [-C cipher(s)] hostname\n",	progName);	exit(1);}PRFileDesc *setupSSLSocket(PRNetAddr *addr){	PRFileDesc         *tcpSocket;	PRFileDesc         *sslSocket;	PRSocketOptionData	socketOption;	PRStatus            prStatus;	SECStatus           secStatus;retry:	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;	} #if 0	/* Verify that a connection can be made to the socket. */	prStatus = PR_Connect(tcpSocket, addr, PR_INTERVAL_NO_TIMEOUT);	if (prStatus != PR_SUCCESS) {		PRErrorCode err = PR_GetError();		if (err == PR_CONNECT_REFUSED_ERROR) {			PR_Close(tcpSocket);			PR_Sleep(PR_MillisecondsToInterval(10));			fprintf(stderr, "Connection to port refused, retrying.\n");			goto retry;		}		errWarn("PR_Connect");		goto loser;	}#endif	/* Import the socket into the SSL layer. */	sslSocket = SSL_ImportFD(NULL, tcpSocket);	if (!sslSocket) {		errWarn("SSL_ImportFD");		goto loser;	}	/* Set configuration options. */	secStatus = SSL_Enable(sslSocket, SSL_SECURITY, PR_TRUE);	if (secStatus != SECSuccess) {		errWarn("SSL_Enable:SSL_SECURITY");		goto loser;	}	secStatus = SSL_Enable(sslSocket, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);	if (secStatus != SECSuccess) {		errWarn("SSL_Enable: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" };SECStatushandle_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;		fprintf(stderr, "***** Connection %d read %d bytes (%d total).\n", 			connection, numBytes, countRead );		readBuffer[numBytes] = '\0';		fprintf(stderr, "************\n%s\n************\n", readBuffer);	}	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.*/SECStatusdo_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;	}	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;}voidclient_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);}intmain(int argc, char **argv){	char *               certDir      = ".";	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 'd' : certDir = PL_strdup(optstate->value);      break;		case 'n' : certNickname = PL_strdup(optstate->value); break;		case 'p' : port = PORT_Atoi(optstate->value);         break;		case 'w' : password = PL_strdup(optstate->value);     break;		case '\0': hostName = PL_strdup(optstate->value);     break;		default  : Usage(progName);		}	}	if (port == 0 || hostName == NULL)		Usage(progName);	if (certDir == NULL) {		certDir = PR_smprintf("%s/.netscape", getenv("HOME"));	}	/* Set our password function callback. */	PK11_SetPasswordFunc(myPasswd);	/* Initialize the NSS libraries. */	secStatus = NSS_Init(certDir);	if (secStatus != SECSuccess) {		exitErr("NSS_Init");	}	/* All cipher suites except RSA_NULL_MD5 are enabled by Domestic Policy. */	NSS_SetDomesticPolicy();	SSL_EnableCipher(SSL_RSA_WITH_NULL_MD5, SSL_ALLOWED);	/* 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. */		disableSSL2Ciphers();		disableSSL3Ciphers();		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_EnableCipher(cipher, SSL_ALLOWED);			}		}	}	client_main(port, connections, hostName);	NSS_Shutdown();	PR_Cleanup();	return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?