chiark / gitweb /
dirmngr: New option --no-use-tor and internal changes.
[gnupg2.git] / dirmngr / ks-engine-hkp.c
index 45965cecc79b12e0cb347c8ee9297f30c0ac94e3..be8b08333d146967ac5a47e641ee6366c929f4eb 100644 (file)
@@ -203,31 +203,51 @@ host_in_pool_p (int *pool, int tblidx)
 }
 
 
+static int
+host_is_alive (hostinfo_t hi, time_t curtime)
+{
+  if (!hi)
+    return 0;
+  if (!hi->dead)
+    return 1;
+  if (!hi->died_at)
+    return 0; /* manually marked dead */
+  if (hi->died_at + RESURRECT_INTERVAL <= curtime
+      || hi->died_at > curtime)
+    {
+      hi->dead = 0;
+      log_info ("resurrected host '%s'", hi->name);
+      return 1;
+    }
+  return 0;
+}
+
 /* Select a random host.  Consult TABLE which indices into the global
    hosttable.  Returns index into TABLE or -1 if no host could be
    selected.  */
 static int
 select_random_host (int *table)
 {
-  int *tbl;
-  size_t tblsize;
+  int *tbl = NULL;
+  size_t tblsize = 0;
   int pidx, idx;
+  time_t curtime;
 
+  curtime = gnupg_get_time ();
   /* We create a new table so that we randomly select only from
      currently alive hosts.  */
-  for (idx=0, tblsize=0; (pidx = table[idx]) != -1; idx++)
-    if (hosttable[pidx] && !hosttable[pidx]->dead)
-      tblsize++;
+  for (idx=0; (pidx = table[idx]) != -1; idx++)
+    if (hosttable[pidx] && host_is_alive (hosttable[pidx], curtime))
+      {
+        tblsize++;
+        tbl = xtryrealloc(tbl, tblsize * sizeof *tbl);
+        if (!tbl)
+          return -1; /* memory allocation failed! */
+        tbl[tblsize-1] = pidx;
+      }
   if (!tblsize)
     return -1; /* No hosts.  */
 
-  tbl = xtrymalloc (tblsize * sizeof *tbl);
-  if (!tbl)
-    return -1;
-  for (idx=0, tblsize=0; (pidx = table[idx]) != -1; idx++)
-    if (hosttable[pidx] && !hosttable[pidx]->dead)
-      tbl[tblsize++] = pidx;
-
   if (tblsize == 1)  /* Save a get_uint_nonce.  */
     pidx = tbl[0];
   else
@@ -258,6 +278,31 @@ arecords_is_pool (dns_addrinfo_t aibuf)
 }
 
 
+/* Print a warninng iff Tor is not running but Tor has been requested.
+ * Also return true if it is not running.  */
+static int
+tor_not_running_p (ctrl_t ctrl)
+{
+  assuan_fd_t sock;
+
+  if (!dirmngr_use_tor ())
+    return 0;
+
+  sock = assuan_sock_connect_byname (NULL, 0, 0, NULL, ASSUAN_SOCK_TOR);
+  if (sock != ASSUAN_INVALID_FD)
+    {
+      assuan_sock_close (sock);
+      return 0;
+    }
+
+  log_info ("(it seems Tor is not running)\n");
+  dirmngr_status (ctrl, "WARNING", "tor_not_running 0",
+                  "Tor is enabled but the local Tor daemon"
+                  " seems to be down", NULL);
+  return 1;
+}
+
+
 /* Add the host AI under the NAME into the HOSTTABLE.  If PORT is not
    zero, it specifies which port to use to talk to the host.  If NAME
    specifies a pool (as indicated by IS_POOL), update the given
@@ -396,6 +441,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
   gpg_error_t err = 0;
   hostinfo_t hi;
   int idx;
+  time_t curtime;
 
   *r_host = NULL;
   if (r_httpflags)
@@ -454,6 +500,8 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
           if (err)
             {
               xfree (reftbl);
+              if (gpg_err_code (err) == GPG_ERR_ECONNREFUSED)
+                tor_not_running_p (ctrl);
               return err;
             }
 
@@ -505,6 +553,8 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
             {
               if (ai->family != AF_INET && ai->family != AF_INET6)
                 continue;
+              if (opt.disable_ipv4 && ai->family == AF_INET)
+                continue;
               dirmngr_tick (ctrl);
 
               add_host (name, is_pool, ai, 0, reftbl, reftblsize, &refidx);
@@ -532,6 +582,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
         xfree (reftbl);
     }
 
+  curtime = gnupg_get_time ();
   hi = hosttable[idx];
   if (hi->pool)
     {
@@ -548,7 +599,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
       if (force_reselect)
         hi->poolidx = -1;
       else if (hi->poolidx >= 0 && hi->poolidx < hosttable_size
-               && hosttable[hi->poolidx] && hosttable[hi->poolidx]->dead)
+               && hosttable[hi->poolidx] && !host_is_alive (hosttable[hi->poolidx], curtime))
         hi->poolidx = -1;
 
       /* Select a host if needed.  */
