New option --ssh-fpr for the agent:KEYINFO command

Also added the option --data.  Hwoever we don't list the other itehms
2.1. does; instead we print dashes.
This commit is contained in:
Werner Koch 2011-08-04 14:57:35 +02:00
parent d4c7a55958
commit 2b5a2eb2d2
4 changed files with 126 additions and 75 deletions

1
.gitignore vendored
View File

@ -31,6 +31,7 @@ agent/gpg-agent
agent/gpg-preset-passphrase
agent/gpg-protect-tool
agent/t-protect
agent/t-ssh-utils
common/libcommon.a
common/libcommonpth.a
common/libgpgrl.a

3
NEWS
View File

@ -5,7 +5,8 @@ Noteworthy changes in version 2.0.18 (unreleased)
* Bug fix for newer versions of Libgcrypt.
* Support the SSH confirm flag.
* Support the SSH confirm flag and show SSH fingerprint in ssh
related pinentries.
* Improved dirmngr/gpgsm interaction for OCSP.

View File

@ -1,5 +1,8 @@
2011-08-04 Werner Koch <wk@g10code.com>
* command.c (cmd_keyinfo, do_one_keyinfo): Support options --data
and --ssh-fpr.
* command-ssh.c (ssh_identity_register): Display the ssh
fingerprint in the prompt.
(add_control_entry): Add arg FMTFPR and use it as comment in

View File

