diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 144 |
1 files changed, 5 insertions, 139 deletions
diff --git a/src/main.rs b/src/main.rs index 850d43b..ed89e76 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,11 @@ use std::env; use std::process::ExitCode; use pwd::Passwd; -use nix::unistd::{self, Uid, Group}; -mod persist; +mod auth; mod flags; +mod persist; mod secure; @@ -50,7 +50,7 @@ fn main() -> ExitCode { } // Load the command config from /etc - let config = match config("/etc/crab.conf") { + let config = match auth::load_config("/etc/crab.conf") { Some(data) => data, None => return ExitCode::from(ERROR_CONFIG) }; @@ -65,7 +65,7 @@ fn main() -> ExitCode { }; // check if the user is authorized - let persist = match allowed(&config, &user.name) { + let persist = match auth::authorize(&config, &user.name) { Some(data) => data && !flags.dont_persist, None => { eprintln!("Operation Not Permitted."); @@ -74,7 +74,7 @@ fn main() -> ExitCode { }; // authenticate the user - if !validate(&user.name, persist) { + if !auth::authenticate(&user.name, persist) { eprintln!("Authentication failed."); return ExitCode::from(ERROR_AUTH_FAILED); } @@ -101,137 +101,3 @@ Options: -d If your user is set to persist, dont save persistance"; println!("{}", help); } - - -struct Config { - identitys: Vec<(String, bool)>, -} - - -/// Validates the authorized user, and authenticates them for -/// the current session. If the user is already persisted, it -/// will attempt to read the persist file, and then skip -/// authentication if the is still persisted. -/// #### Arguments -/// * `user` - The login name of the linux user -/// * `persist` - If the user's login should persist -/// #### Returns -/// * `true` - If the user authenticated sucessfully, or the user is persisted -/// * `false` - If the user failed to authenticate -fn validate(user: &str, persist: bool) -> bool { - if persist && persist::get_persist(user) { - secure::elevate_privilages(0, 0); - 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; - } - secure::elevate_privilages(0, 0); - if persist { - persist::set_persist(user); - } - return true; -} - - -/// Returns if the user is authorized given a sepcific config and user name. -/// #### Arguments -/// * `config` - A config struct contaning the authorization settings for crab -/// * `user` - The name of the user to check is authorized -/// #### Returns -/// * `None` - If the user is not authorized -/// * `Some(bool)` - If the user is authorized, returning the boolean if the -/// user is set to persist -fn allowed(config: &Config, user: &str) -> Option<bool> { - // get user groups - let groups = get_groups(Uid::current()); - // check each config identiy - for (identity, persist) in &config.identitys { - // if it starts with a :, its a group - if identity.starts_with(":") { - let group = &identity[1..]; - if groups.contains(&group.to_string()) { - return Some(persist.clone()); - }; - // else its a user - } else if identity == user { - return Some(persist.clone()); - } - } - None -} - - -/// Returns a vector of group names of the groups a specific linux user is in -/// #### Arguments -/// * 'uid' - The user id od the linux user to get groups from -/// #### Returns -/// A vector of strings of the groups the user is in. If the vector is empty, -/// either the function coudn't retrieve the users groups, or the user is not in -/// any groups. -fn get_groups(uid: Uid) -> Vec<String> { - let no_change = Uid::from_raw(u32::MAX); - if unistd::setresuid(no_change, uid, no_change).is_err() { - return vec![] - }; - let groups = match nix::unistd::getgroups() { - Ok(data) => data, - Err(_) => return vec![] - }; - let names = groups.iter() - .map(|gid| Group::from_gid(*gid)) - .flatten().flatten() - .map(|group| group.name) - .collect(); - names -} - - -/// Returns a option containing the config ad the specific pile path. -/// This function will print out config syntax errors to the standard -/// output if it failes to parse certain lines. -/// #### Arguments -/// * `path` - The path to the config file -/// #### Returns -/// * `None` - If the config failed to load -/// * `Some(Config)` - If the config was sucessfully parsed. -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 identitys = vec![]; - for (line_num, line) in file.split("\n").enumerate() { - let args: Vec<&str> = line.split(" ").collect(); - if line.starts_with("#") || line.trim() == "" { - continue; - } - if args.len() < 2 { - eprintln!("Error in config at line {}: Not enough arguments", line_num); - continue; - } - let identity: 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 - }; - identitys.push((identity, persist)); - } - Some(Config{identitys}) -} |