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

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. #include "resource.h"
  34. #include "kgenctxt.h"
  35. #include "nlsutil.h"
  36. #include "base64.h"
  37. #include "pk11func.h"
  38. #include "textgen.h"
  39. #include "minihttp.h"
  40. #include "connect.h"
  41. #include "messages.h"
  42. /* lock to wait for UI */
  43. typedef struct {
  44.   PRMonitor * lock;
  45.   PRBool UIComplete;
  46. } SSMTokenUI_Monitor;
  47. #define SSM_PARENT_CONN(x) &((x)->m_parent->super)
  48. #if 0 /* XXX not used? */
  49. static SSMTokenUI_Monitor  UIlock;
  50. #endif
  51. PK11SlotListElement * PK11_GetNextSafe(PK11SlotList *list, 
  52.                                        PK11SlotListElement *le, 
  53.                                        PRBool restart);
  54. SSMStatus SSMTokenUI_GetNames(SSMResource * res, PRBool start, char ** name);
  55. SSMStatus SSM_SetUserPasswordCommunicator(PK11SlotInfo * slot, 
  56.   SSMKeyGenContext *ct);
  57. CK_MECHANISM_TYPE
  58. SSMKeyGenContext_GenMechToAlgMech(CK_MECHANISM_TYPE mechanism)
  59. {
  60.     CK_MECHANISM_TYPE searchMech;
  61.     /* We are interested in slots based on the ability to perform
  62.        a given algorithm, not on their ability to generate keys usable
  63.        by that algorithm. Therefore, map keygen-specific mechanism tags
  64.        to tags for the corresponding crypto algorthm. */
  65.     switch(mechanism)
  66.     {
  67.     case CKM_RSA_PKCS_KEY_PAIR_GEN:
  68.         searchMech = CKM_RSA_PKCS;
  69.         break;
  70.     case CKM_DSA_KEY_PAIR_GEN:
  71.         searchMech = CKM_DSA;
  72.         break;
  73.     case CKM_RC4_KEY_GEN:
  74.         searchMech = CKM_RC4;
  75.         break;
  76.     case CKM_DH_PKCS_KEY_PAIR_GEN:
  77.         searchMech = CKM_DH_PKCS_DERIVE; /* ### mwelch  is this right? */
  78.         break;
  79.     case CKM_DES_KEY_GEN:
  80.         /* What do we do about DES keygen? Right now, we're just using
  81.            DES_KEY_GEN to look for tokens, because otherwise we'll have
  82.            to search the token list three times. */
  83.     default:
  84.         searchMech = mechanism;
  85.         break;
  86.     }
  87.     return searchMech;
  88. }
  89. SSMStatus SSMKeyGenContext_GetSlot(SSMKeyGenContext * keyctxt,
  90.                                    CK_MECHANISM_TYPE mechanism)
  91. {
  92.     SSMStatus rv = SSM_SUCCESS;
  93.     PK11SlotList * slotList = NULL;
  94.     CK_MECHANISM_TYPE searchMech;
  95.     PRBool reLock;
  96.     searchMech = SSMKeyGenContext_GenMechToAlgMech(mechanism);
  97.     if (!keyctxt->slot || 
  98. !PK11_DoesMechanism(keyctxt->slot, searchMech)) {
  99.       slotList = PK11_GetAllTokens(searchMech, PR_TRUE, PR_TRUE, 
  100.    keyctxt->super.m_connection);
  101.   
  102.       if (!keyctxt) 
  103.         goto loser; 
  104.       if (!slotList || !slotList->head) 
  105.         goto loser;
  106.    
  107.       if (!slotList->head->next) {
  108.         /* only one slot available, just return it */
  109.         keyctxt->slot = slotList->head->slot;
  110. keyctxt->m_slotName = strdup(PK11_GetSlotName(keyctxt->slot));
  111.       } else { 
  112.         char * mech = PR_smprintf("mech=%d&task=keygen&unused=unused", searchMech);
  113. if (keyctxt->m_ctxtype == SSM_OLD_STYLE_KEYGEN) {
  114.   CMTItem msg;
  115.   GenKeyOldStyleTokenRequest request;
  116.   char ** tokenNames = NULL;
  117.   int numtokens = 0;
  118.   PK11SlotListElement * slotElement;
  119.   
  120.   slotElement = PK11_GetFirstSafe(slotList);
  121.   while(slotElement) {
  122.     numtokens++;
  123.     tokenNames = (char **) PR_REALLOC(tokenNames, numtokens*sizeof(*tokenNames));
  124.     tokenNames[numtokens - 1] = strdup(PK11_GetTokenName(slotElement->slot));
  125.     
  126.     slotElement = PK11_GetNextSafe(slotList, slotElement, PR_FALSE);
  127.   }
  128.   
  129.   /* send message to plugin: use native UI for select token dialog */
  130.   SSM_LockUIEvent(&keyctxt->super); 
  131.   request.rid = keyctxt->super.m_id;
  132.   request.numtokens = numtokens;
  133.   request.tokenNames = tokenNames;
  134.   
  135.   msg.type = SSM_REPLY_OK_MESSAGE | SSM_KEYGEN_TAG | SSM_KEYGEN_TOKEN;
  136.   if (CMT_EncodeMessage(GenKeyOldStyleTokenRequestTemplate, &msg, 
  137. &request) !=  CMTSuccess) 
  138.     goto loser;  
  139.   
  140.   SSM_SendQMessage(keyctxt->super.m_connection->m_controlOutQ, 
  141.    SSM_PRIORITY_NORMAL, 
  142.    msg.type, msg.len, (char *)msg.data, PR_TRUE);
  143.   
  144.   SSM_WaitUIEvent(&keyctxt->super, PR_INTERVAL_NO_TIMEOUT);
  145.   SSM_UnlockUIEvent(&keyctxt->super);
  146.   keyctxt->slot = (PK11SlotInfo*)keyctxt->super.m_uiData;
  147. } else /* post UI event */ {
  148.   /* post a UI event to ask user for the slot */
  149.   SSM_LockUIEvent(&keyctxt->super);
  150.   
  151.   /* Release the lock on the resource temporarily while
  152.    * the UI happens.
  153.    */
  154.   rv = SSM_UnlockResource(&keyctxt->super);
  155.   reLock = (rv == PR_SUCCESS) ? PR_TRUE : PR_FALSE;
  156.   rv = SSMControlConnection_SendUIEvent(keyctxt->super.m_connection,
  157. "get",
  158. "select_token",
  159. (SSMResource *)keyctxt,
  160. mech,
  161. &((SSMResource*)keyctxt)->m_clientContext,
  162. PR_TRUE);
  163.   if (rv != SSM_SUCCESS) {
  164.     if (keyctxt->super.m_UILock != NULL) {
  165.       PR_ExitMonitor(keyctxt->super.m_UILock);
  166.     }
  167.     goto loser;
  168.   }
  169.   /* wait until the UI dialog box is done */
  170.   SSM_WaitUIEvent(&keyctxt->super, PR_INTERVAL_NO_TIMEOUT);
  171.   if (reLock) {
  172.   /* Get the lock back. */
  173.     SSM_LockResource(&keyctxt->super);
  174.   }
  175.   SSM_UnlockUIEvent(&keyctxt->super);
  176.   PR_Free(mech);
  177.   /* ok, the return from UI is processed in command handler */
  178.   /* Make sure password prompt doesn't get sucked away by
  179.    * the disappearing dialog
  180.    */
  181.   PR_Sleep(PR_TicksPerSecond());
  182.   keyctxt->slot = (PK11SlotInfo*)keyctxt->super.m_uiData;
  183.   if (keyctxt->slot != NULL) {
  184.     keyctxt->m_slotName = strdup(PK11_GetSlotName(keyctxt->slot));
  185.   }
  186. } /* end of post UI event */
  187.       } /* end of multiple tokens available */
  188.       /* Get a slot reference so it doesn't disappear */
  189.       if (keyctxt->slot) {
  190. PK11_ReferenceSlot(keyctxt->slot);
  191.       }
  192.     }
  193.     /* we should have a slot now */
  194.     if (keyctxt->slot == NULL) 
  195.       goto loser;
  196.     
  197.     /* Before we authenticate, make sure the user initialized the DB. */
  198.     if (PK11_NeedUserInit(keyctxt->slot)) 
  199.       rv = SSM_SetUserPasswordCommunicator(keyctxt->slot, keyctxt);
  200.     rv = PK11_Authenticate(keyctxt->slot, PR_FALSE, keyctxt);
  201.     if (rv != SECSuccess) {
  202.         goto loser;
  203.     }
  204.     goto done;
  205. loser:
  206.     
  207.     if (rv == SSM_SUCCESS)
  208.         rv = SSM_FAILURE;
  209.     keyctxt->slot = NULL; 
  210. done: 
  211.     if (slotList) 
  212.         PK11_FreeSlotList(slotList);
  213.    
  214.     return rv;
  215. }
  216. /* send a message to communicator to display UI for setting slot password */
  217. SSMStatus
  218. SSM_SetUserPasswordCommunicator(PK11SlotInfo * slot, 
  219.                                 SSMKeyGenContext *ct)
  220. {
  221.   CMTItem msg;
  222.   GenKeyOldStylePasswordRequest passwdmsg;
  223.   SSMStatus rv = SSM_FAILURE;
  224.   PRBool reLock = PR_FALSE;
  225.   
  226.   PR_ASSERT(SSM_IsAKindOf(&ct->super, SSM_RESTYPE_KEYGEN_CONTEXT));
  227.   switch (ct->m_ctxtype) {
  228.   case (SSM_CRMF_KEYGEN):
  229.     rv = SSM_SetUserPassword(slot, &ct->super);   
  230.     break;
  231.   case (SSM_OLD_STYLE_KEYGEN):
  232.     SSM_LockUIEvent(&ct->super);
  233.     passwdmsg.rid = ct->super.m_id;
  234.     passwdmsg.tokenName = PK11_GetTokenName(slot);
  235.     passwdmsg.internal = (CMBool) PK11_IsInternal(slot);
  236.     passwdmsg.minpwdlen = PR_MAX(SSM_MIN_PWD_LEN,PK11_GetMinimumPwdLength(slot));
  237.     passwdmsg.maxpwdlen = slot->maxPassword;
  238.     msg.type = SSM_REPLY_OK_MESSAGE | SSM_KEYGEN_TAG | SSM_KEYGEN_PASSWORD;
  239.     if (CMT_EncodeMessage(GenKeyOldStylePasswordRequestTemplate, &msg, 
  240.   &passwdmsg) != CMTSuccess)
  241.       goto loser;
  242.     rv = SSM_SendQMessage(ct->super.m_connection->m_controlOutQ,
  243.   SSM_PRIORITY_NORMAL,
  244.   msg.type, msg.len, (char *)msg.data, PR_TRUE);
  245.     if (rv != SSM_SUCCESS) 
  246.       SSM_UnlockUIEvent(&ct->super);
  247.     else 
  248.       SSM_WaitUIEvent(&ct->super, PR_INTERVAL_NO_TIMEOUT); 
  249.    break;
  250.   default:
  251.     SSM_DEBUG("Unknown keygen type!n");
  252.     goto loser;
  253.   }
  254.   
  255. loser:
  256.   if (rv != SSM_SUCCESS)
  257.     SSM_DEBUG("SetUserPasswordComm: can't send password request msg!n");
  258.   return rv;
  259. }
  260. SSMStatus
  261. ssmpkcs11_convert_slot(SSMTextGenContext *cx, 
  262.                        PRInt32 slotIndex,
  263.                        PK11SlotInfo *slot,
  264.                        char *fmt,
  265.                        PRBool accumulate);
  266. SSMStatus SSMTokenUI_KeywordHandler(SSMTextGenContext * cx)
  267. {
  268.     SSMResource *ctxt = NULL;
  269.     SSMStatus rv;
  270.     char * tempUStr = NULL;
  271.     char * wrapper = NULL;
  272.     CK_MECHANISM_TYPE searchMech;
  273.     char *searchMechStr;
  274.     static PK11SlotList * slotList;
  275.     static PK11SlotListElement * slotElement;
  276.     PRIntn i = 0;
  277.  
  278.     if (!cx || !cx->m_request || !cx->m_params || !cx->m_result)
  279.         goto loser;
  280.     ctxt = SSMTextGen_GetTargetObject(cx);
  281.     
  282.     /* Get the wrapper string from the properties file. */
  283.     wrapper = (char *) SSM_At(cx->m_params, 0);
  284.     rv = SSM_GetAndExpandTextKeyedByString(cx, wrapper, &tempUStr);
  285.     if (rv != PR_SUCCESS)
  286.         goto loser;
  287.     rv = SSM_HTTPParamValue(cx->m_request, "action", &searchMechStr);
  288.     if (rv != SSM_SUCCESS) 
  289.         goto loser;
  290.     searchMech = atoi(searchMechStr);
  291.     slotList = PK11_GetAllTokens(searchMech, PR_TRUE, PR_TRUE, 
  292.  ctxt->m_connection);
  293.     if (!slotList) 
  294.         goto loser;
  295.     slotElement = PK11_GetFirstSafe(slotList);
  296.     while(slotElement)
  297.     {
  298.         rv = ssmpkcs11_convert_slot(cx, i++, slotElement->slot, tempUStr, 
  299.     PR_TRUE);
  300.         if (rv != SSM_SUCCESS)
  301.             goto loser;
  302.         slotElement = PK11_GetNextSafe(slotList, slotElement, PR_FALSE); 
  303.     }
  304.     rv = SSM_SUCCESS;
  305.     goto done;
  306. loser: 
  307.     SSM_DEBUG("Errors creating token list!n");
  308.     SSMTextGen_UTF8StringClear(&cx->m_result);
  309.     if (rv==SSM_SUCCESS) 
  310.         rv = SSM_FAILURE;
  311. done:
  312.     PR_FREEIF(tempUStr);
  313.     return rv;
  314. }
  315. PK11SlotInfo *
  316. SSMPKCS11_FindSlotByID(SECMODModuleID modID,
  317.                        CK_SLOT_ID slotID);
  318. SSMStatus
  319. figure_out_token_selection(char *str, 
  320.                            SECMODModuleID *modID,
  321.                            CK_SLOT_ID *slotID)
  322. {
  323.     char *walk;
  324.     walk = PL_strchr(str, '+');
  325.     if (!walk)
  326.         return SSM_FAILURE;
  327.     *walk++ = '';
  328.     *modID = atoi(str);
  329.     *slotID = atoi(walk);
  330.     return SSM_SUCCESS;
  331. }
  332. SSMStatus 
  333. SSMTokenUI_CommandHandler(HTTPRequest * req)
  334. {
  335.     SSMStatus rv;
  336.     char * tokenName = NULL;
  337.     SSMResource *res;
  338.     SECMODModuleID modID;
  339.     CK_SLOT_ID slotID;
  340.     PK11SlotInfo *slot;
  341.     if (!req->target) 
  342.         goto loser;
  343.     res = req->target;
  344.     res->m_uiData = NULL;
  345.     /* check the parameter values */
  346.     if (res->m_buttonType == SSM_BUTTON_CANCEL)
  347.     {
  348. slot = NULL;
  349.         goto done; /* return the closing javascript */
  350.     }
  351.     /* Determine what token the user selected. */
  352.     rv = SSM_HTTPParamValue(req, "token", &tokenName);
  353.     if (rv != SSM_SUCCESS)
  354.     {
  355.         req->httprv = HTTP_BAD_REQUEST;
  356.         goto loser;
  357.     }
  358.     rv = figure_out_token_selection(tokenName, &modID, &slotID);
  359.     if (rv != SSM_SUCCESS)
  360.         goto loser;
  361.     slot = SSMPKCS11_FindSlotByID(modID, slotID);
  362.     if (!slot)
  363.         goto loser;
  364. done:
  365.     /* Tell the keygen context what token was selected. */
  366.     res->m_uiData = slot;
  367.     SSM_NotifyUIEvent(res);
  368.     /* Done with our part, so pass back whatever the dialog wants in
  369.        order to close the window. */
  370.     return SSM_HTTPCloseAndSleep(req);
  371. loser:
  372.     res->m_uiData = NULL;
  373.     SSM_NotifyUIEvent(res);
  374.     SSM_DEBUG("Can't get input from token_select dialog!n");
  375.     return SSM_FAILURE;
  376. }