Fix post merge integration test issue

This commit is contained in:
Prabhpreet Dua
2024-04-15 14:25:09 +05:30
parent 4ea51ab123
commit a3e91a95df
6 changed files with 95 additions and 13 deletions

49
Cargo.lock generated
View File

@@ -245,6 +245,38 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "camino"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c"
dependencies = [
"serde",
]
[[package]]
name = "cargo-platform"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc"
dependencies = [
"serde",
]
[[package]]
name = "cargo_metadata"
version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a"
dependencies = [
"camino",
"cargo-platform",
"semver",
"serde",
"serde_json",
"thiserror",
]
[[package]] [[package]]
name = "cast" name = "cast"
version = "0.3.0" version = "0.3.0"
@@ -1139,6 +1171,7 @@ dependencies = [
"serde", "serde",
"stacker", "stacker",
"static_assertions", "static_assertions",
"test-binary",
"test_bin", "test_bin",
"thiserror", "thiserror",
"toml", "toml",
@@ -1290,6 +1323,9 @@ name = "semver"
version = "1.0.21" version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "serde" name = "serde"
@@ -1403,6 +1439,19 @@ dependencies = [
"winapi-util", "winapi-util",
] ]
[[package]]
name = "test-binary"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c7cb854285c40b61c0fade358bf63a2bb1226688a1ea11432ea65349209e6e3"
dependencies = [
"camino",
"cargo_metadata",
"once_cell",
"paste",
"thiserror",
]
[[package]] [[package]]
name = "test_bin" name = "test_bin"
version = "0.4.0" version = "0.4.0"

View File

