gpg: Print AKL info only in verbose mode.
[gnupg.git] / agent / command-ssh.c
index 3ab41cf..9d45a18 100644 (file)
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <assert.h>
+#ifndef HAVE_W32_SYSTEM
+#include <sys/socket.h>
+#include <sys/un.h>
+#endif /*!HAVE_W32_SYSTEM*/
+#ifdef HAVE_UCRED_H
+#include <ucred.h>
+#endif
 
 #include "agent.h"
 
-#include "i18n.h"
-#include "util.h"
-#include "ssh-utils.h"
+#include "../common/i18n.h"
+#include "../common/util.h"
+#include "../common/ssh-utils.h"
 
 
 \f
@@ -255,7 +262,7 @@ static gpg_error_t ssh_key_extract_comment (gcry_sexp_t key, char **comment);
 /* Associating request types with the corresponding request
    handlers.  */
 
-static ssh_request_spec_t request_specs[] =
+static const ssh_request_spec_t request_specs[] =
   {
 #define REQUEST_SPEC_DEFINE(id, name, secret_input) \
   { SSH_REQUEST_##id, ssh_handler_##name, #name, secret_input }
@@ -273,7 +280,7 @@ static ssh_request_spec_t request_specs[] =
 
 
 /* Table holding key type specifications.  */
-static ssh_key_type_spec_t ssh_key_types[] =
+static const ssh_key_type_spec_t ssh_key_types[] =
   {
     {
       "ssh-ed25519", "Ed25519", GCRY_PK_EDDSA, "qd",  "q", "rs", "qd",
@@ -667,13 +674,7 @@ stream_read_blob (estream_t stream, unsigned int secure, gcry_mpi_t *r_mpi)
 static gpg_error_t
 stream_read_cstring (estream_t stream, char **string)
 {
-  gpg_error_t err;
-  unsigned char *buffer;
-
-  err = stream_read_string (stream, 0, &buffer, NULL);
-  if (!err)
-    *string = (char *)buffer;
-  return err;
+  return stream_read_string (stream, 0, (unsigned char **)string, NULL);
 }
 
 
@@ -1039,12 +1040,14 @@ search_control_file (ssh_control_file_t cf, const char *hexgrip,
    We can assume that the user wants to allow ssh using this key. */
 static gpg_error_t
 add_control_entry (ctrl_t ctrl, ssh_key_type_spec_t *spec,
-                   const char *hexgrip, const char *fmtfpr,
+                   const char *hexgrip, gcry_sexp_t key,
                    int ttl, int confirm)
 {
   gpg_error_t err;
   ssh_control_file_t cf;
   int disabled;
+  char *fpr_md5 = NULL;
+  char *fpr_sha256 = NULL;
 
   (void)ctrl;
 
@@ -1058,19 +1061,31 @@ add_control_entry (ctrl_t ctrl, ssh_key_type_spec_t *spec,
       struct tm *tp;
       time_t atime = time (NULL);
 
+      err = ssh_get_fingerprint_string (key, GCRY_MD_MD5, &fpr_md5);
+      if (err)
+        goto out;
+
+      err = ssh_get_fingerprint_string (key, GCRY_MD_SHA256, &fpr_sha256);
+      if (err)
+        goto out;
+
       /* Not yet in the file - add it. Because the file has been
          opened in append mode, we simply need to write to it.  */
       tp = localtime (&atime);
       fprintf (cf->fp,
                ("# %s key added on: %04d-%02d-%02d %02d:%02d:%02d\n"
-                "# MD5 Fingerprint:  %s\n"
+                "# Fingerprints:  %s\n"
+                "#                %s\n"
                 "%s %d%s\n"),
                spec->name,
                1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
                tp->tm_hour, tp->tm_min, tp->tm_sec,
-               fmtfpr, hexgrip, ttl, confirm? " confirm":"");
+               fpr_md5, fpr_sha256, hexgrip, ttl, confirm? " confirm":"");
 
     }
+ out:
+  xfree (fpr_md5);
+  xfree (fpr_sha256);
   close_control_file (cf);
   return 0;
 }
@@ -2111,7 +2126,7 @@ ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret,
        *   string      private_key
        *
        * Note that the private key is the concatenation of the private
-       * key with the public key.  Thus theres are 64 bytes; however
+       * key with the public key.  Thus there's are 64 bytes; however
        * we only want the real 32 byte private key - Libgcrypt expects
        * this.
        */
@@ -2575,7 +2590,6 @@ ssh_handler_request_identities (ctrl_t ctrl,
 
   key_public = NULL;
   key_counter = 0;
-  err = 0;
 
   key_blobs = es_fopenmem (0, "r+b");
   if (! key_blobs)
@@ -2760,7 +2774,7 @@ data_sign (ctrl_t ctrl, ssh_key_type_spec_t *spec,
       err = agent_raw_key_from_file (ctrl, ctrl->keygrip, &key);
       if (err)
         goto out;
-      err = ssh_get_fingerprint_string (key, &fpr);
+      err = ssh_get_fingerprint_string (key, opt.ssh_fingerprint_digest, &fpr);
       if (!err)
         {
           gcry_sexp_t tmpsxp = gcry_sexp_find_token (key, "comment", 0);
@@ -2966,6 +2980,7 @@ ssh_key_extract_comment (gcry_sexp_t key, char **r_comment)
 
 /* This function converts the key contained in the S-Expression KEY
    into a buffer, which is protected by the passphrase PASSPHRASE.
+   If PASSPHRASE is the empty passphrase, the key is not protected.
    Returns usual error code.  */
 static gpg_error_t
 ssh_key_to_protected_buffer (gcry_sexp_t key, const char *passphrase,
@@ -2975,7 +2990,6 @@ ssh_key_to_protected_buffer (gcry_sexp_t key, const char *passphrase,
   unsigned int buffer_new_n;
   gpg_error_t err;
 
-  err = 0;
   buffer_new_n = gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, NULL, 0);
   buffer_new = xtrymalloc_secure (buffer_new_n);
   if (! buffer_new)
@@ -2987,7 +3001,17 @@ ssh_key_to_protected_buffer (gcry_sexp_t key, const char *passphrase,
   gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, buffer_new, buffer_new_n);
   /* FIXME: guarantee?  */
 
-  err = agent_protect (buffer_new, passphrase, buffer, buffer_n, 0, -1);
+  if (*passphrase)
+    err = agent_protect (buffer_new, passphrase, buffer, buffer_n, 0, -1);
+  else
+    {
+      /* The key derivation function does not support zero length
+       * strings.  Store key unprotected if the user wishes so.  */
+      *buffer = buffer_new;
+      *buffer_n = buffer_new_n;
+      buffer_new = NULL;
+      err = 0;
+    }
 
  out:
 
@@ -3039,7 +3063,7 @@ ssh_identity_register (ctrl_t ctrl, ssh_key_type_spec_t *spec,
 
   bin2hex (key_grip_raw, 20, key_grip);
 
-  err = ssh_get_fingerprint_string (key, &key_fpr);
+  err = ssh_get_fingerprint_string (key, opt.ssh_fingerprint_digest, &key_fpr);
   if (err)
     goto out;
 
@@ -3119,7 +3143,7 @@ ssh_identity_register (ctrl_t ctrl, ssh_key_type_spec_t *spec,
 
  key_exists:
   /* And add an entry to the sshcontrol file.  */
-  err = add_control_entry (ctrl, spec, key_grip, key_fpr, ttl, confirm);
+  err = add_control_entry (ctrl, spec, key_grip, key, ttl, confirm);
 
 
  out:
@@ -3377,10 +3401,10 @@ ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response)
 /* Return the request specification for the request identified by TYPE
    or NULL in case the requested request specification could not be
    found.  */
-static ssh_request_spec_t *
+static const ssh_request_spec_t *
 request_spec_lookup (int type)
 {
-  ssh_request_spec_t *spec;
+  const ssh_request_spec_t *spec;
   unsigned int i;
 
   for (i = 0; i < DIM (request_specs); i++)
@@ -3404,7 +3428,7 @@ request_spec_lookup (int type)
 static int
 ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
 {
-  ssh_request_spec_t *spec;
+  const ssh_request_spec_t *spec;
   estream_t response = NULL;
   estream_t request = NULL;
   unsigned char request_type;
@@ -3556,31 +3580,39 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
 }
 
 
-/* Return the peer's pid.  Stripped down code from libassuan.  */
+/* Return the peer's pid.  */
 static unsigned long
 get_client_pid (int fd)
 {
-  pid_t client_pid = (pid_t)(-1);
+  pid_t client_pid = (pid_t)0;
 
-#ifdef HAVE_SO_PEERCRED
+#ifdef SO_PEERCRED
   {
+#ifdef HAVE_STRUCT_SOCKPEERCRED_PID
+    struct sockpeercred cr;
+#else
     struct ucred cr;
+#endif
     socklen_t cl = sizeof cr;
 
-    if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
-      client_pid = cr.pid;
+    if (!getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
+      {
+#if defined (HAVE_STRUCT_SOCKPEERCRED_PID) || defined (HAVE_STRUCT_UCRED_PID)
+        client_pid = cr.pid;
+#elif defined (HAVE_STRUCT_UCRED_CR_PID)
+        client_pid = cr.cr_pid;
+#else
+#error "Unknown SO_PEERCRED struct"
+#endif
+      }
   }
-#elif defined (HAVE_GETPEERUCRED)
+#elif defined (LOCAL_PEERPID)
   {
-    ucred_t *ucred = NULL;
+    socklen_t len = sizeof (pid_t);
 
-    if (getpeerucred (fd, &ucred) != -1)
-      {
-       client_pid= ucred_getpid (ucred);
-       ucred_free (ucred);
-      }
+    getsockopt (fd, SOL_LOCAL, LOCAL_PEERPID, &client_pid, &len);
   }
-#elif defined (HAVE_LOCAL_PEEREID)
+#elif defined (LOCAL_PEEREID)
   {
     struct unpcbid unp;
     socklen_t unpl = sizeof unp;
@@ -3588,9 +3620,21 @@ get_client_pid (int fd)
     if (getsockopt (fd, 0, LOCAL_PEEREID, &unp, &unpl) != -1)
       client_pid = unp.unp_pid;
   }
+#elif defined (HAVE_GETPEERUCRED)
+  {
+    ucred_t *ucred = NULL;
+
+    if (getpeerucred (fd, &ucred) != -1)
+      {
+        client_pid= ucred_getpid (ucred);
+        ucred_free (ucred);
+      }
+  }
+#else
+  (void)fd;
 #endif
 
-  return client_pid == (pid_t)(-1)? 0 : (unsigned long)client_pid;
+  return (unsigned long)client_pid;
 }
 
 
@@ -3631,7 +3675,7 @@ start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client)
   /* Main processing loop. */
   while ( !ssh_request_process (ctrl, stream_sock) )
     {
-      /* Check wether we have reached EOF before trying to read
+      /* Check whether we have reached EOF before trying to read
         another request.  */
       int c;
 
@@ -3663,7 +3707,7 @@ serve_mmapped_ssh_request (ctrl_t ctrl,
   gpg_error_t err;
   int send_err = 0;
   int valid_response = 0;
-  ssh_request_spec_t *spec;
+  const ssh_request_spec_t *spec;
   u32 msglen;
   estream_t request_stream, response_stream;