diff options
author | Wiktor Kwapisiewicz <wiktor@metacode.biz> | 2021-03-25 10:13:28 +0100 |
---|---|---|
committer | Wiktor Kwapisiewicz <wiktor@metacode.biz> | 2021-03-31 11:40:01 +0200 |
commit | ccfa5f6ffc170494a0f3ea5a3906c4b61c2df263 (patch) | |
tree | 87772a13cf6c64f8b3ef1863eec2a2542b731996 | |
parent | 6e943987de1beb3cd8c5406fec27266c313c90ee (diff) |
net: Protect against redirection loops in WKD requests.
- Use explicit depth to indicate how many redirects have been executed
and break the loop if the number is bigger than 10.
- Using `reqwest` was considered but rejected due to Tokio version
incompatibility (`reqwest` insists on using Tokio 1 while Sequoia
uses 0.2 in many places).
-rw-r--r-- | net/src/wkd.rs | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/net/src/wkd.rs b/net/src/wkd.rs index d061c7ef..cc14613c 100644 --- a/net/src/wkd.rs +++ b/net/src/wkd.rs @@ -237,13 +237,18 @@ fn parse_body<S: AsRef<str>>(body: &[u8], email_address: S) fn get_following_redirects<'a, T>( client: &'a hyper::client::Client<T>, url: Uri, -) -> BoxFuture<'a, hyper::Result<Response<Body>>> + depth: i32, +) -> BoxFuture<'a, Result<Response<Body>>> where T: hyper::client::connect::Connect + Clone + Send + Sync + 'static, { async move { let response = client.get(url).await; + if depth < 0 { + return Err(anyhow::anyhow!("Too many redirects")); + } + if let Ok(ref resp) = response { if resp.status().is_redirection() { let url = resp.headers().get("Location") @@ -251,12 +256,12 @@ where .flatten() .map(|value| value.parse::<Uri>()); if let Some(Ok(url)) = url { - return get_following_redirects(&client, url).await; + return get_following_redirects(&client, url, depth - 1).await; } } } - response + response.map_err(|err| anyhow::anyhow!(err)) } .boxed() } @@ -312,10 +317,12 @@ pub async fn get<S: AsRef<str>>(email_address: S) -> Result<Vec<Cert>> { let advanced_uri = wkd_url.to_uri(Variant::Advanced)?; let direct_uri = wkd_url.to_uri(Variant::Direct)?; + const REDIRECT_LIMIT: i32 = 10; + // First, try the Advanced Method. - let res = get_following_redirects(&client, advanced_uri) + let res = get_following_redirects(&client, advanced_uri, REDIRECT_LIMIT) // Fall back to the Direct Method. - .or_else(|_| get_following_redirects(&client, direct_uri)) + .or_else(|_| get_following_redirects(&client, direct_uri, REDIRECT_LIMIT)) .await?; let body = hyper::body::to_bytes(res.into_body()).await?; |