gpg: Print the actual used keyserver address.
authorWerner Koch <wk@gnupg.org>
Fri, 14 Mar 2014 15:12:54 +0000 (16:12 +0100)
committerWerner Koch <wk@gnupg.org>
Fri, 14 Mar 2014 15:12:54 +0000 (16:12 +0100)
* dirmngr/ks-engine-hkp.c (ks_hkp_search, ks_hkp_get): Print SOURCE
status lines.
* g10/call-dirmngr.c (ks_status_parm_s): New.
(ks_search_parm_s): Add field stparm.
(ks_status_cb): New.
(ks_search_data_cb): Send source to the data callback.
(gpg_dirmngr_ks_search): Change callback prototope to include the
SPECIAL arg.  Adjust all users.  Use ks_status_cb.
(gpg_dirmngr_ks_get): Add arg r_source and use ks_status_cb.
* g10/keyserver.c (search_line_handler): Adjust callback and print
"data source" disgnostic.
(keyserver_get): Print data source diagnostic.
--

It has often been requested that the actually used IP of a keyservers
is shown in with gpg --recv-key and --search-key.  This is helpful if
the keyserver is actually a pool of keyservers.  This patch does this.

common/stringhelp.c
dirmngr/ks-engine-hkp.c
g10/call-dirmngr.c
g10/call-dirmngr.h
g10/keyserver.c

