mirror of https://github.com/dswd/vpncloud.git
Compare commits
2 Commits
eb638efadf
...
7b0718399c
Author | SHA1 | Date |
---|---|---|
Dennis Schwerdel | 7b0718399c | |
Dennis Schwerdel | 5bb0187726 |
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
@ -417,7 +417,7 @@ pub struct Args {
|
||||||
pub version: bool,
|
pub version: bool,
|
||||||
|
|
||||||
/// Generate and print a key-pair and exit
|
/// Generate and print a key-pair and exit
|
||||||
#[structopt(long, conflicts_with="private_key")]
|
#[structopt(long, conflicts_with = "private_key")]
|
||||||
pub genkey: bool,
|
pub genkey: bool,
|
||||||
|
|
||||||
/// Disable automatic port forwarding
|
/// Disable automatic port forwarding
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue