bell/
bell.rs

1// Copyright (C) 2024 Bellande Architecture Mechanism Research Innovation Center, Ronaldson Bellande
2
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU General Public License for more details.
12
13// You should have received a copy of the GNU General Public License
14// along with this program.  If not, see <https://www.gnu.org/licenses/>.
15
16mod 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    // Initialize logging
87    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}