From d4082ff430afe670510d2c1c7ea66ee9ddcbe505 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 21 Jan 2019 14:06:51 +0100 Subject: [PATCH] scd: Add option --clear to PASSWD. * scd/command.c (cmd_passwd): Add option --clear. (send_status_printf): New. * scd/app-common.h (APP_CHANGE_FLAG_CLEAR): New. * scd/app-nks.c (do_change_pin): Return an error if that option is used. * scd/app-openpgp.c (do_change_pin): Ditto. -- Card application may support this option to clear the PIN verification status of a specific PIN. Signed-off-by: Werner Koch (cherry picked from commit 29929e65521279eabc98a67c766fe485057405a9) --- po/Makevars | 1 + scd/app-common.h | 5 +++-- scd/app-nks.c | 3 +++ scd/app-openpgp.c | 4 ++++ scd/app.c | 2 +- scd/command.c | 34 +++++++++++++++++++++++++++++++--- scd/scdaemon.h | 3 +++ 7 files changed, 46 insertions(+), 6 deletions(-) diff --git a/po/Makevars b/po/Makevars index b538f19e9..270ac5943 100644 --- a/po/Makevars +++ b/po/Makevars @@ -62,6 +62,7 @@ XGETTEXT_OPTIONS = \ --flag=print_further_info:1:c-format \ --flag=write_status_printf:2:c-format \ --flag=gpgconf_write_status:2:c-format \ + --flag=send_status_printf:3:c-format \ --flag=wks_write_status:2:c-format # This is the copyright holder that gets inserted into the header of the diff --git a/scd/app-common.h b/scd/app-common.h index 38e6cc609..37e3c605d 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -26,8 +26,9 @@ #include -#define APP_CHANGE_FLAG_RESET 1 -#define APP_CHANGE_FLAG_NULLPIN 2 +#define APP_CHANGE_FLAG_RESET 1 /* PIN Reset mode. */ +#define APP_CHANGE_FLAG_NULLPIN 2 /* NULL PIN mode. */ +#define APP_CHANGE_FLAG_CLEAR 4 /* Clear the given PIN. */ /* Bit flags set by the decipher function into R_INFO. */ #define APP_DECIPHER_INFO_NOPAD 1 /* Padding has been removed. */ diff --git a/scd/app-nks.c b/scd/app-nks.c index 801ab904a..0f38e7cd0 100644 --- a/scd/app-nks.c +++ b/scd/app-nks.c @@ -1169,6 +1169,9 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *pwidstr, if (!newdesc) return gpg_error (GPG_ERR_INV_ID); + if ((flags & APP_CHANGE_FLAG_CLEAR)) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + err = switch_application (app, is_sigg); if (err) return err; diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index fa23fbef2..760332ef9 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -2584,10 +2584,14 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int pinlen = 0; (void)ctrl; + memset (&pininfo, 0, sizeof pininfo); pininfo.fixedlen = -1; pininfo.minlen = minlen; + if ((flags & APP_CHANGE_FLAG_CLEAR)) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + if (reset_mode && chvno == 3) { rc = gpg_error (GPG_ERR_INV_ID); diff --git a/scd/app.c b/scd/app.c index a82db26cd..c43057946 100644 --- a/scd/app.c +++ b/scd/app.c @@ -938,7 +938,7 @@ app_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode, } -/* Perform a VERIFY operation without doing anything lese. This may +/* Perform a VERIFY operation without doing anything else. This may be used to initialize a the PIN cache for long lasting other operations. Its use is highly application dependent. */ gpg_error_t diff --git a/scd/command.c b/scd/command.c index 8fa4b381c..ec6793a5f 100644 --- a/scd/command.c +++ b/scd/command.c @@ -1192,12 +1192,13 @@ cmd_random (assuan_context_t ctx, char *line) static const char hlp_passwd[] = - "PASSWD [--reset] [--nullpin] \n" + "PASSWD [--reset] [--nullpin] [--clear] \n" "\n" "Change the PIN or, if --reset is given, reset the retry counter of\n" "the card holder verification vector CHVNO. The option --nullpin is\n" - "used for TCOS cards to set the initial PIN. The format of CHVNO\n" - "depends on the card application."; + "used for TCOS cards to set the initial PIN. The option --clear clears\n" + "the security status associated with the PIN so that the PIN needs to\n" + "be presented again. The format of CHVNO depends on the card application."; static gpg_error_t cmd_passwd (assuan_context_t ctx, char *line) { @@ -1210,6 +1211,8 @@ cmd_passwd (assuan_context_t ctx, char *line) flags |= APP_CHANGE_FLAG_RESET; if (has_option (line, "--nullpin")) flags |= APP_CHANGE_FLAG_NULLPIN; + if (has_option (line, "--clear")) + flags |= APP_CHANGE_FLAG_CLEAR; line = skip_options (line); @@ -1220,6 +1223,11 @@ cmd_passwd (assuan_context_t ctx, char *line) line++; *line = 0; + /* Do not allow other flags aside of --clear. */ + if ((flags & APP_CHANGE_FLAG_CLEAR) && (flags & ~APP_CHANGE_FLAG_CLEAR)) + return set_error (GPG_ERR_UNSUPPORTED_OPERATION, + "--clear used with other options"); + if ((rc = open_card (ctrl))) return rc; @@ -1899,6 +1907,26 @@ send_status_direct (ctrl_t ctrl, const char *keyword, const char *args) } +/* This status functions expects a printf style format string. No + * filtering of the data is done instead the orintf formatted data is + * send using assuan_send_status. */ +gpg_error_t +send_status_printf (ctrl_t ctrl, const char *keyword, const char *format, ...) +{ + gpg_error_t err; + va_list arg_ptr; + assuan_context_t ctx; + + if (!ctrl || !ctrl->server_local || !(ctx = ctrl->server_local->assuan_ctx)) + return 0; + + va_start (arg_ptr, format); + err = vprint_assuan_status (ctx, keyword, format, arg_ptr); + va_end (arg_ptr); + return err; +} + + void popup_prompt (void *opaque, int on) { diff --git a/scd/scdaemon.h b/scd/scdaemon.h index 238e6a8fd..73589ade8 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -123,6 +123,9 @@ int scd_command_handler (ctrl_t, int); void send_status_info (ctrl_t ctrl, const char *keyword, ...) GPGRT_ATTR_SENTINEL(1); void send_status_direct (ctrl_t ctrl, const char *keyword, const char *args); +gpg_error_t send_status_printf (ctrl_t ctrl, const char *keyword, + const char *format, ...) GPGRT_ATTR_PRINTF(3,4); + void popup_prompt (void *opaque, int on); void send_client_notifications (app_t app, int removal); void scd_kick_the_loop (void);