From 59b4fb5f4927908af06bb80ecd86adbf6e54ba14 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Fri, 14 Mar 2014 17:00:10 +0100 Subject: [PATCH] dirmngr: Make use of IPv4 and IPV6 more explicit. * common/http.c (connect_server): Handle the new flags. * common/http.h (HTTP_FLAG_IGNORE_IPv4, HTTP_FLAG_IGNORE_IPv4): New. * dirmngr/ks-engine-hkp.c (map_host): Add arg r_httpflags. (make_host_part): Ditto. (send_request): Add arg httpflags. (ks_hkp_search, ks_hkp_get, ks_hkp_put): Handle httpflags. --- common/http.c | 8 +++++-- common/http.h | 10 +++++---- dirmngr/ks-engine-hkp.c | 47 ++++++++++++++++++++++++++++++----------- 3 files changed, 47 insertions(+), 18 deletions(-) diff --git a/common/http.c b/common/http.c index d95a2fba9..541014153 100644 --- a/common/http.c +++ b/common/http.c @@ -1,6 +1,7 @@ /* http.c - HTTP protocol handler * Copyright (C) 1999, 2001, 2002, 2003, 2004, 2006, 2009, 2010, * 2011 Free Software Foundation, Inc. + * Copyright (C) 2014 Werner Koch * * This file is part of GnuPG. * @@ -1706,8 +1707,6 @@ connect_server (const char *server, unsigned short port, #ifdef HAVE_W32_SYSTEM unsigned long inaddr; #endif - /* Not currently using the flags */ - (void)flags; *r_host_not_found = 0; #ifdef HAVE_W32_SYSTEM @@ -1790,6 +1789,11 @@ connect_server (const char *server, unsigned short port, for (ai = res; ai && !connected; ai = ai->ai_next) { + if (ai->ai_family == AF_INET && (flags & HTTP_FLAG_IGNORE_IPv4)) + continue; + if (ai->ai_family == AF_INET6 && (flags & HTTP_FLAG_IGNORE_IPv6)) + continue; + if (sock != -1) sock_close (sock); sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol); diff --git a/common/http.h b/common/http.h index bea9f07f1..224128b94 100644 --- a/common/http.h +++ b/common/http.h @@ -74,10 +74,12 @@ http_req_t; /* We put the flag values into an enum, so that gdb can display them. */ enum { - HTTP_FLAG_TRY_PROXY = 1, - HTTP_FLAG_SHUTDOWN = 2, - HTTP_FLAG_LOG_RESP = 8, - HTTP_FLAG_IGNORE_CL = 32 + HTTP_FLAG_TRY_PROXY = 1, /* Try to use a proxy. */ + HTTP_FLAG_SHUTDOWN = 2, /* Close sending end after the request. */ + HTTP_FLAG_LOG_RESP = 8, /* Log the server respone. */ + HTTP_FLAG_IGNORE_CL = 32, /* Ignore content-length. */ + HTTP_FLAG_IGNORE_IPv4 = 64, /* Do not use IPv4. */ + HTTP_FLAG_IGNORE_IPv6 = 128 /* Do not use IPv6. */ }; struct http_context_s; diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c index 0b2850ce4..7b67302ab 100644 --- a/dirmngr/ks-engine-hkp.c +++ b/dirmngr/ks-engine-hkp.c @@ -249,13 +249,18 @@ my_getnameinfo (struct addrinfo *ai, char *host, size_t hostlen) to choose one of the hosts. For example we skip those hosts which failed for some time and we stick to one host for a time independent of DNS retry times. If FORCE_RESELECT is true a new - host is always selected. */ + host is always selected. If R_HTTPFLAGS is not NULL if will + received flags which are to be passed to http_open. */ static char * -map_host (ctrl_t ctrl, const char *name, int force_reselect) +map_host (ctrl_t ctrl, const char *name, int force_reselect, + unsigned int *r_httpflags) { hostinfo_t hi; int idx; + if (r_httpflags) + *r_httpflags = 0; + /* No hostname means localhost. */ if (!name || !*name) return xtrystrdup ("localhost"); @@ -406,6 +411,18 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect) return NULL; } + if (r_httpflags) + { + /* If the hosttable does not indicate that a certain host + supports IPv, we explicit set the corresponding http + flags. The reason for this is that a host might be listed in + a pool as not v6 only but actually support v6 when later + resolved the name is resolved by our http layer. */ + if (!hi->v4) + *r_httpflags |= HTTP_FLAG_IGNORE_IPv4; + if (!hi->v6) + *r_httpflags |= HTTP_FLAG_IGNORE_IPv6; + } return xtrystrdup (hi->name); } @@ -605,7 +622,7 @@ ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri) static char * make_host_part (ctrl_t ctrl, const char *scheme, const char *host, unsigned short port, - int force_reselect) + int force_reselect, unsigned int *r_httpflags) { char portstr[10]; char *hostname; @@ -629,7 +646,7 @@ make_host_part (ctrl_t ctrl, /*fixme_do_srv_lookup ()*/ } - hostname = map_host (ctrl, host, force_reselect); + hostname = map_host (ctrl, host, force_reselect, r_httpflags); if (!hostname) return NULL; @@ -648,7 +665,7 @@ ks_hkp_resolve (ctrl_t ctrl, parsed_uri_t uri) gpg_error_t err; char *hostport = NULL; - hostport = make_host_part (ctrl, uri->scheme, uri->host, uri->port, 1); + hostport = make_host_part (ctrl, uri->scheme, uri->host, uri->port, 1, NULL); if (!hostport) { err = gpg_error_from_syserror (); @@ -671,6 +688,7 @@ ks_hkp_resolve (ctrl_t ctrl, parsed_uri_t uri) writing the post data. */ static gpg_error_t send_request (ctrl_t ctrl, const char *request, const char *hostportstr, + unsigned int httpflags, gpg_error_t (*post_cb)(void *, http_t), void *post_cb_value, estream_t *r_fp) { @@ -687,7 +705,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr, post_cb? HTTP_REQ_POST : HTTP_REQ_GET, request, /* fixme: AUTH */ NULL, - 0, + httpflags, /* fixme: proxy*/ NULL, NULL, NULL, /*FIXME curl->srvtag*/NULL); @@ -892,6 +910,7 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern, char *request = NULL; estream_t fp = NULL; int reselect; + unsigned int httpflags; unsigned int tries = SEND_REQUEST_RETRIES; *r_fp = NULL; @@ -941,7 +960,7 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern, xfree (hostport); hostport = make_host_part (ctrl, uri->scheme, uri->host, uri->port, - reselect); + reselect, &httpflags); if (!hostport) { err = gpg_error_from_syserror (); @@ -969,7 +988,7 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern, } /* Send the request. */ - err = send_request (ctrl, request, hostport, NULL, NULL, &fp); + err = send_request (ctrl, request, hostport, httpflags, NULL, NULL, &fp); if (handle_send_request_error (err, request, &tries)) { reselect = 1; @@ -1026,6 +1045,7 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp) char *request = NULL; estream_t fp = NULL; int reselect; + unsigned int httpflags; unsigned int tries = SEND_REQUEST_RETRIES; *r_fp = NULL; @@ -1062,7 +1082,8 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp) again: /* Build the request string. */ xfree (hostport); - hostport = make_host_part (ctrl, uri->scheme, uri->host, uri->port, reselect); + hostport = make_host_part (ctrl, uri->scheme, uri->host, uri->port, + reselect, &httpflags); if (!hostport) { err = gpg_error_from_syserror (); @@ -1081,7 +1102,7 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp) } /* Send the request. */ - err = send_request (ctrl, request, hostport, NULL, NULL, &fp); + err = send_request (ctrl, request, hostport, httpflags, NULL, NULL, &fp); if (handle_send_request_error (err, request, &tries)) { reselect = 1; @@ -1148,6 +1169,7 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen) struct put_post_parm_s parm; char *armored = NULL; int reselect; + unsigned int httpflags; unsigned int tries = SEND_REQUEST_RETRIES; parm.datastring = NULL; @@ -1169,7 +1191,8 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen) reselect = 0; again: xfree (hostport); - hostport = make_host_part (ctrl, uri->scheme, uri->host, uri->port, reselect); + hostport = make_host_part (ctrl, uri->scheme, uri->host, uri->port, + reselect, &httpflags); if (!hostport) { err = gpg_error_from_syserror (); @@ -1185,7 +1208,7 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen) } /* Send the request. */ - err = send_request (ctrl, request, hostport, put_post_cb, &parm, &fp); + err = send_request (ctrl, request, hostport, 0, put_post_cb, &parm, &fp); if (handle_send_request_error (err, request, &tries)) { reselect = 1;