1use std::env;
2use std::fs;
3use std::path::PathBuf;
4
5use serde::{Deserialize, Serialize};
6
7use crate::error::Result;
8
9fn home_dir() -> PathBuf {
10 if let Some(home) = env::var_os("HOME") {
11 PathBuf::from(home)
12 } else if let Some(profile) = env::var_os("USERPROFILE") {
13 PathBuf::from(profile)
14 } else {
15 env::current_dir().unwrap_or_else(|_| PathBuf::from("."))
16 }
17}
18
19pub fn config_dir() -> PathBuf {
20 home_dir().join(".config").join("ploit_malper")
21}
22
23pub fn config_file() -> PathBuf {
24 config_dir().join("config.json")
25}
26
27pub fn nvd_cache_file() -> PathBuf {
28 config_dir().join("nvd_cache.json")
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
32#[serde(default)]
33pub struct MSFRPCConfig {
34 pub host: String,
35 pub port: u16,
36 pub username: String,
37 pub password: String,
38 pub ssl: bool,
39 pub workspace: String,
40}
41
42impl Default for MSFRPCConfig {
43 fn default() -> Self {
44 Self {
45 host: "127.0.0.1".to_string(),
46 port: 55553,
47 username: "msf".to_string(),
48 password: String::new(),
49 ssl: true,
50 workspace: "default".to_string(),
51 }
52 }
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize, Default)]
56#[serde(default)]
57pub struct NVDConfig {
58 pub api_key: String,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
62#[serde(default)]
63pub struct AppConfig {
64 pub msfrpc: MSFRPCConfig,
65 pub nvd: NVDConfig,
66 pub report_dir: String,
67 pub last_scan_file: Option<String>,
68}
69
70impl Default for AppConfig {
71 fn default() -> Self {
72 Self {
73 msfrpc: MSFRPCConfig::default(),
74 nvd: NVDConfig::default(),
75 report_dir: home_dir()
76 .join("ploit_malper_reports")
77 .to_string_lossy()
78 .to_string(),
79 last_scan_file: None,
80 }
81 }
82}
83
84#[derive(Debug, Clone)]
85pub struct ConfigManager {
86 pub config: AppConfig,
87 loaded: bool,
88}
89
90impl ConfigManager {
91 pub fn new() -> Self {
92 Self {
93 config: AppConfig::default(),
94 loaded: false,
95 }
96 }
97
98 pub fn load(&mut self) -> bool {
99 let path = config_file();
100 if !path.exists() {
101 return false;
102 }
103
104 match fs::read_to_string(&path) {
105 Ok(raw) => match serde_json::from_str::<AppConfig>(&raw) {
106 Ok(config) => {
107 self.config = config;
108 self.loaded = true;
109 true
110 }
111 Err(_) => false,
112 },
113 Err(_) => false,
114 }
115 }
116
117 pub fn save(&mut self) -> Result<()> {
118 let dir = config_dir();
119 fs::create_dir_all(&dir)?;
120 let path = config_file();
121 let data = serde_json::to_string_pretty(&self.config)?;
122 fs::write(path, data)?;
123 self.loaded = true;
124 Ok(())
125 }
126
127 pub fn reset(&mut self) -> Result<()> {
128 let config_path = config_file();
129 if config_path.exists() {
130 fs::remove_file(config_path)?;
131 }
132
133 let cache_path = nvd_cache_file();
134 if cache_path.exists() {
135 fs::remove_file(cache_path)?;
136 }
137
138 self.config = AppConfig::default();
139 self.loaded = false;
140 Ok(())
141 }
142
143 pub fn is_configured(&self) -> bool {
144 self.loaded && !self.config.msfrpc.password.is_empty()
145 }
146
147 pub fn is_nvd_configured(&self) -> bool {
148 !self.config.nvd.api_key.is_empty()
149 }
150
151 pub fn get_msfrpc_config(&self) -> &MSFRPCConfig {
152 &self.config.msfrpc
153 }
154
155 pub fn get_nvd_config(&self) -> &NVDConfig {
156 &self.config.nvd
157 }
158}
159
160impl Default for ConfigManager {
161 fn default() -> Self {
162 Self::new()
163 }
164}