Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Enumerations | Functions | Variables
selfserv.c File Reference
#include <stdio.h>
#include <string.h>
#include "secutil.h"
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include "nspr.h"
#include "prio.h"
#include "prerror.h"
#include "prnetdb.h"
#include "prclist.h"
#include "plgetopt.h"
#include "pk11func.h"
#include "secitem.h"
#include "nss.h"
#include "ssl.h"
#include "sslproto.h"
#include "cert.h"
#include "certt.h"

Go to the source code of this file.

Classes

struct  jobStr
struct  perThreadStr

Defines

#define PORT_Sprintf   sprintf
#define PORT_Strstr   strstr
#define PORT_Malloc   PR_Malloc
#define PRINTF   if (verbose) printf
#define FPRINTF   if (verbose) fprintf
#define FLUSH   if (verbose) { fflush(stdout); fflush(stderr); }
#define VLOG(arg)   PR_LOG(lm,PR_LOG_DEBUG,arg)
#define MIN_THREADS   3
#define DEFAULT_THREADS   8
#define MAX_THREADS   4096
#define MAX_PROCS   25
#define DESTROY_CONDVAR(name)
#define DESTROY_LOCK(name)
#define HEXCHAR_TO_INT(c, i)

Typedefs

typedef struct jobStr JOB
typedef int startFn (PRFileDesc *a, PRFileDesc *b, int c)
typedef struct perThreadStr perThread

Enumerations

enum  runState {
  rs_idle = 0, rs_running = 1, rs_zombie = 2, rs_idle = 0,
  rs_running = 1, rs_zombie = 2, rs_idle = 0, rs_running = 1,
  rs_zombie = 2, rs_idle = 0, rs_running = 1, rs_zombie = 2,
  rs_idle = 0, rs_running = 1, rs_zombie = 2, rs_idle = 0,
  rs_running = 1, rs_zombie = 2
}

Functions

static int handle_connection (PRFileDesc *, PRFileDesc *, int)
char * ownPasswd (PK11SlotInfo *info, PRBool retry, void *arg)
static void Usage (const char *progName)
static const char * errWarn (char *funcString)
static void errExit (char *funcString)
void disableAllSSLCiphers (void)
SECStatus disableExportSSLCiphers (void)
static SECStatus mySSLAuthCertificate (void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer)
void printSecurityInfo (PRFileDesc *fd)
static SECStatus myBadCertHandler (void *arg, PRFileDesc *fd)
SECStatus setupJobs (int maxJobs)
void thread_wrapper (void *arg)
int jobLoop (PRFileDesc *a, PRFileDesc *b, int c)
SECStatus launch_threads (startFn *startFunc, PRFileDesc *a, PRFileDesc *b, int c, PRBool local)
void terminateWorkerThreads (void)
static void logger (void *arg)
void savecipher (int c)
static SECStatus reload_crl (PRFileDesc *crlFile)
void stop_server ()
SECStatus do_accepts (PRFileDesc *listen_sock, PRFileDesc *model_sock, int requestCert)
PRFileDescgetBoundListenSocket (unsigned short port)
void server_main (PRFileDesc *listen_sock, int requestCert, SECKEYPrivateKey **privKey, CERTCertificate **cert)
SECStatus readBigFile (const char *fileName)
PRProcesshaveAChild (int argc, char **argv, PRProcessAttr *attr)
void beAGoodParent (int argc, char **argv, int maxProcs, PRFileDesc *listen_sock)
int main (int argc, char **argv)
 The Xalan testcases app.

Variables

int NumSidCacheEntries = 1024
static const char envVarName [] = { SSL_ENV_VAR_NAME }
static const char inheritableSockName [] = { "SELFSERV_LISTEN_SOCKET" }
static PRBool logStats = PR_FALSE
static int logPeriod = 30
static PRUint32 loggerOps = 0
const int ssl2CipherSuites []
const int ssl3CipherSuites []
static int stopping
static PRBool noDelay
static int requestCert
static int verbose
static SECItem bigBuf
static PRThreadacceptorThread
static PRLogModuleInfolm
static int MakeCertOK
static int maxThreads = DEFAULT_THREADS
static PZLockqLock
static PRLocklastLoadedCrlLock
static PZCondVarjobQNotEmptyCv
static PZCondVarfreeListNotEmptyCv
static PZCondVarthreadCountChangeCv
static int threadCount
static PRCList jobQ
static PRCList freeJobs
static JOBjobTable
static perThreadthreads
PRBool useModelSocket = PR_FALSE
PRBool disableSSL2 = PR_FALSE
PRBool disableSSL3 = PR_FALSE
PRBool disableTLS = PR_FALSE
PRBool disableRollBack = PR_FALSE
PRBool NoReuse = PR_FALSE
PRBool hasSidCache = PR_FALSE
PRBool disableStepDown = PR_FALSE
PRBool bypassPKCS11 = PR_FALSE
PRBool disableLocking = PR_FALSE
PRBool testbypass = PR_FALSE
static const char stopCmd [] = { "GET /stop " }
static const char getCmd [] = { "GET " }
static const char EOFmsg [] = { "EOF\r\n\r\n\r\n" }
static const char outHeader []
static const char crlCacheErr [] = { "CRL ReCache Error: " }
PRUint16 cipherlist [100]
int nciphers
static SECItem * lastLoadedCrl = NULL
int numChildren
PRProcesschild [MAX_PROCS]

Class Documentation

struct jobStr

Definition at line 430 of file selfserv.c.

Collaboration diagram for jobStr:
Class Members
PRCList link
PRFileDesc * model_sock
int requestCert
PRFileDesc * tcp_sock
struct perThreadStr

Definition at line 470 of file selfserv.c.

Collaboration diagram for perThreadStr:
Class Members
void * a
PRFileDesc * a
int b
void * b
PRFileDesc * b
int c
PRBool inUse
PRThread * prThread
runState running
int rv
startFn * startFunc
runState state
int tid

Define Documentation

Definition at line 424 of file selfserv.c.

Value:
if (name) { \
        PZ_DestroyCondVar(name); name = NULL; }

Definition at line 589 of file selfserv.c.

Value:
if (name) { \
        PZ_DestroyLock(name); name = NULL; }

Definition at line 591 of file selfserv.c.

#define FLUSH   if (verbose) { fflush(stdout); fflush(stderr); }

Definition at line 174 of file selfserv.c.

Definition at line 173 of file selfserv.c.

#define HEXCHAR_TO_INT (   c,
  i 
)
Value:
if (((c) >= '0') && ((c) <= '9')) { \
       i = (c) - '0'; \
    } else if (((c) >= 'a') && ((c) <= 'f')) { \
       i = (c) - 'a' + 10; \
    } else if (((c) >= 'A') && ((c) <= 'F')) { \
       i = (c) - 'A' + 10; \
    } else if ((c) == '\0') { \
       fprintf(stderr, "Invalid length of cipher string (-c :WXYZ).\n"); \
       exit(9); \
    } else { \
       fprintf(stderr, "Non-hex char in cipher string (-c :WXYZ).\n"); \
       exit(9); \
    }

Definition at line 1643 of file selfserv.c.

#define MAX_PROCS   25

Definition at line 426 of file selfserv.c.

#define MAX_THREADS   4096

Definition at line 425 of file selfserv.c.

Definition at line 423 of file selfserv.c.

Definition at line 90 of file selfserv.c.

#define PORT_Sprintf   sprintf

Definition at line 82 of file selfserv.c.

#define PORT_Strstr   strstr

Definition at line 86 of file selfserv.c.

Definition at line 172 of file selfserv.c.

Definition at line 175 of file selfserv.c.


Typedef Documentation

typedef struct jobStr JOB
typedef struct perThreadStr perThread

Definition at line 466 of file selfserv.c.


Enumeration Type Documentation

enum runState
Enumerator:
rs_idle 
rs_running 
rs_zombie 
rs_idle 
rs_running 
rs_zombie 
rs_idle 
rs_running 
rs_zombie 
rs_idle 
rs_running 
rs_zombie 
rs_idle 
rs_running 
rs_zombie 
rs_idle 
rs_running 
rs_zombie 

