server.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 823 行 · 第 1/2 页
C
823 行
PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); /* Error in transmission. */ if (numBytes < 0) { errWarn("PR_TransmitFile"); /* i = PORT_Strlen(errString); PORT_Memcpy(buf, errString, i); */ /* Transmitted bytes successfully. */ } else { numBytes -= headerLength; fprintf(stderr, "PR_TransmitFile wrote %d bytes from %s\n", numBytes, fileName); } PORT_Free(fileName); PR_Close(local_file_fd); }writerequest: /* Write a header to the socket. */ numBytes = PR_Write(sslSocket, reqhd, PORT_Strlen(reqhd)); if (numBytes < 0) { errWarn("PR_Write"); goto loser; } /* Write the buffer data to the socket. */ if (buffer->index <= 0) { /* Reached the EOF. Report incomplete transaction to socket. */ PORT_Sprintf(messageBuffer, "GET or POST incomplete after %d bytes.\r\n", buffer->dataEnd); numBytes = PR_Write(sslSocket, messageBuffer, PORT_Strlen(messageBuffer)); if (numBytes < 0) { errWarn("PR_Write"); goto loser; } } else { /* Display the buffer data. */ fwrite(buffer->data, 1, buffer->index, stdout); /* Write the buffer data to the socket. */ numBytes = PR_Write(sslSocket, buffer->data, buffer->index); if (numBytes < 0) { errWarn("PR_Write"); goto loser; } /* Display security information for the socket. */ printSecurityInfo(sslSocket); /* Write any discarded data out to the socket. */ if (buffer->index < buffer->dataEnd) { PORT_Sprintf(buffer->data, "Discarded %d characters.\r\n", buffer->dataEnd - buffer->index); numBytes = PR_Write(sslSocket, buffer->data, PORT_Strlen(buffer->data)); if (numBytes < 0) { errWarn("PR_Write"); goto loser; } } } /* Write a footer to the socket. */ numBytes = PR_Write(sslSocket, footer, PORT_Strlen(footer)); if (numBytes < 0) { errWarn("PR_Write"); goto loser; } /* Write a link to the socket. */ numBytes = PR_Write(sslSocket, link, PORT_Strlen(link)); if (numBytes < 0) { errWarn("PR_Write"); goto loser; } /* Complete the HTTP transaction. */ numBytes = PR_Write(sslSocket, "EOF\r\n\r\n\r\n", 9); if (numBytes < 0) { errWarn("PR_Write"); goto loser; } /* Do a nice shutdown if asked. */ if (!strncmp(buffer->data, stopCmd, strlen(stopCmd))) { stopping = 1; } return SECSuccess;loser: /* Do a nice shutdown if asked. */ if (!strncmp(buffer->data, stopCmd, strlen(stopCmd))) { stopping = 1; } return SECFailure;}/* Function: int handle_connection() * * Purpose: Thread to handle a connection to a socket. * */SECStatushandle_connection(void *tcp_sock, int requestCert){ PRFileDesc * tcpSocket = (PRFileDesc *)tcp_sock; PRFileDesc * sslSocket = NULL; SECStatus secStatus = SECFailure; PRStatus prStatus; PRSocketOptionData socketOption; DataBuffer buffer; char * fileName = NULL; /* Initialize the data buffer. */ memset(buffer.data, 0, BUFFER_SIZE); buffer.remaining = BUFFER_SIZE; buffer.index = 0; buffer.dataStart = 0; buffer.dataEnd = 0; /* Make sure the socket is blocking. */ socketOption.option = PR_SockOpt_Nonblocking; socketOption.value.non_blocking = PR_FALSE; PR_SetSocketOption(tcpSocket, &socketOption); sslSocket = setupSSLSocket(tcpSocket, requestCert); if (sslSocket == NULL) { errWarn("setupSSLSocket"); goto cleanup; } secStatus = SSL_ResetHandshake(sslSocket, /* asServer */ PR_TRUE); if (secStatus != SECSuccess) { errWarn("SSL_ResetHandshake"); goto cleanup; } /* Read data from the socket, parse it for HTTP content. * If the user is requesting/requiring authentication, authenticate * the socket. Then write the result back to the socket. */ fprintf(stdout, "\nReading data from socket...\n\n"); secStatus = readDataFromSocket(sslSocket, &buffer, &fileName); if (secStatus != SECSuccess) { goto cleanup; } if (requestCert >= REQUEST_CERT_ALL) { fprintf(stdout, "\nAuthentication requested.\n\n"); secStatus = authenticateSocket(sslSocket, (requestCert == REQUIRE_CERT_ALL)); if (secStatus != SECSuccess) { goto cleanup; } } fprintf(stdout, "\nWriting data to socket...\n\n"); secStatus = writeDataToSocket(sslSocket, &buffer, fileName);cleanup: /* Close down the socket. */ prStatus = PR_Close(tcpSocket); if (prStatus != PR_SUCCESS) { errWarn("PR_Close"); } return secStatus;}/* Function: int accept_connection() * * Purpose: Thread to accept a connection to the socket. * */SECStatusaccept_connection(void *listener, int requestCert){ PRFileDesc *listenSocket = (PRFileDesc*)listener; PRNetAddr addr; PRStatus prStatus; /* XXX need an SSL socket here? */ while (!stopping) { PRFileDesc *tcpSocket; SECStatus result; fprintf(stderr, "\n\n\nAbout to call accept.\n"); /* Accept a connection to the socket. */ tcpSocket = PR_Accept(listenSocket, &addr, PR_INTERVAL_NO_TIMEOUT); if (tcpSocket == NULL) { errWarn("PR_Accept"); break; } /* Accepted the connection, now handle it. */ result = launch_thread(&threadMGR, handle_connection, tcpSocket, requestCert); if (result != SECSuccess) { prStatus = PR_Close(tcpSocket); if (prStatus != PR_SUCCESS) { exitErr("PR_Close"); } break; } } fprintf(stderr, "Closing listen socket.\n"); prStatus = PR_Close(listenSocket); if (prStatus != PR_SUCCESS) { exitErr("PR_Close"); } return SECSuccess;}/* Function: void server_main() * * Purpose: This is the server's main function. It configures a socket * and listens to it. * */voidserver_main( unsigned short port, int requestCert, SECKEYPrivateKey * privKey, CERTCertificate * cert, PRBool disableSSL3){ SECStatus secStatus; PRStatus prStatus; PRFileDesc * listenSocket; PRNetAddr addr; PRSocketOptionData socketOption; /* Create a new socket. */ listenSocket = PR_NewTCPSocket(); if (listenSocket == NULL) { exitErr("PR_NewTCPSocket"); } /* Set socket to be blocking - * on some platforms the default is nonblocking. */ socketOption.option = PR_SockOpt_Nonblocking; socketOption.value.non_blocking = PR_FALSE; prStatus = PR_SetSocketOption(listenSocket, &socketOption); if (prStatus != PR_SUCCESS) { exitErr("PR_SetSocketOption"); } /* This cipher is not on by default. The Acceptance test * would like it to be. Turn this cipher on. */ secStatus = SSL_EnableCipher(SSL_RSA_WITH_NULL_MD5, PR_TRUE); if (secStatus != SECSuccess) { exitErr("SSL_EnableCipher:SSL_RSA_WITH_NULL_MD5"); } /* Configure the network connection. */ addr.inet.family = PR_AF_INET; addr.inet.ip = PR_INADDR_ANY; addr.inet.port = PR_htons(port); /* Bind the address to the listener socket. */ prStatus = PR_Bind(listenSocket, &addr); if (prStatus != PR_SUCCESS) { exitErr("PR_Bind"); } /* Listen for connection on the socket. The second argument is * the maximum size of the queue for pending connections. */ prStatus = PR_Listen(listenSocket, 5); if (prStatus != PR_SUCCESS) { exitErr("PR_Listen"); } /* Launch thread to handle connections to the socket. */ secStatus = launch_thread(&threadMGR, accept_connection, listenSocket, requestCert); if (secStatus != SECSuccess) { PR_Close(listenSocket); } else { reap_threads(&threadMGR); destroy_thread_data(&threadMGR); }}/* Function: int main() * * Purpose: Parses command arguments and configures SSL server. * */intmain(int argc, char **argv){ char * progName = NULL; char * nickName = NULL; char * cipherString = NULL; char * dir = "."; int requestCert = 0; unsigned short port = 0; SECStatus secStatus; PRBool disableSSL3 = PR_FALSE; PLOptState * optstate; PLOptStatus status; /* Zero out the thread manager. */ PORT_Memset(&threadMGR, 0, sizeof(threadMGR)); progName = PL_strdup(argv[0]); optstate = PL_CreateOptState(argc, argv, "3FRc:d:fp:n:rw:"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch(optstate->option) { case '3': disableSSL3 = PR_TRUE; break; case 'F': requestCert = REQUIRE_CERT_ALL; break; case 'R': requestCert = REQUEST_CERT_ALL; break; case 'c': cipherString = PL_strdup(optstate->value); break; case 'd': dir = PL_strdup(optstate->value); break; case 'f': requestCert = REQUIRE_CERT_ONCE; break; case 'n': nickName = PL_strdup(optstate->value); break; case 'p': port = PORT_Atoi(optstate->value); break; case 'r': requestCert = REQUEST_CERT_ONCE; break; case 'w': password = PL_strdup(optstate->value); break; default: case '?': Usage(progName); } } if (nickName == NULL || port == 0) Usage(progName); /* Call the NSPR initialization routines. */ PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); /* Set the cert database password callback. */ PK11_SetPasswordFunc(myPasswd); /* Initialize NSS. */ secStatus = NSS_Init(dir); if (secStatus != SECSuccess) { exitErr("NSS_Init"); } /* Set the policy for this server (REQUIRED - no default). */ secStatus = NSS_SetDomesticPolicy(); if (secStatus != SECSuccess) { exitErr("NSS_SetDomesticPolicy"); } /* XXX keep this? */ /* 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) { SECStatus status; status = SSL_CipherPrefSetDefault(cipher, SSL_ALLOWED); if (status != SECSuccess) errWarn("SSL_CipherPrefSetDefault()"); } } } /* Get own certificate and private key. */ cert = PK11_FindCertFromNickname(nickName, password); if (cert == NULL) { exitErr("PK11_FindCertFromNickname"); } privKey = PK11_FindKeyByAnyCert(cert, password); if (privKey == NULL) { exitErr("PK11_FindKeyByAnyCert"); } /* Configure the server's cache for a multi-process application * using default timeout values (24 hrs) and directory location (/tmp). */ SSL_ConfigMPServerSIDCache(256, 0, 0, NULL); /* Launch server. */ server_main(port, requestCert, privKey, cert, disableSSL3); /* Shutdown NSS and exit NSPR gracefully. */ NSS_Shutdown(); PR_Cleanup(); return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?