Merge branch 'STABLE-BRANCH-2-2' into master
[gnupg.git] / dirmngr / http.c
index cc7f5a5..049aefc 100644 (file)
@@ -318,6 +318,9 @@ static gpg_error_t (*tls_callback) (http_t, http_session_t, int);
 /* The list of files with trusted CA certificates.  */
 static strlist_t tls_ca_certlist;
 
+/* The list of files with extra trusted CA certificates.  */
+static strlist_t cfg_ca_certlist;
+
 /* The global callback for net activity.  */
 static void (*netactivity_cb)(void);
 
@@ -596,6 +599,35 @@ http_register_tls_ca (const char *fname)
 }
 
 
+/* Register a CA certificate for future use.  The certificate is
+ * expected to be in FNAME.  PEM format is assume if FNAME has a
+ * suffix of ".pem".  If FNAME is NULL the list of CA files is
+ * removed.  This is a variant of http_register_tls_ca which puts the
+ * certificate into a separate list enabled using HTTP_FLAG_TRUST_CFG.  */
+void
+http_register_cfg_ca (const char *fname)
+{
+  strlist_t sl;
+
+  if (!fname)
+    {
+      free_strlist (cfg_ca_certlist);
+      cfg_ca_certlist = NULL;
+    }
+  else
+    {
+      /* Warn if we can't access right now, but register it anyway in
+         case it becomes accessible later */
+      if (access (fname, F_OK))
+        log_info (_("can't access '%s': %s\n"), fname,
+                  gpg_strerror (gpg_error_from_syserror()));
+      sl = add_to_strlist (&cfg_ca_certlist, fname);
+      if (*sl->d && !strcmp (sl->d + strlen (sl->d) - 4, ".pem"))
+        sl->flags = 1;
+    }
+}
+
+
 /* Register a callback which is called every time the HTTP mode has
  * made a successful connection to some server.  */
 void
@@ -680,6 +712,7 @@ http_session_release (http_session_t sess)
  * 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
+ *   HTTP_FLAG_TRUST_CFG - Also use CAs set with http_register_cfg_ca
  *   HTTP_FLAG_NO_CRL    - Do not consult CRLs for https.
  */
 gpg_error_t
@@ -793,6 +826,21 @@ http_session_new (http_session_t *r_session,
 #endif /* gnutls >= 3.0.20 */
       }
 
+    /* Add other configured certificates to the session.  */
+    if ((flags & HTTP_FLAG_TRUST_CFG))
+      {
+        for (sl = cfg_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 extra CA from file '%s' failed: %s\n",
+                        sl->d, gnutls_strerror (rc));
+          }
+      }
+
+
     rc = gnutls_init (&sess->tls_session, GNUTLS_CLIENT);
     if (rc < 0)
       {
@@ -1688,9 +1736,19 @@ send_request (http_t hd, const char *httphost, const char *auth,
 #ifdef USE_TLS
   if (hd->uri->use_tls && !hd->session->tls_session)
     {
-      log_error ("TLS requested but no GNUTLS context available\n");
+      log_error ("TLS requested but no TLS context available\n");
       return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
     }
+  if (opt_debug)
+    log_debug ("Using TLS library: %s %s\n",
+# if HTTP_USE_NTBTLS
+               "NTBTLS", ntbtls_check_version (NULL)
+# elif HTTP_USE_GNUTLS
+               "GNUTLS", gnutls_check_version (NULL)
+# else
+               "?", "?"
+# endif /*HTTP_USE_*TLS*/
+               );
 #endif /*USE_TLS*/
 
   if ((hd->flags & HTTP_FLAG_FORCE_TOR))