From 80c069b5e1ad6fbd547de59f332eb3fabb68c572 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 28 Mar 2019 14:46:05 +0100 Subject: [PATCH] card: For passwd add a PIV menu and make the OpenPGP menu optional. * tools/gpg-card.c (get_selection): New. (cmd_passwd): Reworked. Signed-off-by: Werner Koch --- tools/gpg-card.c | 183 ++++++++++++++++++++++++++--------------------- 1 file changed, 102 insertions(+), 81 deletions(-) diff --git a/tools/gpg-card.c b/tools/gpg-card.c index a3113c9c5..7b3f8a3f6 100644 --- a/tools/gpg-card.c +++ b/tools/gpg-card.c @@ -429,6 +429,24 @@ put_data_to_file (const char *fname, const void *buffer, size_t length) } +/* Return a malloced string with the number opf the menu PROMPT. + * Control-D is mapped to "Q". */ +static char * +get_selection (const char *prompt) +{ + char *answer; + + tty_printf ("\n"); + tty_printf ("%s", prompt); + tty_printf ("\n"); + answer = tty_get (_("Your selection? ")); + tty_kill_prompt (); + if (*answer == CONTROL_D) + strcpy (answer, "q"); + return answer; +} + + /* Simply prints TEXT to the output. Returns 0 as a convenience. * This is a separate fucntion so that it can be extended to run @@ -2097,21 +2115,23 @@ cmd_generate (card_info_t info, char *argstr) -/* Sub-menu to change a PIN. */ +/* Change a PIN. */ static gpg_error_t cmd_passwd (card_info_t info, char *argstr) { - gpg_error_t err; + gpg_error_t err = 0; char *answer = NULL; - const char *pinref; + const char *pinref = NULL; + int reset_mode = 0; + int menu_used = 0; if (!info) return print_help ("PASSWD [PINREF]\n\n" - "Menu to change or unblock the PINs. Note that the\n" - "presented menu options depend on the type of card\n" - "and whether the admin mode is enabled. For OpenPGP\n" - "and PIV cards defaults for PINREF are available.", + "Change or unblock the PINs. Note that in interactive mode\n" + "and without a PINREF a menu is presented for certain cards;\n" + "in non-interactive and without a PINREF a default value is\n" + "used for these cards.", 0); if (opt.interactive || opt.verbose) @@ -2119,92 +2139,93 @@ cmd_passwd (card_info_t info, char *argstr) app_type_string (info->apptype), info->dispserialno? info->dispserialno : info->serialno); - if (!*argstr && info->apptype == APP_TYPE_OPENPGP) + if (*argstr) + pinref = argstr; + else if (opt.interactive && info->apptype == APP_TYPE_OPENPGP) { - /* For an OpenPGP card we present the well known menu if no - * argument is given. */ - for (;;) + menu_used = 1; + while (!pinref) { - tty_printf ("\n"); - tty_printf ("1 - change PIN\n" - "2 - unblock and set new PIN\n" - "3 - change Admin PIN\n" - "4 - set the Reset Code\n" - "Q - quit\n"); - tty_printf ("\n"); - - err = 0; xfree (answer); - answer = tty_get (_("Your selection? ")); - tty_kill_prompt (); - if (*answer == CONTROL_D) - break; /* Quit. */ + answer = get_selection ("1 - change the PIN\n" + "2 - unblock and set new a PIN\n" + "3 - change the Admin PIN\n" + "4 - set the Reset Code\n" + "Q - quit\n"); if (strlen (answer) != 1) continue; - if (*answer == 'q' || *answer == 'Q') - break; /* Quit. */ - - if (*answer == '1') - { - /* Change PIN (same as the direct thing in non-admin mode). */ - err = scd_change_pin ("OPENPGP.1", 0); - if (err) - log_error ("Error changing the PIN: %s\n", gpg_strerror (err)); - else - log_info ("PIN changed.\n"); - } + else if (*answer == 'q' || *answer == 'Q') + goto leave; + else if (*answer == '1') + pinref = "OPENPGP.1"; else if (*answer == '2') - { - /* Unblock PIN by setting a new PIN. */ - err = scd_change_pin ("OPENPGP.1", 1); - if (err) - log_error ("Error unblocking the PIN: %s\n", gpg_strerror(err)); - else - log_info ("PIN unblocked and new PIN set.\n"); - } + { pinref = "OPENPGP.1"; reset_mode = 1; } else if (*answer == '3') - { - /* Change Admin PIN. */ - err = scd_change_pin ("OPENPGP.3", 0); - if (err) - log_error ("Error changing the PIN: %s\n", gpg_strerror (err)); - else - log_info ("PIN changed.\n"); - } + pinref = "OPENPGP.3"; else if (*answer == '4') - { - /* Set a new Reset Code. */ - err = scd_change_pin ("OPENPGP.2", 1); - if (err) - log_error ("Error setting the Reset Code: %s\n", - gpg_strerror (err)); - else - log_info ("Reset Code set.\n"); - } + { pinref = "OPENPGP.2"; reset_mode = 1; } + } + } + else if (info->apptype == APP_TYPE_OPENPGP) + pinref = "OPENPGP.1"; + else if (opt.interactive && info->apptype == APP_TYPE_PIV) + { + menu_used = 1; + while (!pinref) + { + xfree (answer); + answer = get_selection ("1 - change the PIN\n" + "2 - change the PUK\n" + "3 - change the Global PIN\n" + "Q - quit\n"); + if (strlen (answer) != 1) + ; + else if (*answer == 'q' || *answer == 'Q') + goto leave; + else if (*answer == '1') + pinref = "PIV.80"; + else if (*answer == '2') + pinref = "PIV.81"; + else if (*answer == '3') + pinref = "PIV.00"; + } + } + else if (info->apptype == APP_TYPE_PIV) + pinref = "PIV.80"; + else + { + err = gpg_error (GPG_ERR_MISSING_VALUE); + goto leave; + } - } /*end for loop*/ + err = scd_change_pin (pinref, reset_mode); + if (err) + { + if (!opt.interactive && !menu_used && !opt.verbose) + ; + else if (!ascii_strcasecmp (pinref, "PIV.81")) + log_error ("Error changing the PUK.\n"); + else if (!ascii_strcasecmp (pinref, "OPENPGP.1") && reset_mode) + log_error ("Error unblocking the PIN.\n"); + else if (!ascii_strcasecmp (pinref, "OPENPGP.2") && reset_mode) + log_error ("Error setting the Reset Code.\n"); + else if (!ascii_strcasecmp (pinref, "OPENPGP.3")) + log_error ("Error changing the Admin PIN.\n"); + else + log_error ("Error changing the PIN.\n"); } else { - if (*argstr) - pinref = argstr; - else if (info->apptype == APP_TYPE_PIV) - pinref = "PIV.80"; - else - { - /* Note that we do not have a default value for OpenPGP - * because we want to be mostly compatible to "gpg - * --card-edit" and show a menu in that case (above). */ - err = gpg_error (GPG_ERR_MISSING_VALUE); - goto leave; - } - err = scd_change_pin (pinref, 0); - if (err) - goto leave; - - if (info->apptype == APP_TYPE_PIV - && !ascii_strcasecmp (pinref, "PIV.81")) + if (!opt.interactive && !opt.verbose) + ; + else if (!ascii_strcasecmp (pinref, "PIV.81")) log_info ("PUK changed.\n"); + else if (!ascii_strcasecmp (pinref, "OPENPGP.1") && reset_mode) + log_info ("PIN unblocked and new PIN set.\n"); + else if (!ascii_strcasecmp (pinref, "OPENPGP.2") && reset_mode) + log_info ("Reset Code set.\n"); + else if (!ascii_strcasecmp (pinref, "OPENPGP.3")) + log_info ("Admin PIN changed.\n"); else log_info ("PIN changed.\n"); } @@ -2261,7 +2282,7 @@ cmd_unblock (card_info_t info) } else { - log_info ("Unblocking not yet supported for '%s'\n", + log_info ("Unblocking not supported for '%s'.\n", app_type_string (info->apptype)); err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); }