Associate saved passwords with usernames
Diff
pisshoff-server/src/command.rs | 3 +--
pisshoff-server/src/server.rs | 4 ++--
pisshoff-server/src/state.rs | 38 ++++++++++++++++++++++++++++++++------
3 files changed, 35 insertions(+), 10 deletions(-)
@@ -2,8 +2,7 @@ pub mod uname;
use crate::server::Connection;
use itertools::{Either, Itertools};
use std::fmt::Write;
use std::{f32, str::FromStr, time::Duration};
use std::{f32, fmt::Write, str::FromStr, time::Duration};
use thrussh::{server::Session, ChannelId};
pub async fn run_command(
@@ -108,7 +108,7 @@ impl Connection {
.server
.state
.previously_accepted_passwords
.seen(password)
.seen(user, password)
{
info!(user, password, "Accepted login due to it being used before");
true
@@ -117,7 +117,7 @@ impl Connection {
self.server
.state
.previously_accepted_passwords
.store(password);
.store(user, password);
true
} else {
info!(?user, ?password, "Rejected login");
@@ -1,5 +1,5 @@
use parking_lot::RwLock;
use std::collections::HashSet;
use std::{borrow::Cow, collections::HashSet};
#[derive(Default)]
pub struct State {
@@ -9,14 +9,40 @@ pub struct State {
}
#[derive(Default)]
pub struct StoredPasswords(RwLock<HashSet<Box<str>>>);
pub struct StoredPasswords(RwLock<HashSet<UsernamePasswordTuple<'static>>>);
impl StoredPasswords {
pub fn seen(&self, password: &str) -> bool {
self.0.read().contains(password)
pub fn seen(&self, username: &str, password: &str) -> bool {
self.0
.read()
.contains(&UsernamePasswordTuple::new(username, password))
}
pub fn store(&self, password: &str) -> bool {
self.0.write().insert(Box::from(password.to_string()))
pub fn store(&self, username: &str, password: &str) -> bool {
self.0
.write()
.insert(UsernamePasswordTuple::new(username, password).into_owned())
}
}
#[derive(Hash, Clone, Debug, PartialEq, Eq)]
struct UsernamePasswordTuple<'a> {
pub username: Cow<'a, str>,
pub password: Cow<'a, str>,
}
impl<'a> UsernamePasswordTuple<'a> {
pub fn new(username: impl Into<Cow<'a, str>>, password: impl Into<Cow<'a, str>>) -> Self {
Self {
username: username.into(),
password: password.into(),
}
}
pub fn into_owned(self) -> UsernamePasswordTuple<'static> {
UsernamePasswordTuple {
username: Cow::Owned(self.username.into_owned()),
password: Cow::Owned(self.password.into_owned()),
}
}
}