|
Packit |
40b132 |
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
Packit |
40b132 |
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
Packit |
40b132 |
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* This file deals with PKCS #11 passwords and authentication.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
#include "seccomon.h"
|
|
Packit |
40b132 |
#include "secmod.h"
|
|
Packit |
40b132 |
#include "secmodi.h"
|
|
Packit |
40b132 |
#include "secmodti.h"
|
|
Packit |
40b132 |
#include "pkcs11t.h"
|
|
Packit |
40b132 |
#include "pk11func.h"
|
|
Packit |
40b132 |
#include "secitem.h"
|
|
Packit |
40b132 |
#include "secerr.h"
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
#include "pkim.h"
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*************************************************************
|
|
Packit |
40b132 |
* local static and global data
|
|
Packit |
40b132 |
*************************************************************/
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* This structure keeps track of status that spans all the Slots.
|
|
Packit |
40b132 |
* NOTE: This is a global data structure. It semantics expect thread crosstalk
|
|
Packit |
40b132 |
* be very careful when you see it used.
|
|
Packit |
40b132 |
* It's major purpose in life is to allow the user to log in one PER
|
|
Packit |
40b132 |
* Tranaction, even if a transaction spans threads. The problem is the user
|
|
Packit |
40b132 |
* may have to enter a password one just to be able to look at the
|
|
Packit |
40b132 |
* personalities/certificates (s)he can use. Then if Auth every is one, they
|
|
Packit |
40b132 |
* may have to enter the password again to use the card. See PK11_StartTransac
|
|
Packit |
40b132 |
* and PK11_EndTransaction.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
static struct PK11GlobalStruct {
|
|
Packit |
40b132 |
int transaction;
|
|
Packit |
40b132 |
PRBool inTransaction;
|
|
Packit |
40b132 |
char *(PR_CALLBACK *getPass)(PK11SlotInfo *,PRBool,void *);
|
|
Packit |
40b132 |
PRBool (PR_CALLBACK *verifyPass)(PK11SlotInfo *,void *);
|
|
Packit |
40b132 |
PRBool (PR_CALLBACK *isLoggedIn)(PK11SlotInfo *,void *);
|
|
Packit |
40b132 |
} PK11_Global = { 1, PR_FALSE, NULL, NULL, NULL };
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/***********************************************************
|
|
Packit |
40b132 |
* Password Utilities
|
|
Packit |
40b132 |
***********************************************************/
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* Check the user's password. Log into the card if it's correct.
|
|
Packit |
40b132 |
* succeed if the user is already logged in.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
static SECStatus
|
|
Packit |
40b132 |
pk11_CheckPassword(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
|
|
Packit |
40b132 |
char *pw, PRBool alreadyLocked, PRBool contextSpecific)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
int len = 0;
|
|
Packit |
40b132 |
CK_RV crv;
|
|
Packit |
40b132 |
SECStatus rv;
|
|
Packit |
40b132 |
PRTime currtime = PR_Now();
|
|
Packit |
40b132 |
PRBool mustRetry;
|
|
Packit |
40b132 |
int retry = 0;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if (slot->protectedAuthPath) {
|
|
Packit |
40b132 |
len = 0;
|
|
Packit |
40b132 |
pw = NULL;
|
|
Packit |
40b132 |
} else if (pw == NULL) {
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
Packit |
40b132 |
return SECFailure;
|
|
Packit |
40b132 |
} else {
|
|
Packit |
40b132 |
len = PORT_Strlen(pw);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
do {
|
|
Packit |
40b132 |
if (!alreadyLocked) PK11_EnterSlotMonitor(slot);
|
|
Packit |
40b132 |
crv = PK11_GETTAB(slot)->C_Login(session,
|
|
Packit |
40b132 |
contextSpecific ? CKU_CONTEXT_SPECIFIC : CKU_USER,
|
|
Packit |
40b132 |
(unsigned char *)pw,len);
|
|
Packit |
40b132 |
slot->lastLoginCheck = 0;
|
|
Packit |
40b132 |
mustRetry = PR_FALSE;
|
|
Packit |
40b132 |
if (!alreadyLocked) PK11_ExitSlotMonitor(slot);
|
|
Packit |
40b132 |
switch (crv) {
|
|
Packit |
40b132 |
/* if we're already logged in, we're good to go */
|
|
Packit |
40b132 |
case CKR_OK:
|
|
Packit |
40b132 |
/* TODO If it was for CKU_CONTEXT_SPECIFIC should we do this */
|
|
Packit |
40b132 |
slot->authTransact = PK11_Global.transaction;
|
|
Packit |
40b132 |
/* Fall through */
|
|
Packit |
40b132 |
case CKR_USER_ALREADY_LOGGED_IN:
|
|
Packit |
40b132 |
slot->authTime = currtime;
|
|
Packit |
40b132 |
rv = SECSuccess;
|
|
Packit |
40b132 |
break;
|
|
Packit |
40b132 |
case CKR_PIN_INCORRECT:
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_BAD_PASSWORD);
|
|
Packit |
40b132 |
rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
|
|
Packit |
40b132 |
break;
|
|
Packit |
40b132 |
/* someone called reset while we fetched the password, try again once
|
|
Packit |
40b132 |
* if the token is still there. */
|
|
Packit |
40b132 |
case CKR_SESSION_HANDLE_INVALID:
|
|
Packit |
40b132 |
case CKR_SESSION_CLOSED:
|
|
Packit |
40b132 |
if (session != slot->session) {
|
|
Packit |
40b132 |
/* don't bother retrying, we were in a middle of an operation,
|
|
Packit |
40b132 |
* which is now lost. Just fail. */
|
|
Packit |
40b132 |
PORT_SetError(PK11_MapError(crv));
|
|
Packit |
40b132 |
rv = SECFailure;
|
|
Packit |
40b132 |
break;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
if (retry++ == 0) {
|
|
Packit |
40b132 |
rv = PK11_InitToken(slot,PR_FALSE);
|
|
Packit |
40b132 |
if (rv == SECSuccess) {
|
|
Packit |
40b132 |
if (slot->session != CK_INVALID_SESSION) {
|
|
Packit |
40b132 |
session = slot->session; /* we should have
|
|
Packit |
40b132 |
* a new session now */
|
|
Packit |
40b132 |
mustRetry = PR_TRUE;
|
|
Packit |
40b132 |
} else {
|
|
Packit |
40b132 |
PORT_SetError(PK11_MapError(crv));
|
|
Packit |
40b132 |
rv = SECFailure;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
break;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
/* Fall through */
|
|
Packit |
40b132 |
default:
|
|
Packit |
40b132 |
PORT_SetError(PK11_MapError(crv));
|
|
Packit |
40b132 |
rv = SECFailure; /* some failure we can't fix by retrying */
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
} while (mustRetry);
|
|
Packit |
40b132 |
return rv;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* Check the user's password. Logout before hand to make sure that
|
|
Packit |
40b132 |
* we are really checking the password.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
SECStatus
|
|
Packit |
40b132 |
PK11_CheckUserPassword(PK11SlotInfo *slot, const char *pw)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
int len = 0;
|
|
Packit |
40b132 |
CK_RV crv;
|
|
Packit |
40b132 |
SECStatus rv;
|
|
Packit |
40b132 |
PRTime currtime = PR_Now();
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if (slot->protectedAuthPath) {
|
|
Packit |
40b132 |
len = 0;
|
|
Packit |
40b132 |
pw = NULL;
|
|
Packit |
40b132 |
} else if (pw == NULL) {
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
Packit |
40b132 |
return SECFailure;
|
|
Packit |
40b132 |
} else {
|
|
Packit |
40b132 |
len = PORT_Strlen(pw);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* If the token doesn't need a login, don't try to relogin because the
|
|
Packit |
40b132 |
* effect is undefined. It's not clear what it means to check a non-empty
|
|
Packit |
40b132 |
* password with such a token, so treat that as an error.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
if (!slot->needLogin) {
|
|
Packit |
40b132 |
if (len == 0) {
|
|
Packit |
40b132 |
rv = SECSuccess;
|
|
Packit |
40b132 |
} else {
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_BAD_PASSWORD);
|
|
Packit |
40b132 |
rv = SECFailure;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return rv;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* force a logout */
|
|
Packit |
40b132 |
PK11_EnterSlotMonitor(slot);
|
|
Packit |
40b132 |
PK11_GETTAB(slot)->C_Logout(slot->session);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
crv = PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER,
|
|
Packit |
40b132 |
(unsigned char *)pw,len);
|
|
Packit |
40b132 |
slot->lastLoginCheck = 0;
|
|
Packit |
40b132 |
PK11_ExitSlotMonitor(slot);
|
|
Packit |
40b132 |
switch (crv) {
|
|
Packit |
40b132 |
/* if we're already logged in, we're good to go */
|
|
Packit |
40b132 |
case CKR_OK:
|
|
Packit |
40b132 |
slot->authTransact = PK11_Global.transaction;
|
|
Packit |
40b132 |
slot->authTime = currtime;
|
|
Packit |
40b132 |
rv = SECSuccess;
|
|
Packit |
40b132 |
break;
|
|
Packit |
40b132 |
case CKR_PIN_INCORRECT:
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_BAD_PASSWORD);
|
|
Packit |
40b132 |
rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
|
|
Packit |
40b132 |
break;
|
|
Packit |
40b132 |
default:
|
|
Packit |
40b132 |
PORT_SetError(PK11_MapError(crv));
|
|
Packit |
40b132 |
rv = SECFailure; /* some failure we can't fix by retrying */
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return rv;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
SECStatus
|
|
Packit |
40b132 |
PK11_Logout(PK11SlotInfo *slot)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
CK_RV crv;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* force a logout */
|
|
Packit |
40b132 |
PK11_EnterSlotMonitor(slot);
|
|
Packit |
40b132 |
crv = PK11_GETTAB(slot)->C_Logout(slot->session);
|
|
Packit |
40b132 |
slot->lastLoginCheck = 0;
|
|
Packit |
40b132 |
PK11_ExitSlotMonitor(slot);
|
|
Packit |
40b132 |
if (crv != CKR_OK) {
|
|
Packit |
40b132 |
PORT_SetError(PK11_MapError(crv));
|
|
Packit |
40b132 |
return SECFailure;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return SECSuccess;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* transaction stuff is for when we test for the need to do every
|
|
Packit |
40b132 |
* time auth to see if we already did it for this slot/transaction
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
void PK11_StartAuthTransaction(void)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
PK11_Global.transaction++;
|
|
Packit |
40b132 |
PK11_Global.inTransaction = PR_TRUE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
void PK11_EndAuthTransaction(void)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
PK11_Global.transaction++;
|
|
Packit |
40b132 |
PK11_Global.inTransaction = PR_FALSE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* before we do a private key op, we check to see if we
|
|
Packit |
40b132 |
* need to reauthenticate.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
void
|
|
Packit |
40b132 |
PK11_HandlePasswordCheck(PK11SlotInfo *slot,void *wincx)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
int askpw = slot->askpw;
|
|
Packit |
40b132 |
PRBool NeedAuth = PR_FALSE;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if (!slot->needLogin) return;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ((slot->defaultFlags & PK11_OWN_PW_DEFAULTS) == 0) {
|
|
Packit |
40b132 |
PK11SlotInfo *def_slot = PK11_GetInternalKeySlot();
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if (def_slot) {
|
|
Packit |
40b132 |
askpw = def_slot->askpw;
|
|
Packit |
40b132 |
PK11_FreeSlot(def_slot);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* timeouts are handled by isLoggedIn */
|
|
Packit |
40b132 |
if (!PK11_IsLoggedIn(slot,wincx)) {
|
|
Packit |
40b132 |
NeedAuth = PR_TRUE;
|
|
Packit |
40b132 |
} else if (askpw == -1) {
|
|
Packit |
40b132 |
if (!PK11_Global.inTransaction ||
|
|
Packit |
40b132 |
(PK11_Global.transaction != slot->authTransact)) {
|
|
Packit |
40b132 |
PK11_EnterSlotMonitor(slot);
|
|
Packit |
40b132 |
PK11_GETTAB(slot)->C_Logout(slot->session);
|
|
Packit |
40b132 |
slot->lastLoginCheck = 0;
|
|
Packit |
40b132 |
PK11_ExitSlotMonitor(slot);
|
|
Packit |
40b132 |
NeedAuth = PR_TRUE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
if (NeedAuth) PK11_DoPassword(slot, slot->session, PR_TRUE,
|
|
Packit |
40b132 |
wincx, PR_FALSE, PR_FALSE);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
void
|
|
Packit |
40b132 |
PK11_SlotDBUpdate(PK11SlotInfo *slot)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
SECMOD_UpdateModule(slot->module);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* set new askpw and timeout values
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
void
|
|
Packit |
40b132 |
PK11_SetSlotPWValues(PK11SlotInfo *slot,int askpw, int timeout)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
slot->askpw = askpw;
|
|
Packit |
40b132 |
slot->timeout = timeout;
|
|
Packit |
40b132 |
slot->defaultFlags |= PK11_OWN_PW_DEFAULTS;
|
|
Packit |
40b132 |
PK11_SlotDBUpdate(slot);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* Get the askpw and timeout values for this slot
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
void
|
|
Packit |
40b132 |
PK11_GetSlotPWValues(PK11SlotInfo *slot,int *askpw, int *timeout)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
*askpw = slot->askpw;
|
|
Packit |
40b132 |
*timeout = slot->timeout;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ((slot->defaultFlags & PK11_OWN_PW_DEFAULTS) == 0) {
|
|
Packit |
40b132 |
PK11SlotInfo *def_slot = PK11_GetInternalKeySlot();
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if (def_slot) {
|
|
Packit |
40b132 |
*askpw = def_slot->askpw;
|
|
Packit |
40b132 |
*timeout = def_slot->timeout;
|
|
Packit |
40b132 |
PK11_FreeSlot(def_slot);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* Returns true if the token is needLogin and isn't logged in.
|
|
Packit |
40b132 |
* This function is used to determine if authentication is needed
|
|
Packit |
40b132 |
* before attempting a potentially privelleged operation.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
PRBool
|
|
Packit |
40b132 |
pk11_LoginStillRequired(PK11SlotInfo *slot, void *wincx)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
return slot->needLogin && !PK11_IsLoggedIn(slot,wincx);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* make sure a slot is authenticated...
|
|
Packit |
40b132 |
* This function only does the authentication if it is needed.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
SECStatus
|
|
Packit |
40b132 |
PK11_Authenticate(PK11SlotInfo *slot, PRBool loadCerts, void *wincx) {
|
|
Packit |
40b132 |
if (pk11_LoginStillRequired(slot,wincx)) {
|
|
Packit |
40b132 |
return PK11_DoPassword(slot, slot->session, loadCerts, wincx,
|
|
Packit |
40b132 |
PR_FALSE, PR_FALSE);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return SECSuccess;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* Authenticate to "unfriendly" tokens (tokens which need to be logged
|
|
Packit |
40b132 |
* in to find the certs.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
SECStatus
|
|
Packit |
40b132 |
pk11_AuthenticateUnfriendly(PK11SlotInfo *slot, PRBool loadCerts, void *wincx)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
SECStatus rv = SECSuccess;
|
|
Packit |
40b132 |
if (!PK11_IsFriendly(slot)) {
|
|
Packit |
40b132 |
rv = PK11_Authenticate(slot, loadCerts, wincx);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return rv;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* NOTE: this assumes that we are logged out of the card before hand
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
SECStatus
|
|
Packit |
40b132 |
PK11_CheckSSOPassword(PK11SlotInfo *slot, char *ssopw)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
CK_SESSION_HANDLE rwsession;
|
|
Packit |
40b132 |
CK_RV crv;
|
|
Packit |
40b132 |
SECStatus rv = SECFailure;
|
|
Packit |
40b132 |
int len = 0;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* get a rwsession */
|
|
Packit |
40b132 |
rwsession = PK11_GetRWSession(slot);
|
|
Packit |
40b132 |
if (rwsession == CK_INVALID_SESSION) {
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_BAD_DATA);
|
|
Packit |
40b132 |
return rv;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if (slot->protectedAuthPath) {
|
|
Packit |
40b132 |
len = 0;
|
|
Packit |
40b132 |
ssopw = NULL;
|
|
Packit |
40b132 |
} else if (ssopw == NULL) {
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
Packit |
40b132 |
return SECFailure;
|
|
Packit |
40b132 |
} else {
|
|
Packit |
40b132 |
len = PORT_Strlen(ssopw);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* check the password */
|
|
Packit |
40b132 |
crv = PK11_GETTAB(slot)->C_Login(rwsession,CKU_SO,
|
|
Packit |
40b132 |
(unsigned char *)ssopw,len);
|
|
Packit |
40b132 |
slot->lastLoginCheck = 0;
|
|
Packit |
40b132 |
switch (crv) {
|
|
Packit |
40b132 |
/* if we're already logged in, we're good to go */
|
|
Packit |
40b132 |
case CKR_OK:
|
|
Packit |
40b132 |
rv = SECSuccess;
|
|
Packit |
40b132 |
break;
|
|
Packit |
40b132 |
case CKR_PIN_INCORRECT:
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_BAD_PASSWORD);
|
|
Packit |
40b132 |
rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
|
|
Packit |
40b132 |
break;
|
|
Packit |
40b132 |
default:
|
|
Packit |
40b132 |
PORT_SetError(PK11_MapError(crv));
|
|
Packit |
40b132 |
rv = SECFailure; /* some failure we can't fix by retrying */
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
PK11_GETTAB(slot)->C_Logout(rwsession);
|
|
Packit |
40b132 |
slot->lastLoginCheck = 0;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* release rwsession */
|
|
Packit |
40b132 |
PK11_RestoreROSession(slot,rwsession);
|
|
Packit |
40b132 |
return rv;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* make sure the password conforms to your token's requirements.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
SECStatus
|
|
Packit |
40b132 |
PK11_VerifyPW(PK11SlotInfo *slot,char *pw)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
int len = PORT_Strlen(pw);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ((slot->minPassword > len) || (slot->maxPassword < len)) {
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_BAD_DATA);
|
|
Packit |
40b132 |
return SECFailure;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return SECSuccess;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* initialize a user PIN Value
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
SECStatus
|
|
Packit |
40b132 |
PK11_InitPin(PK11SlotInfo *slot, const char *ssopw, const char *userpw)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
CK_SESSION_HANDLE rwsession = CK_INVALID_SESSION;
|
|
Packit |
40b132 |
CK_RV crv;
|
|
Packit |
40b132 |
SECStatus rv = SECFailure;
|
|
Packit |
40b132 |
int len;
|
|
Packit |
40b132 |
int ssolen;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if (userpw == NULL) userpw = "";
|
|
Packit |
40b132 |
if (ssopw == NULL) ssopw = "";
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
len = PORT_Strlen(userpw);
|
|
Packit |
40b132 |
ssolen = PORT_Strlen(ssopw);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* get a rwsession */
|
|
Packit |
40b132 |
rwsession = PK11_GetRWSession(slot);
|
|
Packit |
40b132 |
if (rwsession == CK_INVALID_SESSION) {
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_BAD_DATA);
|
|
Packit |
40b132 |
slot->lastLoginCheck = 0;
|
|
Packit |
40b132 |
return rv;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if (slot->protectedAuthPath) {
|
|
Packit |
40b132 |
len = 0;
|
|
Packit |
40b132 |
ssolen = 0;
|
|
Packit |
40b132 |
ssopw = NULL;
|
|
Packit |
40b132 |
userpw = NULL;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* check the password */
|
|
Packit |
40b132 |
crv = PK11_GETTAB(slot)->C_Login(rwsession,CKU_SO,
|
|
Packit |
40b132 |
(unsigned char *)ssopw,ssolen);
|
|
Packit |
40b132 |
slot->lastLoginCheck = 0;
|
|
Packit |
40b132 |
if (crv != CKR_OK) {
|
|
Packit |
40b132 |
PORT_SetError(PK11_MapError(crv));
|
|
Packit |
40b132 |
goto done;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
crv = PK11_GETTAB(slot)->C_InitPIN(rwsession,(unsigned char *)userpw,len);
|
|
Packit |
40b132 |
if (crv != CKR_OK) {
|
|
Packit |
40b132 |
PORT_SetError(PK11_MapError(crv));
|
|
Packit |
40b132 |
} else {
|
|
Packit |
40b132 |
rv = SECSuccess;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
done:
|
|
Packit |
40b132 |
PK11_GETTAB(slot)->C_Logout(rwsession);
|
|
Packit |
40b132 |
slot->lastLoginCheck = 0;
|
|
Packit |
40b132 |
PK11_RestoreROSession(slot,rwsession);
|
|
Packit |
40b132 |
if (rv == SECSuccess) {
|
|
Packit |
40b132 |
/* update our view of the world */
|
|
Packit |
40b132 |
PK11_InitToken(slot,PR_TRUE);
|
|
Packit |
40b132 |
if (slot->needLogin) {
|
|
Packit |
40b132 |
PK11_EnterSlotMonitor(slot);
|
|
Packit |
40b132 |
PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER,
|
|
Packit |
40b132 |
(unsigned char *)userpw,len);
|
|
Packit |
40b132 |
slot->lastLoginCheck = 0;
|
|
Packit |
40b132 |
PK11_ExitSlotMonitor(slot);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return rv;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* Change an existing user password
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
SECStatus
|
|
Packit |
40b132 |
PK11_ChangePW(PK11SlotInfo *slot, const char *oldpw, const char *newpw)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
CK_RV crv;
|
|
Packit |
40b132 |
SECStatus rv = SECFailure;
|
|
Packit |
40b132 |
int newLen = 0;
|
|
Packit |
40b132 |
int oldLen = 0;
|
|
Packit |
40b132 |
CK_SESSION_HANDLE rwsession;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* use NULL values to trigger the protected authentication path */
|
|
Packit |
40b132 |
if (!slot->protectedAuthPath) {
|
|
Packit |
40b132 |
if (newpw == NULL) newpw = "";
|
|
Packit |
40b132 |
if (oldpw == NULL) oldpw = "";
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
if (newpw) newLen = PORT_Strlen(newpw);
|
|
Packit |
40b132 |
if (oldpw) oldLen = PORT_Strlen(oldpw);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* get a rwsession */
|
|
Packit |
40b132 |
rwsession = PK11_GetRWSession(slot);
|
|
Packit |
40b132 |
if (rwsession == CK_INVALID_SESSION) {
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_BAD_DATA);
|
|
Packit |
40b132 |
return rv;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
crv = PK11_GETTAB(slot)->C_SetPIN(rwsession,
|
|
Packit |
40b132 |
(unsigned char *)oldpw,oldLen,(unsigned char *)newpw,newLen);
|
|
Packit |
40b132 |
if (crv == CKR_OK) {
|
|
Packit |
40b132 |
rv = SECSuccess;
|
|
Packit |
40b132 |
} else {
|
|
Packit |
40b132 |
PORT_SetError(PK11_MapError(crv));
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
PK11_RestoreROSession(slot,rwsession);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* update our view of the world */
|
|
Packit |
40b132 |
PK11_InitToken(slot,PR_TRUE);
|
|
Packit |
40b132 |
return rv;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
static char *
|
|
Packit |
40b132 |
pk11_GetPassword(PK11SlotInfo *slot, PRBool retry, void * wincx)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
if (PK11_Global.getPass == NULL) return NULL;
|
|
Packit |
40b132 |
return (*PK11_Global.getPass)(slot, retry, wincx);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
void
|
|
Packit |
40b132 |
PK11_SetPasswordFunc(PK11PasswordFunc func)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
PK11_Global.getPass = func;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
void
|
|
Packit |
40b132 |
PK11_SetVerifyPasswordFunc(PK11VerifyPasswordFunc func)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
PK11_Global.verifyPass = func;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
void
|
|
Packit |
40b132 |
PK11_SetIsLoggedInFunc(PK11IsLoggedInFunc func)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
PK11_Global.isLoggedIn = func;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* authenticate to a slot. This loops until we can't recover, the user
|
|
Packit |
40b132 |
* gives up, or we succeed. If we're already logged in and this function
|
|
Packit |
40b132 |
* is called we will still prompt for a password, but we will probably
|
|
Packit |
40b132 |
* succeed no matter what the password was (depending on the implementation
|
|
Packit |
40b132 |
* of the PKCS 11 module.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
SECStatus
|
|
Packit |
40b132 |
PK11_DoPassword(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
|
|
Packit |
40b132 |
PRBool loadCerts, void *wincx, PRBool alreadyLocked,
|
|
Packit |
40b132 |
PRBool contextSpecific)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
SECStatus rv = SECFailure;
|
|
Packit |
40b132 |
char * password;
|
|
Packit |
40b132 |
PRBool attempt = PR_FALSE;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if (PK11_NeedUserInit(slot)) {
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_IO);
|
|
Packit |
40b132 |
return SECFailure;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* Central server type applications which control access to multiple
|
|
Packit |
40b132 |
* slave applications to single crypto devices need to virtuallize the
|
|
Packit |
40b132 |
* login state. This is done by a callback out of PK11_IsLoggedIn and
|
|
Packit |
40b132 |
* here. If we are actually logged in, then we got here because the
|
|
Packit |
40b132 |
* higher level code told us that the particular client application may
|
|
Packit |
40b132 |
* still need to be logged in. If that is the case, we simply tell the
|
|
Packit |
40b132 |
* server code that it should now verify the clients password and tell us
|
|
Packit |
40b132 |
* the results.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
if (PK11_IsLoggedIn(slot,NULL) &&
|
|
Packit |
40b132 |
(PK11_Global.verifyPass != NULL)) {
|
|
Packit |
40b132 |
if (!PK11_Global.verifyPass(slot,wincx)) {
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_BAD_PASSWORD);
|
|
Packit |
40b132 |
return SECFailure;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return SECSuccess;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* get the password. This can drop out of the while loop
|
|
Packit |
40b132 |
* for the following reasons:
|
|
Packit |
40b132 |
* (1) the user refused to enter a password.
|
|
Packit |
40b132 |
* (return error to caller)
|
|
Packit |
40b132 |
* (2) the token user password is disabled [usually due to
|
|
Packit |
40b132 |
* too many failed authentication attempts].
|
|
Packit |
40b132 |
* (return error to caller)
|
|
Packit |
40b132 |
* (3) the password was successful.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
while ((password = pk11_GetPassword(slot, attempt, wincx)) != NULL) {
|
|
Packit |
40b132 |
/* if the token has a protectedAuthPath, the application may have
|
|
Packit |
40b132 |
* already issued the C_Login as part of it's pk11_GetPassword call.
|
|
Packit |
40b132 |
* In this case the application will tell us what the results were in
|
|
Packit |
40b132 |
* the password value (retry or the authentication was successful) so
|
|
Packit |
40b132 |
* we can skip our own C_Login call (which would force the token to
|
|
Packit |
40b132 |
* try to login again).
|
|
Packit |
40b132 |
*
|
|
Packit |
40b132 |
* Applications that don't know about protectedAuthPath will return a
|
|
Packit |
40b132 |
* password, which we will ignore and trigger the token to
|
|
Packit |
40b132 |
* 'authenticate' itself anyway. Hopefully the blinking display on
|
|
Packit |
40b132 |
* the reader, or the flashing light under the thumbprint reader will
|
|
Packit |
40b132 |
* attract the user's attention */
|
|
Packit |
40b132 |
attempt = PR_TRUE;
|
|
Packit |
40b132 |
if (slot->protectedAuthPath) {
|
|
Packit |
40b132 |
/* application tried to authenticate and failed. it wants to try
|
|
Packit |
40b132 |
* again, continue looping */
|
|
Packit |
40b132 |
if (strcmp(password, PK11_PW_RETRY) == 0) {
|
|
Packit |
40b132 |
rv = SECWouldBlock;
|
|
Packit |
40b132 |
PORT_Free(password);
|
|
Packit |
40b132 |
continue;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
/* applicaton tried to authenticate and succeeded we're done */
|
|
Packit |
40b132 |
if (strcmp(password, PK11_PW_AUTHENTICATED) == 0) {
|
|
Packit |
40b132 |
rv = SECSuccess;
|
|
Packit |
40b132 |
PORT_Free(password);
|
|
Packit |
40b132 |
break;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
rv = pk11_CheckPassword(slot, session, password,
|
|
Packit |
40b132 |
alreadyLocked, contextSpecific);
|
|
Packit |
40b132 |
PORT_Memset(password, 0, PORT_Strlen(password));
|
|
Packit |
40b132 |
PORT_Free(password);
|
|
Packit |
40b132 |
if (rv != SECWouldBlock) break;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
if (rv == SECSuccess) {
|
|
Packit |
40b132 |
if (!PK11_IsFriendly(slot)) {
|
|
Packit |
40b132 |
nssTrustDomain_UpdateCachedTokenCerts(slot->nssToken->trustDomain,
|
|
Packit |
40b132 |
slot->nssToken);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
} else if (!attempt) PORT_SetError(SEC_ERROR_BAD_PASSWORD);
|
|
Packit |
40b132 |
return rv;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
void PK11_LogoutAll(void)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
|
|
Packit |
40b132 |
SECMODModuleList *modList;
|
|
Packit |
40b132 |
SECMODModuleList *mlp = NULL;
|
|
Packit |
40b132 |
int i;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* NSS is not initialized, there are not tokens to log out */
|
|
Packit |
40b132 |
if (lock == NULL) {
|
|
Packit |
40b132 |
return;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
SECMOD_GetReadLock(lock);
|
|
Packit |
40b132 |
modList = SECMOD_GetDefaultModuleList();
|
|
Packit |
40b132 |
/* find the number of entries */
|
|
Packit |
40b132 |
for (mlp = modList; mlp != NULL; mlp = mlp->next) {
|
|
Packit |
40b132 |
for (i=0; i < mlp->module->slotCount; i++) {
|
|
Packit |
40b132 |
PK11_Logout(mlp->module->slots[i]);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
SECMOD_ReleaseReadLock(lock);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
int
|
|
Packit |
40b132 |
PK11_GetMinimumPwdLength(PK11SlotInfo *slot)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
return ((int)slot->minPassword);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* Does this slot have a protected pin path? */
|
|
Packit |
40b132 |
PRBool
|
|
Packit |
40b132 |
PK11_ProtectedAuthenticationPath(PK11SlotInfo *slot)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
return slot->protectedAuthPath;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* we can initialize the password if 1) The toke is not inited
|
|
Packit |
40b132 |
* (need login == true and see need UserInit) or 2) the token has
|
|
Packit |
40b132 |
* a NULL password. (slot->needLogin = false & need user Init = false).
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
PRBool PK11_NeedPWInitForSlot(PK11SlotInfo *slot)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
if (slot->needLogin && PK11_NeedUserInit(slot)) {
|
|
Packit |
40b132 |
return PR_TRUE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
if (!slot->needLogin && !PK11_NeedUserInit(slot)) {
|
|
Packit |
40b132 |
return PR_TRUE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return PR_FALSE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
PRBool PK11_NeedPWInit()
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
PK11SlotInfo *slot = PK11_GetInternalKeySlot();
|
|
Packit |
40b132 |
PRBool ret = PK11_NeedPWInitForSlot(slot);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
PK11_FreeSlot(slot);
|
|
Packit |
40b132 |
return ret;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
PRBool
|
|
Packit |
40b132 |
pk11_InDelayPeriod(PRIntervalTime lastTime, PRIntervalTime delayTime,
|
|
Packit |
40b132 |
PRIntervalTime *retTime)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
PRIntervalTime time;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
*retTime = time = PR_IntervalNow();
|
|
Packit |
40b132 |
return (PRBool) (lastTime) && ((time-lastTime) < delayTime);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* Determine if the token is logged in. We have to actually query the token,
|
|
Packit |
40b132 |
* because it's state can change without intervention from us.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
PRBool
|
|
Packit |
40b132 |
PK11_IsLoggedIn(PK11SlotInfo *slot,void *wincx)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
CK_SESSION_INFO sessionInfo;
|
|
Packit |
40b132 |
int askpw = slot->askpw;
|
|
Packit |
40b132 |
int timeout = slot->timeout;
|
|
Packit |
40b132 |
CK_RV crv;
|
|
Packit |
40b132 |
PRIntervalTime curTime;
|
|
Packit |
40b132 |
static PRIntervalTime login_delay_time = 0;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if (login_delay_time == 0) {
|
|
Packit |
40b132 |
login_delay_time = PR_SecondsToInterval(1);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* If we don't have our own password default values, use the system
|
|
Packit |
40b132 |
* ones */
|
|
Packit |
40b132 |
if ((slot->defaultFlags & PK11_OWN_PW_DEFAULTS) == 0) {
|
|
Packit |
40b132 |
PK11SlotInfo *def_slot = PK11_GetInternalKeySlot();
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if (def_slot) {
|
|
Packit |
40b132 |
askpw = def_slot->askpw;
|
|
Packit |
40b132 |
timeout = def_slot->timeout;
|
|
Packit |
40b132 |
PK11_FreeSlot(def_slot);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ((wincx != NULL) && (PK11_Global.isLoggedIn != NULL) &&
|
|
Packit |
40b132 |
(*PK11_Global.isLoggedIn)(slot, wincx) == PR_FALSE) { return PR_FALSE; }
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* forget the password if we've been inactive too long */
|
|
Packit |
40b132 |
if (askpw == 1) {
|
|
Packit |
40b132 |
PRTime currtime = PR_Now();
|
|
Packit |
40b132 |
PRTime result;
|
|
Packit |
40b132 |
PRTime mult;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
LL_I2L(result, timeout);
|
|
Packit |
40b132 |
LL_I2L(mult, 60*1000*1000);
|
|
Packit |
40b132 |
LL_MUL(result,result,mult);
|
|
Packit |
40b132 |
LL_ADD(result, result, slot->authTime);
|
|
Packit |
40b132 |
if (LL_CMP(result, <, currtime) ) {
|
|
Packit |
40b132 |
PK11_EnterSlotMonitor(slot);
|
|
Packit |
40b132 |
PK11_GETTAB(slot)->C_Logout(slot->session);
|
|
Packit |
40b132 |
slot->lastLoginCheck = 0;
|
|
Packit |
40b132 |
PK11_ExitSlotMonitor(slot);
|
|
Packit |
40b132 |
} else {
|
|
Packit |
40b132 |
slot->authTime = currtime;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
PK11_EnterSlotMonitor(slot);
|
|
Packit |
40b132 |
if (pk11_InDelayPeriod(slot->lastLoginCheck,login_delay_time, &curTime)) {
|
|
Packit |
40b132 |
sessionInfo.state = slot->lastState;
|
|
Packit |
40b132 |
crv = CKR_OK;
|
|
Packit |
40b132 |
} else {
|
|
Packit |
40b132 |
crv = PK11_GETTAB(slot)->C_GetSessionInfo(slot->session,&sessionInfo);
|
|
Packit |
40b132 |
if (crv == CKR_OK) {
|
|
Packit |
40b132 |
slot->lastState = sessionInfo.state;
|
|
Packit |
40b132 |
slot->lastLoginCheck = curTime;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
PK11_ExitSlotMonitor(slot);
|
|
Packit |
40b132 |
/* if we can't get session info, something is really wrong */
|
|
Packit |
40b132 |
if (crv != CKR_OK) {
|
|
Packit |
40b132 |
slot->session = CK_INVALID_SESSION;
|
|
Packit |
40b132 |
return PR_FALSE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
switch (sessionInfo.state) {
|
|
Packit |
40b132 |
case CKS_RW_PUBLIC_SESSION:
|
|
Packit |
40b132 |
case CKS_RO_PUBLIC_SESSION:
|
|
Packit |
40b132 |
default:
|
|
Packit |
40b132 |
break; /* fail */
|
|
Packit |
40b132 |
case CKS_RW_USER_FUNCTIONS:
|
|
Packit |
40b132 |
case CKS_RW_SO_FUNCTIONS:
|
|
Packit |
40b132 |
case CKS_RO_USER_FUNCTIONS:
|
|
Packit |
40b132 |
return PR_TRUE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return PR_FALSE;
|
|
Packit |
40b132 |
}
|