From 9577388b19d315aff5336a0c1513d21838967b29 Mon Sep 17 00:00:00 2001 From: Dominik George <dominik.george@teckids.org> Date: Thu, 13 May 2021 12:32:56 +0200 Subject: [PATCH] [Cache] Fix some more reference passing, and access to original_euid --- src/cache.rs | 75 ++++++++++++++++++++++++++++++---------------------- src/nss.rs | 35 +++++++++++++++++------- src/pam.rs | 2 +- 3 files changed, 69 insertions(+), 43 deletions(-) diff --git a/src/cache.rs b/src/cache.rs index 065862f..475e7b0 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -36,9 +36,9 @@ use serde_json; const USER_TOKEN_FILENAME: &str = "user_token.json"; -struct UserInfo<'a> { +pub struct UserInfo<'a> { uid: Option<uid_t>, - username: Option<&'a str>, + username: Option<String>, passwd: Option<Passwd<'a>>, access_token: Option<BasicTokenResponse> } @@ -65,18 +65,18 @@ impl Cache<'_> { impl <'a>UserInfo<'a> { pub fn set_current_user(&mut self) { - self.set_uid(original_euid); + self.set_uid(get_original_euid()); } pub fn is_initialized(&self) -> bool { self.uid.is_some() || self.username.is_some() } - fn try_resolve(&mut self) -> Result<&Passwd, io::Error> { - // If we already have a full passwd struct, return it as without resolving + fn try_resolve(&mut self) -> Result<(), io::Error> { + // If we already have a full passwd struct, do nothing if self.passwd.is_some() { debug!("passwd entry for context user already resolved"); - return Ok(self.passwd.as_ref().unwrap()); + return Ok(()); } // If we cannot call getpwnam safely, return error (see `is_get_pwnam_safe`) @@ -102,18 +102,19 @@ impl <'a>UserInfo<'a> { Ok(passwd) => { debug!("Successfully resolved context user's passwd entry"); self.passwd = Some(passwd); - Ok(self.passwd.as_ref().unwrap()) + Ok(()) }, Err(e) => Err(e) } } pub fn get_uid(&mut self) -> Result<uid_t, io::Error> { - match self.try_resolve() { - Ok(passwd) => Ok(passwd.pw_uid), - Err(e) => match self.uid { + self.try_resolve(); + match &self.passwd { + Some(passwd) => Ok(passwd.pw_uid), + None => match self.uid { Some(uid) => Ok(uid), - None => Err(e) + None => Err(io::Error::new(io::ErrorKind::InvalidInput, "foo")) } } } @@ -125,17 +126,18 @@ impl <'a>UserInfo<'a> { self.try_resolve(); } - pub fn get_username(&mut self) -> Result<&str, io::Error> { - match self.try_resolve() { - Ok(passwd) => Ok(passwd.pw_name), - Err(e) => match self.username { - Some(username) => Ok(username), - None => Err(e) + pub fn get_username(&mut self) -> Result<String, io::Error> { + self.try_resolve(); + match &self.passwd { + Some(passwd) => Ok(passwd.pw_name.to_string()), + None => match &self.username { + Some(username) => Ok(username.to_string()), + None => Err(io::Error::new(io::ErrorKind::InvalidInput, "foo")) } } } - pub fn set_username(&mut self, username: &'a str) { + pub fn set_username(&mut self, username: String) { self.username = Some(username); self.uid = None; self.passwd = None; @@ -143,13 +145,14 @@ impl <'a>UserInfo<'a> { } pub fn get_home_directory(&mut self) -> Result<&str, io::Error> { - match self.try_resolve() { - Ok(passwd) => Ok(passwd.pw_dir), - Err(e) => Err(e) + self.try_resolve(); + match &self.passwd { + Some(passwd) => Ok(passwd.pw_dir), + None => Err(io::Error::new(io::ErrorKind::InvalidInput, "foo")) } } - fn drop_privileges(&self) -> Result<uid_t, io::Error> { + fn drop_privileges(&mut self) -> Result<uid_t, io::Error> { let current_euid = unsafe { geteuid() }; @@ -185,13 +188,13 @@ impl <'a>UserInfo<'a> { geteuid() }; - if current_euid != original_euid { + if current_euid != get_original_euid() { debug!("Restoring privileges"); let res = unsafe { - seteuid(original_euid) + seteuid(get_original_euid()) }; if res != 0 { - panic!("Could not restore privileges to {}", original_euid); + panic!("Could not restore privileges to {}", get_original_euid()); } } else { debug!("No need to restore privileges, already running as original user"); @@ -204,7 +207,7 @@ impl <'a>UserInfo<'a> { // Determine user ID to find out whether we should override $HOME let uid = self.get_uid()?; - if uid != original_euid { + if uid != get_original_euid() { let user_home = self.get_home_directory()?; env::set_var("HOME", user_home); debug!("Home directory for UID {} is {}", uid, user_home); @@ -217,7 +220,7 @@ impl <'a>UserInfo<'a> { }; // Restore $HOME to original if we changed it earlier - if uid != original_euid { + if uid != get_original_euid() { if saved_home != None { env::set_var("HOME", saved_home.unwrap()); } else { @@ -235,7 +238,7 @@ impl <'a>UserInfo<'a> { } } - pub fn get_access_token(&mut self) -> Option<BasicTokenResponse> { + pub fn get_access_token(&mut self) -> &Option<BasicTokenResponse> { // Try to load our acess token if none is known if self.access_token.is_none() { debug!("No token in memory, trying to load from file"); @@ -250,7 +253,7 @@ impl <'a>UserInfo<'a> { self.restore_privileges(); } - return self.access_token; + return &self.access_token; } pub fn set_access_token(&mut self, token: BasicTokenResponse) -> Result<(), io::Error> { @@ -296,9 +299,17 @@ fn is_getpwnam_safe() -> bool { return true; } -static original_euid: uid_t = unsafe { - geteuid() -}; +static mut original_euid: uid_t = uid_t::MAX; +static mut original_euid_set: bool = false; +fn get_original_euid() -> uid_t { + unsafe { + if !original_euid_set { + original_euid = geteuid(); + original_euid_set = true; + } + original_euid + } +} lazy_static! { static ref CACHE: Mutex<Cache<'static>> = Mutex::new(Cache::new()); diff --git a/src/nss.rs b/src/nss.rs index c8af522..21fa3b4 100644 --- a/src/nss.rs +++ b/src/nss.rs @@ -65,12 +65,17 @@ impl PasswdHooks for OidcPasswd { if !get_cache().context_user.is_initialized() { get_cache().context_user.set_current_user(); } - let token = match get_cache().context_user.get_access_token() { + + let mut cache = get_cache(); + let user_token_res = cache.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(); + let token = match user_token_res { Some(t) => t, None => { - // FIXME Implement caching of system token debug!("Could not find a user token to request NSS data; trying client credentials"); - match get_access_token_client(&conf, "nss", "", "") { + match system_token_res { Ok(ct) => ct, Err(e) => { error!("Failed to get access token with client credentials: {}", e); @@ -96,12 +101,17 @@ impl PasswdHooks for OidcPasswd { if !get_cache().context_user.is_initialized() { get_cache().context_user.set_current_user(); } - let token = match get_cache().context_user.get_access_token() { + + let mut cache = get_cache(); + let user_token_res = cache.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(); + let token = match user_token_res { Some(t) => t, None => { - // FIXME Implement caching of system token debug!("Could not find a user token to request NSS data; trying client credentials"); - match get_access_token_client(&conf, "nss", "", "") { + match system_token_res { Ok(ct) => ct, Err(e) => { error!("Failed to get access token with client credentials: {}", e); @@ -126,12 +136,17 @@ impl PasswdHooks for OidcPasswd { if !get_cache().context_user.is_initialized() { get_cache().context_user.set_current_user(); } - let token = match get_cache().context_user.get_access_token() { + + let mut cache = get_cache(); + let user_token_res = cache.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(); + let token = match user_token_res { Some(t) => t, None => { - // FIXME Implement caching of system token - debug!("Could not find a user token for to request NSS data; trying client credentials"); - match get_access_token_client(&conf, "nss", "", "") { + debug!("Could not find a user token to request NSS data; trying client credentials"); + match system_token_res { Ok(ct) => ct, Err(e) => { error!("Failed to get access token with client credentials: {}", e); diff --git a/src/pam.rs b/src/pam.rs index f721a50..e98a1fa 100644 --- a/src/pam.rs +++ b/src/pam.rs @@ -90,7 +90,7 @@ impl PamServiceModule for PamOidc { match get_access_token_password(&conf, "pam", username.to_string(), password.to_string(), PamError::SERVICE_ERR, PamError::AUTH_ERR) { Ok(t) => { info!("Authenticated {} using Resource Owner Password Grant", username); - get_cache().context_user.set_username(username); + get_cache().context_user.set_username(username.to_string()); get_cache().context_user.set_access_token(t); return PamError::SUCCESS; }, -- GitLab