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

@ -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
@ -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
@ -1279,6 +1286,70 @@ 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