Back to index

lightning-sunbird  0.9+nobinonly
Classes | Functions | Variables
pk11auth.c File Reference
#include "seccomon.h"
#include "secmod.h"
#include "secmodi.h"
#include "secmodti.h"
#include "pkcs11t.h"
#include "pk11func.h"
#include "secitem.h"
#include "secerr.h"
#include "pkim.h"

Go to the source code of this file.

Classes

struct  PK11GlobalStruct

Functions

SECStatus pk11_CheckPassword (PK11SlotInfo *slot, char *pw)
SECStatus PK11_CheckUserPassword (PK11SlotInfo *slot, char *pw)
SECStatus PK11_Logout (PK11SlotInfo *slot)
void PK11_StartAuthTransaction (void)
void PK11_EndAuthTransaction (void)
void PK11_HandlePasswordCheck (PK11SlotInfo *slot, void *wincx)
void PK11_SlotDBUpdate (PK11SlotInfo *slot)
void PK11_SetSlotPWValues (PK11SlotInfo *slot, int askpw, int timeout)
void PK11_GetSlotPWValues (PK11SlotInfo *slot, int *askpw, int *timeout)
PRBool pk11_LoginStillRequired (PK11SlotInfo *slot, void *wincx)
SECStatus PK11_Authenticate (PK11SlotInfo *slot, PRBool loadCerts, void *wincx)
SECStatus pk11_AuthenticateUnfriendly (PK11SlotInfo *slot, PRBool loadCerts, void *wincx)
SECStatus PK11_CheckSSOPassword (PK11SlotInfo *slot, char *ssopw)
SECStatus PK11_VerifyPW (PK11SlotInfo *slot, char *pw)
SECStatus PK11_InitPin (PK11SlotInfo *slot, char *ssopw, char *userpw)
SECStatus PK11_ChangePW (PK11SlotInfo *slot, char *oldpw, char *newpw)
static char * pk11_GetPassword (PK11SlotInfo *slot, PRBool retry, void *wincx)
void PK11_SetPasswordFunc (PK11PasswordFunc func)
void PK11_SetVerifyPasswordFunc (PK11VerifyPasswordFunc func)
void PK11_SetIsLoggedInFunc (PK11IsLoggedInFunc func)
SECStatus PK11_DoPassword (PK11SlotInfo *slot, PRBool loadCerts, void *wincx)
void PK11_LogoutAll (void)
int PK11_GetMinimumPwdLength (PK11SlotInfo *slot)
PRBool PK11_ProtectedAuthenticationPath (PK11SlotInfo *slot)
PRBool PK11_NeedPWInitForSlot (PK11SlotInfo *slot)
PRBool PK11_NeedPWInit ()
PRBool pk11_InDelayPeriod (PRIntervalTime lastTime, PRIntervalTime delayTime, PRIntervalTime *retTime)
PRBool PK11_IsLoggedIn (PK11SlotInfo *slot, void *wincx)

Variables

static struct PK11GlobalStruct PK11_Global

Function Documentation

SECStatus PK11_Authenticate ( PK11SlotInfo *  slot,
PRBool  loadCerts,
void wincx 
)

Definition at line 294 of file pk11auth.c.

                                                                     {
    if (pk11_LoginStillRequired(slot,wincx)) {
       return PK11_DoPassword(slot,loadCerts,wincx);
    }
    return SECSuccess;
}

Here is the call graph for this function:

SECStatus pk11_AuthenticateUnfriendly ( PK11SlotInfo *  slot,
PRBool  loadCerts,
void wincx 
)

Definition at line 306 of file pk11auth.c.

{
    SECStatus rv = SECSuccess;
    if (!PK11_IsFriendly(slot)) {
       rv = PK11_Authenticate(slot, loadCerts, wincx);
    }
    return rv;
}

Here is the call graph for this function:

SECStatus PK11_ChangePW ( PK11SlotInfo *  slot,
char *  oldpw,
char *  newpw 
)

Definition at line 453 of file pk11auth.c.

