Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ arg_enum! {
/// Represents the strategy in which the port scanning will run.
/// - Serial will run from start to end, for example 1 to 1_000.
/// - Random will randomize the order in which ports will be scanned.
#[derive(Deserialize, Debug, StructOpt, Clone, PartialEq)]
#[derive(Deserialize, Debug, StructOpt, Clone, Copy, PartialEq)]
pub enum ScanOrder {
Serial,
Random,
Expand Down Expand Up @@ -41,7 +41,7 @@ pub struct PortRange {
fn parse_range(input: &str) -> Result<PortRange, String> {
let range = input
.split('-')
.map(|x| x.parse::<u16>())
.map(str::parse)
.collect::<Result<Vec<u16>, std::num::ParseIntError>>();

if range.is_err() {
Expand All @@ -63,6 +63,7 @@ fn parse_range(input: &str) -> Result<PortRange, String> {

#[derive(StructOpt, Debug, Clone)]
#[structopt(name = "rustscan", setting = structopt::clap::AppSettings::TrailingVarArg)]
#[allow(clippy::struct_excessive_bools)]
/// Fast Port Scanner built in Rust.
/// WARNING Do not use this program against sensitive infrastructure since the
/// specified server may not be able to handle this many socket connections at once.
Expand Down
51 changes: 30 additions & 21 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#![deny(clippy::all)]
#![warn(clippy::pedantic)]
#![allow(clippy::doc_markdown, clippy::if_not_else, clippy::non_ascii_literal)]

extern crate shell_words;

mod tui;
Expand All @@ -22,12 +26,17 @@ use colorful::{Color, Colorful};
use futures::executor::block_on;
use rlimit::{getrlimit, setrlimit, RawRlim, Resource, Rlim};
use std::collections::HashMap;
use std::convert::TryInto;
use std::fs::File;
use std::io::{prelude::*, BufReader};
use std::net::{IpAddr, ToSocketAddrs};
use std::path::Path;
use std::string::ToString;
use std::time::Duration;
use trust_dns_resolver::{config::*, Resolver};
use trust_dns_resolver::{
config::{ResolverConfig, ResolverOpts},
Resolver,
};

extern crate colorful;
extern crate dirs;
Expand All @@ -41,6 +50,7 @@ const AVERAGE_BATCH_SIZE: RawRlim = 3000;
extern crate log;

#[cfg(not(tarpaulin_include))]
#[allow(clippy::too_many_lines)]
/// Faster Nmap scanning with Rust
/// If you're looking for the actual scanning, check out the module Scanner
fn main() {
Expand Down Expand Up @@ -82,7 +92,7 @@ fn main() {
Duration::from_millis(opts.timeout.into()),
opts.tries,
opts.greppable,
PortStrategy::pick(opts.range, opts.ports, opts.scan_order),
PortStrategy::pick(&opts.range, opts.ports, opts.scan_order),
opts.accessible,
);
debug!("Scanner finished building: {:?}", scanner);
Expand Down Expand Up @@ -119,8 +129,8 @@ fn main() {
}

let mut script_bench = NamedTimer::start("Scripts");
for (ip, ports) in ports_per_ip.iter_mut() {
let vec_str_ports: Vec<String> = ports.iter().map(|port| port.to_string()).collect();
for (ip, ports) in &ports_per_ip {
let vec_str_ports: Vec<String> = ports.iter().map(ToString::to_string).collect();

// nmap port style is 80,443. Comma separated with no spaces.
let ports_str = vec_str_ports.join(",");
Expand Down Expand Up @@ -307,21 +317,18 @@ fn adjust_ulimit_size(opts: &Opts) -> RawRlim {
if opts.ulimit.is_some() {
let limit: Rlim = Rlim::from_raw(opts.ulimit.unwrap());

match setrlimit(Resource::NOFILE, limit, limit) {
Ok(_) => {
detail!(
format!("Automatically increasing ulimit value to {}.", limit),
opts.greppable,
opts.accessible
);
}
Err(_) => {
warning!(
"ERROR. Failed to set ulimit value.",
opts.greppable,
opts.accessible
);
}
if setrlimit(Resource::NOFILE, limit, limit).is_ok() {
detail!(
format!("Automatically increasing ulimit value to {}.", limit),
opts.greppable,
opts.accessible
);
} else {
warning!(
"ERROR. Failed to set ulimit value.",
opts.greppable,
opts.accessible
);
}
}

Expand Down Expand Up @@ -363,7 +370,9 @@ fn infer_batch_size(opts: &Opts, ulimit: RawRlim) -> u16 {
opts.greppable, opts.accessible);
}

batch_size as u16
batch_size
.try_into()
.expect("Couldn't fit the batch size into a u16.")
}

#[cfg(test)]
Expand Down Expand Up @@ -414,8 +423,8 @@ mod tests {
opts.ulimit = Some(2_000);
// print opening should not panic
print_opening(&opts);
assert!(1 == 1);
}

#[test]
fn test_high_ulimit_no_greppable_mode() {
let mut opts = Opts::default();
Expand Down
10 changes: 5 additions & 5 deletions src/port_strategy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub enum PortStrategy {
}

impl PortStrategy {
pub fn pick(range: Option<PortRange>, ports: Option<Vec<u16>>, order: ScanOrder) -> Self {
pub fn pick(range: &Option<PortRange>, ports: Option<Vec<u16>>, order: ScanOrder) -> Self {
match order {
ScanOrder::Serial if ports.is_none() => {
let range = range.as_ref().unwrap();
Expand Down Expand Up @@ -102,15 +102,15 @@ mod tests {
#[test]
fn serial_strategy_with_range() {
let range = PortRange { start: 1, end: 100 };
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Serial);
let strategy = PortStrategy::pick(&Some(range), None, ScanOrder::Serial);
let result = strategy.order();
let expected_range = (1..100).into_iter().collect::<Vec<u16>>();
assert_eq!(expected_range, result);
}
#[test]
fn random_strategy_with_range() {
let range = PortRange { start: 1, end: 100 };
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
let strategy = PortStrategy::pick(&Some(range), None, ScanOrder::Random);
let mut result = strategy.order();
let expected_range = (1..100).into_iter().collect::<Vec<u16>>();
assert_ne!(expected_range, result);
Expand All @@ -121,14 +121,14 @@ mod tests {

#[test]
fn serial_strategy_with_ports() {
let strategy = PortStrategy::pick(None, Some(vec![80, 443]), ScanOrder::Serial);
let strategy = PortStrategy::pick(&None, Some(vec![80, 443]), ScanOrder::Serial);
let result = strategy.order();
assert_eq!(vec![80, 443], result);
}

#[test]
fn random_strategy_with_ports() {
let strategy = PortStrategy::pick(None, Some((1..10).collect()), ScanOrder::Random);
let strategy = PortStrategy::pick(&None, Some((1..10).collect()), ScanOrder::Random);
let mut result = strategy.order();
let expected_range = (1..10).into_iter().collect::<Vec<u16>>();
assert_ne!(expected_range, result);
Expand Down
7 changes: 6 additions & 1 deletion src/port_strategy/range_iterator.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use gcd::Gcd;
use rand::Rng;
use std::convert::TryInto;

pub struct RangeIterator {
active: bool,
Expand Down Expand Up @@ -60,7 +61,11 @@ impl Iterator for RangeIterator {
}

self.normalized_pick = next_pick;
Some((self.actual_start + current_pick) as u16)
Some(
(self.actual_start + current_pick)
.try_into()
.expect("Could not convert u32 to u16"),
)
}
}

Expand Down
14 changes: 7 additions & 7 deletions src/scanner/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use socket_iterator::SocketIterator;
use async_std::io;
use async_std::net::TcpStream;
use async_std::prelude::*;
use colored::*;
use colored::Colorize;
use futures::stream::FuturesUnordered;
use std::{
io::ErrorKind,
Expand Down Expand Up @@ -49,7 +49,7 @@ impl Scanner {
tries: NonZeroU8::new(std::cmp::max(tries, 1)).unwrap(),
greppable,
port_strategy,
ips: ips.iter().map(|ip| ip.to_owned()).collect(),
ips: ips.iter().map(ToOwned::to_owned).collect(),
accessible,
}
}
Expand Down Expand Up @@ -184,7 +184,7 @@ mod tests {
start: 1,
end: 1_000,
};
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
let strategy = PortStrategy::pick(&Some(range), None, ScanOrder::Random);
let scanner = Scanner::new(
&addrs,
10,
Expand All @@ -206,7 +206,7 @@ mod tests {
start: 1,
end: 1_000,
};
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
let strategy = PortStrategy::pick(&Some(range), None, ScanOrder::Random);
let scanner = Scanner::new(
&addrs,
10,
Expand All @@ -227,7 +227,7 @@ mod tests {
start: 1,
end: 1_000,
};
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
let strategy = PortStrategy::pick(&Some(range), None, ScanOrder::Random);
let scanner = Scanner::new(
&addrs,
10,
Expand All @@ -247,7 +247,7 @@ mod tests {
start: 400,
end: 445,
};
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
let strategy = PortStrategy::pick(&Some(range), None, ScanOrder::Random);
let scanner = Scanner::new(
&addrs,
10,
Expand All @@ -270,7 +270,7 @@ mod tests {
start: 400,
end: 600,
};
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
let strategy = PortStrategy::pick(&Some(range), None, ScanOrder::Random);
let scanner = Scanner::new(
&addrs,
10,
Expand Down
22 changes: 13 additions & 9 deletions src/scripts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,18 @@
//!
//! If the format is different, the script will be silently discarded and will not run. With the Debug option it's possible to see where it goes wrong.

#![allow(clippy::module_name_repetitions)]

use crate::input::ScriptsRequired;
use anyhow::{anyhow, Result};
use serde_derive::{Deserialize, Serialize};
use std::collections::HashSet;
use std::convert::TryInto;
use std::fs::{self, File};
use std::io::{self, prelude::*};
use std::net::IpAddr;
use std::path::PathBuf;
use std::string::ToString;
use subprocess::{Exec, ExitStatus};
use text_placeholder::Template;

Expand Down Expand Up @@ -197,7 +201,7 @@ impl Script {
let mut ports_str = self
.open_ports
.iter()
.map(|port| port.to_string())
.map(ToString::to_string)
.collect::<Vec<String>>()
.join(&separator);
if let Some(port) = self.trigger_port {
Expand Down Expand Up @@ -233,7 +237,7 @@ impl Script {
let arguments = shell_words::split(
&to_run
.split(' ')
.map(|arg| arg.to_string())
.map(ToString::to_string)
.collect::<Vec<String>>()
.join(" "),
)
Expand All @@ -250,10 +254,10 @@ fn execute_script(mut arguments: Vec<String>) -> Result<String> {
match process.capture() {
Ok(c) => {
let es = match c.exit_status {
ExitStatus::Exited(c) => c as i32,
ExitStatus::Signaled(c) => c as i32,
ExitStatus::Exited(c) => c.try_into().unwrap(),
ExitStatus::Signaled(c) => c.into(),
ExitStatus::Other(c) => c,
_ => -1,
ExitStatus::Undetermined => -1,
};
if es != 0 {
return Err(anyhow!("Exit code = {}", es));
Expand Down Expand Up @@ -302,7 +306,7 @@ impl ScriptFile {
if line.starts_with('#') {
line.retain(|c| c != '#');
line = line.trim().to_string();
line.push_str("\n");
line.push('\n');
lines_buf.push_str(&line);
} else {
break;
Expand Down Expand Up @@ -380,7 +384,7 @@ mod tests {
#[test]
#[should_panic]
fn find_invalid_folder() {
let scripts = find_scripts("Cargo.toml".into()).unwrap();
let _scripts = find_scripts("Cargo.toml".into()).unwrap();
}

#[test]
Expand All @@ -397,7 +401,7 @@ mod tests {
ScriptFile::new("fixtures/.rustscan_scripts/test_script.txt".into()).unwrap();
script_f.call_format = Some("qwertyuiop".to_string());
let script: Script = into_script(script_f);
let output = script.run().unwrap();
let _output = script.run().unwrap();
}

#[test]
Expand All @@ -407,7 +411,7 @@ mod tests {
ScriptFile::new("fixtures/.rustscan_scripts/test_script.txt".into()).unwrap();
script_f.call_format = None;
let script: Script = into_script(script_f);
let output = script.run().unwrap();
let _output = script.run().unwrap();
}

#[test]
Expand Down