diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 142 |
1 files changed, 50 insertions, 92 deletions
diff --git a/src/main.rs b/src/main.rs index 28f08cd..56df611 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,142 +1,100 @@ use std::env; use std::process::ExitCode; -use pwd::Passwd; -use nix::unistd; -extern crate time; -const ERROR_ARGS: u8 = 1; -const ERROR_CONFIG: u8 = 2; -const ERROR_NO_USER: u8 = 3; -const ERROR_NOT_AUTHORIZED: u8 = 4; -const ERROR_AUTH_FAILED: u8 = 5; -const ERROR_RUN_ROOT: u8 = 6; - -mod persist; +mod auth; mod flags; -mod help; +mod persist; mod secure; + +const ERROR_ARGS: u8 = 1; +const ERROR_CONFIG: u8 = 2; +const ERROR_NOT_AUTHORIZED: u8 = 3; +const ERROR_AUTH_FAILED: u8 = 4; +const ERROR_ELEVATE_PRIVILEGES: u8 = 5; + + fn main() -> ExitCode { + + // gets the arguments from the env let args: Vec<String> = env::args().collect(); + + // pase the arguments into valid flags that are usuable by crab let flags = match flags::parse(&args[1..]) { Some(data) => data, + // if there is an invalid flag, print the help message and exit None => { - help::help(); + help(); return ExitCode::from(ERROR_ARGS); } }; + + // If the version arg flag is set, print the crab version if flags.version { - println!("crab version 0.0.5"); + println!("crab version 0.0.6"); return ExitCode::SUCCESS; } + + // If the help arg flag is set, print the crab help message if flags.help { - help::help(); + help(); return ExitCode::SUCCESS; } + + // If the amount of acutal command arguments is less than two, a.k.a just `crab`, print the command usage if args.len() - flags.arg_count < 2 { println!("usage: crab [-d] command [args]"); return ExitCode::SUCCESS; } - let config = match config("/etc/crab.conf") { + + // Load the command config from /etc + let configs = match auth::load_config_file("/etc/crab.conf") { Some(data) => data, None => return ExitCode::from(ERROR_CONFIG) }; - let user = match Passwd::current_user() { + + + // check if the user is authorized + let auth = match auth::authorize(&configs, nix::unistd::getuid()) { Some(data) => data, None => { - eprintln!("You dont exist."); - return ExitCode::from(ERROR_NO_USER); - } - }; - let persist = match allowed(&config, &user.name) { - Some(data) => data && !flags.dont_persist, - None => { eprintln!("Operation Not Permitted."); return ExitCode::from(ERROR_NOT_AUTHORIZED); } }; - if !validate(&user.name, persist) { + // authenticate the user + if !auth::authenticate(&configs[auth], flags.dont_persist, nix::unistd::getuid()) { eprintln!("Authentication failed."); return ExitCode::from(ERROR_AUTH_FAILED); } - if !unistd::setuid(unistd::geteuid()).is_ok() || !unistd::setgid(unistd::getegid()).is_ok() { - eprintln!("Failed to set root permissions"); - return ExitCode::from(ERROR_RUN_ROOT); + // elevate privileges + if nix::unistd::setuid(configs[auth].privlaged_uid).is_err() { + eprintln!("Failed to elevate privileges."); + return ExitCode::from(ERROR_ELEVATE_PRIVILEGES); }; + + // execute the passed command let start = 1 + flags.arg_count; let err = exec::execvp(&args[start], &args[start..]); + // print an error if an error was returned eprintln!("{}", err); ExitCode::SUCCESS } -struct Config { - users: Vec<(String, bool)> -} -fn validate(user: &str, persist: bool) -> bool { - if persist && persist::get_persist(user) { - return true; - } - let input = match rpassword::prompt_password(format!("crab ({}) password: ", user)) { - Ok(data) => data, - Err(_) => return false - }; - let mut auth = match pam::Authenticator::with_password("crab") { - Ok(data) => data, - Err(_) => return false - }; - auth.get_handler().set_credentials(user.to_owned(), input); - if !auth.authenticate().is_ok() || !auth.open_session().is_ok() { - return false; - } - if persist { - persist::set_persist(user); - } - return true; -} - -fn allowed(config: &Config, user: &str) -> Option<bool> { - for (name, persist) in &config.users { - if name == user { - return Some(persist.clone()); - } - } - None -} - -fn config(path: &str) -> Option<Config> { - let file = match std::fs::read_to_string(path) { - Err(e) => { - eprintln!("{}: {}", &path, e); - return None - }, - Ok(data) => data - }; - - let mut users = vec![]; - for (line_num, line) in file.split("\n").enumerate() { - let args: Vec<&str> = line.split(" ").collect(); - if line.trim() == "" { - continue; - } - if args.len() < 2 { - eprintln!("Error in config at line {}: Not enough arguments", line_num); - continue; - } - let user: String = args[0].to_string(); - let persist: bool = match args[1].parse() { - Err(e) => { - eprintln!("Error in config at line {}: {}", line_num, e); - continue; - }, - Ok(data) => data - }; - users.push((user, persist)); - } - Some(Config{users}) +/// Prints the help message to the standard output +fn help() { + let help = +"Usage: + crab [-d] command [args] +Options: + -v --version Get the current version of the package + -h --help Generates the crab help message + -d If your user is set to persist, dont save persistance"; + println!("{}", help); } |