Bug 391296 – Need an update helper for Shared Databases

r=nelson.


git-svn-id: svn://10.0.0.236/trunk@247495 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rrelyea%redhat.com 2008-03-10 20:16:51 +00:00
parent dcdde8bd96
commit ef7b124a1b
25 changed files with 3559 additions and 183 deletions

View File

@ -942,6 +942,15 @@ Usage(char *progName)
progName);
#endif /* NSS_ENABLE_ECC */
FPS "\t\t [-f pwfile] [-X] [-d certdir] [-P dbprefix]\n");
FPS "\t%s --upgrade-merge --source-dir upgradeDir --upgrade-id uniqueID\n",
progName);
FPS "\t\t [--upgrade-token-name tokenName] [-d targetDBDir]\n");
FPS "\t\t [-P targetDBPrefix] [--source-prefix upgradeDBPrefix]\n");
FPS "\t\t [-f targetPWfile] [-@ upgradePWFile]\n");
FPS "\t%s --merge --source-dir sourceDBDir [-d targetDBdir]\n",
progName);
FPS "\t\t [-P targetDBPrefix] [--source-prefix sourceDBPrefix]\n");
FPS "\t\t [-f targetPWfile] [-@ sourcePWFile]\n");
FPS "\t%s -L [-n cert-name] [-X] [-d certdir] [-P dbprefix] [-r] [-a]\n", progName);
FPS "\t%s -M -n cert-name -t trustargs [-d certdir] [-P dbprefix]\n",
progName);
@ -1259,6 +1268,42 @@ static void LongUsage(char *progName)
" -X");
FPS "\n");
FPS "%-15s Upgrade an old database and merge it into a new one\n",
"--upgrade-merge");
FPS "%-20s Cert database directory to merge into (default is ~/.netscape)\n",
" -d certdir");
FPS "%-20s Cert & Key database prefix of the target database\n",
" -P dbprefix");
FPS "%-20s Specify the password file for the target database\n",
" -f pwfile");
FPS "%-20s \n%-20s Cert database directory to upgrade from\n",
" --source-dir certdir", "");
FPS "%-20s \n%-20s Cert & Key database prefix of the upgrade database\n",
" --soruce-prefix dbprefix", "");
FPS "%-20s \n%-20s Unique identifier for the upgrade database\n",
" --upgrade-id uniqueID", "");
FPS "%-20s \n%-20s Name of the token while it is in upgrade state\n",
" --upgrade-token-name name", "");
FPS "%-20s Specify the password file for the upgrade database\n",
" -@ pwfile");
FPS "\n");
FPS "%-15s Merge source database into the target database\n",
"--merge");
FPS "%-20s Cert database directory of target (default is ~/.netscape)\n",
" -d certdir");
FPS "%-20s Cert & Key database prefix of the target database\n",
" -P dbprefix");
FPS "%-20s Specify the password file for the target database\n",
" -f pwfile");
FPS "%-20s \n%-20s Cert database directory of the source database\n",
" --source-dir certdir", "");
FPS "%-20s \n%-20s Cert & Key database prefix of the source database\n",
" --source-prefix dbprefix", "");
FPS "%-20s Specify the password file for the source database\n",
" -@ pwfile");
FPS "\n");
FPS "%-15s Make a certificate and add to database\n",
"-S");
FPS "%-20s Specify the nickname of the cert\n",
@ -1567,6 +1612,99 @@ CreateCert(
return (rv);
}
/*
* map a class to a user presentable string
*/
static const char *objClassArray[] = {
"Data",
"Certificate",
"Public Key",
"Private Key",
"Secret Key",
"Hardware Feature",
"Domain Parameters",
"Mechanism"
};
static const char *objNSSClassArray[] = {
"CKO_NSS",
"Crl",
"SMIME Record",
"Trust",
"Builtin Root List"
};
const char *
getObjectClass(CK_ULONG classType)
{
static char buf[sizeof(CK_ULONG)*2+3];
if (classType <= CKO_MECHANISM) {
return objClassArray[classType];
}
if (classType >= CKO_NSS && classType <= CKO_NSS_BUILTIN_ROOT_LIST) {
return objNSSClassArray[classType - CKO_NSS];
}
sprintf(buf, "0x%lx", classType);
return buf;
}
char *mkNickname(unsigned char *data, int len)
{
char *nick = PORT_Alloc(len+1);
if (!nick) {
return nick;
}
PORT_Memcpy(nick, data, len);
nick[len] = 0;
return nick;
}
/*
* dump a PK11_MergeTokens error log to the console
*/
void
DumpMergeLog(const char *progname, PK11MergeLog *log)
{
PK11MergeLogNode *node;
for (node = log->head; node; node = node->next) {
SECItem attrItem;
char *nickname = NULL;
const char *objectClass = NULL;
SECStatus rv;
attrItem.data = NULL;
rv = PK11_ReadRawAttribute(PK11_TypeGeneric, node->object,
CKA_LABEL, &attrItem);
if (rv == SECSuccess) {
nickname = mkNickname(attrItem.data, attrItem.len);
PORT_Free(attrItem.data);
}
attrItem.data = NULL;
rv = PK11_ReadRawAttribute(PK11_TypeGeneric, node->object,
CKA_CLASS, &attrItem);
if (rv == SECSuccess) {
if (attrItem.len == sizeof(CK_ULONG)) {
objectClass = getObjectClass(*(CK_ULONG *)attrItem.data);
}
PORT_Free(attrItem.data);
}
fprintf(stderr, "%s: Could not merge object %s (type %s): %s\n",
progName,
nickname ? nickname : "unnamed",
objectClass ? objectClass : "unknown",
SECU_Strerror(node->error));
if (nickname) {
PORT_Free(nickname);
}
}
}
/* Certutil commands */
enum {
cmd_AddCert = 0,
@ -1588,7 +1726,9 @@ enum {
cmd_CheckCertValidity,
cmd_ChangePassword,
cmd_Version,
cmd_Batch
cmd_Batch,
cmd_Merge,
cmd_UpgradeMerge, /* test only */
};
/* Certutil options */
@ -1638,7 +1778,11 @@ enum certutilOpts {
opt_AddPolicyMapExt,
opt_AddPolicyConstrExt,
opt_AddInhibAnyExt,
opt_AddSubjectKeyIDExt
opt_AddSubjectKeyIDExt,
opt_SourceDir,
opt_SourcePrefix,
opt_UpgradeID,
opt_UpgradeTokenName
};
static const
@ -1663,7 +1807,10 @@ secuCommandFlag commands_init[] =
{ /* cmd_CheckCertValidity */ 'V', PR_FALSE, 0, PR_FALSE },
{ /* cmd_ChangePassword */ 'W', PR_FALSE, 0, PR_FALSE },
{ /* cmd_Version */ 'Y', PR_FALSE, 0, PR_FALSE },
{ /* cmd_Batch */ 'B', PR_FALSE, 0, PR_FALSE }
{ /* cmd_Batch */ 'B', PR_FALSE, 0, PR_FALSE },
{ /* cmd_Merge */ 0, PR_FALSE, 0, PR_FALSE, "merge" },
{ /* cmd_UpgradeMerge */ 0, PR_FALSE, 0, PR_FALSE,
"upgrade-merge" }
};
#define NUM_COMMANDS ((sizeof commands_init) / (sizeof commands_init[0]))
@ -1715,7 +1862,16 @@ secuCommandFlag options_init[] =
{ /* opt_AddPolicyMapExt */ 0, PR_FALSE, 0, PR_FALSE, "extPM" },
{ /* opt_AddPolicyConstrExt */ 0, PR_FALSE, 0, PR_FALSE, "extPC" },
{ /* opt_AddInhibAnyExt */ 0, PR_FALSE, 0, PR_FALSE, "extIA" },
{ /* opt_AddSubjectKeyIDExt */ 0, PR_FALSE, 0, PR_FALSE, "extSKID" }
{ /* opt_AddSubjectKeyIDExt */ 0, PR_FALSE, 0, PR_FALSE,
"extSKID" },
{ /* opt_SourceDir */ 0, PR_TRUE, 0, PR_FALSE,
"source-dir"},
{ /* opt_SourcePrefix */ 0, PR_TRUE, 0, PR_FALSE,
"source-prefix"},
{ /* opt_UpgradeID */ 0, PR_TRUE, 0, PR_FALSE,
"upgrade-id"},
{ /* opt_UpgradeTokenName */ 0, PR_TRUE, 0, PR_FALSE,
"upgrade-token-name"},
};
#define NUM_OPTIONS ((sizeof options_init) / (sizeof options_init[0]))
@ -1743,6 +1899,10 @@ certutil_main(int argc, char **argv, PRBool initialize)
char * certreqfile = "tempcertreq";
char * slotname = "internal";
char * certPrefix = "";
char * sourceDir = "";
char * srcCertPrefix = "";
char * upgradeID = "";
char * upgradeTokenName = "";
KeyType keytype = rsaKey;
char * name = NULL;
char * keysource = NULL;
@ -1755,6 +1915,7 @@ certutil_main(int argc, char **argv, PRBool initialize)
int commandsEntered = 0;
char commandToRun = '\0';
secuPWData pwdata = { PW_NONE, 0 };
secuPWData pwdata2 = { PW_NONE, 0 };
PRBool readOnly = PR_FALSE;
PRBool initialized = PR_FALSE;
@ -1781,10 +1942,23 @@ certutil_main(int argc, char **argv, PRBool initialize)
pwdata.source = PW_FROMFILE;
pwdata.data = certutil.options[opt_PasswordFile].arg;
}
if (certutil.options[opt_NewPasswordFile].arg) {
pwdata2.source = PW_FROMFILE;
pwdata2.data = certutil.options[opt_NewPasswordFile].arg;
}
if (certutil.options[opt_CertDir].activated)
SECU_ConfigDirectory(certutil.options[opt_CertDir].arg);
if (certutil.options[opt_SourceDir].activated)
sourceDir = certutil.options[opt_SourceDir].arg;
if (certutil.options[opt_UpgradeID].activated)
upgradeID = certutil.options[opt_UpgradeID].arg;
if (certutil.options[opt_UpgradeTokenName].activated)
upgradeTokenName = certutil.options[opt_UpgradeTokenName].arg;
if (certutil.options[opt_KeySize].activated) {
keysize = PORT_Atoi(certutil.options[opt_KeySize].arg);
if ((keysize < MIN_KEY_BITS) || (keysize > MAX_KEY_BITS)) {
@ -1862,6 +2036,15 @@ certutil_main(int argc, char **argv, PRBool initialize)
}
}
/* --source-prefix certdb name prefix */
if (certutil.options[opt_SourcePrefix].activated) {
if (certutil.options[opt_SourcePrefix].arg) {
srcCertPrefix = strdup(certutil.options[opt_SourcePrefix].arg);
} else {
Usage(progName);
}
}
/* -q PQG file or curve name */
if (certutil.options[opt_PQGFile].activated) {
#ifdef NSS_ENABLE_ECC
@ -2034,6 +2217,32 @@ certutil_main(int argc, char **argv, PRBool initialize)
progName);
return 255;
}
/* Upgrade/Merge needs a source database and a upgrade id. */
if (certutil.commands[cmd_UpgradeMerge].activated &&
!(certutil.options[opt_SourceDir].activated &&
certutil.options[opt_UpgradeID].activated)) {
PR_fprintf(PR_STDERR,
"%s --upgrade-merge: specify an upgrade database directory "
"(--source-dir) and\n"
" an upgrade ID (--upgrade-id).\n",
progName);
return 255;
}
/* Merge needs a source database */
if (certutil.commands[cmd_Merge].activated &&
!certutil.options[opt_SourceDir].activated) {
PR_fprintf(PR_STDERR,
"%s --merge: specify an source database directory "
"(--source-dir)\n",
progName);
return 255;
}
/* To make a cert, need either a issuer or to self-sign it. */
if (certutil.commands[cmd_CreateAndAddCert].activated &&
@ -2109,8 +2318,17 @@ certutil_main(int argc, char **argv, PRBool initialize)
if (PR_TRUE == initialize) {
/* Initialize NSPR and NSS. */
PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
rv = NSS_Initialize(SECU_ConfigDirectory(NULL), certPrefix, certPrefix,
if (!certutil.commands[cmd_UpgradeMerge].activated) {
rv = NSS_Initialize(SECU_ConfigDirectory(NULL),
certPrefix, certPrefix,
"secmod.db", readOnly ? NSS_INIT_READONLY: 0);
} else {
rv = NSS_InitWithMerge(SECU_ConfigDirectory(NULL),
certPrefix, certPrefix, "secmod.db",
sourceDir, srcCertPrefix, srcCertPrefix,
upgradeID, upgradeTokenName,
readOnly ? NSS_INIT_READONLY: 0);
}
if (rv != SECSuccess) {
SECU_PrintPRandOSError(progName);
rv = SECFailure;
@ -2130,6 +2348,8 @@ certutil_main(int argc, char **argv, PRBool initialize)
else if (slotname != NULL)
slot = PK11_FindSlotByName(slotname);
if ( !slot && (certutil.commands[cmd_NewDBs].activated ||
certutil.commands[cmd_ModifyCertTrust].activated ||
@ -2137,6 +2357,8 @@ certutil_main(int argc, char **argv, PRBool initialize)
certutil.commands[cmd_TokenReset].activated ||
certutil.commands[cmd_CreateAndAddCert].activated ||
certutil.commands[cmd_AddCert].activated ||
certutil.commands[cmd_Merge].activated ||
certutil.commands[cmd_UpgradeMerge].activated ||
certutil.commands[cmd_AddEmailCert].activated)) {
SECU_PrintError(progName, "could not find the slot %s",slotname);
@ -2150,6 +2372,132 @@ certutil_main(int argc, char **argv, PRBool initialize)
certutil.options[opt_NewPasswordFile].arg);
}
/* walk through the upgrade merge if necessary.
* This option is more to test what some applications will want to do
* to do an automatic upgrade. The --merge command is more useful for
* the general case where 2 database need to be merged together.
*/
if (certutil.commands[cmd_UpgradeMerge].activated) {
if (*upgradeTokenName == 0) {
upgradeTokenName = upgradeID;
}
if (!PK11_IsInternal(slot)) {
fprintf(stderr, "Only internal DB's can be upgraded\n");
rv = SECSuccess;
goto shutdown;
}
if (!PK11_IsRemovable(slot)) {
printf("database already upgraded.\n");
rv = SECSuccess;
goto shutdown;
}
if (!PK11_NeedLogin(slot)) {
printf("upgrade complete!\n");
rv = SECSuccess;
goto shutdown;
}
/* authenticate to the old DB if necessary */
if (PORT_Strcmp(PK11_GetTokenName(slot), upgradeTokenName) == 0) {
/* if we need a password, supply it. This will be the password
* for the old database */
rv = PK11_Authenticate(slot, PR_FALSE, &pwdata2);
if (rv != SECSuccess) {
SECU_PrintError(progName, "Could not get password for %s",
upgradeTokenName);
goto shutdown;
}
/*
* if we succeeded above, but still aren't logged in, that means
* we just supplied the password for the old database. We may
* need the password for the new database. NSS will automatically
* change the token names at this point
*/
if (PK11_IsLoggedIn(slot, &pwdata)) {
printf("upgrade complete!\n");
rv = SECSuccess;
goto shutdown;
}
}
/* call PK11_IsPresent to update our cached token information */
if (!PK11_IsPresent(slot)) {
/* this shouldn't happen. We call isPresent to force a token
* info update */
fprintf(stderr, "upgrade/merge internal error\n");
rv = SECFailure;
goto shutdown;
}
/* the token is now set to the state of the source database,
* if we need a password for it, PK11_Authenticate will
* automatically prompt us */
rv = PK11_Authenticate(slot, PR_FALSE, &pwdata);
if (rv == SECSuccess) {
printf("upgrade complete!\n");
} else {
SECU_PrintError(progName, "Could not get password for %s",
PK11_GetTokenName(slot));
}
goto shutdown;
}
/*
* merge 2 databases.
*/
if (certutil.commands[cmd_Merge].activated) {
PK11SlotInfo *sourceSlot = NULL;
PK11MergeLog *log;
char *modspec = PR_smprintf(
"configDir='%s' certPrefix='%s' tokenDescription='%s'",
sourceDir, srcCertPrefix,
*upgradeTokenName ? upgradeTokenName : "Source Database");
if (!modspec) {
rv = SECFailure;
goto shutdown;
}
sourceSlot = SECMOD_OpenUserDB(modspec);
PR_smprintf_free(modspec);
if (!sourceSlot) {
SECU_PrintError(progName, "couldn't open source database");
rv = SECFailure;
goto shutdown;
}
rv = PK11_Authenticate(slot, PR_FALSE, &pwdata);
if (rv != SECSuccess) {
SECU_PrintError(progName, "Couldn't get password for %s",
PK11_GetTokenName(slot));
goto merge_fail;
}
rv = PK11_Authenticate(sourceSlot, PR_FALSE, &pwdata2);
if (rv != SECSuccess) {
SECU_PrintError(progName, "Couldn't get password for %s",
PK11_GetTokenName(sourceSlot));
goto merge_fail;
}
log = PK11_CreateMergeLog();
if (!log) {
rv = SECFailure;
SECU_PrintError(progName, "couldn't create error log");
goto merge_fail;
}
rv = PK11_MergeTokens(slot, sourceSlot, log, &pwdata, &pwdata2);
if (rv != SECSuccess) {
DumpMergeLog(progName, log);
}
PK11_DestroyMergeLog(log);
merge_fail:
SECMOD_CloseUserDB(sourceSlot);
PK11_FreeSlot(sourceSlot);
goto shutdown;
}
/* The following 8 options are mutually exclusive with all others. */
/* List certs (-L) */

View File

@ -106,7 +106,7 @@ static CERTSignedCrl *FindCRL
return (crl);
}
static void DisplayCRL (CERTCertDBHandle *certHandle, char *nickName, int crlType)
static SECStatus DisplayCRL (CERTCertDBHandle *certHandle, char *nickName, int crlType)
{
CERTSignedCrl *crl = NULL;
@ -115,7 +115,9 @@ static void DisplayCRL (CERTCertDBHandle *certHandle, char *nickName, int crlTyp
if (crl) {
SECU_PrintCRLInfo (stdout, &crl->crl, "CRL Info:\n", 0);
SEC_DestroyCrl (crl);
return SECSuccess;
}
return SECFailure;
}
static void ListCRLNames (CERTCertDBHandle *certHandle, int crlType, PRBool deletecrls)
@ -211,12 +213,14 @@ static void ListCRLNames (CERTCertDBHandle *certHandle, int crlType, PRBool dele
PORT_FreeArena (arena, PR_FALSE);
}
static void ListCRL (CERTCertDBHandle *certHandle, char *nickName, int crlType)
static SECStatus ListCRL (CERTCertDBHandle *certHandle, char *nickName, int crlType)
{
if (nickName == NULL)
if (nickName == NULL) {
ListCRLNames (certHandle, crlType, PR_FALSE);
else
DisplayCRL (certHandle, nickName, crlType);
return SECSuccess;
}
return DisplayCRL (certHandle, nickName, crlType);
}
@ -1041,7 +1045,7 @@ int main(int argc, char **argv)
if (deleteCRL)
DeleteCRL (certHandle, nickName, crlType);
else if (listCRL) {
ListCRL (certHandle, nickName, crlType);
rv = ListCRL (certHandle, nickName, crlType);
}
else if (importCRL) {
rv = ImportCRL (certHandle, url, crlType, inFile, importOptions,

View File

@ -37,7 +37,7 @@
/*
* Test program for SDR (Secret Decoder Ring) functions.
*
* $Id: sdrtest.c,v 1.13 2004-04-25 15:02:52 gerv%gerv.net Exp $
* $Id: sdrtest.c,v 1.14 2008-03-10 20:16:44 rrelyea%redhat.com Exp $
*/
#include "nspr.h"
@ -61,8 +61,9 @@ static void
synopsis (char *program_name)
{
PR_fprintf (pr_stderr,
"Usage: %s [-d <dir>] [-v] [-t <text>] [-a] -i <input-file>\n"
" %s [-d <dir>] [-v] [-t <text>] [-a] -o <output-file>\n",
"Usage: %s [<common>] -i <input-file>\n"
" %s [<common>] -o <output-file>\n"
" <common> [-d dir] [-v] [-t text] [-a] [-f pwfile | -p pwd]\n",
program_name, program_name);
}
@ -93,6 +94,12 @@ long_usage (char *program_name)
PR_fprintf (pr_stderr,
" %-13s Find security databases in \"dbdir\"\n",
"-d dbdir");
PR_fprintf (pr_stderr,
" %-13s read the password from \"pwfile\"\n",
"-f pwfile");
PR_fprintf (pr_stderr,
" %-13s supply \"password\" on the command line\n",
"-p password");
}
int
@ -180,6 +187,7 @@ main (int argc, char **argv)
SECItem result = {0, 0, 0};
SECItem text;
PRBool ascii = PR_FALSE;
secuPWData pwdata = { PW_NONE, 0 };
pr_stderr = PR_STDERR;
result.data = 0;
@ -188,7 +196,7 @@ main (int argc, char **argv)
program_name = PL_strrchr(argv[0], '/');
program_name = program_name ? (program_name + 1) : argv[0];
optstate = PL_CreateOptState (argc, argv, "?Had:i:o:t:v");
optstate = PL_CreateOptState (argc, argv, "?Had:i:o:t:vf:p:");
if (optstate == NULL) {
SECU_PrintError (program_name, "PL_CreateOptState failed");
return -1;
@ -224,6 +232,26 @@ main (int argc, char **argv)
value = optstate->value;
break;
case 'f':
if (pwdata.data) {
PORT_Free(pwdata.data);
short_usage(program_name);
return -1;
}
pwdata.source = PW_FROMFILE;
pwdata.data = PORT_Strdup(optstate->value);
break;
case 'p':
if (pwdata.data) {
PORT_Free(pwdata.data);
short_usage(program_name);
return -1;
}
pwdata.source = PW_PLAINTEXT;
pwdata.data = PORT_Strdup(optstate->value);
break;
case 'v':
verbose = PR_TRUE;
break;
@ -298,7 +326,17 @@ main (int argc, char **argv)
/* sigh, initialize the key database */
slot = PK11_GetInternalKeySlot();
if (slot && PK11_NeedUserInit(slot)) {
rv = SECU_ChangePW(slot, "", 0);
switch (pwdata.source) {
case PW_FROMFILE:
rv = SECU_ChangePW(slot, 0, pwdata.data);
break;
case PW_PLAINTEXT:
rv = SECU_ChangePW(slot, pwdata.data, 0);
break;
default:
rv = SECU_ChangePW(slot, "", 0);
break;
}
if (rv != SECSuccess) {
SECU_PrintError(program_name, "Failed to initialize slot \"%s\"",
PK11_GetSlotName(slot));
@ -309,7 +347,7 @@ main (int argc, char **argv)
PK11_FreeSlot(slot);
}
rv = PK11SDR_Encrypt(&keyid, &data, &result, 0);
rv = PK11SDR_Encrypt(&keyid, &data, &result, &pwdata);
if (rv != SECSuccess) {
if (verbose)
SECU_PrintError(program_name, "Encrypt operation failed\n");
@ -380,7 +418,7 @@ main (int argc, char **argv)
}
/* Decrypt the value */
rv = PK11SDR_Decrypt(&result, &text, 0);
rv = PK11SDR_Decrypt(&result, &text, &pwdata);
if (rv != SECSuccess) {
if (verbose) SECU_PrintError(program_name, "Decrypt operation failed\n");
retval = -1;
@ -406,5 +444,8 @@ loser:
prdone:
PR_Cleanup ();
if (pwdata.data) {
PORT_Free(pwdata.data);
}
return retval;
}

View File

@ -926,11 +926,16 @@ CERT_NewTempCertificate;
CERT_SetOCSPTimeout;
CERT_PKIXVerifyCert;
HASH_GetType;
NSS_InitWithMerge;
PK11_CreateMergeLog;
PK11_CreateGenericObject;
PK11_CreatePBEV2AlgorithmID;
PK11_DestroyMergeLog;
PK11_GenerateKeyPairWithOpFlags;
PK11_GetAllSlotsForCert;
PK11_GetPBECryptoMechanism;
PK11_IsRemovable;
PK11_MergeTokens;
PK11_WriteRawAttribute;
SECKEY_ECParamsToBasePointOrderLen;
SECKEY_ECParamsToKeySize;

View File

@ -36,7 +36,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: nss.h,v 1.51 2007-05-04 05:15:43 nelson%bolyard.com Exp $ */
/* $Id: nss.h,v 1.52 2008-03-10 20:16:45 rrelyea%redhat.com Exp $ */
#ifndef __nss_h_
#define __nss_h_
@ -196,6 +196,21 @@ extern SECStatus NSS_Initialize(const char *configdir,
const char *certPrefix, const char *keyPrefix,
const char *secmodName, PRUint32 flags);
/*
* same as NSS_Init, but checks to see if we need to merge an
* old database in.
* updatedir is the directory where the old database lives.
* updCertPrefix is the certPrefix for the old database.
* updKeyPrefix is the keyPrefix for the old database.
* updateID is a unique identifier chosen by the application for
* the specific database.
* updatName is the name the user will be prompted for when
* asking to authenticate to the old database */
extern SECStatus NSS_InitWithMerge(const char *configdir,
const char *certPrefix, const char *keyPrefix, const char *secmodName,
const char *updatedir, const char *updCertPrefix,
const char *updKeyPrefix, const char *updateID,
const char *updateName, PRUint32 flags);
/*
* initialize NSS without a creating cert db's, key db's, or secmod db's.
*/

View File

@ -36,7 +36,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: nssinit.c,v 1.91 2008-02-23 05:29:39 nelson%bolyard.com Exp $ */
/* $Id: nssinit.c,v 1.92 2008-03-10 20:16:45 rrelyea%redhat.com Exp $ */
#include <ctype.h>
#include "seccomon.h"
@ -421,7 +421,10 @@ static CERTCertificate dummyCert;
static SECStatus
nss_Init(const char *configdir, const char *certPrefix, const char *keyPrefix,
const char *secmodName, PRBool readOnly, PRBool noCertDB,
const char *secmodName, const char *updateDir,
const char *updCertPrefix, const char *updKeyPrefix,
const char *updateID, const char *updateName,
PRBool readOnly, PRBool noCertDB,
PRBool noModDB, PRBool forceOpen, PRBool noRootInit,
PRBool optimizeSpace, PRBool noSingleThreadedModules,
PRBool allowAlreadyInitializedModules,
@ -434,6 +437,11 @@ nss_Init(const char *configdir, const char *certPrefix, const char *keyPrefix,
char *lcertPrefix = NULL;
char *lkeyPrefix = NULL;
char *lsecmodName = NULL;
char *lupdateDir = NULL;
char *lupdCertPrefix = NULL;
char *lupdKeyPrefix = NULL;
char *lupdateID = NULL;
char *lupdateName = NULL;
PKIX_UInt32 actualMinorVersion = 0;
PKIX_Error *pkixError = NULL;;
@ -480,6 +488,26 @@ nss_Init(const char *configdir, const char *certPrefix, const char *keyPrefix,
if (lsecmodName == NULL) {
goto loser;
}
lupdateDir = nss_doubleEscape(updateDir);
if (lupdateDir == NULL) {
goto loser;
}
lupdCertPrefix = nss_doubleEscape(updCertPrefix);
if (lupdCertPrefix == NULL) {
goto loser;
}
lupdKeyPrefix = nss_doubleEscape(updKeyPrefix);
if (lupdKeyPrefix == NULL) {
goto loser;
}
lupdateID = nss_doubleEscape(updateID);
if (lupdateID == NULL) {
goto loser;
}
lupdateName = nss_doubleEscape(updateName);
if (lupdateName == NULL) {
goto loser;
}
if (noSingleThreadedModules || allowAlreadyInitializedModules ||
dontFinalizeModules) {
pk11_setGlobalOptions(noSingleThreadedModules,
@ -487,10 +515,15 @@ nss_Init(const char *configdir, const char *certPrefix, const char *keyPrefix,
dontFinalizeModules);
}
moduleSpec = PR_smprintf("name=\"%s\" parameters=\"configdir='%s' certPrefix='%s' keyPrefix='%s' secmod='%s' flags=%s %s\" NSS=\"flags=internal,moduleDB,moduleDBOnly,critical\"",
moduleSpec = PR_smprintf(
"name=\"%s\" parameters=\"configdir='%s' certPrefix='%s' keyPrefix='%s' "
"secmod='%s' flags=%s updatedir='%s' updateCertPrefix='%s' "
"updateKeyPrefix='%s' updateid='%s' updateTokenDescription='%s' %s\" "
"NSS=\"flags=internal,moduleDB,moduleDBOnly,critical\"",
pk11_config_name ? pk11_config_name : NSS_DEFAULT_MOD_NAME,
lconfigdir,lcertPrefix,lkeyPrefix,lsecmodName,flags,
pk11_config_strings ? pk11_config_strings : "");
lupdateDir, lupdCertPrefix, lupdKeyPrefix, lupdateID,
lupdateName, pk11_config_strings ? pk11_config_strings : "");
loser:
PORT_Free(flags);
@ -498,6 +531,11 @@ loser:
if (lcertPrefix) PORT_Free(lcertPrefix);
if (lkeyPrefix) PORT_Free(lkeyPrefix);
if (lsecmodName) PORT_Free(lsecmodName);
if (lupdateDir) PORT_Free(lupdateDir);
if (lupdCertPrefix) PORT_Free(lupdCertPrefix);
if (lupdKeyPrefix) PORT_Free(lupdKeyPrefix);
if (lupdateID) PORT_Free(lupdateID);
if (lupdateName) PORT_Free(lupdateName);
if (moduleSpec) {
SECMODModule *module = SECMOD_LoadModule(moduleSpec,NULL,PR_TRUE);
@ -555,15 +593,17 @@ loser:
SECStatus
NSS_Init(const char *configdir)
{
return nss_Init(configdir, "", "", SECMOD_DB, PR_TRUE,
PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, PR_TRUE, PR_FALSE, PR_FALSE, PR_FALSE);
return nss_Init(configdir, "", "", SECMOD_DB, "", "", "", "", "",
PR_TRUE, PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE,
PR_TRUE, PR_FALSE, PR_FALSE, PR_FALSE);
}
SECStatus
NSS_InitReadWrite(const char *configdir)
{
return nss_Init(configdir, "", "", SECMOD_DB, PR_FALSE,
PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, PR_TRUE, PR_FALSE, PR_FALSE, PR_FALSE);
return nss_Init(configdir, "", "", SECMOD_DB, "", "", "", "", "",
PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE,
PR_TRUE, PR_FALSE, PR_FALSE, PR_FALSE);
}
/*
@ -618,7 +658,28 @@ SECStatus
NSS_Initialize(const char *configdir, const char *certPrefix,
const char *keyPrefix, const char *secmodName, PRUint32 flags)
{
return nss_Init(configdir, certPrefix, keyPrefix, secmodName,
return nss_Init(configdir, certPrefix, keyPrefix, secmodName,
"", "", "", "", "",
((flags & NSS_INIT_READONLY) == NSS_INIT_READONLY),
((flags & NSS_INIT_NOCERTDB) == NSS_INIT_NOCERTDB),
((flags & NSS_INIT_NOMODDB) == NSS_INIT_NOMODDB),
((flags & NSS_INIT_FORCEOPEN) == NSS_INIT_FORCEOPEN),
((flags & NSS_INIT_NOROOTINIT) == NSS_INIT_NOROOTINIT),
((flags & NSS_INIT_OPTIMIZESPACE) == NSS_INIT_OPTIMIZESPACE),
((flags & NSS_INIT_PK11THREADSAFE) == NSS_INIT_PK11THREADSAFE),
((flags & NSS_INIT_PK11RELOAD) == NSS_INIT_PK11RELOAD),
((flags & NSS_INIT_NOPK11FINALIZE) == NSS_INIT_NOPK11FINALIZE));
}
SECStatus
NSS_InitWithMerge(const char *configdir, const char *certPrefix,
const char *keyPrefix, const char *secmodName,
const char *updateDir, const char *updCertPrefix,
const char *updKeyPrefix, const char *updateID,
const char *updateName, PRUint32 flags)
{
return nss_Init(configdir, certPrefix, keyPrefix, secmodName,
updateDir, updCertPrefix, updKeyPrefix, updateID, updateName,
((flags & NSS_INIT_READONLY) == NSS_INIT_READONLY),
((flags & NSS_INIT_NOCERTDB) == NSS_INIT_NOCERTDB),
((flags & NSS_INIT_NOMODDB) == NSS_INIT_NOMODDB),
@ -636,7 +697,7 @@ NSS_Initialize(const char *configdir, const char *certPrefix,
SECStatus
NSS_NoDB_Init(const char * configdir)
{
return nss_Init("","","","",
return nss_Init("","","","", "", "", "", "", "",
PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,
PR_FALSE,PR_FALSE,PR_FALSE);
}

View File

@ -66,6 +66,7 @@ CSRCS = \
pk11list.c \
pk11load.c \
pk11mech.c \
pk11merge.c \
pk11nobj.c \
pk11obj.c \
pk11pars.c \

View File

@ -87,6 +87,12 @@ pk11_MakeIDFromPublicKey(SECKEYPublicKey *pubKey)
/*
* import a public key into the desired slot
*
* This function takes a public key structure and creates a public key in a
* given slot. If isToken is set, then a persistant public key is created.
*
* Note: it is possible for this function to return a handle for a key which
* is persistant, even if isToken is not set.
*/
CK_OBJECT_HANDLE
PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey,
@ -113,10 +119,12 @@ PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey,
/* free the existing key */
if (pubKey->pkcs11Slot != NULL) {
PK11SlotInfo *oSlot = pubKey->pkcs11Slot;
PK11_EnterSlotMonitor(oSlot);
(void) PK11_GETTAB(oSlot)->C_DestroyObject(oSlot->session,
if (!PK11_IsPermObject(pubKey->pkcs11Slot,pubKey->pkcs11ID)) {
PK11_EnterSlotMonitor(oSlot);
(void) PK11_GETTAB(oSlot)->C_DestroyObject(oSlot->session,
pubKey->pkcs11ID);
PK11_ExitSlotMonitor(oSlot);
PK11_ExitSlotMonitor(oSlot);
}
PK11_FreeSlot(oSlot);
pubKey->pkcs11Slot = NULL;
}
@ -1889,6 +1897,15 @@ PK11_MakeIDFromPubKey(SECItem *pubKeyData)
SECItem *certCKA_ID;
SECStatus rv;
if (pubKeyData->len <= SHA1_LENGTH) {
/* probably an already hashed value. The strongest known public
* key values <= 160 bits would be less than 40 bit symetric in
* strength. Don't hash them, just return the value. There are
* none at the time of this writing supported by previous versions
* of NSS, so change is binary compatible safe */
return SECITEM_DupItem(pubKeyData);
}
context = PK11_CreateDigestContext(SEC_OID_SHA1);
if (context == NULL) {
return NULL;

File diff suppressed because it is too large Load Diff

View File

@ -114,6 +114,7 @@ char * PK11_GetSlotName(PK11SlotInfo *slot);
PRBool PK11_NeedLogin(PK11SlotInfo *slot);
PRBool PK11_IsFriendly(PK11SlotInfo *slot);
PRBool PK11_IsHW(PK11SlotInfo *slot);
PRBool PK11_IsRemovable(PK11SlotInfo *slot);
PRBool PK11_NeedUserInit(PK11SlotInfo *slot);
PRBool PK11_ProtectedAuthenticationPath(PK11SlotInfo *slot);
int PK11_GetSlotSeries(PK11SlotInfo *slot);
@ -183,6 +184,7 @@ PK11SlotInfo *PK11_GetBestSlotMultiple(CK_MECHANISM_TYPE *type, int count,
PK11SlotInfo *PK11_GetBestSlot(CK_MECHANISM_TYPE type, void *wincx);
CK_MECHANISM_TYPE PK11_GetBestWrapMechanism(PK11SlotInfo *slot);
int PK11_GetBestKeyLength(PK11SlotInfo *slot, CK_MECHANISM_TYPE type);
/*
* Open a new database using the softoken. The caller is responsible for making
* sure the module spec is correct and usable. The caller should ask for one
@ -235,6 +237,20 @@ int PK11_GetBestKeyLength(PK11SlotInfo *slot, CK_MECHANISM_TYPE type);
PK11SlotInfo *SECMOD_OpenUserDB(const char *moduleSpec);
SECStatus SECMOD_CloseUserDB(PK11SlotInfo *slot);
/*
* merge the permanent objects from on token to another
*/
SECStatus PK11_MergeTokens(PK11SlotInfo *targetSlot, PK11SlotInfo *sourceSlot,
PK11MergeLog *log, void *targetPwArg, void *sourcePwArg);
/*
* create and destroy merge logs needed by PK11_MergeTokens
*/
PK11MergeLog * PK11_CreateMergeLog();
void PK11_DestroyMergeLog(PK11MergeLog *log);
/*********************************************************************
* Mechanism Mapping functions
*********************************************************************/
@ -288,6 +304,15 @@ PK11SymKey *PK11_GetWrapKey(PK11SlotInfo *slot, int wrap,
*/
void PK11_SetWrapKey(PK11SlotInfo *slot, int wrap, PK11SymKey *wrapKey);
CK_MECHANISM_TYPE PK11_GetMechanism(PK11SymKey *symKey);
/*
* import a public key into the desired slot
*
* This function takes a public key structure and creates a public key in a
* given slot. If isToken is set, then a persistant public key is created.
*
* Note: it is possible for this function to return a handle for a key which
* is persistant, even if isToken is not set.
*/
CK_OBJECT_HANDLE PK11_ImportPublicKey(PK11SlotInfo *slot,
SECKEYPublicKey *pubKey, PRBool isToken);
PK11SymKey *PK11_KeyGen(PK11SlotInfo *slot,CK_MECHANISM_TYPE type,

View File

@ -252,6 +252,41 @@ loser:
return rv;
}
/* decrypt a block */
static SECStatus
pk11Decrypt(PK11SlotInfo *slot, PLArenaPool *arena,
CK_MECHANISM_TYPE type, PK11SymKey *key,
SECItem *params, SECItem *in, SECItem *result)
{
PK11Context *ctx = 0;
SECItem paddedResult;
SECStatus rv;
paddedResult.len = 0;
paddedResult.data = 0;
ctx = PK11_CreateContextBySymKey(type, CKA_DECRYPT, key, params);
if (!ctx) { rv = SECFailure; goto loser; }
paddedResult.len = in->len;
paddedResult.data = PORT_ArenaAlloc(arena, paddedResult.len);
rv = PK11_CipherOp(ctx, paddedResult.data,
(int*)&paddedResult.len, paddedResult.len,
in->data, in->len);
if (rv != SECSuccess) goto loser;
PK11_Finalize(ctx);
/* Remove the padding */
rv = unpadBlock(&paddedResult, PK11_GetBlockSize(type, 0), result);
if (rv) goto loser;
loser:
if (ctx) PK11_DestroyContext(ctx, PR_TRUE);
return rv;
}
/*
* PK11SDR_Decrypt
* Decrypt a block of data produced by PK11SDR_Encrypt. The key used is identified
@ -263,15 +298,11 @@ PK11SDR_Decrypt(SECItem *data, SECItem *result, void *cx)
SECStatus rv = SECSuccess;
PK11SlotInfo *slot = 0;
PK11SymKey *key = 0;
PK11Context *ctx = 0;
CK_MECHANISM_TYPE type;
SDRResult sdrResult;
SECItem *params = 0;
SECItem paddedResult;
PLArenaPool *arena = 0;
paddedResult.len = 0;
paddedResult.data = 0;
arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
if (!arena) { rv = SECFailure; goto loser; }
@ -288,35 +319,48 @@ PK11SDR_Decrypt(SECItem *data, SECItem *result, void *cx)
rv = PK11_Authenticate(slot, PR_TRUE, cx);
if (rv != SECSuccess) goto loser;
/* Use triple-DES (Should look up the algorithm) */
type = CKM_DES3_CBC;
key = PK11_FindFixedKey(slot, type, &sdrResult.keyid, cx);
if (!key) { rv = SECFailure; goto loser; }
/* Get the parameter values from the data */
params = PK11_ParamFromAlgid(&sdrResult.alg);
if (!params) { rv = SECFailure; goto loser; }
ctx = PK11_CreateContextBySymKey(type, CKA_DECRYPT, key, params);
if (!ctx) { rv = SECFailure; goto loser; }
/* Use triple-DES (Should look up the algorithm) */
type = CKM_DES3_CBC;
key = PK11_FindFixedKey(slot, type, &sdrResult.keyid, cx);
if (!key) {
rv = SECFailure;
} else {
rv = pk11Decrypt(slot, arena, type, key, params,
&sdrResult.data, result);
}
/*
* handle the case where your key indicies may have been broken
*/
if (rv != SECSuccess) {
PK11SymKey *keyList = PK11_ListFixedKeysInSlot(slot, NULL, cx);
PK11SymKey *testKey = NULL;
PK11SymKey *nextKey = NULL;
paddedResult.len = sdrResult.data.len;
paddedResult.data = PORT_ArenaAlloc(arena, paddedResult.len);
for (testKey = keyList; testKey;
testKey = PK11_GetNextSymKey(testKey)) {
rv = pk11Decrypt(slot, arena, type, testKey, params,
&sdrResult.data, result);
if (rv == SECSuccess) {
break;
}
}
rv = PK11_CipherOp(ctx, paddedResult.data, (int*)&paddedResult.len, paddedResult.len,
sdrResult.data.data, sdrResult.data.len);
if (rv != SECSuccess) goto loser;
/* free the list */
for (testKey = keyList; testKey; testKey = nextKey) {
nextKey = PK11_GetNextSymKey(testKey);
PK11_FreeSymKey(testKey);
}
}
PK11_Finalize(ctx);
/* Remove the padding */
rv = unpadBlock(&paddedResult, PK11_GetBlockSize(type, 0), result);
if (rv) goto loser;
loser:
/* SECITEM_ZfreeItem(&paddedResult, PR_FALSE); */
if (arena) PORT_FreeArena(arena, PR_TRUE);
if (ctx) PK11_DestroyContext(ctx, PR_TRUE);
if (key) PK11_FreeSymKey(key);
if (params) SECITEM_ZfreeItem(params, PR_TRUE);
if (slot) PK11_FreeSlot(slot);

View File

@ -1494,6 +1494,12 @@ PK11_IsHW(PK11SlotInfo *slot)
return slot->isHW;
}
PRBool
PK11_IsRemovable(PK11SlotInfo *slot)
{
return !slot->isPerm;
}
PRBool
PK11_IsInternal(PK11SlotInfo *slot)
{

View File

@ -164,6 +164,8 @@ CK_OBJECT_HANDLE pk11_FindPrivateKeyFromCertID(PK11SlotInfo *slot,
SECItem *keyID);
SECKEYPrivateKey *PK11_MakePrivKey(PK11SlotInfo *slot, KeyType keyType,
PRBool isTemp, CK_OBJECT_HANDLE privID, void *wincx);
CERTCertificate *PK11_MakeCertFromHandle(PK11SlotInfo *slot,
CK_OBJECT_HANDLE certID, CK_ATTRIBUTE *privateLabel);
SECItem *pk11_GenerateNewParamWithKeyLen(CK_MECHANISM_TYPE type, int keyLen);
SECItem *pk11_ParamFromIVWithLen(CK_MECHANISM_TYPE type,

View File

@ -465,4 +465,38 @@ typedef enum {
#define CRL_IMPORT_DEFAULT_OPTIONS 0x00000000
#define CRL_IMPORT_BYPASS_CHECKS 0x00000001
/*
* Merge Error Log
*/
typedef struct PK11MergeLogStr PK11MergeLog;
typedef struct PK11MergeLogNodeStr PK11MergeLogNode;
/* These need to be global, leave some open fields so we can 'expand'
* these without breaking binary compatibility */
struct PK11MergeLogNodeStr {
PK11MergeLogNode *next; /* next entry in the list */
PK11MergeLogNode *prev; /* last entry in the list */
PK11GenericObject *object; /* object that failed */
int error; /* what the error was */
CK_RV reserved1;
unsigned long reserved2; /* future flags */
unsigned long reserved3; /* future scalar */
void *reserved4; /* future pointer */
void *reserved5; /* future expansion pointer */
};
struct PK11MergeLogStr {
PK11MergeLogNode *head;
PK11MergeLogNode *tail;
PRArenaPool *arena;
int version;
unsigned long reserved1;
unsigned long reserved2;
unsigned long reserved3;
void *reserverd4;
void *reserverd5;
};
#endif /*_SECMODT_H_ */

View File

@ -638,10 +638,12 @@ lg_FindPublicKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
case CKA_MODIFIABLE:
case CKA_EXTRACTABLE:
return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
case CKA_SUBJECT:
return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
case CKA_LABEL:
label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey);
if (label == NULL) {
return LG_CLONE_ATTR(attribute,type,lg_StaticOneAttr);
return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
}
crv = lg_CopyAttribute(attribute,type,label,PORT_Strlen(label));
PORT_Free(label);
@ -652,6 +654,9 @@ lg_FindPublicKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
key = lg_GetPublicKey(obj);
if (key == NULL) {
if (type == CKA_ID) {
return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
}
return CKR_OBJECT_HANDLE_INVALID;
}
@ -1602,6 +1607,19 @@ done:
return crv;
}
static CK_RV
lg_SetPublicKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
const void *value, unsigned int len,
PRBool *writePrivate)
{
/* we can't change the ID and we don't store the subject, but let the
* upper layers feel better about the fact we tried to set these */
if ((type == CKA_ID) || (type == CKA_SUBJECT) || (type == CKA_LABEL)) {
return CKR_OK;
}
return CKR_ATTRIBUTE_READ_ONLY;
}
static CK_RV
lg_SetTrustAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attr)
{
@ -1613,11 +1631,15 @@ lg_SetTrustAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attr)
SECStatus rv;
CK_RV crv;
if (attr->type == CKA_LABEL) {
return CKR_OK;
}
crv = lg_GetULongAttribute(attr->type, attr, 1, &trust);
if (crv != CKR_OK) {
return crv;
}
flags = lg_MapTrust(trust, (PRBool) (attr->type == CKA_TRUST_SERVER_AUTH));
flags = lg_MapTrust(trust, (PRBool) (attr->type == CKA_TRUST_CLIENT_AUTH));
certHandle = lg_getCertDB(obj->sdb);
@ -1704,6 +1726,10 @@ lg_SetSingleAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attr,
crv = lg_SetPrivateKeyAttribute(obj,attr->type,
attr->pValue,attr->ulValueLen, writePrivate);
break;
case CKO_PUBLIC_KEY:
crv = lg_SetPublicKeyAttribute(obj,attr->type,
attr->pValue,attr->ulValueLen, writePrivate);
break;
}
return crv;
}

View File

@ -205,7 +205,7 @@ sftkdb_encrypt_stub(PRArenaPool *arena, SDB *sdb, SECItem *plainText,
return SECFailure;
}
/* if we aren't th handle, try the other handle */
/* if we aren't the key handle, try the other handle */
if (handle->type != SFTK_KEYDB_TYPE) {
handle = handle->peerDB;
}
@ -239,12 +239,14 @@ sftkdb_decrypt_stub(SDB *sdb, SECItem *cipherText, SECItem **plainText)
{
SFTKDBHandle *handle = sdb->app_private;
SECStatus rv;
SECItem *oldKey = NULL;
if (handle == NULL) {
return SECFailure;
}
/* if we aren't th handle, try the other handle */
oldKey = handle->oldKey;
if (handle->type != SFTK_KEYDB_TYPE) {
handle = handle->peerDB;
}
@ -260,7 +262,8 @@ sftkdb_decrypt_stub(SDB *sdb, SECItem *cipherText, SECItem **plainText)
/* PORT_SetError */
return SECFailure;
}
rv = sftkdb_DecryptAttribute(&handle->passwordKey, cipherText, plainText);
rv = sftkdb_DecryptAttribute( oldKey ? oldKey : &handle->passwordKey,
cipherText, plainText);
PZ_Unlock(handle->passwordLock);
return rv;

View File

@ -478,11 +478,11 @@ void ForkedChild(void)
#endif
static char *
sftk_setStringName(const char *inString, char *buffer, int buffer_length)
sftk_setStringName(const char *inString, char *buffer, int buffer_length, PRBool nullTerminate)
{
int full_length, string_length;
full_length = buffer_length -1;
full_length = nullTerminate ? buffer_length -1 : buffer_length;
string_length = PORT_Strlen(inString);
/*
* shorten the string, respecting utf8 encoding
@ -522,7 +522,9 @@ sftk_setStringName(const char *inString, char *buffer, int buffer_length)
}
}
PORT_Memset(buffer,' ',full_length);
buffer[full_length] = 0;
if (nullTerminate) {
buffer[full_length] = 0;
}
PORT_Memcpy(buffer,inString,string_length);
return buffer;
}
@ -536,11 +538,12 @@ sftk_configure(const char *man, const char *libdes)
/* make sure the internationalization was done correctly... */
if (man) {
manufacturerID = sftk_setStringName(man,manufacturerID_space,
sizeof(manufacturerID_space));
sizeof(manufacturerID_space), PR_TRUE);
}
if (libdes) {
libraryDescription = sftk_setStringName(libdes,
libraryDescription_space, sizeof(libraryDescription_space));
libraryDescription_space, sizeof(libraryDescription_space),
PR_TRUE);
}
return CKR_OK;
@ -554,13 +557,13 @@ sftk_configure(const char *man, const char *libdes)
* see if the key DB password is enabled
*/
static PRBool
sftk_hasNullPassword(SFTKDBHandle *keydb)
sftk_hasNullPassword(SFTKSlot *slot, SFTKDBHandle *keydb)
{
PRBool pwenabled;
pwenabled = PR_FALSE;
if (sftkdb_HasPasswordSet(keydb) == SECSuccess) {
return (sftkdb_CheckPassword(keydb, "") == SECSuccess);
return (sftkdb_CheckPassword(slot, keydb, "") == SECSuccess);
}
return pwenabled;
@ -2028,8 +2031,8 @@ sftk_RegisterSlot(SFTKSlot *slot, int moduleIndex)
*
*/
CK_RV
SFTK_SlotReInit(SFTKSlot *slot,
char *configdir,sftk_token_parameters *params, int moduleIndex)
SFTK_SlotReInit(SFTKSlot *slot, char *configdir, char *updatedir,
char *updateID, sftk_token_parameters *params, int moduleIndex)
{
PRBool needLogin = !params->noKeyDB;
CK_RV crv;
@ -2048,15 +2051,21 @@ SFTK_SlotReInit(SFTKSlot *slot,
slot->readOnly = params->readOnly;
sftk_setStringName(params->tokdes ? params->tokdes :
sftk_getDefTokName(slot->slotID), slot->tokDescription,
sizeof(slot->tokDescription));
sizeof(slot->tokDescription),PR_TRUE);
sftk_setStringName(params->updtokdes ? params->updtokdes : " ",
slot->updateTokDescription,
sizeof(slot->updateTokDescription),PR_TRUE);
if ((!params->noCertDB) || (!params->noKeyDB)) {
SFTKDBHandle * certHandle = NULL;
SFTKDBHandle *keyHandle = NULL;
crv = sftk_DBInit(params->configdir ? params->configdir : configdir,
params->certPrefix, params->keyPrefix, params->readOnly,
params->noCertDB, params->noKeyDB, params->forceOpen,
&certHandle, &keyHandle);
params->certPrefix, params->keyPrefix,
params->updatedir ? params->updatedir : updatedir,
params->updCertPrefix, params->updKeyPrefix,
params->updateID ? params->updateID : updateID,
params->readOnly, params->noCertDB, params->noKeyDB,
params->forceOpen, &certHandle, &keyHandle);
if (crv != CKR_OK) {
goto loser;
}
@ -2067,7 +2076,7 @@ SFTK_SlotReInit(SFTKSlot *slot,
if (needLogin) {
/* if the data base is initialized with a null password,remember that */
slot->needLogin =
(PRBool)!sftk_hasNullPassword(slot->keyDB);
(PRBool)!sftk_hasNullPassword(slot, slot->keyDB);
if ((params->minPW >= 0) && (params->minPW <= SFTK_MAX_PIN)) {
slot->minimumPinLen = params->minPW;
}
@ -2092,7 +2101,8 @@ loser:
* initialize one of the slot structures. figure out which by the ID
*/
CK_RV
SFTK_SlotInit(char *configdir,sftk_token_parameters *params, int moduleIndex)
SFTK_SlotInit(char *configdir, char *updatedir, char *updateID,
sftk_token_parameters *params, int moduleIndex)
{
unsigned int i;
CK_SLOT_ID slotID = params->slotID;
@ -2155,11 +2165,12 @@ SFTK_SlotInit(char *configdir,sftk_token_parameters *params, int moduleIndex)
slot->slotID = slotID;
sftk_setStringName(params->slotdes ? params->slotdes :
sftk_getDefSlotName(slotID), slot->slotDescription,
sizeof(slot->slotDescription));
sizeof(slot->slotDescription), PR_TRUE);
/* call the reinit code to set everything that changes between token
* init calls */
crv = SFTK_SlotReInit(slot, configdir, params, moduleIndex);
crv = SFTK_SlotReInit(slot, configdir, updatedir, updateID,
params, moduleIndex);
if (crv != CKR_OK) {
goto loser;
}
@ -2177,7 +2188,7 @@ loser:
}
static CK_RV sft_CloseAllSession(SFTKSlot *slot)
CK_RV sftk_CloseAllSessions(SFTKSlot *slot)
{
SFTKSession *session;
unsigned int i;
@ -2268,7 +2279,7 @@ SFTK_ShutdownSlot(SFTKSlot *slot)
* the sessHashSize variable guarentees we have all the session
* mechanism set up */
if (slot->head) {
sft_CloseAllSession(slot);
sftk_CloseAllSessions(slot);
}
/* clear all objects.. session objects are cleared as a result of
@ -2518,8 +2529,8 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
for (i=0; i < paramStrings.token_count; i++) {
crv = SFTK_SlotInit(paramStrings.configdir,
&paramStrings.tokens[i],
moduleIndex);
paramStrings.updatedir, paramStrings.updateID,
&paramStrings.tokens[i], moduleIndex);
if (crv != CKR_OK) {
nscFreeAllSlots(moduleIndex);
break;
@ -2660,13 +2671,28 @@ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
pInfo->firmwareVersion.major = 0;
pInfo->firmwareVersion.minor = 0;
PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32);
PORT_Memcpy(pInfo->slotDescription,slot->slotDescription,64);
PORT_Memcpy(pInfo->manufacturerID,manufacturerID,
sizeof(pInfo->manufacturerID));
PORT_Memcpy(pInfo->slotDescription,slot->slotDescription,
sizeof(pInfo->slotDescription));
pInfo->flags = (slot->present) ? CKF_TOKEN_PRESENT : 0;
/* all user defined slots are defined as removable */
if (slotID >= SFTK_MIN_USER_SLOT_ID) {
pInfo->flags |= CKF_REMOVABLE_DEVICE;
} else {
/* In the case where we are doing a merge update, we need
* the DB slot to be removable so the token name can change
* appropriately. */
SFTKDBHandle *handle = sftk_getKeyDB(slot);
if (handle) {
if (sftkdb_InUpdateMerge(handle)) {
pInfo->flags |= CKF_REMOVABLE_DEVICE;
}
sftk_freeDB(handle);
}
}
/* ok we really should read it out of the keydb file. */
/* pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; */
pInfo->hardwareVersion.major = SOFTOKEN_VMAJOR;
@ -2684,10 +2710,22 @@ sftk_checkNeedLogin(SFTKSlot *slot, SFTKDBHandle *keyHandle)
if (sftkdb_PWCached(keyHandle) == SECSuccess) {
return slot->needLogin;
}
slot->needLogin = (PRBool)!sftk_hasNullPassword(keyHandle);
slot->needLogin = (PRBool)!sftk_hasNullPassword(slot, keyHandle);
return (slot->needLogin);
}
static PRBool
sftk_isBlank(const char *s, int len)
{
int i;
for (i=0; i < len; i++) {
if (s[i] != ' ') {
return PR_FALSE;
}
}
return PR_TRUE;
}
/* NSC_GetTokenInfo obtains information about a particular token in
* the system. */
CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
@ -2711,7 +2749,7 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
pInfo->ulRwSessionCount = slot->rwSessionCount;
pInfo->firmwareVersion.major = 0;
pInfo->firmwareVersion.minor = 0;
PORT_Memcpy(pInfo->label,slot->tokDescription,32);
PORT_Memcpy(pInfo->label,slot->tokDescription,sizeof(pInfo->label));
handle = sftk_getKeyDB(slot);
pInfo->flags = CKF_RNG | CKF_DUAL_CRYPTO_OPERATIONS;
if (handle == NULL) {
@ -2740,6 +2778,27 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
pInfo->flags |= CKF_USER_PIN_INITIALIZED;
} else {
pInfo->flags |= CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED;
/*
* if we are doing a merge style update, and we need to get the password
* of our source database (the database we are updating from), make sure we
* return a token name that will match the database we are prompting for.
*/
if (sftkdb_NeedUpdateDBPassword(handle)) {
/* if we have an update tok description, use it. otherwise
* use the updateID for this database */
if (!sftk_isBlank(slot->updateTokDescription,
sizeof(pInfo->label))) {
PORT_Memcpy(pInfo->label,slot->updateTokDescription,
sizeof(pInfo->label));
} else {
/* build from updateID */
const char *updateID = sftkdb_GetUpdateID(handle);
if (updateID) {
sftk_setStringName(updateID, (char *)pInfo->label,
sizeof(pInfo->label), PR_FALSE);
}
}
}
}
pInfo->ulMaxPinLen = SFTK_MAX_PIN;
pInfo->ulMinPinLen = (CK_ULONG)slot->minimumPinLen;
@ -2988,7 +3047,7 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession,
/* build the hashed pins which we pass around */
/* change the data base */
rv = sftkdb_ChangePassword(handle, NULL, newPinStr);
rv = sftkdb_ChangePassword(slot, handle, NULL, newPinStr);
sftk_freeDB(handle);
handle = NULL;
@ -3067,7 +3126,7 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
/* change the data base password */
PR_Lock(slot->pwCheckLock);
rv = sftkdb_ChangePassword(handle, oldPinStr, newPinStr);
rv = sftkdb_ChangePassword(slot, handle, oldPinStr, newPinStr);
sftk_freeDB(handle);
handle = NULL;
if ((rv != SECSuccess) && (slot->slotID == FIPS_SLOT_ID)) {
@ -3205,7 +3264,7 @@ CK_RV NSC_CloseAllSessions (CK_SLOT_ID slotID)
slot = sftk_SlotFromID(slotID, PR_FALSE);
if (slot == NULL) return CKR_SLOT_ID_INVALID;
return sft_CloseAllSession(slot);
return sftk_CloseAllSessions(slot);
}
@ -3313,18 +3372,22 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
/* build the hashed pins which we pass around */
PR_Lock(slot->pwCheckLock);
rv = sftkdb_CheckPassword(handle,pinStr);
sftk_freeDB(handle);
handle = NULL;
rv = sftkdb_CheckPassword(slot,handle,pinStr);
if ((rv != SECSuccess) && (slot->slotID == FIPS_SLOT_ID)) {
PR_Sleep(loginWaitTime);
}
PR_Unlock(slot->pwCheckLock);
if (rv == SECSuccess) {
PZ_Lock(slot->slotLock);
slot->isLoggedIn = PR_TRUE;
/* make sure the login state matches the underlying
* database state */
slot->isLoggedIn = sftkdb_PWCached(handle) == SECSuccess ?
PR_TRUE : PR_FALSE;
PZ_Unlock(slot->slotLock);
sftk_freeDB(handle);
handle = NULL;
/* update all sessions */
sftk_update_all_states(slot);
return CKR_OK;
@ -3450,9 +3513,11 @@ static CK_RV sftk_CreateNewSlot(SFTKSlot *slot, CK_OBJECT_CLASS class,
if (newSlot) {
crv = SFTK_SlotReInit(newSlot, paramStrings.configdir,
paramStrings.updatedir, paramStrings.updateID,
&paramStrings.tokens[0], moduleIndex);
} else {
crv = SFTK_SlotInit(paramStrings.configdir,
paramStrings.updatedir, paramStrings.updateID,
&paramStrings.tokens[0], moduleIndex);
}
if (crv != CKR_OK) {

View File

@ -376,7 +376,8 @@ struct SFTKSlotStr {
SFTKSession **head; /* variable -reset */
unsigned int sessHashSize; /* invariant */
char tokDescription[33]; /* per load */
char slotDescription[64]; /* invariant */
char updateTokDescription[33]; /* per load */
char slotDescription[65]; /* invariant */
};
/*
@ -530,8 +531,13 @@ typedef struct sftk_token_parametersStr {
char *configdir;
char *certPrefix;
char *keyPrefix;
char *updatedir;
char *updCertPrefix;
char *updKeyPrefix;
char *updateID;
char *tokdes;
char *slotdes;
char *updtokdes;
int minPW;
PRBool readOnly;
PRBool noCertDB;
@ -543,6 +549,8 @@ typedef struct sftk_token_parametersStr {
typedef struct sftk_parametersStr {
char *configdir;
char *updatedir;
char *updateID;
char *secmodName;
char *man;
char *libdes;
@ -580,12 +588,14 @@ extern CK_RV nsc_CommonGetSlotList(CK_BBOOL tokPresent,
CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount, int moduleIndex);
/* slot initialization, reinit, shutdown and destruction */
extern CK_RV SFTK_SlotInit(char *configdir,
extern CK_RV SFTK_SlotInit(char *configdir, char *updatedir, char *updateID,
sftk_token_parameters *params, int moduleIndex);
extern CK_RV SFTK_SlotReInit(SFTKSlot *slot, char *configdir,
char *updatedir, char *updateID,
sftk_token_parameters *params, int moduleIndex);
extern CK_RV SFTK_DestroySlotData(SFTKSlot *slot);
extern CK_RV SFTK_ShutdownSlot(SFTKSlot *slot);
extern CK_RV sftk_CloseAllSessions(SFTKSlot *slot);
/* internal utility functions used by pkcs11.c */

File diff suppressed because it is too large Load Diff

View File

@ -71,12 +71,18 @@ SECStatus sftkdb_AddSecmodDB(SDBType dbType, const char *appName,
/* keydb functions */
SECStatus sftkdb_PWIsInitialized(SFTKDBHandle *keydb);
SECStatus sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw);
SECStatus sftkdb_CheckPassword(SFTKSlot * slot, SFTKDBHandle *keydb, const char *pw);
SECStatus sftkdb_PWCached(SFTKDBHandle *keydb);
SECStatus sftkdb_HasPasswordSet(SFTKDBHandle *keydb);
SECStatus sftkdb_ResetKeyDB(SFTKDBHandle *keydb);
SECStatus sftkdb_ChangePassword(SFTKDBHandle *keydb, char *oldPin, char *newPin);
SECStatus sftkdb_ChangePassword(SFTKSlot *slot, SFTKDBHandle *keydb,
char *oldPin, char *newPin);
SECStatus sftkdb_ClearPassword(SFTKDBHandle *keydb);
SECStatus sftkdb_InUpdateMerge(SFTKDBHandle *keydb);
SECStatus sftkdb_NeedUpdateDBPassword(SFTKDBHandle *keydb);
const char *sftkdb_GetUpdateID(SFTKDBHandle *keydb);
SECItem *sftkdb_GetUpdatePasswordKey(SFTKDBHandle *keydb);
void sftkdb_FreeUpdatePasswordKey(SFTKDBHandle *keydb);
/* Utility functions */
/*
@ -96,8 +102,10 @@ SECStatus sftkdb_ClearPassword(SFTKDBHandle *keydb);
* forceOpen - Continue to force initializations even if the databases cannot
* be opened.
*/
CK_RV sftk_DBInit(const char *configdir, const char *certPrefix,
const char *keyPrefix, PRBool readOnly, PRBool noCertDB,
CK_RV sftk_DBInit(const char *configdir, const char *certPrefix,
const char *keyPrefix, const char *updatedir,
const char *updCertPrefix, const char *updKeyPrefix,
const char *updateID, PRBool readOnly, PRBool noCertDB,
PRBool noKeyDB, PRBool forceOpen,
SFTKDBHandle **certDB, SFTKDBHandle **keyDB);
CK_RV sftkdb_Shutdown(void);

View File

@ -46,9 +46,13 @@ struct SFTKDBHandleStr {
CK_OBJECT_HANDLE type;
SECItem passwordKey;
SECItem *newKey;
SECItem *oldKey;
SECItem *updatePasswordKey;
PZLock *passwordLock;
SFTKDBHandle *peerDB;
SDB *update;
char *updateID;
PRBool updateDBIsInit;
};
#define SFTK_KEYDB_TYPE 0x40000000

View File

@ -15,7 +15,7 @@
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* Portions created by the Initial Developer are Copyright (C) 1994-2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
@ -344,9 +344,15 @@ sftk_parseTokenParameters(char *param, sftk_token_parameters *parsed)
while (*index) {
SFTK_HANDLE_STRING_ARG(index,parsed->configdir,"configDir=",;)
SFTK_HANDLE_STRING_ARG(index,parsed->updatedir,"updateDir=",;)
SFTK_HANDLE_STRING_ARG(index,parsed->updCertPrefix,"updateCertPrefix=",;)
SFTK_HANDLE_STRING_ARG(index,parsed->updKeyPrefix,"updateKeyPrefix=",;)
SFTK_HANDLE_STRING_ARG(index,parsed->updateID,"updateID=",;)
SFTK_HANDLE_STRING_ARG(index,parsed->certPrefix,"certPrefix=",;)
SFTK_HANDLE_STRING_ARG(index,parsed->keyPrefix,"keyPrefix=",;)
SFTK_HANDLE_STRING_ARG(index,parsed->tokdes,"tokenDescription=",;)
SFTK_HANDLE_STRING_ARG(index,parsed->updtokdes,
"updateTokenDescription=",;)
SFTK_HANDLE_STRING_ARG(index,parsed->slotdes,"slotDescription=",;)
SFTK_HANDLE_STRING_ARG(index,tmp,"minPWLen=",
if(tmp) { parsed->minPW=atoi(tmp); PORT_Free(tmp); })
@ -410,9 +416,9 @@ sftk_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS)
char *tmp;
char *index;
char *certPrefix = NULL, *keyPrefix = NULL;
char *tokdes = NULL, *ptokdes = NULL;
char *tokdes = NULL, *ptokdes = NULL, *pupdtokdes = NULL;
char *slotdes = NULL, *pslotdes = NULL;
char *fslotdes = NULL, *fpslotdes = NULL;
char *fslotdes = NULL, *ftokdes = NULL, *fupdtokdes = NULL;
char *minPW = NULL;
index = sftk_argStrip(param);
@ -420,6 +426,8 @@ sftk_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS)
while (*index) {
SFTK_HANDLE_STRING_ARG(index,parsed->configdir,"configDir=",;)
SFTK_HANDLE_STRING_ARG(index,parsed->updatedir,"updateDir=",;)
SFTK_HANDLE_STRING_ARG(index,parsed->updateID,"updateID=",;)
SFTK_HANDLE_STRING_ARG(index,parsed->secmodName,"secmod=",;)
SFTK_HANDLE_STRING_ARG(index,parsed->man,"manufacturerID=",;)
SFTK_HANDLE_STRING_ARG(index,parsed->libdes,"libraryDescription=",;)
@ -431,7 +439,8 @@ sftk_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS)
SFTK_HANDLE_STRING_ARG(index,slotdes,"cryptoSlotDescription=",;)
SFTK_HANDLE_STRING_ARG(index,pslotdes,"dbSlotDescription=",;)
SFTK_HANDLE_STRING_ARG(index,fslotdes,"FIPSSlotDescription=",;)
SFTK_HANDLE_STRING_ARG(index,fpslotdes,"FIPSTokenDescription=",;)
SFTK_HANDLE_STRING_ARG(index,ftokdes,"FIPSTokenDescription=",;)
SFTK_HANDLE_STRING_ARG(index,pupdtokdes, "updateTokenDescription=",;)
SFTK_HANDLE_STRING_ARG(index,minPW,"minPWLen=",;)
SFTK_HANDLE_STRING_ARG(index,tmp,"flags=",
@ -466,18 +475,22 @@ sftk_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS)
certPrefix = NULL;
keyPrefix = NULL;
if (isFIPS) {
tokens[index].tokdes = fslotdes;
tokens[index].slotdes = fpslotdes;
tokens[index].tokdes = ftokdes;
tokens[index].updtokdes = pupdtokdes;
tokens[index].slotdes = fslotdes;
fslotdes = NULL;
fpslotdes = NULL;
ftokdes = NULL;
fupdtokdes = NULL;
} else {
tokens[index].tokdes = ptokdes;
tokens[index].updtokdes = pupdtokdes;
tokens[index].slotdes = pslotdes;
tokens[0].slotID = NETSCAPE_SLOT_ID;
tokens[0].tokdes = tokdes;
tokens[0].slotdes = slotdes;
tokens[0].noCertDB = PR_TRUE;
tokens[0].noKeyDB = PR_TRUE;
pupdtokdes = NULL;
ptokdes = NULL;
pslotdes = NULL;
tokdes = NULL;
@ -490,10 +503,12 @@ loser:
FREE_CLEAR(keyPrefix);
FREE_CLEAR(tokdes);
FREE_CLEAR(ptokdes);
FREE_CLEAR(pupdtokdes);
FREE_CLEAR(slotdes);
FREE_CLEAR(pslotdes);
FREE_CLEAR(fslotdes);
FREE_CLEAR(fpslotdes);
FREE_CLEAR(ftokdes);
FREE_CLEAR(fupdtokdes);
FREE_CLEAR(minPW);
return CKR_OK;
}

View File

@ -550,6 +550,114 @@ sftkdb_switchKeys(SFTKDBHandle *keydb, SECItem *passKey)
PZ_Unlock(keydb->passwordLock);
}
/*
* returns true if we are in a middle of a merge style update.
*/
PRBool
sftkdb_InUpdateMerge(SFTKDBHandle *keydb)
{
return keydb->updateID ? PR_TRUE : PR_FALSE;
}
/*
* returns true if we are looking for the password for the user's old source
* database as part of a merge style update.
*/
PRBool
sftkdb_NeedUpdateDBPassword(SFTKDBHandle *keydb)
{
if (!sftkdb_InUpdateMerge(keydb)) {
return PR_FALSE;
}
if (keydb->updateDBIsInit && !keydb->updatePasswordKey) {
return PR_TRUE;
}
return PR_FALSE;
}
/*
* fetch an update password key from a handle.
*/
SECItem *
sftkdb_GetUpdatePasswordKey(SFTKDBHandle *handle)
{
SECItem *key = NULL;
/* if we're a cert db, fetch it from our peer key db */
if (handle->type == SFTK_CERTDB_TYPE) {
handle = handle->peerDB;
}
/* don't have one */
if (!handle) {
return NULL;
}
PZ_Lock(handle->passwordLock);
if (handle->updatePasswordKey) {
key = SECITEM_DupItem(handle->updatePasswordKey);
}
PZ_Unlock(handle->passwordLock);
return key;
}
/*
* free the update password key from a handle.
*/
void
sftkdb_FreeUpdatePasswordKey(SFTKDBHandle *handle)
{
SECItem *key = NULL;
/* if we're a cert db, we don't have one */
if (handle->type == SFTK_CERTDB_TYPE) {
return;
}
/* don't have one */
if (!handle) {
return;
}
PZ_Lock(handle->passwordLock);
if (handle->updatePasswordKey) {
key = handle->updatePasswordKey;
handle->updatePasswordKey = NULL;
}
PZ_Unlock(handle->passwordLock);
if (key) {
SECITEM_ZfreeItem(key, PR_TRUE);
}
return;
}
/*
* what password db we use depends heavily on the update state machine
*
* 1) no update db, return the normal database.
* 2) update db and no merge return the update db.
* 3) update db and in merge:
* return the update db if we need the update db's password,
* otherwise return our normal datbase.
*/
static SDB *
sftk_getPWSDB(SFTKDBHandle *keydb)
{
if (!keydb->update) {
return keydb->db;
}
if (!sftkdb_InUpdateMerge(keydb)) {
return keydb->update;
}
if (sftkdb_NeedUpdateDBPassword(keydb)) {
return keydb->update;
}
return keydb->db;
}
/*
* return success if we have a valid password entry.
* This is will show up outside of PKCS #11 as CKF_USER_PIN_INIT
@ -568,7 +676,7 @@ sftkdb_HasPasswordSet(SFTKDBHandle *keydb)
return SECFailure;
}
db = SFTK_GET_SDB(keydb);
db = sftk_getPWSDB(keydb);
if (db == NULL) {
return SECFailure;
}
@ -588,7 +696,7 @@ sftkdb_HasPasswordSet(SFTKDBHandle *keydb)
* check if the supplied password is valid
*/
SECStatus
sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw)
sftkdb_CheckPassword(SFTKSlot *slot, SFTKDBHandle *keydb, const char *pw)
{
SECStatus rv;
SECItem salt, value;
@ -603,7 +711,7 @@ sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw)
return SECFailure;
}
db = SFTK_GET_SDB(keydb);
db = sftk_getPWSDB(keydb);
if (db == NULL) {
return SECFailure;
}
@ -621,27 +729,133 @@ sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw)
crv = (*db->sdb_GetMetaData)(db, "password", &salt, &value);
if (crv != CKR_OK) {
rv = SECFailure;
goto loser;
goto done;
}
/* get our intermediate key based on the entry salt value */
rv = sftkdb_passwordToKey(keydb, &salt, pw, &key);
if (rv != SECSuccess) {
goto loser;
goto done;
}
/* decrypt the entry value */
rv = sftkdb_DecryptAttribute(&key, &value, &result);
if (rv != SECSuccess) {
goto loser;
goto done;
}
/* if it's what we expect, update our key in the database handle and
* return Success */
if ((result->len == SFTK_PW_CHECK_LEN) &&
PORT_Memcmp(result->data, SFTK_PW_CHECK_STRING, SFTK_PW_CHECK_LEN) == 0){
/*
* We have a password, now lets handle any potential update cases..
*
* First, the normal case: no update. In this case we only need the
* the password for our only DB, which we now have, we switch
* the keys and fall through.
* Second regular (non-merge) update: The target DB does not yet have
* a password initialized, we now have the password for the source DB,
* so we can switch the keys and simply update the target database.
* Merge update case: This one is trickier.
* 1) If we need the source DB password, then we just got it here.
* We need to save that password,
* then we need to check to see if we need or have the target
* database password.
* If we have it (it's the same as the source), or don't need
* it (it's not set or is ""), we can start the update now.
* If we don't have it, we need the application to get it from
* the user. Clear our sessions out to simulate a token
* removal. C_GetTokenInfo will change the token description
* and the token will still appear to be logged out.
* 2) If we already have the source DB password, this password is
* for the target database. We can now move forward with the
* update, as we now have both required passwords.
*
*/
PZ_Lock(keydb->passwordLock);
if (sftkdb_NeedUpdateDBPassword(keydb)) {
/* Squirrel this special key away.
* This has the side effect of turning sftkdb_NeedLegacyPW off,
* as well as changing which database is returned from
* SFTK_GET_PW_DB (thus effecting both sftkdb_CheckPassword()
* and sftkdb_HasPasswordSet()) */
keydb->updatePasswordKey = SECITEM_DupItem(&key);
PZ_Unlock(keydb->passwordLock);
if (keydb->updatePasswordKey == NULL) {
/* PORT_Error set by SECITEM_DupItem */
rv = SECFailure;
goto done;
}
/* Simulate a token removal -- we need to do this any
* any case at this point so the token name is correct. NOTE: if
* slot is NULL, then we were called from the database init code,
* there are no sessions, so there is no need to close them. */
if (slot) {
sftk_CloseAllSessions(slot);
}
/*
* OK, we got the update DB password, see if we need a password
* for the target...
*/
if (sftkdb_HasPasswordSet(keydb) == SECSuccess) {
/* We have a password, do we know what the password is?
* check 1) for the password the user supplied for the
* update DB,
* and 2) for the null password.
*
* RECURSION NOTE: we are calling ourselves here. This means
* any updates, switchKeys, etc will have been completed
* if these functions return successfully, in those cases
* just exit returning Success. We don't recurse infinitely
* because we are making this call from a NeedUpdateDBPassword
* block and we've already set that update password at this
* point. */
rv = sftkdb_CheckPassword(slot, keydb, pw);
if (rv == SECSuccess) {
/* source and target databases have the same password, we
* are good to go */
goto done;
}
sftkdb_CheckPassword(slot, keydb, "");
/*
* Important 'NULL' code here. At this point either we
* succeeded in logging in with "" or we didn't.
*
* If we did succeed at login, our machine state will be set
* to logged in appropriately. The application will find that
* it's logged in as soon as it opens a new session. We have
* also completed the update. Life is good.
*
* If we did not succeed, well the user still successfully
* logged into the update database, since we faked the token
* removal it's just like the user logged into his smart card
* then removed it. the actual login work, so we report that
* success back to the user, but we won't actually be
* logged in. The application will find this out when it
* checks it's login state, thus triggering another password
* prompt so we can get the real target DB password.
*
* summary, we exit from here with SECSuccess no matter what.
*/
rv = SECSuccess;
goto done;
} else {
/* there is no password, just fall through to update.
* update will write the source DB's password record
* into the target DB just like it would in a non-merge
* update case. */
}
} else {
PZ_Unlock(keydb->passwordLock);
}
/* load the keys, so the keydb can parse it's key set */
sftkdb_switchKeys(keydb, &key);
/* we need to update, do it now */
if (keydb->update) {
/* update the peer certdb if it exists */
if (keydb->peerDB) {
@ -654,7 +868,7 @@ sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw)
/*PORT_SetError( bad password); */
}
loser:
done:
if (key.data) {
PORT_ZFree(key.data,key.len);
}
@ -951,7 +1165,8 @@ sftkdb_convertObjects(SFTKDBHandle *handle, CK_ATTRIBUTE *template,
* change the database password.
*/
SECStatus
sftkdb_ChangePassword(SFTKDBHandle *keydb, char *oldPin, char *newPin)
sftkdb_ChangePassword(SFTKSlot *slot, SFTKDBHandle *keydb,
char *oldPin, char *newPin)
{
SECStatus rv = SECSuccess;
SECItem plainText;
@ -987,7 +1202,7 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb, char *oldPin, char *newPin)
value.len = sizeof(valueData);
crv = (*db->sdb_GetMetaData)(db, "password", &salt, &value);
if (crv == CKR_OK) {
rv = sftkdb_CheckPassword(keydb, oldPin);
rv = sftkdb_CheckPassword(slot, keydb, oldPin);
if (rv == SECFailure) {
goto loser;
}

View File

@ -97,7 +97,7 @@ run_tests()
done
}
tests="cipher perf libpkix cert dbtests tools fips sdr crmf smime ssl ocsp"
tests="cipher perf libpkix cert dbtests tools fips sdr crmf smime ssl ocsp merge"
if [ -z "$BUILD_LIBPKIX_TESTS" ] ; then
tests=`echo "${tests}" | sed -e "s/libpkix//"`
fi
@ -132,6 +132,7 @@ env_backup > ${ENV_BACKUP}
# standard tests, no pkix, no sharedb
if [ -z "$NSS_TEST_DISABLE_STANDARD" ] ; then
TEST_MODE=STANDARD
run_tests
fi
@ -152,6 +153,7 @@ if [ -z "$NSS_TEST_DISABLE_PKIX" ] ; then
TESTS=`echo "${ALL_TESTS}" | sed -e "s/cipher//" -e "s/libpkix//" \
-e "s/dbupgrade//"`
TEST_MODE=PKIX
run_tests
. ${ENV_BACKUP}
@ -161,6 +163,7 @@ fi
if [ -z "$NSS_TEST_DISABLE_UPGRADE_DB" ] ; then
# upgrade certs dbs to shared db
TESTS="dbupgrade"
TEST_MODE=UPGRADE_DB
run_tests
TABLE_ARGS="bgcolor=pink"
@ -193,6 +196,7 @@ if [ -z "$NSS_TEST_DISABLE_SHARED_DB" ] ; then
# run the tests for native sharedb support
TESTS=`echo "${ALL_TESTS}" | sed -e "s/libpkix//" -e "s/dbupgrade//"`
TEST_MODE=SHARED_DB
run_tests
. ${ENV_BACKUP}

View File

@ -0,0 +1,251 @@
#! /bin/sh
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# 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 the Initial Developer are Copyright (C) 1994-2000
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
########################################################################
#
# mozilla/security/nss/tests/merge/merge.sh
#
# Script to test NSS merge
#
# needs to work on all Unix and Windows platforms
#
# special strings
# ---------------
# FIXME ... known problems, search for this string
# NOTE .... unexpected behavior
#
########################################################################
############################## merge_init ##############################
# local shell function to initialize this script
########################################################################
merge_init()
{
SCRIPTNAME=merge.sh # sourced - $0 would point to all.sh
if [ -z "${CLEANUP}" ] ; then # if nobody else is responsible for
CLEANUP="${SCRIPTNAME}" # cleaning this script will do it
fi
if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then
cd ../common
. ./init.sh
fi
if [ ! -r $CERT_LOG_FILE ]; then # we need certificates here
cd ${QADIR}/cert
. ./cert.sh
fi
if [ ! -d ${HOSTDIR}/SDR ]; then
cd ${QADIR}/sdr
. ./sdr.sh
fi
SCRIPTNAME=merge.sh
html_head "Merge Tests"
# need the SSL & SMIME directories from cert.sh
grep "SUCCESS: SMIME passed" $CERT_LOG_FILE >/dev/null || {
Exit 11 "Fatal - S/MIME of cert.sh needs to pass first"
}
grep "SUCCESS: SSL passed" $CERT_LOG_FILE >/dev/null || {
Exit 8 "Fatal - SSL of cert.sh needs to pass first"
}
#temporary files for SDR tests
VALUE1=$HOSTDIR/tests.v1.$$
VALUE3=$HOSTDIR/tests.v3.$$
# local directories used in this test.
MERGEDIR=${HOSTDIR}/merge
R_MERGEDIR=../merge
D_MERGE="merge.$version"
# SDR not initialized in common/init
P_R_SDR=../SDR
D_SDR="SDR.$version"
mkdir -p ${MERGEDIR}
PROFILE=.
if [ -n "${MULTIACCESS_DBM}" ]; then
PROFILE="multiaccess:${D_MERGE}"
P_R_SDR="multiaccess:${D_SDR}"
fi
cd ${MERGEDIR}
# clear out any existing databases, potentially from a previous run.
rm -f *.db
# copy alicedir over as a seed database.
cp ${R_ALICEDIR}/* .
# copy the smime text samples
cp ${QADIR}/smime/*.txt .
#
# allow all the tests to run in standalone mode.
# in standalone mode, TEST_MODE is not set.
# if NSS_DEFAULT_DB_TYPE is dbm, then test merge with dbm
# if NSS_DEFAULT_DB_TYPE is sql, then test merge with sql
# if NSS_DEFAULT_DB_TYPE is not set, then test database upgrade merge
# from dbm databases (created above) into a new sql db.
if [ -z "${TEST_MODE}" ] && [ -z "${NSS_DEFAULT_DB_TYPE}" ]; then
echo "*** Using Standalone Upgrade DB mode"
export NSS_DEFAULT_DB_TYPE=sql
echo certutil --upgrade-merge --source-dir ${P_R_ALICEDIR} --upgrade-id local -d ${PROFILE} -f ${R_PWFILE} -@ ${R_PWFILE}
#gdb `which certutil`
certutil --upgrade-merge --source-dir ${P_R_ALICEDIR} --upgrade-id local -d ${PROFILE} -f ${R_PWFILE} -@ ${R_PWFILE}
TEST_MODE=UPGRADE_DB
fi
}
#
# this allows us to run this test for both merge and upgrade-merge cases.
# merge_cmd takes the potential upgrade-id and the rest of the certutil
# arguments.
#
merge_cmd()
{
MERGE_CMD=--merge
if [ "${TEST_MODE}" = "UPGRADE_DB" ]; then
MERGE_CMD="--upgrade-merge --upgrade-token-name OldDB --upgrade-id ${1}"
fi
shift
echo certutil ${MERGE_CMD} $*
${PROFTOOL} certutil ${MERGE_CMD} $*
}
merge_main()
{
# first create a local sdr key and encrypt some data with it
# This will cause a colision with the SDR key in ../SDR.
echo "$SCRIPTNAME: Creating an SDR key & Encrypt"
echo "sdrtest -d ${PROFILE} -o ${VALUE3} -t Test2 -f ${R_PWFILE}"
${PROFTOOL} sdrtest -d ${PROFILE} -o ${VALUE3} -t Test2 -f ${R_PWFILE}
html_msg $? 0 "Creating SDR Key"
# Now merge in Dave
# Dave's cert is already in alicedir, but his key isn't. This will make
# sure we are updating the keys and CKA_ID's on the certificate properly.
MERGE_ID=dave
echo "$SCRIPTNAME: Merging in Key for Existing user"
merge_cmd dave --source-dir ${P_R_DAVEDIR} -d ${PROFILE} -f ${R_PWFILE} -@ ${R_PWFILE}
html_msg $? 0 "Merging Dave"
# Merge in server
# contains a CRL and new user certs
MERGE_ID=server
echo "$SCRIPTNAME: Merging in new user "
merge_cmd server --source-dir ${P_R_SERVERDIR} -d ${PROFILE} -f ${R_PWFILE} -@ ${R_PWFILE}
html_msg $? 0 "Merging server"
# Merge in ext_client
# contains a new certificate chain and additional trust flags
MERGE_ID=ext_client
echo "$SCRIPTNAME: Merging in new chain "
merge_cmd ext_client --source-dir ${P_R_EXT_CLIENTDIR} -d ${PROFILE} -f ${R_PWFILE} -@ ${R_PWFILE}
html_msg $? 0 "Merging ext_client"
# Merge in SDR
# contains a secret SDR key
MERGE_ID=SDR
echo "$SCRIPTNAME: Merging in SDR "
merge_cmd sdr --source-dir ${P_R_SDR} -d ${PROFILE} -f ${R_PWFILE} -@ ${R_PWFILE}
html_msg $? 0 "Merging SDR"
# insert a listing of the database into the log for diagonic purposes
certutil -L -d ${PROFILE}
crlutil -L -d ${PROFILE}
# Make sure we can decrypt with our original SDR key generated above
echo "$SCRIPTNAME: Decrypt - With Original SDR Key"
${PROFTOOL} echo "sdrtest -d ${PROFILE} -i ${VALUE3} -t Test2 -f ${R_PWFILE}"
sdrtest -d ${PROFILE} -i ${VALUE3} -t Test2 -f ${R_PWFILE}
html_msg $? 0 "Decrypt - Value 3"
# Make sure we can decrypt with our the SDR key merged in from ../SDR
echo "$SCRIPTNAME: Decrypt - With Merged SDR Key"
echo "sdrtest -d ${PROFILE} -i ${VALUE1} -t Test1 -f ${R_PWFILE}"
${PROFTOOL} sdrtest -d ${PROFILE} -i ${VALUE1} -t Test1 -f ${R_PWFILE}
html_msg $? 0 "Decrypt - Value 1"
# Make sure we can sign with merge certificate
echo "$SCRIPTNAME: Signing with merged key ------------------"
echo "cmsutil -S -T -N Dave -H SHA1 -i alice.txt -d ${PROFILE} -p nss -o dave.dsig"
${PROFTOOL} cmsutil -S -T -N Dave -H SHA1 -i alice.txt -d ${PROFILE} -p nss -o dave.dsig
html_msg $? 0 "Create Detached Signature Dave" "."
echo "cmsutil -D -i dave.dsig -c alice.txt -d ${PROFILE} "
${PROFTOOL} cmsutil -D -i dave.dsig -c alice.txt -d ${PROFILE}
html_msg $? 0 "Verifying Dave's Detached Signature"
# Make sure that trust objects were properly merged
echo "$SCRIPTNAME: verifying merged cert ------------------"
echo "certutil -V -n ExtendedSSLUser -u C -d ${PROFILE}"
${PROFTOOL} certutil -V -n ExtendedSSLUser -u C -d ${PROFILE}
html_msg $? 0 "Verifying ExtendedSSL User Cert"
# Make sure that the crl got properly copied in
echo "$SCRIPTNAME: verifying merged crl ------------------"
echo "crlutil -L -n TestCA -d ${PROFILE}"
${PROFTOOL} crlutil -L -n TestCA -d ${PROFILE}
html_msg $? 0 "Verifying TestCA CRL"
}
############################## smime_cleanup ###########################
# local shell function to finish this script (no exit since it might be
# sourced)
########################################################################
merge_cleanup()
{
html "</TABLE><BR>"
cd ${QADIR}
. common/cleanup.sh
}
################## main #################################################
merge_init
merge_main
merge_cleanup