diff options
author | Werner Koch <[email protected]> | 2018-11-22 21:27:56 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2018-11-23 08:23:26 +0000 |
commit | 4a4bb874f63741026bd26264c43bb32b1099f060 (patch) | |
tree | 0857a46bd3ddc7e0afda2ffb1bebde518d8e9c6e /dirmngr/ks-engine-http.c | |
parent | doc: Clarify use of clear and nodefault in the AKL. (diff) | |
download | gnupg-4a4bb874f63741026bd26264c43bb32b1099f060.tar.gz gnupg-4a4bb874f63741026bd26264c43bb32b1099f060.zip |
dirmngr: Avoid possible CSRF attacks via http redirects.
* dirmngr/http.h (parsed_uri_s): Add fields off_host and off_path.
(http_redir_info_t): New.
* dirmngr/http.c (do_parse_uri): Set new fields.
(same_host_p): New.
(http_prepare_redirect): New.
* dirmngr/t-http-basic.c: New test.
* dirmngr/ks-engine-hkp.c (send_request): Use http_prepare_redirect
instead of the open code.
* dirmngr/ks-engine-http.c (ks_http_fetch): Ditto.
--
With this change a http query will not follow a redirect unless the
Location header gives the same host. If the host is different only
the host and port is taken from the Location header and the original
path and query parts are kept.
Signed-off-by: Werner Koch <[email protected]>
(cherry picked from commit fa1b1eaa4241ff3f0634c8bdf8591cbc7c464144)
Diffstat (limited to 'dirmngr/ks-engine-http.c')
-rw-r--r-- | dirmngr/ks-engine-http.c | 68 |
1 files changed, 18 insertions, 50 deletions
diff --git a/dirmngr/ks-engine-http.c b/dirmngr/ks-engine-http.c index 946c92769..1abb3501d 100644 --- a/dirmngr/ks-engine-http.c +++ b/dirmngr/ks-engine-http.c @@ -74,17 +74,18 @@ ks_http_fetch (ctrl_t ctrl, const char *url, unsigned int flags, http_session_t session = NULL; unsigned int session_flags; http_t http = NULL; - int redirects_left = MAX_REDIRECTS; + http_redir_info_t redirinfo = { MAX_REDIRECTS }; estream_t fp = NULL; char *request_buffer = NULL; parsed_uri_t uri = NULL; - int is_onion, is_https; err = http_parse_uri (&uri, url, 0); if (err) goto leave; - is_onion = uri->onion; - is_https = uri->use_tls; + redirinfo.orig_url = url; + redirinfo.orig_onion = uri->onion; + redirinfo.orig_https = uri->use_tls; + redirinfo.allow_downgrade = !!(flags & KS_HTTP_FETCH_ALLOW_DOWNGRADE); /* By default we only use the system provided certificates with this * fetch command. */ @@ -158,53 +159,20 @@ ks_http_fetch (ctrl_t ctrl, const char *url, unsigned int flags, case 302: case 307: { - const char *s = http_get_header (http, "Location"); - - log_info (_("URL '%s' redirected to '%s' (%u)\n"), - url, s?s:"[none]", http_get_status_code (http)); - if (s && *s && redirects_left-- ) - { - if (is_onion || is_https) - { - /* Make sure that an onion address only redirects to - * another onion address, or that a https address - * only redirects to a https address. */ - http_release_parsed_uri (uri); - uri = NULL; - err = http_parse_uri (&uri, s, 0); - if (err) - goto leave; - - if (is_onion && !uri->onion) - { - err = gpg_error (GPG_ERR_FORBIDDEN); - goto leave; - } - if (!(flags & KS_HTTP_FETCH_ALLOW_DOWNGRADE) - && is_https && !uri->use_tls) - { - err = gpg_error (GPG_ERR_FORBIDDEN); - goto leave; - } - } - - xfree (request_buffer); - request_buffer = xtrystrdup (s); - if (request_buffer) - { - url = request_buffer; - http_close (http, 0); - http = NULL; - http_session_release (session); - goto once_more; - } - err = gpg_error_from_syserror (); - } - else - err = gpg_error (GPG_ERR_NO_DATA); - log_error (_("too many redirections\n")); + xfree (request_buffer); + err = http_prepare_redirect (&redirinfo, http_get_status_code (http), + http_get_header (http, "Location"), + &request_buffer); + if (err) + goto leave; + + url = request_buffer; + http_close (http, 0); + http = NULL; + http_session_release (session); + session = NULL; } - goto leave; + goto once_more; default: log_error (_("error accessing '%s': http status %u\n"), |