New agent option pinentry-mode.

This provides the framework and implements the ask, cancel and error.
loopback will be implemented later.
This commit is contained in:
Werner Koch 2011-03-03 18:35:08 +01:00
parent 35205e1300
commit b786f0e12b
6 changed files with 197 additions and 45 deletions

View 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.

View File

@ -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];

View 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,
/* 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;

View 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);

View 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 */
}

View 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.
@ -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
(<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