selfserv.c

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

C
1,329
字号
	}	++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_JOINABLE_THREAD, 0);    if (slot->prThread == NULL) {	PR_Unlock(threadLock);	printf("selfserv: Failed to launch thread!\n");	return SECFailure;    }     slot->inUse   = 1;    slot->running = 1;    ++numRunning;    PR_Unlock(threadLock);    PRINTF("selfserv: Launched thread in slot %d \n", i);    FLUSH;    return SECSuccess;}int reap_threads(void){    perThread * slot;    int         i;    if (!threadLock)    	return 0;    PR_Lock(threadLock);    while (numRunning > 0) {    	PR_WaitCondVar(threadEndQ, PR_INTERVAL_NO_TIMEOUT);	for (i = 0; i < numUsed; ++i) {	    slot = threads + i;	    if (slot->running == rs_zombie)  {		/* Handle cleanup of thread here. */		PRINTF("selfserv: Thread in slot %d returned %d\n", i, slot->rv);		/* Now make sure the thread has ended OK. */		PR_JoinThread(slot->prThread);		slot->running = rs_idle;		--numRunning;		/* notify the thread launcher. */		PR_NotifyCondVar(threadStartQ);	    }	}    }    /* Safety Sam sez: make sure count is right. */    for (i = 0; i < numUsed; ++i) {	slot = threads + i;    	if (slot->running != rs_idle)  {	    FPRINTF(stderr, "selfserv: Thread in slot %d is in state %d!\n", 	            i, slot->running);    	}    }    PR_Unlock(threadLock);    FLUSH;    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_FALSE;PRBool disableSSL3     = PR_FALSE;PRBool disableTLS      = PR_FALSE;PRBool disableRollBack  = PR_FALSE;static const char stopCmd[] = { "GET /stop " };static const char outHeader[] = {    "HTTP/1.0 200 OK\r\n"    "Server: Generic Web Server\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;    PR_Lock(lv->lock);    rv = lv->count += addend;    if (rv <= 0) {	PR_NotifyCondVar(lv->condVar);    }    PR_Unlock(lv->lock);    return rv;}intdo_writes(    PRFileDesc *	ssl_sock,    PRFileDesc *	model_sock,    int         	requestCert    ){    int			sent  = 0;    int 		count = 0;    lockedVars *	lv = (lockedVars *)model_sock;    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, "selfserv: 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);    FLUSH;    return (sent < bigBuf.len) ? SECFailure : SECSuccess;}int handle_fdx_connection(    PRFileDesc *       tcp_sock,    PRFileDesc *       model_sock,    int                requestCert    ){    PRFileDesc *       ssl_sock	= NULL;    SECStatus          result;    int                firstTime = 1;    lockedVars         lv;    PRSocketOptionData opt;    char               buf[10240];    opt.option             = PR_SockOpt_Nonblocking;    opt.value.non_blocking = PR_FALSE;    PR_SetSocketOption(tcp_sock, &opt);    if (useModelSocket && model_sock) {	SECStatus rv;	ssl_sock = SSL_ImportFD(model_sock, tcp_sock);	if (!ssl_sock) {	    errWarn("SSL_ImportFD with model");	    goto cleanup;	}	rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 1);	if (rv != SECSuccess) {	    errWarn("SSL_ResetHandshake");	    goto cleanup;	}    } else {	ssl_sock = tcp_sock;    }    lockedVars_Init(&lv);    lockedVars_AddToCount(&lv, 1);    /* Attempt to launch the writer thread. */    result = launch_thread(do_writes, ssl_sock, (PRFileDesc *)&lv,                            requestCert);    if (result == SECSuccess)       do {	/* do reads here. */	int count;	count = PR_Read(ssl_sock, buf, sizeof buf);	if (count < 0) {	    errWarn("FDX PR_Read");	    break;	}	FPRINTF(stderr, "selfserv: FDX PR_Read read %d bytes.\n", count );	if (firstTime) {	    firstTime = 0;	    printSecurityInfo(ssl_sock);	}    } while (lockedVars_AddToCount(&lv, 0) > 0);    /* Wait for writer to finish */    lockedVars_WaitForDone(&lv);    lockedVars_Destroy(&lv);    FLUSH;cleanup:    if (ssl_sock)	PR_Close(ssl_sock);    else	PR_Close(tcp_sock);    return SECSuccess;}inthandle_connection(     PRFileDesc *tcp_sock,    PRFileDesc *model_sock,    int         requestCert    ){    PRFileDesc *       ssl_sock = NULL;    char  *            post;    char  *            pBuf;			/* unused space at end of buf */    const char *       errString;    PRStatus           status;    int                bufRem;			/* unused bytes at end of buf */    int                bufDat;			/* characters received in buf */    int                newln    = 0;		/* # of consecutive newlns */    int                firstTime = 1;    int                i;    int                rv;    PRSocketOptionData opt;    char               msgBuf[120];    char               buf[10240];    pBuf   = buf;    bufRem = sizeof buf;    memset(buf, 0, sizeof buf);    opt.option             = PR_SockOpt_Nonblocking;    opt.value.non_blocking = PR_FALSE;    PR_SetSocketOption(tcp_sock, &opt);    if (useModelSocket && model_sock) {	SECStatus rv;	ssl_sock = SSL_ImportFD(model_sock, tcp_sock);	if (!ssl_sock) {	    errWarn("SSL_ImportFD with model");	    goto cleanup;	}	rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 1);	if (rv != SECSuccess) {	    errWarn("SSL_ResetHandshake");	    goto cleanup;	}    } else {	ssl_sock = tcp_sock;    }    while (1) {	newln = 0;	i     = 0;	rv = PR_Read(ssl_sock, pBuf, bufRem);	if (rv == 0) {	    errWarn("HDX PR_Read hit EOF");	    break;	}	if (rv < 0) {	    errWarn("HDX PR_Read");	    goto cleanup;	}	if (firstTime) {	    firstTime = 0;	    printSecurityInfo(ssl_sock);	}	pBuf   += rv;	bufRem -= rv;	bufDat = pBuf - buf;	/* Parse the input, starting at the beginning of the buffer.	 * Stop when we detect two consecutive \n's (or \r\n's) 	 * as this signifies the end of the GET or POST portion.	 * The posted data follows.	 */	while (i < bufDat && newln < 2) {	    int octet = buf[i++];	    if (octet == '\n') {		newln++;	    } else if (octet != '\r') {		newln = 0;	    }	}	/* came to the end of the buffer, or second newln	 * If we didn't get an empty line (CRLFCRLF) then keep on reading.	 */	if (newln < 2) 	    continue;	/* we're at the end of the HTTP request.	 * If the request is a POST, then there will be one more	 * line of data.	 * This parsing is a hack, but ok for SSL test purposes.	 */	post = PORT_Strstr(buf, "POST ");	if (!post || *post != 'P') 	    break;	/* It's a post, so look for the next and final CR/LF. */	/* We should parse content length here, but ... */	while (i < bufDat && newln < 3) {	    int octet = buf[i++];	    if (octet == '\n') {		newln++;	    }	}	if (newln == 3)	    break;    }    bufDat = pBuf - buf;    if (bufDat) do {	/* just close if no data */	/* Have either (a) a complete get, (b) a complete post, (c) EOF */	if (i > 0 && !strncmp(buf, stopCmd, 4)) {	    PRFileDesc *local_file_fd = NULL;	    PRInt32     bytes;	    char *      pSave;	    PRFileInfo  info;	    char        saveChar;	    /* try to open the file named.  	     * If succesful, then write it to the client.	     */	    pSave = strpbrk(buf + 4, " \r\n");	    if (pSave) {		saveChar = *pSave;		*pSave = 0;	    }	    status = PR_GetFileInfo(buf + 4, &info);	    if (status == PR_SUCCESS &&		info.type == PR_FILE_FILE &&		info.size >= 0 &&		NULL != (local_file_fd = PR_Open(buf + 4, PR_RDONLY, 0))) {		bytes = PR_TransmitFile(ssl_sock, local_file_fd, outHeader,					sizeof outHeader - 1, 					PR_TRANSMITFILE_KEEP_OPEN,					PR_INTERVAL_NO_TIMEOUT);		if (bytes < 0) {		    errString = errWarn("PR_TransmitFile");		    i = PORT_Strlen(errString);		    PORT_Memcpy(buf, errString, i);		    goto send_answer;		} else {		    bytes -= sizeof outHeader - 1;		    FPRINTF(stderr, 			    "selfserv: PR_TransmitFile wrote %d bytes from %s\n",			    bytes, buf + 4);		}		PR_Close(local_file_fd);		break;	    }	    /* file didn't open. */	    if (pSave) {		*pSave = saveChar;	/* put it back. */	    }	}send_answer:	/* if user has requested client auth in a subsequent handshake,	 * do it here.	 */	if (requestCert > 2) { /* request cert was 3 or 4 */	    CERTCertificate *  cert =  SSL_PeerCertificate(ssl_sock);	    if (cert) {		CERT_DestroyCertificate(cert);	    } else {		rv = SSL_Enable(ssl_sock, SSL_REQUEST_CERTIFICATE, 1);		if (rv < 0) {		    errWarn("second SSL_Enable SSL_REQUEST_CERTIFICATE");		    break;		}		rv = SSL_Enable(ssl_sock, SSL_REQUIRE_CERTIFICATE, 				(requestCert == 4));		if (rv < 0) {		    errWarn("second SSL_Enable SSL_REQUIRE_CERTIFICATE");		    break;		}		rv = SSL_RedoHandshake(ssl_sock);		if (rv != 0) {		    errWarn("SSL_RedoHandshake");		    break;		}		rv = SSL_ForceHandshake(ssl_sock);

⌨️ 快捷键说明

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