完善routerkey和aspa功能
This commit is contained in:
123
tests/test_loader.rs
Normal file
123
tests/test_loader.rs
Normal file
@@ -0,0 +1,123 @@
|
||||
use std::net::IpAddr;
|
||||
use std::str::FromStr;
|
||||
|
||||
use rpki::rtr::loader::{
|
||||
parse_aspa_line, parse_router_key_line, parse_vrp_line, ParsedAspa, ParsedVrp,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn parse_ipv4_vrp_line() {
|
||||
let got = parse_vrp_line("10.0.0.0/24,24,65001").unwrap();
|
||||
assert_eq!(
|
||||
got,
|
||||
ParsedVrp {
|
||||
prefix_addr: IpAddr::from_str("10.0.0.0").unwrap(),
|
||||
prefix_len: 24,
|
||||
max_len: 24,
|
||||
asn: 65001,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_ipv6_vrp_line() {
|
||||
let got = parse_vrp_line("2001:db8::/32,48,65003").unwrap();
|
||||
assert_eq!(
|
||||
got,
|
||||
ParsedVrp {
|
||||
prefix_addr: IpAddr::from_str("2001:db8::").unwrap(),
|
||||
prefix_len: 32,
|
||||
max_len: 48,
|
||||
asn: 65003,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_rejects_invalid_max_len() {
|
||||
let err = parse_vrp_line("10.0.0.0/24,16,65001").unwrap_err();
|
||||
assert!(err.to_string().contains("max_len"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_rejects_invalid_ip() {
|
||||
let err = parse_vrp_line("10.0.0.999/24,24,65001").unwrap_err();
|
||||
assert!(err.to_string().contains("invalid IP"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_rejects_invalid_format() {
|
||||
let err = parse_vrp_line("10.0.0.0/24,24").unwrap_err();
|
||||
assert!(err.to_string().contains("expected format"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_aspa_line_ok() {
|
||||
let got = parse_aspa_line("64496,64497 64498").unwrap();
|
||||
assert_eq!(
|
||||
got,
|
||||
ParsedAspa {
|
||||
customer_asn: 64496,
|
||||
provider_asns: vec![64497, 64498],
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_aspa_rejects_empty_provider_list() {
|
||||
let err = parse_aspa_line("64496,").unwrap_err();
|
||||
assert!(err.to_string().contains("provider list"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_aspa_rejects_as0() {
|
||||
let err = parse_aspa_line("0,64497").unwrap_err();
|
||||
assert!(err.to_string().contains("AS0"));
|
||||
|
||||
let err = parse_aspa_line("64496,0").unwrap_err();
|
||||
assert!(err.to_string().contains("AS0"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_router_key_line_ok() {
|
||||
let got = parse_router_key_line(
|
||||
"00112233445566778899aabbccddeeff00112233,64496,3013300d06092a864886f70d010101050003020000",
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(got.asn, 64496);
|
||||
assert_eq!(
|
||||
got.ski,
|
||||
[
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
|
||||
0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33,
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
got.spki,
|
||||
vec![
|
||||
0x30, 0x13, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
|
||||
0x01, 0x01, 0x05, 0x00, 0x03, 0x02, 0x00, 0x00,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_router_key_rejects_invalid_ski_length() {
|
||||
let err = parse_router_key_line("0011,64496,deadbeef").unwrap_err();
|
||||
assert!(err.to_string().contains("SKI"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_router_key_rejects_empty_spki() {
|
||||
let err =
|
||||
parse_router_key_line("00112233445566778899aabbccddeeff00112233,64496,").unwrap_err();
|
||||
assert!(err.to_string().contains("SPKI"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_router_key_rejects_invalid_spki_der() {
|
||||
let err =
|
||||
parse_router_key_line("00112233445566778899aabbccddeeff00112233,64496,deadbeef")
|
||||
.unwrap_err();
|
||||
assert!(err.to_string().contains("valid DER"));
|
||||
}
|
||||
@@ -113,6 +113,22 @@ async fn router_key_length_matches_wire_size() {
|
||||
assert_eq!(header.length(), 8 + 20 + 4 + 32);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn router_key_read_rejects_reserved_zero_octet() {
|
||||
let (mut client, mut server) = duplex(1024);
|
||||
let mut bytes = vec![1, RouterKey::PDU, 1, 1];
|
||||
bytes.extend_from_slice(&(8u32 + 20 + 4 + 4).to_be_bytes());
|
||||
bytes.extend_from_slice(&[0u8; 20]);
|
||||
bytes.extend_from_slice(&64496u32.to_be_bytes());
|
||||
bytes.extend_from_slice(&[1, 2, 3, 4]);
|
||||
|
||||
client.write_all(&bytes).await.unwrap();
|
||||
|
||||
let err = RouterKey::read(&mut server).await.unwrap_err();
|
||||
assert_eq!(err.kind(), std::io::ErrorKind::InvalidData);
|
||||
assert!(err.to_string().contains("zero octet"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn aspa_length_matches_wire_size() {
|
||||
let pdu = Aspa::new(2, Flags::new(1), 64496, vec![64497, 64498]);
|
||||
@@ -127,6 +143,37 @@ async fn aspa_length_matches_wire_size() {
|
||||
assert_eq!(header.length(), 8 + 4 + 8);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn aspa_read_rejects_unsorted_provider_list() {
|
||||
let (mut client, mut server) = duplex(1024);
|
||||
let mut bytes = vec![2, Aspa::PDU, 1, 0];
|
||||
bytes.extend_from_slice(&(20u32).to_be_bytes());
|
||||
bytes.extend_from_slice(&64496u32.to_be_bytes());
|
||||
bytes.extend_from_slice(&64498u32.to_be_bytes());
|
||||
bytes.extend_from_slice(&64497u32.to_be_bytes());
|
||||
|
||||
client.write_all(&bytes).await.unwrap();
|
||||
|
||||
let err = Aspa::read(&mut server).await.unwrap_err();
|
||||
assert_eq!(err.kind(), std::io::ErrorKind::InvalidData);
|
||||
assert!(err.to_string().contains("strictly increasing"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn aspa_read_rejects_withdraw_with_providers() {
|
||||
let (mut client, mut server) = duplex(1024);
|
||||
let mut bytes = vec![2, Aspa::PDU, 0, 0];
|
||||
bytes.extend_from_slice(&(16u32).to_be_bytes());
|
||||
bytes.extend_from_slice(&64496u32.to_be_bytes());
|
||||
bytes.extend_from_slice(&64497u32.to_be_bytes());
|
||||
|
||||
client.write_all(&bytes).await.unwrap();
|
||||
|
||||
let err = Aspa::read(&mut server).await.unwrap_err();
|
||||
assert_eq!(err.kind(), std::io::ErrorKind::InvalidData);
|
||||
assert!(err.to_string().contains("withdrawal"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aspa_announcement_rejects_empty_provider_list() {
|
||||
let err = PayloadAspa::new(Asn::from(64496u32), vec![])
|
||||
@@ -136,6 +183,19 @@ fn aspa_announcement_rejects_empty_provider_list() {
|
||||
assert!(err.to_string().contains("at least one provider"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn router_key_payload_rejects_invalid_spki() {
|
||||
let err = rpki::rtr::payload::RouterKey::new(
|
||||
Ski::default(),
|
||||
Asn::from(64496u32),
|
||||
vec![0xde, 0xad, 0xbe, 0xef],
|
||||
)
|
||||
.validate()
|
||||
.unwrap_err();
|
||||
assert_eq!(err.kind(), std::io::ErrorKind::InvalidData);
|
||||
assert!(err.to_string().contains("valid DER"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aspa_announcement_rejects_as0() {
|
||||
let err = PayloadAspa::new(Asn::from(0u32), vec![Asn::from(64497u32)])
|
||||
|
||||
@@ -1780,3 +1780,41 @@ async fn invalid_aspa_prevents_snapshot_response() {
|
||||
let err = join.expect_err("session should fail on invalid ASPA");
|
||||
assert!(err.to_string().contains("ASPA announcement"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn invalid_router_key_prevents_snapshot_response() {
|
||||
let snapshot = Snapshot::from_payloads(vec![Payload::RouterKey(RouterKey::new(
|
||||
Ski::default(),
|
||||
Asn::from(64496u32),
|
||||
vec![0xde, 0xad, 0xbe, 0xef],
|
||||
))]);
|
||||
let cache = RtrCacheBuilder::new()
|
||||
.session_ids(SessionIds::from_array([42, 42, 42]))
|
||||
.serial(100)
|
||||
.timing(Timing::new(600, 600, 7200))
|
||||
.snapshot(snapshot)
|
||||
.build();
|
||||
|
||||
let server_cache = shared_cache(cache);
|
||||
let (addr, shutdown_tx, server_handle) = start_session_server_returning_result(server_cache).await;
|
||||
|
||||
let mut client = TcpStream::connect(addr).await.unwrap();
|
||||
ResetQuery::new(1).write(&mut client).await.unwrap();
|
||||
|
||||
let response = CacheResponse::read(&mut client).await.unwrap();
|
||||
assert_eq!(response.version(), 1);
|
||||
assert_eq!(response.session_id(), 42);
|
||||
|
||||
let read_res = timeout(Duration::from_secs(1), Header::read(&mut client))
|
||||
.await
|
||||
.expect("timed out waiting for server close");
|
||||
assert!(read_res.is_err(), "server should close instead of sending invalid RouterKey");
|
||||
|
||||
let _ = shutdown_tx.send(true);
|
||||
let join = timeout(Duration::from_secs(1), server_handle)
|
||||
.await
|
||||
.expect("server task did not exit within timeout")
|
||||
.unwrap();
|
||||
let err = join.expect_err("session should fail on invalid RouterKey");
|
||||
assert!(err.to_string().contains("RouterKey SPKI"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user