diff --git a/src/fingerprints.rs b/src/fingerprints.rs index 0d95644..4972567 100644 --- a/src/fingerprints.rs +++ b/src/fingerprints.rs @@ -8,8 +8,12 @@ use std::{ use crate::{directory::watch_directory, ssh::Authentication}; use log::{error, warn}; use notify::RecommendedWatcher; -use russh_keys::load_public_key; -use tokio::{fs::read_dir, sync::oneshot, task::JoinHandle}; +use ssh_key::{HashAlg, PublicKey}; +use tokio::{ + fs::{read_dir, read_to_string}, + sync::oneshot, + task::JoinHandle, +}; #[derive(Debug)] pub(crate) struct FingerprintsValidator { @@ -47,58 +51,88 @@ impl FingerprintsValidator { { break; } - let mut user_set = HashSet::new(); - match read_dir(user_keys_directory.as_path()).await { - Ok(mut read_dir) => { - while let Ok(Some(entry)) = read_dir.next_entry().await { - match load_public_key(entry.path()) { - Ok(data) => { - user_set.insert(data.fingerprint()); - } - Err(err) => { - warn!( - "Unable to load public key in {:?}: {}", - entry.file_name(), - err - ); + tokio::join!( + async { + let mut user_set = HashSet::new(); + match read_dir(user_keys_directory.as_path()).await { + Ok(mut read_dir) => { + while let Ok(Some(entry)) = read_dir.next_entry().await { + match read_to_string(entry.path()).await { + Ok(data) => { + user_set.extend( + data.lines() + .flat_map(|line| { + PublicKey::from_openssh(line).ok() + }) + .flat_map(|key| { + key.fingerprint(HashAlg::Sha256) + .to_string() + .split(':') + .nth(1) + .map(str::to_string) + }), + ); + } + Err(err) => { + warn!( + "Unable to load user key in {:?}: {}", + entry.file_name(), + err + ); + } + } } + *user_fingerprints_clone.write().unwrap() = user_set; + } + Err(err) => { + error!( + "Unable to read user keys directory {:?}: {}", + &user_keys_directory, err + ); } } - *user_fingerprints_clone.write().unwrap() = user_set; - } - Err(err) => { - error!( - "Unable to read user keys directory {:?}: {}", - &user_keys_directory, err - ); - } - } - let mut admin_set = HashSet::new(); - match read_dir(admin_keys_directory.as_path()).await { - Ok(mut read_dir) => { - while let Ok(Some(entry)) = read_dir.next_entry().await { - match load_public_key(entry.path()) { - Ok(data) => { - admin_set.insert(data.fingerprint()); - } - Err(err) => { - warn!( - "Unable to load public key in {:?}: {}", - entry.file_name(), - err - ); + }, + async { + let mut admin_set = HashSet::new(); + match read_dir(admin_keys_directory.as_path()).await { + Ok(mut read_dir) => { + while let Ok(Some(entry)) = read_dir.next_entry().await { + match read_to_string(entry.path()).await { + Ok(data) => { + admin_set.extend( + data.lines() + .flat_map(|line| { + PublicKey::from_openssh(line).ok() + }) + .flat_map(|key| { + key.fingerprint(HashAlg::Sha256) + .to_string() + .split(':') + .nth(1) + .map(str::to_string) + }), + ); + } + Err(err) => { + warn!( + "Unable to load admin key in {:?}: {}", + entry.file_name(), + err + ); + } + } } + *admin_fingerprints_clone.write().unwrap() = admin_set; + } + Err(err) => { + error!( + "Unable to read admin keys directory {:?}: {}", + &admin_keys_directory, err + ); } } - *admin_fingerprints_clone.write().unwrap() = admin_set; } - Err(err) => { - error!( - "Unable to read admin keys directory {:?}: {}", - &admin_keys_directory, err - ); - } - } + ); init_tx.take().map(|tx| tx.send(())); tokio::time::sleep(Duration::from_secs(2)).await; } diff --git a/src/ssh.rs b/src/ssh.rs index 966b686..3856c78 100644 --- a/src/ssh.rs +++ b/src/ssh.rs @@ -608,7 +608,7 @@ impl Handler for ServerHandler { } else if let Some(handler) = self .server .tcp - .get(&BorrowedTcpAlias(&host_to_connect, &port_to_connect) as &dyn TcpAliasKey) + .get(&BorrowedTcpAlias(host_to_connect, &port_to_connect) as &dyn TcpAliasKey) { if let Ok(mut io) = handler .tunneling_channel(originator_address, originator_port as u16) diff --git a/src/tcp_alias.rs b/src/tcp_alias.rs index d702e15..81fcf95 100644 --- a/src/tcp_alias.rs +++ b/src/tcp_alias.rs @@ -23,7 +23,7 @@ pub(crate) trait TcpAliasKey { } impl TcpAliasKey for TcpAlias { - fn key<'k>(&'k self) -> BorrowedTcpAlias<'k> { + fn key(&self) -> BorrowedTcpAlias { BorrowedTcpAlias(self.0.as_str(), &self.1) } } @@ -44,7 +44,7 @@ impl<'a> Eq for (dyn TcpAliasKey + 'a) {} impl<'a> PartialOrd for (dyn TcpAliasKey + 'a) { fn partial_cmp(&self, other: &Self) -> Option { - self.key().partial_cmp(&other.key()) + Some(self.cmp(other)) } } diff --git a/tests/data/user_keys/key1.pub b/tests/data/user_keys/key1.pub deleted file mode 100644 index 39bd513..0000000 --- a/tests/data/user_keys/key1.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMYVfXHTqf3/0W8ZQ/I8zmMirvmosV78n1qtYgVQX58W key1 diff --git a/tests/data/user_keys/key2.pub b/tests/data/user_keys/keys_1_2.pub similarity index 86% rename from tests/data/user_keys/key2.pub rename to tests/data/user_keys/keys_1_2.pub index 145bc0f..fdefcd8 100644 --- a/tests/data/user_keys/key2.pub +++ b/tests/data/user_keys/keys_1_2.pub @@ -1 +1,3 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMYVfXHTqf3/0W8ZQ/I8zmMirvmosV78n1qtYgVQX58W key1 + ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCUdw1f/va/ax8L/5qoZw37+76psjybsY7qNJMxOhwqKQ6fKiLu2xv+uFQxdEbNitXbcC8zZ2m98XzEPlNoY3DTqw5RAt2qZQMMXFLzDNHCpY6xT1DxLFTYxczXj9Xk4Ms7/RQP6pxLV5PIVc06HXBThCzcLMDdnl9n0jEWu1CwSGtsc87/Gvbnr3QrfrnK40IS7c5SIfbI5yN7pfnCEkRf637EGzc11Tq4e2/ujweETZ1C+KcJZapVVHTvFfITyOqLeqrgXgsMQUML48SfDUl/RsY4nk6aFKwK7f0oGzykqLTX0YHS1wxLOnPSkK33ohvtjvcUzA/eAmjUiQquJQ7DW6RPvW57lozzIxwFvO4O/j398r3W1de3R7Q3rmAwKbujFSJlZb4OvS1ZLS8md8TwCO1xwE+4aY3xvsmeHpfBcEjhTmEYEEY630hbiMgHsbH1M7uAZkbXUgw7R6cLPCndc4GiDOLN/bkKwa55evbOS1J1cD4pi5lUSnzZzk9lYrU= key2