Index: cackey.c ================================================================== --- cackey.c +++ cackey.c @@ -815,10 +815,12 @@ DWORD protocol; unsigned int cached_certs_count; struct cackey_pcsc_identity *cached_certs; + + cackey_pcsc_id_type id_type_hint; }; typedef enum { CACKEY_TLV_APP_GENERIC = 0x01, CACKEY_TLV_APP_SKI = 0x02, @@ -936,23 +938,24 @@ } /* PC/SC Related Functions */ /* * SYNPOSIS - * void cackey_slots_disconnect_all(void); + * void cackey_slots_disconnect_all(int unitialize_all_readers); * * ARGUMENTS - * None + * int unitialize_all_readers Free the "pcsc_reader" object associated with + * each slot (boolean) * * RETURN VALUE * None * * NOTES * This function disconnects from all cards. * */ -static void cackey_slots_disconnect_all(void) { +static void cackey_slots_disconnect_all(int unitialize_all_readers) { uint32_t idx; CACKEY_DEBUG_PRINTF("Called."); for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) { @@ -970,20 +973,34 @@ if (cackey_slots[idx].label) { free(cackey_slots[idx].label); cackey_slots[idx].label = NULL; } + + if (unitialize_all_readers || !cackey_slots[idx].active) { + if (cackey_slots[idx].pcsc_reader) { + free(cackey_slots[idx].pcsc_reader); + + cackey_slots[idx].pcsc_reader = NULL; + } + + cackey_slots[idx].transaction_need_hw_lock = 0; + cackey_slots[idx].transaction_depth = 0; + cackey_slots[idx].id_type_hint = CACKEY_ID_TYPE_UNKNOWN; + } else { + if (cackey_slots[idx].transaction_depth > 0) { + cackey_slots[idx].transaction_need_hw_lock = 1; + } + } cackey_slots[idx].pcsc_card_connected = 0; - cackey_slots[idx].transaction_depth = 0; - cackey_slots[idx].transaction_need_hw_lock = 0; if (cackey_slots[idx].active) { CACKEY_DEBUG_PRINTF("Marking active slot %lu as being reset", (unsigned long) idx); + + cackey_slots[idx].slot_reset = 1; } - - cackey_slots[idx].slot_reset = 1; } CACKEY_DEBUG_PRINTF("Returning"); return; @@ -1016,11 +1033,11 @@ if (cackey_pcsc_handle == NULL) { cackey_pcsc_handle = malloc(sizeof(*cackey_pcsc_handle)); if (cackey_pcsc_handle == NULL) { CACKEY_DEBUG_PRINTF("Call to malloc() failed, returning in failure"); - cackey_slots_disconnect_all(); + cackey_slots_disconnect_all(0); return(CACKEY_PCSC_E_GENERIC); } CACKEY_DEBUG_PRINTF("SCardEstablishContext() called"); @@ -1029,11 +1046,11 @@ CACKEY_DEBUG_PRINTF("Call to SCardEstablishContext failed (returned %s/%li), returning in failure", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_est_context_ret), (long) scard_est_context_ret); free(cackey_pcsc_handle); cackey_pcsc_handle = NULL; - cackey_slots_disconnect_all(); + cackey_slots_disconnect_all(0); return(CACKEY_PCSC_E_GENERIC); } } @@ -1049,11 +1066,11 @@ CACKEY_DEBUG_PRINTF("Call to SCardEstablishContext failed (returned %s/%li), returning in failure", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_est_context_ret), (long) scard_est_context_ret); free(cackey_pcsc_handle); cackey_pcsc_handle = NULL; - cackey_slots_disconnect_all(); + cackey_slots_disconnect_all(0); return(CACKEY_PCSC_E_GENERIC); } CACKEY_DEBUG_PRINTF("Handle has been re-established"); @@ -1099,10 +1116,12 @@ } if (scard_rel_context_ret != SCARD_S_SUCCESS) { return(CACKEY_PCSC_E_GENERIC); } + + cackey_slots_disconnect_all(0); return(CACKEY_PCSC_S_OK); } /* @@ -1492,10 +1511,14 @@ if (!slot) { CACKEY_DEBUG_PRINTF("Invalid slot specified."); return(CACKEY_PCSC_E_GENERIC); } + + if (respcode) { + *respcode = 0xffff; + } pcsc_connect_ret = cackey_connect_card(slot); if (pcsc_connect_ret != CACKEY_PCSC_S_OK) { CACKEY_DEBUG_PRINTF("Unable to connect to card, returning in failure"); @@ -2140,14 +2163,14 @@ int idx; CACKEY_DEBUG_PRINTF("Reselecting the root applet"); if (type_hint == CACKEY_ID_TYPE_UNKNOWN) { - if (slot->cached_certs && slot->cached_certs_count > 0) { - type_hint = slot->cached_certs[0].id_type; - } + type_hint = slot->id_type_hint; } + + slot->id_type_hint = CACKEY_ID_TYPE_UNKNOWN; switch (type_hint) { case CACKEY_ID_TYPE_PIV: CACKEY_DEBUG_PRINTF("Trying to reselect the PIV root applet first"); @@ -2186,10 +2209,12 @@ CACKEY_DEBUG_PRINTF("Successfully selected the %s applet -- setting the \"LOGIN REQUIRED\" flag on the token", try_type == CACKEY_ID_TYPE_CAC ? "CAC" : "PIV" ); slot->token_flags = CKF_LOGIN_REQUIRED; + + slot->id_type_hint = try_type; return(try_type); } } @@ -3160,11 +3185,14 @@ } CACKEY_DEBUG_PRINTF("Something went wrong during signing, resetting the slot and hoping for the best."); cackey_pcsc_disconnect(); + cackey_pcsc_connect(); + + cackey_detect_and_select_root_applet(slot, CACKEY_ID_TYPE_UNKNOWN); return(CACKEY_PCSC_E_GENERIC); } tmpbuf += bytes_to_send; @@ -4585,10 +4613,11 @@ cackey_slots[idx].transaction_need_hw_lock = 0; cackey_slots[idx].slot_reset = 0; cackey_slots[idx].token_flags = 0; cackey_slots[idx].label = NULL; cackey_slots[idx].internal = 0; + cackey_slots[idx].id_type_hint = CACKEY_ID_TYPE_UNKNOWN; } #ifdef CACKEY_NO_EXTRA_CERTS if (getenv("CACKEY_EXTRA_CERTS") != NULL) { include_dod_certs = 1; @@ -4704,21 +4733,17 @@ if (cackey_sessions[idx].active) { C_CloseSession(idx); } } - cackey_slots_disconnect_all(); + cackey_slots_disconnect_all(1); for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) { if (cackey_slots[idx].internal) { continue; } - if (cackey_slots[idx].pcsc_reader) { - free(cackey_slots[idx].pcsc_reader); - } - if (cackey_slots[idx].cached_certs) { cackey_free_certs(cackey_slots[idx].cached_certs, cackey_slots[idx].cached_certs_count, 1); cackey_slots[idx].cached_certs = NULL; } @@ -4853,29 +4878,17 @@ if (slot_reset) { CACKEY_DEBUG_PRINTF("Purging all slot information."); /* Only update the list of slots if we are actually being supply the slot information */ - cackey_slots_disconnect_all(); + cackey_slots_disconnect_all(1); for (currslot = 0; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) { if (cackey_slots[currslot].internal) { continue; } - if (cackey_slots[currslot].pcsc_reader) { - free(cackey_slots[currslot].pcsc_reader); - - cackey_slots[currslot].pcsc_reader = NULL; - } - - if (cackey_slots[currslot].label) { - free(cackey_slots[currslot].label); - - cackey_slots[currslot].label = NULL; - } - cackey_slots[currslot].active = 0; } } }