aboutsummaryrefslogtreecommitdiffstats
path: root/dirmngr
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dirmngr/Makefile.am1
-rw-r--r--dirmngr/dirmngr.c3
-rw-r--r--dirmngr/dirmngr.h22
-rw-r--r--dirmngr/http-ntbtls.c109
-rw-r--r--dirmngr/http.c121
-rw-r--r--dirmngr/ks-engine-hkp.c2
-rw-r--r--dirmngr/ks-engine-http.c2
-rw-r--r--dirmngr/t-http.c66
8 files changed, 233 insertions, 93 deletions
diff --git a/dirmngr/Makefile.am b/dirmngr/Makefile.am
index d3f89bcef..7fa42829d 100644
--- a/dirmngr/Makefile.am
+++ b/dirmngr/Makefile.am
@@ -62,6 +62,7 @@ dirmngr_SOURCES = dirmngr.c dirmngr.h server.c crlcache.c crlfetch.c \
ocsp.c ocsp.h validate.c validate.h \
dns-stuff.c dns-stuff.h \
http.c http.h \
+ http-ntbtls.c \
ks-action.c ks-action.h ks-engine.h \
ks-engine-hkp.c ks-engine-http.c ks-engine-finger.c ks-engine-kdns.c
diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c
index bb07656a5..718296d0f 100644
--- a/dirmngr/dirmngr.c
+++ b/dirmngr/dirmngr.c
@@ -1468,6 +1468,7 @@ dirmngr_exit (int rc)
void
dirmngr_init_default_ctrl (ctrl_t ctrl)
{
+ ctrl->magic = SERVER_CONTROL_MAGIC;
if (opt.http_proxy)
ctrl->http_proxy = xstrdup (opt.http_proxy);
}
@@ -1478,6 +1479,8 @@ dirmngr_deinit_default_ctrl (ctrl_t ctrl)
{
if (!ctrl)
return;
+ ctrl->magic = 0xdeadbeef;
+
xfree (ctrl->http_proxy);
ctrl->http_proxy = NULL;
}
diff --git a/dirmngr/dirmngr.h b/dirmngr/dirmngr.h
index 19d2303ca..57e3372a0 100644
--- a/dirmngr/dirmngr.h
+++ b/dirmngr/dirmngr.h
@@ -168,12 +168,19 @@ typedef struct cert_ref_s *cert_ref_t;
/* Forward references; access only through server.c. */
struct server_local_s;
+#if SIZEOF_UNSIGNED_LONG == 8
+# define SERVER_CONTROL_MAGIC 0x6469726d6e677220
+#else
+# define SERVER_CONTROL_MAGIC 0x6469726d
+#endif
+
/* Connection control structure. */
struct server_control_s
{
- int refcount; /* Count additional references to this object. */
- int no_server; /* We are not running under server control. */
- int status_fd; /* Only for non-server mode. */
+ unsigned long magic;/* Always has SERVER_CONTROL_MAGIC. */
+ int refcount; /* Count additional references to this object. */
+ int no_server; /* We are not running under server control. */
+ int status_fd; /* Only for non-server mode. */
struct server_local_s *server_local;
int force_crl_refresh; /* Always load a fresh CRL. */
@@ -213,6 +220,15 @@ gpg_error_t dirmngr_status (ctrl_t ctrl, const char *keyword, ...);
gpg_error_t dirmngr_status_help (ctrl_t ctrl, const char *text);
gpg_error_t dirmngr_tick (ctrl_t ctrl);
+/*-- http-ntbtls.c --*/
+/* Note that we don't use a callback for gnutls. */
+
+gpg_error_t gnupg_http_tls_verify_cb (void *opaque,
+ http_t http,
+ http_session_t session,
+ unsigned int flags,
+ void *tls_context);
+
/*-- loadswdb.c --*/
gpg_error_t dirmngr_load_swdb (ctrl_t ctrl, int force);
diff --git a/dirmngr/http-ntbtls.c b/dirmngr/http-ntbtls.c
new file mode 100644
index 000000000..5686877ec
--- /dev/null
+++ b/dirmngr/http-ntbtls.c
@@ -0,0 +1,109 @@
+/* http-ntbtls.c - Support for using NTBTLS with http.c
+ * Copyright (C) 2017 Werner Koch
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dirmngr.h"
+#include "certcache.h"
+#include "validate.h"
+
+#ifdef HTTP_USE_NTBTLS
+# include <ntbtls.h>
+
+
+
+/* The callback used to verify the peer's certificate. */
+gpg_error_t
+gnupg_http_tls_verify_cb (void *opaque,
+ http_t http,
+ http_session_t session,
+ unsigned int http_flags,
+ void *tls_context)
+{
+ ctrl_t ctrl = opaque;
+ gpg_error_t err;
+ int idx;
+ ksba_cert_t cert;
+ ksba_cert_t hostcert = NULL;
+ unsigned int validate_flags;
+
+ (void)http;
+ (void)session;
+
+ log_assert (ctrl && ctrl->magic == SERVER_CONTROL_MAGIC);
+
+ /* Get the peer's certs fron ntbtls. */
+ for (idx = 0;
+ (cert = ntbtls_x509_get_peer_cert (tls_context, idx)); idx++)
+ {
+ if (!idx)
+ hostcert = cert;
+ else
+ {
+ /* Quick hack to make verification work by inserting the supplied
+ * certs into the cache. FIXME! */
+ cache_cert (cert);
+ ksba_cert_release (cert);
+ }
+ }
+ if (!idx)
+ {
+ err = gpg_error (GPG_ERR_MISSING_CERT);
+ goto leave;
+ }
+
+ validate_flags = VALIDATE_FLAG_TLS;
+ /* if ((http_flags & HTTP_FLAG_TRUST_DEF)) */
+ /* validate_flags |= VALIDATE_FLAG_??; */
+ if ((http_flags & HTTP_FLAG_TRUST_SYS))
+ validate_flags |= VALIDATE_FLAG_SYSTRUST;
+
+ /* FIXME: For now we don't use CRLs. */
+ validate_flags |= VALIDATE_FLAG_NOCRLCHECK;
+
+ err = validate_cert_chain (ctrl, hostcert, NULL, validate_flags, NULL);
+
+ leave:
+ ksba_cert_release (hostcert);
+ return err;
+}
+
+
+#else /*!HTTP_USE_NTBTLS*/
+
+/* Dummy function used when not build without ntbtls support. */
+gpg_error_t
+gnupg_http_tls_verify_cb (void *opaque,
+ http_t http,
+ http_session_t session,
+ unsigned int flags,
+ void *tls_context)
+{
+ (void)opaque;
+ (void)http;
+ (void)session;
+ (void)flags;
+ (void)tls_context;
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+}
+#endif /*!HTTP_USE_NTBTLS*/
diff --git a/dirmngr/http.c b/dirmngr/http.c
index 51aec7e7c..e7c6d4224 100644
--- a/dirmngr/http.c
+++ b/dirmngr/http.c
@@ -413,6 +413,21 @@ my_gnutls_write (gnutls_transport_ptr_t ptr, const void *buffer, size_t size)
#endif /*HTTP_USE_GNUTLS*/
+#ifdef HTTP_USE_NTBTLS
+/* Connect the ntbls callback to our generic callback. */
+static gpg_error_t
+my_ntbtls_verify_cb (void *opaque, ntbtls_t tls, unsigned int verify_flags)
+{
+ http_t hd = opaque;
+ log_assert (hd && hd->session && hd->session->verify_cb);
+ return hd->session->verify_cb (hd->session->verify_cb_value,
+ hd, hd->session,
+ (hd->flags | hd->session->flags),
+ tls);
+}
+#endif /*HTTP_USE_NTBTLS*/
+
+
/* This notification function is called by estream whenever stream is
@@ -632,91 +647,16 @@ http_session_new (http_session_t *r_session,
#if HTTP_USE_NTBTLS
{
- x509_cert_t ca_chain;
- char line[256];
- estream_t fp, mem_p;
- size_t nread, nbytes;
- struct b64state state;
- void *buf;
- size_t buflen;
- char *pemname;
-
- 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));
- goto leave;
- }
-
- fp = es_fopen (pemname, "r");
- if (!fp)
- {
- err = gpg_error_from_syserror ();
- log_error ("can't open '%s': %s\n", pemname, gpg_strerror (err));
- xfree (pemname);
- goto leave;
- }
- xfree (pemname);
-
- mem_p = es_fopenmem (0, "r+b");
- err = b64dec_start (&state, "CERTIFICATE");
- if (err)
- {
- log_error ("b64dec failure: %s\n", gpg_strerror (err));
- goto leave;
- }
-
- while ( (nread = es_fread (line, 1, DIM (line), fp)) )
- {
- err = b64dec_proc (&state, line, nread, &nbytes);
- if (err)
- {
- if (gpg_err_code (err) == GPG_ERR_EOF)
- break;
-
- log_error ("b64dec failure: %s\n", gpg_strerror (err));
- es_fclose (fp);
- es_fclose (mem_p);
- goto leave;
- }
- else if (nbytes)
- es_fwrite (line, 1, nbytes, mem_p);
- }
- err = b64dec_finish (&state);
- if (err)
- {
- log_error ("b64dec failure: %s\n", gpg_strerror (err));
- es_fclose (fp);
- es_fclose (mem_p);
- goto leave;
- }
-
- es_fclose_snatch (mem_p, &buf, &buflen);
- es_fclose (fp);
-
- err = ntbtls_x509_cert_new (&ca_chain);
- if (err)
- {
- log_error ("ntbtls_x509_new failed: %s\n", gpg_strerror (err));
- xfree (buf);
- goto leave;
- }
-
- err = ntbtls_x509_append_cert (ca_chain, buf, buflen);
- xfree (buf);
+ (void)intended_hostname; /* Not needed because we do not preload
+ * certificates. */
err = ntbtls_new (&sess->tls_session, NTBTLS_CLIENT);
if (err)
{
log_error ("ntbtls_new failed: %s\n", gpg_strerror (err));
- ntbtls_x509_cert_release (ca_chain);
goto leave;
}
- err = ntbtls_set_ca_chain (sess->tls_session, ca_chain, NULL);
}
#elif HTTP_USE_GNUTLS
{
@@ -1819,6 +1759,21 @@ send_request (http_t hd, const char *httphost, const char *auth,
return err;
}
+#ifdef HTTP_USE_NTBTLS
+ if (hd->session->verify_cb)
+ {
+ err = ntbtls_set_verify_cb (hd->session->tls_session,
+ my_ntbtls_verify_cb, hd);
+ if (err)
+ {
+ log_error ("ntbtls_set_verify_cb failed: %s\n",
+ gpg_strerror (err));
+ xfree (proxy_authstr);
+ return err;
+ }
+ }
+#endif /*HTTP_USE_NTBTLS*/
+
while ((err = ntbtls_handshake (hd->session->tls_session)))
{
switch (err)
@@ -1833,12 +1788,18 @@ send_request (http_t hd, const char *httphost, const char *auth,
hd->session->verify.done = 0;
-
/* Try the available verify callbacks until one returns success
- * or a real error. */
+ * or a real error. Note that NTBTLS does the verification
+ * during the handshake via */
+#ifdef HTTP_USE_NTBTLS
+ err = 0; /* Fixme check that the CB has been called. */
+#else
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+#endif
- if (hd->session->verify_cb)
+ if (hd->session->verify_cb
+ && gpg_err_source (err) == GPG_ERR_SOURCE_DIRMNGR
+ && gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
err = hd->session->verify_cb (hd->session->verify_cb_value,
hd, hd->session,
(hd->flags | hd->session->flags),
diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
index b342f0968..4ca1e0025 100644
--- a/dirmngr/ks-engine-hkp.c
+++ b/dirmngr/ks-engine-hkp.c
@@ -1124,7 +1124,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
*r_fp = NULL;
err = http_session_new (&session, httphost, HTTP_FLAG_TRUST_DEF,
- NULL, ctrl);
+ gnupg_http_tls_verify_cb, ctrl);
if (err)
goto leave;
http_session_set_log_cb (session, cert_log_cb);
diff --git a/dirmngr/ks-engine-http.c b/dirmngr/ks-engine-http.c
index f070019c1..9352a0f18 100644
--- a/dirmngr/ks-engine-http.c
+++ b/dirmngr/ks-engine-http.c
@@ -77,7 +77,7 @@ ks_http_fetch (ctrl_t ctrl, const char *url, estream_t *r_fp)
/* Note that we only use the system provided certificates with the
* fetch command. */
err = http_session_new (&session, NULL, HTTP_FLAG_TRUST_SYS,
- NULL, ctrl);
+ gnupg_http_tls_verify_cb, ctrl);
if (err)
goto leave;
http_session_set_log_cb (session, cert_log_cb);
diff --git a/dirmngr/t-http.c b/dirmngr/t-http.c
index 8b1d89ac0..464112198 100644
--- a/dirmngr/t-http.c
+++ b/dirmngr/t-http.c
@@ -42,7 +42,6 @@
#include "logging.h"
#include "http.h"
-
#if HTTP_USE_NTBTLS
# include <ntbtls.h>
#elif HTTP_USE_GNUTLS
@@ -118,6 +117,56 @@ my_gnutls_log (int level, const char *text)
}
#endif
+
+static gpg_error_t
+my_http_tls_verify_cb (void *opaque,
+ http_t http,
+ http_session_t session,
+ unsigned int http_flags,
+ void *tls_context)
+{
+ gpg_error_t err;
+ int idx;
+ ksba_cert_t cert;
+ ksba_cert_t hostcert = NULL;
+
+ (void)opaque;
+ (void)http;
+ (void)session;
+
+
+ /* Get the peer's certs fron ntbtls. */
+ for (idx = 0;
+ (cert = ntbtls_x509_get_peer_cert (tls_context, idx)); idx++)
+ {
+ if (!idx)
+ {
+ log_info ("Received host certificate\n");
+ hostcert = cert;
+ }
+ else
+ {
+
+ log_info ("Received additional certificate\n");
+ ksba_cert_release (cert);
+ }
+ }
+ if (!idx)
+ {
+ err = gpg_error (GPG_ERR_MISSING_CERT);
+ goto leave;
+ }
+
+ err = 0;
+
+ leave:
+ ksba_cert_release (hostcert);
+ log_info ("my_http_tls_verify_cb returns: %s\n", gpg_strerror (err));
+ return err;
+}
+
+
+
/* Prepend FNAME with the srcdir environment variable's value and
return an allocated filename. */
static char *
@@ -142,8 +191,7 @@ main (int argc, char **argv)
{
int last_argc = -1;
gpg_error_t err;
- int rc;
- parsed_uri_t uri;
+ int rc; parsed_uri_t uri;
uri_tuple_t r;
http_t hd;
int c;
@@ -171,7 +219,7 @@ main (int argc, char **argv)
"Options:\n"
" --verbose print timings etc.\n"
" --debug flyswatter\n"
- " --gnutls-debug N use GNUTLS debug level N\n"
+ " --tls-debug N use TLS debug level N\n"
" --cacert FNAME expect CA certificate in file FNAME\n"
" --no-verify do not verify the certificate\n"
" --force-tls use HTTP_FLAG_FORCE_TLS\n"
@@ -191,7 +239,7 @@ main (int argc, char **argv)
debug++;
argc--; argv++;
}
- else if (!strcmp (*argv, "--gnutls-debug"))
+ else if (!strcmp (*argv, "--tls-debug"))
{
argc--; argv++;
if (argc)
@@ -248,9 +296,11 @@ main (int argc, char **argv)
assuan_sock_init ();
#if HTTP_USE_NTBTLS
-
- (void)err;
-
+ log_info ("new session.\n");
+ err = http_session_new (&session, NULL, HTTP_FLAG_TRUST_DEF,
+ my_http_tls_verify_cb, NULL);
+ if (err)
+ log_error ("http_session_new failed: %s\n", gpg_strerror (err));
ntbtls_set_debug (tls_dbg, NULL, NULL);
#elif HTTP_USE_GNUTLS