New agent option pinentry-mode.
authorWerner Koch <wk@gnupg.org>
Thu, 3 Mar 2011 17:35:08 +0000 (18:35 +0100)
committerWerner Koch <wk@gnupg.org>
Thu, 3 Mar 2011 17:35:08 +0000 (18:35 +0100)
This provides the framework and implements the ask, cancel and error.
loopback will be implemented later.

agent/ChangeLog
agent/agent.h
agent/call-pinentry.c
agent/command.c
agent/gpg-agent.c
doc/gpg-agent.texi

index 7ec8789..de5f3da 100644 (file)
@@ -1,3 +1,16 @@
+2011-03-03  Werner Koch  <wk@g10code.com>
+
+       * gpg-agent.c: Add option --allow-loopback-pinentry.
+       * command.c (option_handler): Add option pinentry-mode.
+       * agent.h (pinentry_mode_t): New enum.
+       (struct server_local_s): Add PINENTRY_MODE.
+       (struct opt): Add ALLOW_LOOPBACK_PINENTRY.
+       * call-pinentry.c (agent_askpin): Implement ask, cancel and error
+       pinentry modes.
+       (agent_get_passphrase, agent_get_confirmation): Ditto.
+       (agent_show_message): Return cancel if pinentry mode is not "ask".
+       (agent_popup_message_start): Ditto.
+
 2011-03-02  Werner Koch  <wk@g10code.com>
 
        * call-scd.c (hash_algo_option): New.
index 3319c36..3e01897 100644 (file)
 /* Maximum length of a digest.  */
 #define MAX_DIGEST_LEN 64
 