@ -37,6 +37,7 @@
#include "agent.h"
#include <assuan.h>
#include "i18n.h"
#include "../common/ssh-utils.h"
/* maximum allowed size of the inquired ciphertext */
#define MAXLEN_CIPHERTEXT 4096
@ -72,7 +73,7 @@ struct putval_item_s
struct putval_item_s *next;
size_t off; /* Offset to the value into DATA. */
size_t len; /* Length of the value. */
char d[1]; /* Key | Nul | value. */
char d[1]; /* Key | Nul | value. */
};
@ -86,14 +87,14 @@ static struct putval_item_s *putval_list;
integers and there should be no problem if they are overflowing as
callers need to check only whether a counter changed. The actual
values are not meaningful. */
struct
struct
{
/* Incremented if any of the other counters below changed. */
unsigned int any;
/* Incremented if a key is added or removed from the internal privat
key database. */
unsigned int key;
unsigned int key;
/* Incremented if a change of the card readers stati has been
detected. */
@ -291,7 +292,7 @@ agent_write_status (ctrl_t ctrl, const char *keyword, ...)
va_start (arg_ptr, keyword);
p = buf;
p = buf;
n = 0;
while ( (text = va_arg (arg_ptr, const char *)) )
{
@ -332,7 +333,7 @@ agent_inq_pinentry_launched (ctrl_t ctrl, unsigned long pid)
{
char line[100];
if (!ctrl || !ctrl->server_local
if (!ctrl || !ctrl->server_local
|| !ctrl->server_local->allow_pinentry_notify)
return 0;
snprintf (line, DIM(line)-1, "PINENTRY_LAUNCHED %lu", pid);
@ -341,7 +342,7 @@ agent_inq_pinentry_launched (ctrl_t ctrl, unsigned long pid)
static const char hlp_geteventcounter[] =
static const char hlp_geteventcounter[] =
"GETEVENTCOUNTER\n"
"\n"
"Return a a status line named EVENTCOUNTER with the current values\n"
@ -399,7 +400,7 @@ bump_card_eventcounter (void)
static const char hlp_istrusted[] =
static const char hlp_istrusted[] =
"ISTRUSTED <hexstring_with_fingerprint>\n"
"\n"
"Return OK when we have an entry with this fingerprint in our\n"
@ -439,7 +440,7 @@ cmd_istrusted (assuan_context_t ctx, char *line)
}
static const char hlp_listtrusted[] =
static const char hlp_listtrusted[] =
"LISTTRUSTED\n"
"\n"
"List all entries from the trustlist.";
@ -447,7 +448,7 @@ static gpg_error_t
cmd_listtrusted (assuan_context_t ctx, char *line)
{
int rc;
(void)line;
rc = agent_listtrusted (ctx);
@ -457,7 +458,7 @@ cmd_listtrusted (assuan_context_t ctx, char *line)
}
static const char hlp_martrusted[] =
static const char hlp_martrusted[] =
"MARKTRUSTED <hexstring_with_fingerprint> <flag> <display_name>\n"
"\n"
"Store a new key in into the trustlist.";
@ -484,7 +485,7 @@ cmd_marktrusted (assuan_context_t ctx, char *line)
for (p=line; i < 40; p++, i++)
fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
fpr[i] = 0;
while (spacep (p))
p++;
flag = *p++;
@ -542,7 +543,7 @@ cmd_sigkey (assuan_context_t ctx, char *line)
}
static const char hlp_setkeydesc[] =
static const char hlp_setkeydesc[] =
"SETKEYDESC plus_percent_escaped_string\n"
"\n"
"Set a description to be used for the next PKSIGN or PKDECRYPT\n"
@ -629,7 +630,7 @@ cmd_sethash (assuan_context_t ctx, char *line)
algo = 0;
line = skip_options (line);
if (!algo)
{
/* No hash option has been given: require an algo number instead */
@ -649,7 +650,7 @@ cmd_sethash (assuan_context_t ctx, char *line)
n /= 2;
if (algo == MD_USER_TLS_MD5SHA1 && n == 36)
;
else if (n != 16 && n != 20 && n != 24
else if (n != 16 && n != 20 && n != 24
&& n != 28 && n != 32 && n != 48 && n != 64)
return set_error (GPG_ERR_ASS_PARAMETER, "unsupported length of hash");
@ -666,7 +667,7 @@ cmd_sethash (assuan_context_t ctx, char *line)
}
static const char hlp_pksign[] =
static const char hlp_pksign[] =
"PKSIGN [options]\n"
"\n"
"Perform the actual sign operation. Neither input nor output are\n"
@ -678,9 +679,9 @@ cmd_pksign (assuan_context_t ctx, char *line)
cache_mode_t cache_mode = CACHE_MODE_NORMAL;
ctrl_t ctrl = assuan_get_pointer (ctx);
membuf_t outbuf;
(void)line;
if (opt.ignore_cache_for_signing)
cache_mode = CACHE_MODE_IGNORE;
else if (!ctrl->server_local->use_cache_for_signing)
@ -702,7 +703,7 @@ cmd_pksign (assuan_context_t ctx, char *line)
}
static const char hlp_pkdecrypt[] =
static const char hlp_pkdecrypt[] =
"PKDECRYPT <options>\n"
"\n"
"Perform the actual decrypt operation. Input is not\n"
@ -741,7 +742,7 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
}
static const char hlp_genkey[] =
static const char hlp_genkey[] =
"GENKEY\n"
"\n"
"Generate a new key, store the secret part and return the public\n"
@ -787,7 +788,7 @@ cmd_genkey (assuan_context_t ctx, char *line)
static const char hlp_readkey[] =
static const char hlp_readkey[] =
"READKEY <hexstring_with_keygrip>\n"
"\n"
"Return the public key for the given keygrip.";
@ -831,16 +832,16 @@ cmd_readkey (assuan_context_t ctx, char *line)
static const char hlp_keyinfo[] =
"KEYINFO [--list] <keygrip>\n"
static const char hlp_keyinfo[] =
"KEYINFO [--list] [--data] [--ssh-fpr] <keygrip>\n"
"\n"
"Return information about the key specified by the KEYGRIP. If the\n"
"key is not available GPG_ERR_NOT_FOUND is returned. If the option\n"
"--list is given the keygrip is ignored and information about all\n"
"available keys are returned. The information is returned as a\n"
"status line with this format:\n"
"status line unless --data was specified, with this format:\n"
"\n"
" KEYINFO <keygrip> <type> <serialno> <idstr>\n"
" KEYINFO <keygrip> <type> <serialno> <idstr> - - <fpr>\n"
"\n"
"KEYGRIP is the keygrip.\n"
"\n"
@ -856,12 +857,18 @@ static const char hlp_keyinfo[] =
"IDSTR is the IDSTR used to distinguish keys on a smartcard. If it\n"
" is not known a dash is used instead.\n"
"\n"
"FPR returns the formatted ssh-style fingerprint of the key. It is only\n"
" print if the option --ssh-fpr has been used. '-' is printed if the\n"
" fingerprint is not available.\n"
"\n"
"More information may be added in the future.";
static gpg_error_t
do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip)
do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx,
int data, int with_ssh_fpr)
{
gpg_error_t err;
char hexgrip[40+1];
char *fpr = NULL;
int keytype;
unsigned char *shadow_info = NULL;
char *serialno = NULL;
@ -874,29 +881,65 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip)
/* Reformat the grip so that we use uppercase as good style. */
bin2hex (grip, 20, hexgrip);
if (keytype == PRIVATE_KEY_CLEAR
if (keytype == PRIVATE_KEY_CLEAR
|| keytype == PRIVATE_KEY_PROTECTED)
keytypestr = "D";
else if (keytype == PRIVATE_KEY_SHADOWED)
keytypestr = "T";
else
else
keytypestr = "-";
/* Compute the ssh fingerprint if requested. */
if (with_ssh_fpr)
{
gcry_sexp_t key;
if (!agent_raw_key_from_file (ctrl, grip, &key))
{
ssh_get_fingerprint_string (key, &fpr);
gcry_sexp_release (key);
}
}
if (shadow_info)
{
err = parse_shadow_info (shadow_info, &serialno, &idstr);
if (err)
goto leave;
}
err = agent_write_status (ctrl, "KEYINFO",
hexgrip,
keytypestr,
serialno? serialno : "-",
idstr? idstr : "-",
NULL);
/* Note that we don't support the CACHED and PROTECTION values as
gnupg 2.1 does. We print '-' instead. However we support the
ssh fingerprint. */
if (!data)
err = agent_write_status (ctrl, "KEYINFO",
hexgrip,
keytypestr,
serialno? serialno : "-",
idstr? idstr : "-",
"-",
"-",
fpr? fpr : "-",
NULL);
else
{
char *string;
string = xtryasprintf ("%s %s %s %s - - %s\n",
hexgrip, keytypestr,
serialno? serialno : "-",
idstr? idstr : "-",
fpr? fpr : "-");
if (!string)
err = gpg_error_from_syserror ();
else
err = assuan_send_data (ctx, string, strlen(string));
xfree (string);
}
leave:
xfree (fpr);
xfree (shadow_info);
xfree (serialno);
xfree (idstr);
@ -912,8 +955,11 @@ cmd_keyinfo (assuan_context_t ctx, char *line)
unsigned char grip[20];
DIR *dir = NULL;
int list_mode;
int opt_data, opt_ssh_fpr;
list_mode = has_option (line, "--list");
opt_data = has_option (line, "--data");
opt_ssh_fpr = has_option (line, "--ssh-fpr");
line = skip_options (line);
if (list_mode)
@ -921,7 +967,7 @@ cmd_keyinfo (assuan_context_t ctx, char *line)
char *dirname;
struct dirent *dir_entry;
char hexgrip[41];
dirname = make_filename_try (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL);
if (!dirname)
{
@ -948,7 +994,7 @@ cmd_keyinfo (assuan_context_t ctx, char *line)
if ( hex2bin (hexgrip, grip, 20) < 0 )
continue; /* Bad hex string. */
err = do_one_keyinfo (ctrl, grip);
err = do_one_keyinfo (ctrl, grip, ctx, opt_data, opt_ssh_fpr);
if (err)
goto leave;
}
@ -959,9 +1005,9 @@ cmd_keyinfo (assuan_context_t ctx, char *line)
err = parse_keygrip (ctx, line, grip);
if (err)
goto leave;
err = do_one_keyinfo (ctrl, grip);
err = do_one_keyinfo (ctrl, grip, ctx, opt_data, opt_ssh_fpr);
}
leave:
if (dir)
closedir (dir);
@ -998,7 +1044,7 @@ send_back_passphrase (assuan_context_t ctx, int via_data, const char *pw)
}
static const char hlp_get_passphrase[] =
static const char hlp_get_passphrase[] =
"GET_PASSPHRASE [--data] [--check] [--no-ask] [--repeat[=N]]\n"
" [--qualitybar] <cache_id>\n"
" [<error_message> <prompt> <description>]\n"
@ -1119,8 +1165,8 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
plus_to_blank (desc);
next_try:
rc = agent_get_passphrase (ctrl, &response, desc, prompt,
repeat_errtext? repeat_errtext:errtext,
rc = agent_get_passphrase (ctrl, &response, desc, prompt,
repeat_errtext? repeat_errtext:errtext,
opt_qualbar);
xfree (repeat_errtext);
repeat_errtext = NULL;
@ -1145,7 +1191,7 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
{
xfree (response2);
xfree (response);
repeat_errtext = try_percent_escape
repeat_errtext = try_percent_escape
(_("does not match - try again"), NULL);
if (!repeat_errtext)
{
@ -1172,7 +1218,7 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
}
static const char hlp_clear_passphrase[] =
static const char hlp_clear_passphrase[] =
"CLEAR_PASSPHRASE <cache_id>\n"
"\n"
"may be used to invalidate the cache entry for a passphrase. The\n"
@ -1198,7 +1244,7 @@ cmd_clear_passphrase (assuan_context_t ctx, char *line)
}
static const char hlp_get_confirmation[] =
static const char hlp_get_confirmation[] =
"GET_CONFIRMATION <description>\n"
"\n"
"This command may be used to ask for a simple confirmation.\n"
@ -1265,7 +1311,7 @@ cmd_learn (assuan_context_t ctx, char *line)
static const char hlp_passwd[] =
static const char hlp_passwd[] =
"PASSWD <hexstring_with_keygrip>\n"
"\n"
"Change the passphrase/PIN for the key identified by keygrip in LINE.";
@ -1284,7 +1330,7 @@ cmd_passwd (assuan_context_t ctx, char *line)
ctrl->in_passwd++;
rc = agent_key_from_file (ctrl, ctrl->server_local->keydesc,
grip, &shadow_info, CACHE_MODE_IGNORE, NULL,
grip, &shadow_info, CACHE_MODE_IGNORE, NULL,
&s_skey);
if (rc)
;
@ -1309,7 +1355,7 @@ cmd_passwd (assuan_context_t ctx, char *line)
}
static const char hlp_preset_passphrase[] =
static const char hlp_preset_passphrase[] =
"PRESET_PASSPHRASE <string_or_keygrip> <timeout> <hexstring>\n"
"\n"
"Set the cached passphrase/PIN for the key identified by the keygrip\n"
@ -1338,7 +1384,7 @@ cmd_preset_passphrase (assuan_context_t ctx, char *line)
line++;
while (*line && (*line == ' ' || *line == '\t'))
line++;
/* Currently, only infinite timeouts are allowed. */
ttl = -1;
if (line[0] != '-' || line[1] != '1')
@ -1378,7 +1424,7 @@ cmd_preset_passphrase (assuan_context_t ctx, char *line)
static const char hlp_scd[] =
static const char hlp_scd[] =
"SCD <commands to pass to the scdaemon>\n"
" \n"
"This is a general quote command to redirect everything to the\n"
@ -1396,7 +1442,7 @@ cmd_scd (assuan_context_t ctx, char *line)
static const char hlp_getval[] =
static const char hlp_getval[] =
"GETVAL <key>\n"
"\n"
"Return the value for KEY from the special environment as created by\n"
@ -1415,7 +1461,7 @@ cmd_getval (assuan_context_t ctx, char *line)
p = strchr (key, ' ');
if (p)
{
*p++ = 0;
*p++ = 0;
for (; *p == ' '; p++)
;
if (*p)
@ -1440,7 +1486,7 @@ cmd_getval (assuan_context_t ctx, char *line)
}
static const char hlp_putval[] =
static const char hlp_putval[] =
"PUTVAL <key> [<percent_escaped_value>]\n"
"\n"
"The gpg-agent maintains a kind of environment which may be used to\n"
@ -1474,7 +1520,7 @@ cmd_putval (assuan_context_t ctx, char *line)
p = strchr (key, ' ');
if (p)
{
*p++ = 0;
*p++ = 0;
for (; *p == ' '; p++)
;
if (*p)
@ -1503,7 +1549,7 @@ cmd_putval (assuan_context_t ctx, char *line)
xfree (vl);
}
if (valuelen) /* Add entry. */
if (valuelen) /* Add entry. */
{
vl = xtrymalloc (sizeof *vl + strlen (key) + valuelen);
if (!vl)
@ -1527,7 +1573,7 @@ cmd_putval (assuan_context_t ctx, char *line)
static const char hlp_updatestartuptty[] =
static const char hlp_updatestartuptty[] =
"UPDATESTARTUPTTY\n"
"\n"
"Set startup TTY and X11 DISPLAY variables to the values of this\n"
@ -1537,7 +1583,7 @@ static const char hlp_updatestartuptty[] =
static gpg_error_t
cmd_updatestartuptty (assuan_context_t ctx, char *line)
{
static const char *names[] =
static const char *names[] =
{ "GPG_TTY", "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL };
ctrl_t ctrl = assuan_get_pointer (ctx);
gpg_error_t err = 0;
@ -1545,7 +1591,7 @@ cmd_updatestartuptty (assuan_context_t ctx, char *line)
int idx;
char *lc_ctype = NULL;
char *lc_messages = NULL;
(void)line;
se = session_env_new ();
@ -1559,14 +1605,14 @@ cmd_updatestartuptty (assuan_context_t ctx, char *line)
err = session_env_setenv (se, names[idx], value);
}
if (!err && ctrl->lc_ctype)
if (!err && ctrl->lc_ctype)
if (!(lc_ctype = xtrystrdup (ctrl->lc_ctype)))
err = gpg_error_from_syserror ();
if (!err && ctrl->lc_messages)
if (!(lc_messages = xtrystrdup (ctrl->lc_messages)))
err = gpg_error_from_syserror ();
if (err)
{
session_env_release (se);
@ -1599,7 +1645,7 @@ cmd_killagent (assuan_context_t ctx, char *line)
ctrl_t ctrl = assuan_get_pointer (ctx);
(void)line;
if (!opt.use_standard_socket)
return set_error (GPG_ERR_NOT_SUPPORTED, "no --use-standard-socket");
@ -1625,7 +1671,7 @@ cmd_reloadagent (assuan_context_t ctx, char *line)
static const char hlp_getinfo[] =
static const char hlp_getinfo[] =
"GETINFO <what>\n"
"\n"
"Multipurpose function to return a variety of information.\n"
@ -1693,15 +1739,15 @@ cmd_getinfo (assuan_context_t ctx, char *line)
int iterator;
const char *name, *value;
char *string;
iterator = 0;
iterator = 0;
while ((name = session_env_list_stdenvnames (&iterator, NULL)))
{
value = session_env_getenv_or_default
(line[5] == 't'? opt.startup_env:ctrl->session_env, name, NULL);
if (value)
{
string = xtryasprintf ("%s=%s", name, value);
string = xtryasprintf ("%s=%s", name, value);
if (!string)
rc = gpg_error_from_syserror ();
else
@ -1827,7 +1873,7 @@ static void
post_cmd_notify (assuan_context_t ctx, gpg_error_t err)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
(void)err;
/* Switch off any I/O monitor controlled logging pausing. */
@ -1844,7 +1890,7 @@ io_monitor (assuan_context_t ctx, void *hook, int direction,
const char *line, size_t linelen)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
(void) hook;
/* Note that we only check for the uppercase name. This allows to
@ -1871,7 +1917,7 @@ command_has_option (const char *cmd, const char *cmdopt)
if (!strcmp (cmdopt, "repeat"))
return 1;
}
return 0;
}
@ -1905,8 +1951,8 @@ register_commands (assuan_context_t ctx)
{ "MARKTRUSTED", cmd_marktrusted, hlp_martrusted },
{ "LEARN", cmd_learn, hlp_learn },
{ "PASSWD", cmd_passwd, hlp_passwd },
{ "INPUT", NULL },
{ "OUTPUT", NULL },
{ "INPUT", NULL },
{ "OUTPUT", NULL },
{ "SCD", cmd_scd, hlp_scd },
{ "GETVAL", cmd_getval, hlp_getval },
{ "PUTVAL", cmd_putval, hlp_putval },
@ -1924,7 +1970,7 @@ register_commands (assuan_context_t ctx)
table[i].help);
if (rc)
return rc;
}
}
assuan_register_post_cmd_notify (ctx, post_cmd_notify);
assuan_register_reset_notify (ctx, reset_notify);
assuan_register_option_handler (ctx, option_handler);
@ -1963,7 +2009,7 @@ start_command_handler (ctrl_t ctrl, gnupg_fd_t listen_fd, gnupg_fd_t fd)
/* FIXME: Need to call assuan_sock_set_nonce for Windows. But
this branch is currently not used. */
}
else
else
{
rc = assuan_init_socket_server (ctx, fd, ASSUAN_SOCKET_SERVER_ACCEPTED);
}
@ -2002,7 +2048,7 @@ start_command_handler (ctrl_t ctrl, gnupg_fd_t listen_fd, gnupg_fd_t fd)
log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
break;
}
rc = assuan_process (ctx);
if (rc)
{