{
    CK_RV crv;
    SECStatus rv = SECFailure;
    int newLen;
    int oldLen;
    CK_SESSION_HANDLE rwsession;

    if (newpw == NULL) newpw = "";
    if (oldpw == NULL) oldpw = "";
    newLen = PORT_Strlen(newpw);
    oldLen = PORT_Strlen(oldpw);

    /* get a rwsession */
    rwsession = PK11_GetRWSession(slot);
    if (rwsession == CK_INVALID_SESSION) {
       PORT_SetError(SEC_ERROR_BAD_DATA);
       return rv;
    }

    crv = PK11_GETTAB(slot)->C_SetPIN(rwsession,
              (unsigned char *)oldpw,oldLen,(unsigned char *)newpw,newLen);
    if (crv == CKR_OK) {
       rv = SECSuccess;
    } else {
       PORT_SetError(PK11_MapError(crv));
    }

    PK11_RestoreROSession(slot,rwsession);

    /* update our view of the world */
    PK11_InitToken(slot,PR_TRUE);
    return rv;
}

Here is the call graph for this function:

SECStatus pk11_CheckPassword ( PK11SlotInfo *  slot,
char *  pw 
)

Definition at line 81 of file pk11auth.c.

{
    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);
    }

    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 */
    }
    return rv;
}

Here is the call graph for this function:

SECStatus PK11_CheckSSOPassword ( PK11SlotInfo *  slot,
char *  ssopw 
)

Definition at line 320 of file pk11auth.c.

{
    CK_SESSION_HANDLE rwsession;
    CK_RV crv;
    SECStatus rv = SECFailure;
    int len = 0;

    /* get a rwsession */
    rwsession = PK11_GetRWSession(slot);
    if (rwsession == CK_INVALID_SESSION) {
       PORT_SetError(SEC_ERROR_BAD_DATA);
       return rv;
    }

    if (slot->protectedAuthPath) {
       len = 0;
       ssopw = NULL;
    } else if (ssopw == NULL) {
       PORT_SetError(SEC_ERROR_INVALID_ARGS);
       return SECFailure;
    } else {
       len = PORT_Strlen(ssopw);
    }

    /* check the password */
    crv = PK11_GETTAB(slot)->C_Login(rwsession,CKU_SO,
                                          (unsigned char *)ssopw,len);
    slot->lastLoginCheck = 0;
    switch (crv) {
    /* if we're already logged in, we're good to go */
    case CKR_OK:
       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 */
    }
    PK11_GETTAB(slot)->C_Logout(rwsession);
    slot->lastLoginCheck = 0;

    /* release rwsession */
    PK11_RestoreROSession(slot,rwsession);
    return rv;
}

Here is the call graph for this function:

SECStatus PK11_CheckUserPassword ( PK11SlotInfo *  slot,
char *  pw 
)

Definition at line 127 of file pk11auth.c.

{
    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;
}

Here is the call graph for this function:

SECStatus PK11_DoPassword ( PK11SlotInfo *  slot,
PRBool  loadCerts,
void wincx 
)

Definition at line 522 of file pk11auth.c.

