mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-31 11:41:32 +01:00
dirmngr: First take on ntbtls cert verification.
* dirmngr/http-ntbtls.c: New. * dirmngr/Makefile.am (dirmngr_SOURCES): Add file. * dirmngr/dirmngr.h (SERVER_CONTROL_MAGIC): New. (server_conrol_s): Add field 'magic', * dirmngr/dirmngr.c (dirmngr_init_default_ctrl): Set MAGIC. (dirmngr_deinit_default_ctrl): Set MAGIC to deadbeef. * dirmngr/http.c (my_ntbtls_verify_cb): New. (http_session_new) [HTTP_USE_NTBTLS]: Remove all CA setting code. (send_request) [HTTP_USE_NTBTLS]: Set the verify callback. Do not call the verify callback after the handshake. * dirmngr/ks-engine-hkp.c (send_request): Pass gnupg_http_tls_verify_cb to http_session_new. * dirmngr/ks-engine-http.c (ks_http_fetch): Ditto. * dirmngr/t-http.c (my_http_tls_verify_cb): New. (main): Rename option --gnutls-debug to --tls-debug. (main) [HTTP_USE_NTBTLS]: Create a session. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
a74902cccd
commit
64fffd0ce2
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
109
dirmngr/http-ntbtls.c
Normal file
109
dirmngr/http-ntbtls.c
Normal file
@ -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*/
|
121
dirmngr/http.c
121
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),
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user