[git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-110-gd2777f8

by Werner Koch cvs at cvs.gnupg.org
Mon Dec 10 18:32:17 CET 2012


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, master has been updated
       via  d2777f84be0ded5906a9bec3bc23cfed0a9be02f (commit)
       via  25fb53ab4ae7e1c098500229c776d29b82713a20 (commit)
       via  36ba7845995dd3caf8faeec3e09b3ffb879fc29b (commit)
       via  ceab60b59d907354d323ace09d7b3f2d36d330fb (commit)
      from  1e1326aeb8923782138e133f091afec41d969c40 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit d2777f84be0ded5906a9bec3bc23cfed0a9be02f
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Dec 10 18:27:23 2012 +0100

    ssh: Improve key lookup for many keys.
    
    * agent/command-ssh.c: Remove dirent.h.
    (control_file_s): Add struct item.
    (rewind_control_file): New.
    (search_control_file): Factor code out to ...
    (read_control_file_item): New.
    (ssh_handler_request_identities): Change to iterate over entries in
    sshcontrol.
    --
    
    Formerly we scanned the private key directory for matches of entries
    in sshcontrol.  This patch changes it to scan the sshcontrol file and
    thus considers only keys configured there.  The rationale for this is
    that it is common to have only a few ssh keys but many private keys.
    Even if that assumption does not hold true, the scanning of the
    sshcontrol file is faster than reading the directory and only then
    scanning the ssh control for each directory entry.

diff --git a/agent/command-ssh.c b/agent/command-ssh.c
index 435177d..533793c 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -27,7 +27,6 @@
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <dirent.h>
 #include <assert.h>
 
 #include "agent.h"
@@ -168,6 +167,14 @@ struct control_file_s
 {
   char *fname;  /* Name of the file.  */
   FILE *fp;     /* This is never NULL. */
+  int lnr;      /* The current line number.  */
+  struct {
+    int valid;           /* True if the data of this structure is valid.  */
+    int disabled;        /* The item is disabled.  */
+    int ttl;             /* The TTL of the item.   */
+    int confirm;         /* The confirm flag is set.  */
+    char hexgrip[40+1];  /* The hexgrip of the item (uppercase).  */
+  } item;
 };
 typedef struct control_file_s *control_file_t;
 
@@ -741,6 +748,15 @@ open_control_file (control_file_t *r_cf, int append)
 
 
 static void
+rewind_control_file (control_file_t cf)
+{
+  fseek (cf->fp, 0, SEEK_SET);
+  cf->lnr = 0;
+  clearerr (cf->fp);
+}
+
+
+static void
 close_control_file (control_file_t cf)
 {
   if (!cf)
@@ -751,29 +767,19 @@ close_control_file (control_file_t cf)
 }
 
 
-/* Search the control file CF from the beginning until a matching
-   HEXGRIP is found; return success in this case and store true at
-   DISABLED if the found key has been disabled.  If R_TTL is not NULL
-   a specified TTL for that key is stored there.  If R_CONFIRM is not
-   NULL it is set to 1 if the key has the confirm flag set. */
+
+/* Read the next line from the control file and store the data in CF.
+   Returns 0 on success, GPG_ERR_EOF on EOF, or other error codes. */
 static gpg_error_t
-search_control_file (control_file_t cf, const char *hexgrip,
-                     int *r_disabled, int *r_ttl, int *r_confirm)
+read_control_file_item (control_file_t cf)
 {
   int c, i, n;
   char *p, *pend, line[256];
-  long ttl;
-  int lnr = 0;
+  long ttl = 0;
 
-  assert (strlen (hexgrip) == 40 );
-
-  if (r_confirm)
-    *r_confirm = 0;
-
-  fseek (cf->fp, 0, SEEK_SET);
+  cf->item.valid = 0;
   clearerr (cf->fp);
-  *r_disabled = 0;
- next_line:
+
   do
     {
       if (!fgets (line, DIM(line)-1, cf->fp) )
@@ -782,7 +788,7 @@ search_control_file (control_file_t cf, const char *hexgrip,
             return gpg_error (GPG_ERR_EOF);
           return gpg_error_from_syserror ();
         }
-      lnr++;
+      cf->lnr++;
 
       if (!*line || line[strlen(line)-1] != '\n')
         {
@@ -799,35 +805,34 @@ search_control_file (control_file_t cf, const char *hexgrip,
     }
   while (!*p || *p == '\n' || *p == '#');
 
-  *r_disabled = 0;
+  cf->item.disabled = 0;
   if (*p == '!')
     {
-      *r_disabled = 1;
+      cf->item.disabled = 1;
       for (p++; spacep (p); p++)
         ;
     }
 
   for (i=0; hexdigitp (p) && i < 40; p++, i++)
-    if (hexgrip[i] != (*p >= 'a'? (*p & 0xdf): *p))
-      goto next_line;
+    cf->item.hexgrip[i] = (*p >= 'a'? (*p & 0xdf): *p);
+  cf->item.hexgrip[i] = 0;
   if (i != 40 || !(spacep (p) || *p == '\n'))
     {
-      log_error ("invalid formatted line in `%s', line %d\n", cf->fname, lnr);
+      log_error ("%s:%d: invalid formatted line\n", cf->fname, cf->lnr);
       return gpg_error (GPG_ERR_BAD_DATA);
     }
 
   ttl = strtol (p, &pend, 10);
   p = pend;
-  if (!(spacep (p) || *p == '\n') || ttl < -1)
+  if (!(spacep (p) || *p == '\n') || (int)ttl < -1)
     {
-      log_error ("invalid TTL value in `%s', line %d; assuming 0\n",
-                 cf->fname, lnr);
-      ttl = 0;
+      log_error ("%s:%d: invalid TTL value; assuming 0\n", cf->fname, cf->lnr);
+      cf->item.ttl = 0;
     }
-  if (r_ttl)
-    *r_ttl = ttl;
+  cf->item.ttl = ttl;
 
   /* Now check for key-value pairs of the form NAME[=VALUE]. */
+  cf->item.confirm = 0;
   while (*p)
     {
       for (; spacep (p) && *p != '\n'; p++)
@@ -837,22 +842,68 @@ search_control_file (control_file_t cf, const char *hexgrip,
       n = strcspn (p, "= \t\n");
       if (p[n] == '=')
         {
-          log_error ("assigning a value to a flag is not yet supported; "
-                     "in `%s', line %d; flag ignored\n", cf->fname, lnr);
+          log_error ("%s:%d: assigning a value to a flag is not yet supported; "
+                     "flag ignored\n", cf->fname, cf->lnr);
           p++;
         }
       else if (n == 7 && !memcmp (p, "confirm", 7))
         {
-          if (r_confirm)
-            *r_confirm = 1;
+          cf->item.confirm = 1;
         }
       else
-        log_error ("invalid flag `%.*s' in `%s', line %d; ignored\n",
-                   n, p, cf->fname, lnr);
+        log_error ("%s:%d: invalid flag '%.*s'; ignored\n",
+                   cf->fname, cf->lnr, n, p);
       p += n;
     }
 
-  return 0; /* Okay:  found it.  */
+  /* log_debug ("%s:%d: grip=%s ttl=%d%s%s\n", */
+  /*            cf->fname, cf->lnr, */
+  /*            cf->item.hexgrip, cf->item.ttl, */
+  /*            cf->item.disabled? " disabled":"", */
+  /*            cf->item.confirm? " confirm":""); */
+
+  cf->item.valid = 1;
+  return 0; /* Okay: valid entry found.  */
+}
+
+
+
+/* Search the control file CF from the beginning until a matching
+   HEXGRIP is found; return success in this case and store true at
+   DISABLED if the found key has been disabled.  If R_TTL is not NULL
+   a specified TTL for that key is stored there.  If R_CONFIRM is not
+   NULL it is set to 1 if the key has the confirm flag set. */
+static gpg_error_t
+search_control_file (control_file_t cf, const char *hexgrip,
+                     int *r_disabled, int *r_ttl, int *r_confirm)
+{
+  gpg_error_t err;
+
+  assert (strlen (hexgrip) == 40 );
+
+  *r_disabled = 0;
+  if (r_ttl)
+    *r_ttl = 0;
+  if (r_confirm)
+    *r_confirm = 0;
+
+  rewind_control_file (cf);
+  while (!(err=read_control_file_item (cf)))
+    {
+      if (!cf->item.valid)
+        continue; /* Should not happen.  */
+      if (!strcmp (hexgrip, cf->item.hexgrip))
+        break;
+    }
+  if (!err)
+    {
+      *r_disabled = cf->item.disabled;
+      if (r_ttl)
+        *r_ttl = cf->item.ttl;
+      if (r_confirm)
+        *r_confirm = cf->item.confirm;
+    }
+  return err;
 }
 
 
@@ -1896,19 +1947,13 @@ static gpg_error_t
 ssh_handler_request_identities (ctrl_t ctrl,
                                 estream_t request, estream_t response)
 {
-  char *key_type;
   ssh_key_type_spec_t spec;
-  struct dirent *dir_entry;
-  char *key_directory;
-  size_t key_directory_n;
-  char *key_path;
-  unsigned char *buffer;
-  size_t buffer_n;
+  char *key_fname = NULL;
+  char *fnameptr;
   u32 key_counter;
   estream_t key_blobs;
   gcry_sexp_t key_secret;
   gcry_sexp_t key_public;
-  DIR *dir;
   gpg_error_t err;
   int ret;
   control_file_t cf = NULL;
@@ -1919,14 +1964,9 @@ ssh_handler_request_identities (ctrl_t ctrl,
 
   /* Prepare buffer stream.  */
 
-  key_directory = NULL;
   key_secret = NULL;
   key_public = NULL;
-  key_type = NULL;
-  key_path = NULL;
   key_counter = 0;
-  buffer = NULL;
-  dir = NULL;
   err = 0;
 
   key_blobs = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
@@ -1936,34 +1976,6 @@ ssh_handler_request_identities (ctrl_t ctrl,
       goto out;
     }
 
-  /* Open key directory.  */
-  key_directory = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL);
-  if (! key_directory)
-    {
-      err = gpg_err_code_from_errno (errno);
-      goto out;
-    }
-  key_directory_n = strlen (key_directory);
-
-  key_path = xtrymalloc (key_directory_n + 46);
-  if (! key_path)
-    {
-      err = gpg_err_code_from_errno (errno);
-      goto out;
-    }
-
-  sprintf (key_path, "%s/", key_directory);
-  sprintf (key_path + key_directory_n + 41, ".key");
-
-  dir = opendir (key_directory);
-  if (! dir)
-    {
-      err = gpg_err_code_from_errno (errno);
-      goto out;
-    }
-
-
-
   /* First check whether a key is currently available in the card
      reader - this should be allowed even without being listed in
      sshcontrol. */
@@ -1982,77 +1994,93 @@ ssh_handler_request_identities (ctrl_t ctrl,
     }
 
 
-  /* Then look at all the registered an allowed keys. */
+  /* Prepare buffer for key name construction.  */
+  {
+    char *dname;
 
+    dname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL);
+    if (!dname)
+      {
+        err = gpg_err_code_from_syserror ();
+        goto out;
+      }
 
-  /* Fixme: We should better iterate over the control file and check
-     whether the key file is there.  This is better in respect to
-     performance if there are a lot of keys in our key storage. */
-  /* FIXME: make sure that buffer gets deallocated properly.  */
+    key_fname = xtrymalloc (strlen (dname) + 1 + 40 + 4 + 1);
+    if (!key_fname)
+      {
+        err = gpg_err_code_from_syserror ();
+        xfree (dname);
+        goto out;
+      }
+    fnameptr = stpcpy (stpcpy (key_fname, dname), "/");
+    xfree (dname);
+  }
+
+  /* Then look at all the registered and non-disabled keys. */
   err = open_control_file (&cf, 0);
   if (err)
     goto out;
 
-  while ( (dir_entry = readdir (dir)) )
+  while (!read_control_file_item (cf))
     {
-      if ((strlen (dir_entry->d_name) == 44)
-          && (! strncmp (dir_entry->d_name + 40, ".key", 4)))
-        {
-          char hexgrip[41];
-          int disabled;
-
-          /* We do only want to return keys listed in our control
-             file. */
-          strncpy (hexgrip, dir_entry->d_name, 40);
-          hexgrip[40] = 0;
-          if ( strlen (hexgrip) != 40 )
-            continue;
-          if (search_control_file (cf, hexgrip, &disabled, NULL, NULL)
-              || disabled)
-            continue;
-
-          strncpy (key_path + key_directory_n + 1, dir_entry->d_name, 40);
+      if (!cf->item.valid)
+        continue; /* Should not happen.  */
+      if (cf->item.disabled)
+        continue;
+      assert (strlen (cf->item.hexgrip) == 40);
 
-          /* Read file content.  */
-          err = file_to_buffer (key_path, &buffer, &buffer_n);
-          if (err)
-            goto out;
+      stpcpy (stpcpy (fnameptr, cf->item.hexgrip), ".key");
 
-          err = gcry_sexp_sscan (&key_secret, NULL, (char*)buffer, buffer_n);
-          if (err)
-            goto out;
+      /* Read file content.  */
+      {
+        unsigned char *buffer;
+        size_t buffer_n;
+
+        err = file_to_buffer (key_fname, &buffer, &buffer_n);
+        if (err)
+          {
+            log_error ("%s:%d: key '%s' skipped: %s\n",
+                       cf->fname, cf->lnr, cf->item.hexgrip,
+                       gpg_strerror (err));
+            continue;
+          }
 
-          xfree (buffer);
-          buffer = NULL;
+        err = gcry_sexp_sscan (&key_secret, NULL, (char*)buffer, buffer_n);
+        xfree (buffer);
+        if (err)
+          goto out;
+      }
 
-          err = sexp_extract_identifier (key_secret, &key_type);
-          if (err)
-            goto out;
+      {
+        char *key_type = NULL;
 
-          err = ssh_key_type_lookup (NULL, key_type, &spec);
-          if (err)
-            goto out;
+        err = sexp_extract_identifier (key_secret, &key_type);
+        if (err)
+          goto out;
 
-          xfree (key_type);
-          key_type = NULL;
+        err = ssh_key_type_lookup (NULL, key_type, &spec);
+        xfree (key_type);
+        if (err)
+          goto out;
+      }
 
-          err = key_secret_to_public (&key_public, spec, key_secret);
-          if (err)
-            goto out;
+      err = key_secret_to_public (&key_public, spec, key_secret);
+      if (err)
+        goto out;
 
-          gcry_sexp_release (key_secret);
-          key_secret = NULL;
+      gcry_sexp_release (key_secret);
+      key_secret = NULL;
 
-          err = ssh_send_key_public (key_blobs, key_public, NULL);
-          if (err)
-            goto out;
+      err = ssh_send_key_public (key_blobs, key_public, NULL);
+      if (err)
+        goto out;
 
-          gcry_sexp_release (key_public);
-          key_public = NULL;
+      gcry_sexp_release (key_public);
+      key_public = NULL;
 
-          key_counter++;
-        }
+      key_counter++;
     }
+  err = 0;
 
   ret = es_fseek (key_blobs, 0, SEEK_SET);
   if (ret)
@@ -2062,43 +2090,27 @@ ssh_handler_request_identities (ctrl_t ctrl,
     }
 
  out:
-
   /* Send response.  */
 
   gcry_sexp_release (key_secret);
   gcry_sexp_release (key_public);
 
-  if (! err)
+  if (!err)
     {
       ret_err = stream_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER);
-      if (ret_err)
-	goto leave;
-      ret_err = stream_write_uint32 (response, key_counter);
-      if (ret_err)
-	goto leave;
-      ret_err = stream_copy (response, key_blobs);
-      if (ret_err)
-	goto leave;
+      if (!ret_err)
+        ret_err = stream_write_uint32 (response, key_counter);
+      if (!ret_err)
+        ret_err = stream_copy (response, key_blobs);
     }
   else
     {
       ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
-      goto leave;
-    };
-
- leave:
-
-  if (key_blobs)
-    es_fclose (key_blobs);
-  if (dir)
-    closedir (dir);
+    }
 
+  es_fclose (key_blobs);
   close_control_file (cf);
-
-  xfree (key_directory);
-  xfree (key_path);
-  xfree (buffer);
-  xfree (key_type);
+  xfree (key_fname);
 
   return ret_err;
 }

commit 25fb53ab4ae7e1c098500229c776d29b82713a20
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Dec 10 16:39:12 2012 +0100

    ssh: Cleanup sshcontrol file access code.
    
    * agent/command-ssh.c (SSH_CONTROL_FILE_NAME): New macro to replace
    the direct use of the string.
    (struct control_file_s, control_file_t): New.
    (open_control_file, close_control_file): New.  Use them instead of
    using fopen/fclose directly.

diff --git a/agent/command-ssh.c b/agent/command-ssh.c
index ddf8e2c..435177d 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -1,5 +1,5 @@
 /* command-ssh.c - gpg-agent's ssh-agent emulation layer
- * Copyright (C) 2004, 2005, 2006, 2009 Free Software Foundation, Inc.
+ * Copyright (C) 2004, 2005, 2006, 2009, 2012 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -63,6 +63,8 @@
 #define SSH_DSA_SIGNATURE_ELEMS    2
 #define SPEC_FLAG_USE_PKCS1V2 (1 << 0)
 
+/* The name of the control file.  */
+#define SSH_CONTROL_FILE_NAME "sshcontrol"
 
 /* The blurb we put into the header of a newly created control file.  */
 static const char sshcontrolblurb[] =
@@ -79,7 +81,6 @@ static const char sshcontrolblurb[] =
 "\n";
 
 
-
 /* Macros.  */
 
 /* Return a new uint32 with b0 being the most significant byte and b3
@@ -162,6 +163,16 @@ typedef struct ssh_key_type_spec
 } ssh_key_type_spec_t;
 
 
+/* An object used to access the sshcontrol file.  */
+struct control_file_s
+{
+  char *fname;  /* Name of the file.  */
+  FILE *fp;     /* This is never NULL. */
+};
+typedef struct control_file_s *control_file_t;
+
+
+
 /* Prototypes.  */
 static gpg_error_t ssh_handler_request_identities (ctrl_t ctrl,
 						   estream_t request,
@@ -659,92 +670,124 @@ file_to_buffer (const char *filename, unsigned char **buffer, size_t *buffer_n)
 
 
 
-/* Open the ssh control file and create it if not available. With
+/* Open the ssh control file and create it if not available.  With
    APPEND passed as true the file will be opened in append mode,
-   otherwise in read only mode.  On success a file pointer is stored
-   at the address of R_FP. */
+   otherwise in read only mode.  On success 0 is returned and a new
+   control file object stored at R_CF.  On error an error code is
+   returned and NULL is stored at R_CF.  */
 static gpg_error_t
-open_control_file (FILE **r_fp, int append)
+open_control_file (control_file_t *r_cf, int append)
 {
   gpg_error_t err;
-  char *fname;
-  FILE *fp;
+  control_file_t cf;
+
+  cf = xtrycalloc (1, sizeof *cf);
+  if (!cf)
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
 
   /* Note: As soon as we start to use non blocking functions here
      (i.e. where Pth might switch threads) we need to employ a
      mutex.  */
-  *r_fp = NULL;
-  fname = make_filename (opt.homedir, "sshcontrol", NULL);
+  cf->fname = make_filename_try (opt.homedir, SSH_CONTROL_FILE_NAME, NULL);
+  if (!cf->fname)
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
   /* FIXME: With "a+" we are not able to check whether this will will
      be created and thus the blurb needs to be written first.  */
-  fp = fopen (fname, append? "a+":"r");
-  if (!fp && errno == ENOENT)
+  cf->fp = fopen (cf->fname, append? "a+":"r");
+  if (!cf->fp && errno == ENOENT)
     {
-      estream_t stream = es_fopen (fname, "wx,mode=-rw-r");
+      estream_t stream = es_fopen (cf->fname, "wx,mode=-rw-r");
       if (!stream)
         {
           err = gpg_error_from_syserror ();
-          log_error (_("can't create '%s': %s\n"), fname, gpg_strerror (err));
-          xfree (fname);
-          return err;
+          log_error (_("can't create `%s': %s\n"),
+                     cf->fname, gpg_strerror (err));
+          goto leave;
         }
       es_fputs (sshcontrolblurb, stream);
       es_fclose (stream);
-      fp = fopen (fname, append? "a+":"r");
+      cf->fp = fopen (cf->fname, append? "a+":"r");
     }
 
-  if (!fp)
+  if (!cf->fp)
     {
-      err = gpg_error (gpg_err_code_from_errno (errno));
-      log_error (_("can't open '%s': %s\n"), fname, gpg_strerror (err));
-      xfree (fname);
-      return err;
+      err = gpg_error_from_syserror ();
+      log_error (_("can't open `%s': %s\n"),
+                 cf->fname, gpg_strerror (err));
+      goto leave;
     }
 
-  *r_fp = fp;
+  err = 0;
 
-  return 0;
+ leave:
+  if (err && cf)
+    {
+      if (cf->fp)
+        fclose (cf->fp);
+      xfree (cf->fname);
+      xfree (cf);
+    }
+  else
+    *r_cf = cf;
+
+  return err;
+}
+
+
+static void
+close_control_file (control_file_t cf)
+{
+  if (!cf)
+    return;
+  fclose (cf->fp);
+  xfree (cf->fname);
+  xfree (cf);
 }
 
 
-/* Search the file at stream FP from the beginning until a matching
+/* Search the control file CF from the beginning until a matching
    HEXGRIP is found; return success in this case and store true at
    DISABLED if the found key has been disabled.  If R_TTL is not NULL
    a specified TTL for that key is stored there.  If R_CONFIRM is not
    NULL it is set to 1 if the key has the confirm flag set. */
 static gpg_error_t
-search_control_file (FILE *fp, const char *hexgrip,
+search_control_file (control_file_t cf, const char *hexgrip,
                      int *r_disabled, int *r_ttl, int *r_confirm)
 {
   int c, i, n;
   char *p, *pend, line[256];
   long ttl;
   int lnr = 0;
-  const char fname[] = "sshcontrol";
 
   assert (strlen (hexgrip) == 40 );
 
   if (r_confirm)
     *r_confirm = 0;
 
-  fseek (fp, 0, SEEK_SET);
-  clearerr (fp);
+  fseek (cf->fp, 0, SEEK_SET);
+  clearerr (cf->fp);
   *r_disabled = 0;
  next_line:
   do
     {
-      if (!fgets (line, DIM(line)-1, fp) )
+      if (!fgets (line, DIM(line)-1, cf->fp) )
         {
-          if (feof (fp))
+          if (feof (cf->fp))
             return gpg_error (GPG_ERR_EOF);
-          return gpg_error (gpg_err_code_from_errno (errno));
+          return gpg_error_from_syserror ();
         }
       lnr++;
 
       if (!*line || line[strlen(line)-1] != '\n')
         {
           /* Eat until end of line */
-          while ( (c=getc (fp)) != EOF && c != '\n')
+          while ( (c=getc (cf->fp)) != EOF && c != '\n')
             ;
           return gpg_error (*line? GPG_ERR_LINE_TOO_LONG
                                  : GPG_ERR_INCOMPLETE_LINE);
@@ -769,7 +812,7 @@ search_control_file (FILE *fp, const char *hexgrip,
       goto next_line;
   if (i != 40 || !(spacep (p) || *p == '\n'))
     {
-      log_error ("invalid formatted line in '%s', line %d\n", fname, lnr);
+      log_error ("invalid formatted line in `%s', line %d\n", cf->fname, lnr);
       return gpg_error (GPG_ERR_BAD_DATA);
     }
 
@@ -777,8 +820,8 @@ search_control_file (FILE *fp, const char *hexgrip,
   p = pend;
   if (!(spacep (p) || *p == '\n') || ttl < -1)
     {
-      log_error ("invalid TTL value in '%s', line %d; assuming 0\n",
-                 fname, lnr);
+      log_error ("invalid TTL value in `%s', line %d; assuming 0\n",
+                 cf->fname, lnr);
       ttl = 0;
     }
   if (r_ttl)
@@ -795,7 +838,7 @@ search_control_file (FILE *fp, const char *hexgrip,
       if (p[n] == '=')
         {
           log_error ("assigning a value to a flag is not yet supported; "
-                     "in '%s', line %d; flag ignored\n", fname, lnr);
+                     "in `%s', line %d; flag ignored\n", cf->fname, lnr);
           p++;
         }
       else if (n == 7 && !memcmp (p, "confirm", 7))
@@ -804,8 +847,8 @@ search_control_file (FILE *fp, const char *hexgrip,
             *r_confirm = 1;
         }
       else
-        log_error ("invalid flag '%.*s' in '%s', line %d; ignored\n",
-                   n, p, fname, lnr);
+        log_error ("invalid flag `%.*s' in `%s', line %d; ignored\n",
+                   n, p, cf->fname, lnr);
       p += n;
     }
 
@@ -824,16 +867,16 @@ add_control_entry (ctrl_t ctrl, const char *hexgrip, const char *fmtfpr,
                    int ttl, int confirm)
 {
   gpg_error_t err;
-  FILE *fp;
+  control_file_t cf;
   int disabled;
 
   (void)ctrl;
 
-  err = open_control_file (&fp, 1);
+  err = open_control_file (&cf, 1);
   if (err)
     return err;
 
-  err = search_control_file (fp, hexgrip, &disabled, NULL, NULL);
+  err = search_control_file (cf, hexgrip, &disabled, NULL, NULL);
   if (err && gpg_err_code(err) == GPG_ERR_EOF)
     {
       struct tm *tp;
@@ -842,15 +885,16 @@ add_control_entry (ctrl_t ctrl, const char *hexgrip, const char *fmtfpr,
       /* 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 (fp, ("# Key added on: %04d-%02d-%02d %02d:%02d:%02d\n"
-                    "# Fingerprint:  %s\n"
-                    "%s %d%s\n"),
+      fprintf (cf->fp,
+               ("# Key added on: %04d-%02d-%02d %02d:%02d:%02d\n"
+                "# Fingerprint:  %s\n"
+                "%s %d%s\n"),
                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":"");
 
     }
-  fclose (fp);
+  close_control_file (cf);
   return 0;
 }
 
@@ -859,20 +903,20 @@ add_control_entry (ctrl_t ctrl, const char *hexgrip, const char *fmtfpr,
 static int
 ttl_from_sshcontrol (const char *hexgrip)
 {
-  FILE *fp;
+  control_file_t cf;
   int disabled, ttl;
 
   if (!hexgrip || strlen (hexgrip) != 40)
     return 0;  /* Wrong input: Use global default.  */
 
-  if (open_control_file (&fp, 0))
+  if (open_control_file (&cf, 0))
     return 0; /* Error: Use the global default TTL.  */
 
-  if (search_control_file (fp, hexgrip, &disabled, &ttl, NULL)
+  if (search_control_file (cf, hexgrip, &disabled, &ttl, NULL)
       || disabled)
     ttl = 0;  /* Use the global default if not found or disabled.  */
 
-  fclose (fp);
+  close_control_file (cf);
 
   return ttl;
 }
@@ -882,21 +926,21 @@ ttl_from_sshcontrol (const char *hexgrip)
 static int
 confirm_flag_from_sshcontrol (const char *hexgrip)
 {
-  FILE *fp;
+  control_file_t cf;
   int disabled, confirm;
 
   if (!hexgrip || strlen (hexgrip) != 40)
     return 1;  /* Wrong input: Better ask for confirmation.  */
 
-  if (open_control_file (&fp, 0))
+  if (open_control_file (&cf, 0))
     return 1; /* Error: Better ask for confirmation.  */
 
-  if (search_control_file (fp, hexgrip, &disabled, NULL, &confirm)
+  if (search_control_file (cf, hexgrip, &disabled, NULL, &confirm)
       || disabled)
     confirm = 0;  /* If not found or disabled, there is no reason to
                      ask for confirmation.  */
 
-  fclose (fp);
+  close_control_file (cf);
 
   return confirm;
 }
@@ -1867,7 +1911,7 @@ ssh_handler_request_identities (ctrl_t ctrl,
   DIR *dir;
   gpg_error_t err;
   int ret;
-  FILE *ctrl_fp = NULL;
+  control_file_t cf = NULL;
   char *cardsn;
   gpg_error_t ret_err;
 
@@ -1942,10 +1986,10 @@ ssh_handler_request_identities (ctrl_t ctrl,
 
 
   /* Fixme: We should better iterate over the control file and check
-     whether the key file is there.  This is better in resepct to
-     performance if tehre are a lot of key sin our key storage. */
+     whether the key file is there.  This is better in respect to
+     performance if there are a lot of keys in our key storage. */
   /* FIXME: make sure that buffer gets deallocated properly.  */
-  err = open_control_file (&ctrl_fp, 0);
+  err = open_control_file (&cf, 0);
   if (err)
     goto out;
 
@@ -1963,7 +2007,7 @@ ssh_handler_request_identities (ctrl_t ctrl,
           hexgrip[40] = 0;
           if ( strlen (hexgrip) != 40 )
             continue;
-          if (search_control_file (ctrl_fp, hexgrip, &disabled, NULL, NULL)
+          if (search_control_file (cf, hexgrip, &disabled, NULL, NULL)
               || disabled)
             continue;
 
@@ -2049,8 +2093,7 @@ ssh_handler_request_identities (ctrl_t ctrl,
   if (dir)
     closedir (dir);
 
-  if (ctrl_fp)
-    fclose (ctrl_fp);
+  close_control_file (cf);
 
   xfree (key_directory);
   xfree (key_path);

commit 36ba7845995dd3caf8faeec3e09b3ffb879fc29b
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Dec 10 14:45:26 2012 +0100

    agent: Add envvar "gnupg_SSH_AUTH_SOCK_by"
    
    * agent/gpg-agent.c (main): Pass new envar gnupg_SSH_AUTH_SOCK_by to
    an invoked process.
    --
    
    This environment variable is useful for debugging if
    --use-standard-socket is used (which is the default since 2.1).
    Commonly you should have this in your init script (e.g. ~/.bashrc):
    
        unset GPG_AGENT_INFO
        unset SSH_AGENT_PID
        SSH_AUTH_SOCK="${HOME}/.gnupg/S.gpg-agent.ssh"
        export SSH_AUTH_SOCK
    
    The problem is that gpg-agent won't be able to override the
    SSH_AUTH_SOCK envvar if gpg-agent has been invoked as
    
      gpg-agent --enable-ssh-support --daemon /bin/bash
    
    To fix this you should instead use this code in the init script:
    
      unset GPG_AGENT_INFO
      unset SSH_AGENT_PID
      if [ ${gnupg_SSH_AUTH_SOCK_by:-0} -ne $$ ]; then
        export SSH_AUTH_SOCK="${HOME}/.gnupg/S.gpg-agent.ssh"
      fi
    
    This will work in all cases and thus allows to start gpg-agent for
    testing purposes with a different homedir and use this gpg-agent as an
    ssh-agent.  Example:
    
      GNUPGHOME=$(pwd) gpg-agent --enable-ssh-support --daemon /bin/bash
    
    gnupg_SSH_AUTH_SOCK_by is set to the PID of the exec-ed process and
    thus will work safely if called recursively.

diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index 32da578..4690114 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -1067,7 +1067,7 @@ main (int argc, char **argv )
         }
       else if (pid)
         { /* We are the parent */
-          char *infostr, *infostr_ssh_sock;
+          char *infostr, *infostr_ssh_sock, *infostr_ssh_valid;
 
           /* Close the socket FD. */
           close (fd);
@@ -1104,6 +1104,13 @@ main (int argc, char **argv )
 		  kill (pid, SIGTERM);
 		  exit (1);
 		}
+	      if (asprintf (&infostr_ssh_valid, "gnupg_SSH_AUTH_SOCK_by=%lu",
+			    (unsigned long)getpid()) < 0)
+		{
+		  log_error ("out of core\n");
+		  kill (pid, SIGTERM);
+		  exit (1);
+		}
 	    }
 
           *socket_name = 0; /* Don't let cleanup() remove the socket -
@@ -1142,7 +1149,8 @@ main (int argc, char **argv )
                   kill (pid, SIGTERM );
                   exit (1);
                 }
-              if (opt.ssh_support && putenv (infostr_ssh_sock))
+              if (opt.ssh_support && (putenv (infostr_ssh_sock)
+                                      || putenv (infostr_ssh_valid)))
                 {
                   log_error ("failed to set environment: %s\n",
                              strerror (errno) );
@@ -1189,6 +1197,7 @@ main (int argc, char **argv )
 	      if (opt.ssh_support)
 		{
 		  xfree (infostr_ssh_sock);
+		  xfree (infostr_ssh_valid);
 		}
               exit (0);
             }

commit ceab60b59d907354d323ace09d7b3f2d36d330fb
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Dec 10 09:40:40 2012 +0100

    config: Update npth.m4.
    
    * m4/npth.m4: Take from current npth master.

diff --git a/m4/npth.m4 b/m4/npth.m4
index 5b60e2c..17c2644 100644
--- a/m4/npth.m4
+++ b/m4/npth.m4
@@ -34,12 +34,12 @@ dnl Test for libnpth and define NPTH_CFLAGS and NPTH_LIBS.
 dnl
 AC_DEFUN([AM_PATH_NPTH],
 [ AC_REQUIRE([_AM_PATH_NPTH_CONFIG])dnl
-  tmp=ifelse([$1], ,1:0.0,$1)
+  tmp=ifelse([$1], ,1:0.91,$1)
   if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then
      req_npth_api=`echo "$tmp"     | sed 's/\(.*\):\(.*\)/\1/'`
      min_npth_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'`
   else
-     req_npth_api=0
+     req_npth_api=1
      min_npth_version="$tmp"
   fi
 
@@ -47,28 +47,40 @@ AC_DEFUN([AM_PATH_NPTH],
   ok=no
   if test "$NPTH_CONFIG" != "no" ; then
     req_major=`echo $min_npth_version | \
-               sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
     req_minor=`echo $min_npth_version | \
-               sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
-
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
     if test "$npth_version_major" -gt "$req_major"; then
         ok=yes
     else
         if test "$npth_version_major" -eq "$req_major"; then
-            if test "$npth_version_minor" -ge "$req_minor"; then
+            if test "$npth_version_minor" -gt "$req_minor"; then
                ok=yes
+            else
+               if test "$npth_version_minor" -eq "$req_minor"; then
+                  ok=yes
+               fi
             fi
         fi
     fi
   fi
   if test $ok = yes; then
+    AC_MSG_RESULT([yes ($npth_version)])
+  else
+    AC_MSG_RESULT(no)
+  fi
+  if test $ok = yes; then
      # If we have a recent NPTH, we should also check that the
      # API is compatible.
      if test "$req_npth_api" -gt 0 ; then
         tmp=`$NPTH_CONFIG --api-version 2>/dev/null || echo 0`
         if test "$tmp" -gt 0 ; then
-           if test "$req_npth_api" -ne "$tmp" ; then
+           AC_MSG_CHECKING([NPTH API version])
+           if test "$req_npth_api" -eq "$tmp" ; then
+             AC_MSG_RESULT([okay])
+           else
              ok=no
+             AC_MSG_RESULT([does not match. want=$req_npth_api got=$tmp])
            fi
         fi
      fi
@@ -76,12 +88,23 @@ AC_DEFUN([AM_PATH_NPTH],
   if test $ok = yes; then
     NPTH_CFLAGS=`$NPTH_CONFIG --cflags`
     NPTH_LIBS=`$NPTH_CONFIG --libs`
-    AC_MSG_RESULT(yes)
     ifelse([$2], , :, [$2])
+    npth_config_host=`$NPTH_CONFIG --host 2>/dev/null || echo none`
+    if test x"$npth_config_host" != xnone ; then
+      if test x"$npth_config_host" != x"$host" ; then
+        AC_MSG_WARN([[
+***
+*** The config script $NPTH_CONFIG was
+*** built for $npth_config_host and thus may not match the
+*** used host $host.
+*** You may want to use the configure option --with-npth-prefix
+*** to specify a matching config script.
+***]])
+      fi
+    fi
   else
     NPTH_CFLAGS=""
     NPTH_LIBS=""
-    AC_MSG_RESULT(no)
     ifelse([$3], , :, [$3])
   fi
   AC_SUBST(NPTH_CFLAGS)

-----------------------------------------------------------------------

Summary of changes:
 agent/command-ssh.c |  457 ++++++++++++++++++++++++++++----------------------
 agent/gpg-agent.c   |   13 ++-
 m4/npth.m4          |   41 ++++-
 3 files changed, 299 insertions(+), 212 deletions(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list