dirmngr: Add per-session verify callback to http.c
authorWerner Koch <wk@gnupg.org>
Sat, 18 Feb 2017 15:09:16 +0000 (16:09 +0100)
committerWerner Koch <wk@gnupg.org>
Sat, 18 Feb 2017 15:39:02 +0000 (16:39 +0100)
* dirmngr/http.h (http_verify_cb_t): New type.
* dirmngr/http.c (http_session_s): Add fields flags, verify_cb, and
verify_cb_value.
(http_session_new): Remove arg tls_priority.  Add args verify_cb and
verify-cb_value.  Store them in the session object.
(send_request): Use per-session verify callback.
(http_verify_server_credentials) [HTTP_USE_NTBTLS]: Return
GPG_ERR_NOT_IMPLEMENTED.
* dirmngr/ks-engine-hkp.c (send_request): Adjust for changed
http_session_new.
* dirmngr/ks-engine-http.c (ks_http_fetch): Ditto.
* dirmngr/t-http.c (main): Ditto.

* dirmngr/server.c (do_get_cert_local): Replace xmalloc by malloc.

Signed-off-by: Werner Koch <wk@gnupg.org>
dirmngr/http.c
dirmngr/http.h
dirmngr/ks-engine-hkp.c
dirmngr/ks-engine-http.c
dirmngr/server.c
dirmngr/t-http.c

index 0f6cac6..51aec7e 100644 (file)
@@ -221,6 +221,13 @@ struct http_session_s
   /* A callback function to log details of TLS certifciates.  */
   void (*cert_log_cb) (http_session_t, gpg_error_t, const char *,
                        const void **, size_t *);
+
+  /* The flags passed to the session object.  */
+  unsigned int flags;
+
+  /* A per-session TLS verification callback.  */
+  http_verify_cb_t verify_cb;
+  void *verify_cb_value;
 };
 
 
@@ -606,8 +613,9 @@ http_session_release (http_session_t sess)
  *   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,
