Back to index

lightning-sunbird  0.9+nobinonly
Defines | Functions | Variables
server.c File Reference
#include <stdio.h>
#include <string.h>
#include "nspr.h"
#include "plgetopt.h"
#include "prerror.h"
#include "prnetdb.h"
#include "pk11func.h"
#include "secitem.h"
#include "ssl.h"
#include "certt.h"
#include "nss.h"
#include "secder.h"
#include "key.h"
#include "sslproto.h"
#include "sslsample.h"

Go to the source code of this file.

Defines

#define PORT_Sprintf   sprintf
#define REQUEST_CERT_ONCE   1
#define REQUIRE_CERT_ONCE   2
#define REQUEST_CERT_ALL   3
#define REQUIRE_CERT_ALL   4

Functions

static void Usage (const char *progName)
SECStatus readDataFromSocket (PRFileDesc *sslSocket, DataBuffer *buffer, char **fileName)
PRFileDescsetupSSLSocket (PRFileDesc *tcpSocket, int requestCert)
SECStatus authenticateSocket (PRFileDesc *sslSocket, PRBool requireCert)
SECStatus writeDataToSocket (PRFileDesc *sslSocket, DataBuffer *buffer, char *fileName)
SECStatus handle_connection (void *tcp_sock, int requestCert)
SECStatus accept_connection (void *listener, int requestCert)
void server_main (unsigned short port, int requestCert, SECKEYPrivateKey *privKey, CERTCertificate *cert, PRBool disableSSL3)
int main (int argc, char **argv)
 The Xalan testcases app.

Variables

GlobalThreadMgr threadMGR
char * password = NULL
CERTCertificate * cert = NULL
SECKEYPrivateKey * privKey = NULL
int stopping

Define Documentation

#define PORT_Sprintf   sprintf

Definition at line 70 of file server.c.

Definition at line 75 of file server.c.

Definition at line 73 of file server.c.

Definition at line 76 of file server.c.

Definition at line 74 of file server.c.


Function Documentation

SECStatus accept_connection ( void listener,
int  requestCert 
)

Definition at line 590 of file server.c.

