diff --git a/agent/ChangeLog b/agent/ChangeLog index 7ec8789fd..de5f3da5b 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,16 @@ +2011-03-03 Werner Koch + + * 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 * call-scd.c (hash_algo_option): New. diff --git a/agent/agent.h b/agent/agent.h index 3319c3684..3e01897d1 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -45,6 +45,18 @@ /* 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]; diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c index c570e3819..4c30f6dea 100644 --- a/agent/call-pinentry.c +++ b/agent/call-pinentry.c @@ -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, /* 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; diff --git a/agent/command.c b/agent/command.c index 79b9b9731..b4b9b9e4c 100644 --- a/agent/command.c +++ b/agent/command.c @@ -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); diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index e5af91ed9..c64b32feb 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -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 */ } diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index cb5f7d732..280670bd3 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -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. @@ -26,23 +26,23 @@ .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 ( ( ) ... @@ -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 ( ( ) ... @@ -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