Definition at line 468 of file selfserv.c.

{ rs_idle = 0, rs_running = 1, rs_zombie = 2 } runState;

Function Documentation

void beAGoodParent ( int  argc,
char **  argv,
int  maxProcs,
PRFileDesc listen_sock 
)

Definition at line 1574 of file selfserv.c.

{
    PRProcess *     newProcess;
    PRProcessAttr * attr;
    int             i;
    PRInt32         exitCode;
    PRStatus        rv;

    rv = PR_SetFDInheritable(listen_sock, PR_TRUE);
    if (rv != PR_SUCCESS)
       errExit("PR_SetFDInheritable");

    attr = PR_NewProcessAttr();
    if (!attr)
       errExit("PR_NewProcessAttr");

    rv = PR_ProcessAttrSetInheritableFD(attr, listen_sock, inheritableSockName);
    if (rv != PR_SUCCESS)
       errExit("PR_ProcessAttrSetInheritableFD");

    for (i = 0; i < maxProcs; ++i) {
       newProcess = haveAChild(argc, argv, attr);
       if (!newProcess) 
           break;
    }

    rv = PR_SetFDInheritable(listen_sock, PR_FALSE);
    if (rv != PR_SUCCESS)
       errExit("PR_SetFDInheritable");

    while (numChildren > 0) {
       newProcess = child[numChildren - 1];
       PR_WaitProcess(newProcess, &exitCode);
       fprintf(stderr, "Child %d exited with exit code %x\n", 
              numChildren, exitCode);
       numChildren--;
    }
    exit(0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 269 of file selfserv.c.

{
    const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
    int             i            = SSL_NumImplementedCiphers;
    SECStatus       rv;

    while (--i >= 0) {
       PRUint16 suite = cipherSuites[i];
        rv = SSL_CipherPrefSetDefault(suite, PR_FALSE);
       if (rv != SECSuccess) {
           printf("SSL_CipherPrefSetDefault rejected suite 0x%04x (i = %d)\n",
                 suite, i);
           errWarn("SSL_CipherPrefSetDefault");
       }
    }
}

Here is the caller graph for this function:

Definition at line 288 of file selfserv.c.

{
    const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
    int             i            = SSL_NumImplementedCiphers;
    SECStatus       rv           = SECSuccess;
    SSLCipherSuiteInfo info;

    while (--i >= 0) {
       PRUint16 suite = cipherSuites[i];
       SECStatus status;
       status = SSL_GetCipherSuiteInfo(suite, &info, sizeof info);
       if (status != SECSuccess) {
           printf("SSL_GetCipherSuiteInfo rejected suite 0x%04x (i = %d)\n",
                 suite, i);
           errWarn("SSL_GetCipherSuiteInfo");
           rv = SECFailure;
           continue;
       }
       if (info.cipherSuite != suite) {
           printf(
"SSL_GetCipherSuiteInfo returned wrong suite! Wanted 0x%04x, Got 0x%04x\n",
                 suite, i);
           PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
           rv = SECFailure;
           continue;
       }
       /* should check here that info.length >= offsetof isExportable */
       if (info.isExportable) {
           status = SSL_CipherPolicySet(suite, SSL_NOT_ALLOWED);
           if (status != SECSuccess) {
              printf("SSL_CipherPolicySet rejected suite 0x%04x (i = %d)\n",
                     suite, i);
              errWarn("SSL_CipherPolicySet");
              rv = SECFailure;
           }
       }
    }
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

SECStatus do_accepts ( PRFileDesc listen_sock,
PRFileDesc model_sock,
int  requestCert 
)

Definition at line 1219 of file selfserv.c.

{
    PRNetAddr   addr;
    PRErrorCode  perr;
#ifdef XP_UNIX
    struct sigaction act;
#endif

    VLOG(("selfserv: do_accepts: starting"));
    PR_SetThreadPriority( PR_GetCurrentThread(), PR_PRIORITY_HIGH);

    acceptorThread = PR_GetCurrentThread();
#ifdef XP_UNIX
    /* set up the signal handler */
    act.sa_handler = sigusr1_handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    if (sigaction(SIGUSR1, &act, NULL)) {
        fprintf(stderr, "Error installing signal handler.\n");
        exit(1);
    }
#endif
    while (!stopping) {
       PRFileDesc *tcp_sock;
       PRCList    *myLink;

       FPRINTF(stderr, "\n\n\nselfserv: About to call accept.\n");
       tcp_sock = PR_Accept(listen_sock, &addr, PR_INTERVAL_NO_TIMEOUT);
       if (tcp_sock == NULL) {
           perr      = PR_GetError();
           if ((perr != PR_CONNECT_RESET_ERROR &&
                perr != PR_PENDING_INTERRUPT_ERROR) || verbose) {
              errWarn("PR_Accept");
           } 
           if (perr == PR_CONNECT_RESET_ERROR) {
              FPRINTF(stderr, 
                      "Ignoring PR_CONNECT_RESET_ERROR error - continue\n");
              continue;
           }
           stopping = 1;
           break;
       }

        VLOG(("selfserv: do_accept: Got connection\n"));

        if (logStats) {
            loggerOps++;
        }

       PZ_Lock(qLock);
       while (PR_CLIST_IS_EMPTY(&freeJobs) && !stopping) {
            PZ_WaitCondVar(freeListNotEmptyCv, PR_INTERVAL_NO_TIMEOUT);
       }
       if (stopping) {
           PZ_Unlock(qLock);
            if (tcp_sock) {
               PR_Close(tcp_sock);
            }
           break;
       }
       myLink = PR_LIST_HEAD(&freeJobs);
       PR_REMOVE_AND_INIT_LINK(myLink);
       /* could release qLock here and reaquire it 7 lines below, but 
       ** why bother for 4 assignment statements? 
       */
       {
           JOB * myJob = (JOB *)myLink;
           myJob->tcp_sock    = tcp_sock;
           myJob->model_sock  = model_sock;
           myJob->requestCert = requestCert;
       }

       PR_APPEND_LINK(myLink, &jobQ);
       PZ_NotifyCondVar(jobQNotEmptyCv);
       PZ_Unlock(qLock);
    }

    FPRINTF(stderr, "selfserv: Closing listen socket.\n");
    VLOG(("selfserv: do_accepts: exiting"));
    if (listen_sock) {
        PR_Close(listen_sock);
    }
    return SECSuccess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void errExit ( char *  funcString) [static]

Definition at line 254 of file selfserv.c.

{
    errWarn(funcString);
    exit(3);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static const char* errWarn ( char *  funcString) [static]

Definition at line 243 of file selfserv.c.

{
    PRErrorCode  perr      = PR_GetError();
    const char * errString = SECU_Strerror(perr);

    fprintf(stderr, "selfserv: %s returned error %d:\n%s\n",
            funcString, perr, errString);
    return errString;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRFileDesc* getBoundListenSocket ( unsigned short  port)

Definition at line 1309 of file selfserv.c.

{
    PRFileDesc *       listen_sock;
    int                listenQueueDepth = 5 + (2 * maxThreads);
    PRStatus         prStatus;
    PRNetAddr          addr;
    PRSocketOptionData opt;

    addr.inet.family = PR_AF_INET;
    addr.inet.ip     = PR_INADDR_ANY;
    addr.inet.port   = PR_htons(port);

    listen_sock = PR_NewTCPSocket();
    if (listen_sock == NULL) {
       errExit("PR_NewTCPSocket");
    }

    opt.option = PR_SockOpt_Nonblocking;
    opt.value.non_blocking = PR_FALSE;
    prStatus = PR_SetSocketOption(listen_sock, &opt);
    if (prStatus < 0) {
       errExit("PR_SetSocketOption(PR_SockOpt_Nonblocking)");
    }

    opt.option=PR_SockOpt_Reuseaddr;
    opt.value.reuse_addr = PR_TRUE;
    prStatus = PR_SetSocketOption(listen_sock, &opt);
    if (prStatus < 0) {
       errExit("PR_SetSocketOption(PR_SockOpt_Reuseaddr)");
    }

#ifndef WIN95
    /* Set PR_SockOpt_Linger because it helps prevent a server bind issue
     * after clean shutdown . See bug 331413 .
     * Don't do it in the WIN95 build configuration because clean shutdown is
     * not implemented, and PR_SockOpt_Linger causes a hang in ssl.sh .
     * See bug 332348 */
    opt.option=PR_SockOpt_Linger;
    opt.value.linger.polarity = PR_TRUE;
    opt.value.linger.linger = PR_SecondsToInterval(1);
    prStatus = PR_SetSocketOption(listen_sock, &opt);
    if (prStatus < 0) {
        errExit("PR_SetSocketOption(PR_SockOpt_Linger)");
    }
#endif

    prStatus = PR_Bind(listen_sock, &addr);
    if (prStatus < 0) {
       errExit("PR_Bind");
    }

    prStatus = PR_Listen(listen_sock, listenQueueDepth);
    if (prStatus < 0) {
       errExit("PR_Listen");
    }
    return listen_sock;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int handle_connection ( PRFileDesc tcp_sock,
PRFileDesc model_sock,
int  requestCert 
) [static]

Definition at line 906 of file selfserv.c.

{
    PRFileDesc *       ssl_sock = NULL;
    PRFileDesc *       local_file_fd = 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                reqLen;
    int                rv;
    int                numIOVs;
    PRSocketOptionData opt;
    PRIOVec            iovs[16];
    char               msgBuf[160];
    char               buf[10240];
    char               fileName[513];
    char               proto[128];

    pBuf   = buf;
    bufRem = sizeof buf;

    VLOG(("selfserv: handle_connection: starting"));
    opt.option             = PR_SockOpt_Nonblocking;
    opt.value.non_blocking = PR_FALSE;
    PR_SetSocketOption(tcp_sock, &opt);

    VLOG(("selfserv: handle_connection: starting\n"));
    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;
    }

    if (noDelay) {
       opt.option         = PR_SockOpt_NoDelay;
       opt.value.no_delay = PR_TRUE;
       status = PR_SetSocketOption(ssl_sock, &opt);
       if (status != PR_SUCCESS) {
           errWarn("PR_SetSocketOption(PR_SockOpt_NoDelay, PR_TRUE)");
            if (ssl_sock) {
               PR_Close(ssl_sock);
            }
           return SECFailure;
       }
    }

    while (1) {
       newln = 0;
       reqLen     = 0;
       rv = PR_Read(ssl_sock, pBuf, bufRem - 1);
       if (rv == 0 || 
           (rv < 0 && PR_END_OF_FILE_ERROR == PR_GetError())) {
           if (verbose)
              errWarn("HDX PR_Read hit EOF");
           break;
       }
       if (rv < 0) {
           errWarn("HDX PR_Read");
           goto cleanup;
       }
       /* NULL termination */
       pBuf[rv] = 0;
       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 (reqLen < bufDat && newln < 2) {
           int octet = buf[reqLen++];
           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 (reqLen < bufDat && newln < 3) {
           int octet = buf[reqLen++];
           if (octet == '\n') {
              newln++;
           }
       }
       if (newln == 3)
           break;
    } /* read loop */

    bufDat = pBuf - buf;
    if (bufDat) do { /* just close if no data */
       /* Have either (a) a complete get, (b) a complete post, (c) EOF */
       if (reqLen > 0 && !strncmp(buf, getCmd, sizeof getCmd - 1)) {
           char *      fnBegin = buf + 4;
           char *      fnEnd;
           PRFileInfo  info;
           /* try to open the file named.  
            * If succesful, then write it to the client.
            */
           fnEnd = strpbrk(fnBegin, " \r\n");
           if (fnEnd) {
              int fnLen = fnEnd - fnBegin;
              if (fnLen < sizeof fileName) {
                    char *real_fileName = fileName;
                    char *protoEnd = NULL;
                    strncpy(fileName, fnBegin, fnLen);
                    fileName[fnLen] = 0;  /* null terminate */
                    if ((protoEnd = strstr(fileName, "://")) != NULL) {
                        int protoLen = PR_MIN(protoEnd - fileName, sizeof(proto) - 1);
                        PL_strncpy(proto, fileName, protoLen);
                        proto[protoLen] = 0;
                        real_fileName= protoEnd + 3;
                    } else {
                        proto[0] = 0;
                    }
                  status = PR_GetFileInfo(real_fileName, &info);
                  if (status == PR_SUCCESS &&
                     info.type == PR_FILE_FILE &&
                     info.size >= 0 ) {
                     local_file_fd = PR_Open(real_fileName, PR_RDONLY, 0);
                  }
              }
           }
       }
       /* 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_OptionSet(ssl_sock, SSL_REQUEST_CERTIFICATE, 1);
              if (rv < 0) {
                  errWarn("second SSL_OptionSet SSL_REQUEST_CERTIFICATE");
                  break;
              }
              rv = SSL_OptionSet(ssl_sock, SSL_REQUIRE_CERTIFICATE, 
                            (requestCert == 4));
              if (rv < 0) {
                  errWarn("second SSL_OptionSet SSL_REQUIRE_CERTIFICATE");
                  break;
              }
              rv = SSL_ReHandshake(ssl_sock, PR_TRUE);
              if (rv != 0) {
                  errWarn("SSL_ReHandshake");
                  break;
              }
              rv = SSL_ForceHandshake(ssl_sock);
              if (rv < 0) {
                  errWarn("SSL_ForceHandshake");
                  break;
              }
           }
       }

       numIOVs = 0;

       iovs[numIOVs].iov_base = (char *)outHeader;
       iovs[numIOVs].iov_len  = (sizeof(outHeader)) - 1;
       numIOVs++;

       if (local_file_fd) {
           PRInt32     bytes;
           int         errLen;
           if (!PL_strlen(proto) || !PL_strcmp(proto, "file")) {
                bytes = PR_TransmitFile(ssl_sock, local_file_fd, outHeader,
                                        sizeof outHeader - 1,
                                        PR_TRANSMITFILE_KEEP_OPEN,
                                        PR_INTERVAL_NO_TIMEOUT);
                if (bytes >= 0) {
                    bytes -= sizeof outHeader - 1;
                    FPRINTF(stderr, 
                            "selfserv: PR_TransmitFile wrote %d bytes from %s\n",
                            bytes, fileName);
                    break;
                }
                errString = errWarn("PR_TransmitFile");
                errLen = PORT_Strlen(errString);
                errLen = PR_MIN(errLen, sizeof msgBuf - 1);
                PORT_Memcpy(msgBuf, errString, errLen);
                msgBuf[errLen] = 0;
                
                iovs[numIOVs].iov_base = msgBuf;
                iovs[numIOVs].iov_len  = PORT_Strlen(msgBuf);
                numIOVs++;
            }
            if (!PL_strcmp(proto, "crl")) {
                if (reload_crl(local_file_fd) == SECFailure) {
                    errString = errWarn("CERT_CacheCRL");
                    if (!errString)
                        errString = "Unknow error";
                    PR_snprintf(msgBuf, sizeof(msgBuf), "%s%s ",
                                crlCacheErr, errString);
                    
                    iovs[numIOVs].iov_base = msgBuf;
                    iovs[numIOVs].iov_len  = PORT_Strlen(msgBuf);
                    numIOVs++;
                } else {
                    FPRINTF(stderr, 
                            "selfserv: CRL %s reloaded.\n",
                            fileName);
                    break;
                }
            }
       } else if (reqLen <= 0) {   /* hit eof */
           PORT_Sprintf(msgBuf, "Get or Post incomplete after %d bytes.\r\n",
                      bufDat);

           iovs[numIOVs].iov_base = msgBuf;
           iovs[numIOVs].iov_len  = PORT_Strlen(msgBuf);
           numIOVs++;
       } else if (reqLen < bufDat) {
           PORT_Sprintf(msgBuf, "Discarded %d characters.\r\n", 
                        bufDat - reqLen);

           iovs[numIOVs].iov_base = msgBuf;
           iovs[numIOVs].iov_len  = PORT_Strlen(msgBuf);
           numIOVs++;
       }

       if (reqLen > 0) {
           if (verbose > 1) 
              fwrite(buf, 1, reqLen, stdout);    /* display it */

           iovs[numIOVs].iov_base = buf;
           iovs[numIOVs].iov_len  = reqLen;
           numIOVs++;

/*         printSecurityInfo(ssl_sock); */
       }

       iovs[numIOVs].iov_base = (char *)EOFmsg;
       iovs[numIOVs].iov_len  = sizeof EOFmsg - 1;
       numIOVs++;

       rv = PR_Writev(ssl_sock, iovs, numIOVs, PR_INTERVAL_NO_TIMEOUT);
       if (rv < 0) {
           errWarn("PR_Writev");
           break;
       }
    } while (0);

cleanup:
    if (ssl_sock) {
        PR_Close(ssl_sock);
    } else if (tcp_sock) {
        PR_Close(tcp_sock);
    }
    if (local_file_fd)
       PR_Close(local_file_fd);
    VLOG(("selfserv: handle_connection: exiting\n"));

    /* do a nice shutdown if asked. */
    if (!strncmp(buf, stopCmd, sizeof stopCmd - 1)) {
        VLOG(("selfserv: handle_connection: stop command"));
        stop_server();
    }
    VLOG(("selfserv: handle_connection: exiting"));
    return SECSuccess;      /* success */
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRProcess* haveAChild ( int  argc,
char **  argv,
PRProcessAttr attr 
)

Definition at line 1560 of file selfserv.c.

{
    PRProcess *  newProcess;

    newProcess = PR_CreateProcess(argv[0], argv, NULL, attr);
    if (!newProcess) {
       errWarn("Can't create new process.");
    } else {
       child[numChildren++] = newProcess;
    }
    return newProcess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int jobLoop ( PRFileDesc a,
PRFileDesc b,
int  c 
)

Definition at line 498 of file selfserv.c.

{
    PRCList * myLink = 0;
    JOB     * myJob;

    PZ_Lock(qLock);
    do {
       myLink = 0;
       while (PR_CLIST_IS_EMPTY(&jobQ) && !stopping) {
            PZ_WaitCondVar(jobQNotEmptyCv, PR_INTERVAL_NO_TIMEOUT);
       }
       if (!PR_CLIST_IS_EMPTY(&jobQ)) {
           myLink = PR_LIST_HEAD(&jobQ);
           PR_REMOVE_AND_INIT_LINK(myLink);
       }
       PZ_Unlock(qLock);
       myJob = (JOB *)myLink;
       /* myJob will be null when stopping is true and jobQ is empty */
       if (!myJob) 
           break;
       handle_connection( myJob->tcp_sock, myJob->model_sock, 
                        myJob->requestCert);
       PZ_Lock(qLock);
       PR_APPEND_LINK(myLink, &freeJobs);
       PZ_NotifyCondVar(freeListNotEmptyCv);
    } while (PR_TRUE);
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

SECStatus launch_threads ( startFn startFunc,
PRFileDesc a,
PRFileDesc b,
int  c,
PRBool  local 
)

Definition at line 529 of file selfserv.c.

{
    int i;
    SECStatus rv = SECSuccess;

    /* create the thread management serialization structs */
    qLock               = PZ_NewLock(nssILockSelfServ);
    jobQNotEmptyCv      = PZ_NewCondVar(qLock);
    freeListNotEmptyCv  = PZ_NewCondVar(qLock);
    threadCountChangeCv = PZ_NewCondVar(qLock);

    /* create monitor for crl reload procedure */
    lastLoadedCrlLock   = PR_NewLock();

    /* allocate the array of thread slots */
    threads = PR_Calloc(maxThreads, sizeof(perThread));
    if ( NULL == threads )  {
        fprintf(stderr, "Oh Drat! Can't allocate the perThread array\n");
        return SECFailure;
    }
    /* 5 is a little extra, intended to keep the jobQ from underflowing. 
    ** That is, from going empty while not stopping and clients are still
    ** trying to contact us.
    */
    rv = setupJobs(maxThreads + 5);
    if (rv != SECSuccess)
       return rv;

    PZ_Lock(qLock);
    for (i = 0; i < maxThreads; ++i) {
       perThread * slot = threads + i;

       slot->state = rs_running;
       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_TRUE==local)?PR_LOCAL_THREAD:PR_GLOBAL_THREAD,
                        PR_UNJOINABLE_THREAD, 0);
       if (slot->prThread == NULL) {
           printf("selfserv: Failed to launch thread!\n");
           slot->state = rs_idle;
           rv = SECFailure;
           break;
       } 

       ++threadCount;
    }
    PZ_Unlock(qLock); 

    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void logger ( void arg) [static]

Definition at line 619 of file selfserv.c.

{
    PRFloat64 seconds;
    PRFloat64 opsPerSec;
    PRIntervalTime period;
    PRIntervalTime previousTime;
    PRIntervalTime latestTime;
    PRUint32 previousOps;
    PRUint32 ops;
    PRIntervalTime logPeriodTicks = PR_SecondsToInterval(logPeriod);
    PRFloat64 secondsPerTick = 1.0 / (PRFloat64)PR_TicksPerSecond();

    previousOps = loggerOps;
    previousTime = PR_IntervalNow();
 
    for (;;) {
       PR_Sleep(logPeriodTicks);
        latestTime = PR_IntervalNow();
        ops = loggerOps;
        period = latestTime - previousTime;
        seconds = (PRFloat64) period*secondsPerTick;
        opsPerSec = (ops - previousOps) / seconds;
        printf("%.2f ops/second, %d threads\n", opsPerSec, threadCount);
        fflush(stdout);
        previousOps = ops;
        previousTime = latestTime;
    }
}

Here is the call graph for this function:

int main ( int  argc,
char **  argv 
)

The Xalan testcases app.

Definition at line 1659 of file selfserv.c.

{
    char *               progName    = NULL;
    char *               nickName    = NULL;
#ifdef NSS_ENABLE_ECC
    char *               ecNickName   = NULL;
#endif
    char *               fNickName   = NULL;
    const char *         fileName    = NULL;
    char *               cipherString= NULL;
    const char *         dir         = ".";
    char *               passwd      = NULL;
    const char *         pidFile     = NULL;
    char *               tmp;
    char *               envString;
    PRFileDesc *         listen_sock;
    CERTCertificate *    cert   [kt_kea_size] = { NULL };
    SECKEYPrivateKey *   privKey[kt_kea_size] = { NULL };
    int                  optionsFound = 0;
    int                  maxProcs     = 1;
    unsigned short       port        = 0;
    SECStatus            rv;
    PRStatus             prStatus;
    PRBool               bindOnly = PR_FALSE;
    PRBool               useExportPolicy = PR_FALSE;
    PRBool               useLocalThreads = PR_FALSE;
    PLOptState              *optstate;
    PLOptStatus          status;
    PRThread             *loggerThread;
    PRBool               debugCache = PR_FALSE; /* bug 90518 */
    char                 emptyString[] = { "" };
    char*                certPrefix = emptyString;
    PRUint32         protos = 0;


    tmp = strrchr(argv[0], '/');
    tmp = tmp ? tmp + 1 : argv[0];
    progName = strrchr(tmp, '\\');
    progName = progName ? progName + 1 : tmp;

    PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);

    /* please keep this list of options in ASCII collating sequence.
    ** numbers, then capital letters, then lower case, alphabetical. 
    */
    optstate = PL_CreateOptState(argc, argv, 
        "2:3BC:DEL:M:NP:RSTbc:d:e:f:hi:lmn:op:qrst:vw:xy");
    while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
       ++optionsFound;
       switch(optstate->option) {
       case '2': fileName = optstate->value; break;

       case '3': disableSSL3 = PR_TRUE; break;

       case 'B': bypassPKCS11 = PR_TRUE; break;

        case 'C': if (optstate->value) NumSidCacheEntries = PORT_Atoi(optstate->value); break;

       case 'D': noDelay = PR_TRUE; break;
       case 'E': disableStepDown = PR_TRUE; break;

        case 'L':
            logStats = PR_TRUE;
           if (optstate->value == NULL) {
              logPeriod = 30;
           } else {
                logPeriod  = PORT_Atoi(optstate->value);
                if (logPeriod <= 0) logPeriod = 30;
           }
            break;

       case 'M': 
           maxProcs = PORT_Atoi(optstate->value); 
           if (maxProcs < 1)         maxProcs = 1;
           if (maxProcs > MAX_PROCS) maxProcs = MAX_PROCS;
           break;

       case 'N': NoReuse = PR_TRUE; break;

       case 'R': disableRollBack = PR_TRUE; break;
        
        case 'S': disableSSL2 = PR_TRUE; break;

       case 'T': disableTLS = PR_TRUE; break;

       case 'b': bindOnly = PR_TRUE; break;

       case 'c': cipherString = PORT_Strdup(optstate->value); break;

       case 'd': dir = optstate->value; break;

#ifdef NSS_ENABLE_ECC
       case 'e': ecNickName = PORT_Strdup(optstate->value); break;
#endif /* NSS_ENABLE_ECC */

       case 'f': fNickName = PORT_Strdup(optstate->value); break;

       case 'h': Usage(progName); exit(0); break;

       case 'i': pidFile = optstate->value; break;

        case 'l': useLocalThreads = PR_TRUE; break;

       case 'm': useModelSocket = PR_TRUE; break;

        case 'n': nickName = PORT_Strdup(optstate->value); break;

        case 'P': certPrefix = PORT_Strdup(optstate->value); break;

       case 'o': MakeCertOK = 1; break;

       case 'p': port = PORT_Atoi(optstate->value); break;

       case 'q': testbypass = PR_TRUE; break;

       case 'r': ++requestCert; break;

       case 's': disableLocking = PR_TRUE; break;

       case 't':
           maxThreads = PORT_Atoi(optstate->value);
           if ( maxThreads > MAX_THREADS ) maxThreads = MAX_THREADS;
           if ( maxThreads < MIN_THREADS ) maxThreads = MIN_THREADS;
           break;

       case 'v': verbose++; break;

       case 'w': passwd = PORT_Strdup(optstate->value); break;

       case 'x': useExportPolicy = PR_TRUE; break;

       case 'y': debugCache = PR_TRUE; break;

       default:
       case '?':
           fprintf(stderr, "Unrecognized or bad option specified.\n");
           fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
           exit(4);
           break;
       }
    }
    PL_DestroyOptState(optstate);
    if (status == PL_OPT_BAD) {
       fprintf(stderr, "Unrecognized or bad option specified.\n");
       fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
       exit(5);
    }
    if (!optionsFound) {
       Usage(progName);
       exit(51);
    } 

    /* The -b (bindOnly) option is only used by the ssl.sh test
     * script on Linux to determine whether a previous selfserv
     * process has fully died and freed the port.  (Bug 129701)
     */
    if (bindOnly) {
       listen_sock = getBoundListenSocket(port);
       if (!listen_sock) {
           exit(1);
       }
        if (listen_sock) {
            PR_Close(listen_sock);
        }
       exit(0);
    }

    if ((nickName == NULL) && (fNickName == NULL) 
#ifdef NSS_ENABLE_ECC
                                          && (ecNickName == NULL)
#endif
    ) {
       fprintf(stderr, "Required arg '-n' (rsa nickname) not supplied.\n");
       fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
        exit(6);
    }

    if (port == 0) {
       fprintf(stderr, "Required argument 'port' must be non-zero value\n");
       exit(7);
    }

    if (NoReuse && maxProcs > 1) {
       fprintf(stderr, "-M and -N options are mutually exclusive.\n");
       exit(14);
    }

    if (pidFile) {
       FILE *tmpfile=fopen(pidFile,"w+");

       if (tmpfile) {
           fprintf(tmpfile,"%d",getpid());
           fclose(tmpfile);
       }
    }

    envString = getenv(envVarName);
    tmp = getenv("TMP");
    if (!tmp)
       tmp = getenv("TMPDIR");
    if (!tmp)
       tmp = getenv("TEMP");
    if (envString) {
       /* we're one of the children in a multi-process server. */
       listen_sock = PR_GetInheritedFD(inheritableSockName);
       if (!listen_sock)
           errExit("PR_GetInheritedFD");
#ifndef WINNT
       /* we can't do this on NT because it breaks NSPR and
       PR_Accept will fail on the socket in the child process if
       the socket state is change to non inheritable
       It is however a security issue to leave it accessible,
       but it is OK for a test server such as selfserv.
       NSPR should fix it eventually . see bugzilla 101617
       and 102077
       */
       prStatus = PR_SetFDInheritable(listen_sock, PR_FALSE);
       if (prStatus != PR_SUCCESS)
           errExit("PR_SetFDInheritable");
#endif
#ifdef DEBUG_nelsonb
       WaitForDebugger();
#endif
       rv = SSL_InheritMPServerSIDCache(envString);
       if (rv != SECSuccess)
           errExit("SSL_InheritMPServerSIDCache");
       hasSidCache = PR_TRUE;
    } else if (maxProcs > 1) {
       /* we're going to be the parent in a multi-process server.  */
       listen_sock = getBoundListenSocket(port);
       rv = SSL_ConfigMPServerSIDCache(NumSidCacheEntries, 0, 0, tmp);
       if (rv != SECSuccess)
           errExit("SSL_ConfigMPServerSIDCache");
       hasSidCache = PR_TRUE;
       beAGoodParent(argc, argv, maxProcs, listen_sock);
       exit(99); /* should never get here */
    } else {
       /* we're an ordinary single process server. */
       listen_sock = getBoundListenSocket(port);
       prStatus = PR_SetFDInheritable(listen_sock, PR_FALSE);
       if (prStatus != PR_SUCCESS)
           errExit("PR_SetFDInheritable");
       if (!NoReuse) {
           rv = SSL_ConfigServerSessionIDCache(NumSidCacheEntries, 
                                               0, 0, tmp);
           if (rv != SECSuccess)
              errExit("SSL_ConfigServerSessionIDCache");
           hasSidCache = PR_TRUE;
       }
    }

    lm = PR_NewLogModule("TestCase");

    if (fileName)
       readBigFile(fileName);

    /* set our password function */
    PK11_SetPasswordFunc( passwd ? ownPasswd : SECU_GetModulePassword);

    /* Call the libsec initialization routines */
    rv = NSS_Initialize(dir, certPrefix, certPrefix, SECMOD_DB, NSS_INIT_READONLY);
    if (rv != SECSuccess) {
       fputs("NSS_Init failed.\n", stderr);
              exit(8);
    }

    /* set the policy bits true for all the cipher suites. */
    if (useExportPolicy) {
       NSS_SetExportPolicy();
       if (disableStepDown) {
           fputs("selfserv: -x and -E options may not be used together\n", 
                 stderr);
           exit(98);
       }
    } else {
       NSS_SetDomesticPolicy();
       if (disableStepDown) {
           rv = disableExportSSLCiphers();
           if (rv != SECSuccess) {
              errExit("error disabling export ciphersuites ");
           }
       }
    }

    /* all the SSL2 and SSL3 cipher suites are enabled by default. */
    if (cipherString) {
       char *cstringSaved = cipherString;
       int ndx;

       /* disable all the ciphers, then enable the ones we want. */
       disableAllSSLCiphers();

       while (0 != (ndx = *cipherString++)) {
           int  cipher;

           if (ndx == ':') {
              int ctmp;

              cipher = 0;
              HEXCHAR_TO_INT(*cipherString, ctmp)
              cipher |= (ctmp << 12);
              cipherString++;
              HEXCHAR_TO_INT(*cipherString, ctmp)
              cipher |= (ctmp << 8);
              cipherString++;
              HEXCHAR_TO_INT(*cipherString, ctmp)
              cipher |= (ctmp << 4);
              cipherString++;
              HEXCHAR_TO_INT(*cipherString, ctmp)
              cipher |= ctmp;
              cipherString++;
           } else {
              const int *cptr;

              if (! isalpha(ndx)) {
                  fprintf(stderr, 
                         "Non-alphabetic char in cipher string (-c arg).\n");
                  exit(9);
              }
              cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
              for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; ) 
                  /* do nothing */;
           }
           if (cipher > 0) {
              SECStatus status;
              status = SSL_CipherPrefSetDefault(cipher, SSL_ALLOWED);
              if (status != SECSuccess) 
                  SECU_PrintError(progName, "SSL_CipherPrefSet()");
           } else {
              fprintf(stderr, 
                     "Invalid cipher specification (-c arg).\n");
              exit(9);
           }
       }
       PORT_Free(cstringSaved);
    }

    if (testbypass) {
       const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
       int             i            = SSL_NumImplementedCiphers;
       PRBool        enabled;

       for (i=0; i < SSL_NumImplementedCiphers; i++, cipherSuites++) {
           if (SSL_CipherPrefGetDefault(*cipherSuites, &enabled) == SECSuccess
                                && enabled)
              savecipher(*cipherSuites);             
       }
       protos = (disableTLS ? 0 : SSL_CBP_TLS1_0) +
               (disableSSL3 ? 0 : SSL_CBP_SSL3);
    }
    
    if (nickName) {
       cert[kt_rsa] = PK11_FindCertFromNickname(nickName, passwd);
       if (cert[kt_rsa] == NULL) {
           fprintf(stderr, "selfserv: Can't find certificate %s\n", nickName);
           exit(10);
       }
       privKey[kt_rsa] = PK11_FindKeyByAnyCert(cert[kt_rsa], passwd);
       if (privKey[kt_rsa] == NULL) {
           fprintf(stderr, "selfserv: Can't find Private Key for cert %s\n", 
                   nickName);
           exit(11);
       }
       if (testbypass) {
           PRBool bypassOK;
           if (SSL_CanBypass(cert[kt_rsa], privKey[kt_rsa], protos, cipherlist, 
                             nciphers, &bypassOK, passwd) != SECSuccess) {
              SECU_PrintError(progName, "Bypass test failed %s\n", nickName);
              exit(14);
           }
           fprintf(stderr, "selfserv: %s can%s bypass\n", nickName,
                  bypassOK ? "" : "not");
       }
    }
    if (fNickName) {
       cert[kt_fortezza] = PK11_FindCertFromNickname(fNickName, NULL);
       if (cert[kt_fortezza] == NULL) {
           fprintf(stderr, "selfserv: Can't find certificate %s\n", fNickName);
           exit(12);
       }
       privKey[kt_fortezza] = PK11_FindKeyByAnyCert(cert[kt_fortezza], NULL);
    }
#ifdef NSS_ENABLE_ECC
    if (ecNickName) {
       cert[kt_ecdh] = PK11_FindCertFromNickname(ecNickName, passwd);
       if (cert[kt_ecdh] == NULL) {
           fprintf(stderr, "selfserv: Can't find certificate %s\n",
                  ecNickName);
           exit(13);
       }
       privKey[kt_ecdh] = PK11_FindKeyByAnyCert(cert[kt_ecdh], passwd);
       if (privKey[kt_ecdh] == NULL) {
           fprintf(stderr, "selfserv: Can't find Private Key for cert %s\n", 
                   ecNickName);
           exit(11);
       }          
       if (testbypass) {
           PRBool bypassOK;
           if (SSL_CanBypass(cert[kt_ecdh], privKey[kt_ecdh], protos, cipherlist,
                           nciphers, &bypassOK, passwd) != SECSuccess) {
              SECU_PrintError(progName, "Bypass test failed %s\n", ecNickName);
              exit(15);
           }
           fprintf(stderr, "selfserv: %s can%s bypass\n", ecNickName,
                  bypassOK ? "" : "not");
       }
    }
#endif /* NSS_ENABLE_ECC */

    if (testbypass)
       goto cleanup;

/* allocate the array of thread slots, and launch the worker threads. */
    rv = launch_threads(&jobLoop, 0, 0, requestCert, useLocalThreads);

    if (rv == SECSuccess && logStats) {
       loggerThread = PR_CreateThread(PR_SYSTEM_THREAD, 
                     logger, NULL, PR_PRIORITY_NORMAL, 
                        useLocalThreads ? PR_LOCAL_THREAD:PR_GLOBAL_THREAD,
                        PR_UNJOINABLE_THREAD, 0);
       if (loggerThread == NULL) {
           fprintf(stderr, "selfserv: Failed to launch logger thread!\n");
           rv = SECFailure;
       } 
    }

    if (rv == SECSuccess) {
       server_main(listen_sock, requestCert, privKey, cert);
    }

    VLOG(("selfserv: server_thread: exiting"));

cleanup:
    {
       int i;
       for (i=0; i<kt_kea_size; i++) {
           if (cert[i]) {
              CERT_DestroyCertificate(cert[i]);
           }
           if (privKey[i]) {
              SECKEY_DestroyPrivateKey(privKey[i]);
           }
       }
    }

    if (debugCache) {
       nss_DumpCertificateCacheInfo();
    }

    if (nickName) {
        PORT_Free(nickName);
    }
    if (passwd) {
        PORT_Free(passwd);
    }
    if (certPrefix && certPrefix != emptyString) {                            
        PORT_Free(certPrefix);
    }
    if (fNickName) {
        PORT_Free(fNickName);
    }
 #ifdef NSS_ENABLE_ECC
    if (ecNickName) {
        PORT_Free(ecNickName);
    }
 #endif

    if (hasSidCache) {
       SSL_ShutdownServerSessionIDCache();
    }
    if (NSS_Shutdown() != SECSuccess) {
       SECU_PrintError(progName, "NSS_Shutdown");
       PR_Cleanup();
       exit(1);
    }
    PR_Cleanup();
    printf("selfserv: normal termination\n");
    return 0;
}
static SECStatus myBadCertHandler ( void arg,
PRFileDesc fd 
) [static]

Definition at line 410 of file selfserv.c.

{
    int err = PR_GetError();
    if (!MakeCertOK)
       fprintf(stderr, 
           "selfserv: -- SSL: Client Certificate Invalid, err %d.\n%s\n", 
            err, SECU_Strerror(err));
    return (MakeCertOK ? SECSuccess : SECFailure);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus mySSLAuthCertificate ( void arg,
PRFileDesc fd,
PRBool  checkSig,
PRBool  isServer 
) [static]

Definition at line 329 of file selfserv.c.

{
    SECStatus rv;
    CERTCertificate *    peerCert;

    peerCert = SSL_PeerCertificate(fd);

    PRINTF("selfserv: Subject: %s\nselfserv: Issuer : %s\n",
           peerCert->subjectName, peerCert->issuerName);

    rv = SSL_AuthCertificate(arg, fd, checkSig, isServer);

    if (rv == SECSuccess) {
       PRINTF("selfserv: -- SSL3: Certificate Validated.\n");
    } else {
       int err = PR_GetError();
       FPRINTF(stderr, "selfserv: -- SSL3: Certificate Invalid, err %d.\n%s\n", 
                err, SECU_Strerror(err));
    }
    CERT_DestroyCertificate(peerCert);
    FLUSH;
    return rv;  
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* ownPasswd ( PK11SlotInfo *  info,
PRBool  retry,
void arg 
)

Definition at line 161 of file selfserv.c.

{
       char * passwd = NULL;

       if ( (!retry) && arg ) {
              passwd = PL_strdup((char *)arg);
       }

       return passwd;
}

Here is the caller graph for this function:

Definition at line 355 of file selfserv.c.

{
    CERTCertificate * cert      = NULL;
    SSL3Statistics *  ssl3stats = SSL_GetStatistics();
    SECStatus         result;
    SSLChannelInfo    channel;
    SSLCipherSuiteInfo suite;

    PRINTF(
       "selfserv: %ld cache hits; %ld cache misses, %ld cache not reusable\n",
       ssl3stats->hch_sid_cache_hits, ssl3stats->hch_sid_cache_misses,
       ssl3stats->hch_sid_cache_not_ok);

    result = SSL_GetChannelInfo(fd, &channel, sizeof channel);
    if (result == SECSuccess && 
        channel.length == sizeof channel && 
       channel.cipherSuite) {
       result = SSL_GetCipherSuiteInfo(channel.cipherSuite, 
                                   &suite, sizeof suite);
       if (result == SECSuccess) {
           FPRINTF(stderr, 
           "selfserv: SSL version %d.%d using %d-bit %s with %d-bit %s MAC\n",
              channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
              suite.effectiveKeyBits, suite.symCipherName, 
              suite.macBits, suite.macAlgorithmName);
           FPRINTF(stderr, 
           "selfserv: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n",
              channel.authKeyBits, suite.authAlgorithmName,
              channel.keaKeyBits,  suite.keaTypeName);
       }
    }
    if (requestCert)
       cert = SSL_PeerCertificate(fd);
    else
       cert = SSL_LocalCertificate(fd);
    if (cert) {
       char * ip = CERT_NameToAscii(&cert->issuer);
       char * sp = CERT_NameToAscii(&cert->subject);
        if (sp) {
           FPRINTF(stderr, "selfserv: subject DN: %s\n", sp);
           PORT_Free(sp);
       }
        if (ip) {
           FPRINTF(stderr, "selfserv: issuer  DN: %s\n", ip);
           PORT_Free(ip);
       }
       CERT_DestroyCertificate(cert);
       cert = NULL;
    }
    FLUSH;
}

Here is the caller graph for this function:

SECStatus readBigFile ( const char *  fileName)

Definition at line 1516 of file selfserv.c.

{
    PRFileInfo  info;
    PRStatus  status;
    SECStatus rv     = SECFailure;
    int              count;
    int              hdrLen;
    PRFileDesc *local_file_fd = NULL;

    status = PR_GetFileInfo(fileName, &info);

    if (status == PR_SUCCESS &&
       info.type == PR_FILE_FILE &&
       info.size > 0 &&
       NULL != (local_file_fd = PR_Open(fileName, PR_RDONLY, 0))) {

       hdrLen      = PORT_Strlen(outHeader);
       bigBuf.len  = hdrLen + info.size;
       bigBuf.data = PORT_Malloc(bigBuf.len + 4095);
       if (!bigBuf.data) {
           errWarn("PORT_Malloc");
           goto done;
       }

       PORT_Memcpy(bigBuf.data, outHeader, hdrLen);

       count = PR_Read(local_file_fd, bigBuf.data + hdrLen, info.size);
       if (count != info.size) {
           errWarn("PR_Read local file");
           goto done;
       }
       rv = SECSuccess;
done:
        if (local_file_fd) {
            PR_Close(local_file_fd);
        }
    }
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus reload_crl ( PRFileDesc crlFile) [static]

Definition at line 855 of file selfserv.c.

{
    SECItem *crlDer;
    CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
    SECStatus rv;

    /* Read in the entire file specified with the -f argument */
    crlDer = PORT_Malloc(sizeof(SECItem));
    if (!crlDer) {
        errWarn("Can not allocate memory.");
        return SECFailure;
    }

    rv = SECU_ReadDERFromFile(crlDer, crlFile, PR_FALSE);
    if (rv != SECSuccess) {
        errWarn("Unable to read input file.");
        PORT_Free(crlDer);
        return SECFailure;
    }

    PR_Lock(lastLoadedCrlLock);
    rv = CERT_CacheCRL(certHandle, crlDer);
    if (rv == SECSuccess) {
        SECItem *tempItem = crlDer;
        if (lastLoadedCrl != NULL) {
            rv = CERT_UncacheCRL(certHandle, lastLoadedCrl);
            if (rv != SECSuccess) {
                errWarn("Unable to uncache crl.");
                goto loser;
            }
            crlDer = lastLoadedCrl;
        } else {
            crlDer = NULL;
        }
        lastLoadedCrl = tempItem;
    }

  loser:
    PR_Unlock(lastLoadedCrlLock);
    SECITEM_FreeItem(crlDer, PR_TRUE);
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 681 of file selfserv.c.

{
    if (nciphers < sizeof cipherlist / sizeof (cipherlist[0]))
       cipherlist[nciphers++] = (PRUint16)c;
}

Here is the caller graph for this function:

void server_main ( PRFileDesc listen_sock,
int  requestCert,
SECKEYPrivateKey **  privKey,
CERTCertificate **  cert 
)

Definition at line 1368 of file selfserv.c.

{
    PRFileDesc *model_sock  = NULL;
    int         rv;
    SSLKEAType  kea;
    SECStatus secStatus;

    if (useModelSocket) {
       model_sock = PR_NewTCPSocket();
       if (model_sock == NULL) {
           errExit("PR_NewTCPSocket on model socket");
       }
       model_sock = SSL_ImportFD(NULL, model_sock);
       if (model_sock == NULL) {
           errExit("SSL_ImportFD");
       }
    } else {
       model_sock = listen_sock = SSL_ImportFD(NULL, listen_sock);
       if (listen_sock == NULL) {
           errExit("SSL_ImportFD");
       }
    }

    /* do SSL configuration. */
    /* all suites except RSA_NULL_MD5 are enabled by default */

#if 0
    /* This is supposed to be true by default.
    ** Setting it explicitly should not be necessary.
    ** Let's test and make sure that's true.
    */
    rv = SSL_OptionSet(model_sock, SSL_SECURITY, 1);
    if (rv < 0) {
       errExit("SSL_OptionSet SSL_SECURITY");
    }
#endif

    rv = SSL_OptionSet(model_sock, SSL_ENABLE_SSL3, !disableSSL3);
    if (rv != SECSuccess) {
       errExit("error enabling SSLv3 ");
    }

    rv = SSL_OptionSet(model_sock, SSL_ENABLE_TLS, !disableTLS);
    if (rv != SECSuccess) {
       errExit("error enabling TLS ");
    }

    rv = SSL_OptionSet(model_sock, SSL_ENABLE_SSL2, !disableSSL2);
    if (rv != SECSuccess) {
       errExit("error enabling SSLv2 ");
    }
    
    rv = SSL_OptionSet(model_sock, SSL_ROLLBACK_DETECTION, !disableRollBack);
    if (rv != SECSuccess) {
       errExit("error enabling RollBack detection ");
    }
    if (disableStepDown) {
       rv = SSL_OptionSet(model_sock, SSL_NO_STEP_DOWN, PR_TRUE);
       if (rv != SECSuccess) {
           errExit("error disabling SSL StepDown ");
       }
    }
    if (bypassPKCS11) {
       rv = SSL_OptionSet(model_sock, SSL_BYPASS_PKCS11, PR_TRUE);
       if (rv != SECSuccess) {
           errExit("error enabling PKCS11 bypass ");
       }
    }
    if (disableLocking) {
       rv = SSL_OptionSet(model_sock, SSL_NO_LOCKS, PR_TRUE);
       if (rv != SECSuccess) {
           errExit("error disabling SSL socket locking ");
       }
    } 

    for (kea = kt_rsa; kea < kt_kea_size; kea++) {
       if (cert[kea] != NULL) {
           secStatus = SSL_ConfigSecureServer(model_sock, 
                     cert[kea], privKey[kea], kea);
           if (secStatus != SECSuccess)
              errExit("SSL_ConfigSecureServer");
       }
    }

    if (bigBuf.data) { /* doing FDX */
       rv = SSL_OptionSet(model_sock, SSL_ENABLE_FDX, 1);
       if (rv < 0) {
           errExit("SSL_OptionSet SSL_ENABLE_FDX");
       }
    }

    if (NoReuse) {
        rv = SSL_OptionSet(model_sock, SSL_NO_CACHE, 1);
        if (rv < 0) {
            errExit("SSL_OptionSet SSL_NO_CACHE");
        }
    }

    /* 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 ) {
       errExit("SSL_CipherPrefSetDefault:SSL_RSA_WITH_NULL_MD5");
    }


    if (requestCert) {
       SSL_AuthCertificateHook(model_sock, mySSLAuthCertificate, 
                               (void *)CERT_GetDefaultCertDB());
       if (requestCert <= 2) { 
           rv = SSL_OptionSet(model_sock, SSL_REQUEST_CERTIFICATE, 1);
           if (rv < 0) {
              errExit("first SSL_OptionSet SSL_REQUEST_CERTIFICATE");
           }
           rv = SSL_OptionSet(model_sock, SSL_REQUIRE_CERTIFICATE, 
                           (requestCert == 2));
           if (rv < 0) {
              errExit("first SSL_OptionSet SSL_REQUIRE_CERTIFICATE");
           }
       }
    }

    if (MakeCertOK)
       SSL_BadCertHook(model_sock, myBadCertHandler, NULL);

    /* end of ssl configuration. */


    /* Now, do the accepting, here in the main thread. */
    rv = do_accepts(listen_sock, model_sock, requestCert);

    terminateWorkerThreads();

    if (useModelSocket && model_sock) {
        if (model_sock) {
            PR_Close(model_sock);
        }
    }

}

Here is the call graph for this function:

Here is the caller graph for this function:

SECStatus setupJobs ( int  maxJobs)

Definition at line 448 of file selfserv.c.

{
    int i;

    jobTable = (JOB *)PR_Calloc(maxJobs, sizeof(JOB));
    if (!jobTable)
       return SECFailure;

    PR_INIT_CLIST(&jobQ);
    PR_INIT_CLIST(&freeJobs);

    for (i = 0; i < maxJobs; ++i) {
       JOB * pJob = jobTable + i;
       PR_APPEND_LINK(&pJob->link, &freeJobs);
    }
    return SECSuccess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 898 of file selfserv.c.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 596 of file selfserv.c.

Here is the call graph for this function:

Here is the caller graph for this function:

void thread_wrapper ( void arg)

Definition at line 483 of file selfserv.c.

{
    perThread * slot = (perThread *)arg;

    slot->rv = (* slot->startFunc)(slot->a, slot->b, slot->c);

    /* notify the thread exit handler. */
    PZ_Lock(qLock);
    slot->state = rs_zombie;
    --threadCount;
    PZ_NotifyAllCondVar(threadCountChangeCv);
    PZ_Unlock(qLock);
}

Here is the caller graph for this function:

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

Definition at line 178 of file selfserv.c.

{
    fprintf(stderr, 

"Usage: %s -n rsa_nickname -p port [-3BDENRSTblmrsvx] [-w password] [-t threads]\n"
#ifdef NSS_ENABLE_ECC
"         [-i pid_file] [-c ciphers] [-d dbdir] [-e ec_nickname] \n"
"         [-f fortezza_nickname] [-L [seconds]] [-M maxProcs] [-P dbprefix]\n"
#else
"         [-i pid_file] [-c ciphers] [-d dbdir] [-f fortezza_nickname] \n"
"         [-L [seconds]] [-M maxProcs] [-P dbprefix] [-C SSLCacheEntries]\n"
#endif /* NSS_ENABLE_ECC */
"-S means disable SSL v2\n"
"-3 means disable SSL v3\n"
"-B bypasses the PKCS11 layer for SSL encryption and MACing\n"
"-q checks for bypassability\n"
"-D means disable Nagle delays in TCP\n"
"-E means disable export ciphersuites and SSL step down key gen\n"
"-T means disable TLS\n"
"-R means disable detection of rollback from TLS to SSL3\n"
"-b means try binding to the port and exit\n"
"-m means test the model-socket feature of SSL_ImportFD.\n"
"-r flag is interepreted as follows:\n"
"    1 -r  means request, not require, cert on initial handshake.\n"
"    2 -r's mean request  and require, cert on initial handshake.\n"
"    3 -r's mean request, not require, cert on second handshake.\n"
"    4 -r's mean request  and require, cert on second handshake.\n"
"-s means disable SSL socket locking for performance\n"
"-v means verbose output\n"
"-x means use export policy.\n"
"-L seconds means log statistics every 'seconds' seconds (default=30).\n"
"-M maxProcs tells how many processes to run in a multi-process server\n"
"-N means do NOT use the server session cache.  Incompatible with -M.\n"
"-t threads -- specify the number of threads to use for connections.\n"
"-i pid_file file to write the process id of selfserve\n"
"-l means use local threads instead of global threads\n"
"-C SSLCacheEntries sets the maximum number of entries in the SSL session cache\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"
"n    SSL3 RSA WITH RC4 128 SHA\n"
"v    SSL3 RSA WITH AES 128 CBC SHA\n"
"y    SSL3 RSA WITH AES 256 CBC SHA\n"
"z    SSL3 RSA WITH NULL SHA\n"
"\n"
":WXYZ  Use cipher with hex code { 0xWX , 0xYZ } in TLS\n"
       ,progName);
}

Here is the call graph for this function:


Variable Documentation

Definition at line 152 of file selfserv.c.

SECItem bigBuf [static]

Definition at line 150 of file selfserv.c.

Definition at line 661 of file selfserv.c.

Definition at line 1557 of file selfserv.c.

Definition at line 677 of file selfserv.c.

const char crlCacheErr[] = { "CRL ReCache Error: " } [static]

Definition at line 675 of file selfserv.c.

Definition at line 662 of file selfserv.c.

Definition at line 657 of file selfserv.c.

Definition at line 654 of file selfserv.c.

Definition at line 655 of file selfserv.c.

Definition at line 660 of file selfserv.c.

Definition at line 656 of file selfserv.c.

const char envVarName[] = { SSL_ENV_VAR_NAME } [static]

Definition at line 97 of file selfserv.c.

const char EOFmsg[] = { "EOF\r\n\r\n\r\n" } [static]

Definition at line 667 of file selfserv.c.

PRCList freeJobs [static]

Definition at line 444 of file selfserv.c.

Definition at line 440 of file selfserv.c.

const char getCmd[] = { "GET " } [static]

Definition at line 666 of file selfserv.c.

Definition at line 659 of file selfserv.c.

const char inheritableSockName[] = { "SELFSERV_LISTEN_SOCKET" } [static]

Definition at line 98 of file selfserv.c.

PRCList jobQ [static]

Definition at line 443 of file selfserv.c.

Definition at line 439 of file selfserv.c.

JOB* jobTable [static]

Definition at line 445 of file selfserv.c.

SECItem* lastLoadedCrl = NULL [static]

Definition at line 852 of file selfserv.c.

Definition at line 438 of file selfserv.c.

PRLogModuleInfo* lm [static]

Definition at line 154 of file selfserv.c.

PRUint32 loggerOps = 0 [static]

Definition at line 102 of file selfserv.c.

int logPeriod = 30 [static]

Definition at line 101 of file selfserv.c.

PRBool logStats = PR_FALSE [static]

Definition at line 100 of file selfserv.c.

int MakeCertOK [static]

Definition at line 407 of file selfserv.c.

Definition at line 427 of file selfserv.c.

Definition at line 678 of file selfserv.c.

PRBool noDelay [static]

Definition at line 147 of file selfserv.c.

Definition at line 658 of file selfserv.c.

Definition at line 1556 of file selfserv.c.

Definition at line 93 of file selfserv.c.

const char outHeader[] [static]
Initial value:
 {
    "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"
}

Definition at line 668 of file selfserv.c.

PZLock* qLock [static]

Definition at line 437 of file selfserv.c.

int requestCert [static]

Definition at line 148 of file selfserv.c.

const char stopCmd[] = { "GET /stop " } [static]

Definition at line 665 of file selfserv.c.

int stopping [static]

Definition at line 145 of file selfserv.c.

Definition at line 663 of file selfserv.c.

int threadCount [static]

Definition at line 442 of file selfserv.c.

Definition at line 441 of file selfserv.c.

perThread* threads [static]

Definition at line 480 of file selfserv.c.

Definition at line 653 of file selfserv.c.

int verbose [static]

Definition at line 149 of file selfserv.c.