From 1a8260bd6b9b811d29b0dad57c1aefc77582149b Mon Sep 17 00:00:00 2001 From: mdecimus Date: Mon, 5 Aug 2024 19:46:29 +0200 Subject: [PATCH] Properly parse Forwarded and X-Forwarded for headers (closes #669) --- crates/jmap/src/api/http.rs | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/crates/jmap/src/api/http.rs b/crates/jmap/src/api/http.rs index a182b0ba..cb82d1a7 100644 --- a/crates/jmap/src/api/http.rs +++ b/crates/jmap/src/api/http.rs @@ -370,9 +370,39 @@ impl JmapInstance { } else if let Some(forwarded_for) = req .headers() .get(header::FORWARDED) - .or_else(|| req.headers().get("X-Forwarded-For")) .and_then(|h| h.to_str().ok()) - .and_then(|h| h.parse::().ok()) + .and_then(|h| { + let h = h.to_ascii_lowercase(); + h.split_once("for=").and_then(|(_, rest)| { + let mut start_ip = usize::MAX; + let mut end_ip = usize::MAX; + + for (pos, ch) in rest.char_indices() { + match ch { + '0'..='9' | 'a'..='f' | ':' | '.' => { + if start_ip == usize::MAX { + start_ip = pos; + } + end_ip = pos; + } + '"' | '[' | ' ' if start_ip == usize::MAX => {} + _ => { + break; + } + } + } + + rest.get(start_ip..=end_ip) + .and_then(|h| h.parse::().ok()) + }) + }) + .or_else(|| { + req.headers() + .get("X-Forwarded-For") + .and_then(|h| h.to_str().ok()) + .map(|h| h.split_once(',').map_or(h, |(ip, _)| ip).trim()) + .and_then(|h| h.parse::().ok()) + }) { forwarded_for } else {