Index: cackey.c ================================================================== --- cackey.c +++ cackey.c @@ -1116,11 +1116,15 @@ SCardDisconnect(slot->pcsc_card, SCARD_LEAVE_CARD); } slot->slot_reset = 1; slot->pcsc_card_connected = 0; - slot->token_flags = CKF_LOGIN_REQUIRED; + if (cackey_pin_command == NULL) { + slot->token_flags = CKF_LOGIN_REQUIRED; + } else { + slot->token_flags = 0; + } CACKEY_DEBUG_PRINTF("Returning."); return; } @@ -2872,11 +2876,10 @@ if (respcode == 0x6982) { CACKEY_DEBUG_PRINTF("Security status not satisified. Returning NEEDLOGIN"); cackey_mark_slot_reset(slot); - slot->token_flags = CKF_LOGIN_REQUIRED; return(CACKEY_PCSC_E_NEEDLOGIN); } if (send_ret == CACKEY_PCSC_E_TOKENABSENT) { @@ -3971,11 +3974,11 @@ static struct cackey_identity *cackey_read_identities(struct cackey_slot *slot, unsigned long *ids_found) { struct cackey_pcsc_identity *pcsc_identities; struct cackey_identity *identities; unsigned long num_ids, id_idx, curr_id_type; unsigned long num_certs, num_dod_certs, cert_idx; - int include_extra_certs = 0; + int include_extra_certs = 0, include_dod_certs; CACKEY_DEBUG_PRINTF("Called."); if (ids_found == NULL) { CACKEY_DEBUG_PRINTF("Error. ids_found is NULL"); @@ -3993,14 +3996,28 @@ if (getenv("CACKEY_NO_DOD_CERTS_ON_HW_SLOTS") != NULL) { include_extra_certs = 0; } +#ifdef CACKEY_NO_EXTRA_CERTS + if (getenv("CACKEY_EXTRA_CERTS") != NULL) { + include_dod_certs = 1; + } else { + include_dod_certs = 0; + } +#else if (getenv("CACKEY_NO_EXTRA_CERTS") != NULL) { - num_dod_certs = 0; + include_dod_certs = 0; } else { + include_dod_certs = 1; + } +#endif + + if (include_dod_certs) { num_dod_certs = sizeof(extra_certs) / sizeof(extra_certs[0]); + } else { + num_dod_certs = 0; } if (slot->internal) { num_ids = cackey_read_dod_identities(NULL, num_dod_certs); @@ -4406,11 +4423,15 @@ cackey_slots[currslot].internal = 0; cackey_slots[currslot].pcsc_reader = strdup(pcsc_readers); cackey_slots[currslot].pcsc_card_connected = 0; cackey_slots[currslot].transaction_depth = 0; cackey_slots[currslot].transaction_need_hw_lock = 0; - cackey_slots[currslot].token_flags = CKF_LOGIN_REQUIRED; + if (cackey_pin_command == NULL) { + cackey_slots[currslot].token_flags = CKF_LOGIN_REQUIRED; + } else { + cackey_slots[currslot].token_flags = 0; + } cackey_slots[currslot].label = NULL; cackey_mark_slot_reset(&cackey_slots[currslot]); } } else { @@ -5361,11 +5382,16 @@ return(CKR_GENERAL_ERROR); } cackey_sessions[hSession].state = CKS_RO_PUBLIC_SESSION; - cackey_slots[slotID].token_flags = CKF_LOGIN_REQUIRED; + + if (cackey_pin_command == NULL) { + cackey_slots[slotID].token_flags = CKF_LOGIN_REQUIRED; + } else { + cackey_slots[slotID].token_flags = 0; + } mutex_retval = cackey_mutex_unlock(cackey_biglock); if (mutex_retval != 0) { CACKEY_DEBUG_PRINTF("Error. Unlocking failed."); @@ -6285,10 +6311,16 @@ switch (cackey_sessions[hSession].decrypt_mechanism) { case CKM_RSA_PKCS: /* Ask card to decrypt */ buflen = cackey_signdecrypt(&cackey_slots[slotID], cackey_sessions[hSession].decrypt_identity, pEncryptedPart, ulEncryptedPartLen, buf, sizeof(buf), 0, 1); + + if (buflen == CACKEY_PCSC_E_NEEDLOGIN && cackey_pin_command != NULL) { + if (C_Login(hSession, CKU_USER, NULL, 0) == CKR_OK) { + buflen = cackey_signdecrypt(&cackey_slots[slotID], cackey_sessions[hSession].decrypt_identity, pEncryptedPart, ulEncryptedPartLen, buf, sizeof(buf), 0, 1); + } + } if (buflen < 0) { /* Decryption failed. */ if (buflen == CACKEY_PCSC_E_NEEDLOGIN) { retval = CKR_USER_NOT_LOGGED_IN; @@ -6796,10 +6828,16 @@ switch (cackey_sessions[hSession].sign_mechanism) { case CKM_RSA_PKCS: /* Ask card to sign */ CACKEY_DEBUG_PRINTF("Asking to sign from identity %p in session %lu", (void *) cackey_sessions[hSession].sign_identity, (unsigned long) hSession); sigbuflen = cackey_signdecrypt(&cackey_slots[slotID], cackey_sessions[hSession].sign_identity, cackey_sessions[hSession].sign_buf, cackey_sessions[hSession].sign_bufused, sigbuf, sizeof(sigbuf), 1, 0); + + if (sigbuflen == CACKEY_PCSC_E_NEEDLOGIN && cackey_pin_command != NULL) { + if (C_Login(hSession, CKU_USER, NULL, 0) == CKR_OK) { + sigbuflen = cackey_signdecrypt(&cackey_slots[slotID], cackey_sessions[hSession].sign_identity, cackey_sessions[hSession].sign_buf, cackey_sessions[hSession].sign_bufused, sigbuf, sizeof(sigbuf), 1, 0); + } + } if (sigbuflen < 0) { /* Signing failed. */ if (sigbuflen == CACKEY_PCSC_E_NEEDLOGIN) { retval = CKR_USER_NOT_LOGGED_IN; Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -151,10 +151,21 @@ ]) if ! test "${dodcertsonhwslots}" = 'no'; then AC_DEFINE(CACKEY_CARD_SLOT_INCLUDE_EXTRA_CERTS, [1], [Specify that DoD certificates should be made available on hardware token slots]) fi + +dnl Option to disable DoD certs entirely +AC_ARG_ENABLE(dod-certs, AC_HELP_STRING([--disable-dod-certs], [Disable including DoD certs entirely. The user may override this with the CACKEY_EXTRA_CERTS environment variable.]), [ + dodcerts=$enableval +], [ + dodcerts=yes +]) + +if test "${dodcerts}" = 'no'; then + AC_DEFINE(CACKEY_NO_EXTRA_CERTS, [1], [Specify that DoD certificates should not be made available]) +fi dnl Option to hard-code a command to run to request a PIN (enabling protected authentication path) AC_ARG_WITH(pin-command, AC_HELP_STRING([--with-pin-command=], [Specify a command to run to request a PIN from the user. The user may override this with the CACKEY_PIN_COMMAND environment variable.]), [ pincommand="${withval}" ], [