From 6794776a1ac0b28792871ac580b7faf4f57f2672 Mon Sep 17 00:00:00 2001
From: Dominik George <dominik.george@teckids.org>
Date: Sat, 8 May 2021 15:38:37 +0200
Subject: [PATCH] [Cache] Refactor privilege dropping code into methods

---
 src/cache.rs | 52 +++++++++++++++++++++++++++++-----------------------
 1 file changed, 29 insertions(+), 23 deletions(-)

diff --git a/src/cache.rs b/src/cache.rs
index cb707c2..2a23c4f 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) {
-- 
GitLab