client.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:11k
- /*
- * 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 void
- Usage(const char *progName)
- {
- fprintf(stderr,
- "Usage: %s [-n rsa_nickname] [-p port] [-d dbdir] [-c connections]n"
- " [-w dbpasswd] [-C cipher(s)] hostnamen",
- 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.0rnrn" };
- 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;
- fprintf(stderr, "***** Connection %d read %d bytes (%d total).n",
- connection, numBytes, countRead );
- readBuffer[numBytes] = ' ';
- fprintf(stderr, "************n%sn************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.
- */
- 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;
- }
- 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 * 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 ' ': 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;
- }