Compare commits

...

2 Commits

Author SHA1 Message Date
Dennis Schwerdel 7b0718399c More tests 2020-10-11 22:47:55 +02:00
Dennis Schwerdel 5bb0187726 More tests + clippy changes 2020-10-11 21:45:28 +02:00
4 changed files with 93 additions and 18 deletions

View File

@ -442,9 +442,9 @@ impl<D: Device, P: Protocol, S: Socket, TS: TimeSource> GenericCloud<D, P, S, TS
fn store_beacon(&mut self) -> Result<(), Error> { fn store_beacon(&mut self) -> Result<(), Error> {
if let Some(ref path) = self.config.beacon_store { if let Some(ref path) = self.config.beacon_store {
let peers: Vec<_> = self.own_addresses.choose_multiple(&mut thread_rng(), 3).cloned().collect(); let peers: Vec<_> = self.own_addresses.choose_multiple(&mut thread_rng(), 3).cloned().collect();
if path.starts_with('|') { if let Some(path) = path.strip_prefix('|') {
self.beacon_serializer self.beacon_serializer
.write_to_cmd(&peers, &path[1..]) .write_to_cmd(&peers, path)
.map_err(|e| Error::BeaconIo("Failed to call beacon command", e))?; .map_err(|e| Error::BeaconIo("Failed to call beacon command", e))?;
} else { } else {
self.beacon_serializer self.beacon_serializer
@ -459,9 +459,9 @@ impl<D: Device, P: Protocol, S: Socket, TS: TimeSource> GenericCloud<D, P, S, TS
fn load_beacon(&mut self) -> Result<(), Error> { fn load_beacon(&mut self) -> Result<(), Error> {
let peers; let peers;
if let Some(ref path) = self.config.beacon_load { if let Some(ref path) = self.config.beacon_load {
if path.starts_with('|') { if let Some(path) = path.strip_prefix('|') {
self.beacon_serializer self.beacon_serializer
.read_from_cmd(&path[1..], Some(50)) .read_from_cmd(path, Some(50))
.map_err(|e| Error::BeaconIo("Failed to call beacon command", e))?; .map_err(|e| Error::BeaconIo("Failed to call beacon command", e))?;
return Ok(()) return Ok(())
} else { } else {

View File

@ -17,8 +17,8 @@ pub const DEFAULT_PORT: u16 = 3210;
fn parse_listen(addr: &str) -> SocketAddr { fn parse_listen(addr: &str) -> SocketAddr {
if addr.starts_with("*:") { if let Some(addr) = addr.strip_prefix("*:") {
let port = try_fail!(addr[2..].parse::<u16>(), "Invalid port: {}"); let port = try_fail!(addr.parse::<u16>(), "Invalid port: {}");
SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), port) SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), port)
} else if addr.contains(':') { } else if addr.contains(':') {
try_fail!(addr.parse::<SocketAddr>(), "Invalid address: {}: {}", addr) try_fail!(addr.parse::<SocketAddr>(), "Invalid address: {}: {}", addr)

View File

@ -381,7 +381,7 @@ pub struct InitState<P: Payload> {
salted_node_id_hash: SaltedNodeIdHash, salted_node_id_hash: SaltedNodeIdHash,
payload: P, payload: P,
key_pair: Arc<Ed25519KeyPair>, key_pair: Arc<Ed25519KeyPair>,
trusted_keys: Arc<Vec<Ed25519PublicKey>>, trusted_keys: Arc<[Ed25519PublicKey]>,
ecdh_private_key: Option<EcdhPrivateKey>, ecdh_private_key: Option<EcdhPrivateKey>,
next_stage: u8, next_stage: u8,
close_time: usize, close_time: usize,
@ -393,7 +393,7 @@ pub struct InitState<P: Payload> {
impl<P: Payload> InitState<P> { impl<P: Payload> InitState<P> {
pub fn new( pub fn new(
node_id: NodeId, payload: P, key_pair: Arc<Ed25519KeyPair>, trusted_keys: Arc<Vec<Ed25519PublicKey>>, node_id: NodeId, payload: P, key_pair: Arc<Ed25519KeyPair>, trusted_keys: Arc<[Ed25519PublicKey]>,
algorithms: Algorithms algorithms: Algorithms
) -> Self ) -> Self
{ {
@ -449,6 +449,7 @@ impl<P: Payload> InitState<P> {
self.repeat_last_message(out); self.repeat_last_message(out);
Ok(()) Ok(())
} else { } else {
self.next_stage = CLOSING;
Err(Error::CryptoInit("Initialization timeout")) Err(Error::CryptoInit("Initialization timeout"))
} }
} }
@ -494,9 +495,7 @@ impl<P: Payload> InitState<P> {
hash == d.as_ref() hash == d.as_ref()
} }
fn send_message( fn send_message(&mut self, stage: u8, ecdh_public_key: Option<EcdhPublicKey>, out: &mut MsgBuffer) {
&mut self, stage: u8, ecdh_public_key: Option<EcdhPublicKey>, out: &mut MsgBuffer
) {
debug!("Sending init with stage={}", stage); debug!("Sending init with stage={}", stage);
assert!(out.is_empty()); assert!(out.is_empty());
let mut public_key = [0; ED25519_PUBLIC_KEY_LEN]; let mut public_key = [0; ED25519_PUBLIC_KEY_LEN];
@ -678,7 +677,7 @@ mod tests {
let key_pair = Arc::new(Ed25519KeyPair::from_pkcs8(pkcs8_bytes.as_ref()).unwrap()); let key_pair = Arc::new(Ed25519KeyPair::from_pkcs8(pkcs8_bytes.as_ref()).unwrap());
let mut public_key = [0; ED25519_PUBLIC_KEY_LEN]; let mut public_key = [0; ED25519_PUBLIC_KEY_LEN];
public_key.clone_from_slice(key_pair.public_key().as_ref()); public_key.clone_from_slice(key_pair.public_key().as_ref());
let trusted_nodes = Arc::new(vec![public_key]); let trusted_nodes = Arc::new([public_key]);
let mut node1 = [0; NODE_ID_BYTES]; let mut node1 = [0; NODE_ID_BYTES];
rng.fill(&mut node1).unwrap(); rng.fill(&mut node1).unwrap();
let mut node2 = [0; NODE_ID_BYTES]; let mut node2 = [0; NODE_ID_BYTES];
@ -714,9 +713,85 @@ mod tests {
} }
} }
// TODO Test: last message repeated when message is lost #[test]
fn lost_init_sender_recovers() {
let (mut sender, mut receiver) = create_pair();
let mut out = MsgBuffer::new(8);
sender.send_ping(&mut out);
assert_eq!(sender.stage(), STAGE_PONG);
// lost ping, sender recovers
out.clear();
sender.every_second(&mut out).unwrap();
let result = receiver.handle_init(&mut out).unwrap();
assert_eq!(receiver.stage(), STAGE_PENG);
assert_eq!(result, InitResult::Continue);
// lost pong, sender recovers
out.clear();
receiver.every_second(&mut out).unwrap();
let result = sender.handle_init(&mut out).unwrap();
assert_eq!(sender.stage(), WAITING_TO_CLOSE);
match result {
InitResult::Success { .. } => {
// lost peng, sender recovers
out.clear();
}
InitResult::Continue => unreachable!()
};
sender.every_second(&mut out).unwrap();
let result = receiver.handle_init(&mut out).unwrap();
assert_eq!(receiver.stage(), CLOSING);
match result {
InitResult::Success { .. } => assert!(out.is_empty()),
InitResult::Continue => unreachable!()
}
}
// TODO Test: timeout after 5 retries #[test]
fn lost_init_receiver_recovers() {
let (mut sender, mut receiver) = create_pair();
let mut out = MsgBuffer::new(8);
sender.send_ping(&mut out);
assert_eq!(sender.stage(), STAGE_PONG);
let result = receiver.handle_init(&mut out).unwrap();
assert_eq!(receiver.stage(), STAGE_PENG);
assert_eq!(result, InitResult::Continue);
// lost pong, receiver recovers
out.clear();
sender.every_second(&mut out).unwrap();
receiver.handle_init(&mut out).unwrap();
let result = sender.handle_init(&mut out).unwrap();
assert_eq!(sender.stage(), WAITING_TO_CLOSE);
match result {
InitResult::Success { .. } => {
// lost peng, sender recovers
out.clear();
}
InitResult::Continue => unreachable!()
};
receiver.every_second(&mut out).unwrap();
sender.handle_init(&mut out).unwrap();
let result = receiver.handle_init(&mut out).unwrap();
assert_eq!(receiver.stage(), CLOSING);
match result {
InitResult::Success { .. } => assert!(out.is_empty()),
InitResult::Continue => unreachable!()
}
}
#[test]
fn timeout() {
let (mut sender, _receiver) = create_pair();
let mut out = MsgBuffer::new(8);
sender.send_ping(&mut out);
assert_eq!(sender.stage(), STAGE_PONG);
for _ in 0..5 {
out.clear();
sender.every_second(&mut out).unwrap();
}
out.clear();
assert!(sender.every_second(&mut out).is_err());
assert_eq!(sender.stage(), CLOSING);
}
// TODO Test: duplicated message or replay attacks // TODO Test: duplicated message or replay attacks

View File

@ -70,7 +70,7 @@ pub struct Config {
pub struct Crypto { pub struct Crypto {
node_id: NodeId, node_id: NodeId,
key_pair: Arc<Ed25519KeyPair>, key_pair: Arc<Ed25519KeyPair>,
trusted_keys: Arc<Vec<Ed25519PublicKey>>, trusted_keys: Arc<[Ed25519PublicKey]>,
algorithms: Algorithms algorithms: Algorithms
} }
@ -124,7 +124,7 @@ impl Crypto {
speeds.into_iter().map(|(a, s)| format!("{}: {:.1} MiB/s", a, s)).collect::<Vec<_>>().join(", ") speeds.into_iter().map(|(a, s)| format!("{}: {:.1} MiB/s", a, s)).collect::<Vec<_>>().join(", ")
); );
} }
Ok(Self { node_id, key_pair: Arc::new(key_pair), trusted_keys: Arc::new(trusted_keys), algorithms: algos }) Ok(Self { node_id, key_pair: Arc::new(key_pair), trusted_keys: trusted_keys.into_boxed_slice().into(), algorithms: algos })
} }
pub fn generate_keypair(password: Option<&str>) -> (String, String) { pub fn generate_keypair(password: Option<&str>) -> (String, String) {
@ -215,7 +215,7 @@ pub struct PeerCrypto<P: Payload> {
impl<P: Payload> PeerCrypto<P> { impl<P: Payload> PeerCrypto<P> {
pub fn new( pub fn new(
node_id: NodeId, init_payload: P, key_pair: Arc<Ed25519KeyPair>, trusted_keys: Arc<Vec<Ed25519PublicKey>>, node_id: NodeId, init_payload: P, key_pair: Arc<Ed25519KeyPair>, trusted_keys: Arc<[Ed25519PublicKey]>,
algorithms: Algorithms algorithms: Algorithms
) -> Self ) -> Self
{ {