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 + -
显示快捷键?