📄 ctrlconn.c
字号:
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); /* Destory the obscuring object */ if (conn->m_obscureObj) { SSMObscure_Destroy(conn->m_obscureObj); } /* 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 /* Can't just exit on the Mac, because otherwise the NSPR threads will keep spinning forever. We have to send the app a Quit command so that all the threads will shut down in an orderly way. */ gTheApp->SendAEQuit();#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 (PR_CreateThread(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;}voidSSMControlConnection_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; int orv; /* 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); /* Obscure the message header */ orv = SSMObscure_Send(ctrl->m_obscureObj, &header, sizeof(CMTMessageHeader)); if (orv != 0) { goto loser; } /* 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; } /* Obscure the message body */ orv = SSMObscure_Send(ctrl->m_obscureObj, data, len); if (orv != 0) { 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. PSM 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -