Skip to content

Commit

Permalink
- Error Handling Update
Browse files Browse the repository at this point in the history
- Added Port Variety
  • Loading branch information
skyline69 committed May 10, 2023
1 parent 68c2c66 commit 90851eb
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 88 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "haxrs"
version = "0.1.2"
version = "0.1.3"
edition = "2021"
authors = ["skyline <[email protected]>"]
license-file = "LICENSE"
Expand Down
9 changes: 5 additions & 4 deletions src/behind/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ pub enum Command {
Empty,
}

fn menu_table_select() {
clear_terminal().unwrap();
fn menu_table_select() -> Result<(), TerminalError>{
clear_terminal()?;
print_login_logo();
match menu_table() {
Ok(_) => {}
Expand All @@ -33,6 +33,7 @@ fn menu_table_select() {
std::process::exit(1);
}
}
Ok(())
}

pub fn command_input() -> Result<Command, TerminalError> {
Expand Down Expand Up @@ -79,12 +80,12 @@ pub(crate) fn menu_table() -> Result<(), TerminalError> {
Ok(())
}
Command::Selection3 => {
selection_3();
selection_3()?;
Ok(())
},
Command::Exit => std::process::exit(0),
Command::Clear => {
menu_table_select();
menu_table_select()?;
Ok(())
}
Command::Menu => menu_table(),
Expand Down
12 changes: 12 additions & 0 deletions src/behind/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ pub enum VersionCheckError {
VersionParseError(semver::Error),
}

#[allow(clippy::enum_variant_names)]
#[derive(Debug)]
pub enum TerminalError {
ClearError(clearscreen::Error),
CommandIOError(std::io::Error),
ReqwestError(reqwest::Error),
}

impl fmt::Display for TerminalError {
Expand All @@ -26,6 +28,10 @@ impl fmt::Display for TerminalError {
log::error!("Could not read/write to terminal: {}", err);
write!(f, "Could not read/write to terminal: {}", err)
},
TerminalError::ReqwestError(err) => {
log::error!("Request error: {}", err);
write!(f, "Request error: {}", err)
},
}
}
}
Expand All @@ -42,8 +48,14 @@ impl From<std::io::Error> for TerminalError {
fn from(err: std::io::Error) -> TerminalError {
TerminalError::CommandIOError(err)
}
}

impl From<reqwest::Error> for TerminalError {
fn from(err: reqwest::Error) -> TerminalError {
TerminalError::ReqwestError(err)
}
}

impl fmt::Display for VersionCheckError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Expand Down
47 changes: 32 additions & 15 deletions src/behind/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use log4rs::Config;
use log4rs::config::{Appender, Root};
use log4rs::encode::pattern::PatternEncoder;
use log::LevelFilter;
use crate::behind::cli::error_msg;


