ctrlconn.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:84k
- /* -*- 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 "ctrlconn.h"
- #include "dataconn.h"
- #include "sslconn.h"
- #include "p7cinfo.h"
- #include "p7econn.h"
- #include "p7dconn.h"
- #include "secmime.h"
- #include "hashconn.h"
- #include "certres.h"
- #include "cert.h"
- #include "certdb.h"
- #include "cdbhdl.h"
- #include "servimpl.h"
- #include "newproto.h"
- #include "messages.h"
- #include "serv.h"
- #include "ssmerrs.h"
- #include "minihttp.h"
- #include "secmod.h"
- #include "kgenctxt.h"
- #include "advisor.h"
- #include "processmsg.h"
- #include "signtextres.h"
- #include "p12res.h"
- #include "p12plcy.h"
- #include "secmime.h"
- #include "ciferfam.h"
- #include "profile.h"
- #include "prefs.h"
- #include "ocsp.h"
- #include "msgthread.h"
- #ifdef XP_MAC
- #include "macshell.h"
- #endif
- /*
- * The structure passed to get an attribute for the control connection,
- * which may require a password prompt.
- */
- typedef struct GetAttrArgStr {
- SSMResource *res;
- SSMAttributeID attrID;
- SSMResourceAttrType attrType;
- } GetAttrArg;
- static SSMStatus
- ssmcontrolconnection_encodegetattr_reply(SECItem *msg, SSMStatus rv,
- SSMAttributeValue *value,
- SSMResourceAttrType attrType);
- /* The ONLY reason why we can use these macros for both control and
- data connections is that they inherit from the same superclass.
- Do NOT try this at home. */
- #define SSMCONNECTION(c) (&(c)->super)
- #define SSMRESOURCE(c) (&(c)->super.super)
- /* Special resource id values */
- #define SSM_BASE_RID 0x00000003
- #define SSM_MAX_RID 0x0FFFFFFF
- static long ssm_ctrl_count = 0;
- static SSMResourceID ssm_next_ctrlrid = SSM_MAX_RID;
- static char * gUserDir = NULL;
- static PRMonitor *policySetLock = NULL;
- static PRBool policySet = PR_FALSE;
- SSMStatus SSM_InitPolicyHandler(void)
- {
- policySetLock = PR_NewMonitor();
- if (policySetLock == NULL) {
- return PR_FAILURE;
- }
- return PR_SUCCESS;
- }
- #ifdef TIMEBOMB
- #include "timebomb.h"
- PRBool SSMTimeBombExpired = PR_FALSE;
- #endif
- SSMStatus SSMControlConnection_Create(void *arg,
- SSMControlConnection * connection,
- SSMResource **res)
- {
- SSMStatus rv = PR_SUCCESS;
- SSMControlConnection *conn;
- *res = NULL; /* in case we fail */
-
- conn = (SSMControlConnection *) PR_CALLOC(sizeof(SSMControlConnection));
- if (!conn) goto loser;
-
- SSMRESOURCE(conn)->m_connection = conn;
- rv = SSMControlConnection_Init(conn, SSM_RESTYPE_CONTROL_CONNECTION,
- (PRFileDesc *) arg);
- if (rv != PR_SUCCESS)
- goto loser;
-
- SSMControlConnection_Invariant(conn);
- ssm_ctrl_count++;
- SSM_DEBUG("Control count is now %ld.n", ssm_ctrl_count);
- *res = SSMRESOURCE(conn);
- rv = SSM_HashInsert(ctrlConnections, (SSMHashKey)(*res)->m_id,
- (void *)*res);
- if (rv != PR_SUCCESS)
- goto loser;
- return PR_SUCCESS;
- loser:
- if (rv == PR_SUCCESS) rv = PR_FAILURE;
- if (conn)
- {
- SSM_ShutdownResource(SSMRESOURCE(conn), rv); /* force destroy */
- SSM_FreeResource(SSMRESOURCE(conn));
- }
-
- return rv;
- }
- #ifdef XP_MAC
- int
- toascii(char c)
- {
- return (int) c;
- }
- #endif
- SSMStatus SSMControlConnection_GenerateNonce(SSMControlConnection *conn)
- {
- SSMStatus rv = PR_FAILURE;
- SECStatus srv;
- char* buf = NULL;
- char* n = NULL;
- const int NONCE_SIZE = 8;
- int i;
- conn->m_nonce = NULL; /* in case of failure */
- buf = (char*)PR_CALLOC(NONCE_SIZE);
- if (buf == NULL) {
- goto loser;
- }
- srv = RNG_GenerateGlobalRandomBytes(buf, NONCE_SIZE);
- if (srv != SECSuccess) {
- goto loser;
- }
- n = PL_strdup("nonce");
- for (i = 0; i < NONCE_SIZE; i++) {
- n = PR_sprintf_append(n, "%d", (int)toascii(buf[i]));
- if (n == NULL) {
- goto loser;
- }
- }
- conn->m_nonce = n;
- rv = PR_SUCCESS;
- loser:
- if (buf != NULL) {
- PR_Free(buf);
- }
- return rv;
- }
- SSMStatus SSMControlConnection_Init(SSMControlConnection *conn,
- SSMResourceType type,
- PRFileDesc *socket)
- {
- SSMStatus rv = PR_SUCCESS;
- PRBool locked = PR_FALSE;
- PRNetAddr dataAddr;
- rv = SSM_HashCreate(&conn->m_resourceDB);
- if (rv != PR_SUCCESS || !conn->m_resourceDB)
- goto loser;
- /* We need to see if there are any other control connections already
- * established. If there are, then we need to use the next RID
- * as ours so the correct control connection is found for UI events.
- * Before all control connections would get the RID of 3, and that would
- * cause problems.
- */
- conn->m_lastRID = ssm_next_ctrlrid;
- conn->m_secAdvisorList = NULL;
- rv = SSM_HashCreate(&conn->m_resourceIdDB);
- if (rv != PR_SUCCESS || conn->m_resourceIdDB == NULL)
- goto loser;
- rv = SSMConnection_Init(NULL, &conn->super, type);
- if (rv != PR_SUCCESS) goto loser;
- ssm_next_ctrlrid = conn->super.super.m_id;
- SSM_LockResource(SSMRESOURCE(conn));
- locked = PR_TRUE;
- /* Current version. Allow this to drop when the Hello request comes in. */
- conn->m_version = SSM_PROTOCOL_VERSION;
- /* Generate a nonce. */
- rv = SSMControlConnection_GenerateNonce(conn);
- if (rv != PR_SUCCESS) goto loser;
- SSM_DEBUG("Generated nonce of `%s'.n",conn->m_nonce);
- conn->m_controlOutQ = SSM_NewCollection();
- if (!conn->m_controlOutQ)
- goto loser;
- conn->m_socket = socket;
- /* Create the data socket */
- conn->m_dataSocket = SSM_OpenPort();
- if (!conn->m_dataSocket) {
- goto loser;
- }
- /* Get the data port */
- rv = PR_GetSockName(conn->m_dataSocket, &dataAddr);
- if (rv != PR_SUCCESS) {
- goto loser;
- }
- conn->m_dataPort = PR_ntohs(dataAddr.inet.port);
- SSMCONNECTION(conn)->m_auth_func = SSMControlConnection_Authenticate;
-
- /* Creat password handling stuff:temporary and long-term password tables */
- rv = SSM_HashCreate(&conn->m_passwdTable);
- if (rv != PR_SUCCESS || !conn->m_passwdTable)
- goto loser;
- conn->m_passwdLock = PR_NewMonitor();
- if (!conn->m_passwdLock)
- goto loser;
- conn->m_waiting = 0;
- rv = SSM_HashCreate(&conn->m_encrPasswdTable);
- if (rv != PR_SUCCESS || !conn->m_encrPasswdTable)
- goto loser;
- conn->m_encrPasswdLock = PR_NewMonitor();
- if (!conn->m_encrPasswdLock)
- goto loser;
- /* database for cert look-up by cert ID */
- rv = SSM_HashCreate(&conn->m_certIdDB);
- if (rv != PR_SUCCESS || !conn->m_certIdDB)
- goto loser;
- conn->m_prefs = PREF_NewPrefs();
- if (conn->m_prefs == NULL) {
- goto loser;
- }
- conn->m_doesUI = PR_FALSE;
- /* Spin threads after we set the shutdown function. */
- SSM_DEBUG("spawning read msg thread for %lx.n", (long) conn);
- #ifdef ALLOW_STANDALONE
- if (!standalone)
- {
- #endif
- /* Get reference for front end thread */
- SSM_GetResourceReference(SSMRESOURCE(conn));
- conn->m_frontEndThread = SSM_CreateThread(SSMRESOURCE(conn),
- SSM_FrontEndThread);
- if (conn->m_frontEndThread == NULL)
- goto loser;
- #ifdef ALLOW_STANDALONE
- }
- #endif
- SSM_UnlockResource(SSMRESOURCE(conn));
- return PR_SUCCESS;
- loser:
- if (rv == PR_SUCCESS) rv = PR_FAILURE;
- if (locked)
- SSM_UnlockResource(SSMRESOURCE(conn));
- if (socket)
- {
- PR_Close(socket); /* close this */
- conn->m_socket = NULL;
- }
- if (conn->m_passwdLock)
- PR_DestroyMonitor(conn->m_passwdLock);
- if (conn->m_passwdTable)
- SSM_HashDestroy(conn->m_passwdTable);
- if (conn->m_encrPasswdLock)
- PR_DestroyMonitor(conn->m_encrPasswdLock);
- if (conn->m_encrPasswdTable)
- SSM_HashDestroy(conn->m_encrPasswdTable);
- if (conn->m_certIdDB)
- SSM_HashDestroy(conn->m_certIdDB);
- if (conn->m_prefs)
- PREF_ClosePrefs(conn->m_prefs);
- if (conn->m_resourceDB)
- SSM_HashDestroy(conn->m_resourceDB);
- if (conn->m_resourceIdDB)
- SSM_HashDestroy(conn->m_resourceIdDB);
-
- return rv;
- }
- SSMStatus SSMControlConnection_Shutdown(SSMResource *arg, SSMStatus status)
- {
- SSMStatus rv, trv; /* rv propagates superclass shutdown */
- PRThread *closer = PR_GetCurrentThread();
- SSMControlConnection *conn = (SSMControlConnection *) arg;
- SSMControlConnection_Invariant(conn);
-
- #ifdef TIMEBOMB
- if (SSMTimeBombExpired)
- return;
- #endif
- SSM_LockResource(arg);
-
- /* if the thread calling this routine is a service thread,
- clear its place in the connection object. this is a
- prelude to the wakeup call just below. */
- arg->m_threadCount--; /* decrement if service thread */
- if (closer == conn->m_writeThread)
- conn->m_writeThread = NULL;
- if (closer == conn->m_frontEndThread)
- conn->m_frontEndThread = NULL;
- else
- arg->m_threadCount++; /* not a service thread, restore thread count */
- /* shut down our base class. */
- rv = SSMConnection_Shutdown(arg, status);
- /* wake up threads if this is the first time throwing an error */
- if ((arg->m_status != PR_SUCCESS) &&
- (rv != SSM_ERR_ALREADY_SHUT_DOWN))
- {
- SSM_DEBUG("First time aborting control connection.n");
- SSM_DEBUG("Posting shutdown msgs to queues.n");
- /* close queues that our threads may be listening on */
- if (conn->m_controlOutQ)
- SSM_SendQMessage(conn->m_controlOutQ,
- SSM_PRIORITY_SHUTDOWN,
- SSM_DATA_PROVIDER_SHUTDOWN,
- 0, NULL, PR_TRUE);
- if (conn->m_writeThread) PR_Interrupt(conn->m_writeThread);
- if (conn->m_frontEndThread) PR_Interrupt(conn->m_frontEndThread);
- }
- /* If the front end thread is down, close the client socket */
- if ((!conn->m_frontEndThread) && (conn->m_socket))
- {
- /* Got a socket but nothing to work on it with. Close the socket. */
- #ifndef XP_UNIX
- /* Don't close socket with linger on UNIX since the
- * control socket on UNIX is a UNIX domain socket.
- */
- SSM_DEBUG("Closing control socket with linger.n");
- trv = SSM_CloseSocketWithLinger(conn->m_socket);
- #else
- SSM_DEBUG("Closing control socket.n");
- trv = PR_Close(conn->m_socket);
- #endif
- PR_ASSERT(trv == PR_SUCCESS);
- conn->m_socket = NULL; /* don't try closing more than once */
- SSM_DEBUG("Closed control socket (rv == %d).n",rv);
- }
- if (SSMRESOURCE(conn)->m_threadCount == 0)
- {
- /* All service threads are down. Shut down NSS. */
- ssm_ShutdownNSS(conn);
- }
- SSM_UnlockResource(arg);
- return rv;
- }
- SSMStatus SSMControlConnection_Destroy(SSMResource *res,
- PRBool doFree)
- {
- SSMControlConnection *conn = (SSMControlConnection *) res;
- void *value;
- /* Drain and destroy the queue. */
- if (conn->m_controlOutQ)
- ssm_DrainAndDestroyQueue(&(conn->m_controlOutQ));
- /* Free our fields. */
- PR_FREEIF(conn->m_nonce);
- PR_FREEIF(conn->m_profileName);
- PR_FREEIF(conn->m_dirRoot);
- PR_DestroyMonitor(conn->m_passwdLock);
- PR_DestroyMonitor(conn->m_encrPasswdLock);
- SSM_HashDestroy(conn->m_passwdTable);
- SSM_HashDestroy(conn->m_encrPasswdTable);
- PREF_ClosePrefs(conn->m_prefs);
-
- /* log out all pk11 slots for now */
- if (conn->m_pkcs11Init) {
- PK11_LogoutAll();
- }
- if (conn->m_secAdvisorList)
- SECITEM_ZfreeItem(conn->m_secAdvisorList, PR_TRUE);
- /* Destroy superclass fields. */
- SSMConnection_Destroy(SSMRESOURCE(conn), PR_FALSE);
- SSM_HashRemove(ctrlConnections,
- (SSMHashKey)(conn->super.super.m_id), &value);
-
- /* If this is the last control connection, quit. */
- --ssm_ctrl_count;
- SSM_DEBUG("Control count is now %ld.n", ssm_ctrl_count);
- if ((ssm_ctrl_count <= 0)
- #ifdef DEBUG
- && (PR_GetEnv("NSM_SUPPRESS_EXIT") == NULL)
- #endif
- )
- {
- SSM_DEBUG("Last control connection gone, quitting.n");
- #ifdef XP_UNIX
- SSM_ReleaseLockFile();
- #endif
- #ifdef XP_MAC
- SetQuitFlag(PR_TRUE); // tell primordial thread to quit
- #else
- exit(0);
- #endif
- }
- /* Free the connection object if asked. */
- if (doFree)
- PR_DELETE(conn);
- return PR_SUCCESS;
- }
- SSMStatus SSMControlConnection_GetAttrIDs(SSMResource* res,
- SSMAttributeID** ids, PRIntn* count)
- {
- SSMStatus rv;
- if (res == NULL || ids == NULL || count == NULL) {
- goto loser;
- }
- rv = SSMConnection_GetAttrIDs(res, ids, count);
- if (rv != PR_SUCCESS) {
- goto loser;
- }
- *ids = (SSMAttributeID *) PR_REALLOC(*ids, (*count + 2)*sizeof(SSMAttributeID));
- if (!*ids) {
- goto loser;
- }
- (*ids)[*count++] = SSM_FID_DEFAULT_EMAIL_SIGNER_CERT;
- (*ids)[*count++] = SSM_FID_DEFAULT_EMAIL_RECIPIENT_CERT;
- goto done;
- loser:
- if (rv == PR_SUCCESS) {
- rv = PR_FAILURE;
- }
- done:
- return rv;
- }
- static void ssmcontrolconnection_getattr_thread(void* inArg)
- {
- GetAttrArg *arg = (GetAttrArg*)inArg;
- SSMResource *res = arg->res;
- SSMAttributeID attrID = arg->attrID;
- SSMResourceAttrType attrType = arg->attrType;
- SSMControlConnection* conn = (SSMControlConnection*)res;
- SSMStatus rv = PR_SUCCESS;
- CERTCertificate *cert = NULL;
- SSMResourceCert *certRes;
- SSMResourceID certID = 0;
- char *certNickname = NULL;
- PRBool locked = PR_FALSE;
- SSMAttributeValue realValue, *value;
- SECItem msg;
- value = &realValue;
- /* see what it is */
- #ifdef DEBUG
- SSM_RegisterThread("ctrlconn getattr",NULL);
- #endif
- switch(attrID) {
- case SSM_FID_DEFAULT_EMAIL_SIGNER_CERT:
- SSM_LockResource(SSMRESOURCE(conn));
- locked = PR_TRUE;
- rv = PREF_GetStringPref(conn->m_prefs, "security.default_mail_cert",
- &certNickname);
- if (rv != PR_SUCCESS) {
- goto loser;
- }
- if (certNickname) {
- cert = CERT_FindUserCertByUsage(conn->m_certdb,
- certNickname,
- certUsageEmailSigner,
- PR_FALSE,
- conn);
- if (cert) {
- SSM_CreateResource(SSM_RESTYPE_CERTIFICATE, cert, conn,
- &certID, (SSMResource**)&certRes);
- rv = SSM_ClientGetResourceReference(&certRes->super, &certID);
- SSM_FreeResource(&certRes->super);
- if (rv != SSM_SUCCESS)
- goto loser;
- }
- }
- if (cert == NULL)
- goto loser;
- value->u.rid = certID;
- value->type = SSM_RID_ATTRIBUTE;
- SSM_UnlockResource(SSMRESOURCE(conn));
- locked = PR_FALSE;
- break;
- case SSM_FID_DEFAULT_EMAIL_RECIPIENT_CERT:
- SSM_LockResource(SSMRESOURCE(conn));
- locked = PR_TRUE;
- rv = PREF_GetStringPref(conn->m_prefs, "security.default_mail_cert",
- &certNickname);
- if (rv != PR_SUCCESS) {
- goto loser;
- }
- if (certNickname) {
- cert = CERT_FindUserCertByUsage(conn->m_certdb,
- certNickname,
- certUsageEmailRecipient,
- PR_FALSE,
- conn);
- if (cert) {
- SSM_CreateResource(SSM_RESTYPE_CERTIFICATE, cert, conn,
- &certID, (SSMResource**)&certRes);
- rv = SSM_ClientGetResourceReference(&certRes->super, &certID);
- SSM_FreeResource(&certRes->super);
- if (rv != SSM_SUCCESS)
- goto loser;
- }
- }
- value->u.rid = certID;
- value->type = SSM_RID_ATTRIBUTE;
- SSM_UnlockResource(SSMRESOURCE(conn));
- locked = PR_FALSE;
- break;
- default:
- rv = SSMConnection_GetAttr(res, attrID, attrType, value);
- if (rv != PR_SUCCESS) {
- goto loser;
- }
- }
- if (value->type != attrType) {
- goto loser;
- }
- goto done;
- loser:
- value->type = SSM_NO_ATTRIBUTE;
- if (rv == PR_SUCCESS) {
- rv = PR_FAILURE;
- }
- done:
- if (locked) {
- SSM_UnlockResource(SSMRESOURCE(conn));
- }
- rv = ssmcontrolconnection_encodegetattr_reply(&msg, rv, value,
- attrType);
- if (rv != SSM_SUCCESS) {
- rv = ssmcontrolconnection_encode_err_reply(&msg, rv);
- PR_ASSERT(rv == SSM_SUCCESS);
- }
- ssmcontrolconnection_send_message_to_client(conn, &msg);
- PR_FREEIF(msg.data);
- SSM_FreeResource(res);
- }
- SSMStatus SSMControlConnection_GetAttr(SSMResource *res, SSMAttributeID attrID,
- SSMResourceAttrType attrType,
- SSMAttributeValue *value)
- {
- GetAttrArg *arg = NULL;
- if (res == NULL || value == NULL) {
- goto loser;
- }
- arg = SSM_NEW(GetAttrArg);
- if (arg == NULL) {
- goto loser;
- }
- arg->res = res;
- arg->attrID = attrID;
- arg->attrType = attrType;
- if (SSM_CreateAndRegisterThread(PR_USER_THREAD, ssmcontrolconnection_getattr_thread,
- (void *)arg, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
- PR_UNJOINABLE_THREAD, 0) == NULL) {
- goto loser;
- }
- return SSM_ERR_DEFER_RESPONSE;
- loser:
- if (arg != NULL) {
- PR_Free(arg);
- }
- return SSM_FAILURE;
- }
- void
- SSMControlConnection_Invariant(SSMControlConnection *conn)
- {
- if (conn)
- {
- SSMConnection_Invariant(SSMCONNECTION(conn));
- SSM_LockResource(SSMRESOURCE(conn));
- PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(conn), SSM_RESTYPE_CONTROL_CONNECTION));
- PR_ASSERT(conn->m_controlOutQ != NULL);
- SSM_UnlockResource(SSMRESOURCE(conn));
- }
- }
- void SSMControlConnection_RecycleItem(SECItem* msg)
- {
- PR_ASSERT(msg != NULL);
- if (msg->data != NULL) {
- cmt_free(msg->data);
- msg->data = NULL;
- }
- return;
- }
- /*
- * Read msgs from the control connection queue and send them back to client
- */
- void SSM_WriteCtrlThread(void * arg)
- {
- PRIntn sent, len, type;
- SSMControlConnection * ctrl = NULL;
- SSMStatus rv= PR_FAILURE;
- char * data;
- #ifdef TIMEBOMB
- if (SSMTimeBombExpired)
- return;
- #endif
- ctrl = (SSMControlConnection *)arg;
- SSM_RegisterNewThread("ctrl write", (SSMResource*) arg);
- SSM_DEBUG("initializing.n");
- if (!ctrl)
- {
- rv = (SSMStatus) PR_INVALID_ARGUMENT_ERROR;
- goto loser;
- }
- if (!ctrl->m_socket)
- {
- rv = (SSMStatus) PR_INVALID_ARGUMENT_ERROR;
- goto loser;
- }
- ctrl->m_writeThread = PR_GetCurrentThread();
- /* wait for SSM_DATA_PROVIDER_OPEN message */
- rv = SSM_RecvQMessage(ctrl->m_controlOutQ,
- SSM_PRIORITY_ANY,
- &type, &len, &data,
- PR_TRUE);
- if (rv != PR_SUCCESS || type != SSM_DATA_PROVIDER_OPEN)
- goto loser;
- SSM_DEBUG("got queue open message.n");
-
- /* look for data in the incoming queue and send it to the client */
- while ((SSMRESOURCE(ctrl)->m_status == PR_SUCCESS) && (rv == PR_SUCCESS))
- {
- rv = SSM_RecvQMessage(ctrl->m_controlOutQ,
- SSM_PRIORITY_ANY,
- &type, &len, &data,
- PR_TRUE);
- if (rv != PR_SUCCESS)
- {
- SSM_DEBUG("Couldn't read or block on outgoing queue (%d).n",
- rv);
- goto loser;
- }
- switch (type)
- {
- case SSM_DATA_PROVIDER_SHUTDOWN:
- SSM_DEBUG("got queue close message.n");
- goto loser;
- default:
- {
- CMTMessageHeader header;
- /* got a regular control message. send it to the client */
- SSM_DEBUG("got message for client (type=%lx,len=%ld).n",
- type, len);
- header.type = PR_htonl(type);
- header.len = PR_htonl(len);
- /* Send the message header */
- sent = SSM_WriteThisMany(ctrl->m_socket, &header, sizeof(CMTMessageHeader));
- if (sent != sizeof(CMTMessageHeader)) {
- rv = (SSMStatus) PR_GetError();
- SSM_DEBUG("cannot send message type: %d.n", rv);
- goto loser;
- }
- /* Send the message body */
- sent = SSM_WriteThisMany(ctrl->m_socket, data, len);
- if (sent != len)
- {
- rv = (SSMStatus) PR_GetError();
- SSM_DEBUG("cannot send message data: %d.n", rv);
- goto loser;
- }
- PR_Free(data);
- }
- break;
- } /* end of switch */
- } /* end of while alive loop */
-
- loser:
- if (ctrl)
- {
- SSM_DEBUG("Shutting down, rv = %d.n", rv);
- SSM_ShutdownResource(SSMRESOURCE(ctrl), rv);
- SSM_FreeResource(SSMRESOURCE(ctrl));
- }
- return;
- }
- /*
- * Check if given cert (arg) already exists in our cert resource db.
- */
- void SSMControlConnection_CertLookUp(SSMControlConnection * connection,
- void * arg, SSMResource ** res)
- {
- PR_ASSERT(res);
- SSM_HashFind(connection->m_certIdDB, (SSMHashKey) arg, (void **)res);
- if (*res != NULL)
- SSM_GetResourceReference(*res);
- }
- /* NSS_Init does not open the cert and key db's read/write. Cartman needs
- * them to be opened read/write in order to do key gen's and import
- * certificate chains.
- *
- * For now, we pretty much re-create the code of NSS_Init in this file. If
- * NSS_Init is ever modified so that we can open the db's read/write, then
- * we just call the new function from the function SSM_InitNSS.
- */
- static char *
- ssm_certdb_name_cb(void *arg, int dbVersion)
- {
- const char *configdir = (const char*)arg;
- const char *dbver;
- switch (dbVersion) {
- case 7:
- dbver = "7";
- break;
- case 6:
- dbver = "6";
- break;
- case 5:
- dbver = "5";
- break;
- case 4:
- default:
- dbver = "";
- break;
- }
- #ifdef XP_MAC
- /* on Mac, :: means parent directory. does non-Mac get // with Seamonkey? */
- if(configdir[PL_strlen(configdir) - 1] == ':') {
- return PR_smprintf("%sCertificates%s", configdir, dbver);
- } else {
- return PR_smprintf("%s:Certificates%s", configdir, dbver);
- }
- #else
- return PR_smprintf("%s/cert%s.db", configdir, dbver);
- #endif
- }
- static char *ssm_keydb_name_cb(void *arg, int dbVersion)
- {
- const char *configdir = (const char*)arg;
- const char *dbver;
- switch (dbVersion) {
- case 3:
- dbver = "3";
- break;
- case 2:
- default:
- dbver = "";
- break;
- }
- #ifdef XP_MAC
- if (configdir[PL_strlen(configdir) - 1] == ':') {
- return PR_smprintf("%sKey Database%s", configdir, dbver);
- } else {
- return PR_smprintf("%s:Key Database%s", configdir, dbver);
- }
- #else
- return PR_smprintf("%s/key%s.db", configdir, dbver);
- #endif
- }
- SECStatus
- ssm_OpenCertDB(const char * configdir,SSMControlConnection *ctrl)
- {
- CERTCertDBHandle *certdb;
- SECStatus status = SECFailure;
- #ifdef ALLOW_STANDALONE
- PRBool readonly = standalone;
- #else
- PRBool readonly = PR_FALSE;
- #endif
-
- /* We should not be doing this! */
- if (0) {
- certdb = CERT_GetDefaultCertDB();
- if (certdb) {
- return SECSuccess;
- }
- }
- certdb = PORT_ZNew(CERTCertDBHandle);
- if (certdb == NULL) {
- goto loser;
- }
- status = CERT_OpenCertDB(certdb, readonly, ssm_certdb_name_cb,
- (void*)configdir);
- if (status == SECSuccess) {
- CERT_SetDefaultCertDB(certdb);
- ctrl->m_certdb = certdb;
- } else {
- PR_Free(certdb);
- ctrl->m_certdb = NULL;
- }
- loser:
- return status;
- }
- SECStatus
- ssm_OpenKeyDB(const char * configdir, SSMControlConnection *ctrl)
- {
- SECKEYKeyDBHandle *keydb;
- #ifdef ALLOW_STANDALONE
- PRBool readonly = standalone;
- #else
- PRBool readonly = PR_FALSE;
- #endif
-
- /* we should not be doing this! */
- if (0) {
- keydb = SECKEY_GetDefaultKeyDB();
- if (keydb) {
- return SECSuccess;
- }
- }
-
- keydb = SECKEY_OpenKeyDB(readonly, ssm_keydb_name_cb, (void*)configdir);
- if (keydb == NULL) {
- ctrl->m_keydb = NULL;
- return SECFailure;
- }
- SECKEY_SetDefaultKeyDB(keydb);
- ctrl->m_keydb = keydb;
- return SECSuccess;
- }
- SECStatus
- ssm_OpenSecModDB(const char * configdir)
- {
- static char *secmodname;
- if (secmodname) {
- return SECSuccess;
- }
- #ifdef XP_UNIX
- secmodname = PR_smprintf("%s/secmodule.db", configdir);
- #elif defined(XP_MAC)
- if (configdir[PL_strlen(configdir) - 1] == ':') {
- secmodname = PR_smprintf("%sSecurity Modules", configdir);
- } else {
- secmodname = PR_smprintf("%s:Security Modules", configdir);
- }
- #else
- secmodname = PR_smprintf("%s/secmod.db", configdir);
- #endif
- if (secmodname == NULL) {
- return SECFailure;
- }
- SECMOD_init(secmodname);
- return SECSuccess;
- }
- void
- ssm_ShutdownNSS(SSMControlConnection *ctrl)
- {
- if (ctrl->m_certdb != NULL) {
- CERT_ClosePermCertDB(ctrl->m_certdb);
- }
- if (ctrl->m_keydb != NULL) {
- SECKEY_CloseKeyDB(ctrl->m_keydb);
- }
- }
- #if 0
- SSMPolicyType
- SSM_ConvertSVRPlcyToSSMPolicy(PRInt32 policy)
- {
- return ssmDomestic;
- }
- #endif
- void
- SSM_SetP12Export(void)
- {
- SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
- SEC_PKCS12EnableCipher(PKCS12_RC4_128, 0);
- SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
- SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 0);
- SEC_PKCS12EnableCipher(PKCS12_DES_56, 0);
- SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 0);
- }
- void
- SSM_SetSMIMEExport(void)
- {
- SECMIME_EnableCipher(SMIME_RC2_CBC_40, 1);
- #if 0
- SECMIME_EnableCipher(SMIME_RC2_CBC_64, 0);
- SECMIME_EnableCipher(SMIME_RC2_CBC_128, 0);
- SECMIME_EnableCipher(SMIME_RC5PAD_64_16_40, 1);
- SECMIME_EnableCipher(SMIME_RC5PAD_64_16_64, 0);
- SECMIME_EnableCipher(SMIME_RC5PAD_64_16_128, 0);
- SECMIME_EnableCipher(SMIME_DES_CBC_56, 0);
- SECMIME_EnableCipher(SMIME_DES_EDE3_168, 0);
- SECMIME_EnableCipher(SMIME_FORTEZZA, 0);
- #endif
- SECMIME_EnableCipher(CIPHER_FAMILYID_MASK, 0);
- }
- SECStatus
- SSM_InitNSS(char* certpath, SSMControlConnection *ctrl, PRInt32 policy)
- {
- SECStatus status;
- SECStatus rv = SECFailure;
- PR_EnterMonitor(policySetLock);
- if (policySet) {
- SSM_DEBUG("We got another hello request. If this is for "
- "a different user then the first, bad things may happenn");
- #if 0
- if (reqPolicy != policyType) {
- SSM_DEBUG("Got a hello request with different policy type "
- "than has already been established. "
- "Refusing connectionn");
- rv = SECFailure;
- goto loser;
- }
- #endif
- }
- #if 0
- else if (policyType != reqPolicy) {
- SSM_DEBUG("Initial hello message has different policy type than "
- "the server. Setting policy to Exportn");
- NSS_SetExportPolicy();
- SSM_SetP12Export();
- SSM_SetSMIMEExport();
- policyType = ssmExport;
- }
- #endif
- SSM_DEBUG("First time initializing NSS.n");
- status = ssm_OpenCertDB(certpath, ctrl);
- if (status != SECSuccess) {
- goto loser;
- }
- status = ssm_OpenKeyDB(certpath, ctrl);
- if (status != SECSuccess) {
- goto loser;
- }
- status = ssm_OpenSecModDB(certpath);
- if (status != SECSuccess) {
- goto loser;
- }
- ctrl->m_pkcs11Init = PR_TRUE;
- rv = SECSuccess;
- PORT_SetUCS2_ASCIIConversionFunction(SSM_UCS2_ASCIIConversion);
- PORT_SetUCS2_UTF8ConversionFunction(SSM_UCS2_UTF8Conversion);
- policySet = PR_TRUE;
- /* set default policy strings */
- CERT_SetCAPolicyStringCallback(SSM_GetCAPolicyString, ctrl);
- loser:
- if (rv != SECSuccess) {
- ssm_ShutdownNSS(ctrl);
- }
- PR_ExitMonitor(policySetLock);
- return rv;
- }
- /* End the section of code shamelessly copied and modified from NSS_Init*/
- static int ssm_ask_pref_to_pk11(int asktype)
- {
- switch (asktype) {
- case 1:
- return -1;
- case 2:
- return 1;
- }
- return 0;
- }
- #ifdef XP_MAC
- extern OSErr ConvertMacPathToUnixPath(const char *macPath, char **unixPath);
- #endif
- /* Set up profile and password information. */
- SSMStatus
- SSMControlConnection_SetupNSS(SSMControlConnection *ctrl, PRInt32 policy)
- {
- SSMStatus rv = PR_SUCCESS;
- SECStatus srv = SECSuccess;
- PRFileInfo info;
- #ifdef XP_MAC
- char *unixPath;
- #endif
- /* check the profile directory */
- #ifdef XP_UNIX
- /* we expect a non-empty string here: bail if we don't have one */
- if ((PR_GetFileInfo(ctrl->m_dirRoot, &info) != PR_SUCCESS) ||
- (info.type != PR_FILE_DIRECTORY)) {
- SSM_DEBUG("Cannot find a profile in %s.n", ctrl->m_dirRoot);
- goto loser;
- }
- #elif defined(XP_MAC)
- /* we expect a path that is already Macified. */
- ConvertMacPathToUnixPath(ctrl->m_dirRoot, &unixPath);
- if (!unixPath)
- goto loser;
- if (unixPath[0] != ' ')
- {
- /* profile directory was supplied: check to make sure it exists */
- if ((PR_GetFileInfo(unixPath, &info) != PR_SUCCESS) ||
- (info.type != PR_FILE_DIRECTORY)) {
- SSM_DEBUG("Cannot find a profile in %s.n", ctrl->m_dirRoot);
- goto loser;
- }
- }
- else
- goto loser; /* for now */
- /* ### mwelch - we're leaking unixPath for now */
- #else
- if (ctrl->m_dirRoot[0] != ' ') {
- /* profile directory was supplied: check to make sure it exists */
- if ((PR_GetFileInfo(ctrl->m_dirRoot, &info) != PR_SUCCESS) ||
- (info.type != PR_FILE_DIRECTORY)) {
- SSM_DEBUG("Cannot find a profile in %s.n", ctrl->m_dirRoot);
- goto loser;
- }
- }
- else {
- /* profile directory was not supplied: get the "default" directory */
- if (ctrl->m_profileName[0] == ' ') {
- /* this is (almost always) a 3rd party application on win32 that
- * wants to use a "default" profile
- * set it to "Default" and hope for the best
- */
- ctrl->m_profileName = PL_strdup("Default");
- }
- ctrl->m_dirRoot = SSM_PROF_GetProfileDirectory(ctrl);
- if (ctrl->m_dirRoot == NULL) {
- goto loser;
- }
- }
- #endif
- /* Do the libsec initialization */
-
- if (gUserDir != NULL) {
- #ifndef WIN32
- if (strcmp(ctrl->m_dirRoot, gUserDir) != 0) {
- goto loser;
- }
- #else
- if (STRNCASECMP(ctrl->m_dirRoot, gUserDir, strlen(gUserDir))) {
- goto loser;
- }
- #endif
- /*
- * This is the best way to get the current key and cert dbs.
- * When NSS fully supports multiple profiles, we'll have to do
- * away with this call.
- */
- ctrl->m_certdb = CERT_GetDefaultCertDB();
- ctrl->m_keydb = SECKEY_GetDefaultKeyDB();
- } else {
- gUserDir = strdup(ctrl->m_dirRoot);
- /*
- * We only want to initialize NSS once.
- */
- srv = SSM_InitNSS(ctrl->m_dirRoot, ctrl, policy);
- if (srv != SECSuccess) {
- goto loser;
- }
- }
- #ifdef ALLOW_STANDALONE
- if (standalone)
- {
- /* Set password callback to be a function which uses a
- preset password. Very insecure, which is why this is
- set in debug code only. */
- PK11_SetPasswordFunc(SSM_StandaloneGetPasswdCallback);
- PK11_SetVerifyPasswordFunc(SSM_StandaloneVerifyPasswdCallback);
- }
- else
- {
- #endif
- /* set passwd callback */
- PK11_SetPasswordFunc(SSM_GetPasswdCallback);
- /* verify passwd */
- PK11_SetVerifyPasswordFunc(SSM_VerifyPasswdCallback);
- #ifdef ALLOW_STANDALONE
- }
- #endif
- goto done;
- loser:
- /* Gather the error from wherever it came */
- if (rv == PR_SUCCESS)
- rv = (srv == SECSuccess) ? PR_SUCCESS : PR_FAILURE;
- if (rv == PR_SUCCESS) rv = PR_FAILURE;
-
- done:
- return rv;
- }
- SSMStatus SSMControlConnection_ProcessHello(SSMControlConnection *ctrl, SECItem *msg)
- {
- SSMStatus rv = PR_SUCCESS;
- HelloRequest request;
- HelloReply reply;
- /* parse client info and store it in the connection object
- */
- #ifdef NSM_PROTOCOL_STRICT
- /* we should only ever get one hello request */
- PR_ASSERT(ctrl->m_profileName == NULL);
- #endif
- if (CMT_DecodeMessage(HelloRequestTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
- goto loser;
- }
- /* allow earlier client libs to try to talk to us, but not later ones */
- if (request.version > ctrl->m_version) {
- goto loser;
- }
- ctrl->m_doesUI = request.doesUI;
- ctrl->m_profileName = request.profile;
- if (request.profileDir == NULL) {
- /* it may be an empty string but it should not be NULL */
- goto loser;
- }
- ctrl->m_dirRoot = request.profileDir;
- SSM_DEBUG("Selected profile directory <%s>.n", ctrl->m_dirRoot);
- msg->data = NULL;
- rv = SSMControlConnection_SetupNSS(ctrl, request.policy);
- /* Create the auto-renewal thread */
- ctrl->m_certRenewalThread = SSM_CreateThread(SSMRESOURCE(ctrl),
- SSM_CertificateRenewalThread);
- goto done;
- loser:
- if (rv == PR_SUCCESS) rv = PR_FAILURE;
-
- done:
- /* construct HELLO_REPLY message
- */
- SSM_DEBUG("composing Hello reply.n");
- reply.result = rv;
- reply.sessionID = SSMRESOURCE(ctrl)->m_id;
- reply.version = ctrl->m_version;
- reply.httpPort = SSM_GetHTTPPort();
- reply.nonce.len = strlen(ctrl->m_nonce);
- reply.nonce.data = (unsigned char *) ctrl->m_nonce;
- reply.policy = SSM_GetPolicy();
- reply.stringVersion = SSMVersionString;
- if (rv == PR_SUCCESS) {
- msg->type = (SECItemType) (SSM_HELLO_MESSAGE | SSM_REPLY_OK_MESSAGE);
- }
- else {
- msg->type = (SECItemType) (SSM_HELLO_MESSAGE | SSM_REPLY_ERR_MESSAGE);
- }
- CMT_EncodeMessage(HelloReplyTemplate, (CMTItem*)msg, &reply);
- return rv;
- }
- typedef struct {
- char* pref; /* pref key */
- long id; /* cipher ID for NSS */
- } SSMCipherPref;
- /* cipher suites are listed in the order of decreasing preference in each
- * cipher family
- */
- SSMCipherPref SSMSSLCiphers[] = {
- /* SSL2 ciphers */
- {"security.ssl2.rc4_128", SSL_EN_RC4_128_WITH_MD5},
- {"security.ssl2.rc2_128", SSL_EN_RC2_128_CBC_WITH_MD5},
- {"security.ssl2.des_ede3_192", SSL_EN_DES_192_EDE3_CBC_WITH_MD5},
- {"security.ssl2.des_64", SSL_EN_DES_64_CBC_WITH_MD5},
- {"security.ssl2.rc4_40", SSL_EN_RC4_128_EXPORT40_WITH_MD5},
- {"security.ssl2.rc2_40", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5},
- /* SSL3 ciphers */
- {"security.ssl3.fortezza_fortezza_sha",
- SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA},
- {"security.ssl3.fortezza_rc4_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA},
- {"security.ssl3.rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5},
- {"security.ssl3.rsa_fips_des_ede3_sha",
- SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA},
- {"security.ssl3.rsa_des_ede3_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA},
- {"security.ssl3.rsa_fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA},
- {"security.ssl3.rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA},
- {"security.ssl3.rsa_1024_rc4_56_sha",
- TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
- {"security.ssl3.rsa_1024_des_cbc_sha",
- TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA},
- {"security.ssl3.rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5},
- {"security.ssl3.rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5},
- {"security.ssl3.fortezza_null_sha", SSL_FORTEZZA_DMS_WITH_NULL_SHA},
- {"security.ssl3.rsa_null_md5", SSL_RSA_WITH_NULL_MD5},
- {NULL, 0} /* end marker */
- };
- SSMCipherPref SSMSMIMECiphers[] = {
- /* SMIME bulk ciphers */
- {"security.smime.fortezza", SMIME_FORTEZZA},
- {"security.smime.des_ede3", SMIME_DES_EDE3_168},
- {"security.smime.rc2_128", SMIME_RC2_CBC_128},
- {"security.smime.des", SMIME_DES_CBC_56},
- {"security.smime.rc2_64", SMIME_RC2_CBC_64},
- {"security.smime.rc2_40", SMIME_RC2_CBC_40},
- {NULL, 0} /* end marker */
- };
- static void ssm_enable_ssl_cipher_prefs(SSMControlConnection* ctrl)
- {
- int i;
- PRBool boolVal = PR_TRUE;
- for (i = 0; SSMSSLCiphers[i].pref != NULL; i++) {
- if ((PREF_GetBoolPref(ctrl->m_prefs, SSMSSLCiphers[i].pref,
- &boolVal) == PR_SUCCESS) &&
- (boolVal == PR_FALSE)) {
- /* we only have to disable a cipher, not enable one, because
- * prefs only restrict ciphers further over the policies
- */
- SSL_EnableCipher(SSMSSLCiphers[i].id, boolVal);
- }
- }
- }
- static void ssm_enable_smime_cipher_prefs(SSMControlConnection* ctrl)
- {
- int i;
- PRBool boolVal = PR_TRUE;
- for (i = 0; SSMSMIMECiphers[i].pref != NULL; i++) {
- if ((PREF_GetBoolPref(ctrl->m_prefs, SSMSMIMECiphers[i].pref,
- &boolVal) == PR_SUCCESS) &&
- (boolVal == PR_FALSE)) {
- SECMIME_EnableCipher(SSMSMIMECiphers[i].id, boolVal);
- }
- }
- }
- static SSMStatus ssm_enable_security_prefs(SSMControlConnection* ctrl)
- {
- PRBool prefval;
- PRIntn ask;
- PRIntn timeout;
- PK11SlotInfo* slot = NULL;
- PRBool ocspOn;
- char *ocspURL = NULL, *ocspSigner = NULL;
- PR_ASSERT((ctrl != NULL) && (ctrl->m_prefs != NULL));
- /* enforce the user's preferences for SSL cipher families */
- if (PREF_GetBoolPref(ctrl->m_prefs, "security.enable_ssl2", &prefval) !=
- PR_SUCCESS) {
- goto loser;
- }
- SSL_EnableDefault(SSL_ENABLE_SSL2, prefval);
- if (PREF_GetBoolPref(ctrl->m_prefs, "security.enable_ssl3", &prefval) !=
- PR_SUCCESS) {
- goto loser;
- }
- SSL_EnableDefault(SSL_ENABLE_SSL3, prefval);
- /* set password values */
- if (PREF_GetIntPref(ctrl->m_prefs, "security.ask_for_password", &ask) !=
- PR_SUCCESS) {
- goto loser;
- }
- if (PREF_GetIntPref(ctrl->m_prefs, "security.password_lifetime",
- &timeout) != PR_SUCCESS) {
- goto loser;
- }
- slot = PK11_GetInternalKeySlot();
- PK11_SetSlotPWValues(slot, ssm_ask_pref_to_pk11((int)ask),
- (int)timeout);
- PK11_FreeSlot(slot);
- /* disable any additional ciphers that might be marked in prefs */
- ssm_enable_ssl_cipher_prefs(ctrl);
- ssm_enable_smime_cipher_prefs(ctrl);
- /*
- * Let's take care of OCSP prefs.
- */
- if (PREF_GetBoolPref(ctrl->m_prefs, "security.OCSP.enabled",
- &ocspOn) != SSM_SUCCESS ||
- !ocspOn) {
- CERT_DisableOCSPChecking(ctrl->m_certdb);
- CERT_DisableOCSPDefaultResponder(ctrl->m_certdb);
- } else {
- /* OCSP should be enabled */
- CERT_EnableOCSPChecking(ctrl->m_certdb);
- /* Do we have a default responder set? */
- if (PREF_GetBoolPref(ctrl->m_prefs,
- "security.OCSP.useDefaultResponder", &ocspOn) == SSM_SUCCESS &&
- ocspOn) {
- /* First let's make sure the default URL and
- * signer have been set.
- */
- PREF_GetStringPref(ctrl->m_prefs, "security.OCSP.URL", &ocspURL);
- PREF_GetStringPref(ctrl->m_prefs, "security.OCSP.signingCA",
- &ocspSigner);
- if (ocspURL != NULL && ocspSigner != NULL) {
- CERT_SetOCSPDefaultResponder(ctrl->m_certdb, ocspURL,
- ocspSigner);
- CERT_EnableOCSPDefaultResponder(ctrl->m_certdb);
- }
- }
- }
- return PR_SUCCESS;
- loser:
- return PR_FAILURE;
- }
- SSMStatus SSMControlConnection_ProcessPrefs(SSMControlConnection* ctrl,
- SECItem* msg)
- {
- SSMStatus rv = PR_SUCCESS;
- SetPrefListMessage request;
- SingleNumMessage reply;
- int i;
- PRBool boolval;
- PRIntn intval;
- SSM_DEBUG("Preferences were passed in from the plugin.n");
- /* decode the message */
- if (CMT_DecodeMessage(SetPrefListMessageTemplate, &request,
- (CMTItem*)msg) != CMTSuccess) {
- goto loser;
- }
- for (i = 0; i < request.length; i++) {
- if (request.list[i].key == NULL) {
- /* misconfigured pref item: look at the next */
- continue;
- }
- switch (request.list[i].type) {
- case STRING_PREF: /* string type */
- rv = PREF_SetStringPref(ctrl->m_prefs, request.list[i].key,
- request.list[i].value);
- break;
- case BOOL_PREF: /* boolean type */
- if (PL_strcmp(request.list[i].value, "true") == 0) {
- boolval = PR_TRUE;
- }
- else if (PL_strcmp(request.list[i].value, "false") == 0) {
- boolval = PR_FALSE;
- }
- else {
- /* misconfigured */
- break;
- }
- rv = PREF_SetBoolPref(ctrl->m_prefs, request.list[i].key,
- boolval);
- break;
- case INT_PREF: /* integer type */
- intval = atoi(request.list[i].value);
- rv = PREF_SetIntPref(ctrl->m_prefs, request.list[i].key,
- intval);
- break;
- default:
- SSM_DEBUG("We do not understand the pref type.n");
- break;
- }
- }
- /* prefs are all stored: now take action to apply prefs */
- rv = ssm_enable_security_prefs(ctrl);
- rv = PR_SUCCESS;
- loser:
- reply.value = rv;
- msg->type =(SECItemType) (SSM_REPLY_OK_MESSAGE | SSM_PREF_ACTION);
- CMT_EncodeMessage(SingleNumMessageTemplate, (CMTItem*)msg, &reply);
- return rv;
- }
-
- SSMStatus
- SSMControlConnection_ProcessDataRequest(SSMControlConnection * ctrl,
- SECItem * msg)
- {
- SSMInfoSSL infoSSL;
- SSMInfoP7Encode infoP7Encode;
- SSMInfoP7Decode infoP7Decode;
- SSMHashInitializer infoHash;
- SSMDataConnection *datac;
- void *createArg;
- SSMResourceType connType = SSM_RESTYPE_NULL;
- SSMStatus rv = PR_SUCCESS;
- SSMResourceID dataRID = 0;
- PRInt32 msgtype = msg->type & SSM_SUBTYPE_MASK;
- DataConnectionReply reply;
- switch (msgtype)
- {
- case SSM_SSL_CONNECTION:
- {
- SSLDataConnectionRequest request;
- SSM_DEBUG("... specifically, an SSL data request.n");
- /* Decode the SSL request message */
- if (CMT_DecodeMessage(SSLDataConnectionRequestTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
- goto loser;
- }
- (void) memset(&infoSSL, 0, sizeof(SSMInfoSSL));
- infoSSL.isTLS = PR_FALSE;
- infoSSL.flags = request.flags;
- infoSSL.port = request.port;
- infoSSL.hostIP = request.hostIP;
- infoSSL.hostName = request.hostName;
- infoSSL.forceHandshake = request.forceHandshake;
- infoSSL.clientContext = request.clientContext;
- msg->data = NULL;
- /* fill in the control connection... */
- infoSSL.parent = ctrl;
- connType = SSM_RESTYPE_SSL_DATA_CONNECTION;
- createArg = &infoSSL;
- }
- break;
- case SSM_PKCS7DECODE_STREAM:
- {
- SingleItemMessage request;
- SSM_DEBUG("PKCS7 Decode Request.n");
- if (CMT_DecodeMessage(SingleItemMessageTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
- goto loser;
- }
- connType = SSM_RESTYPE_PKCS7_DECODE_CONNECTION;
- infoP7Decode.ctrl = ctrl;
- infoP7Decode.clientContext = request.item;
- createArg = &infoP7Decode;
- }
- break;
- case SSM_TLS_CONNECTION:
- case SSM_PROXY_CONNECTION:
- {
- TLSDataConnectionRequest request;
- SSM_DEBUG("... specifically, a TLS connection request.n");
- /* decode the TLS request message */
- if (CMT_DecodeMessage(TLSDataConnectionRequestTemplate, &request,
- (CMTItem*)msg) != CMTSuccess) {
- goto loser;
- }
- (void)memset(&infoSSL, 0, sizeof(SSMInfoSSL));
- /* notify that this is either an SMTP or an SSL proxy connection, not
- * a regular SSL connection
- */
- infoSSL.isTLS = PR_TRUE;
- infoSSL.port = request.port;
- infoSSL.hostIP = request.hostIP;
- infoSSL.hostName = request.hostName;
- msg->data = NULL;
- /* fill in the control connection... */
- infoSSL.parent = ctrl;
- connType = SSM_RESTYPE_SSL_DATA_CONNECTION;
- createArg = &infoSSL;
- }
- break;
- case SSM_PKCS7ENCODE_STREAM:
- {
- PKCS7DataConnectionRequest request;
- SSM_DEBUG("... specifically, a PKCS#7 Encode request.n");
- if (CMT_DecodeMessage(PKCS7DataConnectionRequestTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
- goto loser;
- }
- infoP7Encode.ciRID = request.resID;
- connType = SSM_RESTYPE_PKCS7_ENCODE_CONNECTION;
- infoP7Encode.ctrl = ctrl;
- infoP7Encode.clientContext = request.clientContext;
- createArg = &infoP7Encode;
- }
- break;
- case SSM_HASH_STREAM:
- {
- SingleNumMessage request;
- connType = SSM_RESTYPE_HASH_CONNECTION;
- infoHash.m_parent = ctrl;
- if (CMT_DecodeMessage(SingleNumMessageTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
- goto loser;
- }
- infoHash.m_hashtype = (HASH_HashType) request.value;
- msg->data = NULL;
- createArg = &infoHash;
- }
- break;
- default:
- SSM_DEBUG("Unknown data connection type (%lx).n",
- (msg->type & SSM_SUBTYPE_MASK));
- }
- if (connType != SSM_RESTYPE_NULL)
- {
- /* ... then create the data connection */
- SSM_DEBUG("Firing up data connection.n");
- rv = SSM_CreateResource(connType, createArg, ctrl, &dataRID,
- (SSMResource **) &datac);
- if ((rv != PR_SUCCESS) || (!datac)) {
- goto loser;
- }
- } else {
- rv = (SSMStatus) SSM_ERR_BAD_RESOURCE_TYPE;
- goto loser;
- }
-
- /* compose reply message */
- SSM_DEBUG("Composing reply.n");
- msg->type = (SECItemType) (SSM_DATA_CONNECTION | msgtype | SSM_REPLY_OK_MESSAGE);
- reply.result = rv;
- reply.connID = dataRID;
- reply.port = ctrl->m_dataPort;
- if (CMT_EncodeMessage(DataConnectionReplyTemplate, (CMTItem*)msg, &reply) != CMTSuccess) {
- goto loser;
- }
- if (rv != PR_SUCCESS) goto loser;
- goto done;
- loser:
- if (msg->data)
- {
- PR_Free(msg->data);
- msg->data = NULL;
- }
- if (rv == PR_SUCCESS) rv = PR_FAILURE;
- reply.result = PR_GetError();
- reply.connID = 0;
- reply.port = 0;
- CMT_EncodeMessage(DataConnectionReplyTemplate, (CMTItem*)msg, &reply);
- done:
- return rv;
- }
- SSMStatus
- SSMControlConnection_ProcessDupResourceRequest(SSMControlConnection * ctrl,
- SECItem * msg)
- {
- SSMResourceID objID;
- SSMResource *obj = NULL;
- SSMStatus rv = PR_SUCCESS;
- SingleNumMessage request;
- DupResourceReply reply;
- SSM_DEBUG("Got a Duplicate Resource request.n");
- /* parse message and get resource/field ID */
- if (CMT_DecodeMessage(SingleNumMessageTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
- goto loser;
- }
- objID = request.value;
- /* ### mwelch Should free this here, instead of in the actual
- message parsing code. (4/13/99) */
- msg->data = NULL;
-
- SSM_DEBUG("Rsrc ID %ld.n", objID);
-
- rv = SSMControlConnection_GetResource(ctrl, objID, &obj);
- if (rv != PR_SUCCESS)
- goto loser;
-
- PR_ASSERT(obj != NULL);
- rv = SSM_ClientGetResourceReference(obj, &objID);
- if (rv != PR_SUCCESS)
- goto loser;
- SSM_DEBUG("DuplicateResource: result %ld, new rsrc ID %ld.n",
- (long) rv, (long)obj->m_id);
- goto done;
- loser:
- /* Got an error while getting the reference. This is recoverable,
- because we just report the error back to the client. */
- if (rv == PR_SUCCESS) rv = PR_FAILURE;
- done:
- msg->data = NULL;
- msg->len = 0;
- /* compose reply message */
- SSM_DEBUG("Composing reply.n");
- msg->type = (SECItemType) (SSM_RESOURCE_ACTION | SSM_DUPLICATE_RESOURCE
- | ((rv == SSM_SUCCESS) ? SSM_REPLY_OK_MESSAGE : SSM_REPLY_ERR_MESSAGE));
- reply.result = rv;
- reply.resID = (obj ? obj->m_id : 0);
- if (CMT_EncodeMessage(DupResourceReplyTemplate, (CMTItem*)msg, &reply) != CMTSuccess) {
- goto loser;
- }
- rv = PR_SUCCESS;
- if ((msg->data == NULL) || (msg->len == 0)) rv = PR_FAILURE;
- if (obj != NULL)
- SSM_FreeResource(obj);
- return rv;
- }
- SSMStatus
- SSMControlConnection_ProcessDestroyRequest(SSMControlConnection * ctrl,
- SECItem * msg)
- {
- SSMStatus rv = PR_SUCCESS;
- DestroyResourceRequest request;
- SingleNumMessage reply;
- SSM_DEBUG("Got a Destroy Resource request.n");
- /* parse message and get resource/field ID */
- if (CMT_DecodeMessage(DestroyResourceRequestTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
- goto loser;
- }
- msg->data = NULL;
-
- SSM_DEBUG("RID %ld, expected type %ld.n", request.resID, request.resType);
-
- rv = SSM_ClientDestroyResource(ctrl, request.resID, (SSMResourceType) request.resType);
- goto done;
- loser:
- /* Got an error while getting the reference. This is recoverable,
- because we just report the error back to the client. */
- if (rv == PR_SUCCESS) rv = PR_FAILURE;
- done:
- msg->data = NULL;
- msg->len = 0;
- /* compose reply message */
- SSM_DEBUG("Composing reply.n");
- msg->type = (SECItemType) (SSM_RESOURCE_ACTION
- | SSM_DESTROY_RESOURCE
- | ((rv == SSM_SUCCESS) ? SSM_REPLY_OK_MESSAGE : SSM_REPLY_ERR_MESSAGE));
- reply.value = rv;
- CMT_EncodeMessage(SingleNumMessageTemplate, (CMTItem*)msg, &reply);
- rv = PR_SUCCESS;
- if ((msg->data == NULL) || (msg->len == 0)) rv = PR_FAILURE;
- return rv;
- }
- static SSMStatus
- ssmcontrolconnection_encodegetattr_reply(SECItem *msg, SSMStatus rv,
- SSMAttributeValue *value,
- SSMResourceAttrType attrType)
- {
- GetAttribReply reply;
- msg->data = NULL;
- msg->len = 0;
- /* compose reply message */
- SSM_DEBUG("Composing reply.n");
- msg->type = (SECItemType) (SSM_RESOURCE_ACTION
- | SSM_GET_ATTRIBUTE
- | SSM_REPLY_OK_MESSAGE
- | attrType);
- reply.result = rv;
- reply.value = *value;
- CMT_EncodeMessage(GetAttribReplyTemplate, (CMTItem*)msg, &reply);
- SSM_DestroyAttrValue(value, PR_FALSE);
- rv = SSM_SUCCESS;
- if ((msg->data == NULL) || (msg->len == 0))
- rv = SSM_FAILURE;
- return rv;
- }
- SSMStatus
- SSMControlConnection_ProcessGetAttrRequest(SSMControlConnection * ctrl,
- SECItem * msg)
- {
- SSMResource *obj = NULL;
- SSMResourceAttrType mAttrType;
- SSMStatus rv;
- SSMAttributeValue value = {SSM_NO_ATTRIBUTE};
- GetAttribRequest request;
- SSM_DEBUG("Got a Get Attribute request.n");
- /* parse message and get resource/field ID */
- if (CMT_DecodeMessage(GetAttribRequestTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
- goto loser;
- }
- msg->data = NULL;
-
- SSM_DEBUG("Rsrc ID %ld, attr ID %ld.n", request.resID, request.fieldID);
-
- if (request.resID == SSM_SESSION_RESOURCE) {
- SSM_GetResourceReference(&ctrl->super.super);
- obj = (SSMResource *)ctrl;
- } else {
- rv = SSMControlConnection_GetResource(ctrl, request.resID, &obj);
- if (rv != PR_SUCCESS)
- goto loser;
- }
-
- PR_ASSERT(obj != NULL);
- mAttrType = (SSMResourceAttrType) (msg->type & SSM_SPECIFIC_MASK);
- rv = SSM_GetResAttribute(obj, (SSMAttributeID) request.fieldID, mAttrType,
- &value);
- SSM_DEBUG("GetResAttribute: result %ld, type %lx.n",
- (long) rv, (long) value.type);
- if (rv == SSM_ERR_DEFER_RESPONSE)
- goto defer;
- if (rv != PR_SUCCESS)
- goto loser;
-
- /* Make sure the type returned matches what was asked. */
- if (mAttrType != value.type) {
- rv = SSM_ERR_ATTRIBUTE_TYPE_MISMATCH;
- /* pick default values for resource result that work
- for all three resource replies*/
- SSM_DestroyAttrValue(&value, PR_FALSE);
- value.type = SSM_NUMERIC_ATTRIBUTE;
- value.u.numeric = 0;
- }
- goto done;
- loser:
- /* Got an error while getting resource and/or attributes. This
- is recoverable, because we just report the error back to the
- client. */
- if (rv == PR_SUCCESS)
- rv = PR_FAILURE;
- /* Create a suitable zero value for any type requested */
- SSM_DestroyAttrValue(&value, PR_FALSE);
- value.type = SSM_NUMERIC_ATTRIBUTE;
- value.u.numeric = 0;
- done:
- rv = ssmcontrolconnection_encodegetattr_reply(msg, rv, &value,
- (SSMResourceAttrType) (msg->type & SSM_SPECIFIC_MASK));
- if (obj != NULL)
- SSM_FreeResource(obj);
- defer:
- return rv;
- }
- SSMStatus
- SSMControlConnection_ProcessSetAttrRequest(SSMControlConnection * ctrl,
- SECItem * msg)
- {
- SSMStatus rv;
- SSMResource *obj;
- SetAttribRequest request;
- SSM_DEBUG("Got a Set Attribute Request.n");
- if (CMT_DecodeMessage(SetAttribRequestTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
- goto loser;
- }
- PORT_Free(msg->data);
- msg->data = NULL;
- msg->len = 0;
- SSM_DEBUG("Rsrc ID %ld, attr ID %ld.n", request.resID, request.fieldID);
- rv = SSMControlConnection_GetResource(ctrl, request.resID, &obj);
- if (rv != PR_SUCCESS) {
- goto loser;
- }
- PR_ASSERT(obj != NULL);
- rv = SSM_SetResAttribute(obj, (SSMAttributeID)request.fieldID, &request.value);
- SSM_FreeResource(obj);
- SSM_DestroyAttrValue(&request.value, PR_FALSE);
- if (rv != PR_SUCCESS) {
- goto loser;
- }
- msg->type = (SECItemType) (SSM_RESOURCE_ACTION | SSM_SET_ATTRIBUTE |
- SSM_REPLY_OK_MESSAGE | (msg->type & SSM_SPECIFIC_MASK));
- return PR_SUCCESS;
- loser:
- return PR_FAILURE;
- }
- SSMStatus
- SSMControlConnection_ProcessCreateRequest(SSMControlConnection * ctrl,
- SECItem * msg)
- {
- SSMStatus rv;
- SSMResourceID rid = 0;
- SSMResource *res = NULL;
- unsigned char *params = NULL;
- CreateResourceRequest request;
- CreateResourceReply reply;
- SSM_DEBUG("Got a Create Resource Request.n");
- if (CMT_DecodeMessage(CreateResourceRequestTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
- goto loser;
- }
- msg->data = NULL;
- msg->len = 0;
- SSM_DEBUG("Type %ld, param len %ld.n", request.type, request.params.len);
- /* Bleah. Switch on the type.
- ### mwelch Must replace, since many of these resources can be
- generically created using control connection + single param */
- switch(request.type)
- {
- case SSM_RESTYPE_KEYGEN_CONTEXT:
- {
- SSMKeyGenContextCreateArg arg;
- arg.parent = ctrl;
- arg.type = SSM_CRMF_KEYGEN;
- arg.param = &request.params;
- SSM_DEBUG("Creating key gen context.n");
- rv = SSM_CreateResource((SSMResourceType) request.type, &arg,
- ctrl, &rid, &res);
- }
- break;
- case SSM_RESTYPE_SIGNTEXT:
- {
- rv = SSMSignTextResource_Create(request.params.data, ctrl, &res);
- if (rv == PR_SUCCESS) {
- PR_ASSERT(res != NULL);
- rid = res->m_id;
- }
- }
- break;
- default:
- rv = (SSMStatus) PR_INVALID_ARGUMENT_ERROR;
- break;
- }
- if (rv != PR_SUCCESS && rv != SSM_ERR_DEFER_RESPONSE)
- goto loser;
- PR_ASSERT(res != NULL);
- if (SSM_ClientGetResourceReference(res, &res->m_id) != PR_SUCCESS)
- goto loser;
- /* if deferred response don't create reply message */
- if (rv != PR_SUCCESS)
- goto done;
- msg->type = (SECItemType) (SSM_RESOURCE_ACTION
- | SSM_CREATE_RESOURCE
- | SSM_REPLY_OK_MESSAGE);
- goto done;
- loser:
- if (rv == PR_SUCCESS)
- rv = PR_FAILURE;
- done:
- if (params)
- PR_Free(params);
- /* Create a reply message here. */
- reply.result = rv;
- reply.resID = rid;
- CMT_EncodeMessage(CreateResourceReplyTemplate,(CMTItem*)msg, &reply);
- return rv;
- }
- SSMStatus
- SSMControlConnection_ProcessResourceRequest(SSMControlConnection * ctrl,
- SECItem * msg)
- {
- SSMStatus rv = PR_SUCCESS;
- SSM_DEBUG("Got a resource-related request.n");
- switch (msg->type & SSM_SUBTYPE_MASK)
- {
- case SSM_GET_ATTRIBUTE:
- rv = SSMControlConnection_ProcessGetAttrRequest(ctrl, msg);
- break;
- case SSM_CONSERVE_RESOURCE:
- rv = SSMControlConnection_ProcessConserveRequest(ctrl, msg);
- break;
- case SSM_DESTROY_RESOURCE:
- rv = SSMControlConnection_ProcessDestroyRequest(ctrl, msg);
- break;
- case SSM_DUPLICATE_RESOURCE:
- rv = SSMControlConnection_ProcessDupResourceRequest(ctrl, msg);
- break;
- case SSM_SET_ATTRIBUTE:
- rv = SSMControlConnection_ProcessSetAttrRequest(ctrl, msg);
- break;
- case SSM_CREATE_RESOURCE:
- rv = SSMControlConnection_ProcessCreateRequest(ctrl, msg);
- break;
- case SSM_TLS_STEPUP:
- rv = SSMControlConnection_ProcessTLSRequest(ctrl, msg);
- break;
- case SSM_PROXY_STEPUP:
- rv = SSMControlConnection_ProcessProxyStepUpRequest(ctrl, msg);
- break;
- default:
- SSM_DEBUG("Unknown resource request (%lx).n",
- (msg->type & SSM_SUBTYPE_MASK));
- goto loser;
- }
- goto done;
- loser:
- SSM_DEBUG("ProcessResourceRequest: loser hit, rv = %ld.n", rv);
- if (msg->data)
- {
- PR_Free(msg->data);
- msg->data = NULL;
- msg->len = 0;
- }
- if (rv == PR_SUCCESS) rv = PR_FAILURE;
- done:
- return rv;
- }
- static SSMStatus ssm_verifydetachedthread(SSMControlConnection *ctrl,
- SECItem *msg)
- {
- VerifyDetachedSigRequest request;
- SingleNumMessage reply;
- SSMP7ContentInfo *ci;
- SSMStatus rv;
-
- SSM_DEBUG("Processing Verify Detached Signature request.n");
- if (CMT_DecodeMessage(VerifyDetachedSigRequestTemplate, &request,
- (CMTItem*)msg) != CMTSuccess) {
- rv = SSM_FAILURE;
- } else {
- rv = SSM_SUCCESS;
- }
- msg->data = NULL;
-
- if (rv == SSM_SUCCESS) {
-
- /* Get the content info resource, if it exists. */
- rv = SSMControlConnection_GetResource(ctrl, request.pkcs7ContentID,
- (SSMResource **) &ci);
- }
-
- if (rv == SSM_SUCCESS) {
-
- PR_ASSERT(SSM_IsAKindOf(&ci->super, SSM_RESTYPE_PKCS7_CONTENT_INFO));
- SSM_DEBUG("Found content info (%s at %ld).n",
- SSM_ResourceClassName(&ci->super),
- ci->super.m_id);
- rv = SSMP7ContentInfo_VerifyDetachedSignature(ci,
- (SECCertUsage)request.certUsage,
- (HASH_HashType) request.hashAlgID,
- (PRBool) request.keepCert,
- (PRIntn) request.hash.len,
- (char *)request.hash.data);
- SSM_DEBUG("VerifyDetachedSig rv = %d.n", rv);
- }
- msg->type = (SECItemType) (SSM_OBJECT_SIGNING | SSM_VERIFY_DETACHED_SIG |
- SSM_REPLY_OK_MESSAGE);
- if (rv != SSM_SUCCESS) {
- reply.value = PR_GetError();
- } else {
- reply.value = 0;
- }
- CMT_EncodeMessage(SingleNumMessageTemplate, (CMTItem*)msg, &reply);
- ssmcontrolconnection_send_message_to_client(ctrl, msg);
- return SSM_SUCCESS;
- }
- SSMStatus
- SSMControlConnection_ProcessSigningRequest(SSMControlConnection *ctrl,
- SECItem *msg)
- {
- SSMStatus rv = PR_FAILURE;
- SSMP7ContentInfo *ci;
- SSMResourceID ciRID;
- SEC_PKCS7ContentInfo *cinfo;
- SSMResourceCert *scert, *ecert, *rcert;
- CERTCertificate **rcerts;
- PRInt32 i;
-
- /* Handle a Verify Detached Signature message */
- switch(msg->type & SSM_SUBTYPE_MASK)
- {
- case SSM_VERIFY_DETACHED_SIG:
- {
- if (PK11_IsFIPS()) {
- /*
- * When FIPS is enabled, we want to do the verification on a
- * separate thread so that we don't block the front end
- * thread when the password response comes back
- */
- rv = SSM_ProcessMsgOnThread(ssm_verifydetachedthread,
- ctrl, msg);
- } else {
- rv = ssm_verifydetachedthread(ctrl, msg);
- }
- if (rv == SSM_SUCCESS) {
- return SSM_ERR_DEFER_RESPONSE;
- } else {
- return SSM_FAILURE;
- }
- }
- break;
- case SSM_CREATE_SIGNED:
- {
- CreateSignedRequest request;
- CreateContentInfoReply reply;
- SSM_DEBUG("Processing Create Signed request.n");
- if (CMT_DecodeMessage(CreateSignedRequestTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
- goto create_signed_loser;
- }
- msg->data = NULL;
- rv = SSMControlConnection_GetResource(ctrl, request.scertRID,
- (SSMResource **)&scert);
- if (rv != PR_SUCCESS)
- goto create_signed_loser;
- if (!SSM_IsAKindOf(&scert->super, SSM_RESTYPE_CERTIFICATE))
- goto create_signed_loser;
- rv = SSMControlConnection_GetResource(ctrl, request.ecertRID,
- (SSMResource **)&ecert);
- if (rv == PR_SUCCESS &&
- !SSM_IsAKindOf(&ecert->super, SSM_RESTYPE_CERTIFICATE))
- goto create_signed_loser;
- cinfo = SECMIME_CreateSigned(scert->cert,
- (ecert) ? ecert->cert : NULL,
- ctrl->m_certdb,
- (SECOidTag) request.dig_alg,
- (SECItem*)&request.digest,
- (SECKEYGetPasswordKey) NULL, NULL);
- if (cinfo == NULL)
- goto create_signed_loser;
- rv = SSM_CreateResource(SSM_RESTYPE_PKCS7_CONTENT_INFO, cinfo,
- ctrl, &ciRID, (SSMResource **)&ci);
- if (rv != PR_SUCCESS)
- goto create_signed_loser;
- /* Get a client reference */
- rv = SSM_ClientGetResourceReference(&ci->super, &ciRID);
- if (rv != PR_SUCCESS) {
- goto create_signed_loser;
- }
- msg->type = (SECItemType) (SSM_OBJECT_SIGNING | SSM_CREATE_SIGNED |
- SSM_REPLY_OK_MESSAGE);
- reply.ciRID = ciRID;
- reply.result = PR_SUCCESS;
- reply.errorCode = 0;
- CMT_EncodeMessage(CreateContentInfoReplyTemplate, (CMTItem*)msg, &reply);
- break;
-
- create_signed_loser:
- msg->type = (SECItemType) (SSM_OBJECT_SIGNING | SSM_CREATE_SIGNED |
- SSM_REPLY_ERR_MESSAGE);
- reply.ciRID = 0;
- reply.result = PR_FAILURE;
- reply.errorCode = PORT_GetError();
- CMT_EncodeMessage(CreateContentInfoReplyTemplate, (CMTItem*)msg, &reply);
- /* Return success here so that ProcessMessage doesn't just send
- * back a message with only the rv. That's not interesting return
- * value in this case.
- */
- return PR_SUCCESS;
- }
- case SSM_CREATE_ENCRYPTED:
- {
- CreateEncryptedRequest request;
- CreateContentInfoReply reply;
- SSM_DEBUG("Processing Create Encrypted request.n");
- if (CMT_DecodeMessage(CreateEncryptedRequestTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
- goto create_encrypted_loser;
- }
- msg->data = NULL;
- rv = SSMControlConnection_GetResource(ctrl, request.scertRID,
- (SSMResource **)&scert);
- if (rv != PR_SUCCESS)
- goto create_encrypted_loser;
- if (!SSM_IsAKindOf(&scert->super, SSM_RESTYPE_CERTIFICATE))
- goto create_encrypted_loser;
- rcerts = (CERTCertificate **) PR_Calloc(request.nrcerts+1, sizeof(CERTCertificate *));
- if (rcerts == NULL)
- goto create_encrypted_loser;
- for(i = 0; i < request.nrcerts; i++) {
- rv = SSMControlConnection_GetResource(ctrl, request.rcertRIDs[i],
- (SSMResource **)&rcert);
- if (rv != PR_SUCCESS)
- goto create_encrypted_loser;
- if (!SSM_IsAKindOf(&rcert->super, SSM_RESTYPE_CERTIFICATE))
- goto create_encrypted_loser;
- rcerts[i] = CERT_DupCertificate(rcert->cert);
- SSM_FreeResource(&rcert->super);
- }
- cinfo = SECMIME_CreateEncrypted(scert->cert, rcerts, ctrl->m_certdb,
- NULL, NULL);
- if (cinfo == NULL)
- goto create_encrypted_loser;
- rv = SSM_CreateResource(SSM_RESTYPE_PKCS7_CONTENT_INFO, cinfo,
- ctrl, &ciRID, (SSMResource **)&ci);
- if (rv != PR_SUCCESS)
- goto create_encrypted_loser;
- /* Get a client reference */
- rv = SSM_ClientGetResourceReference(&ci->super, &ciRID);
- if (rv != PR_SUCCESS) {
- goto create_encrypted_loser;
- }
- msg->type = (SECItemType) (SSM_OBJECT_SIGNING | SSM_CREATE_ENCRYPTED |
- SSM_REPLY_OK_MESSAGE);
- reply.ciRID = ciRID;
- reply.result = PR_SUCCESS;
- CMT_EncodeMessage(CreateContentInfoReplyTemplate, (CMTItem*)msg, &reply);
- break;
- /*
- goto create_encrypted_done;
- */
- create_encrypted_loser:
- msg->type = (SECItemType) (SSM_OBJECT_SIGNING | SSM_CREATE_ENCRYPTED |
- SSM_REPLY_ERR_MESSAGE);
- reply.ciRID = 0;
- reply.result = PR_FAILURE;
- CMT_EncodeMessage(CreateContentInfoReplyTemplate, (CMTItem*)msg, &reply);
- /*
- create_encrypted_done:
- */
- if (rcerts != NULL) {
- for(i = 0; i < request.nrcerts; i++) {
- if (rcerts[i] != NULL)
- CERT_DestroyCertificate(rcerts[i]);
- }
- PR_Free(rcerts);
- }
- }
- return PR_FAILURE;
- default:
- {
- SingleNumMessage reply;
- SSM_DEBUG("Unknown signing-related request (%lx).n", msg->type & SSM_SUBTYPE_MASK);
- reply.value = SSM_ERR_BAD_REQUEST;
- CMT_EncodeMessage(SingleNumMessageTemplate, (CMTItem*)msg, &reply);
- }
- break;
- }
- return PR_SUCCESS;
- }
- /*
- * Called by the ReadCtrlThread, processes messages for control connection
- * and places response messages in the queue
- */
- SSMStatus SSMControlConnection_ProcessMessage(SSMControlConnection * ctrl, SECItem * msg)
- {
- SSMStatus rv = PR_FAILURE;
- SECStatus secstatus = SECFailure;
- SSM_DEBUG("SSMControlConnection_ProcessMessage called.n");
- if (!ctrl || !msg)
- {
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
- goto loser;
- }
- if ((msg->type & SSM_CATEGORY_MASK)!= SSM_REQUEST_MESSAGE)
- {
- /* post CARTMAN_ERROR here */
- goto loser;
- }
- /* action depending on the message type and data */
- switch (msg->type & SSM_TYPE_MASK)
- {
- case SSM_HELLO_MESSAGE:
- SSM_DEBUG("we have a Hello request.n");
- rv = SSMControlConnection_ProcessHello(ctrl, msg);
- if (rv != PR_SUCCESS) goto hello_loser;
- break;
- case SSM_DATA_CONNECTION:
- /* differentiate between different data connection types */
- SSM_DEBUG("we have a data connection request.n");
- rv = SSMControlConnection_ProcessDataRequest(ctrl,msg);
- break;
- case SSM_RESOURCE_ACTION:
- rv = SSMControlConnection_ProcessResourceRequest(ctrl,msg);
- break;
- case SSM_CERT_ACTION:
- rv = SSMControlConnection_ProcessCertRequest(ctrl, msg);
- break;
- case SSM_KEYGEN_TAG:
- rv = SSMControlConnection_ProcessKeygenTag(ctrl, msg);
- break;
- case SSM_OBJECT_SIGNING:
- /* Handle an object signing related message */
- rv = SSMControlConnection_ProcessSigningRequest(ctrl,msg);
- break;
- case SSM_PKCS11_ACTION:
- rv = SSMControlConnection_ProcessPKCS11Request(ctrl, msg);
- break;
- case SSM_LOCALIZED_TEXT:
- rv = SSMControlConnection_ProcessLocalizedTextRequest(ctrl, msg);
- break;
- case SSM_CRMF_ACTION:
- rv = SSMControlConnection_ProcessCRMFRequest(ctrl, msg);
- break;
- case SSM_FORMSIGN_ACTION:
- rv = SSMControlConnection_ProcessFormSigningRequest(ctrl, msg);
- break;
- case SSM_SECURITY_ADVISOR:
- rv = SSMControlConnection_ProcessSecurityAdvsiorRequest(ctrl, msg);
- break;
- case SSM_SEC_CFG_ACTION:
- rv = SSMControlConnection_ProcessSecCfgRequest(ctrl, msg);
- break;
- case SSM_PREF_ACTION:
- rv = SSMControlConnection_ProcessPrefs(ctrl, msg);
- break;
- case SSM_MISC_ACTION:
- rv = SSMControlConnection_ProcessMiscRequest(ctrl, msg);
- break;
- default:
- /* just send it back to the client or post an error
- */
- SSM_DEBUG("Unknown request type (%lx).n", msg->type & SSM_TYPE_MASK);
- break;
- }
- if (rv == SSM_ERR_DEFER_RESPONSE) {
- /* If asked to defer response, don't send anything back.
- Just indicate that we did what we needed to do. */
- rv = PR_SUCCESS;
- goto done;
- }
- if (rv != PR_SUCCESS) {
- rv = ssmcontrolconnection_encode_err_reply(msg,rv);
- }
- hello_loser:
- ssmcontrolconnection_send_message_to_client(ctrl, msg);
- SSMControlConnection_RecycleItem(msg);
- msg = NULL; /* so that exception handling doesn't try to free it */
- SSM_DEBUG("SSMControlConnection_ProcessMessage returning rv == %ld.n", rv);
- goto done;
- loser:
- if (rv == PR_SUCCESS) rv = (SSMStatus) secstatus;
- if (rv == PR_SUCCESS) rv = PR_FAILURE;
- SSM_DEBUG("FAILURE in SSMControlConnection_ProcessMessage, rv = %ld.n", rv);
- /* Attempt to pack a generic error message. ### mwelch todo */
-
- done:
- if (msg) SSMControlConnection_RecycleItem(msg);
- return rv;
- }
- SSMStatus
- ssmcontrolconnection_send_message_to_client(SSMControlConnection *ctrl,
- SECItem *msg)
- {
- SSM_DEBUG("queueing reply: type %lx, len %ld.n", msg->type, msg->len);
- SSM_SendQMessage(ctrl->m_controlOutQ,
- SSM_PRIORITY_NORMAL,
- msg->type, msg->len,
- (char *)msg->data, PR_TRUE);
-
- return SSM_SUCCESS;
- }
- SSMStatus
- ssmcontrolconnection_encode_err_reply(SECItem *msg, SSMStatus rv)
- {
- SingleNumMessage reply;
-
- msg->type = (SECItemType) SSM_REPLY_ERR_MESSAGE;
- reply.value = rv;
- CMT_EncodeMessage(SingleNumMessageTemplate, (CMTItem*)msg, &reply);
- if (!msg->data || msg->len == 0){
- rv = SSM_FAILURE;
- } else {
- rv = SSM_SUCCESS;
- }
- return rv;
- }
- SSMStatus
- SSMControlConnection_Authenticate(SSMConnection *arg, char *nonce)
- {
- SSMStatus rv = SSM_FAILURE;
- SSMControlConnection *ctrl = (SSMControlConnection *) arg;
- if (!SSM_IsAKindOf(SSMRESOURCE(ctrl), SSM_RESTYPE_CONTROL_CONNECTION))
- goto loser;
- /* Compare the nonce against what we have. */
- if (!strncmp(ctrl->m_nonce, nonce, strlen(ctrl->m_nonce)))
- rv = SSM_SUCCESS;
-
- loser:
- return rv;
- }
- SSMStatus
- SSMControlConnection_SendUIEvent(SSMControlConnection *conn,
- char *command,
- char *baseRef,
- SSMResource *target, /* can pass NULL */
- char *otherParams /* can pass NULL */,
- CMTItem * clientContext /* can pass NULL */,
- PRBool isModal)
- {
- char *url;
- SECItem event;
- SSMStatus rv = PR_SUCCESS;
- PRUint32 width, height;
- SSMResourceID rid = 0;
- UIEvent reply;
- if (!conn->m_doesUI) {
- return SSM_FAILURE;
- }
- if ((!target) && (conn))
- target = &conn->super.super;
- PR_ASSERT(target);
- if (target)
- rid = ((SSMResource *) target)->m_id;
- /* Construct a URL out of the parameters we've been given. */
- rv = SSM_GenerateURL(conn, command, baseRef, target, otherParams,
- &width, &height, &url);
- if (rv != PR_SUCCESS) {
- goto loser;
- }
- /* Generate the actual message to send to the client. */
- reply.resourceID = rid;
- reply.width = width;
- reply.height = height;
- reply.isModal = isModal;
- reply.url = url;
- if (clientContext) {
- reply.clientContext = *clientContext;
- } else {
- reply.clientContext.len = 0;
- reply.clientContext.data = NULL;
- }
- if (CMT_EncodeMessage(UIEventTemplate, (CMTItem*)&event, &reply) != CMTSuccess) {
- goto loser;
- }
- /* Post the message on the outgoing control channel. */
- rv = SSM_SendQMessage(conn->m_controlOutQ, SSM_PRIORITY_NORMAL,
- SSM_EVENT_MESSAGE | SSM_UI_EVENT,
- (int) event.len, (char *) event.data, PR_FALSE);
- if (rv != PR_SUCCESS) goto loser;
- goto done;
- loser:
- if (rv == PR_SUCCESS) rv = PR_FAILURE;
- done:
- PR_FREEIF(event.data);
- return rv;
- }
- static SSMStatus SSMControlConnection_SavePref(SSMControlConnection* ctrl,
- char* key, char* value,
- PRIntn type)
- {
- SSMStatus rv = PR_FAILURE;
- SetPrefElement item = {0};
- SetPrefListMessage request = {0};
- CMTItem message = {0};
- /* pack the request */
- item.key = PL_strdup(key);
- item.type = type;
- if (value != NULL) {
- item.value = PL_strdup(value);
- }
- else if (type == STRING_PREF) {
- item.value = NULL; /* this is legal */
- }
- else {
- goto loser;
- }
-
- request.length = 1;
- request.list = &item;
- message.type = SSM_EVENT_MESSAGE | SSM_SAVE_PREF_EVENT;
- if (CMT_EncodeMessage(SetPrefListMessageTemplate, &message,
- &request) != CMTSuccess) {
- goto loser;
- }
- /* send the message through the control out queue */
- SSM_SendQMessage(ctrl->m_controlOutQ, SSM_PRIORITY_NORMAL,
- message.type, message.len, (char*)message.data,
- PR_TRUE);
- rv = PR_SUCCESS;
- loser:
- PR_FREEIF(item.key);
- PR_FREEIF(item.value);
- return rv;
- }
- SSMStatus SSMControlConnection_SaveStringPref(SSMControlConnection* ctrl,
- char* key, char* value)
- {
- SSMStatus rv = PR_SUCCESS;
- if ((ctrl == NULL) || (ctrl->m_prefs == NULL) || (key == NULL)) {
- return PR_FAILURE;
- }
- if (PREF_StringPrefChanged(ctrl->m_prefs, key, value)) {
- rv = PREF_SetStringPref(ctrl->m_prefs, key, value);
- if (rv != PR_SUCCESS) {
- return rv;
- }
- rv = SSMControlConnection_SavePref(ctrl, key, value, STRING_PREF);
- }
- return rv;
- }
- SSMStatus SSMControlConnection_SaveBoolPref(SSMControlConnection* ctrl,
- char* key, PRBool value)
- {
- SSMStatus rv = PR_SUCCESS;
- if ((ctrl == NULL) || (ctrl->m_prefs == NULL) || (key == NULL)) {
- return PR_FAILURE;
- }
- if (PREF_BoolPrefChanged(ctrl->m_prefs, key, value)) {
- rv = PREF_SetBoolPref(ctrl->m_prefs, key, value);
- if (rv != PR_SUCCESS) {
- return rv;
- }
- if (value) {
- rv = SSMControlConnection_SavePref(ctrl, key, "true", BOOL_PREF);
- }
- else {
- rv = SSMControlConnection_SavePref(ctrl, key, "false", BOOL_PREF);
- }
- }
- return rv;
- }
- SSMStatus SSMControlConnection_SaveIntPref(SSMControlConnection* ctrl,
- char* key, PRIntn value)
- {
- SSMStatus rv = PR_SUCCESS;
- if ((ctrl == NULL) || (ctrl->m_prefs == NULL) || (key == NULL)) {
- return PR_FAILURE;
- }
- if (PREF_IntPrefChanged(ctrl->m_prefs, key, value)) {
- char* tmp = NULL;
- rv = PREF_SetIntPref(ctrl->m_prefs, key, value);
- if (rv != PR_SUCCESS) {
- return rv;
- }
- tmp = PR_smprintf("%d", value);
- rv = SSMControlConnection_SavePref(ctrl, key, tmp, INT_PREF);
- PR_FREEIF(tmp);
- }
- return rv;
- }
- extern SSMControlConnection * SSM_PARENT_CONN (SSMConnection * x);
- void SSM_LockPasswdTable(SSMConnection * conn)
- {
- SSMControlConnection * control = SSM_PARENT_CONN(conn);
- PR_EnterMonitor(control->m_passwdLock);
- }
- SSMStatus SSM_UnlockPasswdTable(SSMConnection * conn)
- {
- SSMControlConnection * control = SSM_PARENT_CONN(conn);
- return PR_ExitMonitor(control->m_passwdLock);
- }
- SSMStatus SSM_WaitPasswdTable(SSMConnection * conn)
- {
- SSMControlConnection * control = SSM_PARENT_CONN(conn);
- return PR_Wait(control->m_passwdLock, SSM_PASSWORD_WAIT_TIME);
- }
- SSMStatus SSM_NotifyAllPasswdTable(SSMConnection * conn)
- {
- SSMControlConnection * control = SSM_PARENT_CONN(conn);
- return PR_NotifyAll(control->m_passwdLock);
- }
- /* Find the next unallocated resource ID */
- SSMResourceID
- SSMControlConnection_GenerateResourceID(SSMControlConnection *conn)
- {
- void *junk;
- SSMResourceID rid;
- rid = conn->m_lastRID;
- do {
- rid++;
- if(rid > SSM_MAX_RID)
- rid = SSM_BASE_RID;
- SSM_HashFind(conn->m_resourceDB, rid, &junk);
- } while(junk != NULL);
- conn->m_lastRID = rid;
- return rid;
- }
- SSMStatus
- SSM_GetControlConnection(SSMResourceID rid, SSMControlConnection **res)
- {
- return SSM_HashFind(ctrlConnections, rid, (void **)res);
- }
- SSMStatus
- SSMControlConnection_AddResource(SSMResource *res, SSMResourceID rid)
- {
- SSMStatus rv;
- rv = SSM_HashInsert(res->m_connection->m_resourceDB, rid, res);
- if (rv != PR_SUCCESS)
- return rv;
- rv = SSM_HashInsert(res->m_connection->m_resourceIdDB, (SSMHashKey)res,
- (void *)rid);
- return rv;
- }
- SSMStatus
- SSMControlConnection_GetResource(SSMControlConnection * connection,
- SSMResourceID rid, SSMResource **res)
- {
- SSMStatus rv = PR_FAILURE;
- if (connection->m_resourceDB) {
- rv = SSM_HashFind(connection->m_resourceDB, rid, (void **) res);
- if (*res)
- SSM_GetResourceReference(*res);
- }
- return rv;
- }
- SSMStatus
- SSMControlConnection_GetGlobalResourceID(SSMControlConnection * connection,
- SSMResource * res, SSMResourceID *rid)
- {
- return SSM_HashFind(connection->m_resourceIdDB, (SSMHashKey)res,
- (void **) rid);
- }
- SSMStatus
- SSMControlConnection_FormSubmitHandler(SSMResource * res, HTTPRequest * req)
- {
- SSMStatus rv;
- char* tmpStr = NULL;
- SSMSSLDataConnection* conn;
-
- conn = (SSMSSLDataConnection*)res;
- /* make sure you got the right baseRef */
- rv = SSM_HTTPParamValue(req, "baseRef", &tmpStr);
- if (rv != SSM_SUCCESS ||
- PL_strcmp(tmpStr, "windowclose_doclose_js") != 0) {
- goto loser;
- }
- rv = SSM_HTTPCloseAndSleep(req);
- if (rv != SSM_SUCCESS)
- SSM_DEBUG("Errors closing window in FormSubmitHandler: %dn", rv);
-
-
- if (!res->m_formName)
- goto loser;
- if (PL_strcmp(res->m_formName, "choose_cert_by_usage") == 0)
- rv = SSM_ChooseCertUsageHandler(req);
- else if (PL_strcmp(res->m_formName, "set_db_password") == 0)
- rv = SSM_SetDBPasswordHandler(req);
- else /* other cases where this could be used will go here */
- goto loser;
- return rv;
- loser:
- SSM_DEBUG("FormSubmit handler is called with no valid formNamen");
- SSM_NotifyUIEvent(res);
- return SSM_FAILURE;
- }
- typedef struct DefaultCertLookupArgStr {
- char *defaultEmailCert;
- SSMControlConnection *conn;
- PRBool isOwnThread;
- CERTCertificate *cert;
- SSMStatus rv;
- } DefaultCertLookupArg;
- static void
- ssm_lookup_default_cert(void *arg)
- {
- DefaultCertLookupArg *lookupArg = (DefaultCertLookupArg*)arg;
- char *defaultEmailCert = lookupArg->defaultEmailCert;
- SSMControlConnection *conn = lookupArg->conn;
- CERTCertificate *tmp;
- CERTCertificate *cert = lookupArg->cert;
-
- #ifdef DEBUG
- if (lookupArg->isOwnThread) {
- SSM_RegisterThread("email cert lookup", NULL);
- }
- #endif
- SSM_DEBUG("Looking up the cert %s", defaultEmailCert);
- tmp = CERT_FindUserCertByUsage(conn->m_certdb,
- defaultEmailCert,
- certUsageEmailSigner,
- PR_FALSE,
- conn);
- if (tmp == NULL) {
- lookupArg->rv =
- SSMControlConnection_SaveStringPref(conn,
- "security.default_mail_cert",
- cert->nickname);
- } else {
- CERT_DestroyCertificate(tmp);
- lookupArg->rv = SSM_FAILURE;
- }
- SSM_FreeResource(&conn->super.super);
- if (lookupArg->isOwnThread) {
- PR_Free(arg);
- }
- CERT_DestroyCertificate(cert);
- }
- SSMStatus
- SSM_UseAsDefaultEmailIfNoneSet(SSMControlConnection *conn,
- CERTCertificate *cert,
- PRBool onFrontEndThread)
- {
- SSMStatus rv = SSM_FAILURE;
- char *defaultEmailCert;
- if (cert->emailAddr) {
- rv = PREF_GetStringPref(conn->m_prefs, "security.default_mail_cert",
- &defaultEmailCert);
- if (rv != SSM_SUCCESS || defaultEmailCert == NULL) {
- rv = SSMControlConnection_SaveStringPref(conn,
- "security.default_mail_cert",
- cert->nickname);
- } else {
- DefaultCertLookupArg *arg = SSM_ZNEW(DefaultCertLookupArg);
- SSM_GetResourceReference(&conn->super.super);
- PR_ASSERT(arg);
- if (arg == NULL) {
- goto loser;
- }
- arg->defaultEmailCert = defaultEmailCert;
- arg->conn = conn;
- arg->cert = CERT_DupCertificate(cert);
- if (strchr(defaultEmailCert, ':') != NULL && onFrontEndThread) {
- /* ARGH!! The default email cert is on an external token
- * this may require an authentication event, so in order
- * to prevent dead-locking the front end thread, we'll
- * do the look up on a separate thread.
- */
- arg->isOwnThread = PR_TRUE;
- SSM_CreateAndRegisterThread(PR_USER_THREAD, ssm_lookup_default_cert,
- (void *)arg,
- PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
- PR_UNJOINABLE_THREAD, 0);
- /*
- * We don't know if the cert was made default, so we'll return
- * failure in this case.
- */
- rv = SSM_FAILURE;
- } else {
- /*
- * It's in the internal database, so just lookup
- * on this same thread.
- */
- arg->isOwnThread = PR_FALSE;
- ssm_lookup_default_cert((void*)arg);
- rv = arg->rv;
- PR_Free(arg);
- }
- }
- }
- return rv;
- loser:
- return SSM_FAILURE;
- }