Skip to content
Snippets Groups Projects
Verified Commit ba5ad72f authored by Nik | Klampfradler's avatar Nik | Klampfradler
Browse files

[Cache] Add comments and debug logging

Fixed a security issue on the go which would write the user cache file
as root if dropping privileges failed.
parent 37d478fb
No related branches found
No related tags found
No related merge requests found
...@@ -89,17 +89,27 @@ impl Cache { ...@@ -89,17 +89,27 @@ impl Cache {
}; };
let target_euid = (*getpwnam(nam.as_ptr())).pw_uid; let target_euid = (*getpwnam(nam.as_ptr())).pw_uid;
if target_euid == self.original_euid { if target_euid == self.original_euid {
debug!("No need to drop privileges, already running as {}", username);
return Ok(self.original_euid); return Ok(self.original_euid);
} else if self.original_euid == 0 { } else if self.original_euid == 0 {
seteuid(target_euid); let res = seteuid(target_euid);
return Ok(target_euid); if res == 0 {
debug!("Successfully dropped privileges to {}", username);
return Ok(target_euid);
} else {
error!("Could not drop privileges to {}", username);
return Err("Failed to drop privileges".to_string());
}
} }
error!("Not running as root or target user, cannot drop privileges");
return Err("Dropping privileges not supported".to_string()); return Err("Dropping privileges not supported".to_string());
} }
fn restore_privileges(&self) { fn restore_privileges(&self) {
debug!("Restoring privileges");
seteuid(self.original_euid); seteuid(self.original_euid);
} }
...@@ -112,6 +122,7 @@ impl Cache { ...@@ -112,6 +122,7 @@ impl Cache {
}; };
let user_home = CString::from_raw((*getpwnam(nam.as_ptr())).pw_dir).to_str().unwrap(); let user_home = CString::from_raw((*getpwnam(nam.as_ptr())).pw_dir).to_str().unwrap();
env::set_var("HOME", user_home); env::set_var("HOME", user_home);
debug!("Home directory for {} is {}", username, user_home);
let base_dirs = BaseDirectories::with_prefix(BASE_NAME)?; let base_dirs = BaseDirectories::with_prefix(BASE_NAME)?;
...@@ -122,7 +133,16 @@ impl Cache { ...@@ -122,7 +133,16 @@ impl Cache {
} }
match self.drop_privileges(username) { match self.drop_privileges(username) {
Ok(_) => base_dirs.create_cache_directory(BASE_NAME).ok(), Ok(_) => match base_dirs.create_cache_directory(BASE_NAME) {
Ok(v) => {
info!("Created XDG cache directory for user {}", username);
Some(v)
},
Err(e) => {
error!("Error creating XDG cache directory for user {}: {}", username, e);
None
}
}
Err(_) => None Err(_) => None
}; };
self.restore_privileges(); self.restore_privileges();
...@@ -138,56 +158,66 @@ impl Cache { ...@@ -138,56 +158,66 @@ impl Cache {
} }
pub fn load_user_token(&self, owner: String) -> Option<&UserToken> { pub fn load_user_token(&self, owner: String) -> Option<&UserToken> {
match self.user_tokens.get(&owner) { let token = self.user_tokens.get(&owner);
Some(t) => { if token.is_none() || token.unwrap().is_expired() {
if t.is_expired() { debug!("No recent token for {} in memory, trying to load from file", owner);
// Try to load token from file self.user_tokens.remove(&owner);
self.drop_privileges(owner).ok();
let new_token = match self.place_user_cache_file(owner, USER_TOKEN_FILENAME) { self.drop_privileges(owner).ok();
Ok(path) => match load_json(path) { let new_token = match self.place_user_cache_file(owner, USER_TOKEN_FILENAME) {
Ok(read_token) => { Ok(path) => match load_json::<UserToken>(path) {
self.user_tokens.insert(owner, read_token); Ok(read_token) => {
Some(&read_token) if !read_token.is_expired() {
}, debug!("Found valid token for {} in file", owner);
Err(e) => { self.user_tokens.insert(owner, read_token);
self.user_tokens.remove(&owner); Some(&read_token)
None } else {
} debug!("Token in file for {} is expired.", owner);
},
Err(e) => {
self.user_tokens.remove(&owner);
None None
} }
}; },
self.restore_privileges(); Err(e) => None
new_token },
} else { Err(e) => None
Some(t) };
} self.restore_privileges();
}, new_token
None => None } else {
debug!("Found valid token for {} in memory", owner);
token
} }
} }
pub fn save_user_token(&self, owner: String, token: UserToken) { pub fn save_user_token(&self, owner: String, token: UserToken) -> Result<(), io::Error> {
self.user_tokens.insert(owner, token); self.user_tokens.insert(owner, token);
debug!("Saved token for {} in memory", owner);
// Try to write user's token cache file // Try to write user's token cache file
self.drop_privileges(owner).ok(); let res = match self.drop_privileges(owner) {
match self.place_user_cache_file(owner, USER_TOKEN_FILENAME) { Ok(_) => match self.place_user_cache_file(owner, USER_TOKEN_FILENAME) {
Ok(path) => save_json(path, token), Ok(path) => {
Err(e) => Err(e) debug!("Storing token for {} in cache file", owner);
save_json(path, token)
},
Err(e) => Err(e)
},
Err(e) => Err(io::Error::new(io::ErrorKind::PermissionDenied, e))
}; };
self.restore_privileges(); self.restore_privileges();
return res;
} }
pub fn delete_user_token(&self, owner: String) { pub fn delete_user_token(&self, owner: String) {
self.user_tokens.remove(&owner); self.user_tokens.remove(&owner);
debug!("Token for {} removed from memory", owner);
// Try to remove user's token cache file // Try to remove user's token cache file
self.drop_privileges(owner).ok(); self.drop_privileges(owner).ok();
match self.place_user_cache_file(owner, USER_TOKEN_FILENAME) { match self.place_user_cache_file(owner, USER_TOKEN_FILENAME) {
Ok(path) => fs::remove_file(path), Ok(path) => {
debug!("Deleting cache file for {}", owner);
fs::remove_file(path)
},
Err(e) => Err(e) Err(e) => Err(e)
}; };
self.restore_privileges(); self.restore_privileges();
...@@ -197,6 +227,7 @@ impl Cache { ...@@ -197,6 +227,7 @@ impl Cache {
for (owner, token) in self.user_tokens { for (owner, token) in self.user_tokens {
if token.is_expired() { if token.is_expired() {
self.delete_user_token(owner); self.delete_user_token(owner);
debug!("Deleted expired token for {}", owner);
} }
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment