main.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:18k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /*
  3.  * The contents of this file are subject to the Mozilla Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/MPL/
  7.  * 
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  * 
  13.  * The Original Code is the Netscape security libraries.
  14.  * 
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation.  Portions created by Netscape are 
  17.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  18.  * Rights Reserved.
  19.  * 
  20.  * Contributor(s):
  21.  * 
  22.  * Alternatively, the contents of this file may be used under the
  23.  * terms of the GNU General Public License Version 2 or later (the
  24.  * "GPL"), in which case the provisions of the GPL are applicable 
  25.  * instead of those above.  If you wish to allow use of your 
  26.  * version of this file only under the terms of the GPL and not to
  27.  * allow others to use your version of this file under the MPL,
  28.  * indicate your decision by deleting the provisions above and
  29.  * replace them with the notice and other provisions required by
  30.  * the GPL.  If you do not delete the provisions above, a recipient
  31.  * may use your version of this file under either the MPL or the
  32.  * GPL.
  33.  */
  34. #include "serv.h"
  35. #include "secport.h"
  36. #include "dataconn.h"
  37. #include "ctrlconn.h"
  38. #include "minihttp.h"
  39. #include "ciferfam.h"
  40. #include "secmime.h"
  41. #include "messages.h"
  42. #include "textgen.h"
  43. #include "oldfunc.h"
  44. #include "nss.h"
  45. #include "p12plcy.h"
  46. #include "nlslayer.h"
  47. #include "softoken.h"
  48. void SSM_InitLogging(void);
  49. #ifdef TIMEBOMB
  50. #include "timebomb.h"
  51. #endif
  52. #ifdef WIN32
  53. #include <wtypes.h>
  54. #include <winreg.h>
  55. #include <winerror.h>
  56. #endif
  57. #ifdef XP_UNIX
  58. #include <signal.h>
  59. #include <unistd.h>
  60. #ifndef SIG_ERR
  61. #define SIG_ERR -1
  62. #endif /*SIG_ERR*/
  63. #endif /*XP_UNIX*/
  64. #define POLICY_TYPE_INDEX 0
  65. SSMCollection * connections       = NULL;
  66. SSMHashTable  * tokenList         = NULL;
  67. PRMonitor     * tokenLock         = NULL;
  68. SSMHashTable  * ctrlConnections   = NULL;
  69. SSMPolicyType   policyType        = ssmDomestic;
  70. /*
  71.  * The following is a quick write of enabling various ciphers.  This code is
  72.  * essentially moved from the server core code.  Eventually we will need to
  73.  * place this data and functionality in a more modular way.
  74.  */
  75. #define SSM_POLICY_END 0 /* end of table */
  76. #define SSM_POLICY_SSL 1 /* SSL ciphersuites: not really used */
  77. #define SSM_POLICY_PK12 2 /* PKCS #12 ciphersuites */
  78. #define SSM_POLICY_SMIME 3 /* S/MIME ciphersuites */
  79. typedef struct {
  80.     PRInt32 policy;
  81.     PRInt32 key;
  82.     PRInt32 value;
  83. } SSMPolicyEntry;
  84. static SSMPolicyEntry ssmPK12PolicyTable[] =
  85. {
  86.     {SSM_POLICY_PK12, PKCS12_RC4_40,       (PRInt32)PR_TRUE},
  87.     {SSM_POLICY_PK12, PKCS12_RC4_128,      (PRInt32)PR_TRUE},
  88.     {SSM_POLICY_PK12, PKCS12_RC2_CBC_40,   (PRInt32)PR_TRUE},
  89.     {SSM_POLICY_PK12, PKCS12_RC2_CBC_128,  (PRInt32)PR_TRUE},
  90.     {SSM_POLICY_PK12, PKCS12_DES_56,       (PRInt32)PR_TRUE},
  91.     {SSM_POLICY_PK12, PKCS12_DES_EDE3_168, (PRInt32)PR_TRUE},
  92.     {SSM_POLICY_END, 0, 0}
  93. };
  94. static SSMPolicyEntry ssmSMIMEPolicyTable[] =
  95. {
  96.     {SSM_POLICY_SMIME, SMIME_RC2_CBC_40,       (PRInt32)PR_TRUE},
  97.     {SSM_POLICY_SMIME, SMIME_RC2_CBC_64,       (PRInt32)PR_TRUE},
  98.     {SSM_POLICY_SMIME, SMIME_RC2_CBC_128,      (PRInt32)PR_TRUE},
  99.     {SSM_POLICY_SMIME, SMIME_DES_CBC_56,       (PRInt32)PR_TRUE},
  100.     {SSM_POLICY_SMIME, SMIME_DES_EDE3_168,     (PRInt32)PR_TRUE},
  101.     {SSM_POLICY_SMIME, SMIME_RC5PAD_64_16_40,  (PRInt32)PR_TRUE},
  102.     {SSM_POLICY_SMIME, SMIME_RC5PAD_64_16_64,  (PRInt32)PR_TRUE},
  103.     {SSM_POLICY_SMIME, SMIME_RC5PAD_64_16_128, (PRInt32)PR_TRUE},
  104.     {SSM_POLICY_END, 0, 0}
  105. };
  106. static SSMStatus SSM_InstallPK12Policy(void)
  107. {
  108.     const SSMPolicyEntry* entry = ssmPK12PolicyTable;
  109.     int i;
  110.     for (i = 0; entry[i].policy != SSM_POLICY_END; i++) {
  111.         if (SEC_PKCS12EnableCipher(entry[i].key, entry[i].value) != 
  112.             SECSuccess) {
  113.             return SSM_FAILURE;
  114.         }
  115.     }
  116.     return SSM_SUCCESS;
  117. }
  118. static SSMStatus SSM_InstallSMIMEPolicy(void)
  119. {
  120.     const SSMPolicyEntry* entry = ssmSMIMEPolicyTable;
  121.     int i;
  122.     
  123.     for (i = 0; entry[i].policy != SSM_POLICY_END; i++) {
  124.         if (SECMIME_SetPolicy(entry[i].key, entry[i].value) != SECSuccess) {
  125.             return SSM_FAILURE;
  126.         }
  127.     }
  128.     return SSM_SUCCESS;
  129. }
  130. /* XXX sjlee: we don't need to do a similar thing for SSL as we can call an
  131.  *     NSS function to do it
  132.  */
  133. #if 0
  134. /*
  135.  * This function is required by svrplcy to set the
  136.  * utility policy.  This will tell us what kind of 
  137.  * policy we are running.
  138.  */
  139. SECStatus Utility_SetPolicy(long which, int policy)
  140. {
  141.     policyType = ssmDomestic;
  142.     return SECSuccess;
  143. }
  144. #endif
  145. void SSM_SetPolicy(void)
  146. {
  147. #if 0
  148.     SVRPLCY_InstallSSLPolicy();
  149.     SVRPLCY_InstallPK12Policy();
  150.     SVRPLCY_InstallSMIMEPolicy();
  151.     SVRPLCY_InstallUtilityPolicy();
  152. #else
  153. /* Always domestic policy now */
  154. NSS_SetDomesticPolicy();
  155.     SSM_InstallPK12Policy();
  156.     SSM_InstallSMIMEPolicy();
  157. #endif
  158. }
  159. SSMPolicyType
  160. SSM_GetPolicy(void)
  161. {
  162.     return policyType;
  163. }
  164. static void
  165. enable_SMIME_cipher_prefs(void)
  166. {
  167.     SSMPolicyType policy;
  168.     policy = SSM_GetPolicy();
  169.     switch (policy)
  170.     {
  171.     case ssmDomestic:
  172.         SECMIME_EnableCipher(SMIME_DES_EDE3_168, 1);
  173.         SECMIME_EnableCipher(SMIME_RC2_CBC_128, 1);
  174.         SECMIME_EnableCipher(SMIME_RC2_CBC_64, 1);
  175.         SECMIME_EnableCipher(SMIME_DES_CBC_56, 1);
  176. #if 0
  177.         SECMIME_EnableCipher(SMIME_RC5PAD_64_16_128, 1);
  178.         SECMIME_EnableCipher(SMIME_RC5PAD_64_16_64, 1);
  179.         SECMIME_EnableCipher(SMIME_FORTEZZA, 1);
  180. #endif
  181.     case ssmExport:
  182.         SECMIME_EnableCipher(SMIME_RC2_CBC_40, 1);
  183. #if 0
  184.         SECMIME_EnableCipher(SMIME_RC5PAD_64_16_40, 1);
  185. #endif
  186.     case ssmFrance:
  187.     default:
  188.         break;
  189.     }
  190.     /* now tell secmime that we've sent it the last preference */
  191.     SECMIME_EnableCipher(CIPHER_FAMILYID_MASK, 0);
  192. }
  193. #define SHORT_PK11_STRING 33
  194. #define LONG_PK11_STRING  65
  195. static char*
  196. ssm_ConverToLength(char *origString, PRUint32 newLen)
  197. {
  198.     char *newString;
  199.     PRUint32 origLen;
  200.     PRUint32 copyLen;
  201.     newString = SSM_NEW_ARRAY(char,newLen+1);
  202.     if (newString == NULL) {
  203.         return origString;
  204.     }
  205.     origLen = PL_strlen(origString);
  206.     copyLen = (origLen > newLen) ? newLen : origLen;
  207.     memcpy(newString, origString, copyLen);
  208.     memset(newString+copyLen, ' ' ,newLen - copyLen);
  209.     newString[newLen]='';
  210.     PR_Free(origString);
  211.     return newString;
  212. }
  213. SECStatus
  214. ssm_InitializePKCS11Strings(void)
  215. {
  216.     char *manufacturerID             = NULL;
  217.     char *libraryDescription         = NULL;
  218.     char *tokenDescription           = NULL;
  219.     char *privateTokenDescription    = NULL;
  220.     char *slotDescription            = NULL;
  221.     char *privateSlotDescription     = NULL;
  222.     char *fipsSlotDescription        = NULL;
  223.     char *fipsPrivateSlotDescription = NULL; 
  224.     SSMTextGenContext *cx;
  225.     SSMStatus rv;
  226.     rv = SSMTextGen_NewTopLevelContext(NULL, &cx);
  227.     if (rv != SSM_SUCCESS) {
  228.         goto loser;
  229.     }
  230.     rv = SSM_FindUTF8StringInBundles(cx, "manufacturerID", &manufacturerID);
  231.     if (rv != SSM_SUCCESS) {
  232.         goto loser;
  233.     }
  234.     if (PL_strlen(manufacturerID) != SHORT_PK11_STRING) {
  235.         manufacturerID = ssm_ConverToLength(manufacturerID, SHORT_PK11_STRING);
  236.     }
  237.     rv = SSM_FindUTF8StringInBundles(cx, "libraryDescription", 
  238.                                      &libraryDescription);
  239.     if (rv != SSM_SUCCESS) {
  240.         goto loser;
  241.     }
  242.     if (PL_strlen(libraryDescription) != SHORT_PK11_STRING) {
  243.         libraryDescription = ssm_ConverToLength(libraryDescription, 
  244.                                                 SHORT_PK11_STRING);
  245.     }
  246.     rv = SSM_FindUTF8StringInBundles(cx, "tokenDescription", 
  247.                                      &tokenDescription);
  248.     if (rv != SSM_SUCCESS) {
  249.         goto loser;
  250.     }
  251.     if (PL_strlen(tokenDescription) != SHORT_PK11_STRING) {
  252.         tokenDescription = ssm_ConverToLength(tokenDescription, 
  253.                                               SHORT_PK11_STRING);
  254.     }
  255.     rv = SSM_FindUTF8StringInBundles(cx, "privateTokenDescription",
  256.                                      &privateTokenDescription);
  257.     if (rv != SSM_SUCCESS) {
  258.         goto loser;
  259.     }
  260.     if (PL_strlen(privateTokenDescription) != SHORT_PK11_STRING) {
  261.         privateTokenDescription = ssm_ConverToLength(privateTokenDescription,
  262.                                                      SHORT_PK11_STRING);
  263.     }
  264.     rv = SSM_FindUTF8StringInBundles(cx, "slotDescription", &slotDescription);
  265.     if (rv != SSM_SUCCESS) {
  266.         goto loser;
  267.     }
  268.     if (PL_strlen(slotDescription) != LONG_PK11_STRING) {
  269.         slotDescription = ssm_ConverToLength(slotDescription,
  270.                                              LONG_PK11_STRING);
  271.     }
  272.     rv = SSM_FindUTF8StringInBundles(cx, "privateSlotDescription",
  273.                                      &privateSlotDescription);
  274.     if (rv != SSM_SUCCESS) {
  275.         goto loser;
  276.     }
  277.     if (PL_strlen(privateSlotDescription) != LONG_PK11_STRING) {
  278.         privateSlotDescription = ssm_ConverToLength(privateSlotDescription,
  279.                                                     LONG_PK11_STRING);
  280.     }
  281.     rv = SSM_FindUTF8StringInBundles(cx, "fipsSlotDescription",
  282.                                      &fipsSlotDescription);
  283.     if (rv != SSM_SUCCESS) {
  284.         goto loser;
  285.     }
  286.     if (PL_strlen(fipsSlotDescription) != LONG_PK11_STRING) {
  287.         fipsSlotDescription = ssm_ConverToLength(fipsSlotDescription,
  288.                                                  LONG_PK11_STRING);
  289.     }
  290.     rv = SSM_FindUTF8StringInBundles(cx, "fipsPrivateSlotDescription",
  291.                                      &fipsPrivateSlotDescription);
  292.     if (rv != SSM_SUCCESS) {
  293.         goto loser;
  294.     }
  295.     if (PL_strlen(fipsPrivateSlotDescription) != LONG_PK11_STRING) {
  296.         fipsPrivateSlotDescription = 
  297.             ssm_ConverToLength(fipsPrivateSlotDescription, LONG_PK11_STRING);
  298.     }
  299.     if (cx != NULL) {
  300.         SSMTextGen_DestroyContext(cx);
  301.     }
  302.     PK11_ConfigurePKCS11(manufacturerID, libraryDescription, tokenDescription,
  303.                          privateTokenDescription, slotDescription, 
  304.                          privateSlotDescription, fipsSlotDescription, 
  305.                          fipsPrivateSlotDescription, 0, 0);
  306.     return SECSuccess;
  307.  loser:
  308.     PR_FREEIF(manufacturerID);
  309.     PR_FREEIF(libraryDescription);
  310.     PR_FREEIF(tokenDescription);
  311.     PR_FREEIF(privateTokenDescription);
  312.     PR_FREEIF(slotDescription);
  313.     PR_FREEIF(privateSlotDescription);
  314.     if (cx != NULL) {
  315.         SSMTextGen_DestroyContext(cx);
  316.     }
  317.     return SECFailure;
  318. }
  319. #ifdef XP_UNIX
  320. #define CATCH_SIGNAL_DEFAULT(SIGNAL) 
  321.     if (((int)signal(SIGNAL, psm_signal_handler_default)) == ((int)SIG_ERR)) 
  322.         goto loser;
  323. #define CATCH_SIGNAL_IGNORE(SIGNAL) 
  324.     if (((int)signal(SIGNAL, psm_signal_handler_ignore)) == ((int)SIG_ERR)) 
  325.         goto loser;
  326. static void
  327. psm_signal_handler_default(int sig)
  328. {
  329. #ifdef DEBUG
  330.   printf ("Trapping the signal %dn", sig);
  331. #endif
  332.   SSM_ReleaseLockFile();
  333.   kill(getpid(),SIGKILL);
  334. }
  335. static void
  336. psm_signal_handler_ignore(int sig)
  337. {
  338. #ifdef DEBUG
  339.   printf ("Ignoring the signal %dn", sig);
  340. #endif
  341.   signal(sig,psm_signal_handler_ignore);
  342. }
  343. static SSMStatus
  344. psm_catch_signals(void)
  345. {
  346.   CATCH_SIGNAL_IGNORE(SIGHUP);
  347.   CATCH_SIGNAL_DEFAULT(SIGINT);
  348.   CATCH_SIGNAL_DEFAULT(SIGQUIT);
  349.   CATCH_SIGNAL_DEFAULT(SIGILL);
  350.   CATCH_SIGNAL_DEFAULT(SIGTRAP);
  351.   CATCH_SIGNAL_DEFAULT(SIGABRT);
  352.   CATCH_SIGNAL_DEFAULT(SIGIOT);
  353. #ifdef SIGEMT
  354.   CATCH_SIGNAL_DEFAULT(SIGEMT);
  355. #endif
  356.   CATCH_SIGNAL_DEFAULT(SIGFPE);
  357.   CATCH_SIGNAL_DEFAULT(SIGBUS);
  358.   CATCH_SIGNAL_DEFAULT(SIGSEGV);
  359. #ifdef SIGSYS
  360.   CATCH_SIGNAL_DEFAULT(SIGSYS);
  361. #endif
  362.   CATCH_SIGNAL_IGNORE(SIGPIPE);
  363.   CATCH_SIGNAL_DEFAULT(SIGTERM);
  364. #ifndef LINUX
  365.   CATCH_SIGNAL_DEFAULT(SIGUSR1);
  366. #endif
  367.   CATCH_SIGNAL_DEFAULT(SIGUSR2);
  368. #ifdef SIGXCPU
  369.   CATCH_SIGNAL_DEFAULT(SIGXCPU);
  370. #endif
  371. #ifdef SIGDANGER
  372.   CATCH_SIGNAL_DEFAULT(SIGDANGER);
  373. #endif
  374.   return SSM_SUCCESS;
  375.  loser:
  376.   return SSM_FAILURE;
  377. }
  378. #endif
  379. #if defined(XP_PC) && !defined(DEBUG)
  380. int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
  381.                    LPSTR lpszLine, int nShow)
  382. #elif defined(XP_MAC)
  383. /*
  384. We run RunMacPSM in a separate thread off the main thread. 
  385. This is because we can't do any blocking I/O routines on the main
  386. thread, because Mac NSPR doesn't own the original thread used to
  387. run the app.
  388. */
  389. static void* glue_component = NULL;
  390. void RunMacPSM(void *arg)
  391. #else
  392. int main(int argc, char ** argv)
  393. #endif
  394. {
  395. #if (defined(XP_PC) && !defined(DEBUG)) || (defined(XP_MAC))
  396.     /* substitute argc and argv for NSPR */
  397.     int argc = 0;
  398.     char *argv[] = {"", NULL};
  399. #endif
  400.     PRIntn result = 0;
  401. #ifdef XP_MAC
  402.     glue_component = arg;
  403. #endif
  404. #ifdef DEBUG
  405.     PR_STDIO_INIT();
  406. #endif
  407. #ifdef DEBUG
  408.     /* Initialize logging. */
  409.     SSM_InitLogging();
  410. #endif
  411. #ifdef TIMEBOMB
  412.     SSM_CheckTimebomb();
  413. #endif
  414. #ifdef XP_UNIX
  415.     if (psm_catch_signals() != SSM_SUCCESS) {
  416.       SSM_DEBUG("Couldn't set signal handlers.  Quittingn");
  417.       exit(1);
  418.     }
  419. #endif
  420.     SSM_SetPolicy();
  421.     enable_SMIME_cipher_prefs();
  422.     if (SSM_GetPolicy() == ssmDomestic) {
  423.       SSM_EnableHighGradeKeyGen();
  424.     }
  425. /* Initialize NLS layer */
  426. if (nlsInit() != PR_TRUE) {
  427. SSM_DEBUG("Failed to initialize the NLS layern");
  428. exit(1);
  429. }
  430.     /* Initialize global list of control connections. */
  431.     connections = SSM_NewCollection();
  432.     if (connections == NULL)
  433.     {
  434.         SSM_DEBUG("Can't initialize! (%ld)n", (long) result);
  435.         exit(1);
  436.     }
  437.     /* Initialize global list of tokens */
  438.     result = SSM_HashCreate(&tokenList);
  439.     if (result != PR_SUCCESS || !tokenList) {
  440.        SSM_DEBUG("Can't initialize - tokenList n");
  441.        exit(result);
  442.     }
  443.     tokenLock = PR_NewMonitor();
  444.     if (!tokenLock) {
  445.         SSM_DEBUG("Can't initialize - tokenLockn");
  446. exit(1);
  447.     }
  448.     /* Initialize hash table of control connections */
  449.     result = SSM_HashCreate(&ctrlConnections);
  450.     if (result != PR_SUCCESS || !ctrlConnections) {
  451.         SSM_DEBUG("Can't initialize global table for control connections n");
  452.         exit(result);
  453.     }
  454.     /* Initialize resource table */
  455.     SSM_ResourceInit();
  456.     if (SSM_InitPolicyHandler() != PR_SUCCESS) {
  457.         SSM_DEBUG("Couldn't initialize the Policy Handler.n");
  458.         exit (1);
  459.     }
  460.     /* initialize random number generator */
  461.     SSM_DEBUG("Initializing random number generator.n");
  462.     RNG_RNGInit();
  463.     RNG_SystemInfoForRNG();
  464.    
  465.     /*
  466.      * All the ciphers except SSL_RSA_WITH_NULL_MD5 are on by default.
  467.      * Enable encryption, enable NULL cipher. 
  468.      */
  469. #ifdef XP_MAC
  470. result = mainLoop(argc, argv);
  471. #else
  472.     result = PR_Initialize(mainLoop, argc, argv, 0);
  473. #endif
  474. #ifdef DEBUG
  475.     printf("main: Finishing (%ld)n", (long) result);
  476. #endif
  477. #ifdef XP_UNIX
  478.     SSM_ReleaseLockFile();
  479. #endif
  480. #ifndef XP_MAC
  481.     return result;
  482. #endif
  483. }
  484. #ifdef XP_MAC
  485. void *
  486. psm_malloc(unsigned long numbytes)
  487. {
  488. return NewPtrClear(numbytes);
  489. }
  490. void
  491. psm_free(void *ptr)
  492. {
  493. DisposePtr((char *) ptr);
  494. }
  495. #endif
  496. PRIntn mainLoop(PRIntn argc, char ** argv)
  497. {
  498.     PRFileDesc              *socket, *respsocket;
  499.     PRNetAddr               clientaddr;
  500.     SSMControlConnection    *curconnect;
  501.     SSMResourceID           ctrlID;
  502.     SSMStatus                status = PR_FAILURE;
  503.     PRBool                  alive = PR_TRUE;
  504.     /* Register ourselves so that logs, etc can identify us */
  505.     SSM_RegisterThread("main", NULL);
  506.     /* Open NLS stuff */
  507.     SSM_DEBUG("Initializing NLS.n");
  508. #ifdef XP_MAC
  509. SSM_InitNLS(":ui:");
  510. #else
  511.     SSM_InitNLS("ui");
  512. #endif
  513.     ssm_InitializePKCS11Strings();
  514.     /* Initialize the protocol */
  515. #ifdef XP_MAC
  516. CMT_Init(malloc, free);
  517. #else
  518.     CMT_Init(PR_Malloc, PR_Free);
  519. #endif
  520.     /* Open the HTTP listener */
  521.     SSM_DEBUG("Opening HTTP thread.n");
  522. status = SSM_InitHTTP();
  523.     if (status != SSM_SUCCESS) 
  524.     {
  525.         SSM_DEBUG("Couldn't open web port. Exiting.n");
  526.         goto loser;
  527.     }
  528.     /* open a port for control connections, with well-known port# */
  529.     socket = SSM_OpenControlPort();
  530.     if (!socket) 
  531.     {
  532.         SSM_DEBUG("Couldn't open control port. Exiting.n");
  533.         goto loser;
  534.     }
  535. #ifdef XP_MAC
  536.     if (PR_CEnterMonitor(glue_component) != NULL) {
  537.         PR_CNotify(glue_component);
  538.         PR_CExitMonitor(glue_component);
  539.     }
  540. #endif
  541.     
  542.     while (alive) 
  543.     {
  544.         /* wait until there is incoming request */
  545.   
  546.         respsocket = PR_Accept(socket, &clientaddr, PR_INTERVAL_NO_TIMEOUT); 
  547.         /*      while (respsocket == NULL) 
  548.                 { 
  549.                 if (PR_GetError() != PR_WOULD_BLOCK_ERROR) 
  550.                 goto loser;
  551.                 PR_Sleep(CARTMAN_SPINTIME);
  552. #ifdef DEBUG
  553.                 printf("master: Still ready for client connection on port %dn", CARTMAN_PORT); fflush(stdout);
  554. #endif
  555.                 respsocket = PR_Accept(socket, &clientaddr, 
  556.                 PR_SecondsToInterval(2));
  557.                 } */
  558.         if (!respsocket) {
  559.             /* accept failed: abort */
  560.             status = PR_GetError();
  561.             SSM_DEBUG("Error %d accepting control connection.  Exiting.n",
  562.                       status);
  563.             goto loser;
  564.         }
  565.         if (SSM_SocketPeerCheck(respsocket, PR_TRUE)) {
  566.             SSM_DEBUG("creating control connection.n");
  567.             status = SSM_CreateResource(SSM_RESTYPE_CONTROL_CONNECTION,
  568.                                         respsocket,
  569.                                         NULL,
  570.                                         &ctrlID,
  571.                                         (SSMResource **) &curconnect);
  572.             if (status != PR_SUCCESS)
  573.                 break;
  574.             PR_ASSERT(RESOURCE_CLASS(curconnect) == SSM_RESTYPE_CONTROL_CONNECTION);
  575.         }
  576.         else {
  577.             /* connection did not come from localhost: shut down the 
  578.              * connection and continue to loop
  579.              */
  580.             SSM_DEBUG("Connection attempt from a non-local host!n");
  581.             status = PR_Shutdown(respsocket, PR_SHUTDOWN_BOTH);
  582.             respsocket = NULL;
  583.         }
  584.     } /* end while(true) */
  585.  loser:
  586.     /* Shut down the HTTP thread. */
  587.     if (httpListenThread != NULL){
  588.       PR_Interrupt(httpListenThread);
  589.     }
  590.     exit(1);
  591.     /* ### mwelch - should we return meaningful error code? */
  592.     return 0;
  593. }