dirmngr: Add per-session verify callback to http.c

* 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>
This commit is contained in:
Werner Koch 2017-02-18 16:09:16 +01:00
parent cd32ebd152
commit a74902cccd
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
6 changed files with 58 additions and 23 deletions

View 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;

View 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);

View 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);

View 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);

View 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"),

View 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));