feat: added the ability to test a connection
This commit is contained in:
parent
fb98d062ef
commit
022340ec95
@ -18,11 +18,11 @@ mod commands;
|
||||
mod shell;
|
||||
|
||||
pub struct Connection {
|
||||
config: ClientConfig,
|
||||
foreign_sign_pubkey: ed25519_dalek::PublicKey,
|
||||
foreign_enc_pubkey: ecies_ed25519::PublicKey,
|
||||
socket: Arc<UdpSocket>,
|
||||
ip: SocketAddr,
|
||||
pub(crate) config: ClientConfig,
|
||||
pub(crate) foreign_sign_pubkey: ed25519_dalek::PublicKey,
|
||||
pub(crate) foreign_enc_pubkey: ecies_ed25519::PublicKey,
|
||||
pub(crate) socket: Arc<UdpSocket>,
|
||||
pub(crate) ip: SocketAddr,
|
||||
}
|
||||
|
||||
impl Connection {
|
||||
|
||||
118
sparse-05/sparse-05-client/src/commands/connecttest.rs
Normal file
118
sparse-05/sparse-05-client/src/commands/connecttest.rs
Normal file
@ -0,0 +1,118 @@
|
||||
use std::{
|
||||
io::{self, Write},
|
||||
net::SocketAddr,
|
||||
path::PathBuf,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use anyhow::bail;
|
||||
use ed25519_dalek::{Signature, Signer, Verifier};
|
||||
use sparse_05_common::messages::{
|
||||
Capabilities, Command, Response, CONNECTED_MESSAGE, CONNECT_MESSAGE,
|
||||
};
|
||||
use tokio::{fs, net::UdpSocket};
|
||||
|
||||
use crate::configs::ClientConfig;
|
||||
|
||||
pub async fn connecttest(config: PathBuf, ip: SocketAddr) -> anyhow::Result<()> {
|
||||
let config = fs::read(&config).await?;
|
||||
let config: ClientConfig = rmp_serde::from_slice(&config)?;
|
||||
|
||||
let remote = Arc::new(UdpSocket::bind("0.0.0.0:0").await?);
|
||||
|
||||
let connect_signature = config.keypair.sign(CONNECT_MESSAGE).to_bytes();
|
||||
let connect_msg = &[&connect_signature, CONNECT_MESSAGE].concat();
|
||||
|
||||
let mut counter = 0;
|
||||
|
||||
let (foreign_sign_pubkey, foreign_enc_pubkey, capabilities) = loop {
|
||||
if counter > 25 {
|
||||
bail!("could not connect to server");
|
||||
}
|
||||
|
||||
print!(
|
||||
"\rConnecting{}",
|
||||
match counter % 3 {
|
||||
2 => ".. ",
|
||||
1 => ". ",
|
||||
_ => "...",
|
||||
}
|
||||
);
|
||||
io::stdout().flush().unwrap();
|
||||
|
||||
remote.send_to(connect_msg, ip).await?;
|
||||
|
||||
let mut buf = [0u8; 2000];
|
||||
|
||||
match tokio::time::timeout(
|
||||
std::time::Duration::from_millis(250),
|
||||
remote.recv_from(&mut buf),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(packet) => {
|
||||
let (count, addr) = packet?;
|
||||
|
||||
if addr != ip {
|
||||
bail!("received response from wrong source");
|
||||
}
|
||||
|
||||
let data = &buf[..count];
|
||||
|
||||
if data.len() < 65 {
|
||||
bail!("could not get signature from server");
|
||||
}
|
||||
|
||||
let signature: [u8; 64] = data[..64].try_into().unwrap();
|
||||
let data = &data[64..];
|
||||
|
||||
let Ok(foreign_keys) = ecies_ed25519::decrypt(&config.enc_privkey, data) else {
|
||||
counter += 1;
|
||||
continue;
|
||||
};
|
||||
|
||||
if foreign_keys.len()
|
||||
< ed25519_dalek::PUBLIC_KEY_LENGTH + ecies_ed25519::PUBLIC_KEY_LENGTH
|
||||
{
|
||||
bail!("could not get public keys from the server");
|
||||
}
|
||||
|
||||
let foreign_sign_pubkey = ed25519_dalek::PublicKey::from_bytes(
|
||||
&foreign_keys[..ed25519_dalek::PUBLIC_KEY_LENGTH],
|
||||
)?;
|
||||
let foreign_enc_pubkey = ecies_ed25519::PublicKey::from_bytes(
|
||||
&foreign_keys[ed25519_dalek::PUBLIC_KEY_LENGTH
|
||||
..(ed25519_dalek::PUBLIC_KEY_LENGTH + ecies_ed25519::PUBLIC_KEY_LENGTH)],
|
||||
)?;
|
||||
|
||||
let capabilities: Capabilities = rmp_serde::from_slice(
|
||||
&foreign_keys
|
||||
[(ed25519_dalek::PUBLIC_KEY_LENGTH + ecies_ed25519::PUBLIC_KEY_LENGTH)..],
|
||||
)?;
|
||||
|
||||
foreign_sign_pubkey.verify(data, &Signature::from(signature))?;
|
||||
|
||||
break (foreign_sign_pubkey, foreign_enc_pubkey, capabilities);
|
||||
}
|
||||
Err(_) => {
|
||||
counter += 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let connection = Arc::new(crate::commands::connect::Connection {
|
||||
config,
|
||||
foreign_enc_pubkey,
|
||||
foreign_sign_pubkey,
|
||||
socket: Arc::clone(&remote),
|
||||
ip,
|
||||
});
|
||||
|
||||
remote
|
||||
.send_to(&connection.encrypt_and_sign(CONNECTED_MESSAGE)?, ip)
|
||||
.await?;
|
||||
|
||||
println!("\rConnected! ");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -1,2 +1,3 @@
|
||||
pub mod connect;
|
||||
pub mod connecttest;
|
||||
pub mod generate;
|
||||
|
||||
@ -15,5 +15,6 @@ async fn main() -> anyhow::Result<()> {
|
||||
commands::generate::generate(name, port, target).await
|
||||
}
|
||||
Command::Connect { config, ip } => commands::connect::connect(config, ip).await,
|
||||
Command::ConnectTest { config, ip } => commands::connecttest::connecttest(config, ip).await,
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,6 +46,13 @@ pub enum Command {
|
||||
#[structopt(parse(from_os_str))]
|
||||
config: PathBuf,
|
||||
|
||||
#[structopt(parse(try_from_str = to_socket_addr))]
|
||||
ip: SocketAddr,
|
||||
},
|
||||
ConnectTest {
|
||||
#[structopt(parse(from_os_str))]
|
||||
config: PathBuf,
|
||||
|
||||
#[structopt(parse(try_from_str = to_socket_addr))]
|
||||
ip: SocketAddr,
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user