@@ -60,3 +60,4 @@ chacha20poly1305 = { version = "0.10.1", default-features = false, features = [
libc = "0.2" libc = "0.2"
zerocopy = { version = "0.7.32", features = ["derive"] } zerocopy = { version = "0.7.32", features = ["derive"] }
home = "0.5.9" home = "0.5.9"
test-binary = "3.0.2"

View File

@@ -9,6 +9,15 @@ homepage = "https://rosenpass.eu/"
repository = "https://github.com/rosenpass/rosenpass" repository = "https://github.com/rosenpass/rosenpass"
readme = "readme.md" readme = "readme.md"
[[bin]]
name = "rosenpass"
path = "src/main.rs"
[[bin]]
name = "rp-it-dos"
required-features = ["integration_test_dos_exchange"]
path = "src/main.rs"
[[bench]] [[bench]]
name = "handshake" name = "handshake"
harness = false harness = false
@@ -42,7 +51,9 @@ anyhow = { workspace = true }
[dev-dependencies] [dev-dependencies]
criterion = { workspace = true } criterion = { workspace = true }
test_bin = { workspace = true } test_bin = { workspace = true }
test-binary = { workspace = true }
stacker = { workspace = true } stacker = { workspace = true }
libc = { workspace = true}
[features] [features]
integration_test = ["dep:libc"] integration_test_dos_exchange = ["dep:libc"]

View File

@@ -34,13 +34,13 @@ use rosenpass_util::b64::{b64_writer, fmt_b64};
const IPV4_ANY_ADDR: Ipv4Addr = Ipv4Addr::new(0, 0, 0, 0); const IPV4_ANY_ADDR: Ipv4Addr = Ipv4Addr::new(0, 0, 0, 0);
const IPV6_ANY_ADDR: Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0); const IPV6_ANY_ADDR: Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
#[cfg(feature = "integration_test")] #[cfg(feature = "integration_test_dos_exchange")]
const UNDER_LOAD_RATIO: f64 = 0.001; const UNDER_LOAD_RATIO: f64 = 0.001;
#[cfg(feature = "integration_test")] #[cfg(feature = "integration_test_dos_exchange")]
const DURATION_UPDATE_UNDER_LOAD_STATUS: Duration = Duration::from_millis(10); const DURATION_UPDATE_UNDER_LOAD_STATUS: Duration = Duration::from_millis(10);
#[cfg(not(feature = "integration_test"))] #[cfg(not(feature = "integration_test_dos_exchange"))]
const UNDER_LOAD_RATIO: f64 = 0.5; const UNDER_LOAD_RATIO: f64 = 0.5;
#[cfg(not(feature = "integration_test"))] #[cfg(not(feature = "integration_test_dos_exchange"))]
const DURATION_UPDATE_UNDER_LOAD_STATUS: Duration = Duration::from_millis(100); const DURATION_UPDATE_UNDER_LOAD_STATUS: Duration = Duration::from_millis(100);
fn ipv4_any_binding() -> SocketAddr { fn ipv4_any_binding() -> SocketAddr {
@@ -830,12 +830,12 @@ impl AppServer {
0.0 0.0
}; };
#[cfg(feature = "integration_test")] #[cfg(feature = "integration_test_dos_exchange")]
let prev_under_load = self.under_load; let prev_under_load = self.under_load;
if load_ratio > UNDER_LOAD_RATIO { if load_ratio > UNDER_LOAD_RATIO {
self.under_load = DoSOperation::UnderLoad; self.under_load = DoSOperation::UnderLoad;
//Test feature- if under load goes to normal operation, write to file //Test feature- if under load goes to normal operation, write to file
#[cfg(feature = "integration_test")] #[cfg(feature = "integration_test_dos_exchange")]
{ {
if prev_under_load == DoSOperation::Normal { if prev_under_load == DoSOperation::Normal {
let sem_name = b"/rp_integration_test_under_dos\0"; let sem_name = b"/rp_integration_test_under_dos\0";
@@ -853,7 +853,10 @@ impl AppServer {
} }
} }
} else { } else {
self.under_load = DoSOperation::Normal; // Don't switch to normal operation if executing integration test for DoS exchange
if cfg!(not(feature = "integration_test_dos_exchange")) {
self.under_load = DoSOperation::Normal;
}
} }
self.blocking_polls_count = 0; self.blocking_polls_count = 0;

View File

@@ -1498,12 +1498,13 @@ impl<M> Envelope<M>
where where
M: AsBytes + FromBytes, M: AsBytes + FromBytes,
{ {
/// Calculate the message authentication code (`mac`) /// Calculate the message authentication code (`mac`) and also append cookie value
pub fn seal(&mut self, peer: PeerPtr, srv: &CryptoServer) -> Result<()> { pub fn seal(&mut self, peer: PeerPtr, srv: &CryptoServer) -> Result<()> {
let mac = hash_domains::mac()? let mac = hash_domains::mac()?
.mix(peer.get(srv).spkt.secret())? .mix(peer.get(srv).spkt.secret())?
.mix(&self.as_bytes()[span_of!(Self, msg_type..mac)])?; .mix(&self.as_bytes()[span_of!(Self, msg_type..mac)])?;
self.mac.copy_from_slice(mac.into_value()[..16].as_ref()); self.mac.copy_from_slice(mac.into_value()[..16].as_ref());
self.seal_cookie(peer, srv)?;
Ok(()) Ok(())
} }

View File

@@ -123,10 +123,23 @@ fn check_exchange_under_normal() {
fs::remove_dir_all(&tmpdir).unwrap(); fs::remove_dir_all(&tmpdir).unwrap();
} }
// check that we can exchange keys // check that we can trigger a DoS condition and we can exchange keys under DoS
#[cfg(feature = "integration_test")] // This test creates a responder (server) with the feature flag "integration_test_dos_exchange". The feature flag posts a semaphore
// (linux) to indicate that the server is under load condition. It also modifies the responders behaviour to be permanently under DoS condition
// once triggered, and makes the DoS mechanism more sensitive to be easily triggered.
// The test also creates a thread to send UDP packets to the server to trigger the DoS condition. The test waits for the server to
// be under load condition and then stops the DoS attack. The test then starts the client (initiator) to exchange keys. The test checks that the keys are exchanged successfully under load condition.
#[test] #[test]
fn check_exchange_under_dos() { fn check_exchange_under_dos() {
//Generate binary with responder with feature integration_test
let server_test_bin = test_binary::TestBinary::relative_to_parent(
"rp-it-dos",
&PathBuf::from_iter(["Cargo.toml"]),
)
.with_feature("integration_test_dos_exchange")
.build()
.unwrap();
let tmpdir = PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join("exchange-dos"); let tmpdir = PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join("exchange-dos");
fs::create_dir_all(&tmpdir).unwrap(); fs::create_dir_all(&tmpdir).unwrap();
@@ -164,7 +177,8 @@ fn check_exchange_under_dos() {
} }
}; };
let listen_addr = format!("localhost:{port}"); let listen_addr = format!("localhost:{port}");
let mut server = test_bin::get_test_bin(BIN) let mut server = std::process::Command::new(server_test_bin)
.args(["--log-level", "debug"])
.args(["exchange", "secret-key"]) .args(["exchange", "secret-key"])
.arg(&secret_key_paths[0]) .arg(&secret_key_paths[0])
.arg("public-key") .arg("public-key")
@@ -226,8 +240,12 @@ fn check_exchange_under_dos() {
panic!("Failed to wait for semaphore- load condition not reached"); panic!("Failed to wait for semaphore- load condition not reached");
} }
//Stop DoS attack
stop_dos_handle.store(true, std::sync::atomic::Ordering::Relaxed);
// start second process, the client // start second process, the client
let mut client = test_bin::get_test_bin(BIN) let mut client = test_bin::get_test_bin(BIN)
.args(["--log-level", "debug"])
.args(["exchange", "secret-key"]) .args(["exchange", "secret-key"])
.arg(&secret_key_paths[1]) .arg(&secret_key_paths[1])
.arg("public-key") .arg("public-key")
@@ -248,7 +266,6 @@ fn check_exchange_under_dos() {
// time's up, kill the childs // time's up, kill the childs
server.kill().unwrap(); server.kill().unwrap();
client.kill().unwrap(); client.kill().unwrap();
stop_dos_handle.store(true, std::sync::atomic::Ordering::Relaxed);
dos_attack.join().unwrap(); dos_attack.join().unwrap();
// read the shared keys they created // read the shared keys they created