@@ -585,7 +636,8 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
         {
           for (ai = aibuf; ai; ai = ai->next)
             {
-              if (ai->family == AF_INET6 || ai->family == AF_INET)
+              if (ai->family == AF_INET6
+                  || (!opt.disable_ipv4 && ai->family == AF_INET))
                 {
                   err = resolve_dns_addr (ai->addr, ai->addrlen, 0, &host);
                   if (!err)
@@ -600,7 +652,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
       free_dns_addrinfo (aibuf);
     }
 
-  if (hi->dead)
+  if (!host_is_alive (hi, curtime))
     {
       log_error ("host '%s' marked as dead\n", hi->name);
       if (r_httphost)
@@ -705,7 +757,8 @@ ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
 {
   gpg_error_t err = 0;
   hostinfo_t hi, hi2;
-  int idx, idx2, idx3, n;
+  int idx, idx2, idx3, n, is_alive;
+  time_t curtime;
 
   if (!name || !*name || !strcmp (name, "localhost"))
     return 0;
@@ -714,13 +767,15 @@ ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
   if (idx == -1)
     return gpg_error (GPG_ERR_NOT_FOUND);
 
+  curtime = gnupg_get_time ();
   hi = hosttable[idx];
-  if (alive && hi->dead)
+  is_alive = host_is_alive (hi, curtime);
+  if (alive && !is_alive)
     {
       hi->dead = 0;
       err = ks_printf_help (ctrl, "marking '%s' as alive", name);
     }
-  else if (!alive && !hi->dead)
+  else if (!alive && is_alive)
     {
       hi->dead = 1;
       hi->died_at = 0; /* Manually set dead.  */
@@ -752,14 +807,15 @@ ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
 
           hi2 = hosttable[n];
           if (!hi2)
-            ;
-          else if (alive && hi2->dead)
+            continue;
+          is_alive = host_is_alive (hi2, curtime);
+          if (alive && !is_alive)
             {
               hi2->dead = 0;
               err = ks_printf_help (ctrl, "marking '%s' as alive",
                                     hi2->name);
             }
-          else if (!alive && !hi2->dead)
+          else if (!alive && is_alive)
             {
               hi2->dead = 1;
               hi2->died_at = 0; /* Manually set dead. */
@@ -975,34 +1031,6 @@ ks_hkp_resolve (ctrl_t ctrl, parsed_uri_t uri)
 }
 
 
-/* Housekeeping function called from the housekeeping thread.  It is
-   used to mark dead hosts alive so that they may be tried again after
-   some time.  */
-void
-ks_hkp_housekeeping (time_t curtime)
-{
-  int idx;
-  hostinfo_t hi;
-
-  for (idx=0; idx < hosttable_size; idx++)
-    {
-      hi = hosttable[idx];
-      if (!hi)
-        continue;
-      if (!hi->dead)
-        continue;
-      if (!hi->died_at)
-        continue; /* Do not resurrect manually shot hosts.  */
-      if (hi->died_at + RESURRECT_INTERVAL <= curtime
-          || hi->died_at > curtime)
-        {
-          hi->dead = 0;
-          log_info ("resurrected host '%s'", hi->name);
-        }
-    }
-}
-
-
 /* Reload (SIGHUP) action for this module.  We mark all host alive
  * even those which have been manually shot.  */
 void
@@ -1060,7 +1088,8 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
                    /* fixme: AUTH */ NULL,
                    (httpflags
                     |(opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
-                    |(opt.use_tor? HTTP_FLAG_FORCE_TOR:0)),
+                    |(dirmngr_use_tor ()? HTTP_FLAG_FORCE_TOR:0)
+                    |(opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)),
                    ctrl->http_proxy,
                    session,
                    NULL,
@@ -1178,13 +1207,13 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
 }
 
 
-/* Helper to evaluate the error code ERR form a send_request() call
+/* Helper to evaluate the error code ERR from a send_request() call
    with REQUEST.  The function returns true if the caller shall try
    again.  TRIES_LEFT points to a variable to track the number of
    retries; this function decrements it and won't return true if it is
    down to zero. */
 static int
-handle_send_request_error (gpg_error_t err, const char *request,
+handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
                            unsigned int *tries_left)
 {
   int retry = 0;
@@ -1195,16 +1224,9 @@ handle_send_request_error (gpg_error_t err, const char *request,
   switch (gpg_err_code (err))
     {
     case GPG_ERR_ECONNREFUSED:
-      if (opt.use_tor)
-        {
-          assuan_fd_t sock;
-
-          sock = assuan_sock_connect_byname (NULL, 0, 0, NULL, ASSUAN_SOCK_TOR);
-          if (sock == ASSUAN_INVALID_FD)
-            log_info ("(it seems Tor is not running)\n");
-          else
-            assuan_sock_close (sock);
-        }
+      if (tor_not_running_p (ctrl))
+        break; /* A retry does not make sense.  */
+      /* Okay: Tor is up or --use-tor is not used.  */
       /*FALLTHRU*/
     case GPG_ERR_ENETUNREACH:
     case GPG_ERR_ENETDOWN:
@@ -1222,6 +1244,16 @@ handle_send_request_error (gpg_error_t err, const char *request,
         }
       break;
 
+    case GPG_ERR_EACCES:
+      if (dirmngr_use_tor ())
+        {
+          log_info ("(Tor configuration problem)\n");
+          dirmngr_status (ctrl, "WARNING", "tor_config_problem 0",
+                          "Please check that the \"SocksPort\" flag "
+                          "\"IPv6Traffic\" is set in torrc", NULL);
+        }
+      break;
+
     default:
       break;
     }
@@ -1332,7 +1364,7 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
   /* Send the request.  */
   err = send_request (ctrl, request, hostport, httphost, httpflags,
                       NULL, NULL, &fp, r_http_status);
-  if (handle_send_request_error (err, request, &tries))
+  if (handle_send_request_error (ctrl, err, request, &tries))
     {
       reselect = 1;
       goto again;
@@ -1466,7 +1498,7 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
   /* Send the request.  */
   err = send_request (ctrl, request, hostport, httphost, httpflags,
                       NULL, NULL, &fp, NULL);
-  if (handle_send_request_error (err, request, &tries))
+  if (handle_send_request_error (ctrl, err, request, &tries))
     {
       reselect = 1;
       goto again;
@@ -1575,7 +1607,7 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
   /* Send the request.  */
   err = send_request (ctrl, request, hostport, httphost, 0,
                       put_post_cb, &parm, &fp, NULL);
-  if (handle_send_request_error (err, request, &tries))
+  if (handle_send_request_error (ctrl, err, request, &tries))
     {
       reselect = 1;
       goto again;