Start fleshing out filesystem and pwd tracking
Diff
pisshoff-server/src/command.rs | 44 +++++++++++++++++++++++++++++++--------
pisshoff-server/src/file_system.rs | 41 ++++++++++++++++++++++++++++++++++++-
pisshoff-server/src/main.rs | 1 +-
pisshoff-server/src/server.rs | 11 ++++++++++-
4 files changed, 89 insertions(+), 8 deletions(-)
@@ -2,6 +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 thrussh::{server::Session, ChannelId};
@@ -26,18 +27,45 @@ pub async fn run_command(
session.data(channel, format!("{}\n", conn.username()).into());
}
"pwd" => {
let username = conn.username();
let pwd = if conn.username() == "root" {
"/root\n".to_string()
session.data(
channel,
format!("{}\n", conn.file_system().pwd().display()).into(),
);
}
"ls" => {
let resp = if args.len() == 1 {
conn.file_system().ls(None).join(" ")
} else if args.len() == 2 {
conn.file_system().ls(Some(args.get(1).unwrap())).join(" ")
} else {
format!("/home/{username}\n")
let mut out = String::new();
for dir in args.iter().skip(1) {
if !out.is_empty() {
out.push_str("\n\n");
}
write!(out, "{dir}:").unwrap();
out.push_str(&conn.file_system().ls(Some(dir)).join(" "));
}
out
};
session.data(channel, pwd.into());
if !resp.is_empty() {
session.data(channel, format!("{resp}\n").into());
}
}
"ls" => {
"cd" => {
if args.len() > 2 {
session.data(
channel,
"-bash: cd: too many arguments\n".to_string().into(),
);
return;
}
conn.file_system().cd(args.get(1).map(String::as_str));
}
"exit" => {
let exit_status = args
@@ -0,0 +1,41 @@
#![allow(dead_code)]
use std::path::{Path, PathBuf};
pub struct FileSystem {
pwd: PathBuf,
home: PathBuf,
}
impl FileSystem {
pub fn new(user: &str) -> Self {
let pwd = if user == "root" {
PathBuf::new().join("/root")
} else {
PathBuf::new().join("/home").join(user)
};
Self {
home: pwd.clone(),
pwd,
}
}
pub fn cd(&mut self, v: Option<&str>) {
if let Some(v) = v {
self.pwd.push(v);
} else {
self.pwd = self.home.clone();
}
}
pub fn pwd(&self) -> &Path {
&self.pwd
}
#[allow(clippy::unused_self)]
pub fn ls(&self, _dir: Option<&str>) -> &[&str] {
&[]
}
}
@@ -17,6 +17,7 @@ use tracing_subscriber::EnvFilter;
mod audit;
mod command;
mod config;
mod file_system;
mod server;
mod state;
@@ -2,6 +2,7 @@ use crate::audit::{
ExecCommandEvent, SignalEvent, SubsystemRequestEvent, TcpIpForwardEvent, WindowAdjustedEvent,
WindowChangeRequestEvent,
};
use crate::file_system::FileSystem;
use crate::{
audit::{
AuditLog, AuditLogAction, LoginAttemptEvent, OpenDirectTcpIpEvent, OpenX11Event,
@@ -74,6 +75,7 @@ impl thrussh::server::Server for Server {
..AuditLog::default()
},
username: None,
file_system: None,
}
}
}
@@ -83,6 +85,7 @@ pub struct Connection {
server: Server,
audit_log: AuditLog,
username: Option<String>,
file_system: Option<FileSystem>,
}
impl Connection {
@@ -90,6 +93,14 @@ impl Connection {
self.username.as_deref().unwrap_or("root")
}
pub fn file_system(&mut self) -> &mut FileSystem {
if self.file_system.is_none() {
self.file_system = Some(FileSystem::new(self.username()));
}
self.file_system.as_mut().unwrap()
}
fn try_login(&mut self, user: &str, password: &str) -> bool {
self.username = Some(user.to_string());