pk11slot.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,388 行 · 第 1/5 页

C
2,388
字号
   if (slot->sessionLock) {	PR_DestroyLock(slot->sessionLock);	slot->sessionLock = NULL;   }   if (slot->freeListLock) {	PR_DestroyLock(slot->freeListLock);	slot->freeListLock = NULL;   }#endif   /* ok, well not quit finally... now we free the memory */   PORT_Free(slot);}/* We're all done with the slot, free it */voidPK11_FreeSlot(PK11SlotInfo *slot){    PRBool freeit = PR_FALSE;    PK11_USE_THREADS(PR_Lock(slot->refLock);)    if (slot->refCount-- == 1) freeit = PR_TRUE;    PK11_USE_THREADS(PR_Unlock(slot->refLock);)    if (freeit) PK11_DestroySlot(slot);}voidPK11_EnterSlotMonitor(PK11SlotInfo *slot) {    PR_Lock(slot->sessionLock);}voidPK11_ExitSlotMonitor(PK11SlotInfo *slot) {    PR_Unlock(slot->sessionLock);}/*********************************************************** * Functions to find specific slots. ***********************************************************/PK11SlotInfo *PK11_FindSlotByName(char *name){   SECMODModuleList *mlp;   SECMODModuleList *modules = SECMOD_GetDefaultModuleList();   SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();   int i;   PK11SlotInfo *slot = NULL;   if ((name == NULL) || (*name == 0)) {	return PK11_GetInternalKeySlot();   }   /* work through all the slots */   SECMOD_GetReadLock(moduleLock);   for(mlp = modules; mlp != NULL; mlp = mlp->next) {	for (i=0; i < mlp->module->slotCount; i++) {	    PK11SlotInfo *tmpSlot = mlp->module->slots[i];	    if (PK11_IsPresent(tmpSlot)) {		if (PORT_Strcmp(tmpSlot->token_name,name) == 0) {		    slot = PK11_ReferenceSlot(tmpSlot);		    break;		}	    }	}	if (slot != NULL) break;    }    SECMOD_ReleaseReadLock(moduleLock);    if (slot == NULL) {	PORT_SetError(SEC_ERROR_NO_TOKEN);    }    return slot;}PK11SlotInfo *PK11_FindSlotBySerial(char *serial){   SECMODModuleList *mlp;   SECMODModuleList *modules = SECMOD_GetDefaultModuleList();   SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();   int i;   PK11SlotInfo *slot = NULL;   /* work through all the slots */   SECMOD_GetReadLock(moduleLock);   for(mlp = modules; mlp != NULL; mlp = mlp->next) {	for (i=0; i < mlp->module->slotCount; i++) {	    PK11SlotInfo *tmpSlot = mlp->module->slots[i];	    if (PK11_IsPresent(tmpSlot)) {		if (PORT_Memcmp(tmpSlot->serial,serial,					sizeof(tmpSlot->serial)) == 0) {		    slot = PK11_ReferenceSlot(tmpSlot);		    break;		}	    }	}	if (slot != NULL) break;    }    SECMOD_ReleaseReadLock(moduleLock);    if (slot == NULL) {	PORT_SetError(SEC_ERROR_NO_TOKEN);    }    return slot;}/*********************************************************** * Password Utilities ***********************************************************//* * Check the user's password. Log into the card if it's correct. * succeed if the user is already logged in. */SECStatuspk11_CheckPassword(PK11SlotInfo *slot,char *pw){    int len = PORT_Strlen(pw);    CK_RV crv;    SECStatus rv;    int64 currtime = PR_Now();    PK11_EnterSlotMonitor(slot);    crv = PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER,						(unsigned char *)pw,len);    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;}/* * Check the user's password. Logout before hand to make sure that * we are really checking the password. */SECStatusPK11_CheckUserPassword(PK11SlotInfo *slot,char *pw){    int len = PORT_Strlen(pw);    CK_RV crv;    SECStatus rv;    int64 currtime = PR_Now();    /* 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);    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;}SECStatusPK11_Logout(PK11SlotInfo *slot){    CK_RV crv;    /* force a logout */    PK11_EnterSlotMonitor(slot);    crv = PK11_GETTAB(slot)->C_Logout(slot->session);    PK11_ExitSlotMonitor(slot);    if (crv != CKR_OK) {	PORT_SetError(PK11_MapError(crv));	return SECFailure;    }    return  SECSuccess;}/* * transaction stuff is for when we test for the need to do every * time auth to see if we already did it for this slot/transaction */void PK11_StartAuthTransaction(void){PK11_Global.transaction++;PK11_Global.inTransaction = PR_TRUE;}void PK11_EndAuthTransaction(void){PK11_Global.transaction++;PK11_Global.inTransaction = PR_FALSE;}/* * before we do a private key op, we check to see if we * need to reauthenticate. */voidPK11_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 (slot->askpw == -1) {	if (!PK11_Global.inTransaction	||			 (PK11_Global.transaction != slot->authTransact)) {    	    PK11_EnterSlotMonitor(slot);	    PK11_GETTAB(slot)->C_Logout(slot->session);    	    PK11_ExitSlotMonitor(slot);	    NeedAuth = PR_TRUE;	}    }    if (NeedAuth) PK11_DoPassword(slot,PR_TRUE,wincx);}voidPK11_SlotDBUpdate(PK11SlotInfo *slot){    SECMOD_AddPermDB(slot->module);}/* * set new askpw and timeout values */voidPK11_SetSlotPWValues(PK11SlotInfo *slot,int askpw, int timeout){        slot->askpw = askpw;        slot->timeout = timeout;        slot->defaultFlags |= PK11_OWN_PW_DEFAULTS;        PK11_SlotDBUpdate(slot);}/* * Get the askpw and timeout values for this slot */voidPK11_GetSlotPWValues(PK11SlotInfo *slot,int *askpw, int *timeout){    *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);	}    }}/* * make sure a slot is authenticated... */SECStatusPK11_Authenticate(PK11SlotInfo *slot, PRBool loadCerts, void *wincx) {    if (slot->needLogin && !PK11_IsLoggedIn(slot,wincx)) {	return PK11_DoPassword(slot,loadCerts,wincx);    }    return SECSuccess;}/* * notification stub. If we ever get interested in any events that * the pkcs11 functions may pass back to use, we can catch them here... * currently pdata is a slotinfo structure. */CK_RV pk11_notify(CK_SESSION_HANDLE session, CK_NOTIFICATION event,							 CK_VOID_PTR pdata){    return CKR_OK;}/* * grab a new RW session * !!! has a side effect of grabbing the Monitor if either the slot's default * session is RW or the slot is not thread safe. Monitor is release in function * below */CK_SESSION_HANDLE PK11_GetRWSession(PK11SlotInfo *slot){    CK_SESSION_HANDLE rwsession;    CK_RV crv;    if (!slot->isThreadSafe || slot->defRWSession) PK11_EnterSlotMonitor(slot);    if (slot->defRWSession) return slot->session;    crv = PK11_GETTAB(slot)->C_OpenSession(slot->slotID,				CKF_RW_SESSION|CKF_SERIAL_SESSION,				  	  slot, pk11_notify,&rwsession);    if (crv == CKR_SESSION_COUNT) {	PK11_GETTAB(slot)->C_CloseSession(slot->session);	slot->session = CK_INVALID_SESSION;    	crv = PK11_GETTAB(slot)->C_OpenSession(slot->slotID,				CKF_RW_SESSION|CKF_SERIAL_SESSION,				  	  slot,pk11_notify,&rwsession);    }    if (crv != CKR_OK) {	PORT_SetError(PK11_MapError(crv));	if (slot->session == CK_INVALID_SESSION) {    	    PK11_GETTAB(slot)->C_OpenSession(slot->slotID,CKF_SERIAL_SESSION,				  	 slot,pk11_notify,&slot->session);	}	if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);	return CK_INVALID_SESSION;    }    return rwsession;}PRBoolPK11_RWSessionHasLock(PK11SlotInfo *slot,CK_SESSION_HANDLE session_handle) {    return (PRBool)(!slot->isThreadSafe || slot->defRWSession);}/* * close the rwsession and restore our readonly session * !!! has a side effect of releasing the Monitor if either the slot's default * session is RW or the slot is not thread safe. */voidPK11_RestoreROSession(PK11SlotInfo *slot,CK_SESSION_HANDLE rwsession){    if (slot->defRWSession) {	PK11_ExitSlotMonitor(slot);	return;    }    PK11_GETTAB(slot)->C_CloseSession(rwsession);    if (slot->session == CK_INVALID_SESSION) {    	 PK11_GETTAB(slot)->C_OpenSession(slot->slotID,CKF_SERIAL_SESSION,				  	 slot,pk11_notify,&slot->session);    }    if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);}/* * NOTE: this assumes that we are logged out of the card before hand */SECStatusPK11_CheckSSOPassword(PK11SlotInfo *slot, char *ssopw){    CK_SESSION_HANDLE rwsession;    CK_RV crv;    SECStatus rv = SECFailure;    int len = PORT_Strlen(ssopw);    /* get a rwsession */    rwsession = PK11_GetRWSession(slot);    if (rwsession == CK_INVALID_SESSION) return rv;    /* check the password */    crv = PK11_GETTAB(slot)->C_Login(rwsession,CKU_SO,						(unsigned char *)ssopw,len);    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);    /* release rwsession */    PK11_RestoreROSession(slot,rwsession);    return rv;}/* * make sure the password conforms to your token's requirements. */SECStatusPK11_VerifyPW(PK11SlotInfo *slot,char *pw){    int len = PORT_Strlen(pw);    if ((slot->minPassword > len) || (slot->maxPassword < len)) {	PORT_SetError(SEC_ERROR_BAD_DATA);	return SECFailure;    }    return SECSuccess;}/* * initialize a user PIN Value */SECStatusPK11_InitPin(PK11SlotInfo *slot,char *ssopw, 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) goto done;    /* check the password */    crv = PK11_GETTAB(slot)->C_Login(rwsession,CKU_SO, 					  (unsigned char *)ssopw,ssolen);    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);    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);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?