Index: mozilla/security/nss/lib/pk11wrap/pk11auth.c =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/pk11wrap/pk11auth.c,v retrieving revision 1.5 diff -u -r1.5 pk11auth.c --- mozilla/security/nss/lib/pk11wrap/pk11auth.c 29 Sep 2005 23:44:39 -0000 1.5 +++ mozilla/security/nss/lib/pk11wrap/pk11auth.c 12 Jan 2007 01:23:20 -0000 @@ -84,6 +84,8 @@ CK_RV crv; SECStatus rv; int64 currtime = PR_Now(); + PRBool mustRetry; + int retry = 0; if (slot->protectedAuthPath) { len = 0; @@ -95,27 +97,46 @@ len = PORT_Strlen(pw); } - PK11_EnterSlotMonitor(slot); - crv = PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER, + do { + PK11_EnterSlotMonitor(slot); + crv = PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER, (unsigned char *)pw,len); - slot->lastLoginCheck = 0; - PK11_ExitSlotMonitor(slot); - switch (crv) { - /* if we're already logged in, we're good to go */ - case CKR_OK: - slot->authTransact = PK11_Global.transaction; - case CKR_USER_ALREADY_LOGGED_IN: - slot->authTime = currtime; - rv = SECSuccess; - break; - case CKR_PIN_INCORRECT: - PORT_SetError(SEC_ERROR_BAD_PASSWORD); - rv = SECWouldBlock; /* everything else is ok, only the pin is bad */ - break; - default: - PORT_SetError(PK11_MapError(crv)); - rv = SECFailure; /* some failure we can't fix by retrying */ - } + slot->lastLoginCheck = 0; + mustRetry = PR_FALSE; + PK11_ExitSlotMonitor(slot); + switch (crv) { + /* if we're already logged in, we're good to go */ + case CKR_OK: + slot->authTransact = PK11_Global.transaction; + case CKR_USER_ALREADY_LOGGED_IN: + slot->authTime = currtime; + rv = SECSuccess; + break; + case CKR_PIN_INCORRECT: + PORT_SetError(SEC_ERROR_BAD_PASSWORD); + rv = SECWouldBlock; /* everything else is ok, only the pin is bad */ + break; + /* someone called reset while we fetched the password, try again once + * if the token is still there. */ + case CKR_SESSION_HANDLE_INVALID: + case CKR_SESSION_CLOSED: + if (retry++ == 0) { + rv = PK11_InitToken(slot,PR_FALSE); + if (rv == SECSuccess) { + if (slot->session != CK_INVALID_SESSION) { + mustRetry = PR_TRUE; + } else { + PORT_SetError(PK11_MapError(crv)); + rv = SECFailure; + } + } + break; + } + default: + PORT_SetError(PK11_MapError(crv)); + rv = SECFailure; /* some failure we can't fix by retrying */ + } + } while (mustRetry); return rv; }