1pub mod presets;
3pub mod yaml;
4
5pub use presets::{Module, OutputFormat, Parallelism, RateLimit, ScanPreset};
6pub use yaml::YamlConfig;
7
8use std::collections::HashMap;
9use std::sync::{Once, OnceLock};
10
11#[derive(Debug, Clone)]
12pub struct RedDBConfig {
13 pub verbose: bool,
15 pub no_color: bool,
16 pub output_format: String,
17 pub output_file: Option<String>,
18 pub preset: Option<String>,
19 pub threads: usize,
20 pub rate_limit: u32,
21 pub auto_persist: bool,
22
23 pub network: NetworkConfig,
25 pub web: WebConfig,
26 pub recon: ReconConfig,
27 pub database: DatabaseConfig,
28
29 pub wordlists: HashMap<String, String>,
31 pub credentials: HashMap<String, HashMap<String, String>>,
32 pub commands: HashMap<String, HashMap<String, String>>,
33}
34
35#[derive(Debug, Clone)]
36pub struct NetworkConfig {
37 pub threads: usize, pub timeout_ms: u64,
39 pub max_retries: usize,
40 pub request_delay_ms: u64,
41 pub dns_resolver: String,
42 pub dns_timeout_ms: u64,
43}
44
45#[derive(Debug, Clone)]
46pub struct WebConfig {
47 pub user_agent: String,
48 pub follow_redirects: bool,
49 pub max_redirects: usize,
50 pub verify_ssl: bool,
51 pub headers: HashMap<String, String>,
52 pub timeout_secs: u64,
53}
54
55#[derive(Debug, Clone)]
56pub struct ReconConfig {
57 pub subdomain_wordlist: Option<String>,
58 pub passive_only: bool,
59 pub dns_timeout_ms: u64,
60}
61
62#[derive(Debug, Clone)]
63pub struct DatabaseConfig {
64 pub db_dir: Option<String>,
65 pub auto_name: bool,
66 pub auto_persist: bool,
67 pub format_version: u32,
68}
69
70static INIT: Once = Once::new();
71static GLOBAL_CONFIG: OnceLock<RedDBConfig> = OnceLock::new();
72
73pub fn init() -> &'static RedDBConfig {
74 GLOBAL_CONFIG.get_or_init(RedDBConfig::load)
75}
76
77pub fn get() -> &'static RedDBConfig {
79 init()
80}
81
82impl Default for RedDBConfig {
83 fn default() -> Self {
84 Self::from_yaml_config(YamlConfig::default())
85 }
86}
87
88impl RedDBConfig {
89 fn from_yaml_config(cfg: YamlConfig) -> Self {
90 Self {
91 verbose: cfg.verbose.unwrap_or(false),
92 no_color: cfg.no_color.unwrap_or(false),
93 output_format: cfg.output_format.unwrap_or_else(|| "human".to_string()),
94 output_file: cfg.output_file,
95 preset: cfg.preset,
96 threads: cfg.threads.unwrap_or(10),
97 rate_limit: cfg.rate_limit.unwrap_or(0),
98 auto_persist: cfg.auto_persist.unwrap_or(false),
99
100 network: NetworkConfig {
101 threads: cfg.threads.unwrap_or(10),
102 timeout_ms: cfg.network_timeout_ms.unwrap_or(5000),
103 max_retries: cfg.network_max_retries.unwrap_or(2),
104 request_delay_ms: cfg.network_request_delay_ms.unwrap_or(0),
105 dns_resolver: cfg
106 .network_dns_resolver
107 .unwrap_or_else(|| "8.8.8.8".to_string()),
108 dns_timeout_ms: cfg.network_dns_timeout_ms.unwrap_or(3000),
109 },
110
111 web: WebConfig {
112 user_agent: cfg
113 .web_user_agent
114 .unwrap_or_else(|| "RedDB/1.0".to_string()),
115 follow_redirects: cfg.web_follow_redirects.unwrap_or(true),
116 max_redirects: cfg.web_max_redirects.unwrap_or(5),
117 verify_ssl: cfg.web_verify_ssl.unwrap_or(true),
118 headers: cfg.web_headers,
119 timeout_secs: cfg.web_timeout_secs.unwrap_or(10),
120 },
121
122 recon: ReconConfig {
123 subdomain_wordlist: cfg.recon_subdomain_wordlist,
124 passive_only: cfg.recon_passive_only.unwrap_or(false),
125 dns_timeout_ms: cfg.recon_dns_timeout_ms.unwrap_or(3000),
126 },
127
128 database: DatabaseConfig {
129 db_dir: cfg.db_dir,
130 auto_name: cfg.db_auto_name.unwrap_or(true),
131 auto_persist: cfg.db_auto_persist.unwrap_or(true),
132 format_version: cfg.db_format_version.unwrap_or(1),
133 },
134
135 wordlists: cfg.wordlists,
136 credentials: cfg.credentials,
137 commands: cfg.commands,
138 }
139 }
140
141 pub fn load() -> Self {
142 let yaml_config = YamlConfig::load_from_cwd_cached();
143 Self::from_yaml_config(yaml_config.clone())
144 }
145
146 pub fn create_default_file() -> Result<(), String> {
147 use std::fs;
149 use std::path::Path;
150
151 let path = ".reddb.yaml";
152
153 if Path::new(path).exists() {
154 return Err("Config file already exists.".to_string());
155 }
156
157 let content = r#"# RedDB Configuration File
158verbose: false
159no_color: false
160output_format: human
161threads: 10
162auto_persist: false
163
164network:
165 timeout_ms: 5000
166 max_retries: 2
167 dns_resolver: "8.8.8.8"
168 dns_timeout_ms: 3000
169
170web:
171 user_agent: "RedDB/1.0"
172 follow_redirects: true
173 verify_ssl: true
174"#;
175 fs::write(path, content).map_err(|e| e.to_string())
176 }
177}