index 2d2b412..7cbf82c 100644 (file)
@@ -77,7 +77,7 @@ change_slashes (char *name)
 
 
 /*
- * Check whether STRINGS starts with KEYWORD.  The keyword is
+ * Check whether STRING starts with KEYWORD.  The keyword is
  * delimited by end of string, a space or a tab.  Returns NULL if not
  * found or a pointer into STRING to the next non-space character
  * after the KEYWORD (which may be end of string).
index 28b05e9..5c45435 100644 (file)
@@ -454,8 +454,7 @@ mark_host_dead (const char *name)
 
 
 /* Mark a host in the hosttable as dead or - if ALIVE is true - as
-   alive.  If the host NAME does not exist a warning status message is
-   printed.  */
+   alive.  */
 gpg_error_t
 ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
 {
@@ -974,6 +973,10 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
   if (err)
     goto leave;
 
+  err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
+  if (err)
+    goto leave;
+
   /* Peek at the response.  */
   {
     int c = es_getc (fp);
@@ -1082,6 +1085,10 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
   if (err)
     goto leave;
 
+  err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
+  if (err)
+    goto leave;
+
   /* Return the read stream and close the HTTP context.  */
   *r_fp = fp;
   fp = NULL;
index 9935333..73f829e 100644 (file)
 #include "call-dirmngr.h"
 
 
+/* Parameter structure used to gather status info.  */
+struct ks_status_parm_s
+{
+  char *source;
+};
+
+
 /* Parameter structure used with the KS_SEARCH command.  */
 struct ks_search_parm_s
 {
@@ -47,8 +54,9 @@ struct ks_search_parm_s
   membuf_t saveddata;   /* Buffer to build complete lines.  */
   char *helpbuf;        /* NULL or malloced buffer.  */
   size_t helpbufsize;   /* Allocated size of HELPBUF.  */
-  gpg_error_t (*data_cb)(void*, char*);  /* Callback.  */
+  gpg_error_t (*data_cb)(void*, int, char*);  /* Callback.  */
   void *data_cb_value;  /* First argument for DATA_CB.  */
+  struct ks_status_parm_s *stparm; /* Link to the status parameter.  */
 };
 
 
@@ -235,6 +243,29 @@ close_context (ctrl_t ctrl, assuan_context_t ctx)
 
 
 \f
+/* Status callback for ks_get and ks_search.  */
+static gpg_error_t
+ks_status_cb (void *opaque, const char *line)
+{
+  struct ks_status_parm_s *parm = opaque;
+  gpg_error_t err = 0;
+  const char *s;
+
+  if ((s = has_leading_keyword (line, "SOURCE")))
+    {
+      if (!parm->source)
+        {
+          parm->source = xtrystrdup (s);
+          if (!parm->source)
+            err = gpg_error_from_syserror ();
+        }
+    }
+
+  return err;
+}
+
+
+\f
 /* Data callback for the KS_SEARCH command. */
 static gpg_error_t
 ks_search_data_cb (void *opaque, const void *data, size_t datalen)
@@ -248,6 +279,22 @@ ks_search_data_cb (void *opaque, const void *data, size_t datalen)
   if (parm->lasterr)
     return 0;
 
+  if (parm->stparm->source)
+    {
+      err = parm->data_cb (parm->data_cb_value, 1, parm->stparm->source);
+      if (err)
+        {
+          parm->lasterr = err;
+          return err;
+        }
+      /* Clear it so that we won't get back here unless the server
+         accidentally sends a second source status line.  Note that
+         will not see all accidentally sent source lines because it
+         depends on whether data lines have been send in between.  */
+      xfree (parm->stparm->source);
+      parm->stparm->source = NULL;
+    }
+
   if (!data)
     return 0;  /* Ignore END commands.  */
 
@@ -270,7 +317,7 @@ ks_search_data_cb (void *opaque, const void *data, size_t datalen)
           fixedbuf[linelen] = 0;
           if (linelen && fixedbuf[linelen-1] == '\r')
             fixedbuf[linelen-1] = 0;
-          err = parm->data_cb (parm->data_cb_value, fixedbuf);
+          err = parm->data_cb (parm->data_cb_value, 0, fixedbuf);
         }
       else
         {
@@ -289,7 +336,7 @@ ks_search_data_cb (void *opaque, const void *data, size_t datalen)
           parm->helpbuf[linelen] = 0;
           if (linelen && parm->helpbuf[linelen-1] == '\r')
             parm->helpbuf[linelen-1] = 0;
-          err = parm->data_cb (parm->data_cb_value, parm->helpbuf);
+          err = parm->data_cb (parm->data_cb_value, 0, parm->helpbuf);
         }
       if (err)
         parm->lasterr = err;
@@ -306,17 +353,18 @@ ks_search_data_cb (void *opaque, const void *data, size_t datalen)
 
 /* Run the KS_SEARCH command using the search string SEARCHSTR.  All
    data lines are passed to the CB function.  That function is called
-   with CB_VALUE as its first argument and the decoded data line as
-   second argument.  The callback function may modify the data line
-   and it is guaranteed that this data line is a complete line with a
-   terminating 0 character but without the linefeed.  NULL is passed
-   to the callback to indicate EOF.  */
+   with CB_VALUE as its first argument, a 0 as second argument, and
+   the decoded data line as third argument.  The callback function may
+   modify the data line and it is guaranteed that this data line is a
+   complete line with a terminating 0 character but without the
+   linefeed.  NULL is passed to the callback to indicate EOF.  */
 gpg_error_t
 gpg_dirmngr_ks_search (ctrl_t ctrl, const char *searchstr,
-                       gpg_error_t (*cb)(void*, char *), void *cb_value)
+                       gpg_error_t (*cb)(void*, int, char *), void *cb_value)
 {
   gpg_error_t err;
   assuan_context_t ctx;
+  struct ks_status_parm_s stparm;
   struct ks_search_parm_s parm;
   char line[ASSUAN_LINELENGTH];
 
@@ -336,18 +384,21 @@ gpg_dirmngr_ks_search (ctrl_t ctrl, const char *searchstr,
     xfree (escsearchstr);
   }
 
+  memset (&stparm, 0, sizeof stparm);
   memset (&parm, 0, sizeof parm);
   init_membuf (&parm.saveddata, 1024);
   parm.data_cb = cb;
   parm.data_cb_value = cb_value;
+  parm.stparm = &stparm;
 
   err = assuan_transact (ctx, line, ks_search_data_cb, &parm,
-                        NULL, NULL, NULL, NULL);
+                        NULL, NULL, ks_status_cb, &stparm);
   if (!err)
-    err = cb (cb_value, NULL);  /* Send EOF.  */
+    err = cb (cb_value, 0, NULL);  /* Send EOF.  */
 
   xfree (get_membuf (&parm.saveddata, NULL));
   xfree (parm.helpbuf);
+  xfree (stparm.source);
 
   close_context (ctrl, ctx);
   return err;
@@ -382,24 +433,32 @@ ks_get_data_cb (void *opaque, const void *data, size_t datalen)
    don't need to escape the patterns before sending them to the
    server.
 
+   If R_SOURCE is not NULL the source of the data is stored as a
+   malloced string there.  If a source is not known NULL is stored.
+
    If there are too many patterns the function returns an error.  That
    could be fixed by issuing several search commands or by
    implementing a different interface.  However with long keyids we
    are able to ask for (1000-10-1)/(2+8+1) = 90 keys at once.  */
 gpg_error_t
