diff --git a/src/tools/util.c b/src/tools/util.c index 0a548755..0ad1fd9d 100644 --- a/src/tools/util.c +++ b/src/tools/util.c @@ -31,12 +31,28 @@ #include #include "util.h" -int util_connect_card(sc_context_t *ctx, sc_card_t **cardp, +int +is_string_valid_atr(const char *atr_str) +{ + unsigned char atr[SC_MAX_ATR_SIZE]; + size_t atr_len = sizeof(atr); + + if (sc_hex_to_bin(atr_str, atr, &atr_len)) + return 0; + if (atr_len < 2) + return 0; + if (atr[0] != 0x3B && atr[0] != 0x3F) + return 0; + return 1; +} + +int +util_connect_card(sc_context_t *ctx, sc_card_t **cardp, const char *reader_id, int do_wait, int verbose) { - sc_reader_t *reader, *found; - sc_card_t *card; - int r, tmp_reader_num; + struct sc_reader *reader = NULL, *found = NULL; + struct sc_card *card = NULL; + int r; if (do_wait) { unsigned int event; @@ -61,11 +77,12 @@ int util_connect_card(sc_context_t *ctx, sc_card_t **cardp, return 3; } reader = found; - } else { - if (sc_ctx_get_reader_count(ctx) == 0) { - fprintf(stderr, "No smart card readers found.\n"); - return 1; - } + } + else if (sc_ctx_get_reader_count(ctx) == 0) { + fprintf(stderr, "No smart card readers found.\n"); + return 1; + } + else { if (!reader_id) { unsigned int i; /* Automatically try to skip to a reader with a card if reader not specified */ @@ -78,35 +95,47 @@ int util_connect_card(sc_context_t *ctx, sc_card_t **cardp, } /* If no reader had a card, default to the first reader */ reader = sc_ctx_get_reader(ctx, 0); - } else { - /* If the reader identifiers looks like an ATR, try to find the reader with that card */ - unsigned char atr_buf[SC_MAX_ATR_SIZE * 3]; - size_t atr_buf_len = sizeof(atr_buf); - unsigned int i; + } + else { + /* If the reader identifier looks like an ATR, try to find the reader with that card */ + if (is_string_valid_atr(reader_id)) { + unsigned char atr_buf[SC_MAX_ATR_SIZE * 3]; + size_t atr_buf_len = sizeof(atr_buf); + unsigned int i; - if (sc_hex_to_bin(reader_id, atr_buf, &atr_buf_len) == SC_SUCCESS) { + sc_hex_to_bin(reader_id, atr_buf, &atr_buf_len); /* Loop readers, looking for a card with ATR */ for (i = 0; i < sc_ctx_get_reader_count(ctx); i++) { - reader = sc_ctx_get_reader(ctx, i); - if ((sc_detect_card_presence(reader) & SC_READER_CARD_PRESENT) && (reader->atr.len > 0)) { - if (!memcmp(reader->atr.value, atr_buf, reader->atr.len)) { - fprintf(stderr, "Matched ATR in reader: %s\n", reader->name); - goto autofound; - } - } + struct sc_reader *rdr = sc_ctx_get_reader(ctx, i); + + if (!(sc_detect_card_presence(rdr) & SC_READER_CARD_PRESENT)) + continue; + else if (rdr->atr.len != atr_buf_len) + continue; + else if (memcmp(rdr->atr.value, atr_buf, rdr->atr.len)) + continue; + + fprintf(stderr, "Matched ATR in reader: %s\n", rdr->name); + reader = rdr; + goto autofound; } } - if (!sscanf(reader_id, "%d", &tmp_reader_num)) { - /* Try to get the reader by name if it does not parse as a number */ - reader = sc_ctx_get_reader_by_name(ctx, reader_id); - } else { - reader = sc_ctx_get_reader(ctx, tmp_reader_num); + else { + char *endptr = NULL; + unsigned int num; + + errno = 0; + num = strtol(reader_id, &endptr, 0); + if (!errno && endptr && *endptr == '\0') + reader = sc_ctx_get_reader(ctx, num); + else + reader = sc_ctx_get_reader_by_name(ctx, reader_id); } } autofound: if (!reader) { - fprintf(stderr, - "Reader \"%s\" not found (%d reader(s) detected)\n", reader_id, sc_ctx_get_reader_count(ctx)); + fprintf(stderr, "Reader \"%s\" not found (%d reader(s) detected)\n", + reader_id, sc_ctx_get_reader_count(ctx)); return 1; } @@ -118,20 +147,18 @@ autofound: if (verbose) printf("Connecting to card in reader %s...\n", reader->name); - if ((r = sc_connect_card(reader, &card)) < 0) { - fprintf(stderr, - "Failed to connect to card: %s\n", - sc_strerror(r)); + r = sc_connect_card(reader, &card); + if (r < 0) { + fprintf(stderr, "Failed to connect to card: %s\n", sc_strerror(r)); return 1; } if (verbose) printf("Using card driver %s.\n", card->driver->name); - if ((r = sc_lock(card)) < 0) { - fprintf(stderr, - "Failed to lock card: %s\n", - sc_strerror(r)); + r = sc_lock(card); + if (r < 0) { + fprintf(stderr, "Failed to lock card: %s\n", sc_strerror(r)); sc_disconnect_card(card); return 1; }