Replace use of opt.homedir by accessor functions.
[gnupg.git] / dirmngr / http.c
index d623f7e..f0fcd0d 100644 (file)
@@ -560,9 +560,14 @@ http_session_release (http_session_t sess)
 
 
 /* Create a new session object which is currently used to enable TLS
-   support.  It may eventually allow reusing existing connections.  */
+ * support.  It may eventually allow reusing existing connections.
+ * Valid values for FLAGS are:
+ *   HTTP_FLAG_TRUST_DEF - Use the CAs set with http_register_tls_ca
+ *   HTTP_FLAG_TRUST_SYS - Also use the CAs defined by the system
+ */
 gpg_error_t
-http_session_new (http_session_t *r_session, const char *tls_priority)
+http_session_new (http_session_t *r_session, const char *tls_priority,
+                  const char *intended_hostname, unsigned int flags)
 {
   gpg_error_t err;
   http_session_t sess;
@@ -600,14 +605,62 @@ http_session_new (http_session_t *r_session, const char *tls_priority)
         goto leave;
       }
 
-    for (sl = tls_ca_certlist; sl; sl = sl->next)
+    /* If the user has not specified a CA list, and they are looking
+     * for the hkps pool from sks-keyservers.net, then default to
+     * Kristian's certificate authority:  */
+    if (!tls_ca_certlist
+        && intended_hostname
+        && !ascii_strcasecmp (intended_hostname,
+                              "hkps.pool.sks-keyservers.net"))
       {
-        rc = gnutls_certificate_set_x509_trust_file
-          (sess->certcred, sl->d,
-           (sl->flags & 1)? GNUTLS_X509_FMT_PEM : GNUTLS_X509_FMT_DER);
+        char *pemname = make_filename_try (gnupg_datadir (),
+                                           "sks-keyservers.netCA.pem", NULL);
+        if (!pemname)
+          {
+            err = gpg_error_from_syserror ();
+            log_error ("setting CA from file '%s' failed: %s\n",
+                       pemname, gpg_strerror (err));
+          }
+        else
+          {
+            rc = gnutls_certificate_set_x509_trust_file
+              (sess->certcred, pemname, GNUTLS_X509_FMT_PEM);
+            if (rc < 0)
+              log_info ("setting CA from file '%s' failed: %s\n",
+                        pemname, gnutls_strerror (rc));
+            xfree (pemname);
+          }
+      }
+
+    /* Add configured certificates to the session.  */
+    if ((flags & HTTP_FLAG_TRUST_DEF))
+      {
+        for (sl = tls_ca_certlist; sl; sl = sl->next)
+          {
+            rc = gnutls_certificate_set_x509_trust_file
+              (sess->certcred, sl->d,
+               (sl->flags & 1)? GNUTLS_X509_FMT_PEM : GNUTLS_X509_FMT_DER);
+            if (rc < 0)
+              log_info ("setting CA from file '%s' failed: %s\n",
+                        sl->d, gnutls_strerror (rc));
+          }
+      }
+
+    /* Add system certificates to the session.  */
+    if ((flags & HTTP_FLAG_TRUST_SYS))
+      {
+#if GNUTLS_VERSION_NUMBER >= 0x030014
+        static int shown;
+
+        rc = gnutls_certificate_set_x509_system_trust (sess->certcred);
         if (rc < 0)
-          log_info ("setting CA from file '%s' failed: %s\n",
-                    sl->d, gnutls_strerror (rc));
+          log_info ("setting system CAs failed: %s\n", gnutls_strerror (rc));
+        else if (!shown)
+          {
+            shown = 1;
+            log_info ("number of system provided CAs: %d\n", rc);
+          }
+#endif /* gnutls >= 3.0.20 */
       }
 
     rc = gnutls_init (&sess->tls_session, GNUTLS_CLIENT);
@@ -753,9 +806,7 @@ http_raw_connect (http_t *r_hd, const char *server, unsigned short port,
     {
       int mode;
 
-#if ASSUAN_VERSION_NUMBER >= 0x020300 /* >= 2.3.0 */
       if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
-#endif
         {
           log_error ("Tor support is not available\n");
           return gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
@@ -1086,6 +1137,7 @@ do_parse_uri (parsed_uri_t uri, int only_local_part,
   uri->is_http = 0;
   uri->opaque = 0;
   uri->v6lit = 0;
+  uri->onion = 0;
 
   /* A quick validity check. */
   if (strspn (p, VALID_URI_CHARS) != n)
@@ -1172,49 +1224,54 @@ do_parse_uri (parsed_uri_t uri, int only_local_part,
         {
           uri->opaque = 1;
           uri->path = p;
+          if (is_onion_address (uri->path))
+            uri->onion = 1;
           return 0;
         }
 
     } /* End global URI part. */
 
-  /* Parse the pathname part */
-  if (!p || !*p)
-    return 0;  /* We don't have a path.  Okay. */
-
-  /* TODO: Here we have to check params. */
-
-  /* Do we have a query part? */
-  if ((p2 = strchr (p, '?')))
-    *p2++ = 0;
-
-  uri->path = p;
-  if ((n = remove_escapes (p)) < 0)
-    return GPG_ERR_BAD_URI;
-  if (n != strlen (p))
-    return GPG_ERR_BAD_URI;    /* Path includes a Nul. */
-  p = p2 ? p2 : NULL;
-
-  if (!p || !*p)
-    return 0; /* We don't have a query string.  Okay. */
-
-  /* Now parse the query string. */
-  tail = &uri->query;
-  for (;;)
+  /* Parse the pathname part if any.  */
+  if (p && *p)
     {
-      uri_tuple_t elem;
+      /* TODO: Here we have to check params. */
 
-      if ((p2 = strchr (p, '&')))
-       *p2++ = 0;
-      if (!(elem = parse_tuple (p)))
-       return GPG_ERR_BAD_URI;
-      *tail = elem;
-      tail = &elem->next;
+      /* Do we have a query part? */
+      if ((p2 = strchr (p, '?')))
+        *p2++ = 0;
 
-      if (!p2)
-       break; /* Ready. */
-      p = p2;
+      uri->path = p;
+      if ((n = remove_escapes (p)) < 0)
+        return GPG_ERR_BAD_URI;
+      if (n != strlen (p))
+        return GPG_ERR_BAD_URI;        /* Path includes a Nul. */
+      p = p2 ? p2 : NULL;
+
+      /* Parse a query string if any.  */
+      if (p && *p)
+        {
+          tail = &uri->query;
+          for (;;)
+            {
+              uri_tuple_t elem;
+
+              if ((p2 = strchr (p, '&')))
+                *p2++ = 0;
+              if (!(elem = parse_tuple (p)))
+                return GPG_ERR_BAD_URI;
+              *tail = elem;
+              tail = &elem->next;
+
+              if (!p2)
+                break; /* Ready. */
+              p = p2;
+            }
+        }
     }
 
+  if (is_onion_address (uri->host))
+    uri->onion = 1;
+
   return 0;
 }
 
@@ -1475,9 +1532,7 @@ send_request (http_t hd, const char *httphost, const char *auth,
     {
       int mode;
 
-#if ASSUAN_VERSION_NUMBER >= 0x020300 /* >= 2.3.0 */
       if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
-#endif
         {
           log_error ("Tor support is not available\n");
           return gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);