{
    SECStatus rv = SECFailure;
    char * password;
    PRBool attempt = PR_FALSE;

    if (PK11_NeedUserInit(slot)) {
       PORT_SetError(SEC_ERROR_IO);
       return SECFailure;
    }


    /*
     * Central server type applications which control access to multiple
     * slave applications to single crypto devices need to virtuallize the
     * login state. This is done by a callback out of PK11_IsLoggedIn and
     * here. If we are actually logged in, then we got here because the
     * higher level code told us that the particular client application may
     * still need to be logged in. If that is the case, we simply tell the
     * server code that it should now verify the clients password and tell us
     * the results.
     */
    if (PK11_IsLoggedIn(slot,NULL) && 
                     (PK11_Global.verifyPass != NULL)) {
       if (!PK11_Global.verifyPass(slot,wincx)) {
           PORT_SetError(SEC_ERROR_BAD_PASSWORD);
           return SECFailure;
       }
       return SECSuccess;
    }

    /* get the password. This can drop out of the while loop
     * for the following reasons:
     *        (1) the user refused to enter a password. 
     *               (return error to caller)
     * (2) the token user password is disabled [usually due to
     *    too many failed authentication attempts].
     *               (return error to caller)
     * (3) the password was successful.
     */
    while ((password = pk11_GetPassword(slot, attempt, wincx)) != NULL) {
       /* if the token has a protectedAuthPath, the application may have
         * already issued the C_Login as part of it's pk11_GetPassword call.
         * In this case the application will tell us what the results were in 
         * the password value (retry or the authentication was successful) so
        * we can skip our own C_Login call (which would force the token to
        * try to login again).
        * 
        * Applications that don't know about protectedAuthPath will return a 
        * password, which we will ignore and trigger the token to 
        * 'authenticate' itself anyway. Hopefully the blinking display on 
        * the reader, or the flashing light under the thumbprint reader will 
        * attract the user's attention */
       attempt = PR_TRUE;
       if (slot->protectedAuthPath) {
           /* application tried to authenticate and failed. it wants to try
            * again, continue looping */
           if (strcmp(password, PK11_PW_RETRY) == 0) {
              rv = SECWouldBlock;
              PORT_Free(password);
              continue;
           }
           /* applicaton tried to authenticate and succeeded we're done */
           if (strcmp(password, PK11_PW_AUTHENTICATED) == 0) {
              rv = SECSuccess;
              PORT_Free(password);
              break;
           }
       }
       rv = pk11_CheckPassword(slot,password);
       PORT_Memset(password, 0, PORT_Strlen(password));
       PORT_Free(password);
       if (rv != SECWouldBlock) break;
    }
    if (rv == SECSuccess) {
       rv = pk11_CheckVerifyTest(slot);
       if (!PK11_IsFriendly(slot)) {
           nssTrustDomain_UpdateCachedTokenCerts(slot->nssToken->trustDomain,
                                             slot->nssToken);
       }
    } else if (!attempt) PORT_SetError(SEC_ERROR_BAD_PASSWORD);
    return rv;
}

Here is the call graph for this function:

Definition at line 197 of file pk11auth.c.

int PK11_GetMinimumPwdLength ( PK11SlotInfo *  slot)

Definition at line 630 of file pk11auth.c.

{
    return ((int)slot->minPassword);
}
static char* pk11_GetPassword ( PK11SlotInfo *  slot,
PRBool  retry,
void wincx 
) [static]

Definition at line 489 of file pk11auth.c.

{
    if (PK11_Global.getPass == NULL) return NULL;
    return (*PK11_Global.getPass)(slot, retry, wincx);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void PK11_GetSlotPWValues ( PK11SlotInfo *  slot,
int askpw,
int timeout 
)

Definition at line 262 of file pk11auth.c.

{
    *askpw = slot->askpw;
    *timeout = slot->timeout;

    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);
       }
    }
}

Here is the call graph for this function:

void PK11_HandlePasswordCheck ( PK11SlotInfo *  slot,
void wincx 
)

Definition at line 208 of file pk11auth.c.

{
    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);
}

Here is the call graph for this function:

PRBool pk11_InDelayPeriod ( PRIntervalTime  lastTime,
PRIntervalTime  delayTime,
PRIntervalTime retTime 
)

Definition at line 668 of file pk11auth.c.

{
    PRIntervalTime time;

    *retTime = time = PR_IntervalNow();
    return (PRBool) (lastTime) && ((time-lastTime) < delayTime);
}
SECStatus PK11_InitPin ( PK11SlotInfo *  slot,
char *  ssopw,
char *  userpw 
)

Definition at line 388 of file pk11auth.c.

{
    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);
       PK11_EnterSlotMonitor(slot);
       PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER,
                                          (unsigned char *)userpw,len);
       slot->lastLoginCheck = 0;
       PK11_ExitSlotMonitor(slot);
    }
    return rv;
}

Here is the call graph for this function:

PRBool PK11_IsLoggedIn ( PK11SlotInfo *  slot,
void wincx 
)

Definition at line 682 of file pk11auth.c.

