strsclnt.c

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

C
1,128
字号
    PR_Lock(lv->lock);    rv = lv->count += addend;    if (rv <= 0) {	PR_NotifyCondVar(lv->condVar);    }    PR_Unlock(lv->lock);    return rv;}intdo_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" };SECStatushandle_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;	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.*/intdo_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;    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) {    	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)      ) {	    PR_Close(tcp_sock);	    PR_Sleep(PR_MillisecondsToInterval(10));	    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;    }    if (bigBuf.data != NULL) {	result = handle_fdx_connection( ssl_sock, connection);    } else {	result = handle_connection( ssl_sock, connection);    }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. */PRUint32getIPAddress(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;}voidclient_main(    unsigned short      port,     int                 connections,     SECKEYPrivateKey ** privKey,    CERTCertificate **  cert,     const char *	hostName,    char *		nickName){    PRFileDesc *model_sock	= NULL;    int         i;    int         rv;    PRUint32	ipAddress;	/* in host byte order */    PRNetAddr   addr;    networkStart();    /* 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. */        disableSSL2Ciphers();        disableSSL3Ciphers();        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_EnableCipher(cipher, SSL_ALLOWED);		if (rv != SECSuccess) {		    fprintf(stderr, 		    "strsclnt: SSL_EnableCipher 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_Enable(model_sock, SSL_SECURITY, 1);    if (rv < 0) {	errExit("SSL_Enable SSL_SECURITY");    }    if (bigBuf.data) { /* doing FDX */	rv = SSL_Enable(model_sock, SSL_ENABLE_FDX, 1);	if (rv < 0) {	    errExit("SSL_Enable SSL_ENABLE_FDX");	}    }    SSL_SetURL(model_sock, hostName);    SSL_AuthCertificateHook(model_sock, mySSLAuthCertificate, 			    (void *)CERT_GetDefaultCertDB());    SSL_BadCertHook(model_sock, myBadCertHandler, NULL);    SSL_GetClientAuthDataHook(model_sock, NSS_GetClientAuthData, nickName);    /* I'm not going to set the HandshakeCallback function. */    /* end of ssl configuration. */    rv = launch_thread(do_connects, &addr, model_sock, 1);    if (connections > 1) {	/* wait for the first connection to terminate, then launch the rest. */	reap_threads();	/* Start up the connections */	for (i = 2; i <= connections; ++i) {	    rv = launch_thread(do_connects, &addr, model_sock, i);	}    }    reap_threads();    destroy_thread_data();    PR_Close(model_sock);    networkEnd();}SECStatusreadBigFile(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;}intmain(int argc, char **argv){    const char *         dir         = ".";    char *               fNickName   = NULL;    const char *         fileName    = NULL;    char *               hostName    = NULL;    char *               nickName    = NULL;    char *               progName    = NULL;    char *               tmp         = NULL;    char *		 passwd      = NULL;    CERTCertificate *    cert   [kt_kea_size] = { NULL };    SECKEYPrivateKey *   privKey[kt_kea_size] = { NULL };    int                  connections = 1;    int                  exitVal;    unsigned short       port        = 443;    SECStatus            rv;    PLOptState *         optstate;    PLOptStatus          status;    /* 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:C:c:d:f:n:op:vw:");    while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {	switch(optstate->option) {	case '2':	    fileName = optstate->value;	    break;	case 'C':	    cipherString = optstate->value;	    break;	case 'c':	    connections = PORT_Atoi(optstate->value);	    break;	case 'd':	    dir = optstate->value;	    break;	case 'f':	    fNickName = optstate->value;	    break;        case 'n':	    nickName = optstate->value;	    break;	case 'o':	    MakeCertOK = 1;	    break;	case 'p':	    port = PORT_Atoi(optstate->value);	    break;        case 'v':	    verbose++;	    break;	case 'w':	    passwd = optstate->value;	    break;	case '\0':	    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_Init(dir);    if (rv != SECSuccess) {    	fputs("NSS_Init failed.\n", stderr);	exit(1);    }    if (nickName) {	cert[kt_rsa] = PK11_FindCertFromNickname(nickName, passwd);	if (cert[kt_rsa] == NULL) {	    fprintf(stderr, "strsclnt: Can't find certificate %s\n", nickName);	    exit(1);	}	privKey[kt_rsa] = PK11_FindKeyByAnyCert(cert[kt_rsa], passwd);	if (privKey[kt_rsa] == NULL) {	    fprintf(stderr, "strsclnt: Can't find Private Key for cert %s\n", 		    nickName);	    exit(1);	}    }    if (fNickName) {	cert[kt_fortezza] = PK11_FindCertFromNickname(fNickName, passwd);	if (cert[kt_fortezza] == NULL) {	    fprintf(stderr, "strsclnt: Can't find certificate %s\n", fNickName);	    exit(1);	}	privKey[kt_fortezza] = PK11_FindKeyByAnyCert(cert[kt_fortezza], passwd);	if (privKey[kt_fortezza] == NULL) {	    fprintf(stderr, "strsclnt: Can't find Private Key for cert %s\n", 		    fNickName);	    exit(1);	}    }    client_main(port, connections, privKey, cert, hostName, nickName);    /* some final stats. */    if (ssl3_hsh_sid_cache_hits + ssl3_hsh_sid_cache_misses +        ssl3_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",	    ssl3_hsh_sid_cache_hits, 	    ssl3_hsh_sid_cache_misses,	    ssl3_hsh_sid_cache_not_ok);    }    exitVal = (ssl3_hsh_sid_cache_misses > 1) ||              (ssl3_hsh_sid_cache_not_ok != 0) ||	      (certsTested > 1);    NSS_Shutdown();    PR_Cleanup();    return exitVal;}

⌨️ 快捷键说明

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