Added a third panel to display current projecct information and tool

information.
This commit is contained in:
2026-05-21 17:04:37 -05:00
parent 95b86f80aa
commit 283a336643
2 changed files with 269 additions and 5 deletions
+155
View File
@@ -29,6 +29,7 @@ pub struct AppState {
pub module_loader: ModuleLoader,
pub output_scroll: u16,
prompt: Prompt,
pub info_scroll: u16,
}
impl AppState {
@@ -60,6 +61,7 @@ impl AppState {
execute_command: String::new(),
num_responses: 0,
},
info_scroll: 0,
},
main_rx,
)
@@ -582,12 +584,92 @@ impl Project {
}
}
}
println!("{} | {} config loaded!", self.org_name, self.name);
println!("loading hosts...");
let mut hosts_folder = self.config_folder.clone();
let mut users_folder = self.config_folder.clone();
hosts_folder.pop();
hosts_folder.push("hosts");
users_folder.pop();
users_folder.push("users");
let mut users = HashMap::new();
if users_folder.exists() {
for entry in read_dir(users_folder)? {
let entry = entry?;
let user_config_string = read_to_string(entry.path())?;
let mut new_user = User::new();
for line in user_config_string.lines() {
if line.contains(": ") {
let (setting, data) = line.split_once(": ").unwrap();
match setting.trim() {
"username" => new_user.name = data.trim().to_string(),
"password" => new_user.password = Some(data.trim().to_string()),
"hash" => new_user.hash = Some(data.trim().to_string()),
"compromised" => new_user.compromised = data.trim().parse().unwrap(),
"ticket" => new_user.ticket = Some(PathBuf::from(data.trim())),
_ => {}
}
}
}
users.insert(new_user.name.clone(), new_user);
}
}
if hosts_folder.exists() {
for entry in read_dir(hosts_folder)? {
let entry = entry?;
let host_path = entry.path();
let mut new_host = Host::new();
let host_conf_text = read_to_string(host_path)?;
for line in host_conf_text.lines() {
if line.contains(": ") {
let (setting, data) = line.split_once(": ").unwrap();
match setting.trim() {
"ip" => new_host.ip = data.trim().to_string(),
"hostname" => new_host.hostname = data.trim().to_string(),
"control_port" => new_host.control_port = data.trim().parse()?,
"pwned" => new_host.pwned = data.trim().parse()?,
"id" => new_host.id = data.trim().parse()?,
"findings" => {
new_host.findings = data
.trim()
.split(",")
.map(|finding| finding.to_string())
.collect::<Vec<String>>()
}
"open_ports" => {
new_host.open_ports = data
.trim()
.split(",")
.into_iter()
.map(|port| port.parse().unwrap())
.collect::<Vec<usize>>()
}
"users" => {
let names: Vec<&str> = data.trim().split(",").collect();
names.into_iter().for_each(|name| {
if let Some(user) = users.get(name) {
new_host.users.push(user.clone());
}
});
}
_ => {}
}
}
}
}
}
println!("{} | {} loaded!", self.org_name, self.name);
return Ok(());
}
pub fn save_config(&mut self) -> Result<(), Box<dyn Error>> {
create_dir_all(&self.config_folder)?;
let mut hosts_folder = self.config_folder.clone();
hosts_folder.push("hosts");
let mut users_folder = self.config_folder.clone();
users_folder.push("users");
create_dir_all(&hosts_folder)?;
create_dir_all(&users_folder)?;
let mut conf_file = self.config_folder.clone();
conf_file.push("project.conf");
let mut file = File::create(conf_file)?;
@@ -604,6 +686,67 @@ impl Project {
out_string.push_str("stage: upcoming");
}
file.write_all(out_string.as_bytes())?;
if !self.hosts.is_empty() {
for host in &self.hosts {
let mut host_conf_file =
File::create(hosts_folder.join(format!("{}.conf", host.id)))?;
let mut out_string = format!(
"
ip: {}
hostname: {}
control_port: {}
pwned: {}
id: {}",
host.ip, host.hostname, host.control_port, host.pwned, host.id,
);
if !host.findings.is_empty() {
out_string.push_str(&format!("\nfindings: "));
out_string.push_str(&host.findings.join(","));
}
if !host.open_ports.is_empty() {
out_string.push_str(&format!("\nopen_ports: "));
out_string.push_str(
&host
.open_ports
.iter()
.map(|port| port.to_string())
.collect::<Vec<String>>()
.join(","),
);
}
if !host.users.is_empty() {
out_string.push_str(&format!("\nusers: "));
out_string.push_str(
&host
.users
.iter()
.map(|user| user.name.clone())
.collect::<Vec<String>>()
.join(","),
);
for user in &host.users {
let mut user_conf_file =
File::create(users_folder.join(format!("{}.conf", user.name)))?;
let mut user_string = format!("username: {}", &user.name);
user_string.push_str(&format!("\ncompromised: {}", user.compromised));
if user.hash.is_some() {
let hash = user.hash.clone().unwrap();
user_string.push_str(&format!("hash: {hash}"));
}
if user.password.is_some() {
let password = user.password.clone().unwrap();
user_string.push_str(&format!("password: {password}"));
}
if user.ticket.is_some() {
let ticket = user.ticket.clone().unwrap().display().to_string();
user_string.push_str(&format!("ticket: {ticket}"));
}
user_conf_file.write_all(user_string.as_bytes())?;
}
}
host_conf_file.write_all(out_string.as_bytes())?;
}
}
return Ok(());
}
}
@@ -710,6 +853,18 @@ pub struct User {
pub compromised: bool,
}
impl User {
pub fn new() -> Self {
Self {
name: String::new(),
password: None,
hash: None,
ticket: None,
compromised: false,
}
}
}
#[derive(Clone, Debug)]
pub enum ToolMessage {
Input(String),