New option --ssh-fpr for the agent:KEYINFO command
authorWerner Koch <wk@gnupg.org>
Thu, 4 Aug 2011 12:57:35 +0000 (14:57 +0200)
committerWerner Koch <wk@gnupg.org>
Thu, 4 Aug 2011 13:00:58 +0000 (15:00 +0200)
Also added the option --data.  Hwoever we don't list the other itehms
2.1. does; instead we print dashes.

.gitignore
NEWS
agent/ChangeLog
agent/command.c

index 92c4674..eb3806e 100644 (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
diff --git a/NEWS b/NEWS
index a4dbff2..efa8345 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -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.
 
index 9060a49..09e6026 100644 (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
index c300fe5..97cf507 100644 (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)
 
 
 \f
-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)
 
 
 \f
-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)
 
 
 \f
-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)
 
 
 \f
-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)
 
 
 \f
-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)
 
 
 \f
-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)
 
 
 \f
-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)
 
 
 \f
-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)
 
 
 \f
-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)
         {