summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs144
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})
-}