From a40cde2d049a89e77f7e756d1d7e9594cd70e1d1 Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sun, 5 Jan 2020 10:54:47 +0100 Subject: [PATCH 01/10] util: refactor listing card drivers Make util_list_card_drivers() a function in util.c to allow consistent listing of available card drivers from tools. --- src/tools/util.c | 20 ++++++++++++++++++++ src/tools/util.h | 1 + 2 files changed, 21 insertions(+) diff --git a/src/tools/util.c b/src/tools/util.c index 5faab385..ade86fb1 100644 --- a/src/tools/util.c +++ b/src/tools/util.c @@ -305,6 +305,26 @@ util_print_usage_and_die(const char *app_name, const struct option options[], exit(2); } +int util_list_card_drivers(const sc_context_t *ctx) +{ + int i; + + if (ctx == NULL) { + fprintf(stderr, "Unable to get card drivers!\n"); + return 1; + } + if (ctx->card_drivers[0] == NULL) { + fprintf(stderr, "No card drivers installed!\n"); + return 1; + } + printf("Available card drivers:\n"); + for (i = 0; ctx->card_drivers[i] != NULL; i++) { + printf(" %-16s %s\n", ctx->card_drivers[i]->short_name, + ctx->card_drivers[i]->name); + } + return 0; +} + const char * util_acl_to_str(const sc_acl_entry_t *e) { static char line[80], buf[20]; diff --git a/src/tools/util.h b/src/tools/util.h index 21c8293e..929928d8 100644 --- a/src/tools/util.h +++ b/src/tools/util.h @@ -41,6 +41,7 @@ void util_hex_dump(FILE *f, const u8 *in, int len, const char *sep); void util_hex_dump_asc(FILE *f, const u8 *in, size_t count, int addr); NORETURN void util_print_usage_and_die(const char *app_name, const struct option options[], const char *option_help[], const char *args); +int util_list_card_drivers(const sc_context_t *ctx); const char * util_acl_to_str(const struct sc_acl_entry *e); void util_warn(const char *fmt, ...); void util_error(const char *fmt, ...); From 5da40bf027b2e91063bd012580bde7dd5e375ddd Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Wed, 25 Dec 2019 19:12:31 +0100 Subject: [PATCH 02/10] opensc-explorer: make '--card-driver ?' list all available drivers Make opensc-explorer a bit more user friendly by treating the question mark given as argument to option '--card-driver' special: list all available drivers instead of stupidly bailing out. --- doc/tools/opensc-explorer.1.xml | 7 +++++-- src/tools/opensc-explorer.c | 8 +++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/doc/tools/opensc-explorer.1.xml b/doc/tools/opensc-explorer.1.xml index 7fdd93ce..30bc3057 100644 --- a/doc/tools/opensc-explorer.1.xml +++ b/doc/tools/opensc-explorer.1.xml @@ -55,8 +55,11 @@ driver - Use the given card driver. The default is - auto-detected. + Use the given card driver. + The default is to auto-detect the correct card driver. + The literal value ? lists + all available card drivers and terminates + opensc-explorer. diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index ecc6b179..fb116546 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -76,7 +76,7 @@ static const struct option options[] = { }; static const char *option_help[] = { "Uses reader number [0]", - "Forces the use of driver [auto-detect]", + "Forces the use of driver [auto-detect; '?' for list]", "Selects path on start-up, or none if empty [3F00]", "Wait for card insertion", "Verbose operation. Use several times to enable debug output.", @@ -2152,6 +2152,12 @@ int main(int argc, char *argv[]) } if (opt_driver != NULL) { + /* special card driver value "?" means: list available drivers */ + if (strncmp("?", opt_driver, sizeof("?")) == 0) { + err = util_list_card_drivers(ctx); + goto end; + } + err = sc_set_card_driver(ctx, opt_driver); if (err) { fprintf(stderr, "Driver '%s' not found!\n", opt_driver); From 94288b438e8b741aa944290774a32468f361a27a Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 4 Jan 2020 16:44:07 +0100 Subject: [PATCH 03/10] opensc-tool: make '--card-driver ?' list all available drivers Extend opensc-tool the same way opensc-explorer was extended. I.e. treat the question mark given as argument to option '--card-driver' special: list all available drivers instead of stupidly bailing out. --- doc/tools/opensc-tool.1.xml | 8 ++++++-- src/tools/opensc-tool.c | 27 +++++++++------------------ 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/doc/tools/opensc-tool.1.xml b/doc/tools/opensc-tool.1.xml index f362a376..ea2c235a 100644 --- a/doc/tools/opensc-tool.1.xml +++ b/doc/tools/opensc-tool.1.xml @@ -52,8 +52,12 @@ driver, driver - Use the given card driver. - The default is auto-detected. + + Use the given card driver. + The default is to auto-detect the correct card driver. + The literal value ? lists + all available card drivers. + diff --git a/src/tools/opensc-tool.c b/src/tools/opensc-tool.c index f829332f..22fbbc7b 100644 --- a/src/tools/opensc-tool.c +++ b/src/tools/opensc-tool.c @@ -90,7 +90,7 @@ static const char *option_help[] = { "Sends an APDU in format AA:BB:CC:DD:EE:FF...", "Uses reader number [0]", "Does card reset of type [cold]", - "Forces the use of driver [auto-detect]", + "Forces the use of driver [auto-detect; '?' for list]", "Lists algorithms supported by card", "Wait for a card to be inserted", "Verbose operation. Use several times to enable debug output.", @@ -300,22 +300,6 @@ static int list_readers(void) return 0; } -static int list_drivers(void) -{ - int i; - - if (ctx->card_drivers[0] == NULL) { - printf("No card drivers installed!\n"); - return 0; - } - printf("Configured card drivers:\n"); - for (i = 0; ctx->card_drivers[i] != NULL; i++) { - printf(" %-16s %s\n", ctx->card_drivers[i]->short_name, - ctx->card_drivers[i]->name); - } - return 0; -} - static int print_file(sc_card_t *in_card, const sc_file_t *file, const sc_path_t *path, int depth) { @@ -784,6 +768,13 @@ int main(int argc, char *argv[]) break; case 'c': opt_driver = optarg; + + /* treat argument "?" as request to list drivers */ + if (opt_driver && strncmp("?", opt_driver, sizeof("?")) == 0) { + opt_driver = NULL; + do_list_drivers = 1; + action_count++; + } break; case 'w': opt_wait = 1; @@ -844,7 +835,7 @@ int main(int argc, char *argv[]) action_count--; } if (do_list_drivers) { - if ((err = list_drivers())) + if ((err = util_list_card_drivers(ctx))) goto end; action_count--; } From 30fdc7de4ac2778dfe75fa05a3b6649961411d69 Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 4 Jan 2020 17:44:03 +0100 Subject: [PATCH 04/10] piv-tool: make '--card-driver ?' list all available drivers Extend piv-tool the same way opensc-explorer was extended. I.e. treat the question mark given as argument to option '--card-driver' special: list all available drivers instead of stupidly bailing out. In contrast to opensc-tool and opensc-explorer, which are card-agnostic, I am not sure whether the option '--card-driver' makes sense on this card-specific tool. --- doc/tools/piv-tool.1.xml | 9 +++++++-- src/tools/piv-tool.c | 16 +++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/doc/tools/piv-tool.1.xml b/doc/tools/piv-tool.1.xml index 27a052b2..e9b77629 100644 --- a/doc/tools/piv-tool.1.xml +++ b/doc/tools/piv-tool.1.xml @@ -168,8 +168,13 @@ driver, driver - Use the given card driver. - The default is auto-detected. + + Use the given card driver. + The default is to auto-detect the correct card driver. + The literal value ? lists + all available card drivers and terminates + piv-tool. + diff --git a/src/tools/piv-tool.c b/src/tools/piv-tool.c index 3c9a3b68..5be365dc 100644 --- a/src/tools/piv-tool.c +++ b/src/tools/piv-tool.c @@ -98,7 +98,7 @@ static const char *option_help[] = { "Input file for cert", "Sends an APDU in format AA:BB:CC:DD:EE:FF...", "Uses reader number [0]", - "Forces the use of driver [auto-detect]", + "Forces the use of driver [auto-detect; '?' for list]", "Wait for a card to be inserted", "Verbose operation. Use several times to enable debug output.", }; @@ -478,6 +478,7 @@ int main(int argc, char *argv[]) int compress_cert = 0; int do_print_serial = 0; int do_print_name = 0; + int do_list_card_drivers = 0; int action_count = 0; const char *opt_driver = NULL; const char *out_file = NULL; @@ -556,12 +557,20 @@ int main(int argc, char *argv[]) break; case 'c': opt_driver = optarg; + + /* special card driver value "?" means: list available drivers */ + if (opt_driver != NULL && strncmp("?", opt_driver, sizeof("?")) == 0) { + opt_driver = NULL; + do_list_card_drivers = 1; + action_count++; + } break; case 'w': opt_wait = 1; break; } } + if (action_count == 0) util_print_usage_and_die(app_name, options, option_help, NULL); @@ -603,6 +612,11 @@ int main(int argc, char *argv[]) if (action_count <= 0) goto end; + if (do_list_card_drivers) { + err = util_list_card_drivers(ctx); + goto end; + } + if (opt_driver != NULL) { err = sc_set_card_driver(ctx, opt_driver); if (err) { From a10368769c6457702e8e713c8da9d08d149c3936 Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 4 Jan 2020 17:48:04 +0100 Subject: [PATCH 05/10] cardos-tool: make '--card-driver ?' list all available drivers Extend cardos-tool the same way opensc-explorer was extended. I.e. treat the question mark given as argument to option '--card-driver' special: list all available drivers instead of stupidly bailing out. In contrast to opensc-tool and opensc-explorer, which are card-agnostic, I am not sure whether the option '--card-driver' makes sense on this card-specific tool. --- doc/tools/cardos-tool.1.xml | 12 +++++++++--- src/tools/cardos-tool.c | 15 ++++++++++++++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/doc/tools/cardos-tool.1.xml b/doc/tools/cardos-tool.1.xml index c41e78a0..d3ed342b 100644 --- a/doc/tools/cardos-tool.1.xml +++ b/doc/tools/cardos-tool.1.xml @@ -36,9 +36,15 @@ smart cards and similar security tokens based on Siemens Card/OS M4. name, - name - Use the card driver specified by name. - The default is to auto-detect the correct card driver. + name + + + Use the given card driver. + The default is to auto-detect the correct card driver. + The literal value ? lists + all available card drivers and terminates + cardos-tool. + diff --git a/src/tools/cardos-tool.c b/src/tools/cardos-tool.c index cb292c51..d748846d 100644 --- a/src/tools/cardos-tool.c +++ b/src/tools/cardos-tool.c @@ -67,7 +67,7 @@ static const char *option_help[] = { "Specify startkey for format", "Change Startkey with given APDU command", "Uses reader number [0]", - "Forces the use of driver [auto-detect]", + "Forces the use of driver [auto-detect; '?' for list]", "Wait for a card to be inserted", "Verbose operation. Use several times to enable debug output.", }; @@ -1038,6 +1038,7 @@ int main(int argc, char *argv[]) int do_info = 0; int do_format = 0; int do_change_startkey = 0; + int do_list_card_drivers = 0; int action_count = 0; const char *opt_driver = NULL; const char *opt_startkey = NULL; @@ -1077,6 +1078,13 @@ int main(int argc, char *argv[]) break; case 'c': opt_driver = optarg; + + /* special card driver value "?" means: list available drivers */ + if (opt_driver != NULL && strncmp("?", opt_driver, sizeof("?")) == 0) { + opt_driver = NULL; + do_list_card_drivers = 1; + action_count++; + } break; case 'w': opt_wait = 1; @@ -1095,6 +1103,11 @@ int main(int argc, char *argv[]) return 1; } + if (do_list_card_drivers) { + err = util_list_card_drivers(ctx); + goto end; + } + if (opt_driver != NULL) { err = sc_set_card_driver(ctx, opt_driver); if (err) { From 5514a0529f21a2fcd21f24ee9bd51ac7936789de Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sun, 5 Jan 2020 22:05:01 +0100 Subject: [PATCH 06/10] dnie-tool: rename option '--driver' to '--card-driver' Rename option '--driver' to '--card-driver' for increased consistency. In addition, extend it the same way opensc-explorer was extended. I.e. treat the question mark given as argument to option '--card-driver' special: list all available drivers instead of stupidly bailing out. In contrast to opensc-tool and opensc-explorer, which are card-agnostic, I am not sure whether the option '--card-driver' makes sense on this card-specific tool. --- doc/tools/dnie-tool.1.xml | 15 +++++++++++---- src/tools/dnie-tool.c | 10 ++++++++-- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/doc/tools/dnie-tool.1.xml b/doc/tools/dnie-tool.1.xml index 8c9cecc9..996b60e3 100644 --- a/doc/tools/dnie-tool.1.xml +++ b/doc/tools/dnie-tool.1.xml @@ -97,11 +97,18 @@ - driver, - driver + name, + name - Specify the card driver driver to use. - Default is use driver from configuration file, or auto-detect if absent + + + Use the given card driver. + The default is to auto-detect the correct card driver. + The literal value ? lists + all available card drivers and terminates + dnie-tool. + + diff --git a/src/tools/dnie-tool.c b/src/tools/dnie-tool.c index d788cd8c..7a20cc2f 100644 --- a/src/tools/dnie-tool.c +++ b/src/tools/dnie-tool.c @@ -54,7 +54,7 @@ static const char *app_name = "dnie-tool"; static const struct option options[] = { {"reader", 1, NULL, 'r'}, - {"driver", 1, NULL, 'c'}, + {"card-driver", 1, NULL, 'c'}, {"wait", 0, NULL, 'w'}, {"pin", 1, NULL, 'p'}, {"idesp", 0, NULL, 'i'}, @@ -68,7 +68,7 @@ static const struct option options[] = { static const char *option_help[] = { "Uses reader number [0]", - "Uses card driver [auto-detect]", + "Uses card driver [auto-detect; '?' for list]", "Wait for a card to be inserted", "Specify PIN", "Retrieve IDESP", @@ -150,6 +150,12 @@ int main(int argc, char* argv[]) } if (opt_driver != NULL) { + /* special card driver value "?" means: list available drivers */ + if (strncmp("?", opt_driver, sizeof("?")) == 0) { + err = util_list_card_drivers(ctx); + goto dnie_tool_end; + } + err = sc_set_card_driver(ctx, opt_driver); if (err) { fprintf(stderr, "Driver '%s' not found!\n", From 04f4f589a18c12ef775d10e3e1da758d17058f8d Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Mon, 6 Jan 2020 17:17:09 +0100 Subject: [PATCH 07/10] piv-tool: cleanup - remove command line option '--card-driver'; - instead force driver 'PIV-II' and fail if card is not a PIV card - overhaul option parsing - remove unused variable 'long_optind' - make work option '--reader' ( "r:" was missing in the optstring!!!) - bail out with usage message on all unknown/unhandled args - correctly terminate option parsing (no infinite loop) --- doc/tools/piv-tool.1.xml | 13 ----------- src/tools/piv-tool.c | 49 ++++++++++++++-------------------------- 2 files changed, 17 insertions(+), 45 deletions(-) diff --git a/doc/tools/piv-tool.1.xml b/doc/tools/piv-tool.1.xml index e9b77629..70619cce 100644 --- a/doc/tools/piv-tool.1.xml +++ b/doc/tools/piv-tool.1.xml @@ -163,19 +163,6 @@ - - - driver, - driver - - - Use the given card driver. - The default is to auto-detect the correct card driver. - The literal value ? lists - all available card drivers and terminates - piv-tool. - - , diff --git a/src/tools/piv-tool.c b/src/tools/piv-tool.c index 5be365dc..fbc2ab3f 100644 --- a/src/tools/piv-tool.c +++ b/src/tools/piv-tool.c @@ -52,6 +52,7 @@ #include "libopensc/opensc.h" #include "libopensc/cardctl.h" +#include "libopensc/cards.h" #include "libopensc/asn1.h" #include "util.h" #include "libopensc/sc-ossl-compat.h" @@ -80,7 +81,6 @@ static const struct option options[] = { { "in", 1, NULL, 'i' }, { "send-apdu", 1, NULL, 's' }, { "reader", 1, NULL, 'r' }, - { "card-driver", 1, NULL, 'c' }, { "wait", 0, NULL, 'w' }, { "verbose", 0, NULL, 'v' }, { NULL, 0, NULL, 0 } @@ -98,7 +98,6 @@ static const char *option_help[] = { "Input file for cert", "Sends an APDU in format AA:BB:CC:DD:EE:FF...", "Uses reader number [0]", - "Forces the use of driver [auto-detect; '?' for list]", "Wait for a card to be inserted", "Verbose operation. Use several times to enable debug output.", }; @@ -469,7 +468,7 @@ static void print_serial(sc_card_t *in_card) int main(int argc, char *argv[]) { - int err = 0, r, c, long_optind = 0; + int err = 0, r, c; int do_send_apdu = 0; int do_admin_mode = 0; int do_gen_key = 0; @@ -478,9 +477,7 @@ int main(int argc, char *argv[]) int compress_cert = 0; int do_print_serial = 0; int do_print_name = 0; - int do_list_card_drivers = 0; int action_count = 0; - const char *opt_driver = NULL; const char *out_file = NULL; const char *in_file = NULL; const char *cert_id = NULL; @@ -490,12 +487,7 @@ int main(int argc, char *argv[]) sc_context_param_t ctx_param; char **old_apdus = NULL; - while (1) { - c = getopt_long(argc, argv, "nA:G:O:Z:C:i:o:fvs:c:w", options, &long_optind); - if (c == -1) - break; - if (c == '?') - util_print_usage_and_die(app_name, options, option_help, NULL); + while ((c = getopt_long(argc, argv, "nA:G:O:Z:C:i:o:r:fvs:c:w", options, (int *) 0)) != -1) { switch (c) { case OPT_SERIAL: do_print_serial = 1; @@ -555,19 +547,11 @@ int main(int argc, char *argv[]) case 'v': verbose++; break; - case 'c': - opt_driver = optarg; - - /* special card driver value "?" means: list available drivers */ - if (opt_driver != NULL && strncmp("?", opt_driver, sizeof("?")) == 0) { - opt_driver = NULL; - do_list_card_drivers = 1; - action_count++; - } - break; case 'w': opt_wait = 1; break; + default: + util_print_usage_and_die(app_name, options, option_help, NULL); } } @@ -612,24 +596,25 @@ int main(int argc, char *argv[]) if (action_count <= 0) goto end; - if (do_list_card_drivers) { - err = util_list_card_drivers(ctx); + /* force PIV card driver */ + err = sc_set_card_driver(ctx, "PIV-II"); + if (err) { + fprintf(stderr, "PIV card driver not found!\n"); + err = 1; goto end; } - if (opt_driver != NULL) { - err = sc_set_card_driver(ctx, opt_driver); - if (err) { - fprintf(stderr, "Driver '%s' not found!\n", opt_driver); - err = 1; - goto end; - } - } - err = util_connect_card(ctx, &card, opt_reader, opt_wait, verbose); if (err) goto end; + /* fail if card is not a PIV card */ + if (card->type < SC_CARD_TYPE_PIV_II_BASE || card->type >= SC_CARD_TYPE_PIV_II_BASE+1000) { + fprintf(stderr, "Card type %X: not a PIV card\n", card->type); + err = 1; + goto end; + } + if (do_admin_mode) { if ((err = admin_mode(admin_info))) goto end; From 58ecb4aba2206b904ebb079b7d8c3ef5a424e49b Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Mon, 6 Jan 2020 18:03:19 +0100 Subject: [PATCH 08/10] cardos-tool: cleanup - remove command line option '--card-driver'; - instead force driver 'cardos' and fail if card is not a CardOS card - overhaul option parsing - remove unused variable 'long_optind' - bail out with usage message on all unknown/unhandled args - correctly terminate option parsing (no infinite loop) --- doc/tools/cardos-tool.1.xml | 13 ---------- src/tools/cardos-tool.c | 49 +++++++++++++------------------------ 2 files changed, 17 insertions(+), 45 deletions(-) diff --git a/doc/tools/cardos-tool.1.xml b/doc/tools/cardos-tool.1.xml index d3ed342b..4846fb3b 100644 --- a/doc/tools/cardos-tool.1.xml +++ b/doc/tools/cardos-tool.1.xml @@ -33,19 +33,6 @@ smart cards and similar security tokens based on Siemens Card/OS M4. Options - - - name, - name - - - Use the given card driver. - The default is to auto-detect the correct card driver. - The literal value ? lists - all available card drivers and terminates - cardos-tool. - - , diff --git a/src/tools/cardos-tool.c b/src/tools/cardos-tool.c index d748846d..fcf275d9 100644 --- a/src/tools/cardos-tool.c +++ b/src/tools/cardos-tool.c @@ -39,6 +39,7 @@ #endif #include "libopensc/opensc.h" +#include "libopensc/cards.h" #include "util.h" static const char *app_name = "cardos-tool"; @@ -54,7 +55,6 @@ static const struct option options[] = { {"startkey", 1, NULL, 's'}, {"change-startkey", 1, NULL, 'S'}, {"reader", 1, NULL, 'r'}, - {"card-driver", 1, NULL, 'c'}, {"wait", 0, NULL, 'w'}, {"verbose", 0, NULL, 'v'}, {NULL, 0, NULL, 0} @@ -67,7 +67,6 @@ static const char *option_help[] = { "Specify startkey for format", "Change Startkey with given APDU command", "Uses reader number [0]", - "Forces the use of driver [auto-detect; '?' for list]", "Wait for a card to be inserted", "Verbose operation. Use several times to enable debug output.", }; @@ -1034,22 +1033,16 @@ static int cardos_change_startkey(const char *change_startkey_apdu) { int main(int argc, char *argv[]) { - int err = 0, r, c, long_optind = 0; + int err = 0, r, c; int do_info = 0; int do_format = 0; int do_change_startkey = 0; - int do_list_card_drivers = 0; int action_count = 0; - const char *opt_driver = NULL; const char *opt_startkey = NULL; const char *opt_change_startkey = NULL; sc_context_param_t ctx_param; - while (1) { - c = getopt_long(argc, argv, "hifs:r:vdc:wS:", options, - &long_optind); - if (c == -1) - break; + while ((c = getopt_long(argc, argv, "hifs:r:vdwS:", options, (int *) 0)) != -1) { switch (c) { case 'h': printf("NB! This tool is only for Siemens CardOS based cards!\n\n"); @@ -1076,19 +1069,11 @@ int main(int argc, char *argv[]) case 'v': verbose++; break; - case 'c': - opt_driver = optarg; - - /* special card driver value "?" means: list available drivers */ - if (opt_driver != NULL && strncmp("?", opt_driver, sizeof("?")) == 0) { - opt_driver = NULL; - do_list_card_drivers = 1; - action_count++; - } - break; case 'w': opt_wait = 1; break; + default: + util_print_usage_and_die(app_name, options, option_help, NULL); } } @@ -1103,25 +1088,25 @@ int main(int argc, char *argv[]) return 1; } - if (do_list_card_drivers) { - err = util_list_card_drivers(ctx); + /* force CardOS card driver */ + err = sc_set_card_driver(ctx, "cardos"); + if (err) { + fprintf(stderr, "CardOS card driver not found!\n"); + err = 1; goto end; } - if (opt_driver != NULL) { - err = sc_set_card_driver(ctx, opt_driver); - if (err) { - fprintf(stderr, "Driver '%s' not found!\n", - opt_driver); - err = 1; - goto end; - } - } - err = util_connect_card(ctx, &card, opt_reader, opt_wait, verbose); if (err) goto end; + /* fail if card is not a CardOS card */ + if (card->type < SC_CARD_TYPE_CARDOS_BASE || card->type >= SC_CARD_TYPE_CARDOS_BASE+1000) { + fprintf(stderr, "Card type %X: not a CardOS card\n", card->type); + err = 1; + goto end; + } + if (do_info) { if ((err = cardos_info())) { goto end; From a0adbc9ef2ab006365f4a746929ff001b767da6f Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Mon, 6 Jan 2020 18:36:37 +0100 Subject: [PATCH 09/10] dnie-tool: cleanup - remove command line option '--card-driver'; - instead force driver 'dnie' and fail if card is not a DNIe card - overhaul option parsing - remove unused variable 'long_optind' - bail out with usage message on all unknown/unhandled args - correctly terminate option parsing (no infinite loop) - slight refactoring - avoid magic constant '0x0f' - make variable 'tries_left' more local - move dependent code into if block --- doc/tools/dnie-tool.1.xml | 15 ------ src/tools/dnie-tool.c | 111 +++++++++++++++++--------------------- 2 files changed, 49 insertions(+), 77 deletions(-) diff --git a/doc/tools/dnie-tool.1.xml b/doc/tools/dnie-tool.1.xml index 996b60e3..0daac27d 100644 --- a/doc/tools/dnie-tool.1.xml +++ b/doc/tools/dnie-tool.1.xml @@ -95,21 +95,6 @@ - - - name, - name - - - - Use the given card driver. - The default is to auto-detect the correct card driver. - The literal value ? lists - all available card drivers and terminates - dnie-tool. - - - , diff --git a/src/tools/dnie-tool.c b/src/tools/dnie-tool.c index 7a20cc2f..eea5fd14 100644 --- a/src/tools/dnie-tool.c +++ b/src/tools/dnie-tool.c @@ -36,6 +36,7 @@ #include "libopensc/opensc.h" #include "libopensc/errors.h" #include "libopensc/cardctl.h" +#include "libopensc/cards.h" #include "libopensc/pkcs15.h" #include "util.h" @@ -54,7 +55,6 @@ static const char *app_name = "dnie-tool"; static const struct option options[] = { {"reader", 1, NULL, 'r'}, - {"card-driver", 1, NULL, 'c'}, {"wait", 0, NULL, 'w'}, {"pin", 1, NULL, 'p'}, {"idesp", 0, NULL, 'i'}, @@ -68,7 +68,6 @@ static const struct option options[] = { static const char *option_help[] = { "Uses reader number [0]", - "Uses card driver [auto-detect; '?' for list]", "Wait for a card to be inserted", "Specify PIN", "Retrieve IDESP", @@ -86,7 +85,6 @@ int main(int argc, char* argv[]) int opt_wait = 0; const char *opt_pin = NULL; const char *opt_reader = NULL; - const char *opt_driver = NULL; int opt_operation = OP_NONE; int verbose = 0; @@ -94,25 +92,16 @@ int main(int argc, char* argv[]) sc_context_t *ctx = NULL; sc_context_param_t ctx_param; sc_card_t *card = NULL; - int c, long_optind, r, tries_left; + int c, r; char *data[] = { NULL, NULL, NULL, NULL, NULL }; sc_serial_number_t serial; - while (1) { - c = getopt_long(argc, argv, "r:c:wp:iVdsav", - options, &long_optind); - if (c == -1) - break; + while ((c = getopt_long(argc, argv, "r:wp:iVdsav", options, (int *) 0)) != -1) { switch (c) { - case '?': - util_print_usage_and_die(app_name, options, option_help, NULL); case 'r': opt_reader = optarg; break; - case 'c': - opt_driver = optarg; - break; case 'w': opt_wait = 1; break; @@ -137,6 +126,8 @@ int main(int argc, char* argv[]) case 'v': verbose++; break; + default: + util_print_usage_and_die(app_name, options, option_help, NULL); } } @@ -146,23 +137,16 @@ int main(int argc, char* argv[]) if (r) { fprintf(stderr, "Error: Failed to establish context: %s\n", sc_strerror(r)); + err = -1; goto dnie_tool_end; } - if (opt_driver != NULL) { - /* special card driver value "?" means: list available drivers */ - if (strncmp("?", opt_driver, sizeof("?")) == 0) { - err = util_list_card_drivers(ctx); - goto dnie_tool_end; - } - - err = sc_set_card_driver(ctx, opt_driver); - if (err) { - fprintf(stderr, "Driver '%s' not found!\n", - opt_driver); - err = -1; - goto dnie_tool_end; - } + /* force DNIe card driver */ + err = sc_set_card_driver(ctx, "dnie"); + if (err) { + fprintf(stderr, "DNIe card driver not found!\n"); + err = -1; + goto dnie_tool_end; } if (util_connect_card(ctx, &card, opt_reader, opt_wait, verbose) ) { @@ -171,13 +155,16 @@ int main(int argc, char* argv[]) goto dnie_tool_end; } - if ( strcmp(card->name,"dnie") ) { - fprintf(stderr, "Error: Card seems not to be a DNIe\n"); - err=-1; + /* fail if card is not a DNIe card */ + if (card->type < SC_CARD_TYPE_DNIE_BASE || card->type >= SC_CARD_TYPE_DNIE_BASE+1000) { + fprintf(stderr, "Card type %X: not a DNIe card\n", card->type); + err = -1; goto dnie_tool_end; } if ( opt_pin ) { + int tries_left; + /* verify */ r = sc_verify(card, SC_AC_CHV, 0, (u8*)opt_pin, strlen(opt_pin), &tries_left); @@ -192,44 +179,44 @@ int main(int argc, char* argv[]) } } - if (opt_operation==0) { - fprintf(stderr,"Error: No operation specified"); - err = -1; - goto dnie_tool_end; - } - if (opt_operation & 0x0f) { + if (opt_operation & (OP_GET_DATA | OP_GET_IDESP | OP_GET_VERSION | OP_GET_SERIALNR)) { r = sc_card_ctl(card, SC_CARDCTL_DNIE_GET_INFO, data); if ( r != SC_SUCCESS ) { fprintf(stderr, "Error: Get info failed: %s\n", sc_strerror(r)); err = -1; goto dnie_tool_end; } - } - if (opt_operation & OP_GET_DATA) { - printf("DNIe Number: %s\n",data[0]); - printf("SurName: %s\n",data[1]); - printf("Name: %s\n",data[2]); - } - if (opt_operation & OP_GET_IDESP) { - if (data[3]==NULL) - printf("IDESP: (Not available)\n"); - else printf("IDESP: %s\n",data[3]); - } - if (opt_operation & OP_GET_VERSION) { - if (data[4]==NULL) - printf("DNIe Version: (Not available)\n"); - else printf("DNIe Version: %s\n",data[4]); - } - if (opt_operation & OP_GET_SERIALNR) { - r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial); - if ( r != SC_SUCCESS ) { - fprintf(stderr,"Error: Get serial failed: %s\n",sc_strerror(r)); - err = -1; - goto dnie_tool_end; + + if (opt_operation & OP_GET_DATA) { + printf("DNIe Number: %s\n",data[0]); + printf("Surname: %s\n",data[1]); + printf("Name: %s\n",data[2]); } - printf("Serial number: "); - util_hex_dump(stdout, serial.value, serial.len, NULL); - putchar('\n'); + if (opt_operation & OP_GET_IDESP) { + if (data[3]==NULL) + printf("IDESP: (Not available)\n"); + else printf("IDESP: %s\n",data[3]); + } + if (opt_operation & OP_GET_VERSION) { + if (data[4]==NULL) + printf("DNIe Version: (Not available)\n"); + else printf("DNIe Version: %s\n",data[4]); + } + if (opt_operation & OP_GET_SERIALNR) { + r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial); + if ( r != SC_SUCCESS ) { + fprintf(stderr,"Error: Get serial failed: %s\n",sc_strerror(r)); + err = -1; + goto dnie_tool_end; + } + printf("Serial number: "); + util_hex_dump(stdout, serial.value, serial.len, NULL); + putchar('\n'); + } + } + else { + fprintf(stderr,"Error: No operation specified"); + err = -1; } dnie_tool_end: From 6b295e4207d9cb7972202d33e00da35e0bd7c685 Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sun, 12 Jan 2020 09:32:59 +0100 Subject: [PATCH 10/10] tools: correctly check return value of getopt_long() According to the specs, getopt_long() returns -1, which is often, but not necessarily the value of EOF. --- src/tools/eidenv.c | 2 +- src/tools/netkey-tool.c | 4 +++- src/tools/openpgp-tool.c | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tools/eidenv.c b/src/tools/eidenv.c index 9c0c48b6..ec344846 100644 --- a/src/tools/eidenv.c +++ b/src/tools/eidenv.c @@ -105,7 +105,7 @@ static void decode_options(int argc, char **argv) { int c; - while ((c = getopt_long(argc, argv,"pwtr:x:hV", options, (int *) 0)) != EOF) { + while ((c = getopt_long(argc, argv,"pwtr:x:hV", options, (int *) 0)) != -1) { switch (c) { case 'r': diff --git a/src/tools/netkey-tool.c b/src/tools/netkey-tool.c index 2456f677..5d35af08 100644 --- a/src/tools/netkey-tool.c +++ b/src/tools/netkey-tool.c @@ -446,7 +446,8 @@ int main( int r, oerr=0, reader=0, debug=0, pin_nr=-1, cert_nr=-1; size_t i, newlen=0; - while((r=getopt_long(argc,argv,"hvr:p:u:0:1:",options,NULL))!=EOF) switch(r){ + while ((r = getopt_long(argc, argv, "hvr:p:u:0:1:", options, NULL)) != -1) { + switch (r) { case 'h': ++do_help; break; case 'v': ++debug; break; case 'r': reader=atoi(optarg); break; @@ -455,6 +456,7 @@ int main( case '0': set_pin(pinlist[2].value, &pinlist[2].len, optarg); break; case '1': set_pin(pinlist[3].value, &pinlist[3].len, optarg); break; default: ++oerr; + } } if(do_help){ fprintf(stderr,"This is netkey-tool V1.0, May 15 2005, Copyright Peter Koch \n"); diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c index 1220346b..63db8b49 100644 --- a/src/tools/openpgp-tool.c +++ b/src/tools/openpgp-tool.c @@ -461,7 +461,7 @@ static int decode_options(int argc, char **argv) char *endptr; unsigned long val; - while ((c = getopt_long(argc, argv,"r:x:CUG:KEht:wvVd:", options, (int *) 0)) != EOF) { + while ((c = getopt_long(argc, argv,"r:x:CUG:KEht:wvVd:", options, (int *) 0)) != -1) { switch (c) { case 'r': opt_reader = optarg;