+
+/* 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_t;
+
+
 /* A large struct name "opt" to keep global flags */
 struct
 {
@@ -67,7 +79,6 @@ struct
   char *startup_lc_ctype;
   char *startup_lc_messages;
 
-
   const char *pinentry_program; /* Filename of the program to start as
                                    pinentry.  */
   const char *scdaemon_program; /* Filename of the program to handle
@@ -105,6 +116,7 @@ struct
   int ignore_cache_for_signing;
   int allow_mark_trusted;
   int allow_preset_passphrase;
+  int allow_loopback_pinentry;
   int keep_tty;      /* Don't switch the TTY (for pinentry) on request */
   int keep_display;  /* Don't switch the DISPLAY (for pinentry) on request */
   int ssh_support;   /* Enable ssh-agent emulation.  */
@@ -149,6 +161,9 @@ struct server_control_s
   char *lc_ctype;
   char *lc_messages;
 
+  /* The current pinentry mode.  */
+  pinentry_mode_t pinentry_mode;
+
   struct {
     int algo;
     unsigned char value[MAX_DIGEST_LEN];
index c570e38..4c30f6d 100644 (file)
@@ -742,6 +742,14 @@ agent_askpin (ctrl_t ctrl,
   if (opt.batch)
     return 0; /* fixme: we should return BAD PIN */
 
+  if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
+    {
+      if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
+        return gpg_error (GPG_ERR_CANCELED);
+      /*FIXME:  Implement loopback mode.  */
+      return gpg_error (GPG_ERR_NO_PIN_ENTRY);
+    }
+
   if (!pininfo || pininfo->max_length < 1)
     return gpg_error (GPG_ERR_INV_VALUE);
   if (!desc_text && pininfo->min_digits)
@@ -895,6 +903,14 @@ agent_get_passphrase (ctrl_t ctrl,
   if (opt.batch)
     return gpg_error (GPG_ERR_BAD_PASSPHRASE);
 
+  if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
+    {
+      if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
+        return gpg_error (GPG_ERR_CANCELED);
+
+      return gpg_error (GPG_ERR_NO_PIN_ENTRY);
+    }
+
   rc = start_pinentry (ctrl);
   if (rc)
     return rc;
@@ -981,6 +997,14 @@ agent_get_confirmation (ctrl_t ctrl,
   int rc;
   char line[ASSUAN_LINELENGTH];
 
+  if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
+    {
+      if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
+        return gpg_error (GPG_ERR_CANCELED);
+
+      return gpg_error (GPG_ERR_NO_PIN_ENTRY);
+    }
+
   rc = start_pinentry (ctrl);
   if (rc)
     return rc;
@@ -1046,7 +1070,7 @@ agent_get_confirmation (ctrl_t ctrl,
 
 \f
 /* Pop up the PINentry, display the text DESC and a button with the
-   text OK_BTN (which may be NULL to use the default of "OK") and waut
+   text OK_BTN (which may be NULL to use the default of "OK") and wait
    for the user to hit this button.  The return value is not
    relevant.  */
 int
@@ -1055,6 +1079,9 @@ agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn)
   int rc;
   char line[ASSUAN_LINELENGTH];
 
+  if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
+    return gpg_error (GPG_ERR_CANCELED);
+
   rc = start_pinentry (ctrl);
   if (rc)
     return rc;
@@ -1123,6 +1150,9 @@ agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
   char line[ASSUAN_LINELENGTH];
   pth_attr_t tattr;
 
+  if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
+    return gpg_error (GPG_ERR_CANCELED);
+
   rc = start_pinentry (ctrl);
   if (rc)
     return rc;
index 79b9b97..b4b9b9e 100644 (file)
@@ -2402,6 +2402,24 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
     ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0;
   else if (!strcmp (key, "allow-pinentry-notify"))
     ctrl->server_local->allow_pinentry_notify = 1;
+  else if (!strcmp (key, "pinentry-mode"))
+    {
+      if (!strcmp (value, "ask") || !strcmp (value, "default"))
+        ctrl->pinentry_mode = PINENTRY_MODE_ASK;
+      else if (!strcmp (value, "cancel"))
+        ctrl->pinentry_mode = PINENTRY_MODE_CANCEL;
+      else if (!strcmp (value, "error"))
+        ctrl->pinentry_mode = PINENTRY_MODE_ERROR;
+      else if (!strcmp (value, "loopback"))
+        {
+          if (opt.allow_loopback_pinentry)
+            ctrl->pinentry_mode = PINENTRY_MODE_LOOPBACK;
+          else
+            err = gpg_error (GPG_ERR_NOT_SUPPORTED);
+        }
+      else
+        err = gpg_error (GPG_ERR_INV_VALUE);
+    }
   else
     err = gpg_error (GPG_ERR_UNKNOWN_OPTION);
 
index e5af91e..c64b32f 100644 (file)
@@ -105,6 +105,7 @@ enum cmd_and_opt_values
   oIgnoreCacheForSigning,
   oAllowMarkTrusted,
   oAllowPresetPassphrase,
+  oAllowLoopbackPinentry,
   oKeepTTY,
   oKeepDISPLAY,
   oSSHSupport,
@@ -179,6 +180,8 @@ static ARGPARSE_OPTS opts[] = {
                              N_("allow clients to mark keys as \"trusted\"")},
   { oAllowPresetPassphrase, "allow-preset-passphrase", 0,
                              N_("allow presetting passphrase")},
+  { oAllowLoopbackPinentry, "allow-loopback-pinentry", 0,
+                             N_("allow presetting passphrase")},
   { oSSHSupport, "enable-ssh-support", 0, N_("enable ssh-agent emulation") },
   { oWriteEnvFile, "write-env-file", 2|8,
             N_("|FILE|write environment settings also to FILE")},
@@ -549,6 +552,8 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
 
     case oAllowPresetPassphrase: opt.allow_preset_passphrase = 1; break;
 
+    case oAllowLoopbackPinentry: opt.allow_loopback_pinentry = 1; break;
+
     default:
       return 0; /* not handled */
     }
index cb5f7d7..280670b 100644 (file)
@@ -2,7 +2,7 @@
 @c This is part of the GnuPG manual.
 @c For copying conditions, see the file gnupg.texi.
 
-@c Note that we use this texinfo file for all versions of GnuPG: 
+@c Note that we use this texinfo file for all versions of GnuPG:
 @c 2.0 and 2.1.  The macro "gpgtwoone" controls parts which are only
 @c valid for GnuPG 2.1 and later.
 
 .IR dir ]
 .RB [ \-\-options
 .IR file ]
-.RI [ options ]  
+.RI [ options ]
 .br
 .B  gpg-agent
 .RB [ \-\-homedir
 .IR dir ]
 .RB [ \-\-options
 .IR file ]
-.RI [ options ]  
-.B  \-\-server 
+.RI [ options ]
+.B  \-\-server
 .br
 .B  gpg-agent
 .RB [ \-\-homedir
 .IR dir ]
 .RB [ \-\-options
 .IR file ]
-.RI [ options ]  
-.B  \-\-daemon 
+.RI [ options ]
+.B  \-\-daemon
 .RI [ command_line ]
 @end ifset
 
@@ -106,7 +106,7 @@ fi
 It reads the data out of the file and exports the variables.  If you
 don't use Secure Shell, you don't need the last two export statements.
 @end ifclear
+
 @noindent
 You should always add the following lines to your @code{.bashrc} or
 whatever initialization file is used for all shell invocations:
@@ -235,7 +235,7 @@ a numeric value or a keyword:
 @item none
 No debugging at all.  A value of less than 1 may be used instead of
 the keyword.
-@item basic  
+@item basic
 Some basic debug messages.  A value between 1 and 2 may be used
 instead of the keyword.
 @item advanced
@@ -263,8 +263,8 @@ usual C-Syntax. The currently defined bits are:
 @table @code
 @item 0  (1)
 X.509 or OpenPGP protocol related data
-@item 1  (2)  
-values of big number integers 
+@item 1  (2)
+values of big number integers
 @item 2  (4)
 low level crypto operations
 @item 5  (32)
@@ -348,6 +348,12 @@ Allow clients to mark keys as trusted, i.e. put them into the
 @file{trustlist.txt} file.  This is by default not allowed to make it
 harder for users to inadvertently accept Root-CA keys.
 
+@anchor{option --allow-loopback-pinentry}
+@item --allow-loopback-pinentry
+@opindex allow-loopback-pinentry
+Allow clients to use the loopback pinentry features; see the option
+@option{pinentry-mode} for details.
+
 @item --ignore-cache-for-signing
 @opindex ignore-cache-for-signing
 This option will let @command{gpg-agent} bypass the passphrase cache for all
@@ -398,7 +404,7 @@ to 1.
 Check the passphrase against the pattern given in @var{file}.  When
 entering a new passphrase matching one of these pattern a warning will
 be displayed. @var{file} should be an absolute filename.  The default is
-not to use any pattern file. 
+not to use any pattern file.
 
 Security note: It is known that checking a passphrase against a list of
 pattern or even against a complete dictionary is not very effective to
@@ -408,7 +414,7 @@ behavior and optionally to run a passphrase cracker regularly on all
 users passphrases to catch the very simple ones.
 
 @item --max-passphrase-days @var{n}
-@opindex max-passphrase-days 
+@opindex max-passphrase-days
 Ask the user to change the passphrase if @var{n} days have passed since
 the last change.  With @option{--enforce-passphrase-constraints} set the
 user may not bypass this check.
@@ -477,10 +483,10 @@ option has been enabled.
 @itemx --lc-ctype @var{string}
 @itemx --lc-messages @var{string}
 @itemx --xauthority @var{string}
-@opindex display 
-@opindex ttyname 
-@opindex ttytype 
-@opindex lc-ctype 
+@opindex display
+@opindex ttyname
+@opindex ttytype
+@opindex lc-ctype
 @opindex lc-messages
 @opindex xauthority
 These options are used with the server mode to pass localization
@@ -563,7 +569,7 @@ agent. By default they may all be found in the current home directory
   two dashes may not be entered and the option may not be abbreviated.
   This file is also read after a @code{SIGHUP} however only a few
   options will actually have an effect.  This default name may be
-  changed on the command line (@pxref{option --options}).  
+  changed on the command line (@pxref{option --options}).
   You should backup this file.
 
 @item trustlist.txt
@@ -576,21 +582,21 @@ agent. By default they may all be found in the current home directory
   allows to cut and paste the fingerprint from a key listing output.  If
   the line is prefixed with a @code{!} the key is explicitly marked as
   not trusted.
-  
+
   Here is an example where two keys are marked as ultimately trusted
   and one as not trusted:
-  
+
   @example
   # CN=Wurzel ZS 3,O=Intevation GmbH,C=DE
   A6935DD34EF3087973C706FC311AA2CCF733765B S
-  
+
   # CN=PCA-1-Verwaltung-02/O=PKI-1-Verwaltung/C=DE
-  DC:BD:69:25:48:BD:BB:7E:31:6E:BB:80:D3:00:80:35:D4:F8:A6:CD S 
+  DC:BD:69:25:48:BD:BB:7E:31:6E:BB:80:D3:00:80:35:D4:F8:A6:CD S
 
   # CN=Root-CA/O=Schlapphuete/L=Pullach/C=DE
   !14:56:98:D3:FE:9C:CA:5A:31:6E:BC:81:D3:11:4E:00:90:A3:44:C2 S
   @end example
-  
+
 Before entering a key into this file, you need to ensure its
 authenticity.  How to do this depends on your organisation; your
 administrator might have already entered those keys which are deemed
@@ -625,7 +631,7 @@ fails, try again using the chain validation model.
 
 @end table
 
-  
+
 @item sshcontrol
 @cindex sshcontrol
 This file is used when support for the secure shell agent protocol has
@@ -641,11 +647,11 @@ optional field for arbitrary flags.  A non-zero TTL overrides the global
 default as set by @option{--default-cache-ttl-ssh}.
 
 The keygrip may be prefixed with a @code{!} to disable an entry entry.
-    
+
 The following example lists exactly one key.  Note that keys available
 through a OpenPGP smartcard in the active smartcard reader are
 implicitly added to this list; i.e. there is no need to list them.
-  
+
   @example
   # Key added on 2005-02-25 15:08:29
   5A6592BF45DC73BD876874A28FD4639282E29B52 0
@@ -675,7 +681,7 @@ a small helper script is provided to create these files (@pxref{addgnupghome}).
 @node Agent Signals
 @section Use of some signals.
 A running @command{gpg-agent} may be controlled by signals, i.e. using
-the @command{kill} command to send a signal to the process. 
+the @command{kill} command to send a signal to the process.
 
 Here is a list of supported signals:
 
@@ -714,7 +720,7 @@ This signal is used for internal purposes.
 
 @end table
 
-@c 
+@c
 @c  Examples
 @c
 @mansect examples
@@ -757,7 +763,7 @@ and add something like (for Bourne shells)
 @noindent
 to your shell initialization file (e.g. @file{~/.bashrc}).
 
-@c 
+@c
 @c  Assuan Protocol
 @c
 @manpause
@@ -800,6 +806,7 @@ secret keys.
 * Agent UPDATESTARTUPTTY:: Change the Standard Display
 * Agent GETEVENTCOUNTER:: Get the Event Counters
 * Agent GETINFO::         Return information about the process
+* Agent OPTION::          Set options for the session
 @end menu
 
 @node Agent PKDECRYPT
@@ -831,13 +838,13 @@ text.
     C: D xxxx)
     C: END
 @end example
-    
+
 Please note that the server may send status info lines while reading the
 data lines from the client.  The data send is a SPKI like S-Exp with
 this structure:
 
 @example
-     (enc-val   
+     (enc-val
        (<algo>
          (<param_name1> <mpi>)
           ...
@@ -850,20 +857,20 @@ the parameters depend on the algorithm.  The agent does return an error
 if there is an inconsistency.
 
 If the decryption was successful the decrypted data is returned by
-means of "D" lines. 
+means of "D" lines.
 
 Here is an example session:
 
 @example
    C: PKDECRYPT
    S: INQUIRE CIPHERTEXT
-   C: D (enc-val elg (a 349324324) 
+   C: D (enc-val elg (a 349324324)
    C: D    (b 3F444677CA)))
    C: END
    S: # session key follows
    S: D (value 1234567890ABCDEF0)
    S: OK descryption successful
-@end example         
+@end example
 
 
 @node Agent PKSIGN
@@ -911,8 +918,8 @@ different algorithms.  The agent does then some checks, asks for the
 passphrase and as a result the server returns the signature as an SPKI
 like S-expression in "D" lines:
 
-@example  
-     (sig-val   
+@example
+     (sig-val
        (<algo>
          (<param_name1> <mpi>)
           ...
@@ -960,7 +967,7 @@ option allows to choose the storage location.  To get the secret key out
 of the PSE, a special export tool has to be used.
 
 @example
-   GENKEY 
+   GENKEY
 @end example
 
 Invokes the key generation process and the server will then inquire
@@ -1095,13 +1102,13 @@ Known sequences with the pattern @@foo@@ are replaced according to this
 table:
 
 @table @code
-@item @@FPR16@@ 
+@item @@FPR16@@
 Format the fingerprint according to gpg rules for a v3 keys.
-@item @@FPR20@@ 
+@item @@FPR20@@
 Format the fingerprint according to gpg rules for a v4 keys.
 @item @@FPR@@
 Choose an appropriate format to format the fingerprint.
-@item @@@@ 
+@item @@@@
 Replaced by a single @code{@@}
 @end table
 
@@ -1123,7 +1130,7 @@ arguments the agent returns a cached passphrase or an error.  By
 convention either the hexified fingerprint of the key shall be used for
 @var{cache_id} or an arbitrary string prefixed with the name of the
 calling application and a colon: Like @code{gpg:somestring}.
-  
+
 @var{error_message} is either a single @code{X} for no error message or
 a string to be shown as an error message like (e.g. "invalid
 passphrase").  Blanks must be percent escaped or replaced by @code{+}'.
@@ -1147,7 +1154,7 @@ has been found in the cache.
 
 If the option @option{--no-ask} is used and the passphrase is not in the
 cache the user will not be asked to enter a passphrase but the error
-code @code{GPG_ERR_NO_DATA} is returned.  
+code @code{GPG_ERR_NO_DATA} is returned.
 
 If the option @option{--qualitybar} is used and a minimum passphrase
 length has been configured, a visual indication of the entered
@@ -1279,11 +1286,75 @@ Return the name of the socket used for SSH connections.  If SSH support
 has not been enabled the error @code{GPG_ERR_NO_DATA} will be returned.
 @end table
 
+@node Agent OPTION
+@subsection Set options for the session
+
+Here is a list of session options which are not yet described with
+other commands.  The general syntax for an Assuan option is:
+
+@smallexample
+OPTION  @var{key}=@var{value}
+@end smallexample
+
+@noindent
+Supported @var{key}s are:
+
+@table @code
+@item agent-awareness
+This may be used to tell gpg-agent of which gpg-agent version the
+client is aware of.  gpg-agent uses this information to enable
+features which might break older clients.
+
+@item putenv
+Change the session's environment to be used for the
+Pinentry.  Valid values are:
+
+  @table @code
+  @item @var{name}
+  Delete envvar @var{name}
+  @item @var{name}=
+  Set envvar @var{name} to the empty string
+  @item @var{name}=@var{value}
+  Set envvar @var{name} to the string @var{value}.
+  @end table
+
+@item use-cache-for-signing
+See Assuan command @code{PKSIGN}.
+
+@item allow-pinentry-notify
+This does not need any value.  It is used to enable the
+PINENTRY_LAUNCHED inquiry.
+
+@item pinentry-mode
+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 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}.
+
+  @end table
+@end table
+
 
 @mansect see also
 @ifset isman
-@command{gpg2}(1), 
-@command{gpgsm}(1), 
+@command{gpg2}(1),
+@command{gpgsm}(1),
 @command{gpg-connect-agent}(1),
 @command{scdaemon}(1)
 @end ifset