checkpoint: implement wgcloak v1 foundations
This commit is contained in:
commit
313ab00765
45 files changed
+12058
No files matched your search
@@ -0,0 +1,96 @@
|
||||
#[path = "../src/transport/http3.rs"]
|
||||
mod http3;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use http3::{
|
||||
decode_capsule, decode_http_datagram, encode_auth_challenge, encode_auth_response,
|
||||
encode_capsule, encode_http_datagram, validate_connect_udp_request, AuthChallenge,
|
||||
ConnectUdpRequest, Http3Error, CONNECT_UDP_CONTEXT_ID,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn validates_extended_connect_request() {
|
||||
validate_connect_udp_request("CONNECT", "connect-udp", "/tunnel", "/tunnel").unwrap();
|
||||
ConnectUdpRequest::new("/tunnel")
|
||||
.validate("/tunnel")
|
||||
.unwrap();
|
||||
assert!(matches!(
|
||||
validate_connect_udp_request("POST", "connect-udp", "/tunnel", "/tunnel"),
|
||||
Err(Http3Error::InvalidRequest("method must be CONNECT"))
|
||||
));
|
||||
assert!(matches!(
|
||||
validate_connect_udp_request("CONNECT", "webtransport", "/tunnel", "/tunnel"),
|
||||
Err(Http3Error::InvalidRequest(":protocol must be connect-udp"))
|
||||
));
|
||||
assert!(validate_connect_udp_request("CONNECT", "connect-udp", "/other", "/tunnel").is_err());
|
||||
assert!(validate_connect_udp_request("CONNECT", "connect-udp", "tunnel", "tunnel").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn http_datagram_uses_context_id_and_preserves_opaque_payload() {
|
||||
for context in [0, 63, 64, 16_383, 16_384, (1 << 30) - 1, 1 << 30] {
|
||||
let encoded = encode_http_datagram(context, b"opaque", 1200).unwrap();
|
||||
assert_eq!(
|
||||
decode_http_datagram(&encoded, context, 1200).unwrap(),
|
||||
b"opaque"[..]
|
||||
);
|
||||
}
|
||||
assert!(matches!(
|
||||
decode_http_datagram(
|
||||
&encode_http_datagram(7, b"x", 1200).unwrap(),
|
||||
CONNECT_UDP_CONTEXT_ID,
|
||||
1200
|
||||
),
|
||||
Err(Http3Error::ContextMismatch { .. })
|
||||
));
|
||||
assert!(matches!(
|
||||
encode_http_datagram(CONNECT_UDP_CONTEXT_ID, &[0; 1201], 1200),
|
||||
Err(Http3Error::Oversized {
|
||||
length: 1201,
|
||||
maximum: 1200
|
||||
})
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn capsule_round_trip_and_truncation_are_checked() {
|
||||
let encoded = encode_capsule(0x2a, b"challenge").unwrap();
|
||||
assert_eq!(
|
||||
decode_capsule(&encoded).unwrap(),
|
||||
(0x2a, bytes::Bytes::from_static(b"challenge"))
|
||||
);
|
||||
assert!(matches!(
|
||||
decode_capsule(&encoded[..encoded.len() - 1]),
|
||||
Err(Http3Error::Truncated)
|
||||
));
|
||||
let mut extra = encoded.to_vec();
|
||||
extra.push(0);
|
||||
assert!(matches!(
|
||||
decode_capsule(&extra),
|
||||
Err(Http3Error::InvalidCapsule)
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn authentication_is_completed_before_session_activation() {
|
||||
let challenge = AuthChallenge::random();
|
||||
let nonce = [5u8; 16];
|
||||
let secret = [7u8; 32];
|
||||
let challenge_capsule = encode_auth_challenge(&challenge).unwrap();
|
||||
assert_eq!(
|
||||
decode_capsule(&challenge_capsule).unwrap().0,
|
||||
http3::AUTH_CHALLENGE_CAPSULE
|
||||
);
|
||||
let response = encode_auth_response(&challenge, "laptop", &nonce, &secret).unwrap();
|
||||
let mut clients = HashMap::new();
|
||||
clients.insert("laptop".to_owned(), secret.to_vec());
|
||||
let client = http3::verify_auth_response(&challenge, &response, &clients).unwrap();
|
||||
assert_eq!(client.id, "laptop");
|
||||
assert_eq!(client.nonce, nonce);
|
||||
|
||||
let bad = encode_auth_response(&challenge, "laptop", &nonce, &[8u8; 32]).unwrap();
|
||||
assert!(http3::verify_auth_response(&challenge, &bad, &clients).is_err());
|
||||
assert!(http3::is_auth_accept(&http3::encode_auth_accept().unwrap()).unwrap());
|
||||
assert!(!http3::is_auth_accept(&http3::encode_auth_reject().unwrap()).unwrap());
|
||||
}
|
||||
Reference in new issue
Block a user