{
       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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

SECStatus authenticateSocket ( PRFileDesc sslSocket,
PRBool  requireCert 
)

Definition at line 303 of file server.c.

{
       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_OptionSet(sslSocket, SSL_REQUEST_CERTIFICATE, PR_TRUE);
       if (secStatus != SECSuccess) {
              errWarn("SSL_OptionSet:SSL_REQUEST_CERTIFICATE");
              return SECFailure;
       }

       /* If desired, require client to authenticate itself.  Note
        * SSL_REQUEST_CERTIFICATE must also be on, as above.  */
       secStatus = SSL_OptionSet(sslSocket, SSL_REQUIRE_CERTIFICATE, requireCert);
       if (secStatus != SECSuccess) {
              errWarn("SSL_OptionSet:SSL_REQUIRE_CERTIFICATE");
              return SECFailure;
       }

       /* Having changed socket configuration parameters, redo handshake. */
       secStatus = SSL_ReHandshake(sslSocket, PR_TRUE);
       if (secStatus != SECSuccess) {
              errWarn("SSL_ReHandshake");
              return SECFailure;
       }

       /* Force the handshake to complete before moving on. */
       secStatus = SSL_ForceHandshake(sslSocket);
       if (secStatus != SECSuccess) {
              errWarn("SSL_ForceHandshake");
              return SECFailure;
       }

       return SECSuccess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

SECStatus handle_connection ( void tcp_sock,
int  requestCert 
)

Definition at line 519 of file server.c.

{
       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;
}

Here is the call graph for this function:

int main ( int  argc,
char **  argv 
)

The Xalan testcases app.

Definition at line 713 of file server.c.

{
       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. */
           disableAllSSLCiphers();

           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, PR_TRUE);
                  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. */
       if (NSS_Shutdown() != SECSuccess) {
            exit(1);
        }
       PR_Cleanup();
       return 0;
}

Here is the call graph for this function:

SECStatus readDataFromSocket ( PRFileDesc sslSocket,
DataBuffer buffer,
char **  fileName 
)

Definition at line 125 of file server.c.

{
       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 \r\n'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 ("\r\n\r\n"), 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, " \r\n");
              *fileName = (char *)PORT_Alloc(fnLength + 1);
              PORT_Strncpy(*fileName, buffer->data + 5, fnLength);
              (*fileName)[fnLength] = '\0';
       }

       return SECSuccess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void server_main ( unsigned short  port,
int  requestCert,
SECKEYPrivateKey *  privKey,
CERTCertificate *  cert,
PRBool  disableSSL3 
)

Definition at line 639 of file server.c.

{
       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_CipherPrefSetDefault(SSL_RSA_WITH_NULL_MD5, PR_TRUE);
       if (secStatus != SECSuccess) {
              exitErr("SSL_CipherPrefSetDefault: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);
       }
}

Here is the call graph for this function:

PRFileDesc* setupSSLSocket ( PRFileDesc tcpSocket,
int  requestCert 
)

Definition at line 210 of file server.c.

{
       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_OptionSet(sslSocket, SSL_SECURITY, PR_TRUE);
       if (secStatus != SECSuccess) {
              errWarn("SSL_OptionSet SSL_SECURITY");
              goto loser;
       }

       secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
       if (secStatus != SECSuccess) {
              errWarn("SSL_OptionSet:SSL_HANDSHAKE_AS_SERVER");
              goto loser;
       }

       secStatus = SSL_OptionSet(sslSocket, SSL_REQUEST_CERTIFICATE, 
                              (requestCert >= REQUEST_CERT_ONCE));
       if (secStatus != SECSuccess) {
              errWarn("SSL_OptionSet:SSL_REQUEST_CERTIFICATE");
              goto loser;
       }

       secStatus = SSL_OptionSet(sslSocket, SSL_REQUIRE_CERTIFICATE, 
                              (requestCert == REQUIRE_CERT_ONCE));
       if (secStatus != SECSuccess) {
              errWarn("SSL_OptionSet: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;
}

Here is the call graph for this function:

static void Usage ( const char *  progName) [static]

Definition at line 86 of file server.c.

{
       fprintf(stderr, 

"Usage: %s -n rsa_nickname -p port [-3RFrf] [-w password]\n"
"                                  [-c ciphers] [-d dbdir] \n"
"-3 means disable SSL v3\n"
"-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 list\n"
"A       SSL2 RC4 128 WITH MD5\n"
"B       SSL2 RC4 128 EXPORT40 WITH MD5\n"
"C       SSL2 RC2 128 CBC WITH MD5\n"
"D       SSL2 RC2 128 CBC EXPORT40 WITH MD5\n"
"E       SSL2 DES 64 CBC WITH MD5\n"
"F       SSL2 DES 192 EDE3 CBC WITH MD5\n"
"\n"
"c       SSL3 RSA WITH RC4 128 MD5\n"
"d       SSL3 RSA WITH 3DES EDE CBC SHA\n"
"e       SSL3 RSA WITH DES CBC SHA\n"
"f       SSL3 RSA EXPORT WITH RC4 40 MD5\n"
"g       SSL3 RSA EXPORT WITH RC2 CBC 40 MD5\n"
"i       SSL3 RSA WITH NULL MD5\n"
"j       SSL3 RSA FIPS WITH 3DES EDE CBC SHA\n"
"k       SSL3 RSA FIPS WITH DES CBC SHA\n"
"l       SSL3 RSA EXPORT WITH DES CBC SHA\t(new)\n"
"m       SSL3 RSA EXPORT WITH RC4 56 SHA\t(new)\n",
       progName);
       exit(1);
}

Here is the call graph for this function:

SECStatus writeDataToSocket ( PRFileDesc sslSocket,
DataBuffer buffer,
char *  fileName 
)

Definition at line 356 of file server.c.

{
       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;
              }

              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 %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;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

CERTCertificate* cert = NULL

Definition at line 81 of file server.c.

char* password = NULL

Definition at line 80 of file server.c.

SECKEYPrivateKey* privKey = NULL

Definition at line 82 of file server.c.

Definition at line 83 of file server.c.

Definition at line 79 of file server.c.