/* * before we do a private key op, we check to see if we * need to reauthenticate. */ void PK11_HandlePasswordCheck(PK11SlotInfo *slot,void *wincx) { int askpw = slot->askpw; PRBool NeedAuth = PR_FALSE; if (!slot->needLogin) return; if ((slot->defaultFlags & PK11_OWN_PW_DEFAULTS) == 0) { PK11SlotInfo *def_slot = PK11_GetInternalKeySlot(); if (def_slot) { askpw = def_slot->askpw; PK11_FreeSlot(def_slot); } } /* timeouts are handled by isLoggedIn */ if (!PK11_IsLoggedIn(slot,wincx)) { NeedAuth = PR_TRUE; } else if (askpw == -1) { if (!PK11_Global.inTransaction || (PK11_Global.transaction != slot->authTransact)) { PK11_EnterSlotMonitor(slot); PK11_GETTAB(slot)->C_Logout(slot->session); slot->lastLoginCheck = 0; PK11_ExitSlotMonitor(slot); NeedAuth = PR_TRUE; } } if (NeedAuth) PK11_DoPassword(slot,PR_TRUE,wincx); }
/* * Check the user's password. Logout before hand to make sure that * we are really checking the password. */ SECStatus PK11_CheckUserPassword(PK11SlotInfo *slot, const char *pw) { int len = 0; CK_RV crv; SECStatus rv; int64 currtime = PR_Now(); if (slot->protectedAuthPath) { len = 0; pw = NULL; } else if (pw == NULL) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } else { len = PORT_Strlen(pw); } /* * If the token does't need a login, don't try to relogin beause the * effect is undefined. It's not clear what it means to check a non-empty * password with such a token, so treat that as an error. */ if (!slot->needLogin) { if (len == 0) { rv = SECSuccess; } else { PORT_SetError(SEC_ERROR_BAD_PASSWORD); rv = SECFailure; } return rv; } /* force a logout */ PK11_EnterSlotMonitor(slot); PK11_GETTAB(slot)->C_Logout(slot->session); 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; 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 */ } return rv; }
/* * the monitors... */ void PK11_EnterContextMonitor(PK11Context *cx) { /* if we own the session and our slot is ThreadSafe, only monitor * the Context */ if ((cx->ownSession) && (cx->slot->isThreadSafe)) { /* Should this use monitors instead? */ PZ_Lock(cx->sessionLock); } else { PK11_EnterSlotMonitor(cx->slot); } }
SECStatus PK11_Logout(PK11SlotInfo *slot) { CK_RV crv; /* force a logout */ PK11_EnterSlotMonitor(slot); crv = PK11_GETTAB(slot)->C_Logout(slot->session); slot->lastLoginCheck = 0; PK11_ExitSlotMonitor(slot); if (crv != CKR_OK) { PORT_SetError(PK11_MapError(crv)); return SECFailure; } return SECSuccess; }
/* * Determine if the token is logged in. We have to actually query the token, * because it's state can change without intervention from us. */ PRBool PK11_IsLoggedIn(PK11SlotInfo *slot,void *wincx) { CK_SESSION_INFO sessionInfo; int askpw = slot->askpw; int timeout = slot->timeout; CK_RV crv; PRIntervalTime curTime; static PRIntervalTime login_delay_time = 0; if (login_delay_time == 0) { login_delay_time = PR_SecondsToInterval(1); } /* If we don't have our own password default values, use the system * ones */ if ((slot->defaultFlags & PK11_OWN_PW_DEFAULTS) == 0) { PK11SlotInfo *def_slot = PK11_GetInternalKeySlot(); if (def_slot) { askpw = def_slot->askpw; timeout = def_slot->timeout; PK11_FreeSlot(def_slot); } } if ((wincx != NULL) && (PK11_Global.isLoggedIn != NULL) && (*PK11_Global.isLoggedIn)(slot, wincx) == PR_FALSE) { return PR_FALSE; } /* forget the password if we've been inactive too long */ if (askpw == 1) { int64 currtime = PR_Now(); int64 result; int64 mult; LL_I2L(result, timeout); LL_I2L(mult, 60*1000*1000); LL_MUL(result,result,mult); LL_ADD(result, result, slot->authTime); if (LL_CMP(result, <, currtime) ) { PK11_EnterSlotMonitor(slot); PK11_GETTAB(slot)->C_Logout(slot->session); slot->lastLoginCheck = 0; PK11_ExitSlotMonitor(slot); } else {
/* * Check the user's password. Logout before hand to make sure that * we are really checking the password. */ SECStatus PK11_CheckUserPassword(PK11SlotInfo *slot, const char *pw) { int len = 0; CK_RV crv; SECStatus rv; int64 currtime = PR_Now(); if (slot->protectedAuthPath) { len = 0; pw = NULL; } else if (pw == NULL) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } else { len = PORT_Strlen(pw); } /* force a logout */ PK11_EnterSlotMonitor(slot); PK11_GETTAB(slot)->C_Logout(slot->session); 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; 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 */ } return rv; }
static void pk11_EnterKeyMonitor(PK11SymKey *symKey) { if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe)) PK11_EnterSlotMonitor(symKey->slot); }
/* * Check the user's password. Log into the card if it's correct. * succeed if the user is already logged in. */ SECStatus pk11_CheckPassword(PK11SlotInfo *slot,char *pw) { int len = 0; CK_RV crv; SECStatus rv; int64 currtime = PR_Now(); PRBool mustRetry; int retry = 0; if (slot->protectedAuthPath) { len = 0; pw = NULL; } else if (pw == NULL) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } else { len = PORT_Strlen(pw); } do { PK11_EnterSlotMonitor(slot); crv = PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER, (unsigned char *)pw,len); 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; /* Fall through */ 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; } /* Fall through */ default: PORT_SetError(PK11_MapError(crv)); rv = SECFailure; /* some failure we can't fix by retrying */ } } while (mustRetry); return rv; }
/* * initialize a user PIN Value */ SECStatus PK11_InitPin(PK11SlotInfo *slot, const char *ssopw, const char *userpw) { CK_SESSION_HANDLE rwsession = CK_INVALID_SESSION; CK_RV crv; SECStatus rv = SECFailure; int len; int ssolen; if (userpw == NULL) userpw = ""; if (ssopw == NULL) ssopw = ""; len = PORT_Strlen(userpw); ssolen = PORT_Strlen(ssopw); /* get a rwsession */ rwsession = PK11_GetRWSession(slot); if (rwsession == CK_INVALID_SESSION) { PORT_SetError(SEC_ERROR_BAD_DATA); slot->lastLoginCheck = 0; return rv; } if (slot->protectedAuthPath) { len = 0; ssolen = 0; ssopw = NULL; userpw = NULL; } /* check the password */ crv = PK11_GETTAB(slot)->C_Login(rwsession,CKU_SO, (unsigned char *)ssopw,ssolen); slot->lastLoginCheck = 0; if (crv != CKR_OK) { PORT_SetError(PK11_MapError(crv)); goto done; } crv = PK11_GETTAB(slot)->C_InitPIN(rwsession,(unsigned char *)userpw,len); if (crv != CKR_OK) { PORT_SetError(PK11_MapError(crv)); } else { rv = SECSuccess; } done: PK11_GETTAB(slot)->C_Logout(rwsession); slot->lastLoginCheck = 0; PK11_RestoreROSession(slot,rwsession); if (rv == SECSuccess) { /* update our view of the world */ PK11_InitToken(slot,PR_TRUE); 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); } } return rv; }
/* * Check the user's password. Log into the card if it's correct. * succeed if the user is already logged in. */ static SECStatus pk11_CheckPassword(PK11SlotInfo *slot, CK_SESSION_HANDLE session, char *pw, PRBool alreadyLocked, PRBool contextSpecific) { int len = 0; CK_RV crv; SECStatus rv; int64 currtime = PR_Now(); PRBool mustRetry; int retry = 0; if (slot->protectedAuthPath) { len = 0; pw = NULL; } else if (pw == NULL) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } else { len = PORT_Strlen(pw); } do { if (!alreadyLocked) PK11_EnterSlotMonitor(slot); crv = PK11_GETTAB(slot)->C_Login(session, contextSpecific ? CKU_CONTEXT_SPECIFIC : CKU_USER, (unsigned char *)pw,len); slot->lastLoginCheck = 0; mustRetry = PR_FALSE; if (!alreadyLocked) PK11_ExitSlotMonitor(slot); switch (crv) { /* if we're already logged in, we're good to go */ case CKR_OK: /* TODO If it was for CKU_CONTEXT_SPECIFIC should we do this */ slot->authTransact = PK11_Global.transaction; /* Fall through */ 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 (session != slot->session) { /* don't bother retrying, we were in a middle of an operation, * which is now lost. Just fail. */ PORT_SetError(PK11_MapError(crv)); rv = SECFailure; break; } if (retry++ == 0) { rv = PK11_InitToken(slot,PR_FALSE); if (rv == SECSuccess) { if (slot->session != CK_INVALID_SESSION) { session = slot->session; /* we should have * a new session now */ mustRetry = PR_TRUE; } else { PORT_SetError(PK11_MapError(crv)); rv = SECFailure; } } break; } /* Fall through */ default: PORT_SetError(PK11_MapError(crv)); rv = SECFailure; /* some failure we can't fix by retrying */ } } while (mustRetry); return rv; }