@@ -3705,10 +3705,11 @@ return(CKR_FUNCTION_NOT_SUPPORTED); } CK_DEFINE_FUNCTION(CK_RV, C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) { int mutex_retval; + int tries_remaining; int login_ret; CACKEY_DEBUG_PRINTF("Called."); if (!cackey_initialized) { @@ -3742,11 +3743,11 @@ CACKEY_DEBUG_PRINTF("Error. Session not active."); return(CKR_SESSION_HANDLE_INVALID); } - login_ret = cackey_login(&cackey_slots[cackey_sessions[hSession].slotID], pPin, ulPinLen, NULL); + login_ret = cackey_login(&cackey_slots[cackey_sessions[hSession].slotID], pPin, ulPinLen, &tries_remaining); if (login_ret != CACKEY_PCSC_S_OK) { cackey_mutex_unlock(cackey_biglock); if (login_ret == CACKEY_PCSC_E_LOCKED) { CACKEY_DEBUG_PRINTF("Error. Token is locked."); @@ -3756,20 +3757,24 @@ return(CKR_PIN_LOCKED); } else if (login_ret == CACKEY_PCSC_E_BADPIN) { CACKEY_DEBUG_PRINTF("Error. Invalid PIN."); cackey_slots[cackey_sessions[hSession].slotID].token_flags |= CKF_USER_PIN_COUNT_LOW; + + if (tries_remaining == 1) { + cackey_slots[cackey_sessions[hSession].slotID].token_flags |= CKF_USER_PIN_FINAL_TRY; + } return(CKR_PIN_INCORRECT); } CACKEY_DEBUG_PRINTF("Error. Unknown error returned from cackey_login() (%i)", login_ret); return(CKR_GENERAL_ERROR); } - cackey_slots[cackey_sessions[hSession].slotID].token_flags &= ~(CKF_USER_PIN_LOCKED | CKF_USER_PIN_COUNT_LOW | CKF_LOGIN_REQUIRED); + cackey_slots[cackey_sessions[hSession].slotID].token_flags &= ~(CKF_USER_PIN_LOCKED | CKF_USER_PIN_COUNT_LOW | CKF_LOGIN_REQUIRED | CKF_USER_PIN_FINAL_TRY); cackey_sessions[hSession].state = CKS_RO_USER_FUNCTIONS; mutex_retval = cackey_mutex_unlock(cackey_biglock); if (mutex_retval != 0) {