1mod audit;
17mod authentication_compliance;
18mod command;
19mod config;
20mod hsm;
21mod network;
22mod user_privilege;
23
24use std::time::{Duration, SystemTime};
25
26use structopt::StructOpt;
27use tokio;
28
29use crate::authentication_compliance::authentication::{authenticate_user, RateLimiter, Session};
30use crate::command::command::run_command_with_privilege;
31use crate::config::config::Config;
32use crate::user_privilege::privilege::{PrivilegeConfig, PrivilegeLevel, PrivilegeManager};
33use crate::user_privilege::user::{
34 add_user, add_user_to_group, change_password, change_privilege, remove_user,
35 remove_user_from_group,
36};
37
38#[derive(StructOpt, Debug)]
39#[structopt(name = "bell", about = "Privilege escalation system")]
40enum Opt {
41 #[structopt(name = "run")]
42 Run {
43 #[structopt(short, long)]
44 privilege_level: String,
45 #[structopt(short, long)]
46 command: String,
47 #[structopt(short, long)]
48 args: Vec<String>,
49 },
50 #[structopt(name = "user")]
51 User {
52 #[structopt(subcommand)]
53 cmd: UserCommand,
54 },
55}
56
57#[derive(StructOpt, Debug)]
58enum UserCommand {
59 Add {
60 username: String,
61 #[structopt(short, long)]
62 privilege: String,
63 },
64 Remove {
65 username: String,
66 },
67 ChangePassword {
68 username: String,
69 },
70 ChangePrivilege {
71 username: String,
72 privilege: String,
73 },
74 AddToGroup {
75 username: String,
76 group: String,
77 },
78 RemoveFromGroup {
79 username: String,
80 group: String,
81 },
82}
83
84#[tokio::main]
85async fn main() -> Result<(), Box<dyn std::error::Error>> {
86 log4rs::init_file("log4rs.yaml", Default::default())?;
88
89 let opt = Opt::from_args();
90
91 let mut config = Config::load()?;
92 let privilege_config = PrivilegeConfig::default();
93 let mut rate_limiter = RateLimiter::new(5, Duration::from_secs(60));
94 let privilege_manager = PrivilegeManager::new(privilege_config);
95
96 match opt {
97 Opt::Run {
98 privilege_level,
99 command,
100 args,
101 } => {
102 println!("Enter username:");
103 let mut username = String::new();
104 std::io::stdin().read_line(&mut username)?;
105 let username = username.trim();
106
107 println!("Enter password:");
108 let mut password = String::new();
109 std::io::stdin().read_line(&mut password)?;
110 let password = password.trim();
111
112 println!("Enter TOTP code:");
113 let mut totp_code = String::new();
114 std::io::stdin().read_line(&mut totp_code)?;
115 let totp_code = totp_code.trim();
116
117 if let Some(user) =
118 authenticate_user(&config, username, password, totp_code, &mut rate_limiter).await?
119 {
120 let session = Session {
121 user: user.clone(),
122 expiry: SystemTime::now() + Duration::from_secs(config.session_duration),
123 };
124
125 let privilege_level = match privilege_level.as_str() {
126 "bell" => PrivilegeLevel::Bell,
127 "root" => PrivilegeLevel::Root,
128 "admin" => PrivilegeLevel::Administrator,
129 "user" => PrivilegeLevel::User,
130 _ => {
131 println!(
132 "Invalid privilege level. Use 'bell', 'root', 'admin', or 'user'."
133 );
134 return Ok(());
135 }
136 };
137
138 run_command_with_privilege(
139 &session,
140 &command,
141 &args,
142 privilege_level,
143 &config,
144 &privilege_manager,
145 )
146 .await?;
147 } else {
148 println!("Authentication failed.");
149 }
150 }
151 Opt::User { cmd } => match cmd {
152 UserCommand::Add {
153 username,
154 privilege,
155 } => {
156 println!("Enter new password:");
157 let mut password = String::new();
158 std::io::stdin().read_line(&mut password)?;
159 let password = password.trim();
160
161 let privilege_level = match privilege.as_str() {
162 "bell" => PrivilegeLevel::Bell,
163 "root" => PrivilegeLevel::Root,
164 "admin" | "administrator" => PrivilegeLevel::Administrator,
165 "user" => PrivilegeLevel::User,
166 _ => {
167 println!(
168 "Invalid privilege level. Use 'bell', 'root', 'admin', or 'user'."
169 );
170 return Ok(());
171 }
172 };
173 add_user(&mut config, &username, password, privilege_level).await?;
174 }
175 UserCommand::Remove { username } => {
176 remove_user(&mut config, &username).await?;
177 }
178 UserCommand::ChangePassword { username } => {
179 println!("Enter new password:");
180 let mut password = String::new();
181 std::io::stdin().read_line(&mut password)?;
182 let password = password.trim();
183
184 change_password(&mut config, &username, password).await?;
185 }
186 UserCommand::ChangePrivilege {
187 username,
188 privilege,
189 } => {
190 let privilege_level = match privilege.as_str() {
191 "bell" => PrivilegeLevel::Bell,
192 "root" => PrivilegeLevel::Root,
193 "admin" | "administrator" => PrivilegeLevel::Administrator,
194 "user" => PrivilegeLevel::User,
195 _ => {
196 println!(
197 "Invalid privilege level. Use 'bell', 'root', 'admin', or 'user'."
198 );
199 return Ok(());
200 }
201 };
202 change_privilege(&mut config, &username, privilege_level).await?;
203 }
204 UserCommand::AddToGroup { username, group } => {
205 add_user_to_group(&mut config, &username, &group).await?;
206 }
207 UserCommand::RemoveFromGroup { username, group } => {
208 remove_user_from_group(&mut config, &username, &group).await?;
209 }
210 },
211 }
212
213 Ok(())
214}