diff --git a/src/client/proxy/matcher.rs b/src/client/proxy/matcher.rs index d0b71981..3ec90fd6 100644 --- a/src/client/proxy/matcher.rs +++ b/src/client/proxy/matcher.rs @@ -657,6 +657,41 @@ mod mac { #[cfg(feature = "client-proxy-system")] #[cfg(windows)] mod win { + fn ipv4_wildcard_to_cidr(value: &str) -> Option { + let parts = value.split('.').collect::>(); + let wildcard = parts.iter().position(|part| *part == "*")?; + + if wildcard == 0 || wildcard > 3 || parts[wildcard..].iter().any(|part| *part != "*") { + return None; + } + + let mut octets = [0; 4]; + for (index, part) in parts[..wildcard].iter().enumerate() { + octets[index] = part.parse().ok()?; + } + + Some(format!( + "{}.{}.{}.{}/{}", + octets[0], + octets[1], + octets[2], + octets[3], + wildcard * 8 + )) + } + + pub(super) fn normalize_proxy_override(value: &str) -> String { + value + .split(';') + .map(|entry| { + let entry = entry.trim(); + ipv4_wildcard_to_cidr(entry).unwrap_or_else(|| entry.to_string()) + }) + .collect::>() + .join(",") + .replace("*.", "") + } + pub(super) fn with_system(builder: &mut super::Builder) { let settings = if let Ok(settings) = windows_registry::CURRENT_USER .open("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings") @@ -681,12 +716,7 @@ mod win { if builder.no.is_empty() { if let Ok(val) = settings.get_string("ProxyOverride") { - builder.no = val - .split(';') - .map(|s| s.trim()) - .collect::>() - .join(",") - .replace("*.", ""); + builder.no = normalize_proxy_override(&val); } } } @@ -778,6 +808,25 @@ mod tests { } } + #[cfg(all(feature = "client-proxy-system", windows))] + #[test] + fn test_windows_proxy_override_ip_wildcard() { + let normalized = + win::normalize_proxy_override("127.*; 10.*.*.*; 192.168.*; 192.168.1.*; *.example.com"); + let no_proxy = NoProxy::from_string(&normalized); + + assert!(no_proxy.contains("127.0.0.1")); + assert!(no_proxy.contains("10.12.34.56")); + assert!(no_proxy.contains("192.168.42.1")); + assert!(no_proxy.contains("192.168.1.42")); + assert!(no_proxy.contains("www.example.com")); + assert!(!no_proxy.contains("128.0.0.1")); + assert!(!no_proxy.contains("192.169.42.1")); + + let subnet = NoProxy::from_string(&win::normalize_proxy_override("192.168.1.*")); + assert!(!subnet.contains("192.168.2.42")); + } + macro_rules! p { ($($n:ident = $v:expr,)*) => ({Builder { $($n: $v.into(),)*