This repository has no description
2.3 kB
62 lines
1use std::io::{Read, Write};
2use std::net::TcpListener;
3
4use knot_runtime::{HttpLimits, HttpRequest, HttpTransport, NetworkError, ReqwestHttp};
5use url::Url;
6
7#[tokio::test]
8async fn the_transport_refuses_a_loopback_target() {
9 let listener = TcpListener::bind("127.0.0.1:0").unwrap();
10 let port = listener.local_addr().unwrap().port();
11 let http = ReqwestHttp::new(HttpLimits::default()).unwrap();
12 let url = Url::parse(&format!("http://127.0.0.1:{port}/")).unwrap();
13 let error = http.execute(HttpRequest::get(url)).await.unwrap_err();
14 assert!(
15 matches!(error, NetworkError::Blocked { .. }),
16 "got {error:?}"
17 );
18 drop(listener);
19}
20
21#[tokio::test]
22async fn a_hostname_resolving_only_to_loopback_is_refused_at_dns() {
23 let listener = TcpListener::bind("127.0.0.1:0").unwrap();
24 let port = listener.local_addr().unwrap().port();
25 let http = ReqwestHttp::new(HttpLimits::default()).unwrap();
26 let url = Url::parse(&format!("https://localhost:{port}/")).unwrap();
27 let error = http.execute(HttpRequest::get(url)).await.unwrap_err();
28 assert!(
29 matches!(
30 error,
31 NetworkError::Connect(_) | NetworkError::Request(_) | NetworkError::Timeout(_)
32 ),
33 "hostname whose only addresses are loopback must fail to connect, got {error:?}"
34 );
35 drop(listener);
36}
37
38#[tokio::test]
39async fn a_redirect_to_an_internal_host_is_not_followed() {
40 let listener = TcpListener::bind("127.0.0.1:0").unwrap();
41 let addr = listener.local_addr().unwrap();
42 std::thread::spawn(move || {
43 if let Ok((mut stream, _)) = listener.accept() {
44 let _ = stream.read(&mut [0u8; 1024]);
45 let _ = stream.write_all(
46 b"HTTP/1.1 302 Found\r\nLocation: http://169.254.169.254/\r\nContent-Length: 0\r\n\r\n",
47 );
48 }
49 });
50 let limits = HttpLimits {
51 block_private_addresses: false,
52 ..HttpLimits::default()
53 };
54 let http = ReqwestHttp::new(limits).unwrap();
55 let url = Url::parse(&format!("http://{addr}/")).unwrap();
56 let response = http.execute(HttpRequest::get(url)).await.unwrap();
57 assert_eq!(
58 response.status.as_u16(),
59 302,
60 "302 is surfaced verbatim, redirect to internal host is never followed"
61 );
62}