{
    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 {
           slot->authTime = currtime;
       }
    }

    PK11_EnterSlotMonitor(slot);
    if (pk11_InDelayPeriod(slot->lastLoginCheck,login_delay_time, &curTime)) {
       sessionInfo.state = slot->lastState;
       crv = CKR_OK;
    } else {
       crv = PK11_GETTAB(slot)->C_GetSessionInfo(slot->session,&sessionInfo);
       if (crv == CKR_OK) {
           slot->lastState = sessionInfo.state;
           slot->lastLoginCheck = curTime;
       }
    }
    PK11_ExitSlotMonitor(slot);
    /* if we can't get session info, something is really wrong */
    if (crv != CKR_OK) {
       slot->session = CK_INVALID_SESSION;
       return PR_FALSE;
    }

    switch (sessionInfo.state) {
    case CKS_RW_PUBLIC_SESSION:
    case CKS_RO_PUBLIC_SESSION:
    default:
       break; /* fail */
    case CKS_RW_USER_FUNCTIONS:
    case CKS_RW_SO_FUNCTIONS:
    case CKS_RO_USER_FUNCTIONS:
       return PR_TRUE;
    }
    return PR_FALSE; 
}

Here is the call graph for this function:

PRBool pk11_LoginStillRequired ( PK11SlotInfo *  slot,
void wincx 
)

Definition at line 284 of file pk11auth.c.

{
    return slot->needLogin && !PK11_IsLoggedIn(slot,wincx);
}

Here is the call graph for this function:

SECStatus PK11_Logout ( PK11SlotInfo *  slot)

Definition at line 171 of file pk11auth.c.

{
    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;
}

Here is the call graph for this function:

Definition at line 606 of file pk11auth.c.

{
    SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
    SECMODModuleList *modList = SECMOD_GetDefaultModuleList();
    SECMODModuleList *mlp = NULL;
    int i;

    /* NSS is not initialized, there are not tokens to log out */
    if (lock == NULL) {
       return;
    }

    SECMOD_GetReadLock(lock);
    /* find the number of entries */
    for (mlp = modList; mlp != NULL; mlp = mlp->next) {
       for (i=0; i < mlp->module->slotCount; i++) {
           PK11_Logout(mlp->module->slots[i]);
       }
    }

    SECMOD_ReleaseReadLock(lock);
}

Here is the call graph for this function:

Definition at line 658 of file pk11auth.c.

{
    PK11SlotInfo *slot = PK11_GetInternalKeySlot();
    PRBool ret = PK11_NeedPWInitForSlot(slot);

    PK11_FreeSlot(slot);
    return ret;
}

Here is the call graph for this function:

PRBool PK11_NeedPWInitForSlot ( PK11SlotInfo *  slot)

Definition at line 647 of file pk11auth.c.

{
    if (slot->needLogin && PK11_NeedUserInit(slot)) {
       return PR_TRUE;
    }
    if (!slot->needLogin && !PK11_NeedUserInit(slot)) {
       return PR_TRUE;
    }
    return PR_FALSE;
}

Here is the call graph for this function:

PRBool PK11_ProtectedAuthenticationPath ( PK11SlotInfo *  slot)

Definition at line 637 of file pk11auth.c.

{
       return slot->protectedAuthPath;
}

Definition at line 508 of file pk11auth.c.

{
    PK11_Global.isLoggedIn = func;
}

Definition at line 496 of file pk11auth.c.

Here is the call graph for this function:

void PK11_SetSlotPWValues ( PK11SlotInfo *  slot,
int  askpw,
int  timeout 
)

Definition at line 250 of file pk11auth.c.

{
        slot->askpw = askpw;
        slot->timeout = timeout;
        slot->defaultFlags |= PK11_OWN_PW_DEFAULTS;
        PK11_SlotDBUpdate(slot);
}

Here is the call graph for this function:

Definition at line 502 of file pk11auth.c.

{
    PK11_Global.verifyPass = func;
}
void PK11_SlotDBUpdate ( PK11SlotInfo *  slot)

Definition at line 241 of file pk11auth.c.

{
    SECMOD_UpdateModule(slot->module);
}

Here is the call graph for this function:

Definition at line 191 of file pk11auth.c.

SECStatus PK11_VerifyPW ( PK11SlotInfo *  slot,
char *  pw 
)

Definition at line 373 of file pk11auth.c.

{
    int len = PORT_Strlen(pw);

    if ((slot->minPassword > len) || (slot->maxPassword < len)) {
       PORT_SetError(SEC_ERROR_BAD_DATA);
       return SECFailure;
    }
    return SECSuccess;
}

Here is the call graph for this function:


Variable Documentation

struct PK11GlobalStruct PK11_Global [static]