Index: cackey.c ================================================================== --- cackey.c +++ cackey.c @@ -166,21 +166,29 @@ /* Maximum size of data portion of APDUs */ /** Do not set this above 250 **/ #define CACKEY_APDU_MTU 250 #ifdef CACKEY_DEBUG +# ifdef HAVE_TIME_H +# include +static time_t cackey_debug_start_time = 0; +# define CACKEY_DEBUG_PRINTTIME { if (cackey_debug_start_time == 0) { cackey_debug_start_time = time(NULL); }; fprintf(stderr, "[%lu]: ", (unsigned long) (time(NULL) - cackey_debug_start_time)); } +# else +# define CACKEY_DEBUG_PRINTTIME /**/ +# endif -# define CACKEY_DEBUG_PRINTF(x...) { fprintf(stderr, "%s():%i: ", __func__, __LINE__); fprintf(stderr, x); fprintf(stderr, "\n"); fflush(stderr); } -# define CACKEY_DEBUG_PRINTBUF(f, x, y) { unsigned char *TMPBUF; unsigned long idx; TMPBUF = (unsigned char *) (x); fprintf(stderr, "%s():%i: %s (%s/%lu = {%02x", __func__, __LINE__, f, #x, (unsigned long) (y), TMPBUF[0]); for (idx = 1; idx < (y); idx++) { fprintf(stderr, ", %02x", TMPBUF[idx]); }; fprintf(stderr, "})\n"); fflush(stderr); } -# define CACKEY_DEBUG_PERROR(x) { fprintf(stderr, "%s():%i: ", __func__, __LINE__); perror(x); fflush(stderr); } +# define CACKEY_DEBUG_PRINTF(x...) { CACKEY_DEBUG_PRINTTIME; fprintf(stderr, "%s():%i: ", __func__, __LINE__); fprintf(stderr, x); fprintf(stderr, "\n"); fflush(stderr); } +# define CACKEY_DEBUG_PRINTBUF(f, x, y) { unsigned char *TMPBUF; unsigned long idx; TMPBUF = (unsigned char *) (x); CACKEY_DEBUG_PRINTTIME; fprintf(stderr, "%s():%i: %s (%s/%lu = {%02x", __func__, __LINE__, f, #x, (unsigned long) (y), TMPBUF[0]); for (idx = 1; idx < (y); idx++) { fprintf(stderr, ", %02x", TMPBUF[idx]); }; fprintf(stderr, "})\n"); fflush(stderr); } +# define CACKEY_DEBUG_PERROR(x) { fprintf(stderr, "%s():%i: ", __func__, __LINE__); CACKEY_DEBUG_PRINTTIME; perror(x); fflush(stderr); } # define free(x) { CACKEY_DEBUG_PRINTF("FREE(%p) (%s)", x, #x); free(x); } static void *CACKEY_DEBUG_FUNC_MALLOC(size_t size, const char *func, int line) { void *retval; retval = malloc(size); + CACKEY_DEBUG_PRINTTIME; fprintf(stderr, "%s():%i: ", func, line); fprintf(stderr, "MALLOC() = %p", retval); fprintf(stderr, "\n"); fflush(stderr); @@ -191,10 +199,11 @@ void *retval; retval = realloc(ptr, size); if (retval != ptr) { + CACKEY_DEBUG_PRINTTIME; fprintf(stderr, "%s():%i: ", func, line); fprintf(stderr, "REALLOC(%p) = %p", ptr, retval); fprintf(stderr, "\n"); fflush(stderr); } @@ -209,10 +218,11 @@ static char *CACKEY_DEBUG_FUNC_STRDUP(const char *ptr, const char *func, int line) { char *retval; retval = strdup(ptr); + CACKEY_DEBUG_PRINTTIME; fprintf(stderr, "%s():%i: ", func, line); fprintf(stderr, "STRDUP_MALLOC() = %p", retval); fprintf(stderr, "\n"); fflush(stderr); @@ -892,12 +902,10 @@ return(CACKEY_PCSC_E_GENERIC); } /* Connect to reader, if needed */ if (!slot->pcsc_card_connected) { - slot->protocol = 0; - CACKEY_DEBUG_PRINTF("SCardConnect(%s) called", slot->pcsc_reader); scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &slot->pcsc_card, &protocol); if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) { CACKEY_DEBUG_PRINTF("SCardConnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=0") @@ -1195,11 +1203,11 @@ recv_len = sizeof(recv_buf); scard_xmit_ret = SCardTransmit(slot->pcsc_card, pioSendPci, xmit_buf, xmit_len, NULL, recv_buf, &recv_len); if (scard_xmit_ret == SCARD_E_NOT_TRANSACTED) { - CACKEY_DEBUG_PRINTF("Failed to send APDU to card (SCardTransmit() = %s/%lx), will ask calling function to retry...", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_xmit_ret), (unsigned long) scard_xmit_ret); + CACKEY_DEBUG_PRINTF("Failed to send APDU to card (SCardTransmit() = %s/%lx), will ask calling function to retry (not resetting card)...", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_xmit_ret), (unsigned long) scard_xmit_ret); /* Begin Smartcard Transaction */ cackey_end_transaction(slot); return(CACKEY_PCSC_E_RETRY); @@ -2388,10 +2396,28 @@ return(CACKEY_PCSC_E_TOKENABSENT); } atr_len = sizeof(atr); status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len); + + if (status_ret == SCARD_E_INVALID_HANDLE) { + CACKEY_DEBUG_PRINTF("SCardStatus() returned SCARD_E_INVALID_HANDLE, marking is not already connected and trying again"); + slot->pcsc_card_connected = 0; + slot->slot_reset = 1; + slot->token_flags = CKF_LOGIN_REQUIRED; + + pcsc_connect_ret = cackey_connect_card(slot); + if (pcsc_connect_ret != CACKEY_PCSC_S_OK) { + CACKEY_DEBUG_PRINTF("Unable to connect to card, returning token absent"); + + return(CACKEY_PCSC_E_TOKENABSENT); + } + + atr_len = sizeof(atr); + status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len); + } + if (status_ret != SCARD_S_SUCCESS) { slot->slot_reset = 1; slot->token_flags = CKF_LOGIN_REQUIRED; if (status_ret == SCARD_W_RESET_CARD) { @@ -4510,10 +4536,11 @@ free(cackey_slots[slotID].label); cackey_slots[slotID].label = NULL; } cackey_slots[slotID].slot_reset = 0; + cackey_slots[slotID].pcsc_card_connected = 0; cackey_slots[slotID].token_flags = CKF_LOGIN_REQUIRED; } if (cackey_sessions[hSession].identities == NULL) { cackey_sessions[hSession].identities = cackey_read_identities(&cackey_slots[slotID], &cackey_sessions[hSession].identities_count); Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -24,11 +24,11 @@ dnl Determine how to strip executables AC_CHECK_TOOL(STRIP, strip) dnl Check for all required headers -AC_CHECK_HEADERS(arpa/inet.h inttypes.h stdarg.h stdint.h stdio.h stdlib.h string.h sys/socket.h sys/types.h sys/un.h unistd.h pthread.h zlib.h limits.h,,[ +AC_CHECK_HEADERS(arpa/inet.h inttypes.h stdarg.h stdint.h stdio.h stdlib.h string.h sys/socket.h sys/types.h sys/un.h time.h unistd.h pthread.h zlib.h limits.h,,[ AC_WARN([Required header missing, compilation will likely fail.]) ], [ #ifdef HAVE_ARPA_INET_H # include #endif @@ -60,10 +60,13 @@ # include #endif #ifdef HAVE_UNISTD_H # include #endif +#ifdef HAVE_TIME_H +# include +#endif #ifdef HAVE_PTHREAD_H # include #endif #ifdef HAVE_LIMITS_H # include