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

CA认证

开发平台:

WINDOWS

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /*
  3.  * The contents of this file are subject to the Mozilla Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/MPL/
  7.  * 
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  * 
  13.  * The Original Code is the Netscape security libraries.
  14.  * 
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation.  Portions created by Netscape are 
  17.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  18.  * Rights Reserved.
  19.  * 
  20.  * Contributor(s):
  21.  * 
  22.  * Alternatively, the contents of this file may be used under the
  23.  * terms of the GNU General Public License Version 2 or later (the
  24.  * "GPL"), in which case the provisions of the GPL are applicable 
  25.  * instead of those above.  If you wish to allow use of your 
  26.  * version of this file only under the terms of the GPL and not to
  27.  * allow others to use your version of this file under the MPL,
  28.  * indicate your decision by deleting the provisions above and
  29.  * replace them with the notice and other provisions required by
  30.  * the GPL.  If you do not delete the provisions above, a recipient
  31.  * may use your version of this file under either the MPL or the
  32.  * GPL.
  33.  */
  34. #include "pkcs11ui.h"
  35. #include "pkcs11.h"
  36. #include "pk11func.h"
  37. #include "plstr.h"
  38. #include "secmod.h"
  39. #include "secmodti.h"
  40. #include "minihttp.h"
  41. #include "textgen.h"
  42. /* Utility */
  43. PK11SlotInfo *
  44. SSMPKCS11_FindSlotByID(SECMODModuleID modID,
  45.                        CK_SLOT_ID slotID)
  46. {
  47.     SECMODModule *mod = NULL;
  48.     PRIntn i;
  49.     mod = SECMOD_FindModuleByID(modID);
  50.     if (mod)
  51.     {
  52.         for(i=0;i<mod->slotCount;i++)
  53.         {
  54.             if (mod->slots[i]->slotID == slotID)
  55.                 return mod->slots[i];
  56.         }
  57.     }
  58.     return NULL;
  59. }
  60. /*
  61.   --------------------------------------------------------- 
  62.   PKCS11 module processing (list, add, delete)
  63.   --------------------------------------------------------- 
  64.  */
  65. SSMStatus
  66. ssmpkcs11_convert_module(SSMTextGenContext *cx, 
  67.                          PRInt32 modIndex,
  68.                          SECMODModule *mod, 
  69.                          char *fmt)
  70. {
  71.     char *dllName = NULL;
  72.     char *tempStr = NULL;
  73.     char *lib_ch = NULL;
  74.     CK_INFO modInfo;
  75.     SSMStatus rv = SSM_FAILURE;
  76.     SECStatus srv;
  77.     /* 65? Why 65??? It's what's was used in the original UI. */
  78.     char buf[65];
  79.     char buf2[65];
  80.     srv = PK11_GetModInfo(mod, &modInfo);
  81.     if (srv != SECSuccess)
  82.         goto loser;
  83.     /* we provide the space in (buf), so we don't deallocate lib_ch */
  84.     lib_ch = PK11_MakeString(NULL,buf2,(char *)modInfo.libraryDescription,
  85.                              sizeof(modInfo.libraryDescription));
  86.     if (mod->dllName)
  87.     {
  88.         char *cursor, *newString;
  89.         int numSlashes = 0, newLen, i, j, oldLen;
  90.         dllName = mod->dllName;
  91.         /*
  92.          * Now we need to escape the '' characters so the string shows
  93.          * up correctly in the UI.
  94.          */
  95.         /* First count them to see if we even need to re-allocate*/
  96.         cursor = dllName;
  97.         while ((cursor = PL_strchr(cursor, '\')) != NULL) {
  98.             numSlashes++;
  99.             cursor++;
  100.         }
  101.         if (numSlashes > 0) {
  102.             oldLen = PL_strlen(dllName);
  103.             newLen = oldLen + numSlashes + 1;
  104.             newString = SSM_NEW_ARRAY(char, newLen);
  105.             /*
  106.              * If we can't allocate a new buffer, then let's just display
  107.              * the original string.  That's better than not displaying
  108.              * anything.
  109.              */
  110.             if (newString != NULL) {
  111.                 for (i=0, j=0; i<oldLen+1; i++,j++){
  112.                     newString[j] = dllName[i];
  113.                     if (newString[j] == '\'){
  114.                         newString[j+1] = '\';
  115.                         j++;
  116.                     }
  117.                 }
  118.                 dllName = newString;
  119.             }
  120.         }
  121.     }
  122.     else
  123.     {
  124.         rv = SSM_GetAndExpandText(cx, "text_pk11_no_dll", &dllName);
  125.         if (rv != SSM_SUCCESS)
  126.             goto loser;
  127.     }
  128.     PR_snprintf(buf, sizeof(buf), "%d.%d",
  129.                 modInfo.libraryVersion.major, modInfo.libraryVersion.minor);
  130.     tempStr = PR_smprintf(fmt, modIndex, (long)mod->moduleID, lib_ch,
  131.                           mod->commonName, dllName, buf);
  132.     if (tempStr == NULL) {
  133.         rv = SSM_FAILURE;
  134.         goto loser;
  135.     }
  136.     rv = SSM_ConcatenateUTF8String(&cx->m_result, tempStr);
  137.  loser:
  138.     if (dllName && dllName != mod->dllName)
  139.         PR_Free(dllName);
  140.     PR_FREEIF (tempStr);
  141.     return rv;
  142. }
  143. /*
  144.   PKCS11 module list keyword handler.
  145.   Syntax: {_pk11modules <wrapper_key>}
  146. */
  147. SSMStatus
  148. SSM_PKCS11ModulesKeywordHandler(SSMTextGenContext *cx)
  149. {
  150.     SSMStatus rv = SSM_SUCCESS;
  151.     char *wrapperKey = NULL;
  152.     char *wrapperStr = NULL;
  153.     SECMODModuleList *modList = SECMOD_GetDefaultModuleList();
  154.     SECMODModuleList *modWalk = NULL;
  155.     SECMODListLock *modLock = SECMOD_GetDefaultModuleListLock();
  156.     PRBool gotLock = PR_FALSE; /* indicates whether we should release at end */
  157.     PRInt32 i=0;
  158.     /* Check for parameter validity */
  159.     PR_ASSERT(cx);
  160.     PR_ASSERT(cx->m_request);
  161.     PR_ASSERT(cx->m_params);
  162.     PR_ASSERT(cx->m_result);
  163.     if (!cx || !cx->m_request || !cx->m_params || !cx->m_result)
  164.     {
  165.         rv = PR_INVALID_ARGUMENT_ERROR;
  166.         goto real_loser; /* really bail here */
  167.     }
  168.     if (SSM_Count(cx->m_params) != 1)
  169.     {
  170.         SSM_HTTPReportSpecificError(cx->m_request, "_certList: "
  171.                                     "Incorrect number of parameters "
  172.                                     "(%d supplied, 1 needed).n",
  173.                                     SSM_Count(cx->m_params));
  174.         goto user_loser;
  175.     }
  176.     /* Convert parameters to something we can use in finding certs. */
  177.     wrapperKey = (char *) SSM_At(cx->m_params, 0);
  178.     PR_ASSERT(wrapperKey);
  179.     /* Get the wrapper text. */
  180.     rv = SSM_GetAndExpandTextKeyedByString(cx, wrapperKey, &wrapperStr);
  181.     if (rv != SSM_SUCCESS)
  182.         goto real_loser; /* error string set by the called function */
  183.     /* Iterate over the PKCS11 modules. Put relevant info from each
  184.        into its own copy of the wrapper text. */
  185.     SECMOD_GetReadLock(modLock);
  186.     gotLock = PR_TRUE;
  187.     modWalk = modList;
  188.     while (modWalk)
  189.     {
  190.         rv = ssmpkcs11_convert_module(cx, i++, modWalk->module, wrapperStr);
  191.         modWalk = modWalk->next;
  192.     }
  193.     goto done;
  194. user_loser:
  195.     /* If we reach this point, something in the input is wrong, but we
  196.        can still send something back to the client to indicate that a
  197.        problem has occurred. */
  198.     /* If we can't do what we're about to do, really bail. */
  199.     if (!cx->m_request || !cx->m_request->errormsg)
  200.         goto real_loser;
  201.     /* Clear the string we were accumulating. */
  202.     SSMTextGen_UTF8StringClear(&cx->m_result);
  203.     /* Use the result string given to us to explain what happened. */
  204.     SSM_ConcatenateUTF8String(&cx->m_result, cx->m_request->errormsg);
  205.     /* Clear the result string, since we're sending this inline */
  206.     SSMTextGen_UTF8StringClear(&cx->m_request->errormsg);
  207.     goto done;
  208. real_loser:
  209.     /* If we reach this point, then we are so screwed that we cannot
  210.        send anything vaguely normal back to the client. Bail. */
  211.     if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
  212. done:
  213.     PR_FREEIF(wrapperStr);
  214.     if (modLock && gotLock)
  215.         SECMOD_ReleaseReadLock(modLock);
  216.     return rv;
  217. }
  218. /*
  219.   --------------------------------------------------------- 
  220.   PKCS11 slot code
  221.   --------------------------------------------------------- 
  222.  */
  223. enum
  224. {
  225.     SSM_PK11STR_SLOT_LOGGED_IN = (long) 0,
  226.     SSM_PK11STR_SLOT_NOT_LOGGED_IN,
  227.     SSM_PK11STR_SLOT_NO_LOGIN_REQUIRED,
  228.     SSM_PK11STR_SLOT_NOT_PRESENT,
  229.     SSM_PK11STR_SLOT_UNINITIALIZED,
  230.     SSM_PK11STR_SLOT_DISABLED,
  231.     SSM_PK11STR_SLOT_READY,
  232.     SSM_PK11STR_SLOT_STRING_COUNT
  233. };
  234. static char *slotStringKeys[] =
  235. {
  236.     "text_pk11_slot_logged_in",
  237.     "text_pk11_slot_not_logged_in",
  238.     "text_pk11_slot_no_login_required",
  239.     "text_pk11_slot_not_present",
  240.     "text_pk11_slot_uninitialized",
  241.     "text_pk11_slot_disabled",
  242.     "text_pk11_slot_ready"
  243. };
  244. static char **slotStrings = NULL;
  245. void
  246. ssmpkcs11_initialize_slot_labels(SSMTextGenContext *cx)
  247. {
  248.     SSMStatus rv = SSM_SUCCESS;
  249.     PRIntn i;
  250.     slotStrings = (char **) PR_Calloc(SSM_PK11STR_SLOT_STRING_COUNT + 1,
  251.                             sizeof(char**));
  252.     PR_ASSERT(slotStrings);
  253.     for(i=0;i<SSM_PK11STR_SLOT_STRING_COUNT;i++)
  254.     {
  255.         rv = SSM_FindUTF8StringInBundles(cx, slotStringKeys[i],
  256.                                          &slotStrings[i]);
  257.         PR_ASSERT(rv == SSM_SUCCESS);
  258.     }
  259. }
  260. SSMStatus
  261. ssmpkcs11_convert_slot(SSMTextGenContext *cx, 
  262.                        PRInt32 slotIndex,
  263.                        PK11SlotInfo *slot,
  264.                        char *fmt,
  265.                        PRBool accumulate) /* accumulate in cx->m_result? */
  266. {
  267.     char *name = NULL;
  268.     char *statusStr = NULL;
  269.     char *serial = NULL;
  270.     char *version = NULL;
  271.     char *tempStr = NULL;
  272.     long status, slotID = 0, moduleID = 0;
  273.     CK_TOKEN_INFO tokenInfo;
  274.     SSMStatus rv = SSM_FAILURE;
  275.     SECStatus srv = SECSuccess;
  276.     /* 65? Why 65??? It's what's was used in the original UI. */
  277.     char buf[65];
  278.     char empty[1] = { '' } ;
  279.     if (!slotStrings)
  280.         ssmpkcs11_initialize_slot_labels(cx);
  281.     /* If we have a NULL slot, return blank information. */
  282.     if (!slot)
  283.     {
  284.         name      = empty;
  285.         statusStr = empty;
  286.         serial    = empty;
  287.         version   = empty;
  288.         slotID    = 0;
  289.         goto show_stuff;
  290.     }
  291.     /* Get the slot name. Either the default name or the name of the token
  292.        in the slot will be used. */
  293.     if (PK11_IsPresent(slot))
  294.         name = PK11_GetTokenName(slot);
  295.     else
  296.         name = PK11_GetSlotName(slot);
  297.     /* Report the status of the slot. */
  298.     if (PK11_IsDisabled(slot))
  299.         status = SSM_PK11STR_SLOT_DISABLED;
  300.     else if (!PK11_IsPresent(slot))
  301.         status = SSM_PK11STR_SLOT_NOT_PRESENT;
  302.     else if (PK11_NeedLogin(slot) && PK11_NeedUserInit(slot))
  303.         status = SSM_PK11STR_SLOT_UNINITIALIZED;
  304.     else if (PK11_NeedLogin(slot) && !PK11_IsLoggedIn(slot, NULL))
  305.         status = SSM_PK11STR_SLOT_NOT_LOGGED_IN;
  306.     else if (PK11_NeedLogin(slot))
  307.         status = SSM_PK11STR_SLOT_LOGGED_IN;
  308.     else
  309.         status = SSM_PK11STR_SLOT_READY;
  310.     statusStr = slotStrings[status];
  311.     /* Get the serial number and version. */
  312.     /* This is how the old UI determines if there's a token in, so... */
  313.     if (PK11_IsPresent(slot))
  314.         srv = PK11_GetTokenInfo(slot, &tokenInfo);
  315.     
  316.     if (PK11_IsPresent(slot) && (srv == SECSuccess))
  317.     {
  318.         /* Get serial number and version from the token info. */
  319.         serial = PK11_MakeString(NULL, NULL, (char*)tokenInfo.serialNumber,
  320.                                  sizeof(tokenInfo.serialNumber));
  321.         PR_snprintf(buf, sizeof(buf), "%d.%d",
  322.                     tokenInfo.firmwareVersion.major, 
  323.                     tokenInfo.firmwareVersion.minor);
  324.         version = buf;
  325.     }
  326.     else
  327.     {
  328.         /* Get serial number and version from the slot info. */
  329.         CK_SLOT_INFO slotInfo;
  330.         srv = PK11_GetSlotInfo(slot, &slotInfo);
  331.         if (srv != SECSuccess)
  332.             goto loser;
  333.         serial = empty;
  334.         PR_snprintf(buf, sizeof(buf), "%d.%d",
  335.                     slotInfo.firmwareVersion.major, 
  336.                     slotInfo.firmwareVersion.minor);
  337.         version = buf;
  338.     }
  339.     slotID = (long) (slot->slotID);
  340.     moduleID = (long) (slot->module->moduleID);
  341.  show_stuff:
  342.     tempStr = PR_smprintf(fmt, slotIndex, slotID, moduleID, name,
  343.                           statusStr, serial, version);
  344.     if (accumulate)
  345.     {
  346.         rv = SSM_ConcatenateUTF8String(&cx->m_result, tempStr);
  347.         if (rv != SSM_SUCCESS) {
  348.             goto loser;
  349.         }
  350.     }
  351.     else
  352.         rv = SSM_HTTPSendUTF8String(cx->m_request, tempStr);
  353.  loser:
  354.     /* The data that isn't freed is either because it's a member of the 
  355.      * data in a structure of the PK11 libraries or its a static local 
  356.      * variable.
  357.      */
  358.     if (serial && serial != empty)
  359.         PR_Free(serial);
  360.     PR_FREEIF(tempStr);
  361.     return rv;
  362. }
  363. /*
  364.   PKCS11 slot list keyword handler.
  365.   Syntax: {_pk11slots <moduleID>,<wrapper_key>}
  366. */
  367. SSMStatus
  368. SSM_PKCS11SlotsKeywordHandler(SSMTextGenContext *cx)
  369. {
  370.     SSMStatus rv = SSM_SUCCESS;
  371.     SECMODModule *module = NULL;
  372.     char *wrapperKey = NULL;
  373.     char *moduleIDStr = NULL;
  374.     long moduleID;
  375.     char *wrapperStr = NULL;
  376.     PRInt32 i=0;
  377.     /* Check for parameter validity */
  378.     PR_ASSERT(cx);
  379.     PR_ASSERT(cx->m_request);
  380.     PR_ASSERT(cx->m_params);
  381.     PR_ASSERT(cx->m_result);
  382.     if (!cx || !cx->m_request || !cx->m_params || !cx->m_result)
  383.     {
  384.         rv = PR_INVALID_ARGUMENT_ERROR;
  385.         goto real_loser; /* really bail here */
  386.     }
  387.     if (SSM_Count(cx->m_params) != 2)
  388.     {
  389.         SSM_HTTPReportSpecificError(cx->m_request, "_certList: "
  390.                                     "Incorrect number of parameters "
  391.                                     "(%d supplied, 2 needed).n",
  392.                                     SSM_Count(cx->m_params));
  393.         goto user_loser;
  394.     }
  395.     /* Convert parameters to something we can use in finding certs. */
  396.     moduleIDStr = (char *) SSM_At(cx->m_params, 0);
  397.     PR_ASSERT(moduleIDStr);
  398.     wrapperKey = (char *) SSM_At(cx->m_params, 1);
  399.     PR_ASSERT(wrapperKey);
  400.     /* Find the module we're looking for based on the module ID. */
  401.     module = SECMOD_FindModuleByID((SECMODModuleID) moduleID);
  402.     if (!module)
  403.         goto user_loser;
  404.     /* Get the wrapper text. */
  405.     rv = SSM_GetAndExpandTextKeyedByString(cx, wrapperKey, &wrapperStr);
  406.     if (rv != SSM_SUCCESS)
  407.         goto real_loser; /* error string set by the called function */
  408.     /* Iterate over the slots from this module. Put relevant info from each
  409.        into its own copy of the wrapper text. */
  410.     for(i=0;i<module->slotCount;i++)
  411.     {
  412.         rv = ssmpkcs11_convert_slot(cx, i, module->slots[i], wrapperStr, 
  413.                                     PR_TRUE);
  414.         if (rv != SSM_SUCCESS)
  415.             goto user_loser;
  416.     }
  417.     goto done;
  418. user_loser:
  419.     /* If we reach this point, something in the input is wrong, but we
  420.        can still send something back to the client to indicate that a
  421.        problem has occurred. */
  422.     /* If we can't do what we're about to do, really bail. */
  423.     if (!cx->m_request || !cx->m_request->errormsg)
  424.         goto real_loser;
  425.     /* Clear the string we were accumulating. */
  426.     SSMTextGen_UTF8StringClear(&cx->m_result);
  427.     /* Use the result string given to us to explain what happened. */
  428.     SSM_ConcatenateUTF8String(&cx->m_result, cx->m_request->errormsg);
  429.     /* Clear the result string, since we're sending this inline */
  430.     SSMTextGen_UTF8StringClear(&cx->m_request->errormsg);
  431.     goto done;
  432. real_loser:
  433.     /* If we reach this point, then we are so screwed that we cannot
  434.        send anything vaguely normal back to the client. Bail. */
  435.     if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
  436. done:
  437.     PR_FREEIF(wrapperStr);
  438.     if (module)
  439.         SECMOD_DestroyModule(module);
  440.     return rv;
  441. }
  442. SSMStatus
  443. ssm_pkcs11_chuck_property(SSMTextGenContext *cx, char *propName)
  444. {
  445.     char *text = NULL;
  446.     SSMStatus rv;
  447.     rv = SSM_GetAndExpandText(cx, propName, &text);
  448.     if (rv != SSM_SUCCESS)
  449.         goto loser;
  450.     rv = SSM_HTTPSendUTF8String(cx->m_request, text);
  451.     
  452.  loser:
  453.     PR_FREEIF(text);
  454.     SSMTextGen_UTF8StringClear(&cx->m_result);
  455.     return rv;
  456. }
  457. /* PKCS11ShowSlots?module=<moduleID> */
  458. SSMStatus 
  459. SSM_ShowSlotsCommandHandler(HTTPRequest *req)
  460. {
  461.     SSMTextGenContext *cx = NULL;
  462.     char *tmpl = NULL, *type = NULL;
  463.     char *nomod_ch = NULL;
  464.     char *modID_ch = NULL;
  465.     long moduleID;
  466.     SECMODModule *module = NULL;
  467.     PRIntn i;
  468.     SSMStatus rv;
  469.     /* If we have a "no_module" parameter, then there 
  470.        is no module for which to load slots. */
  471.     rv = SSM_HTTPParamValue(req, "no_module", &nomod_ch);
  472.     if (rv == SSM_SUCCESS)
  473.         goto display_stuff;
  474.     rv = SSM_HTTPParamValue(req, "module", &modID_ch);
  475.     if (rv != SSM_SUCCESS)
  476.         goto display_stuff;
  477.     if (modID_ch)
  478.     {
  479.         /* Convert the module ID into a real module ID. */
  480.         PR_sscanf(modID_ch, "%ld", &moduleID);
  481.         
  482.         /* Find the module we're looking for based on the module ID. */
  483.         module = SECMOD_FindModuleByID((SECMODModuleID) moduleID);
  484.         if (!module)
  485.             goto loser;
  486.     }
  487.  display_stuff:
  488.     /* Make a new top-level text gen context to chuck text back. */
  489.     rv = SSMTextGen_NewTopLevelContext(req, &cx);
  490.     if (rv != SSM_SUCCESS)
  491.         goto loser;
  492.     rv = SSM_GetAndExpandText(cx, "adv_modules_slotlist_type", &type);
  493.     if (rv != SSM_SUCCESS)
  494.         goto loser;
  495.     rv = SSM_HTTPSendOKHeader(req, NULL, type);
  496.     if (rv != SSM_SUCCESS)
  497.         goto loser;
  498.     /* Chuck out part 1. */
  499.     rv = ssm_pkcs11_chuck_property(cx, "adv_modules_slotlist_part1");
  500.     if (rv != SSM_SUCCESS)
  501.         goto loser;
  502.     /* Get the template for the JS slot list. */
  503.     rv = SSM_GetAndExpandText(cx, "adv_modules_slotlist_js_template", &tmpl);
  504.     if (rv != SSM_SUCCESS)
  505.         goto loser;
  506.     /* Iterate over the slots from this module. Put relevant info from each
  507.        into its own copy of the wrapper text. */
  508.     if (module)
  509.     {
  510.         for(i=0;i<module->slotCount;i++)
  511.         {
  512.             rv = ssmpkcs11_convert_slot(cx, i, module->slots[i], tmpl, 
  513.                                         PR_FALSE);
  514.             if (rv != SSM_SUCCESS)
  515.                 goto loser;
  516.         }
  517.     }
  518.     PR_Free(tmpl);
  519.     tmpl = NULL;
  520.     
  521.     /* Chuck out part 2. */
  522.     rv = ssm_pkcs11_chuck_property(cx, "adv_modules_slotlist_part2");
  523.     if (rv != SSM_SUCCESS)
  524.         goto loser;
  525.     /* Get the template for the selectable slot list. */
  526.     rv = SSM_GetAndExpandText(cx, "adv_modules_slotlist_select_template", &tmpl);
  527.     if (rv != SSM_SUCCESS)
  528.         goto loser;
  529.     /* Iterate over the slots from this module. Put relevant info from each
  530.        into its own copy of the wrapper text. */
  531.     if (module)
  532.     {
  533.         for(i=0;i<module->slotCount;i++)
  534.         {
  535.             rv = ssmpkcs11_convert_slot(cx, i, module->slots[i], tmpl, 
  536.                                         PR_FALSE);
  537.             if (rv != SSM_SUCCESS)
  538.                 goto loser;
  539.         }
  540.     }
  541.     /* Chuck out part 3. */
  542.     rv = ssm_pkcs11_chuck_property(cx, "adv_modules_slotlist_part3");
  543.     req->sentResponse = PR_TRUE;
  544.     goto done;
  545.  loser:
  546.     if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
  547.  done:
  548.     if (cx)
  549.         SSMTextGen_DestroyContext(cx);
  550.     PR_FREEIF(tmpl);
  551.     return rv;
  552. }
  553. SSMStatus
  554. ssm_find_module_from_request(HTTPRequest *req, SECMODModule **mod)
  555. {
  556.     char *modID_ch = NULL;
  557.     PRInt32 moduleID;
  558.     SSMStatus rv;
  559.     rv = SSM_HTTPParamValue(req, "module", &modID_ch);
  560.     if (rv != SSM_SUCCESS)
  561.         goto done;
  562.     if (modID_ch)
  563.     {
  564.         /* Convert the module ID into a real module ID. */
  565.         PR_sscanf(modID_ch, "%ld", &moduleID);
  566.         
  567.         /* Find the module we're looking for based on the module ID. */
  568.         *mod = SECMOD_FindModuleByID((SECMODModuleID) moduleID);
  569.     }
  570.  done:
  571.     if ((!*mod) && (rv == SSM_SUCCESS))
  572.         rv = SSM_FAILURE;
  573.     return rv;
  574. }
  575. PK11SlotInfo *
  576. find_slot_by_ID(SECMODModule *mod, CK_SLOT_ID slotID)
  577. {
  578.     int i;
  579.     PK11SlotInfo *slot;
  580.     for (i=0; i < mod->slotCount; i++) {
  581.         slot = mod->slots[i];
  582.         if (slot->slotID == (CK_SLOT_ID) slotID)
  583.             return PK11_ReferenceSlot(slot);
  584.     }
  585.     return NULL;
  586. }
  587. SSMStatus
  588. ssm_find_slot_from_request(HTTPRequest *req, PK11SlotInfo **slot)
  589. {
  590.     char *slotID_ch = NULL;
  591.     PRInt32 slotID;
  592.     SECMODModule *mod;
  593.     SSMStatus rv = SSM_SUCCESS;
  594.     rv = ssm_find_module_from_request(req, &mod);
  595.     if (rv != SSM_SUCCESS)
  596.         goto done;
  597.     rv = SSM_HTTPParamValue(req, "slot", &slotID_ch);
  598.     if (rv != SSM_SUCCESS)
  599.         goto done;
  600.     if (slotID_ch)
  601.     {
  602.         /* Convert the module ID into a real module ID. */
  603.         PR_sscanf(slotID_ch, "%ld", &slotID);
  604.         /* Find the module we're looking for based on the module ID. */
  605.         *slot = find_slot_by_ID(mod, (CK_SLOT_ID) slotID);
  606.     }
  607.  done:
  608.     if ((!*slot) && (rv == SSM_SUCCESS))
  609.         rv = SSM_FAILURE;
  610.     return rv;
  611. }
  612. SSMStatus
  613. ssmpkcs11_show_slot_info(HTTPRequest *req, PK11SlotInfo *slot)
  614. {
  615.     char *wrapperStr = NULL;
  616.     char *tmpl = NULL;
  617.     char *type = NULL;
  618.     SSMTextGenContext *cx;
  619.     SSMStatus rv;
  620.     /* Make a new top-level text gen context to chuck text back. */
  621.     rv = SSMTextGen_NewTopLevelContext(req, &cx);
  622.     if (rv != SSM_SUCCESS)
  623.         goto loser;
  624.     rv = SSM_GetAndExpandText(cx, "adv_modules_slot_info_type", &type);
  625.     if (rv != SSM_SUCCESS)
  626.         goto loser;
  627.     rv = SSM_HTTPSendOKHeader(req, NULL, type);
  628.     if (rv != SSM_SUCCESS)
  629.         goto loser;
  630.     rv = SSM_GetAndExpandText(cx, "adv_modules_slot_info_content", &wrapperStr);
  631.     if (rv != SSM_SUCCESS)
  632.         goto loser; /* error string set by the called function */
  633.     rv = ssmpkcs11_convert_slot(cx, 0, slot, wrapperStr, PR_FALSE);
  634.     goto done;
  635.  loser:
  636.     if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
  637.  done:
  638.     if (cx)
  639.         SSMTextGen_DestroyContext(cx);
  640.     PR_FREEIF(tmpl);
  641.     PR_FREEIF(type);
  642.     PR_FREEIF(wrapperStr);
  643.     return rv;
  644. }
  645. SSMStatus 
  646. SSM_ShowSlotCommandHandler(HTTPRequest *req)
  647. {
  648.     SSMStatus rv;
  649.     PK11SlotInfo *slot;
  650.     /* Find the slot. */
  651.     rv = ssm_find_slot_from_request(req, &slot);
  652.     if (rv != SSM_SUCCESS)
  653.         goto loser;
  654.     /* Display the slot info. */
  655.     rv = ssmpkcs11_show_slot_info(req, slot);
  656.     req->sentResponse = PR_TRUE;
  657.  loser:
  658.     if (slot)
  659.         PK11_FreeSlot(slot);
  660.     return rv;
  661. }
  662. SSMStatus 
  663. SSM_LoginSlotCommandHandler(HTTPRequest *req)
  664. {
  665.     SSMStatus rv;
  666.     PK11SlotInfo *slot;
  667.     /* Find the slot. */
  668.     rv = ssm_find_slot_from_request(req, &slot);
  669.     if (rv != SSM_SUCCESS)
  670.         goto loser;
  671.     /* Log into the slot. */
  672.     PK11_Authenticate(slot, PR_TRUE, req->ctrlconn);
  673.     /* Display the slot info. */
  674.     rv = ssmpkcs11_show_slot_info(req, slot);
  675.     req->sentResponse = PR_TRUE;
  676.  loser:
  677.     if (slot)
  678.         PK11_FreeSlot(slot);
  679.     return rv;
  680. }
  681. SSMStatus
  682. SSM_LogoutSlotCommandHandler(HTTPRequest *req)
  683. {
  684.     SSMStatus rv;
  685.     PK11SlotInfo *slot;
  686.     /* Find the slot. */
  687.     rv = ssm_find_slot_from_request(req, &slot);
  688.     if (rv != SSM_SUCCESS)
  689.         goto loser;
  690.     /* Log out of the slot. */
  691.     PK11_Logout(slot);
  692.     /* Display the slot info. */
  693.     rv = ssmpkcs11_show_slot_info(req, slot);
  694.     req->sentResponse = PR_TRUE;
  695.  loser:
  696.     if (slot)
  697.         PK11_FreeSlot(slot);
  698.     return rv;
  699. }
  700. SSMStatus 
  701. SSM_LogoutAllSlotsCommandHandler(HTTPRequest *req)
  702. {
  703.     SSMStatus rv;
  704.     PK11SlotInfo *slot;
  705.     /* Find the slot. */
  706.     rv = ssm_find_slot_from_request(req, &slot);
  707.     /* Not relevant if we find the slot here, 
  708.        just remember to display (or not) whatever slot we have */
  709.     if (rv != SSM_SUCCESS)
  710.         slot = NULL;
  711.     /* Log out of all slots. */
  712.     PK11_LogoutAll();
  713.     /* Display the slot info (if any). */
  714.     rv = ssmpkcs11_show_slot_info(req, slot);
  715.     req->sentResponse = PR_TRUE;
  716.     if (slot)
  717.         PK11_FreeSlot(slot);
  718.     return rv;
  719. }
  720. /*
  721.   --------------------------------------------------------- 
  722.   FIPS mode code
  723.   --------------------------------------------------------- 
  724.  */
  725. /*
  726.   FIPS mode keyword handler.
  727.   Syntax: {_fipsmode <true_text>,<false_text>}
  728.   where <true_text> is displayed if FIPS mode is on, <false_text> otherwise.
  729.  */
  730. SSMStatus 
  731. SSM_PKCS11FIPSModeKeywordHandler(SSMTextGenContext *cx)
  732. {
  733.     SSMStatus rv = SSM_SUCCESS;
  734.     char *param = NULL;
  735.     char *tempStr = NULL;
  736.     PR_ASSERT(cx);
  737.     PR_ASSERT(cx->m_params);
  738.     PR_ASSERT(cx->m_result);
  739.     if (!cx || !cx->m_params || !cx->m_result)
  740.     {
  741.         rv = PR_INVALID_ARGUMENT_ERROR;
  742.         goto loser; 
  743.     }
  744.     
  745.     /* Figure out if we're in FIPS mode. */
  746.     if (PK11_IsFIPS())
  747.         param = (char *) SSM_At(cx->m_params, 0);
  748.     else
  749.         param = (char *) SSM_At(cx->m_params, 1);
  750.     /* Display the appropriate string. */
  751.     rv = SSMTextGen_SubstituteString(cx, param, &tempStr);
  752.     if (rv != SSM_SUCCESS)
  753.         goto loser; /* error string set by the called function */
  754.     rv = SSM_ConcatenateUTF8String(&cx->m_result, tempStr);
  755.     if (rv == SSM_SUCCESS)
  756.         goto done;
  757.  loser:
  758.     if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
  759.  done:
  760.     PR_FREEIF(tempStr);
  761.     return rv;
  762. }
  763. void
  764. SSM_TrimTrailingWhitespace(char *str)
  765. {
  766.     char *end = &(str[strlen(str)]);
  767.     char *start = str;
  768.     do
  769.     {
  770.         end--;
  771.     }
  772.     while ((end >= start) && 
  773.            ((*end == ' ') || (*end == '')));
  774.     *(++end) = '';
  775. }
  776. /*
  777.   Command handler to set FIPS mode.
  778.   Syntax: setFIPSMode?fips={on|off}&baseRef=<baseRef>&target=<ctrlconn>
  779.  */
  780. SSMStatus
  781. SSM_SetFIPSModeCommandHandler(HTTPRequest *req)
  782. {
  783.     char *fips_ch = NULL, *baseRef_ch = NULL;
  784.     SECStatus srv = SECSuccess;
  785.     PRBool oldFIPS, newFIPS;
  786.     SSMStatus rv = SSM_SUCCESS;
  787.     rv = SSM_HTTPParamValue(req, "fips", &fips_ch);
  788.     if (rv != SSM_SUCCESS)
  789.         goto loser;
  790.     newFIPS = !PL_strncmp(fips_ch, "on", 2);
  791.     oldFIPS = PK11_IsFIPS();
  792.     if (newFIPS != oldFIPS)
  793.     {
  794.         /* 
  795.            Turning FIPS mode on/off requires the exact same operation:
  796.            deleting the built-in PKCS11 module. 
  797.            
  798.            ### mwelch We need these calls to differentiate between 
  799.                       secmod dbs!
  800.         */
  801.         SECMODModule *internal;
  802.         CK_INFO modInfo;
  803.         internal = SECMOD_GetInternalModule();
  804.         if (!internal)
  805.             goto loser;
  806.         srv = PK11_GetModInfo(internal, &modInfo);
  807.         if (srv != SECSuccess)
  808.             goto loser;
  809.         SSM_TrimTrailingWhitespace((char*) modInfo.libraryDescription);
  810.         /* Delete the {FIPS,non-FIPS} internal module, so that 
  811.            it will be replaced by the {non-FIPS,FIPS} counterpart. */
  812.         srv = SECMOD_DeleteInternalModule(internal->commonName);
  813.         if (srv != SECSuccess)
  814.             goto loser;
  815.     }
  816.     /* if there's a baseRef, send it back. otherwise, no content. */
  817.     rv = SSM_HTTPParamValue(req, "baseRef", &baseRef_ch);
  818.     if (rv == SSM_SUCCESS)
  819.     {
  820.         /* send what was requested */
  821.         rv = SSM_HTTPCloseAndSleep(req);
  822.     }
  823.     goto done;
  824.  loser:
  825.     if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
  826.     SSM_HTTPReportSpecificError(req, "SetFIPSModeCommandHandler: Error %d "
  827.                                 "attempting to change FIPS mode.",
  828.                                 srv != SECSuccess ? srv : rv);
  829.  done:
  830.     return rv;
  831. }