diff options
author | rrelyea%redhat.com <devnull@localhost> | 2008-04-05 01:42:53 +0000 |
---|---|---|
committer | rrelyea%redhat.com <devnull@localhost> | 2008-04-05 01:42:53 +0000 |
commit | 24ab9cefba1b585be214d7d533d2535d9a26df1f (patch) | |
tree | 94ab47b9492b72370369ed5a72c031380fa7c971 | |
parent | 8f1714823a79932ce9a50cd7469e9e5958a19966 (diff) | |
download | nss-hg-24ab9cefba1b585be214d7d533d2535d9a26df1f.tar.gz |
[Bug 400238] softtoken unexpectedly logged out
r nelson
Also addes test case
-rw-r--r-- | security/nss/cmd/dbtest/dbtest.c | 113 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/pk11auth.c | 10 | ||||
-rwxr-xr-x | security/nss/tests/dbtests/dbtests.sh | 16 |
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 |