summaryrefslogtreecommitdiff
path: root/src/auth.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/auth.rs')
-rw-r--r--src/auth.rs126
1 files changed, 126 insertions, 0 deletions
diff --git a/src/auth.rs b/src/auth.rs
new file mode 100644
index 0000000..c973921
--- /dev/null
+++ b/src/auth.rs
@@ -0,0 +1,126 @@
+use nix::unistd::Group;
+use crate::{persist, secure};
+
+
+pub struct Config {
+ pub identitys: Vec<(String, bool)>,
+}
+
+
+/// 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.
+pub fn load_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})
+}
+
+
+/// Returns a vector of group names of the groups the current effective uid is in
+/// #### 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() -> Vec<String> {
+ 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 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
+pub fn authorize(config: &Config, user: &str) -> Option<bool> {
+ let groups = get_groups();
+ for (identity, persist) in &config.identitys {
+ if identity.starts_with(":") {
+ let group = &identity[1..];
+ if groups.contains(&group.to_string()) {
+ return Some(persist.clone());
+ };
+ } else if identity == user {
+ return Some(persist.clone());
+ }
+ }
+ None
+}
+
+
+/// Authenticates an authorized user 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
+pub fn authenticate(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;
+ }
+ if persist {
+ persist::set_persist(user);
+ }
+ secure::elevate_privilages(0, 0);
+ return true;
+}