mirror of
https://github.com/s-b-repo/rustsploit
synced 2026-06-27 09:54:12 +00:00
+5
-1
@@ -64,7 +64,7 @@ rlimit = "0.11"
|
||||
|
||||
|
||||
# Bluetooth
|
||||
btleplug = "0.12"
|
||||
btleplug = { version = "0.12", optional = true }
|
||||
|
||||
# WPair migrated from ratatui+crossterm TUI to rustyline REPL — deps removed.
|
||||
|
||||
@@ -163,3 +163,7 @@ strip = true
|
||||
inherits = "release"
|
||||
lto = "thin" # Faster than fat LTO
|
||||
codegen-units = 4 # Parallel codegen
|
||||
|
||||
[features]
|
||||
default = ["bluetooth"]
|
||||
bluetooth = ["dep:btleplug"]
|
||||
|
||||
@@ -16,6 +16,9 @@ fn main() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check which features are enabled
|
||||
let features = Features::detect();
|
||||
|
||||
// Discover categories dynamically from subdirectories of src/modules/
|
||||
let mut categories: Vec<String> = Vec::new();
|
||||
let entries = match fs::read_dir(modules_root) {
|
||||
@@ -31,6 +34,11 @@ fn main() {
|
||||
if path.is_dir() {
|
||||
if let Some(name) = path.file_name().and_then(|n| n.to_str()) {
|
||||
if !name.starts_with('.') {
|
||||
// Skip categories that are entirely disabled
|
||||
if features.should_skip_category(name) {
|
||||
println!("cargo:warning=Skipping category '{}' (feature disabled)", name);
|
||||
continue;
|
||||
}
|
||||
categories.push(name.to_string());
|
||||
}
|
||||
}
|
||||
@@ -42,6 +50,9 @@ fn main() {
|
||||
for cat in &categories {
|
||||
println!("cargo:rerun-if-changed=src/modules/{}", cat);
|
||||
}
|
||||
|
||||
// Also rerun if features change
|
||||
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_BLUETOOTH");
|
||||
|
||||
// Compile regexes once, reuse across all categories.
|
||||
let run_re = Regex::new(r"pub\s+async\s+fn\s+run\s*\(\s*[^)]*:\s*&str\s*\)")
|
||||
@@ -60,7 +71,7 @@ fn main() {
|
||||
let out_file = format!("{}_dispatch.rs", dispatch_name(cat));
|
||||
let display_name = capitalize(cat);
|
||||
|
||||
match generate_dispatch(&root, &out_file, &mod_prefix, &display_name, &run_re, &info_re, &check_re) {
|
||||
match generate_dispatch(&root, &out_file, &mod_prefix, &display_name, &run_re, &info_re, &check_re, &features) {
|
||||
Ok(_module_count) => {
|
||||
registry_entries.push(RegistryEntry {
|
||||
category: cat.clone(),
|
||||
@@ -81,6 +92,40 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Feature detection and module filtering
|
||||
struct Features {
|
||||
bluetooth: bool,
|
||||
}
|
||||
|
||||
impl Features {
|
||||
fn detect() -> Self {
|
||||
Self {
|
||||
bluetooth: env::var("CARGO_FEATURE_BLUETOOTH").is_ok(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if a category should be entirely skipped
|
||||
fn should_skip_category(&self, category: &str) -> bool {
|
||||
match category {
|
||||
"bluetooth" => !self.bluetooth,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if a module path should be skipped (for feature-gated submodules)
|
||||
fn should_skip_module(&self, module_path: &str) -> bool {
|
||||
// If bluetooth feature is disabled, skip any module under bluetooth/
|
||||
if !self.bluetooth && module_path.starts_with("bluetooth/") {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add more feature checks here as needed
|
||||
// Example: if !self.some_feature && module_path.starts_with("some/path/")
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
struct RegistryEntry {
|
||||
category: String,
|
||||
dispatch_name: String,
|
||||
@@ -118,6 +163,7 @@ fn generate_dispatch(
|
||||
run_re: &Regex,
|
||||
info_re: &Regex,
|
||||
check_re: &Regex,
|
||||
features: &Features,
|
||||
) -> Result<usize, Box<dyn std::error::Error>> {
|
||||
let out_dir = env::var("OUT_DIR").map_err(|_| "OUT_DIR environment variable not set")?;
|
||||
let dest_path = Path::new(&out_dir).join(out_file);
|
||||
@@ -127,7 +173,7 @@ fn generate_dispatch(
|
||||
return Err(format!("Module directory '{}' does not exist", root).into());
|
||||
}
|
||||
|
||||
let mappings = find_modules(root_path, run_re, info_re, check_re)?;
|
||||
let mappings = find_modules(root_path, run_re, info_re, check_re, features)?;
|
||||
|
||||
// Sort for deterministic output
|
||||
let mut sorted_mappings: Vec<_> = mappings.into_iter().collect();
|
||||
@@ -411,6 +457,7 @@ fn find_modules(
|
||||
run_re: &Regex,
|
||||
info_re: &Regex,
|
||||
check_re: &Regex,
|
||||
features: &Features,
|
||||
) -> Result<HashSet<ModuleMapping>, Box<dyn std::error::Error>> {
|
||||
let mut mappings = HashSet::new();
|
||||
|
||||
@@ -422,6 +469,12 @@ fn find_modules(
|
||||
|
||||
if let Ok(relative) = path.strip_prefix(root) {
|
||||
let rel_str = relative.with_extension("").to_string_lossy().replace("\\", "/");
|
||||
|
||||
// Skip modules that are feature-gated out
|
||||
if features.should_skip_module(&rel_str) {
|
||||
println!("cargo:warning=Skipping module '{}' (feature disabled)", rel_str);
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut content = String::new();
|
||||
if File::open(path).and_then(|mut f| f.read_to_string(&mut content)).is_ok() {
|
||||
|
||||
+18
-3
@@ -7,23 +7,38 @@ use super::types::{
|
||||
ServerInfo, ToolsCapability,
|
||||
};
|
||||
|
||||
// You can place this function in src/mcp/server.rs or a shared utility module
|
||||
fn errno() -> i32 {
|
||||
unsafe {
|
||||
#[cfg(any(target_os = "freebsd", target_os = "macos"))]
|
||||
{ *libc::__error() }
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{ *libc::__errno_location() }
|
||||
|
||||
// Add fallbacks for other OSes if needed
|
||||
#[cfg(not(any(target_os = "freebsd", target_os = "macos", target_os = "linux")))]
|
||||
{ 0 } // Or compile_error! to force checking for a new OS
|
||||
}
|
||||
}
|
||||
|
||||
fn isolate_protocol_stdout() -> anyhow::Result<tokio::fs::File> {
|
||||
use std::os::fd::FromRawFd;
|
||||
unsafe {
|
||||
let saved_fd = libc::dup(1);
|
||||
if saved_fd < 0 {
|
||||
anyhow::bail!("dup(1) failed: errno {}", *libc::__errno_location());
|
||||
anyhow::bail!("dup(1) failed: errno {}", errno());
|
||||
}
|
||||
let null_path = b"/dev/null\0";
|
||||
let null_fd = libc::open(null_path.as_ptr() as *const libc::c_char, libc::O_WRONLY);
|
||||
if null_fd < 0 {
|
||||
libc::close(saved_fd);
|
||||
anyhow::bail!("open(/dev/null) failed: errno {}", *libc::__errno_location());
|
||||
anyhow::bail!("open(/dev/null) failed: errno {}", errno());
|
||||
}
|
||||
if libc::dup2(null_fd, 1) < 0 {
|
||||
libc::close(null_fd);
|
||||
libc::close(saved_fd);
|
||||
anyhow::bail!("dup2(null, 1) failed: errno {}", *libc::__errno_location());
|
||||
anyhow::bail!("dup2(null, 1) failed: errno {}", errno());
|
||||
}
|
||||
libc::close(null_fd);
|
||||
let std_file = std::fs::File::from_raw_fd(saved_fd);
|
||||
|
||||
@@ -318,7 +318,7 @@ fn sendmmsg_batch(
|
||||
msg
|
||||
}).collect();
|
||||
|
||||
let ret = unsafe { libc::sendmmsg(fd, msgs.as_mut_ptr(), count as u32, 0) };
|
||||
let ret = unsafe { libc::sendmmsg(fd, msgs.as_mut_ptr(), (count as u32).try_into().unwrap(), 0) };
|
||||
if ret < 0 {
|
||||
let errno = std::io::Error::last_os_error().raw_os_error().unwrap_or(0);
|
||||
(0, Some(errno))
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
pub mod bluetooth;
|
||||
pub mod cameras;
|
||||
pub mod cowrie;
|
||||
pub mod crypto;
|
||||
@@ -20,3 +19,6 @@ pub mod vnc;
|
||||
pub mod voip;
|
||||
pub mod webapps;
|
||||
pub mod windows;
|
||||
|
||||
#[cfg(feature = "bluetooth")]
|
||||
pub mod bluetooth;
|
||||
|
||||
@@ -33,7 +33,6 @@ use reqwest::Client;
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{BufRead, BufReader},
|
||||
process::Command,
|
||||
time::Duration,
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
Reference in New Issue
Block a user