]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
Add NSS module for himmelblaud
authorDavid Mulder <dmulder@samba.org>
Thu, 18 Jul 2024 16:27:14 +0000 (10:27 -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/Cargo.toml
himmelblaud/nss/Cargo.toml [new file with mode: 0644]
himmelblaud/nss/src/lib.rs [new file with mode: 0644]
himmelblaud/nss/wscript_build [new file with mode: 0644]
himmelblaud/sock/Cargo.toml
himmelblaud/sock/src/lib.rs
himmelblaud/wscript_build

index 0ba4178a70e1553984f0c7f5bf269e1a191d3d47..f51e21d1137ce7d8d98fdbc3e5d9ff4fce3b7363 100644 (file)
@@ -33,7 +33,7 @@ libc = "0.2.155"
 [workspace]
 members = [
   "chelps", "dbg", "idmap",
-  "ntstatus_gen",
+  "nss", "ntstatus_gen",
   "param", "sock", "tdb",
 ]
 
diff --git a/himmelblaud/nss/Cargo.toml b/himmelblaud/nss/Cargo.toml
new file mode 100644 (file)
index 0000000..ecb0cda
--- /dev/null
@@ -0,0 +1,18 @@
+[package]
+name = "nss_himmelblau"
+edition.workspace = true
+license.workspace = true
+homepage.workspace = true
+version.workspace = true
+
+[lib]
+name = "nss_himmelblau"
+crate-type = [ "cdylib" ]
+path =  "src/lib.rs"
+
+[dependencies]
+libc = "0.2.155"
+libnss = "0.8.0"
+ntstatus_gen.workspace = true
+param = { workspace = true }
+sock = { workspace = true }
diff --git a/himmelblaud/nss/src/lib.rs b/himmelblaud/nss/src/lib.rs
new file mode 100644 (file)
index 0000000..acd423f
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   NSS module for the Himmelblau daemon
+
+   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/>.
+*/
+
+#[macro_use]
+extern crate libnss;
+
+use libnss::group::{Group as NssGroup, GroupHooks};
+use libnss::interop::Response as NssResponse;
+use libnss::passwd::{Passwd as NssPasswd, PasswdHooks};
+use param::LoadParm;
+use sock::{stream_and_timeout, Group, Passwd, Request, Response};
+
+struct HimmelblauPasswd;
+libnss_passwd_hooks!(himmelblau, HimmelblauPasswd);
+
+impl PasswdHooks for HimmelblauPasswd {
+    fn get_all_entries() -> NssResponse<Vec<NssPasswd>> {
+        let lp = match LoadParm::new(None) {
+            Ok(lp) => lp,
+            Err(_) => return NssResponse::Unavail,
+        };
+        let (mut stream, timeout) = match stream_and_timeout(&lp) {
+            Ok((stream, timeout)) => (stream, timeout),
+            Err(_) => return NssResponse::Unavail,
+        };
+
+        let req = Request::NssAccounts;
+        stream
+            .send(&req, timeout)
+            .map(|r| match r {
+                Response::NssAccounts(l) => {
+                    l.into_iter().map(|passwd| passwd.into()).collect()
+                }
+                _ => vec![],
+            })
+            .map(NssResponse::Success)
+            .unwrap_or_else(|_| NssResponse::Success(vec![]))
+    }
+
+    fn get_entry_by_uid(uid: libc::uid_t) -> NssResponse<NssPasswd> {
+        let lp = match LoadParm::new(None) {
+            Ok(lp) => lp,
+            Err(_) => return NssResponse::Unavail,
+        };
+        let (mut stream, timeout) = match stream_and_timeout(&lp) {
+            Ok((stream, timeout)) => (stream, timeout),
+            Err(_) => return NssResponse::Unavail,
+        };
+
+        let req = Request::NssAccountByUid(uid);
+        stream
+            .send(&req, timeout)
+            .map(|r| match r {
+                Response::NssAccount(passwd) => passwd
+                    .map(nsspasswd_from_passwd)
+                    .map(NssResponse::Success)
+                    .unwrap_or_else(|| NssResponse::NotFound),
+                _ => NssResponse::NotFound,
+            })
+            .unwrap_or_else(|_| NssResponse::NotFound)
+    }
+
+    fn get_entry_by_name(name: String) -> NssResponse<NssPasswd> {
+        let lp = match LoadParm::new(None) {
+            Ok(lp) => lp,
+            Err(_) => return NssResponse::Unavail,
+        };
+        let (mut stream, timeout) = match stream_and_timeout(&lp) {
+            Ok((stream, timeout)) => (stream, timeout),
+            Err(_) => return NssResponse::Unavail,
+        };
+
+        let req = Request::NssAccountByName(name);
+        stream
+            .send(&req, timeout)
+            .map(|r| match r {
+                Response::NssAccount(passwd) => passwd
+                    .map(nsspasswd_from_passwd)
+                    .map(NssResponse::Success)
+                    .unwrap_or_else(|| NssResponse::NotFound),
+                _ => NssResponse::NotFound,
+            })
+            .unwrap_or_else(|_| NssResponse::NotFound)
+    }
+}
+
+struct HimmelblauGroup;
+libnss_group_hooks!(himmelblau, HimmelblauGroup);
+
+impl GroupHooks for HimmelblauGroup {
+    fn get_all_entries() -> NssResponse<Vec<NssGroup>> {
+        let lp = match LoadParm::new(None) {
+            Ok(lp) => lp,
+            Err(_) => return NssResponse::Unavail,
+        };
+        let (mut stream, timeout) = match stream_and_timeout(&lp) {
+            Ok((stream, timeout)) => (stream, timeout),
+            Err(_) => return NssResponse::Unavail,
+        };
+
+        let req = Request::NssGroups;
+        stream
+            .send(&req, timeout)
+            .map(|r| match r {
+                Response::NssGroups(l) => {
+                    l.into_iter().map(|group| group.into()).collect()
+                }
+                _ => vec![],
+            })
+            .map(NssResponse::Success)
+            .unwrap_or_else(|_| NssResponse::Success(vec![]))
+    }
+
+    fn get_entry_by_gid(gid: libc::gid_t) -> NssResponse<NssGroup> {
+        let lp = match LoadParm::new(None) {
+            Ok(lp) => lp,
+            Err(_) => return NssResponse::Unavail,
+        };
+        let (mut stream, timeout) = match stream_and_timeout(&lp) {
+            Ok((stream, timeout)) => (stream, timeout),
+            Err(_) => return NssResponse::Unavail,
+        };
+
+        let req = Request::NssGroupByGid(gid);
+        stream
+            .send(&req, timeout)
+            .map(|r| match r {
+                Response::NssGroup(group) => group
+                    .map(nssgroup_from_group)
+                    .map(NssResponse::Success)
+                    .unwrap_or_else(|| NssResponse::NotFound),
+                _ => NssResponse::NotFound,
+            })
+            .unwrap_or_else(|_| NssResponse::NotFound)
+    }
+
+    fn get_entry_by_name(name: String) -> NssResponse<NssGroup> {
+        let lp = match LoadParm::new(None) {
+            Ok(lp) => lp,
+            Err(_) => return NssResponse::Unavail,
+        };
+        let (mut stream, timeout) = match stream_and_timeout(&lp) {
+            Ok((stream, timeout)) => (stream, timeout),
+            Err(_) => return NssResponse::Unavail,
+        };
+
+        let req = Request::NssGroupByName(name);
+        stream
+            .send(&req, timeout)
+            .map(|r| match r {
+                Response::NssGroup(group) => group
+                    .map(nssgroup_from_group)
+                    .map(NssResponse::Success)
+                    .unwrap_or_else(|| NssResponse::NotFound),
+                _ => NssResponse::NotFound,
+            })
+            .unwrap_or_else(|_| NssResponse::NotFound)
+    }
+}
+
+fn nsspasswd_from_passwd(passwd: Passwd) -> NssPasswd {
+    passwd.into()
+}
+
+fn nssgroup_from_group(group: Group) -> NssGroup {
+    group.into()
+}
diff --git a/himmelblaud/nss/wscript_build b/himmelblaud/nss/wscript_build
new file mode 100644 (file)
index 0000000..7ac2c97
--- /dev/null
@@ -0,0 +1,4 @@
+#!/usr/bin/env python
+
+bld.SAMBA_RUST_LIBRARY('libnss_himmelblau.so',
+                       source='src/lib.rs ../sock/src/lib.rs ../ntstatus_gen/src/lib.rs ../param/src/lib.rs ../version/src/lib.rs')
index 675e520f94a71ad1beefc2e5b0f2fde3d53b6abc..f2a788ec633b58b8e5df7bc1ba63ed1cd411ffe6 100644 (file)
@@ -8,5 +8,7 @@ version.workspace = true
 [dependencies]
 libc = "0.2.155"
 libnss = "0.8.0"
+ntstatus_gen.workspace = true
+param.workspace = true
 serde = { version = "1.0.204", features = ["derive"] }
 serde_json = "1.0.120"
index e52ad39ff3793a5a6ab2315a502e7415e387c49e..ea07c5b064ef2d40d933249040fed5eb733e7d55 100644 (file)
 mod proto;
 pub use proto::*;
 
+use ntstatus_gen::*;
+use param::LoadParm;
 use serde_json::{from_slice as json_from_slice, to_vec as json_to_vec};
 use std::error::Error;
 use std::io::{Read, Write};
 use std::os::unix::net::UnixStream;
+use std::path::{Path, PathBuf};
 use std::time::Duration;
 
 pub struct ClientStream {
@@ -55,3 +58,27 @@ impl ClientStream {
         Ok(resp)
     }
 }
+
+pub fn stream_and_timeout(
+    lp: &LoadParm,
+) -> Result<(ClientStream, u64), Box<NTSTATUS>> {
+    // Get the socket path
+    let sock_dir_str = lp
+        .winbindd_socket_directory()
+        .map_err(|_| Box::new(NT_STATUS_NOT_FOUND))?
+        .ok_or(Box::new(NT_STATUS_NOT_FOUND))?;
+    let sock_dir = Path::new(&sock_dir_str);
+    let mut sock_path = PathBuf::from(sock_dir);
+    sock_path.push("hb_pipe");
+    let sock_path = sock_path.to_str().ok_or(Box::new(NT_STATUS_NOT_FOUND))?;
+
+    // Open the socket
+    let timeout: u64 = lp
+        .winbind_request_timeout()
+        .map_err(|_| Box::new(NT_STATUS_NOT_FOUND))?
+        .try_into()
+        .map_err(|_| Box::new(NT_STATUS_NOT_FOUND))?;
+    let stream = ClientStream::new(sock_path)
+        .map_err(|_| Box::new(NT_STATUS_PIPE_NOT_AVAILABLE))?;
+    Ok((stream, timeout))
+}
index f302ab1e6c8df9b7bd6a345177d3cfaede4f3ac4..d269c08b83c6ec635d3e923754a7f2dc1605477d 100644 (file)
@@ -2,3 +2,5 @@
 
 bld.SAMBA_RUST_BINARY('himmelblaud',
                       source='src/main.rs param/src/lib.rs chelps/src/lib.rs dbg/src/lib.rs ntstatus_gen/src/lib.rs sock/src/lib.rs tdb/src/lib.rs version/src/lib.rs')
+
+bld.RECURSE('nss')