From cc4416562a82aa3aa80d806bc762965d60b3f5d1 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Wed, 28 Jun 2023 23:39:37 +0100 Subject: [PATCH] Start fleshing out filesystem and pwd tracking --- 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(-) create mode 100644 pisshoff-server/src/file_system.rs diff --git a/pisshoff-server/src/command.rs b/pisshoff-server/src/command.rs index 1f82200..5e3c615 100644 --- a/pisshoff-server/src/command.rs +++ b/pisshoff-server/src/command.rs @@ -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" => { - // TODO: mock FHS - 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" => { - // pretend /root is empty until we mock the FHS + "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 diff --git a/pisshoff-server/src/file_system.rs b/pisshoff-server/src/file_system.rs new file mode 100644 index 0000000..5f96385 --- /dev/null +++ b/pisshoff-server/src/file_system.rs @@ -0,0 +1,41 @@ +#![allow(dead_code)] + +use std::path::{Path, PathBuf}; + +/// A fake file system, stored in memory only active for the current session. +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] { + &[] + } +} diff --git a/pisshoff-server/src/main.rs b/pisshoff-server/src/main.rs index 379a4c4..71af86d 100644 --- a/pisshoff-server/src/main.rs +++ b/pisshoff-server/src/main.rs @@ -17,6 +17,7 @@ use tracing_subscriber::EnvFilter; mod audit; mod command; mod config; +mod file_system; mod server; mod state; diff --git a/pisshoff-server/src/server.rs b/pisshoff-server/src/server.rs index ef29239..74389d8 100644 --- a/pisshoff-server/src/server.rs +++ b/pisshoff-server/src/server.rs @@ -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, + file_system: Option, } 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()); -- libgit2 1.7.2