aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dirmngr/Makefile.am1
-rw-r--r--dirmngr/dirmngr.c1
-rw-r--r--dirmngr/http-common.h2
-rw-r--r--dirmngr/http.c162
-rw-r--r--doc/dirmngr.texi4
5 files changed, 166 insertions, 4 deletions
diff --git a/dirmngr/Makefile.am b/dirmngr/Makefile.am
index 3846fdf35..9665b5dfd 100644
--- a/dirmngr/Makefile.am
+++ b/dirmngr/Makefile.am
@@ -68,6 +68,7 @@ AM_CFLAGS = $(USE_C99_CFLAGS) \
if HAVE_W32_SYSTEM
ldap_url = ldap-url.h ldap-url.c
+NETLIBS += -lwinhttp
else
ldap_url =
endif
diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c
index 97c2dc490..f79a0f877 100644
--- a/dirmngr/dirmngr.c
+++ b/dirmngr/dirmngr.c
@@ -2045,6 +2045,7 @@ dirmngr_sighup_action (void)
crl_cache_deinit ();
cert_cache_init (hkp_cacert_filenames);
crl_cache_init ();
+ http_reinitialize ();
reload_dns_stuff (0);
ks_hkp_reload ();
}
diff --git a/dirmngr/http-common.h b/dirmngr/http-common.h
index 5e6657b16..ddb340de6 100644
--- a/dirmngr/http-common.h
+++ b/dirmngr/http-common.h
@@ -22,4 +22,6 @@
const char *get_default_keyserver (int name_only);
+void http_reinitialize (void);
+
#endif /* HTTP_COMMON_H */
diff --git a/dirmngr/http.c b/dirmngr/http.c
index e8b6ae4d8..7cab1c2e5 100644
--- a/dirmngr/http.c
+++ b/dirmngr/http.c
@@ -64,6 +64,7 @@
# include <winsock2.h>
# endif
# include <windows.h>
+# include <winhttp.h>
# ifndef EHOSTUNREACH
# define EHOSTUNREACH WSAEHOSTUNREACH
# endif
@@ -1827,6 +1828,141 @@ release_proxy_info (proxy_info_t proxy)
}
+/* Return an http session object. If clear is set, the object is
+ * destroyed. On error nULL is returned. */
+#ifdef HAVE_W32_SYSTEM
+static HINTERNET
+w32_get_internet_session (int clear)
+{
+ static HINTERNET session;
+
+ if (clear)
+ {
+ if (session)
+ {
+ WinHttpCloseHandle (session);
+ session = NULL;
+ }
+ return NULL;
+ }
+
+ if (!session)
+ {
+ session = WinHttpOpen (L"GnuPG dirmngr",
+ WINHTTP_ACCESS_TYPE_NO_PROXY,
+ WINHTTP_NO_PROXY_NAME,
+ WINHTTP_NO_PROXY_BYPASS,
+ 0);
+ if (!session)
+ {
+ log_error ("WinHttpOpen failed: %s\n", w32_strerror (-1));
+ return NULL;
+ }
+ }
+
+ return session;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+
+/* Return a proxy using a Windows API. */
+#ifdef HAVE_W32_SYSTEM
+static char *
+w32_get_proxy (const char *url)
+{
+ WINHTTP_AUTOPROXY_OPTIONS options = {0};
+ WINHTTP_PROXY_INFO info;
+ char *result = NULL;
+ char *p;
+ wchar_t *wurl;
+ int defaultcfg = 0;
+
+ wurl = utf8_to_wchar (url);
+ if (!wurl)
+ {
+ log_error ("utf8_to_wchar failed: %s\n",
+ gpg_strerror (gpg_error_from_syserror ()));
+ return NULL;
+ }
+
+ options.dwFlags = (WINHTTP_AUTOPROXY_ALLOW_AUTOCONFIG
+ | WINHTTP_AUTOPROXY_ALLOW_CM
+ | WINHTTP_AUTOPROXY_ALLOW_STATIC
+ | WINHTTP_AUTOPROXY_AUTO_DETECT
+ | WINHTTP_AUTOPROXY_SORT_RESULTS);
+ options.dwAutoDetectFlags = (WINHTTP_AUTO_DETECT_TYPE_DHCP
+ | WINHTTP_AUTO_DETECT_TYPE_DNS_A);
+ options.fAutoLogonIfChallenged = TRUE;
+
+ if (opt_debug)
+ log_debug ("calling WinHttpGetProxyForUrl (%s)\n", url);
+ if (!WinHttpGetProxyForUrl (w32_get_internet_session (0),
+ wurl, &options, &info))
+ {
+ int ec = (int)GetLastError ();
+ if (ec == ERROR_WINHTTP_AUTODETECTION_FAILED)
+ {
+ if (opt_debug)
+ log_debug ("calling WinHttpGetDefaultProxyConfiguration\n");
+ if (!WinHttpGetDefaultProxyConfiguration (&info))
+ {
+ if (opt_verbose)
+ log_info ("WinHttpGetDefaultProxyConfiguration failed: "
+ "%s (%d)\n", w32_strerror (ec), ec);
+ xfree (wurl);
+ return NULL;
+ }
+ defaultcfg = 1;
+ }
+ else
+ {
+ if (opt_verbose)
+ log_info ("WinHttpGetProxyForUrl failed: %s (%d)\n",
+ w32_strerror (ec), ec);
+ xfree (wurl);
+ return NULL;
+ }
+ }
+ xfree (wurl);
+
+ if (info.dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY)
+ {
+ result = wchar_to_utf8 (info.lpszProxy);
+ if (!result)
+ log_error ("wchar_to_utf8 failed: %s\n",
+ gpg_strerror (gpg_error_from_syserror ()));
+ else
+ {
+ if (opt_debug)
+ log_debug ("proxies to use: '%s'\n", result);
+ /* The returned proxies are delimited by whitespace or
+ * semicolons. We return only the first proxy. */
+ for (p=result; *p; p++)
+ if (spacep (p) || *p == ';')
+ {
+ *p = 0;
+ break;
+ }
+ }
+ }
+ else if (info.dwAccessType == WINHTTP_ACCESS_TYPE_NO_PROXY)
+ {
+ /* No proxy shall be used. */
+ }
+ else
+ log_error ("%s returned unexpected code %lu\n",
+ defaultcfg? "WinHttpGetDefaultProxyConfiguration"
+ :"WinHttpGetProxyForUrl", info.dwAccessType);
+
+ if (info.lpszProxy)
+ GlobalFree (info.lpszProxy);
+ if (info.lpszProxyBypass)
+ GlobalFree (info.lpszProxyBypass);
+ return result;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+
/* Return the proxy to be used for the URL or host specified in HD.
* If OVERRIDE_PROXY is not NULL and not empty, this proxy will be
* used instead of any configured or dynamically determined proxy. If
@@ -1838,11 +1974,14 @@ release_proxy_info (proxy_info_t proxy)
static gpg_error_t
get_proxy_for_url (http_t hd, const char *override_proxy, proxy_info_t *r_proxy)
{
- gpg_error_t err;
+ gpg_error_t err = 0;
const char *proxystr, *s;
proxy_info_t proxy;
+#ifdef HAVE_W32_SYSTEM
+ char *proxystrbuf = NULL;
+#endif
- r_proxy = NULL;
+ *r_proxy = NULL;
if (override_proxy && *override_proxy)
proxystr = override_proxy;
@@ -1851,6 +1990,9 @@ get_proxy_for_url (http_t hd, const char *override_proxy, proxy_info_t *r_proxy)
else if ((s = getenv (HTTP_PROXY_ENV)) && *s)
proxystr = s;
#ifdef HAVE_W32_SYSTEM
+ else if (hd->uri && hd->uri->original
+ && (proxystrbuf = w32_get_proxy (hd->uri->original)))
+ proxystr = proxystrbuf;
#endif
else
return 0; /* No proxy known. */
@@ -1860,7 +2002,7 @@ get_proxy_for_url (http_t hd, const char *override_proxy, proxy_info_t *r_proxy)
{
err = gpg_error_from_syserror ();
log_error ("error allocating memory for proxy\n");
- return err;
+ goto leave;
}
err = parse_uri (&proxy->uri, proxystr, 0, 0);
@@ -1901,6 +2043,10 @@ get_proxy_for_url (http_t hd, const char *override_proxy, proxy_info_t *r_proxy)
proxystr, hd->uri? hd->uri->original : NULL);
}
+ leave:
+#ifdef HAVE_W32_SYSTEM
+ xfree (proxystrbuf);
+#endif
if (err)
xfree (proxy);
else
@@ -3938,3 +4084,13 @@ http_status2string (unsigned int status)
return "";
}
+
+
+/* Fucntion called on SIGHUP to flush internal variables. */
+void
+http_reinitialize (void)
+{
+#ifdef HAVE_W32_SYSTEM
+ w32_get_internet_session (1); /* Clear our session. */
+#endif /*HAVE_W32_SYSTEM*/
+}
diff --git a/doc/dirmngr.texi b/doc/dirmngr.texi
index 398888e71..cd7969828 100644
--- a/doc/dirmngr.texi
+++ b/doc/dirmngr.texi
@@ -427,7 +427,9 @@ force the use of the default responder.
@item --honor-http-proxy
@opindex honor-http-proxy
If the environment variable @env{http_proxy} has been set, use its
-value to access HTTP servers.
+value to access HTTP servers. If on Windows the option is used but
+the environment variable is not set, the proxy settings are taken
+from the system.
@item --http-proxy @var{host}[:@var{port}]
@opindex http-proxy