From 2327a57f0cf42bd0c47b8073d817604305ef1dc0 Mon Sep 17 00:00:00 2001
From: Dominik George <dominik.george@teckids.org>
Date: Mon, 17 May 2021 16:37:07 +0200
Subject: [PATCH] [PAM] Resolve authenticating user using getpwnam outside the
 UserInfo struct

Necessary because in order t oresolve the home directory to store the access token,
the try_resolve method would have to be called, which can not resolve using
getpwnam while the PAM module holds the lock to the structure.
---
 src/cache.rs | 7 +++++++
 src/pam.rs   | 7 ++++++-
 src/unix.rs  | 1 +
 3 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/src/cache.rs b/src/cache.rs
index 2c4018e..9256531 100644
--- a/src/cache.rs
+++ b/src/cache.rs
@@ -182,6 +182,13 @@ impl UserInfo {
         };
     }
 
+    /// Set the full passwd struct from outside
+    pub fn set_passwd(&mut self, passwd: Passwd) {
+        self.passwd = Some(passwd.clone());
+        self.username = Some(passwd.pw_name);
+        self.uid = Some(passwd.pw_uid);
+    }
+
     /// Return the home directory from the passwd slot,
     /// attempting NSS resolution before doing so
     pub fn get_home_directory(&mut self) -> Result<String, io::Error> {
diff --git a/src/pam.rs b/src/pam.rs
index 8bfef0c..d7637ed 100644
--- a/src/pam.rs
+++ b/src/pam.rs
@@ -26,6 +26,8 @@ use crate::logging::setup_log;
 
 use crate::cache::{get_context_user, set_is_getpwnam_safe};
 
+use crate::unix::getpwnam_safe;
+
 use pamsm::{PamServiceModule, Pam, PamFlag, PamError, PamLibExt};
 
 fn pam_sm_prepare(argv: &Vec<String>) -> Config {
@@ -91,7 +93,10 @@ impl PamServiceModule for PamOidc {
                 Ok(t) => {
                     info!("Authenticated {} using Resource Owner Password Grant", username);
                     set_is_getpwnam_safe(false);
-                    get_context_user().set_username(username.to_string());
+                    let passwd = getpwnam_safe(username.to_string());
+                    if passwd.is_ok() {
+                        get_context_user().set_passwd(passwd.unwrap());
+                    }
                     get_context_user().set_access_token(t);
                     set_is_getpwnam_safe(true);
                     return PamError::SUCCESS;
diff --git a/src/unix.rs b/src/unix.rs
index d74e0e7..6452366 100644
--- a/src/unix.rs
+++ b/src/unix.rs
@@ -20,6 +20,7 @@ use std::io;
 use std::mem::uninitialized;
 use std::ptr::null_mut;
 
+#[derive(Clone)]
 pub struct Passwd {
     pub pw_name: String,
     pub pw_passwd: String,
-- 
GitLab