diff --git a/src/cache.rs b/src/cache.rs index cb707c22894508a7fec645e0af05a9a5eba3ff44..2a23c4f8f424498ed69c11fedf0e904529a14948 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -18,7 +18,7 @@ use std::collections::HashMap; use std::convert::From; use std::time::SystemTime; -use libc::{geteuid, seteuid, getpwnam}; +use libc::{geteuid, seteuid, getpwnam, uid_t}; use std::ffi::CString; use oauth2::basic::BasicTokenResponse; @@ -32,7 +32,7 @@ struct UserToken { } -impl UserToken { +impl UserToken { fn is_expired(&self) -> bool { match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { Ok(d) => d.as_secs() >= self.expires_at, @@ -58,16 +58,39 @@ impl From<BasicTokenResponse> for UserToken { } struct Cache { - user_tokens: HashMap<String, UserToken> + user_tokens: HashMap<String, UserToken>, + original_euid: uid_t } impl Cache { pub fn new() -> Cache { Cache { - user_tokens: HashMap::new() + user_tokens: HashMap::new(), + original_euid: geteuid() } } + fn drop_privileges(&self, username: String) -> Result<uid_t, String> { + let nam = match CString::new(username) { + Ok(nam) => nam, + Err(_) => return Err("Invalid username in lookup".to_string()) + }; + let target_euid = (*getpwnam(nam.as_ptr())).pw_uid; + + if target_euid == self.original_euid { + return Ok(self.original_euid); + } else if self.original_euid == 0 { + seteuid(target_euid); + return Ok(target_euid); + } + + return Err("Dropping privileges not supported".to_string()); + } + + fn restore_privileges(&self) { + seteuid(self.original_euid); + } + pub fn load_user_token(&self, owner: String) -> Option<&UserToken> { return self.user_tokens.get(&owner); } @@ -80,26 +103,9 @@ impl Cache { self.user_tokens.remove(&owner); // Try to remove user's token cache file - let original_euid = geteuid(); - let target_euid = (*getpwnam(CStr::new(owner).ok().unwrap().as_ptr())).pw_uid; - - if original_euid != target_euid { - // We are not already running as the target user - if original_euid == 0 { - // If we are root, try dropping privileges to the target user - seteuid(target_euid); - } else { - // Bail out silently if we are not root - return; - } - } - + self.drop_privileges(owner).ok(); // FIXME Add delete code here - - if original_euid != target_euid { - // Restore original privileges if we dropped them earlier - seteuid(original_euid); - } + self.restore_privileges(); } pub fn cleanup_tokens(&self) {