]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
Add nss getpwent to the himmelblau daemon
authorDavid Mulder <dmulder@samba.org>
Tue, 30 Jul 2024 17:18:59 +0000 (11:18 -0600)
committerDavid Mulder <dmulder@samba.org>
Wed, 23 Oct 2024 14:21:33 +0000 (14:21 +0000)
Signed-off-by: David Mulder <dmulder@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
himmelblaud/src/himmelblaud.rs
himmelblaud/src/himmelblaud/himmelblaud_getpwent.rs [new file with mode: 0644]
himmelblaud/src/main.rs
himmelblaud/src/utils.rs [new file with mode: 0644]

index 96d5cc376283d1dd8467eeea60e19ea7bdc3e03e..169f3b1f767c9ac2333e811af55e4f49a8f77694 100644 (file)
@@ -207,6 +207,7 @@ pub(crate) async fn handle_client(
                     }
                 }
             }
+            Request::NssAccounts => resolver.getpwent().await?,
             _ => todo!(),
         };
         reqs.send(resp).await?;
@@ -218,4 +219,5 @@ pub(crate) async fn handle_client(
     Ok(())
 }
 
+mod himmelblaud_getpwent;
 mod himmelblaud_pam_auth;
diff --git a/himmelblaud/src/himmelblaud/himmelblaud_getpwent.rs b/himmelblaud/src/himmelblaud/himmelblaud_getpwent.rs
new file mode 100644 (file)
index 0000000..b618c15
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Himmelblau daemon implementation for nss getpwent
+
+   Copyright (C) David Mulder 2024
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+use crate::himmelblaud::Resolver;
+use crate::utils::split_username;
+use dbg::DBG_ERR;
+use ntstatus_gen::*;
+use sock::{Passwd, Response};
+
+impl Resolver {
+    pub(crate) async fn getpwent(&mut self) -> Result<Response, Box<NTSTATUS>> {
+        let user_entries = self.user_cache.fetch_all()?;
+        let template_homedir = self
+            .lp
+            .template_homedir()
+            .map_err(|e| {
+                DBG_ERR!("{:?}", e);
+                Box::new(NT_STATUS_NOT_A_DIRECTORY)
+            })?
+            .ok_or_else(|| {
+                DBG_ERR!("Failed to discover template homedir. Is it set?");
+                Box::new(NT_STATUS_NOT_A_DIRECTORY)
+            })?;
+        let shell = self
+            .lp
+            .template_shell()
+            .map_err(|e| {
+                DBG_ERR!("{:?}", e);
+                Box::new(NT_STATUS_NOT_A_DIRECTORY)
+            })?
+            .ok_or_else(|| {
+                DBG_ERR!("Failed to discover template shell. Is it set?");
+                Box::new(NT_STATUS_NOT_A_DIRECTORY)
+            })?;
+        let mut res = Vec::new();
+        for entry in user_entries {
+            let uid = self
+                .idmap
+                .gen_to_unix(&self.tenant_id, &entry.upn.to_lowercase())
+                .map_err(|e| {
+                    DBG_ERR!("{:?}", e);
+                    Box::new(NT_STATUS_INVALID_TOKEN)
+                })?;
+            let upn = entry.upn.clone();
+            let (cn, domain) = match split_username(&upn) {
+                Ok(res) => res,
+                Err(e) => {
+                    DBG_ERR!(
+                        "Failed to parse user upn '{}': {:?}",
+                        &entry.upn,
+                        e
+                    );
+                    return Err(Box::new(
+                        NT_STATUS_INVALID_USER_PRINCIPAL_NAME,
+                    ));
+                }
+            };
+            let homedir = template_homedir
+                .clone()
+                .replace("%D", &domain)
+                .replace("%U", &cn);
+            let passwd = Passwd {
+                name: entry.upn.clone(),
+                passwd: "x".to_string(),
+                uid,
+                gid: uid,
+                gecos: entry.name,
+                dir: homedir,
+                shell: shell.clone(),
+            };
+            res.push(passwd);
+        }
+        Ok(Response::NssAccounts(res))
+    }
+}
index 74997fc019432496d12be0d22f5c24fd1bd56e75..161191cd14924e6434c9d2a73b7858d6189e92c2 100644 (file)
@@ -39,6 +39,7 @@ use constants::DEFAULT_ODC_PROVIDER;
 mod cache;
 mod himmelblaud;
 use cache::{GroupCache, PrivateCache, UserCache};
+mod utils;
 
 #[tokio::main(flavor = "current_thread")]
 async fn main() -> ExitCode {
diff --git a/himmelblaud/src/utils.rs b/himmelblaud/src/utils.rs
new file mode 100644 (file)
index 0000000..932232e
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Himmelblau daemon common utilities
+
+   Copyright (C) David Mulder 2024
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+use ntstatus_gen::*;
+
+pub fn split_username(
+    username: &str,
+) -> Result<(String, String), Box<NTSTATUS>> {
+    let tup: Vec<&str> = username.split('@').collect();
+    if tup.len() == 2 {
+        return Ok((tup[0].to_string(), tup[1].to_string()));
+    }
+    Err(Box::new(NT_STATUS_INVALID_USER_PRINCIPAL_NAME))
+}