-gpg_dirmngr_ks_get (ctrl_t ctrl, char **pattern, estream_t *r_fp)
+gpg_dirmngr_ks_get (ctrl_t ctrl, char **pattern,
+                    estream_t *r_fp, char **r_source)
 {
   gpg_error_t err;
   assuan_context_t ctx;
+  struct ks_status_parm_s stparm;
   struct ks_get_parm_s parm;
   char *line = NULL;
   size_t linelen;
   membuf_t mb;
   int idx;
 
+  memset (&stparm, 0, sizeof stparm);
   memset (&parm, 0, sizeof parm);
 
   *r_fp = NULL;
+  if (r_source)
+    *r_source = NULL;
 
   err = open_context (ctrl, &ctx);
   if (err)
@@ -433,7 +492,7 @@ gpg_dirmngr_ks_get (ctrl_t ctrl, char **pattern, estream_t *r_fp)
       goto leave;
     }
   err = assuan_transact (ctx, line, ks_get_data_cb, &parm,
-                         NULL, NULL, NULL, NULL);
+                         NULL, NULL, ks_status_cb, &stparm);
   if (err)
     goto leave;
 
@@ -441,8 +500,15 @@ gpg_dirmngr_ks_get (ctrl_t ctrl, char **pattern, estream_t *r_fp)
   *r_fp = parm.memfp;
   parm.memfp = NULL;
 
+  if (r_source)
+    {
+      *r_source = stparm.source;
+      stparm.source = NULL;
+    }
+
  leave:
   es_fclose (parm.memfp);
+  xfree (stparm.source);
   xfree (line);
   close_context (ctrl, ctx);
   return err;
index 933303d..481b948 100644 (file)
 void gpg_dirmngr_deinit_session_data (ctrl_t ctrl);
 
 gpg_error_t gpg_dirmngr_ks_search (ctrl_t ctrl, const char *searchstr,
-                                   gpg_error_t (*cb)(void*, char *),
+                                   gpg_error_t (*cb)(void*, int, char *),
                                    void *cb_value);
-gpg_error_t gpg_dirmngr_ks_get (ctrl_t ctrl, char *pattern[], estream_t *r_fp);
+gpg_error_t gpg_dirmngr_ks_get (ctrl_t ctrl, char *pattern[],
+                                estream_t *r_fp, char **r_source);
 gpg_error_t gpg_dirmngr_ks_fetch (ctrl_t ctrl,
                                   const char *url, estream_t *r_fp);
 gpg_error_t gpg_dirmngr_ks_put (ctrl_t ctrl, void *data, size_t datalen,
index b8ab81e..3a3bc40 100644 (file)
@@ -831,17 +831,29 @@ show_prompt (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int numdesc,
 
 
 /* This is a callback used by call-dirmngr.c to process the result of
-   KS_SEARCH command.  LINE is the actual data line received with all
-   escaping removed and guaranteed to be exactly one line with
-   stripped LF; an EOF is indicated by LINE passed as NULL.  LINE may
-   be modified after return.  */
+   KS_SEARCH command.  If SPECIAL is 0, LINE is the actual data line
+   received with all escaping removed and guaranteed to be exactly one
+   line with stripped LF; an EOF is indicated by LINE passed as NULL.
+   If special is 1, the line conatins the source of the information
+   (usually an URL).  LINE may be modified after return.  */
 static gpg_error_t
-search_line_handler (void *opaque, char *line)
+search_line_handler (void *opaque, int special, char *line)
 {
   struct search_line_handler_parm_s *parm = opaque;
   gpg_error_t err = 0;
   struct keyrec *keyrec;
 
+  if (special == 1)
+    {
+      log_info ("data source: %s\n", line);
+      return 0;
+    }
+  else if (special)
+    {
+      log_debug ("unknown value %d for special search callback", special);
+      return 0;
+    }
+
   if (parm->eof_seen && line)
     {
       log_debug ("ooops: unexpected data after EOF\n");
@@ -1478,6 +1490,7 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
   char **pattern;
   int idx, npat;
   estream_t datastream;
+  char *source = NULL;
 
   /* Create an array filled with a search pattern for each key.  The
      array is delimited by a NULL entry.  */
@@ -1561,10 +1574,13 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
     }
 
 
-  err = gpg_dirmngr_ks_get (ctrl, pattern, &datastream);
+  err = gpg_dirmngr_ks_get (ctrl, pattern, &datastream, &source);
   for (idx=0; idx < npat; idx++)
     xfree (pattern[idx]);
   xfree (pattern);
+  if (opt.verbose)
+    log_info ("data source: %s\n", source);
+
   if (!err)
     {
       void *stats_handle;
@@ -1590,7 +1606,7 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
       import_release_stats_handle (stats_handle);
     }
   es_fclose (datastream);
-
+  xfree (source);
 
   return err;
 }