summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrrelyea%redhat.com <devnull@localhost>2008-04-05 01:42:53 +0000
committerrrelyea%redhat.com <devnull@localhost>2008-04-05 01:42:53 +0000
commit24ab9cefba1b585be214d7d533d2535d9a26df1f (patch)
tree94ab47b9492b72370369ed5a72c031380fa7c971
parent8f1714823a79932ce9a50cd7469e9e5958a19966 (diff)
downloadnss-hg-24ab9cefba1b585be214d7d533d2535d9a26df1f.tar.gz
[Bug 400238] softtoken unexpectedly logged out
r nelson Also addes test case
-rw-r--r--security/nss/cmd/dbtest/dbtest.c113
-rw-r--r--security/nss/lib/pk11wrap/pk11auth.c10
-rwxr-xr-xsecurity/nss/tests/dbtests/dbtests.sh16
3 files changed, 120 insertions, 19 deletions
diff --git a/security/nss/cmd/dbtest/dbtest.c b/security/nss/cmd/dbtest/dbtest.c
index d01c8180e..fbcd4c53e 100644
--- a/security/nss/cmd/dbtest/dbtest.c
+++ b/security/nss/cmd/dbtest/dbtest.c
@@ -52,6 +52,7 @@
#endif
#include "secutil.h"
+#include "pk11pub.h"
#if defined(XP_UNIX)
#include <unistd.h>
@@ -72,16 +73,33 @@ char *dbDir = NULL;
static char *dbName[]={"secmod.db", "cert8.db", "key3.db"};
static char* dbprefix = "";
static char* secmodName = "secmod.db";
+static char* userPassword = "";
PRBool verbose;
+static char *
+getPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ int *success = (int *)arg;
+
+ if (retry) {
+ *success = 0;
+ return NULL;
+ }
+
+ *success = 1;
+ return PORT_Strdup(userPassword);
+}
+
static void Usage(const char *progName)
{
- printf("Usage: %s [-r] [-f] [-d dbdir ] \n",
+ printf("Usage: %s [-r] [-f] [-i] [-d dbdir ] \n",
progName);
printf("%-20s open database readonly (NSS_INIT_READONLY)\n", "-r");
printf("%-20s Continue to force initializations even if the\n", "-f");
printf("%-20s databases cannot be opened (NSS_INIT_FORCEOPEN)\n", " ");
+ printf("%-20s Try to initialize the database\n", "-i");
+ printf("%-20s Supply a password with which to initialize the db\n", "-p");
printf("%-20s Directory with cert database (default is .\n",
"-d certdir");
exit(1);
@@ -96,6 +114,7 @@ int main(int argc, char **argv)
Error ret;
SECStatus rv;
char * dbString = NULL;
+ PRBool doInitTest = PR_FALSE;
int i;
progName = strrchr(argv[0], '/');
@@ -103,7 +122,7 @@ int main(int argc, char **argv)
progName = strrchr(argv[0], '\\');
progName = progName ? progName+1 : argv[0];
- optstate = PL_CreateOptState(argc, argv, "rfd:h");
+ optstate = PL_CreateOptState(argc, argv, "rfip:d:h");
while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
switch (optstate->option) {
@@ -114,6 +133,12 @@ int main(int argc, char **argv)
case 'f': flags |= NSS_INIT_FORCEOPEN; break;
+ case 'i': doInitTest = PR_TRUE; break;
+
+ case 'p':
+ userPassword = PORT_Strdup(optstate->value);
+ break;
+
case 'd':
dbDir = PORT_Strdup(optstate->value);
break;
@@ -148,33 +173,91 @@ int main(int argc, char **argv)
PR_Access(dbDir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
PR_fprintf(PR_STDERR, errStrings[DIR_NOT_WRITEABLE_ERR], dbDir);
}
- for (i=0;i<3;i++) {
- dbString=PR_smprintf("%s/%s",dbDir,dbName[i]);
- PR_fprintf(PR_STDOUT, "database checked is %s\n",dbString);
- if(PR_Access(dbString, PR_ACCESS_EXISTS) != PR_SUCCESS) {
- PR_fprintf(PR_STDERR, errStrings[FILE_DOESNT_EXIST_ERR],
+ if (!doInitTest) {
+ for (i=0;i<3;i++) {
+ dbString=PR_smprintf("%s/%s",dbDir,dbName[i]);
+ PR_fprintf(PR_STDOUT, "database checked is %s\n",dbString);
+ if(PR_Access(dbString, PR_ACCESS_EXISTS) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_DOESNT_EXIST_ERR],
dbString);
- } else if(PR_Access(dbString, PR_ACCESS_READ_OK) != PR_SUCCESS) {
- PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR],
+ } else if(PR_Access(dbString, PR_ACCESS_READ_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR],
dbString);
- } else if( !( flags & NSS_INIT_READONLY ) &&
- PR_Access(dbString, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
- PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
+ } else if( !( flags & NSS_INIT_READONLY ) &&
+ PR_Access(dbString, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
dbString);
- }
- }
+ }
+ }
+ }
}
+
rv = NSS_Initialize(SECU_ConfigDirectory(dbDir), dbprefix, dbprefix,
secmodName, flags);
if (rv != SECSuccess) {
SECU_PrintPRandOSError(progName);
ret=NSS_INITIALIZE_FAILED_ERR;
} else {
+ ret=SUCCESS;
+ if (doInitTest) {
+ PK11SlotInfo * slot = PK11_GetInternalKeySlot();
+ SECStatus rv;
+ int passwordSuccess = 0;
+ int type = CKM_DES3_CBC;
+ SECItem keyid = { 0, NULL, 0 };
+ unsigned char keyIdData[] = { 0xff, 0xfe };
+ PK11SymKey *key = NULL;
+
+ keyid.data = keyIdData;
+ keyid.len = sizeof(keyIdData);
+
+ PK11_SetPasswordFunc(getPassword);
+ rv = PK11_InitPin(slot, (char *)NULL, userPassword);
+ if (rv != SECSuccess) {
+ PR_fprintf(PR_STDERR, "Failed to Init DB: %s\n",
+ SECU_Strerror(PORT_GetError()));
+ ret = CHANGEPW_FAILED_ERR;
+ }
+ if (*userPassword && !PK11_IsLoggedIn(slot, &passwordSuccess)) {
+ PR_fprintf(PR_STDERR, "New DB did not log in after init\n");
+ ret = AUTHENTICATION_FAILED_ERR;
+ }
+ /* generate a symetric key */
+ key = PK11_TokenKeyGen(slot, type, NULL, 0, &keyid,
+ PR_TRUE, &passwordSuccess);
+
+ if (!key) {
+ PR_fprintf(PR_STDERR, "Could not generated symetric key: %s\n",
+ SECU_Strerror(PORT_GetError()));
+ exit (UNSPECIFIED_ERR);
+ }
+ PK11_FreeSymKey(key);
+ PK11_Logout(slot);
+
+ PK11_Authenticate(slot, PR_TRUE, &passwordSuccess);
+
+ if (*userPassword && !passwordSuccess) {
+ PR_fprintf(PR_STDERR, "New DB Did not initalize\n");
+ ret = AUTHENTICATION_FAILED_ERR;
+ }
+ key = PK11_FindFixedKey(slot, type, &keyid, &passwordSuccess);
+
+ if (!key) {
+ PR_fprintf(PR_STDERR, "Could not find generated key: %s\n",
+ SECU_Strerror(PORT_GetError()));
+ ret = UNSPECIFIED_ERR;
+ } else {
+ PK11_FreeSymKey(key);
+ }
+ PK11_FreeSlot(slot);
+ }
+
if (NSS_Shutdown() != SECSuccess) {
+ PR_fprintf(PR_STDERR, "Could not find generated key: %s\n",
+ SECU_Strerror(PORT_GetError()));
exit(1);
}
- ret=SUCCESS;
}
loser:
diff --git a/security/nss/lib/pk11wrap/pk11auth.c b/security/nss/lib/pk11wrap/pk11auth.c
index d4f6dba09..c957d1b46 100644
--- a/security/nss/lib/pk11wrap/pk11auth.c
+++ b/security/nss/lib/pk11wrap/pk11auth.c
@@ -460,11 +460,13 @@ done:
if (rv == SECSuccess) {
/* update our view of the world */
PK11_InitToken(slot,PR_TRUE);
- PK11_EnterSlotMonitor(slot);
- PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER,
+ if (slot->needLogin) {
+ PK11_EnterSlotMonitor(slot);
+ PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER,
(unsigned char *)userpw,len);
- slot->lastLoginCheck = 0;
- PK11_ExitSlotMonitor(slot);
+ slot->lastLoginCheck = 0;
+ PK11_ExitSlotMonitor(slot);
+ }
}
return rv;
}
diff --git a/security/nss/tests/dbtests/dbtests.sh b/security/nss/tests/dbtests/dbtests.sh
index aab6b1c09..3db294fd5 100755
--- a/security/nss/tests/dbtests/dbtests.sh
+++ b/security/nss/tests/dbtests/dbtests.sh
@@ -155,6 +155,22 @@ dbtest_main()
html_passed "Dbtest readonly didn't work in an empty dir $ret"
fi
rm -rf $EMPTY_DIR/* 2>/dev/null
+ ${BINDIR}/dbtest -i -d $EMPTY_DIR
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ html_failed "Dbtest logout after empty DB Init looses key $ret"
+ else
+ html_passed "Dbtest logout after empty DB Init has key"
+ fi
+ rm -rf $EMPTY_DIR/* 2>/dev/null
+ ${BINDIR}/dbtest -i -p pass -d $EMPTY_DIR
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ html_failed "Dbtest password DB Init looses needlogin state $ret"
+ else
+ html_passed "Dbtest password DB Init maintains needlogin state"
+ fi
+ rm -rf $EMPTY_DIR/* 2>/dev/null
${BINDIR}/certutil -D -n xxxx -d $EMPTY_DIR #created DB
ret=$?
if [ $ret -ne 255 ]; then