Skip to main content

reddb_server/config/
mod.rs

1/// Configuration management for reddb
2pub 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    // Global settings
14    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    // Nested configurations
24    pub network: NetworkConfig,
25    pub web: WebConfig,
26    pub recon: ReconConfig,
27    pub database: DatabaseConfig,
28
29    // Dynamic maps
30    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, // Fallback if global threads not used? Usually global threads overrides.
38    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
77/// Access the global configuration, loading defaults if necessary.
78pub 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        // ... (Same as before, implementation of default file creation)
148        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}