pub(crate) fn log_init() {
Expand All @@ -12,20 +13,36 @@ pub(crate) fn log_init() {

let filename = format!("logs/execution-{}.log", date);

let logfile = FileAppender::builder()
.encoder(Box::new(PatternEncoder::new("{d} {l} - {m}\n")))
.build(filename)
.unwrap();

let config = Config::builder()
.appender(Appender::builder().build("logfile", Box::new(logfile)))
.build(
Root::builder()
.appender("logfile")
.build(LevelFilter::Info),
)
.unwrap();
let logfile: FileAppender = {
match FileAppender::builder().encoder(Box::new(PatternEncoder::new("{d} {l} - {m}\n"))).build(filename) {
Ok(file_appender) => file_appender,
Err(e) => {
error_msg(&format!("Failed to create log file: {}", e));
std::process::exit(1);
}
}
};
let config = {
match Config::builder().appender(Appender::builder().build("logfile", Box::new(logfile))).build(
Root::builder().appender("logfile").build(LevelFilter::Info),
) {
Ok(config) => config,
Err(e) => {
error_msg(&format!("Failed to create log config: {}", e));
std::process::exit(1);
}
}
};
// clear the log file on startup
std::fs::write(format!("logs/execution-{}.log", date), "").unwrap();
log4rs::init_config(config).unwrap();
if let Err(e) = std::fs::write(format!("logs/execution-{}.log", date), "") {
error_msg(&format!("Failed to clear log file: {}", e));
std::process::exit(1);
}
match log4rs::init_config(config) {
Ok(_) => {}
Err(e) => {
error_msg(&format!("Failed to initialize log config: {}", e));
std::process::exit(1);
}
}
}
149 changes: 94 additions & 55 deletions src/behind/selection_1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,73 +16,122 @@ fn is_ip_reachable(ip: &str) -> bool {
}


pub (crate) fn selection_1() -> Result<(), TerminalError> {
pub(crate) fn selection_1() -> Result<(), TerminalError> {
let mut ip_inp = String::new();
print!("\nEnter Target IP: ");
io::stdout().flush()?;
io::stdin().read_line(&mut ip_inp)?;
ip_inp = ip_inp.trim().to_string();
io::stdout().flush()?;

let mut port_inp = String::new();
print!("How many Ports should be scanned?(1 - 65535): ");
io::stdout().flush()?;
io::stdin().read_line(&mut port_inp)?; // Changed from ip_inp to port_inp
port_inp = port_inp.trim().to_string();
io::stdout().flush()?;

let port_inp = match port_inp.parse::<u32>() {
Ok(num) => {
if num > 0 && num < 65536u32 {
num
} else {
log::error!("Port input is not between 1 and 65535: {}", port_inp);
error_msg("Port input is not between 1 and 65535");
return Ok(());
}
},
Err(_) => {
log::error!("Port input is not a number: {}", port_inp);
error_msg("Port input is not a number");
return Ok(());
}
};


log::info!("IP address entered: {}", ip_inp);
if !is_ip_reachable(&ip_inp) {
log::error!("IP address not reachable: {}", ip_inp);
error_msg("IP address not reachable");
return Ok(());
}

println!("{}", "=" .repeat(50).bright_blue());
println!("{}: {}\n{}: {}", "Target IP".purple(), ip_inp.bright_purple(), "Ports to scan".purple(), port_inp.to_string().bright_purple());
println!("{}", "loading...".dimmed().bold());

let start_t = Instant::now();

println!("{}", "LOG: Fetching IP geolocation information...".dimmed()); // Log message
println!("{}", "LOG: Fetching IP geolocation information...".dimmed());
// Log message
log::info!("Fetching IP geolocation information for {}", ip_inp);
let client = Client::new();
let response = client
.get(&format!("http://ip-api.com/json/{}", ip_inp))
.send()
.unwrap();

let rg: Value = response.json().unwrap();
log::info!("IP geolocation information JSON: {}", to_string_pretty(&rg).unwrap());
println!("{}", "LOG: Running Nmap scan... (This could take a while.)".dimmed()); // Log message
let nmap_result = match run_nmap_scan(&ip_inp) {
Ok(result) => result,
Err(e) => {
error_msg(&format!("Nmap scan failed: {}", e));
return Ok(());
let response = client.get(&format!("http://ip-api.com/json/{}", ip_inp)).send()?;

if response.status().is_success() {
let rg: Value = {
match response.json() {
Ok(json) => json,
Err(e) => {
log::error!("Failed to get response from ip-api.com: {}", e);
error_msg(&format!("Failed to get response from ip-api.com: {}", e));
return Ok(());
}
}
};

log::info!("IP geolocation information JSON: {}", {
match to_string_pretty(&rg) {
Ok(json) => json,
Err(e) => {
log::error!("Failed to convert IP geolocation information to JSON: {}", e);
error_msg(&format!("Failed to convert IP geolocation information to JSON: {}", e));
return Ok(());
}
}
};
});
println!("{}", "LOG: Running Nmap scan... (This could take a while.)".dimmed()); // Log message
let nmap_result = match run_nmap_scan(&ip_inp, port_inp) {
Ok(result) => result,
Err(e) => {
error_msg(&format!("Nmap scan failed: {}", e));
return Ok(());
}
};


let open_ports = parse_nmap_output(&nmap_result);

let open_ports = parse_nmap_output(&nmap_result);

println!("{}", "=".repeat(34));
success_msg(&format!("IP: {}", rg["query"].to_string().replace('\"', "")));
success_msg(&format!("Country: {}", rg["country"].to_string().replace('\"', "")));
success_msg(&format!("City: {}", rg["city"]).replace('\"', ""));
success_msg(&format!("Organisation: {}", rg["org"].to_string().replace('\"', "")));

if !open_ports.is_empty() {
for port in open_ports {
println!(
"[{}] Port {} State: OPEN",
"+".green().bold(),
port.to_string().cyan(),
);
println!("{}", "=".repeat(50));
success_msg(&format!("IP: {}", rg["query"].to_string().replace('\"', "")));
success_msg(&format!("Country: {}", rg["country"].to_string().replace('\"', "")));
success_msg(&format!("City: {}", rg["city"]).replace('\"', ""));
success_msg(&format!("Organisation: {}", rg["org"].to_string().replace('\"', "")));

if !open_ports.is_empty() {
for port in open_ports {
println!(
"[{}] Port {} State: OPEN",
"+".green().bold(),
port.to_string().cyan(),
);
}
} else {
error_msg("No open ports found");
}
} else {
error_msg("No open ports found");
}

let end_t = Instant::now();
let duration = end_t.duration_since(start_t);
let result_t = duration.as_secs_f64();
let end_t = Instant::now();
let duration = end_t.duration_since(start_t);
let result_t = duration.as_secs_f64();

if result_t >= 60f64 {
println!("\nTime: {}\n", format!("{:.2}m", result_t / 60.0).cyan());
if result_t >= 60f64 {
println!("\nTime: {}\n", format!("{:.2}m", result_t / 60.0).cyan());
} else {
println!("\nTime: {}\n", format!("{:.2}s", result_t).cyan());
};
} else {
println!("\nTime: {}\n", format!("{:.2}s", result_t).cyan());
};
log::error!("Failed to get response from ip-api.com: {}", response.status());
error_msg(&format!("Failed to get response from IP geolocation API: {}", response.status()));
}
Ok(())
}

Expand All @@ -103,26 +152,16 @@ fn parse_nmap_output(output: &str) -> HashSet<u16> {
open_ports
}

fn run_nmap_scan(ip: &str) -> Result<String, Box<dyn std::error::Error>> {
fn run_nmap_scan(ip: &str, port_count: u32) -> Result<String, Box<dyn std::error::Error>> {
log::info!("Checking for nmap binary...");
if env::consts::OS == "windows" {
let nmap_path = env::current_dir()?.join("nmap-bin").join("nmap.exe");
let output = Command::new(nmap_path)
.arg("-Pn")
.arg("-p")
.arg("22-443")
.arg(ip)
.output()?;
let output = Command::new(nmap_path).arg("-Pn").arg("-p").arg(format!("0-{}", port_count)).arg(ip).output()?;
let output_str = String::from_utf8_lossy(&output.stdout).into_owned();
log::info!("Nmap scan output: {}", output_str);
Ok(output_str)
} else {
let output = Command::new("nmap")
.arg("-Pn")
.arg("-p")
.arg("22-443")
.arg(ip)
.output()?;
let output = Command::new("nmap").arg("-Pn").arg("-p").arg(format!("0-{}", port_count)).arg(ip).output()?;
let output_str = String::from_utf8_lossy(&output.stdout).into_owned();
log::info!("Nmap scan output: {}", output_str);
Ok(output_str)
Expand Down
Loading

0 comments on commit 90851eb

Please sign in to comment.