зеркало из https://github.com/mozilla/pjs.git
962 строки
26 KiB
C
962 строки
26 KiB
C
/* -*- 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 "pkcs11ui.h"
|
|
#include "pkcs11.h"
|
|
#include "pk11func.h"
|
|
#include "plstr.h"
|
|
#include "secmod.h"
|
|
#include "secmodti.h"
|
|
#include "minihttp.h"
|
|
#include "textgen.h"
|
|
|
|
/* Utility */
|
|
PK11SlotInfo *
|
|
SSMPKCS11_FindSlotByID(SECMODModuleID modID,
|
|
CK_SLOT_ID slotID)
|
|
{
|
|
SECMODModule *mod = NULL;
|
|
PRIntn i;
|
|
|
|
mod = SECMOD_FindModuleByID(modID);
|
|
if (mod)
|
|
{
|
|
for(i=0;i<mod->slotCount;i++)
|
|
{
|
|
if (mod->slots[i]->slotID == slotID)
|
|
return mod->slots[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
---------------------------------------------------------
|
|
PKCS11 module processing (list, add, delete)
|
|
---------------------------------------------------------
|
|
*/
|
|
|
|
SSMStatus
|
|
ssmpkcs11_convert_module(SSMTextGenContext *cx,
|
|
PRInt32 modIndex,
|
|
SECMODModule *mod,
|
|
char *fmt)
|
|
{
|
|
char *dllName = NULL;
|
|
char *tempStr = NULL;
|
|
char *lib_ch = NULL;
|
|
CK_INFO modInfo;
|
|
SSMStatus rv = SSM_FAILURE;
|
|
SECStatus srv;
|
|
/* 65? Why 65??? It's what's was used in the original UI. */
|
|
char buf[65];
|
|
char buf2[65];
|
|
|
|
srv = PK11_GetModInfo(mod, &modInfo);
|
|
if (srv != SECSuccess)
|
|
goto loser;
|
|
|
|
/* we provide the space in (buf), so we don't deallocate lib_ch */
|
|
lib_ch = PK11_MakeString(NULL,buf2,(char *)modInfo.libraryDescription,
|
|
sizeof(modInfo.libraryDescription));
|
|
if (mod->dllName)
|
|
{
|
|
char *cursor, *newString;
|
|
int numSlashes = 0, newLen, i, j, oldLen;
|
|
|
|
dllName = mod->dllName;
|
|
/*
|
|
* Now we need to escape the '\' characters so the string shows
|
|
* up correctly in the UI.
|
|
*/
|
|
/* First count them to see if we even need to re-allocate*/
|
|
cursor = dllName;
|
|
while ((cursor = PL_strchr(cursor, '\\')) != NULL) {
|
|
numSlashes++;
|
|
cursor++;
|
|
}
|
|
if (numSlashes > 0) {
|
|
oldLen = PL_strlen(dllName);
|
|
newLen = oldLen + numSlashes + 1;
|
|
newString = SSM_NEW_ARRAY(char, newLen);
|
|
/*
|
|
* If we can't allocate a new buffer, then let's just display
|
|
* the original string. That's better than not displaying
|
|
* anything.
|
|
*/
|
|
if (newString != NULL) {
|
|
for (i=0, j=0; i<oldLen+1; i++,j++){
|
|
newString[j] = dllName[i];
|
|
if (newString[j] == '\\'){
|
|
newString[j+1] = '\\';
|
|
j++;
|
|
}
|
|
}
|
|
dllName = newString;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rv = SSM_GetAndExpandText(cx, "text_pk11_no_dll", &dllName);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
}
|
|
|
|
PR_snprintf(buf, sizeof(buf), "%d.%d",
|
|
modInfo.libraryVersion.major, modInfo.libraryVersion.minor);
|
|
|
|
tempStr = PR_smprintf(fmt, modIndex, (long)mod->moduleID, lib_ch,
|
|
mod->commonName, dllName, buf);
|
|
if (tempStr == NULL) {
|
|
rv = SSM_FAILURE;
|
|
goto loser;
|
|
}
|
|
rv = SSM_ConcatenateUTF8String(&cx->m_result, tempStr);
|
|
|
|
loser:
|
|
if (dllName && dllName != mod->dllName)
|
|
PR_Free(dllName);
|
|
PR_FREEIF (tempStr);
|
|
return rv;
|
|
}
|
|
|
|
/*
|
|
PKCS11 module list keyword handler.
|
|
Syntax: {_pk11modules <wrapper_key>}
|
|
*/
|
|
|
|
SSMStatus
|
|
SSM_PKCS11ModulesKeywordHandler(SSMTextGenContext *cx)
|
|
{
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
char *wrapperKey = NULL;
|
|
char *wrapperStr = NULL;
|
|
SECMODModuleList *modList = SECMOD_GetDefaultModuleList();
|
|
SECMODModuleList *modWalk = NULL;
|
|
SECMODListLock *modLock = SECMOD_GetDefaultModuleListLock();
|
|
PRBool gotLock = PR_FALSE; /* indicates whether we should release at end */
|
|
PRInt32 i=0;
|
|
|
|
/* Check for parameter validity */
|
|
PR_ASSERT(cx);
|
|
PR_ASSERT(cx->m_request);
|
|
PR_ASSERT(cx->m_params);
|
|
PR_ASSERT(cx->m_result);
|
|
if (!cx || !cx->m_request || !cx->m_params || !cx->m_result)
|
|
{
|
|
rv = PR_INVALID_ARGUMENT_ERROR;
|
|
goto real_loser; /* really bail here */
|
|
}
|
|
|
|
if (SSM_Count(cx->m_params) != 1)
|
|
{
|
|
SSM_HTTPReportSpecificError(cx->m_request, "_certList: "
|
|
"Incorrect number of parameters "
|
|
"(%d supplied, 1 needed).\n",
|
|
SSM_Count(cx->m_params));
|
|
goto user_loser;
|
|
}
|
|
|
|
/* Convert parameters to something we can use in finding certs. */
|
|
wrapperKey = (char *) SSM_At(cx->m_params, 0);
|
|
PR_ASSERT(wrapperKey);
|
|
|
|
/* Get the wrapper text. */
|
|
rv = SSM_GetAndExpandTextKeyedByString(cx, wrapperKey, &wrapperStr);
|
|
if (rv != SSM_SUCCESS)
|
|
goto real_loser; /* error string set by the called function */
|
|
|
|
/* Iterate over the PKCS11 modules. Put relevant info from each
|
|
into its own copy of the wrapper text. */
|
|
SECMOD_GetReadLock(modLock);
|
|
gotLock = PR_TRUE;
|
|
|
|
modWalk = modList;
|
|
while (modWalk)
|
|
{
|
|
rv = ssmpkcs11_convert_module(cx, i++, modWalk->module, wrapperStr);
|
|
modWalk = modWalk->next;
|
|
}
|
|
|
|
goto done;
|
|
user_loser:
|
|
/* If we reach this point, something in the input is wrong, but we
|
|
can still send something back to the client to indicate that a
|
|
problem has occurred. */
|
|
|
|
/* If we can't do what we're about to do, really bail. */
|
|
if (!cx->m_request || !cx->m_request->errormsg)
|
|
goto real_loser;
|
|
|
|
/* Clear the string we were accumulating. */
|
|
SSMTextGen_UTF8StringClear(&cx->m_result);
|
|
|
|
/* Use the result string given to us to explain what happened. */
|
|
SSM_ConcatenateUTF8String(&cx->m_result, cx->m_request->errormsg);
|
|
/* Clear the result string, since we're sending this inline */
|
|
SSMTextGen_UTF8StringClear(&cx->m_request->errormsg);
|
|
|
|
goto done;
|
|
real_loser:
|
|
/* If we reach this point, then we are so screwed that we cannot
|
|
send anything vaguely normal back to the client. Bail. */
|
|
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
|
|
done:
|
|
PR_FREEIF(wrapperStr);
|
|
if (modLock && gotLock)
|
|
SECMOD_ReleaseReadLock(modLock);
|
|
|
|
return rv;
|
|
}
|
|
|
|
/*
|
|
---------------------------------------------------------
|
|
PKCS11 slot code
|
|
---------------------------------------------------------
|
|
*/
|
|
|
|
enum
|
|
{
|
|
SSM_PK11STR_SLOT_LOGGED_IN = (long) 0,
|
|
SSM_PK11STR_SLOT_NOT_LOGGED_IN,
|
|
SSM_PK11STR_SLOT_NO_LOGIN_REQUIRED,
|
|
SSM_PK11STR_SLOT_NOT_PRESENT,
|
|
SSM_PK11STR_SLOT_UNINITIALIZED,
|
|
SSM_PK11STR_SLOT_DISABLED,
|
|
SSM_PK11STR_SLOT_READY,
|
|
SSM_PK11STR_SLOT_STRING_COUNT
|
|
};
|
|
|
|
static char *slotStringKeys[] =
|
|
{
|
|
"text_pk11_slot_logged_in",
|
|
"text_pk11_slot_not_logged_in",
|
|
"text_pk11_slot_no_login_required",
|
|
"text_pk11_slot_not_present",
|
|
"text_pk11_slot_uninitialized",
|
|
"text_pk11_slot_disabled",
|
|
"text_pk11_slot_ready"
|
|
};
|
|
|
|
static char **slotStrings = NULL;
|
|
|
|
void
|
|
ssmpkcs11_initialize_slot_labels(SSMTextGenContext *cx)
|
|
{
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
PRIntn i;
|
|
|
|
slotStrings = (char **) PR_Calloc(SSM_PK11STR_SLOT_STRING_COUNT + 1,
|
|
sizeof(char**));
|
|
PR_ASSERT(slotStrings);
|
|
|
|
for(i=0;i<SSM_PK11STR_SLOT_STRING_COUNT;i++)
|
|
{
|
|
rv = SSM_FindUTF8StringInBundles(cx, slotStringKeys[i],
|
|
&slotStrings[i]);
|
|
PR_ASSERT(rv == SSM_SUCCESS);
|
|
}
|
|
}
|
|
|
|
SSMStatus
|
|
ssmpkcs11_convert_slot(SSMTextGenContext *cx,
|
|
PRInt32 slotIndex,
|
|
PK11SlotInfo *slot,
|
|
char *fmt,
|
|
PRBool accumulate) /* accumulate in cx->m_result? */
|
|
{
|
|
char *name = NULL;
|
|
char *statusStr = NULL;
|
|
char *serial = NULL;
|
|
char *version = NULL;
|
|
char *tempStr = NULL;
|
|
long status, slotID = 0, moduleID = 0;
|
|
CK_TOKEN_INFO tokenInfo;
|
|
SSMStatus rv = SSM_FAILURE;
|
|
SECStatus srv = SECSuccess;
|
|
/* 65? Why 65??? It's what's was used in the original UI. */
|
|
char buf[65];
|
|
char empty[1] = { '\0' } ;
|
|
|
|
if (!slotStrings)
|
|
ssmpkcs11_initialize_slot_labels(cx);
|
|
|
|
/* If we have a NULL slot, return blank information. */
|
|
if (!slot)
|
|
{
|
|
name = empty;
|
|
statusStr = empty;
|
|
serial = empty;
|
|
version = empty;
|
|
slotID = 0;
|
|
|
|
goto show_stuff;
|
|
}
|
|
|
|
/* Get the slot name. Either the default name or the name of the token
|
|
in the slot will be used. */
|
|
if (PK11_IsPresent(slot))
|
|
name = PK11_GetTokenName(slot);
|
|
else
|
|
name = PK11_GetSlotName(slot);
|
|
|
|
/* Report the status of the slot. */
|
|
if (PK11_IsDisabled(slot))
|
|
status = SSM_PK11STR_SLOT_DISABLED;
|
|
else if (!PK11_IsPresent(slot))
|
|
status = SSM_PK11STR_SLOT_NOT_PRESENT;
|
|
else if (PK11_NeedLogin(slot) && PK11_NeedUserInit(slot))
|
|
status = SSM_PK11STR_SLOT_UNINITIALIZED;
|
|
else if (PK11_NeedLogin(slot) && !PK11_IsLoggedIn(slot, NULL))
|
|
status = SSM_PK11STR_SLOT_NOT_LOGGED_IN;
|
|
else if (PK11_NeedLogin(slot))
|
|
status = SSM_PK11STR_SLOT_LOGGED_IN;
|
|
else
|
|
status = SSM_PK11STR_SLOT_READY;
|
|
|
|
statusStr = slotStrings[status];
|
|
|
|
/* Get the serial number and version. */
|
|
|
|
/* This is how the old UI determines if there's a token in, so... */
|
|
if (PK11_IsPresent(slot))
|
|
srv = PK11_GetTokenInfo(slot, &tokenInfo);
|
|
|
|
if (PK11_IsPresent(slot) && (srv == SECSuccess))
|
|
{
|
|
/* Get serial number and version from the token info. */
|
|
serial = PK11_MakeString(NULL, NULL, (char*)tokenInfo.serialNumber,
|
|
sizeof(tokenInfo.serialNumber));
|
|
PR_snprintf(buf, sizeof(buf), "%d.%d",
|
|
tokenInfo.firmwareVersion.major,
|
|
tokenInfo.firmwareVersion.minor);
|
|
version = buf;
|
|
}
|
|
else
|
|
{
|
|
/* Get serial number and version from the slot info. */
|
|
CK_SLOT_INFO slotInfo;
|
|
srv = PK11_GetSlotInfo(slot, &slotInfo);
|
|
if (srv != SECSuccess)
|
|
goto loser;
|
|
|
|
serial = empty;
|
|
PR_snprintf(buf, sizeof(buf), "%d.%d",
|
|
slotInfo.firmwareVersion.major,
|
|
slotInfo.firmwareVersion.minor);
|
|
version = buf;
|
|
}
|
|
|
|
slotID = (long) (slot->slotID);
|
|
moduleID = (long) (slot->module->moduleID);
|
|
|
|
show_stuff:
|
|
tempStr = PR_smprintf(fmt, slotIndex, slotID, moduleID, name,
|
|
statusStr, serial, version);
|
|
if (accumulate)
|
|
{
|
|
rv = SSM_ConcatenateUTF8String(&cx->m_result, tempStr);
|
|
if (rv != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
}
|
|
else
|
|
rv = SSM_HTTPSendUTF8String(cx->m_request, tempStr);
|
|
|
|
loser:
|
|
/* The data that isn't freed is either because it's a member of the
|
|
* data in a structure of the PK11 libraries or its a static local
|
|
* variable.
|
|
*/
|
|
if (serial && serial != empty)
|
|
PR_Free(serial);
|
|
PR_FREEIF(tempStr);
|
|
return rv;
|
|
}
|
|
|
|
/*
|
|
PKCS11 slot list keyword handler.
|
|
Syntax: {_pk11slots <moduleID>,<wrapper_key>}
|
|
*/
|
|
|
|
SSMStatus
|
|
SSM_PKCS11SlotsKeywordHandler(SSMTextGenContext *cx)
|
|
{
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
SECMODModule *module = NULL;
|
|
char *wrapperKey = NULL;
|
|
char *moduleIDStr = NULL;
|
|
long moduleID;
|
|
char *wrapperStr = NULL;
|
|
PRInt32 i=0;
|
|
|
|
/* Check for parameter validity */
|
|
PR_ASSERT(cx);
|
|
PR_ASSERT(cx->m_request);
|
|
PR_ASSERT(cx->m_params);
|
|
PR_ASSERT(cx->m_result);
|
|
if (!cx || !cx->m_request || !cx->m_params || !cx->m_result)
|
|
{
|
|
rv = PR_INVALID_ARGUMENT_ERROR;
|
|
goto real_loser; /* really bail here */
|
|
}
|
|
|
|
if (SSM_Count(cx->m_params) != 2)
|
|
{
|
|
SSM_HTTPReportSpecificError(cx->m_request, "_certList: "
|
|
"Incorrect number of parameters "
|
|
"(%d supplied, 2 needed).\n",
|
|
SSM_Count(cx->m_params));
|
|
goto user_loser;
|
|
}
|
|
|
|
/* Convert parameters to something we can use in finding certs. */
|
|
moduleIDStr = (char *) SSM_At(cx->m_params, 0);
|
|
PR_ASSERT(moduleIDStr);
|
|
wrapperKey = (char *) SSM_At(cx->m_params, 1);
|
|
PR_ASSERT(wrapperKey);
|
|
|
|
/* Find the module we're looking for based on the module ID. */
|
|
module = SECMOD_FindModuleByID((SECMODModuleID) moduleID);
|
|
if (!module)
|
|
goto user_loser;
|
|
|
|
/* Get the wrapper text. */
|
|
rv = SSM_GetAndExpandTextKeyedByString(cx, wrapperKey, &wrapperStr);
|
|
if (rv != SSM_SUCCESS)
|
|
goto real_loser; /* error string set by the called function */
|
|
|
|
/* Iterate over the slots from this module. Put relevant info from each
|
|
into its own copy of the wrapper text. */
|
|
for(i=0;i<module->slotCount;i++)
|
|
{
|
|
rv = ssmpkcs11_convert_slot(cx, i, module->slots[i], wrapperStr,
|
|
PR_TRUE);
|
|
if (rv != SSM_SUCCESS)
|
|
goto user_loser;
|
|
}
|
|
goto done;
|
|
user_loser:
|
|
/* If we reach this point, something in the input is wrong, but we
|
|
can still send something back to the client to indicate that a
|
|
problem has occurred. */
|
|
|
|
/* If we can't do what we're about to do, really bail. */
|
|
if (!cx->m_request || !cx->m_request->errormsg)
|
|
goto real_loser;
|
|
|
|
/* Clear the string we were accumulating. */
|
|
SSMTextGen_UTF8StringClear(&cx->m_result);
|
|
|
|
/* Use the result string given to us to explain what happened. */
|
|
SSM_ConcatenateUTF8String(&cx->m_result, cx->m_request->errormsg);
|
|
/* Clear the result string, since we're sending this inline */
|
|
SSMTextGen_UTF8StringClear(&cx->m_request->errormsg);
|
|
|
|
goto done;
|
|
real_loser:
|
|
/* If we reach this point, then we are so screwed that we cannot
|
|
send anything vaguely normal back to the client. Bail. */
|
|
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
|
|
done:
|
|
PR_FREEIF(wrapperStr);
|
|
if (module)
|
|
SECMOD_DestroyModule(module);
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus
|
|
ssm_pkcs11_chuck_property(SSMTextGenContext *cx, char *propName)
|
|
{
|
|
char *text = NULL;
|
|
SSMStatus rv;
|
|
|
|
rv = SSM_GetAndExpandText(cx, propName, &text);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
rv = SSM_HTTPSendUTF8String(cx->m_request, text);
|
|
|
|
loser:
|
|
PR_FREEIF(text);
|
|
SSMTextGen_UTF8StringClear(&cx->m_result);
|
|
return rv;
|
|
}
|
|
|
|
/* PKCS11ShowSlots?module=<moduleID> */
|
|
SSMStatus
|
|
SSM_ShowSlotsCommandHandler(HTTPRequest *req)
|
|
{
|
|
SSMTextGenContext *cx = NULL;
|
|
char *tmpl = NULL, *type = NULL;
|
|
char *nomod_ch = NULL;
|
|
char *modID_ch = NULL;
|
|
long moduleID;
|
|
SECMODModule *module = NULL;
|
|
PRIntn i;
|
|
SSMStatus rv;
|
|
|
|
/* If we have a "no_module" parameter, then there
|
|
is no module for which to load slots. */
|
|
rv = SSM_HTTPParamValue(req, "no_module", &nomod_ch);
|
|
if (rv == SSM_SUCCESS)
|
|
goto display_stuff;
|
|
|
|
rv = SSM_HTTPParamValue(req, "module", &modID_ch);
|
|
if (rv != SSM_SUCCESS)
|
|
goto display_stuff;
|
|
|
|
if (modID_ch)
|
|
{
|
|
/* Convert the module ID into a real module ID. */
|
|
PR_sscanf(modID_ch, "%ld", &moduleID);
|
|
|
|
/* Find the module we're looking for based on the module ID. */
|
|
module = SECMOD_FindModuleByID((SECMODModuleID) moduleID);
|
|
if (!module)
|
|
goto loser;
|
|
}
|
|
|
|
display_stuff:
|
|
/* Make a new top-level text gen context to chuck text back. */
|
|
rv = SSMTextGen_NewTopLevelContext(req, &cx);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
rv = SSM_GetAndExpandText(cx, "adv_modules_slotlist_type", &type);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
rv = SSM_HTTPSendOKHeader(req, NULL, type);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
/* Chuck out part 1. */
|
|
rv = ssm_pkcs11_chuck_property(cx, "adv_modules_slotlist_part1");
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
/* Get the template for the JS slot list. */
|
|
rv = SSM_GetAndExpandText(cx, "adv_modules_slotlist_js_template", &tmpl);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
/* Iterate over the slots from this module. Put relevant info from each
|
|
into its own copy of the wrapper text. */
|
|
if (module)
|
|
{
|
|
for(i=0;i<module->slotCount;i++)
|
|
{
|
|
rv = ssmpkcs11_convert_slot(cx, i, module->slots[i], tmpl,
|
|
PR_FALSE);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
}
|
|
}
|
|
|
|
PR_Free(tmpl);
|
|
tmpl = NULL;
|
|
|
|
/* Chuck out part 2. */
|
|
rv = ssm_pkcs11_chuck_property(cx, "adv_modules_slotlist_part2");
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
/* Get the template for the selectable slot list. */
|
|
rv = SSM_GetAndExpandText(cx, "adv_modules_slotlist_select_template", &tmpl);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
/* Iterate over the slots from this module. Put relevant info from each
|
|
into its own copy of the wrapper text. */
|
|
if (module)
|
|
{
|
|
for(i=0;i<module->slotCount;i++)
|
|
{
|
|
rv = ssmpkcs11_convert_slot(cx, i, module->slots[i], tmpl,
|
|
PR_FALSE);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
}
|
|
}
|
|
|
|
/* Chuck out part 3. */
|
|
rv = ssm_pkcs11_chuck_property(cx, "adv_modules_slotlist_part3");
|
|
req->sentResponse = PR_TRUE;
|
|
|
|
goto done;
|
|
loser:
|
|
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
|
|
done:
|
|
if (cx)
|
|
SSMTextGen_DestroyContext(cx);
|
|
PR_FREEIF(tmpl);
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus
|
|
ssm_find_module_from_request(HTTPRequest *req, SECMODModule **mod)
|
|
{
|
|
char *modID_ch = NULL;
|
|
PRInt32 moduleID;
|
|
SSMStatus rv;
|
|
|
|
rv = SSM_HTTPParamValue(req, "module", &modID_ch);
|
|
if (rv != SSM_SUCCESS)
|
|
goto done;
|
|
|
|
if (modID_ch)
|
|
{
|
|
/* Convert the module ID into a real module ID. */
|
|
PR_sscanf(modID_ch, "%ld", &moduleID);
|
|
|
|
/* Find the module we're looking for based on the module ID. */
|
|
*mod = SECMOD_FindModuleByID((SECMODModuleID) moduleID);
|
|
}
|
|
done:
|
|
if ((!*mod) && (rv == SSM_SUCCESS))
|
|
rv = SSM_FAILURE;
|
|
return rv;
|
|
}
|
|
|
|
PK11SlotInfo *
|
|
find_slot_by_ID(SECMODModule *mod, CK_SLOT_ID slotID)
|
|
{
|
|
int i;
|
|
PK11SlotInfo *slot;
|
|
|
|
for (i=0; i < mod->slotCount; i++) {
|
|
slot = mod->slots[i];
|
|
if (slot->slotID == (CK_SLOT_ID) slotID)
|
|
return PK11_ReferenceSlot(slot);
|
|
}
|
|
return NULL;
|
|
|
|
}
|
|
|
|
SSMStatus
|
|
ssm_find_slot_from_request(HTTPRequest *req, PK11SlotInfo **slot)
|
|
{
|
|
char *slotID_ch = NULL;
|
|
PRInt32 slotID;
|
|
SECMODModule *mod;
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
|
|
rv = ssm_find_module_from_request(req, &mod);
|
|
if (rv != SSM_SUCCESS)
|
|
goto done;
|
|
|
|
rv = SSM_HTTPParamValue(req, "slot", &slotID_ch);
|
|
if (rv != SSM_SUCCESS)
|
|
goto done;
|
|
|
|
if (slotID_ch)
|
|
{
|
|
/* Convert the module ID into a real module ID. */
|
|
PR_sscanf(slotID_ch, "%ld", &slotID);
|
|
|
|
/* Find the module we're looking for based on the module ID. */
|
|
*slot = find_slot_by_ID(mod, (CK_SLOT_ID) slotID);
|
|
}
|
|
done:
|
|
if ((!*slot) && (rv == SSM_SUCCESS))
|
|
rv = SSM_FAILURE;
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus
|
|
ssmpkcs11_show_slot_info(HTTPRequest *req, PK11SlotInfo *slot)
|
|
{
|
|
char *wrapperStr = NULL;
|
|
char *tmpl = NULL;
|
|
char *type = NULL;
|
|
SSMTextGenContext *cx;
|
|
SSMStatus rv;
|
|
|
|
/* Make a new top-level text gen context to chuck text back. */
|
|
rv = SSMTextGen_NewTopLevelContext(req, &cx);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
rv = SSM_GetAndExpandText(cx, "adv_modules_slot_info_type", &type);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
rv = SSM_HTTPSendOKHeader(req, NULL, type);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
rv = SSM_GetAndExpandText(cx, "adv_modules_slot_info_content", &wrapperStr);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser; /* error string set by the called function */
|
|
|
|
rv = ssmpkcs11_convert_slot(cx, 0, slot, wrapperStr, PR_FALSE);
|
|
|
|
goto done;
|
|
loser:
|
|
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
|
|
done:
|
|
if (cx)
|
|
SSMTextGen_DestroyContext(cx);
|
|
PR_FREEIF(tmpl);
|
|
PR_FREEIF(type);
|
|
PR_FREEIF(wrapperStr);
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus
|
|
SSM_ShowSlotCommandHandler(HTTPRequest *req)
|
|
{
|
|
SSMStatus rv;
|
|
PK11SlotInfo *slot;
|
|
|
|
/* Find the slot. */
|
|
rv = ssm_find_slot_from_request(req, &slot);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
/* Display the slot info. */
|
|
rv = ssmpkcs11_show_slot_info(req, slot);
|
|
req->sentResponse = PR_TRUE;
|
|
|
|
loser:
|
|
if (slot)
|
|
PK11_FreeSlot(slot);
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus
|
|
SSM_LoginSlotCommandHandler(HTTPRequest *req)
|
|
{
|
|
SSMStatus rv;
|
|
PK11SlotInfo *slot;
|
|
|
|
/* Find the slot. */
|
|
rv = ssm_find_slot_from_request(req, &slot);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
/* Log into the slot. */
|
|
PK11_Authenticate(slot, PR_TRUE, req->ctrlconn);
|
|
|
|
/* Display the slot info. */
|
|
rv = ssmpkcs11_show_slot_info(req, slot);
|
|
req->sentResponse = PR_TRUE;
|
|
|
|
loser:
|
|
if (slot)
|
|
PK11_FreeSlot(slot);
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus
|
|
SSM_LogoutSlotCommandHandler(HTTPRequest *req)
|
|
{
|
|
SSMStatus rv;
|
|
PK11SlotInfo *slot;
|
|
|
|
/* Find the slot. */
|
|
rv = ssm_find_slot_from_request(req, &slot);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
/* Log out of the slot. */
|
|
PK11_Logout(slot);
|
|
|
|
/* Display the slot info. */
|
|
rv = ssmpkcs11_show_slot_info(req, slot);
|
|
req->sentResponse = PR_TRUE;
|
|
|
|
loser:
|
|
if (slot)
|
|
PK11_FreeSlot(slot);
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus
|
|
SSM_LogoutAllSlotsCommandHandler(HTTPRequest *req)
|
|
{
|
|
SSMStatus rv;
|
|
PK11SlotInfo *slot;
|
|
|
|
/* Find the slot. */
|
|
rv = ssm_find_slot_from_request(req, &slot);
|
|
/* Not relevant if we find the slot here,
|
|
just remember to display (or not) whatever slot we have */
|
|
if (rv != SSM_SUCCESS)
|
|
slot = NULL;
|
|
|
|
/* Log out of all slots. */
|
|
PK11_LogoutAll();
|
|
|
|
/* Display the slot info (if any). */
|
|
rv = ssmpkcs11_show_slot_info(req, slot);
|
|
|
|
req->sentResponse = PR_TRUE;
|
|
|
|
if (slot)
|
|
PK11_FreeSlot(slot);
|
|
return rv;
|
|
}
|
|
|
|
/*
|
|
---------------------------------------------------------
|
|
FIPS mode code
|
|
---------------------------------------------------------
|
|
*/
|
|
|
|
/*
|
|
FIPS mode keyword handler.
|
|
Syntax: {_fipsmode <true_text>,<false_text>}
|
|
where <true_text> is displayed if FIPS mode is on, <false_text> otherwise.
|
|
*/
|
|
SSMStatus
|
|
SSM_PKCS11FIPSModeKeywordHandler(SSMTextGenContext *cx)
|
|
{
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
char *param = NULL;
|
|
char *tempStr = NULL;
|
|
|
|
PR_ASSERT(cx);
|
|
PR_ASSERT(cx->m_params);
|
|
PR_ASSERT(cx->m_result);
|
|
if (!cx || !cx->m_params || !cx->m_result)
|
|
{
|
|
rv = PR_INVALID_ARGUMENT_ERROR;
|
|
goto loser;
|
|
}
|
|
|
|
/* Figure out if we're in FIPS mode. */
|
|
if (PK11_IsFIPS())
|
|
param = (char *) SSM_At(cx->m_params, 0);
|
|
else
|
|
param = (char *) SSM_At(cx->m_params, 1);
|
|
|
|
/* Display the appropriate string. */
|
|
rv = SSMTextGen_SubstituteString(cx, param, &tempStr);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser; /* error string set by the called function */
|
|
|
|
rv = SSM_ConcatenateUTF8String(&cx->m_result, tempStr);
|
|
if (rv == SSM_SUCCESS)
|
|
goto done;
|
|
loser:
|
|
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
|
|
done:
|
|
PR_FREEIF(tempStr);
|
|
return rv;
|
|
}
|
|
|
|
|
|
void
|
|
SSM_TrimTrailingWhitespace(char *str)
|
|
{
|
|
char *end = &(str[strlen(str)]);
|
|
char *start = str;
|
|
|
|
do
|
|
{
|
|
end--;
|
|
}
|
|
while ((end >= start) &&
|
|
((*end == ' ') || (*end == '\0')));
|
|
*(++end) = '\0';
|
|
}
|
|
|
|
/*
|
|
Command handler to set FIPS mode.
|
|
Syntax: setFIPSMode?fips={on|off}&baseRef=<baseRef>&target=<ctrlconn>
|
|
*/
|
|
SSMStatus
|
|
SSM_SetFIPSModeCommandHandler(HTTPRequest *req)
|
|
{
|
|
char *fips_ch = NULL, *baseRef_ch = NULL;
|
|
SECStatus srv = SECSuccess;
|
|
PRBool oldFIPS, newFIPS;
|
|
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
rv = SSM_HTTPParamValue(req, "fips", &fips_ch);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
newFIPS = !PL_strncmp(fips_ch, "on", 2);
|
|
oldFIPS = PK11_IsFIPS();
|
|
|
|
if (newFIPS != oldFIPS)
|
|
{
|
|
/*
|
|
Turning FIPS mode on/off requires the exact same operation:
|
|
deleting the built-in PKCS11 module.
|
|
|
|
### mwelch We need these calls to differentiate between
|
|
secmod dbs!
|
|
*/
|
|
SECMODModule *internal;
|
|
CK_INFO modInfo;
|
|
|
|
internal = SECMOD_GetInternalModule();
|
|
if (!internal)
|
|
goto loser;
|
|
|
|
srv = PK11_GetModInfo(internal, &modInfo);
|
|
if (srv != SECSuccess)
|
|
goto loser;
|
|
SSM_TrimTrailingWhitespace((char*) modInfo.libraryDescription);
|
|
|
|
/* Delete the {FIPS,non-FIPS} internal module, so that
|
|
it will be replaced by the {non-FIPS,FIPS} counterpart. */
|
|
srv = SECMOD_DeleteInternalModule(internal->commonName);
|
|
if (srv != SECSuccess)
|
|
goto loser;
|
|
}
|
|
|
|
/* if there's a baseRef, send it back. otherwise, no content. */
|
|
rv = SSM_HTTPParamValue(req, "baseRef", &baseRef_ch);
|
|
if (rv == SSM_SUCCESS)
|
|
{
|
|
/* send what was requested */
|
|
rv = SSM_HTTPCloseAndSleep(req);
|
|
}
|
|
|
|
goto done;
|
|
loser:
|
|
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
|
|
SSM_HTTPReportSpecificError(req, "SetFIPSModeCommandHandler: Error %d "
|
|
"attempting to change FIPS mode.",
|
|
srv != SECSuccess ? srv : rv);
|
|
done:
|
|
return rv;
|
|
}
|
|
|