-                  const char *intended_hostname, unsigned int flags)
+http_session_new (http_session_t *r_session,
+                  const char *intended_hostname, unsigned int flags,
+                  http_verify_cb_t verify_cb, void *verify_cb_value)
 {
   gpg_error_t err;
   http_session_t sess;
@@ -618,6 +626,9 @@ http_session_new (http_session_t *r_session, const char *tls_priority,
   if (!sess)
     return gpg_error_from_syserror ();
   sess->refcount = 1;
+  sess->flags = flags;
+  sess->verify_cb = verify_cb;
+  sess->verify_cb_value = verify_cb_value;
 
 #if HTTP_USE_NTBTLS
   {
@@ -630,8 +641,6 @@ http_session_new (http_session_t *r_session, const char *tls_priority,
     size_t buflen;
     char *pemname;
 
-    (void)tls_priority;
-
     pemname = make_filename_try (gnupg_datadir (),
                                  "sks-keyservers.netCA.pem", NULL);
     if (!pemname)
@@ -799,7 +808,7 @@ http_session_new (http_session_t *r_session, const char *tls_priority,
     gnutls_transport_set_ptr (sess->tls_session, NULL);
 
     rc = gnutls_priority_set_direct (sess->tls_session,
-                                     tls_priority? tls_priority : "NORMAL",
+                                     "NORMAL",
                                      &errpos);
     if (rc < 0)
       {
@@ -1823,10 +1832,27 @@ send_request (http_t hd, const char *httphost, const char *auth,
         }
 
       hd->session->verify.done = 0;
-      if (tls_callback)
+
+
+      /* Try the available verify callbacks until one returns success
+       * or a real error.  */
+      err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+      if (hd->session->verify_cb)
+        err = hd->session->verify_cb (hd->session->verify_cb_value,
+                                      hd, hd->session,
+                                      (hd->flags | hd->session->flags),
+                                      hd->session->tls_session);
+
+      if (tls_callback
+          && gpg_err_source (err) == GPG_ERR_SOURCE_DIRMNGR
+          && gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
         err = tls_callback (hd, hd->session, 0);
-      else
+
+      if (gpg_err_source (err) == GPG_ERR_SOURCE_DIRMNGR
+          && gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
         err = http_verify_server_credentials (hd->session);
+
       if (err)
         {
           log_info ("TLS connection authentication failed: %s <%s>\n",
@@ -1834,6 +1860,7 @@ send_request (http_t hd, const char *httphost, const char *auth,
           xfree (proxy_authstr);
           return err;
         }
+
     }
 #elif HTTP_USE_GNUTLS
   if (hd->uri->use_tls)
@@ -2910,10 +2937,7 @@ cookie_close (void *cookie)
 gpg_error_t
 http_verify_server_credentials (http_session_t sess)
 {
-#if HTTP_USE_NTBTLS
-  (void)sess;
-  return 0;  /* FIXME!! */
-#elif HTTP_USE_GNUTLS
+#if HTTP_USE_GNUTLS
   static const char const errprefix[] = "TLS verification of peer failed";
   int rc;
   unsigned int status;
index 0b581fe..98ac4a3 100644 (file)
@@ -97,6 +97,13 @@ typedef struct http_session_s *http_session_t;
 struct http_context_s;
 typedef struct http_context_s *http_t;
 
+/* A TLS verify callback function.  */
+typedef gpg_error_t (*http_verify_cb_t) (void *opaque,
+                                         http_t http,
+                                         http_session_t session,
+                                         unsigned int flags,
+                                         void *tls_context);
+
 void http_set_verbose (int verbose, int debug);
 
 void http_register_tls_callback (gpg_error_t (*cb)(http_t,http_session_t,int));
@@ -105,9 +112,10 @@ void http_register_netactivity_cb (void (*cb)(void));
 
 
 gpg_error_t http_session_new (http_session_t *r_session,
-                              const char *tls_priority,
                               const char *intended_hostname,
-                              unsigned int flags);
+                              unsigned int flags,
+                              http_verify_cb_t cb,
+                              void *cb_value);
 http_session_t http_session_ref (http_session_t sess);
 void http_session_release (http_session_t sess);
 
index e39d60e..b342f09 100644 (file)
@@ -1123,7 +1123,8 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
 
   *r_fp = NULL;
 
-  err = http_session_new (&session, NULL, httphost, HTTP_FLAG_TRUST_DEF);
+  err = http_session_new (&session, httphost, HTTP_FLAG_TRUST_DEF,
+                          NULL, ctrl);
   if (err)
     goto leave;
   http_session_set_log_cb (session, cert_log_cb);
index 69642ff..f070019 100644 (file)
@@ -76,7 +76,8 @@ ks_http_fetch (ctrl_t ctrl, const char *url, estream_t *r_fp)
  once_more:
   /* Note that we only use the system provided certificates with the
    * fetch command.  */
-  err = http_session_new (&session, NULL, NULL, HTTP_FLAG_TRUST_SYS);
+  err = http_session_new (&session, NULL, HTTP_FLAG_TRUST_SYS,
+                          NULL, ctrl);
   if (err)
     goto leave;
   http_session_set_log_cb (session, cert_log_cb);
index 1134ac0..92bbc16 100644 (file)
@@ -370,14 +370,15 @@ do_get_cert_local (ctrl_t ctrl, const char *name, const char *command)
   char *buf;
   ksba_cert_t cert;
 
-  if (name)
-    buf = xstrconcat (command, " ", name, NULL);
+  buf = name? strconcat (command, " ", name, NULL) : xtrystrdup (command);
+  if (!buf)
+    rc = gpg_error_from_syserror ();
   else
-    buf = xstrdup (command);
-
-  rc = assuan_inquire (ctrl->server_local->assuan_ctx, buf,
-                       &value, &valuelen, MAX_CERT_LENGTH);
-  xfree (buf);
+    {
+      rc = assuan_inquire (ctrl->server_local->assuan_ctx, buf,
+                           &value, &valuelen, MAX_CERT_LENGTH);
+      xfree (buf);
+    }
   if (rc)
     {
       log_error (_("assuan_inquire(%s) failed: %s\n"),
index a87382a..8b1d89a 100644 (file)
@@ -262,7 +262,7 @@ main (int argc, char **argv)
   http_register_tls_callback (verify_callback);
   http_register_tls_ca (cafile);
 
-  err = http_session_new (&session, NULL, NULL, HTTP_FLAG_TRUST_DEF);
+  err = http_session_new (&session, NULL, HTTP_FLAG_TRUST_DEF, NULL, NULL);
   if (err)
     log_error ("http_session_new failed: %s\n", gpg_strerror (err));