main.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:18k
- /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
- /*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1994-2000 Netscape Communications Corporation. All
- * Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- */
- #include "serv.h"
- #include "secport.h"
- #include "dataconn.h"
- #include "ctrlconn.h"
- #include "minihttp.h"
- #include "ciferfam.h"
- #include "secmime.h"
- #include "messages.h"
- #include "textgen.h"
- #include "oldfunc.h"
- #include "nss.h"
- #include "p12plcy.h"
- #include "nlslayer.h"
- #include "softoken.h"
- void SSM_InitLogging(void);
- #ifdef TIMEBOMB
- #include "timebomb.h"
- #endif
- #ifdef WIN32
- #include <wtypes.h>
- #include <winreg.h>
- #include <winerror.h>
- #endif
- #ifdef XP_UNIX
- #include <signal.h>
- #include <unistd.h>
- #ifndef SIG_ERR
- #define SIG_ERR -1
- #endif /*SIG_ERR*/
- #endif /*XP_UNIX*/
- #define POLICY_TYPE_INDEX 0
- SSMCollection * connections = NULL;
- SSMHashTable * tokenList = NULL;
- PRMonitor * tokenLock = NULL;
- SSMHashTable * ctrlConnections = NULL;
- SSMPolicyType policyType = ssmDomestic;
- /*
- * The following is a quick write of enabling various ciphers. This code is
- * essentially moved from the server core code. Eventually we will need to
- * place this data and functionality in a more modular way.
- */
- #define SSM_POLICY_END 0 /* end of table */
- #define SSM_POLICY_SSL 1 /* SSL ciphersuites: not really used */
- #define SSM_POLICY_PK12 2 /* PKCS #12 ciphersuites */
- #define SSM_POLICY_SMIME 3 /* S/MIME ciphersuites */
- typedef struct {
- PRInt32 policy;
- PRInt32 key;
- PRInt32 value;
- } SSMPolicyEntry;
- static SSMPolicyEntry ssmPK12PolicyTable[] =
- {
- {SSM_POLICY_PK12, PKCS12_RC4_40, (PRInt32)PR_TRUE},
- {SSM_POLICY_PK12, PKCS12_RC4_128, (PRInt32)PR_TRUE},
- {SSM_POLICY_PK12, PKCS12_RC2_CBC_40, (PRInt32)PR_TRUE},
- {SSM_POLICY_PK12, PKCS12_RC2_CBC_128, (PRInt32)PR_TRUE},
- {SSM_POLICY_PK12, PKCS12_DES_56, (PRInt32)PR_TRUE},
- {SSM_POLICY_PK12, PKCS12_DES_EDE3_168, (PRInt32)PR_TRUE},
- {SSM_POLICY_END, 0, 0}
- };
- static SSMPolicyEntry ssmSMIMEPolicyTable[] =
- {
- {SSM_POLICY_SMIME, SMIME_RC2_CBC_40, (PRInt32)PR_TRUE},
- {SSM_POLICY_SMIME, SMIME_RC2_CBC_64, (PRInt32)PR_TRUE},
- {SSM_POLICY_SMIME, SMIME_RC2_CBC_128, (PRInt32)PR_TRUE},
- {SSM_POLICY_SMIME, SMIME_DES_CBC_56, (PRInt32)PR_TRUE},
- {SSM_POLICY_SMIME, SMIME_DES_EDE3_168, (PRInt32)PR_TRUE},
- {SSM_POLICY_SMIME, SMIME_RC5PAD_64_16_40, (PRInt32)PR_TRUE},
- {SSM_POLICY_SMIME, SMIME_RC5PAD_64_16_64, (PRInt32)PR_TRUE},
- {SSM_POLICY_SMIME, SMIME_RC5PAD_64_16_128, (PRInt32)PR_TRUE},
- {SSM_POLICY_END, 0, 0}
- };
- static SSMStatus SSM_InstallPK12Policy(void)
- {
- const SSMPolicyEntry* entry = ssmPK12PolicyTable;
- int i;
- for (i = 0; entry[i].policy != SSM_POLICY_END; i++) {
- if (SEC_PKCS12EnableCipher(entry[i].key, entry[i].value) !=
- SECSuccess) {
- return SSM_FAILURE;
- }
- }
- return SSM_SUCCESS;
- }
- static SSMStatus SSM_InstallSMIMEPolicy(void)
- {
- const SSMPolicyEntry* entry = ssmSMIMEPolicyTable;
- int i;
-
- for (i = 0; entry[i].policy != SSM_POLICY_END; i++) {
- if (SECMIME_SetPolicy(entry[i].key, entry[i].value) != SECSuccess) {
- return SSM_FAILURE;
- }
- }
- return SSM_SUCCESS;
- }
- /* XXX sjlee: we don't need to do a similar thing for SSL as we can call an
- * NSS function to do it
- */
- #if 0
- /*
- * This function is required by svrplcy to set the
- * utility policy. This will tell us what kind of
- * policy we are running.
- */
- SECStatus Utility_SetPolicy(long which, int policy)
- {
- policyType = ssmDomestic;
- return SECSuccess;
- }
- #endif
- void SSM_SetPolicy(void)
- {
- #if 0
- SVRPLCY_InstallSSLPolicy();
- SVRPLCY_InstallPK12Policy();
- SVRPLCY_InstallSMIMEPolicy();
- SVRPLCY_InstallUtilityPolicy();
- #else
- /* Always domestic policy now */
- NSS_SetDomesticPolicy();
- SSM_InstallPK12Policy();
- SSM_InstallSMIMEPolicy();
- #endif
- }
- SSMPolicyType
- SSM_GetPolicy(void)
- {
- return policyType;
- }
- static void
- enable_SMIME_cipher_prefs(void)
- {
- SSMPolicyType policy;
- policy = SSM_GetPolicy();
- switch (policy)
- {
- case ssmDomestic:
- SECMIME_EnableCipher(SMIME_DES_EDE3_168, 1);
- SECMIME_EnableCipher(SMIME_RC2_CBC_128, 1);
- SECMIME_EnableCipher(SMIME_RC2_CBC_64, 1);
- SECMIME_EnableCipher(SMIME_DES_CBC_56, 1);
- #if 0
- SECMIME_EnableCipher(SMIME_RC5PAD_64_16_128, 1);
- SECMIME_EnableCipher(SMIME_RC5PAD_64_16_64, 1);
- SECMIME_EnableCipher(SMIME_FORTEZZA, 1);
- #endif
- case ssmExport:
- SECMIME_EnableCipher(SMIME_RC2_CBC_40, 1);
- #if 0
- SECMIME_EnableCipher(SMIME_RC5PAD_64_16_40, 1);
- #endif
- case ssmFrance:
- default:
- break;
- }
- /* now tell secmime that we've sent it the last preference */
- SECMIME_EnableCipher(CIPHER_FAMILYID_MASK, 0);
- }
- #define SHORT_PK11_STRING 33
- #define LONG_PK11_STRING 65
- static char*
- ssm_ConverToLength(char *origString, PRUint32 newLen)
- {
- char *newString;
- PRUint32 origLen;
- PRUint32 copyLen;
- newString = SSM_NEW_ARRAY(char,newLen+1);
- if (newString == NULL) {
- return origString;
- }
- origLen = PL_strlen(origString);
- copyLen = (origLen > newLen) ? newLen : origLen;
- memcpy(newString, origString, copyLen);
- memset(newString+copyLen, ' ' ,newLen - copyLen);
- newString[newLen]=' ';
- PR_Free(origString);
- return newString;
- }
- SECStatus
- ssm_InitializePKCS11Strings(void)
- {
- char *manufacturerID = NULL;
- char *libraryDescription = NULL;
- char *tokenDescription = NULL;
- char *privateTokenDescription = NULL;
- char *slotDescription = NULL;
- char *privateSlotDescription = NULL;
- char *fipsSlotDescription = NULL;
- char *fipsPrivateSlotDescription = NULL;
- SSMTextGenContext *cx;
- SSMStatus rv;
- rv = SSMTextGen_NewTopLevelContext(NULL, &cx);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- rv = SSM_FindUTF8StringInBundles(cx, "manufacturerID", &manufacturerID);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- if (PL_strlen(manufacturerID) != SHORT_PK11_STRING) {
- manufacturerID = ssm_ConverToLength(manufacturerID, SHORT_PK11_STRING);
- }
- rv = SSM_FindUTF8StringInBundles(cx, "libraryDescription",
- &libraryDescription);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- if (PL_strlen(libraryDescription) != SHORT_PK11_STRING) {
- libraryDescription = ssm_ConverToLength(libraryDescription,
- SHORT_PK11_STRING);
- }
- rv = SSM_FindUTF8StringInBundles(cx, "tokenDescription",
- &tokenDescription);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- if (PL_strlen(tokenDescription) != SHORT_PK11_STRING) {
- tokenDescription = ssm_ConverToLength(tokenDescription,
- SHORT_PK11_STRING);
- }
- rv = SSM_FindUTF8StringInBundles(cx, "privateTokenDescription",
- &privateTokenDescription);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- if (PL_strlen(privateTokenDescription) != SHORT_PK11_STRING) {
- privateTokenDescription = ssm_ConverToLength(privateTokenDescription,
- SHORT_PK11_STRING);
- }
- rv = SSM_FindUTF8StringInBundles(cx, "slotDescription", &slotDescription);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- if (PL_strlen(slotDescription) != LONG_PK11_STRING) {
- slotDescription = ssm_ConverToLength(slotDescription,
- LONG_PK11_STRING);
- }
- rv = SSM_FindUTF8StringInBundles(cx, "privateSlotDescription",
- &privateSlotDescription);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- if (PL_strlen(privateSlotDescription) != LONG_PK11_STRING) {
- privateSlotDescription = ssm_ConverToLength(privateSlotDescription,
- LONG_PK11_STRING);
- }
- rv = SSM_FindUTF8StringInBundles(cx, "fipsSlotDescription",
- &fipsSlotDescription);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- if (PL_strlen(fipsSlotDescription) != LONG_PK11_STRING) {
- fipsSlotDescription = ssm_ConverToLength(fipsSlotDescription,
- LONG_PK11_STRING);
- }
- rv = SSM_FindUTF8StringInBundles(cx, "fipsPrivateSlotDescription",
- &fipsPrivateSlotDescription);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- if (PL_strlen(fipsPrivateSlotDescription) != LONG_PK11_STRING) {
- fipsPrivateSlotDescription =
- ssm_ConverToLength(fipsPrivateSlotDescription, LONG_PK11_STRING);
- }
- if (cx != NULL) {
- SSMTextGen_DestroyContext(cx);
- }
- PK11_ConfigurePKCS11(manufacturerID, libraryDescription, tokenDescription,
- privateTokenDescription, slotDescription,
- privateSlotDescription, fipsSlotDescription,
- fipsPrivateSlotDescription, 0, 0);
- return SECSuccess;
- loser:
- PR_FREEIF(manufacturerID);
- PR_FREEIF(libraryDescription);
- PR_FREEIF(tokenDescription);
- PR_FREEIF(privateTokenDescription);
- PR_FREEIF(slotDescription);
- PR_FREEIF(privateSlotDescription);
- if (cx != NULL) {
- SSMTextGen_DestroyContext(cx);
- }
- return SECFailure;
- }
- #ifdef XP_UNIX
- #define CATCH_SIGNAL_DEFAULT(SIGNAL)
- if (((int)signal(SIGNAL, psm_signal_handler_default)) == ((int)SIG_ERR))
- goto loser;
- #define CATCH_SIGNAL_IGNORE(SIGNAL)
- if (((int)signal(SIGNAL, psm_signal_handler_ignore)) == ((int)SIG_ERR))
- goto loser;
- static void
- psm_signal_handler_default(int sig)
- {
- #ifdef DEBUG
- printf ("Trapping the signal %dn", sig);
- #endif
- SSM_ReleaseLockFile();
- kill(getpid(),SIGKILL);
- }
- static void
- psm_signal_handler_ignore(int sig)
- {
- #ifdef DEBUG
- printf ("Ignoring the signal %dn", sig);
- #endif
- signal(sig,psm_signal_handler_ignore);
- }
- static SSMStatus
- psm_catch_signals(void)
- {
- CATCH_SIGNAL_IGNORE(SIGHUP);
- CATCH_SIGNAL_DEFAULT(SIGINT);
- CATCH_SIGNAL_DEFAULT(SIGQUIT);
- CATCH_SIGNAL_DEFAULT(SIGILL);
- CATCH_SIGNAL_DEFAULT(SIGTRAP);
- CATCH_SIGNAL_DEFAULT(SIGABRT);
- CATCH_SIGNAL_DEFAULT(SIGIOT);
- #ifdef SIGEMT
- CATCH_SIGNAL_DEFAULT(SIGEMT);
- #endif
- CATCH_SIGNAL_DEFAULT(SIGFPE);
- CATCH_SIGNAL_DEFAULT(SIGBUS);
- CATCH_SIGNAL_DEFAULT(SIGSEGV);
- #ifdef SIGSYS
- CATCH_SIGNAL_DEFAULT(SIGSYS);
- #endif
- CATCH_SIGNAL_IGNORE(SIGPIPE);
- CATCH_SIGNAL_DEFAULT(SIGTERM);
- #ifndef LINUX
- CATCH_SIGNAL_DEFAULT(SIGUSR1);
- #endif
- CATCH_SIGNAL_DEFAULT(SIGUSR2);
- #ifdef SIGXCPU
- CATCH_SIGNAL_DEFAULT(SIGXCPU);
- #endif
- #ifdef SIGDANGER
- CATCH_SIGNAL_DEFAULT(SIGDANGER);
- #endif
- return SSM_SUCCESS;
- loser:
- return SSM_FAILURE;
- }
- #endif
- #if defined(XP_PC) && !defined(DEBUG)
- int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
- LPSTR lpszLine, int nShow)
- #elif defined(XP_MAC)
- /*
- We run RunMacPSM in a separate thread off the main thread.
- This is because we can't do any blocking I/O routines on the main
- thread, because Mac NSPR doesn't own the original thread used to
- run the app.
- */
- static void* glue_component = NULL;
- void RunMacPSM(void *arg)
- #else
- int main(int argc, char ** argv)
- #endif
- {
- #if (defined(XP_PC) && !defined(DEBUG)) || (defined(XP_MAC))
- /* substitute argc and argv for NSPR */
- int argc = 0;
- char *argv[] = {"", NULL};
- #endif
- PRIntn result = 0;
- #ifdef XP_MAC
- glue_component = arg;
- #endif
- #ifdef DEBUG
- PR_STDIO_INIT();
- #endif
- #ifdef DEBUG
- /* Initialize logging. */
- SSM_InitLogging();
- #endif
- #ifdef TIMEBOMB
- SSM_CheckTimebomb();
- #endif
- #ifdef XP_UNIX
- if (psm_catch_signals() != SSM_SUCCESS) {
- SSM_DEBUG("Couldn't set signal handlers. Quittingn");
- exit(1);
- }
- #endif
- SSM_SetPolicy();
- enable_SMIME_cipher_prefs();
- if (SSM_GetPolicy() == ssmDomestic) {
- SSM_EnableHighGradeKeyGen();
- }
- /* Initialize NLS layer */
- if (nlsInit() != PR_TRUE) {
- SSM_DEBUG("Failed to initialize the NLS layern");
- exit(1);
- }
- /* Initialize global list of control connections. */
- connections = SSM_NewCollection();
- if (connections == NULL)
- {
- SSM_DEBUG("Can't initialize! (%ld)n", (long) result);
- exit(1);
- }
- /* Initialize global list of tokens */
- result = SSM_HashCreate(&tokenList);
- if (result != PR_SUCCESS || !tokenList) {
- SSM_DEBUG("Can't initialize - tokenList n");
- exit(result);
- }
- tokenLock = PR_NewMonitor();
- if (!tokenLock) {
- SSM_DEBUG("Can't initialize - tokenLockn");
- exit(1);
- }
- /* Initialize hash table of control connections */
- result = SSM_HashCreate(&ctrlConnections);
- if (result != PR_SUCCESS || !ctrlConnections) {
- SSM_DEBUG("Can't initialize global table for control connections n");
- exit(result);
- }
- /* Initialize resource table */
- SSM_ResourceInit();
- if (SSM_InitPolicyHandler() != PR_SUCCESS) {
- SSM_DEBUG("Couldn't initialize the Policy Handler.n");
- exit (1);
- }
- /* initialize random number generator */
- SSM_DEBUG("Initializing random number generator.n");
- RNG_RNGInit();
- RNG_SystemInfoForRNG();
-
- /*
- * All the ciphers except SSL_RSA_WITH_NULL_MD5 are on by default.
- * Enable encryption, enable NULL cipher.
- */
- #ifdef XP_MAC
- result = mainLoop(argc, argv);
- #else
- result = PR_Initialize(mainLoop, argc, argv, 0);
- #endif
- #ifdef DEBUG
- printf("main: Finishing (%ld)n", (long) result);
- #endif
- #ifdef XP_UNIX
- SSM_ReleaseLockFile();
- #endif
- #ifndef XP_MAC
- return result;
- #endif
- }
- #ifdef XP_MAC
- void *
- psm_malloc(unsigned long numbytes)
- {
- return NewPtrClear(numbytes);
- }
- void
- psm_free(void *ptr)
- {
- DisposePtr((char *) ptr);
- }
- #endif
- PRIntn mainLoop(PRIntn argc, char ** argv)
- {
- PRFileDesc *socket, *respsocket;
- PRNetAddr clientaddr;
- SSMControlConnection *curconnect;
- SSMResourceID ctrlID;
- SSMStatus status = PR_FAILURE;
- PRBool alive = PR_TRUE;
- /* Register ourselves so that logs, etc can identify us */
- SSM_RegisterThread("main", NULL);
- /* Open NLS stuff */
- SSM_DEBUG("Initializing NLS.n");
- #ifdef XP_MAC
- SSM_InitNLS(":ui:");
- #else
- SSM_InitNLS("ui");
- #endif
- ssm_InitializePKCS11Strings();
- /* Initialize the protocol */
- #ifdef XP_MAC
- CMT_Init(malloc, free);
- #else
- CMT_Init(PR_Malloc, PR_Free);
- #endif
- /* Open the HTTP listener */
- SSM_DEBUG("Opening HTTP thread.n");
- status = SSM_InitHTTP();
- if (status != SSM_SUCCESS)
- {
- SSM_DEBUG("Couldn't open web port. Exiting.n");
- goto loser;
- }
- /* open a port for control connections, with well-known port# */
- socket = SSM_OpenControlPort();
- if (!socket)
- {
- SSM_DEBUG("Couldn't open control port. Exiting.n");
- goto loser;
- }
- #ifdef XP_MAC
- if (PR_CEnterMonitor(glue_component) != NULL) {
- PR_CNotify(glue_component);
- PR_CExitMonitor(glue_component);
- }
- #endif
-
- while (alive)
- {
- /* wait until there is incoming request */
-
- respsocket = PR_Accept(socket, &clientaddr, PR_INTERVAL_NO_TIMEOUT);
- /* while (respsocket == NULL)
- {
- if (PR_GetError() != PR_WOULD_BLOCK_ERROR)
- goto loser;
- PR_Sleep(CARTMAN_SPINTIME);
- #ifdef DEBUG
- printf("master: Still ready for client connection on port %dn", CARTMAN_PORT); fflush(stdout);
- #endif
- respsocket = PR_Accept(socket, &clientaddr,
- PR_SecondsToInterval(2));
- } */
- if (!respsocket) {
- /* accept failed: abort */
- status = PR_GetError();
- SSM_DEBUG("Error %d accepting control connection. Exiting.n",
- status);
- goto loser;
- }
- if (SSM_SocketPeerCheck(respsocket, PR_TRUE)) {
- SSM_DEBUG("creating control connection.n");
- status = SSM_CreateResource(SSM_RESTYPE_CONTROL_CONNECTION,
- respsocket,
- NULL,
- &ctrlID,
- (SSMResource **) &curconnect);
- if (status != PR_SUCCESS)
- break;
- PR_ASSERT(RESOURCE_CLASS(curconnect) == SSM_RESTYPE_CONTROL_CONNECTION);
- }
- else {
- /* connection did not come from localhost: shut down the
- * connection and continue to loop
- */
- SSM_DEBUG("Connection attempt from a non-local host!n");
- status = PR_Shutdown(respsocket, PR_SHUTDOWN_BOTH);
- respsocket = NULL;
- }
- } /* end while(true) */
- loser:
- /* Shut down the HTTP thread. */
- if (httpListenThread != NULL){
- PR_Interrupt(httpListenThread);
- }
- exit(1);
- /* ### mwelch - should we return meaningful error code? */
- return 0;
- }