[PATCH v2 1/1] pinentry-mode: add new mode no-card-cancel-prompt

Curt Brune curt at brune.net
Sat Jan 7 06:56:53 CET 2017


This patch adds a new pinentry-mode called 'no-card-cancel-prompt'.

The goal is to suppress unneeded pinentry prompting when the inserted
smartcard's serial number does not match the requested serial number.

When the requested smartcard serial number does not match the inserted
card's serial number, automatically skip the card without prompting
the user.  This skips the launching of pinetry and moves on, as if the
user had selected "cancel".

This is convenient when decrypting a file encrypted for multiple
smartcard recipients, but only one smartcard is available.  In this
case only one pinetry will be shown to the user (the one for the
inserted card), while the remaining pinetry prompts for unavailable
smartcards will be suppressed.

Signed-off-by: Curt Brune <curt at brune.net>
---
 agent/call-pinentry.c |  3 ++-
 agent/divert-scd.c    |  5 +++++
 common/agent-opt.c    | 11 +++++++----
 common/shareddefs.h   |  9 +++++----
 doc/gpg-agent.texi    |  4 ++++
 5 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c
index 0f24086..800ccf1 100644
--- a/agent/call-pinentry.c
+++ b/agent/call-pinentry.c
@@ -826,21 +826,22 @@ agent_askpin (ctrl_t ctrl,
   char line[ASSUAN_LINELENGTH];
   struct entry_parm_s parm;
   const char *errtext = NULL;
   int is_pin = 0;
   int saveflag;
   unsigned int pinentry_status;
 
   if (opt.batch)
     return 0; /* fixme: we should return BAD PIN */
 
-  if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
+  if ((ctrl->pinentry_mode != PINENTRY_MODE_ASK) &&
+      (ctrl->pinentry_mode != PINENTRY_MODE_NO_CARD_CANCEL_PROMPT))
     {
       if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
         return gpg_error (GPG_ERR_CANCELED);
       if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
         {
 	  unsigned char *passphrase;
 	  size_t size;
 
 	  *pininfo->pin = 0; /* Reset the PIN. */
 	  rc = pinentry_loopback(ctrl, "PASSPHRASE", &passphrase, &size,
diff --git a/agent/divert-scd.c b/agent/divert-scd.c
index 5d3b1ef..75332ad 100644
--- a/agent/divert-scd.c
+++ b/agent/divert-scd.c
@@ -64,20 +64,25 @@ ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
           log_debug ("detected card with S/N %s\n", serialno);
           i = strcmp (serialno, want_sn);
           xfree (serialno);
           serialno = NULL;
           if (!i)
             {
               xfree (want_sn);
               *r_kid = want_kid;
               return 0; /* yes, we have the correct card */
             }
+          if (ctrl->pinentry_mode == PINENTRY_MODE_NO_CARD_CANCEL_PROMPT)
+            {
+              log_debug ("skipping card with mismatched S/N\n");
+              rc = gpg_error (GPG_ERR_CANCELED);
+            }
         }
       else if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT)
         {
           log_debug ("no card present\n");
           rc = 0;
           no_card = 1;
         }
       else
         {
           log_error ("error accessing card: %s\n", gpg_strerror (rc));
diff --git a/common/agent-opt.c b/common/agent-opt.c
index 4317ba3..3967d7e 100644
--- a/common/agent-opt.c
+++ b/common/agent-opt.c
@@ -42,30 +42,33 @@ parse_pinentry_mode (const char *value)
   int result;
 
   if (!strcmp (value, "ask") || !strcmp (value, "default"))
     result = PINENTRY_MODE_ASK;
   else if (!strcmp (value, "cancel"))
     result = PINENTRY_MODE_CANCEL;
   else if (!strcmp (value, "error"))
     result = PINENTRY_MODE_ERROR;
   else if (!strcmp (value, "loopback"))
     result = PINENTRY_MODE_LOOPBACK;
+  else if (!strcmp (value, "no-card-cancel-prompt"))
+    result = PINENTRY_MODE_NO_CARD_CANCEL_PROMPT;
   else
     result = -1;
 
   return result;
 }
 
 /* Return the string representation for the pinentry MODE.  Returns
    "?" for an invalid mode.  */
 const char *
 str_pinentry_mode (pinentry_mode_t mode)
 {
   switch (mode)
     {
-    case PINENTRY_MODE_ASK:      return "ask";
-    case PINENTRY_MODE_CANCEL:   return "cancel";
-    case PINENTRY_MODE_ERROR:    return "error";
-    case PINENTRY_MODE_LOOPBACK: return "loopback";
+    case PINENTRY_MODE_ASK:                   return "ask";
+    case PINENTRY_MODE_CANCEL:                return "cancel";
+    case PINENTRY_MODE_ERROR:                 return "error";
+    case PINENTRY_MODE_LOOPBACK:              return "loopback";
+    case PINENTRY_MODE_NO_CARD_CANCEL_PROMPT: return "no-card-cancel-prompt";
     }
  return "?";
 }
diff --git a/common/shareddefs.h b/common/shareddefs.h
index 604b7e9..59b0c9d 100644
--- a/common/shareddefs.h
+++ b/common/shareddefs.h
@@ -24,24 +24,25 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef GNUPG_COMMON_SHAREDDEFS_H
 #define GNUPG_COMMON_SHAREDDEFS_H
 
 /* Values for the pinentry mode.  */
 typedef enum
   {
-    PINENTRY_MODE_ASK = 0, /* Ask via pinentry (default).  */
-    PINENTRY_MODE_CANCEL,  /* Always return a cancel error.  */
-    PINENTRY_MODE_ERROR,   /* Return error code for no pinentry.  */
-    PINENTRY_MODE_LOOPBACK /* Use an inquiry to get the value.    */
+    PINENTRY_MODE_ASK = 0,              /* Ask via pinentry (default).  */
+    PINENTRY_MODE_CANCEL,               /* Always return a cancel error.  */
+    PINENTRY_MODE_ERROR,                /* Return error code for no pinentry.  */
+    PINENTRY_MODE_LOOPBACK,             /* Use an inquiry to get the value.    */
+    PINENTRY_MODE_NO_CARD_CANCEL_PROMPT /* Return cancel error if card is absent. */
   }
 pinentry_mode_t;
 
 
 /*-- agent-opt.c --*/
 int parse_pinentry_mode (const char *value);
 const char *str_pinentry_mode (pinentry_mode_t mode);
 
 
 
diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi
index f4da9cf..549e3d0 100644
--- a/doc/gpg-agent.texi
+++ b/doc/gpg-agent.texi
@@ -1408,20 +1408,24 @@ This option is used to change the operation mode of the pinentry.  The
 following values are defined:
 
   @table @code
   @item ask
   This is the default mode which pops up a pinentry as needed.
 
   @item cancel
   Instead of popping up a pinentry, return the error code
   @code{GPG_ERR_CANCELED}.
 
+  @item no-card-cancel-prompt
+  When the requested smartcard serial number does not match the inserted
+  card's serial number, return the error code @code{GPG_ERR_CANCELED}.
+
   @item error
   Instead of popping up a pinentry, return the error code
   @code{GPG_ERR_NO_PIN_ENTRY}.
 
   @item loopback
   Use a loopback pinentry.  This fakes a pinentry by using inquiries
   back to the caller to ask for a passphrase.  This option may only be
   set if the agent has been configured for that.
   Use the @xref{option --allow-loopback-pinentry}.
 
-- 
2.7.4




More information about the Gnupg-devel mailing list