gpg: Keep a lock during the read-update/insert cycle in import.
[gnupg.git] / g10 / call-dirmngr.c
index f739833..9bc90fb 100644 (file)
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 
 #include "gpg.h"
 #include <assuan.h>
-#include "util.h"
-#include "membuf.h"
+#include "../common/util.h"
+#include "../common/membuf.h"
 #include "options.h"
-#include "i18n.h"
-#include "asshelp.h"
-#include "keyserver.h"
-#include "status.h"
+#include "../common/i18n.h"
+#include "../common/asshelp.h"
+#include "../common/keyserver.h"
+#include "../common/status.h"
 #include "call-dirmngr.h"
 
 
-/* Parameter structure used to gather status info.  */
+/* Parameter structure used to gather status info.  Note that it is
+ * also used for WKD requests.  */
 struct ks_status_parm_s
 {
   const char *keyword; /* Look for this keyword or NULL for "SOURCE". */
@@ -145,7 +146,7 @@ warn_version_mismatch (assuan_context_t ctx, const char *servername)
   if (err)
     log_error (_("error getting version from '%s': %s\n"),
                servername, gpg_strerror (err));
-  else if (!compare_version_strings (serverversion, myversion))
+  else if (compare_version_strings (serverversion, myversion) < 0)
     {
       char *warn;
 
@@ -156,6 +157,14 @@ warn_version_mismatch (assuan_context_t ctx, const char *servername)
       else
         {
           log_info (_("WARNING: %s\n"), warn);
+          if (!opt.quiet)
+            {
+              log_info (_("Note: Outdated servers may lack important"
+                          " security fixes.\n"));
+              log_info (_("Note: Use the command \"%s\" to restart them.\n"),
+                        "gpgconf --kill all");
+            }
+
           write_status_strings (STATUS_WARNING, "server_version_mismatch 0",
                                 " ", warn, NULL);
           xfree (warn);
@@ -175,6 +184,10 @@ create_context (ctrl_t ctrl, assuan_context_t *r_ctx)
   assuan_context_t ctx;
 
   *r_ctx = NULL;
+
+  if (opt.disable_dirmngr)
+    return gpg_error (GPG_ERR_NO_DIRMNGR);
+
   err = start_new_dirmngr (&ctx,
                            GPG_ERR_SOURCE_DEFAULT,
                            opt.dirmngr_program,
@@ -368,16 +381,18 @@ clear_context_flags (ctrl_t ctrl, assuan_context_t ctx)
 
 
 \f
-/* Status callback for ks_list, ks_get and ks_search.  */
+/* Status callback for ks_list, ks_get, ks_search, and wkd_get  */
 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;
+  const char *s, *s2;
+  const char *warn;
 
   if ((s = has_leading_keyword (line, parm->keyword? parm->keyword : "SOURCE")))
     {
+      /* Note that the arg for "S SOURCE" is the URL of a keyserver.  */
       if (!parm->source)
         {
           parm->source = xtrystrdup (s);
@@ -385,6 +400,29 @@ ks_status_cb (void *opaque, const char *line)
             err = gpg_error_from_syserror ();
         }
     }
+  else if ((s = has_leading_keyword (line, "WARNING")))
+    {
+      if ((s2 = has_leading_keyword (s, "tor_not_running")))
+        warn = _("Tor is not running");
+      else if ((s2 = has_leading_keyword (s, "tor_config_problem")))
+        warn = _("Tor is not properly configured");
+      else
+        warn = NULL;
+
+      if (warn)
+        {
+          log_info (_("WARNING: %s\n"), warn);
+          if (s2)
+            {
+              while (*s2 && !spacep (s2))
+                s2++;
+              while (*s2 && spacep (s2))
+                s2++;
+              if (*s2)
+                print_further_info ("%s", s2);
+            }
+        }
+    }
 
   return err;
 }
@@ -963,9 +1001,9 @@ ks_put_inq_cb (void *opaque, const char *line)
                    int i;
 
                    i = 0;
-                   if (uid->is_revoked)
+                   if (uid->flags.revoked)
                      validity[i ++] = 'r';
-                   if (uid->is_expired)
+                   if (uid->flags.expired)
                      validity[i ++] = 'e';
                    validity[i] = '\0';
 
@@ -1044,7 +1082,7 @@ gpg_dirmngr_ks_put (ctrl_t ctrl, void *data, size_t datalen, kbnode_t keyblock)
   /* We are going to parse the keyblock, thus we better make sure the
      all information is readily available.  */
   if (keyblock)
-    merge_keys_and_selfsig (keyblock);
+    merge_keys_and_selfsig (ctrl, keyblock);
 
   err = open_context (ctrl, &ctx);
   if (err)
@@ -1292,17 +1330,24 @@ gpg_dirmngr_get_pka (ctrl_t ctrl, const char *userid,
 \f
 /* Ask the dirmngr to retrieve a key via the Web Key Directory
  * protocol.  If QUICK is set the dirmngr is advised to use a shorter
- * timeout.  On success a new estream with the key is stored at R_KEY.
+ * timeout.  On success a new estream with the key stored at R_KEY and the
+ * url of the lookup (if any) stored at R_URL.  Note that
  */
 gpg_error_t
-gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, int quick, estream_t *r_key)
+gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, int quick,
+                     estream_t *r_key, char **r_url)
 {
   gpg_error_t err;
   assuan_context_t ctx;
-  struct dns_cert_parm_s parm;
+  struct ks_status_parm_s stparm = { NULL };
+  struct dns_cert_parm_s parm = { NULL };
   char *line = NULL;
 
-  memset (&parm, 0, sizeof parm);
+  if (r_key)
+    *r_key = NULL;
+
+  if (r_url)
+    *r_url = NULL;
 
   err = open_context (ctrl, &ctx);
   if (err)
@@ -1327,7 +1372,7 @@ gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, int quick, estream_t *r_key)
       goto leave;
     }
   err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
-                         NULL, NULL, NULL, &parm);
+                         NULL, NULL, ks_status_cb, &stparm);
   if (err)
     goto leave;
 
@@ -1338,7 +1383,14 @@ gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, int quick, estream_t *r_key)
       parm.memfp = NULL;
     }
 
+  if (r_url)
+    {
+      *r_url = stparm.source;
+      stparm.source = NULL;
+    }
+
  leave:
+  xfree (stparm.source);
   xfree (parm.fpr);
   xfree (parm.url);
   es_fclose (parm.memfp);