diff --git a/src/cache.rs b/src/cache.rs index b2e753b4ce179e087fad6dbfa571fabf0987e929..018ae67ef9b372c1ffd9329c962239f9ee262537 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -43,45 +43,27 @@ const USER_TOKEN_FILENAME: &str = "user_token.json"; /// Holds (partial or full) information about a user /// This will mostly be the context user (see `Cache`), and is filled with /// as much detail about the user as is available -pub struct UserInfo<'a> { +pub struct UserInfo { /// Numeric user ID uid: Option<uid_t>, /// Username as used for authentication username: Option<String>, /// Passwd struct (once full getpwnam/getpwuid resolution was possible) - passwd: Option<Passwd<'a>>, + passwd: Option<Passwd>, /// OAuth access token if freshly retrieved or known from disk backed storage access_token: Option<BasicTokenResponse> } -/// In-memory structure to hold global process state -/// Needed because the PAM and NSS components might be used chained (if NSS -/// resolution is necessary to complete PAM authentication), and we need to -/// remember state between the calls. -pub struct Cache<'a> { - /// The user currently calling the library - /// For NSS, this will be the process owner; for PAM, this will be the user - /// logging in (after successful authentication) - pub context_user: UserInfo<'a> -} - -impl Cache { - pub fn new() -> Cache { - let euid = unsafe { - geteuid() - }; - Cache { - context_user: UserInfo { - uid: None, - username: None, - passwd: None, - access_token: None - } +impl UserInfo { + pub fn new() -> UserInfo { + Self { + uid: None, + username: None, + passwd: None, + access_token: None } } -} -impl <'a>UserInfo<'a> { /// Set the information of this user object to that of the process owner // FIXME Move to Cache, with a from_current_user generator method here pub fn set_current_user(&mut self) { @@ -189,7 +171,7 @@ impl <'a>UserInfo<'a> { pub fn set_username(&mut self, username: String) { self.username = Some(username); - if self.passwd.is_some() && self.passwd.as_ref().unwrap().pw_name != self.username.as_ref().unwrap() { + if self.passwd.is_some() && self.passwd.as_ref().unwrap().pw_name != self.username.as_ref().unwrap().to_string() { // Invalidate passwd because UID does not match anymore self.passwd = None; self.try_resolve(); @@ -202,12 +184,12 @@ impl <'a>UserInfo<'a> { /// Return the home directory from the passwd slot, /// attempting NSS resolution before doing so - pub fn get_home_directory(&mut self) -> Result<&str, io::Error> { + pub fn get_home_directory(&mut self) -> Result<String, io::Error> { if self.passwd.is_none() { self.try_resolve(); } match &self.passwd { - Some(passwd) => Ok(passwd.pw_dir), + Some(passwd) => Ok(passwd.pw_dir.clone()), None => Err(io::Error::new(io::ErrorKind::InvalidInput, "foo")) } } @@ -277,7 +259,7 @@ impl <'a>UserInfo<'a> { // Determine home directory and override $HOME to make the XDG code return // XDG directories for a different user let user_home = self.get_home_directory()?; - env::set_var("HOME", user_home); + env::set_var("HOME", &user_home); debug!("Home directory for UID {} is {}", uid, user_home); } @@ -401,8 +383,12 @@ fn get_original_euid() -> uid_t { } lazy_static! { - static ref CACHE: Mutex<Cache> = Mutex::new(Cache::new()); + /// Current context user + /// Needed because the PAM and NSS components might be used chained (if NSS + /// resolution is necessary to complete PAM authentication), and we need to + /// remember state between the calls. + static ref CONTEXT_USER: Mutex<UserInfo> = Mutex::new(UserInfo::new()); } -pub fn get_cache() -> MutexGuard<'static, Cache> { - CACHE.lock().unwrap() +pub fn get_context_user() -> MutexGuard<'static, UserInfo> { + CONTEXT_USER.lock().unwrap() } diff --git a/src/nss.rs b/src/nss.rs index dca4b9fd8a3f120426a30f705f33c2e0450c6167..27f3523b8475ae25db3d67f2fb6583401a28fe8d 100644 --- a/src/nss.rs +++ b/src/nss.rs @@ -18,7 +18,7 @@ use crate::config::{ get_optional, }; use config::Config; -use crate::cache::get_cache; +use crate::cache::get_context_user; use crate::logging::setup_log; @@ -53,8 +53,8 @@ fn nss_hook_prepare() -> Config { // Set the context user to the current user, but only if not already set // When doing PAM, we might get called back into by libc to do some NSS // lookup, and we want to keep the PAM login user context in that case - if !get_cache().context_user.is_initialized() { - get_cache().context_user.set_current_user(); + if !get_context_user().is_initialized() { + get_context_user().set_current_user(); } return conf; @@ -67,8 +67,8 @@ impl PasswdHooks for OidcPasswd { let conf = nss_hook_prepare(); info!("[NSS] passwd.get_all_entries called"); - let mut cache = get_cache(); - let user_token_res = cache.context_user.get_access_token(); + let mut context_user = get_context_user(); + let user_token_res = context_user.get_access_token(); // FIXME Implement caching of system token let system_token_res = get_access_token_client(&conf, "nss", "", ""); let system_token_res = system_token_res.as_ref(); @@ -100,8 +100,8 @@ impl PasswdHooks for OidcPasswd { let conf = nss_hook_prepare(); info!("[NSS] passwd.get_entry_by_uid called for {}", uid); - let mut cache = get_cache(); - let user_token_res = cache.context_user.get_access_token(); + let mut context_user = get_context_user(); + let user_token_res = context_user.get_access_token(); // FIXME Implement caching of system token let system_token_res = get_access_token_client(&conf, "nss", "", ""); let system_token_res = system_token_res.as_ref(); @@ -133,8 +133,8 @@ impl PasswdHooks for OidcPasswd { let conf = nss_hook_prepare(); info!("[NSS] passwd.get_entry_by_name called for {}", name); - let mut cache = get_cache(); - let user_token_res = cache.context_user.get_access_token(); + let mut context_user = get_context_user(); + let user_token_res = context_user.get_access_token(); // FIXME Implement caching of system token let system_token_res = get_access_token_client(&conf, "nss", "", ""); let system_token_res = system_token_res.as_ref(); diff --git a/src/pam.rs b/src/pam.rs index 02b26a773ed5862f761609021207ecd8de94753f..8bfef0c02b3cce320bae474581c6720e478f7a99 100644 --- a/src/pam.rs +++ b/src/pam.rs @@ -24,7 +24,7 @@ use crate::oauth::get_access_token_password; use crate::logging::setup_log; -use crate::cache::{get_cache, set_is_getpwnam_safe}; +use crate::cache::{get_context_user, set_is_getpwnam_safe}; use pamsm::{PamServiceModule, Pam, PamFlag, PamError, PamLibExt}; @@ -91,8 +91,8 @@ impl PamServiceModule for PamOidc { Ok(t) => { info!("Authenticated {} using Resource Owner Password Grant", username); set_is_getpwnam_safe(false); - get_cache().context_user.set_username(username.to_string()); - get_cache().context_user.set_access_token(t); + get_context_user().set_username(username.to_string()); + get_context_user().set_access_token(t); set_is_getpwnam_safe(true); return PamError::SUCCESS; },