diff --git a/src/client.rs b/src/client.rs index 364c2cd..1619529 100644 --- a/src/client.rs +++ b/src/client.rs @@ -364,7 +364,7 @@ impl RequestBuilder { } }; - headers = remove_sensitive_headers(headers, &url, &urls); + remove_sensitive_headers(&mut headers, &url, &urls); debug!("redirecting to {:?} '{}'", method, url); } else { return Ok(::response::new(res, client.auto_ungzip.load(Ordering::Relaxed))) diff --git a/src/redirect.rs b/src/redirect.rs index 6823146..3b71f10 100644 --- a/src/redirect.rs +++ b/src/redirect.rs @@ -1,9 +1,8 @@ use std::fmt; -use ::Url; +use hyper::header::{Headers, Authorization, Cookie}; -#[allow(unused_imports)] -use hyper::header::{Headers, Authorization, Cookie, Accept}; +use ::Url; /// A type that controls the policy on how to handle the following of redirects. /// @@ -182,14 +181,17 @@ pub fn check_redirect(policy: &RedirectPolicy, next: &Url, previous: &[Url]) -> }).inner } -pub fn remove_sensitive_headers(mut headers: Headers, next: &Url, previous: &[Url]) -> Headers { - let cross_host = next.host().unwrap() != previous.last().unwrap().host().unwrap(); - if cross_host { - headers.remove::>(); - headers.remove::(); - headers.remove_raw("www-authenticate"); +pub fn remove_sensitive_headers(headers: &mut Headers, next: &Url, previous: &[Url]) { + if let Some(previous) = previous.last() { + let cross_host = next.host_str() != previous.host_str() + || next.port_or_known_default() != previous.port_or_known_default(); + if cross_host { + headers.remove::>(); + headers.remove::(); + headers.remove_raw("cookie2"); + headers.remove_raw("www-authenticate"); + } } - headers } /* @@ -245,6 +247,8 @@ fn test_redirect_policy_custom() { #[test] fn test_remove_sensitive_headers() { + use hyper::header::Accept; + let mut headers = Headers::new(); headers.set(Accept::star()); headers.set(Authorization("let me in".to_owned())); @@ -256,13 +260,15 @@ fn test_remove_sensitive_headers() { let next = Url::parse("http://initial-domain.com/path").unwrap(); let mut prev = vec![Url::parse("http://initial-domain.com/new_path").unwrap()]; - - assert_eq!(remove_sensitive_headers(headers.clone(), &next, &prev), headers); + let mut filtered_headers = headers.clone(); + + remove_sensitive_headers(&mut headers, &next, &prev); + assert_eq!(headers, filtered_headers); prev.push(Url::parse("http://new-domain.com/path").unwrap()); - let mut filtered_headers = headers.clone(); filtered_headers.remove::>(); filtered_headers.remove::(); - assert_eq!(remove_sensitive_headers(headers.clone(), &next, &prev), filtered_headers); -} \ No newline at end of file + remove_sensitive_headers(&mut headers, &next, &prev); + assert_eq!(headers, filtered_headers); +} diff --git a/tests/client.rs b/tests/client.rs index c23cdca..dd49295 100644 --- a/tests/client.rs +++ b/tests/client.rs @@ -186,6 +186,55 @@ fn test_redirect_307_does_not_try_if_reader_cannot_reset() { } } +#[test] +fn test_redirect_removes_sensitive_headers() { + let end_server = server! { + request: b"\ + GET /otherhost HTTP/1.1\r\n\ + Host: $HOST\r\n\ + User-Agent: $USERAGENT\r\n\ + Accept: */*\r\n\ + Accept-Encoding: gzip\r\n\ + \r\n\ + ", + response: b"\ + HTTP/1.1 200 OK\r\n\ + Server: test\r\n\ + Content-Length: 0\r\n\ + \r\n\ + " + }; + + let mid_server = server! { + request: b"\ + GET /sensitive HTTP/1.1\r\n\ + Host: $HOST\r\n\ + Cookie: foo=bar\r\n\ + User-Agent: $USERAGENT\r\n\ + Accept: */*\r\n\ + Accept-Encoding: gzip\r\n\ + \r\n\ + ", + response: format!("\ + HTTP/1.1 302 Found\r\n\ + Server: test\r\n\ + Location: http://{}/otherhost\r\n\ + Content-Length: 0\r\n\ + \r\n\ + ", end_server.addr()) + }; + + let mut client = reqwest::Client::new().unwrap(); + client.referer(false); + client.get(&format!("http://{}/sensitive", mid_server.addr())) + .header( + reqwest::header::Cookie(vec![ + String::from("foo=bar") + ]) + ) + .send().unwrap(); +} + #[test] fn test_redirect_policy_can_return_errors() { let server = server! {