server.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:22k
- /*
- * 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 server program listens on a port, accepts client connection, reads *
- * request and responds to it *
- ****************************************************************************/
- /* Generic header files */
- #include <stdio.h>
- #include <string.h>
- /* NSPR header files */
- #include "nspr.h"
- #include "plgetopt.h"
- #include "prerror.h"
- #include "prnetdb.h"
- /* NSS header files */
- #include "pk11func.h"
- #include "secitem.h"
- #include "ssl.h"
- #include "certt.h"
- #include "nss.h"
- #include "secrng.h"
- #include "secder.h"
- #include "key.h"
- #include "sslproto.h"
- /* Custom header files */
- #include "sslsample.h"
- #ifndef PORT_Sprintf
- #define PORT_Sprintf sprintf
- #endif
- #define REQUEST_CERT_ONCE 1
- #define REQUIRE_CERT_ONCE 2
- #define REQUEST_CERT_ALL 3
- #define REQUIRE_CERT_ALL 4
- /* Global variables */
- GlobalThreadMgr threadMGR;
- char *password = NULL;
- CERTCertificate *cert = NULL;
- SECKEYPrivateKey *privKey = NULL;
- int stopping;
- static void
- Usage(const char *progName)
- {
- fprintf(stderr,
- "Usage: %s -n rsa_nickname -p port [-3RFrf] [-w password]n"
- " [-c ciphers] [-d dbdir] n"
- "-3 means disable SSL v3n"
- "-r means request certificate on first handshake.n"
- "-f means require certificate on first handshake.n"
- "-R means request certificate on all handshakes.n"
- "-F means require certificate on all handshakes.n"
- "-c ciphers Letter(s) chosen from the following listn"
- "A SSL2 RC4 128 WITH MD5n"
- "B SSL2 RC4 128 EXPORT40 WITH MD5n"
- "C SSL2 RC2 128 CBC WITH MD5n"
- "D SSL2 RC2 128 CBC EXPORT40 WITH MD5n"
- "E SSL2 DES 64 CBC WITH MD5n"
- "F SSL2 DES 192 EDE3 CBC WITH MD5n"
- "n"
- "a SSL3 FORTEZZA DMS WITH FORTEZZA CBC SHAn"
- "b SSL3 FORTEZZA DMS WITH RC4 128 SHAn"
- "c SSL3 RSA WITH RC4 128 MD5n"
- "d SSL3 RSA WITH 3DES EDE CBC SHAn"
- "e SSL3 RSA WITH DES CBC SHAn"
- "f SSL3 RSA EXPORT WITH RC4 40 MD5n"
- "g SSL3 RSA EXPORT WITH RC2 CBC 40 MD5n"
- "h SSL3 FORTEZZA DMS WITH NULL SHAn"
- "i SSL3 RSA WITH NULL MD5n"
- "j SSL3 RSA FIPS WITH 3DES EDE CBC SHAn"
- "k SSL3 RSA FIPS WITH DES CBC SHAn"
- "l SSL3 RSA EXPORT WITH DES CBC SHAt(new)n"
- "m SSL3 RSA EXPORT WITH RC4 56 SHAt(new)n",
- progName);
- exit(1);
- }
- /* Function: readDataFromSocket()
- *
- * Purpose: Parse an HTTP request by reading data from a GET or POST.
- *
- */
- SECStatus
- readDataFromSocket(PRFileDesc *sslSocket, DataBuffer *buffer, char **fileName)
- {
- char *post;
- int numBytes = 0;
- int newln = 0; /* # of consecutive newlns */
- /* Read data while it comes in from the socket. */
- while (PR_TRUE) {
- buffer->index = 0;
- newln = 0;
- /* Read the buffer. */
- numBytes = PR_Read(sslSocket, &buffer->data[buffer->index],
- buffer->remaining);
- if (numBytes <= 0) {
- errWarn("PR_Read");
- return SECFailure;
- }
- buffer->dataEnd = buffer->dataStart + numBytes;
- /* Parse the input, starting at the beginning of the buffer.
- * Stop when we detect two consecutive n's (or rn's)
- * as this signifies the end of the GET or POST portion.
- * The posted data follows.
- */
- while (buffer->index < buffer->dataEnd && newln < 2) {
- int octet = buffer->data[buffer->index++];
- if (octet == 'n') {
- newln++;
- } else if (octet != 'r') {
- newln = 0;
- }
- }
- /* Came to the end of the buffer, or second newline.
- * If we didn't get an empty line ("rnrn"), 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(buffer->data, "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 (buffer->index < buffer->dataEnd && newln < 3) {
- int octet = buffer->data[buffer->index++];
- if (octet == 'n') {
- newln++;
- }
- }
- if (newln == 3)
- break;
- }
- /* Have either (a) a complete get, (b) a complete post, (c) EOF */
- /* Execute a "GET " operation. */
- if (buffer->index > 0 && PORT_Strncmp(buffer->data, "GET ", 4) == 0) {
- int fnLength;
- /* File name is the part after "GET ". */
- fnLength = strcspn(buffer->data + 5, " rn");
- *fileName = (char *)PORT_Alloc(fnLength + 1);
- PORT_Strncpy(*fileName, buffer->data + 5, fnLength);
- (*fileName)[fnLength] = ' ';
- }
- return SECSuccess;
- }
- /* Function: authenticateSocket()
- *
- * Purpose: Configure a socket for SSL.
- *
- *
- */
- PRFileDesc *
- setupSSLSocket(PRFileDesc *tcpSocket, int requestCert)
- {
- PRFileDesc *sslSocket;
- SSLKEAType certKEA;
- int certErr = 0;
- SECStatus secStatus;
- /* Set the appropriate flags. */
- sslSocket = SSL_ImportFD(NULL, tcpSocket);
- if (sslSocket == NULL) {
- errWarn("SSL_ImportFD");
- goto loser;
- }
-
- 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_SERVER, PR_TRUE);
- if (secStatus != SECSuccess) {
- errWarn("SSL_Enable:SSL_HANDSHAKE_AS_SERVER");
- goto loser;
- }
- secStatus = SSL_Enable(sslSocket, SSL_REQUEST_CERTIFICATE,
- (requestCert >= REQUEST_CERT_ONCE));
- if (secStatus != SECSuccess) {
- errWarn("SSL_Enable:SSL_REQUEST_CERTIFICATE");
- goto loser;
- }
- secStatus = SSL_Enable(sslSocket, SSL_REQUIRE_CERTIFICATE,
- (requestCert == REQUIRE_CERT_ONCE));
- if (secStatus != SECSuccess) {
- errWarn("SSL_Enable:SSL_REQUIRE_CERTIFICATE");
- goto loser;
- }
- /* Set the appropriate callback routines. */
- secStatus = SSL_AuthCertificateHook(sslSocket, myAuthCertificate,
- CERT_GetDefaultCertDB());
- if (secStatus != SECSuccess) {
- errWarn("SSL_AuthCertificateHook");
- goto loser;
- }
- secStatus = SSL_BadCertHook(sslSocket,
- (SSLBadCertHandler)myBadCertHandler, &certErr);
- if (secStatus != SECSuccess) {
- errWarn("SSL_BadCertHook");
- goto loser;
- }
- secStatus = SSL_HandshakeCallback(sslSocket,
- (SSLHandshakeCallback)myHandshakeCallback,
- NULL);
- if (secStatus != SECSuccess) {
- errWarn("SSL_HandshakeCallback");
- goto loser;
- }
- secStatus = SSL_SetPKCS11PinArg(sslSocket, password);
- if (secStatus != SECSuccess) {
- errWarn("SSL_HandshakeCallback");
- goto loser;
- }
- certKEA = NSS_FindCertKEAType(cert);
- secStatus = SSL_ConfigSecureServer(sslSocket, cert, privKey, certKEA);
- if (secStatus != SECSuccess) {
- errWarn("SSL_ConfigSecureServer");
- goto loser;
- }
- return sslSocket;
- loser:
- PR_Close(tcpSocket);
- return NULL;
- }
- /* Function: authenticateSocket()
- *
- * Purpose: Perform client authentication on the socket.
- *
- */
- SECStatus
- authenticateSocket(PRFileDesc *sslSocket, PRBool requireCert)
- {
- CERTCertificate *cert;
- SECStatus secStatus;
- /* Returns NULL if client authentication is not enabled or if the
- * client had no certificate. */
- cert = SSL_PeerCertificate(sslSocket);
- if (cert) {
- /* Client had a certificate, so authentication is through. */
- CERT_DestroyCertificate(cert);
- return SECSuccess;
- }
- /* Request client to authenticate itself. */
- secStatus = SSL_Enable(sslSocket, SSL_REQUEST_CERTIFICATE, PR_TRUE);
- if (secStatus != SECSuccess) {
- errWarn("SSL_Enable:SSL_REQUEST_CERTIFICATE");
- return SECFailure;
- }
- /* If desired, require client to authenticate itself. Note
- * SSL_REQUEST_CERTIFICATE must also be on, as above. */
- secStatus = SSL_Enable(sslSocket, SSL_REQUIRE_CERTIFICATE, requireCert);
- if (secStatus != SECSuccess) {
- errWarn("SSL_Enable:SSL_REQUIRE_CERTIFICATE");
- return SECFailure;
- }
- /* Having changed socket configuration parameters, redo handshake. */
- secStatus = SSL_RedoHandshake(sslSocket);
- if (secStatus != SECSuccess) {
- errWarn("SSL_RedoHandshake");
- return SECFailure;
- }
- /* Force the handshake to complete before moving on. */
- secStatus = SSL_ForceHandshake(sslSocket);
- if (secStatus != SECSuccess) {
- errWarn("SSL_ForceHandshake");
- return SECFailure;
- }
- return SECSuccess;
- }
- /* Function: writeDataToSocket
- *
- * Purpose: Write the client's request back to the socket. If the client
- * requested a file, dump it to the socket.
- *
- */
- SECStatus
- writeDataToSocket(PRFileDesc *sslSocket, DataBuffer *buffer, char *fileName)
- {
- int headerLength;
- int numBytes;
- char messageBuffer[120];
- PRFileDesc *local_file_fd = NULL;
- char header[] = "<html><body><h1>Sample SSL server</h1><br><br>";
- char filehd[] = "<h2>The file you requested:</h2><br>";
- char reqhd[] = "<h2>This is your request:</h2><br>";
- char link[] = "Try getting a <a HREF="../testfile">file</a><br>";
- char footer[] = "<br><h2>End of request.</h2><br></body></html>";
- headerLength = PORT_Strlen(defaultHeader);
- /* Write a header to the socket. */
- numBytes = PR_Write(sslSocket, header, PORT_Strlen(header));
- if (numBytes < 0) {
- errWarn("PR_Write");
- goto loser;
- }
- if (fileName) {
- PRFileInfo info;
- PRStatus prStatus;
- /* Try to open the local file named.
- * If successful, then write it to the client.
- */
- prStatus = PR_GetFileInfo(fileName, &info);
- if (prStatus != PR_SUCCESS ||
- info.type != PR_FILE_FILE ||
- info.size < 0) {
- PORT_Free(fileName);
- /* Maybe a GET not sent from client.c? */
- goto writerequest;
- return SECSuccess;
- }
- local_file_fd = PR_Open(fileName, PR_RDONLY, 0);
- if (local_file_fd == NULL) {
- PORT_Free(fileName);
- goto writerequest;
- }
- /* Write a header to the socket. */
- numBytes = PR_Write(sslSocket, filehd, PORT_Strlen(filehd));
- if (numBytes < 0) {
- errWarn("PR_Write");
- goto loser;
- }
- /* Transmit the local file prepended by the default header
- * across the socket.
- */
- numBytes = PR_TransmitFile(sslSocket, local_file_fd,
- defaultHeader, headerLength,
- 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 %sn",
- 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.rn",
- 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.rn",
- 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, "EOFrnrnrn", 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.
- *
- */
- SECStatus
- handle_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...nn");
- secStatus = readDataFromSocket(sslSocket, &buffer, &fileName);
- if (secStatus != SECSuccess) {
- goto cleanup;
- }
- if (requestCert >= REQUEST_CERT_ALL) {
- fprintf(stdout, "nAuthentication requested.nn");
- secStatus = authenticateSocket(sslSocket,
- (requestCert == REQUIRE_CERT_ALL));
- if (secStatus != SECSuccess) {
- goto cleanup;
- }
- }
- fprintf(stdout, "nWriting data to socket...nn");
- 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.
- *
- */
- SECStatus
- accept_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, "nnnAbout 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.
- *
- */
- void
- server_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.
- *
- */
- int
- main(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;
- }