From: David Mulder Date: Thu, 18 Jul 2024 16:27:14 +0000 (-0600) Subject: Add NSS module for himmelblaud X-Git-Tag: tdb-1.4.13~920 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1e2abfa313bbe0b779a6b2ef633d38dbe6b5522e;p=thirdparty%2Fsamba.git Add NSS module for himmelblaud Signed-off-by: David Mulder Reviewed-by: Alexander Bokovoy --- diff --git a/himmelblaud/Cargo.toml b/himmelblaud/Cargo.toml index 0ba4178a70e..f51e21d1137 100644 --- a/himmelblaud/Cargo.toml +++ b/himmelblaud/Cargo.toml @@ -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 index 00000000000..ecb0cda557f --- /dev/null +++ b/himmelblaud/nss/Cargo.toml @@ -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 index 00000000000..acd423fa83e --- /dev/null +++ b/himmelblaud/nss/src/lib.rs @@ -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 . +*/ + +#[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> { + 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 { + 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 { + 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> { + 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 { + 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 { + 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 index 00000000000..7ac2c979b74 --- /dev/null +++ b/himmelblaud/nss/wscript_build @@ -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') diff --git a/himmelblaud/sock/Cargo.toml b/himmelblaud/sock/Cargo.toml index 675e520f94a..f2a788ec633 100644 --- a/himmelblaud/sock/Cargo.toml +++ b/himmelblaud/sock/Cargo.toml @@ -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" diff --git a/himmelblaud/sock/src/lib.rs b/himmelblaud/sock/src/lib.rs index e52ad39ff37..ea07c5b064e 100644 --- a/himmelblaud/sock/src/lib.rs +++ b/himmelblaud/sock/src/lib.rs @@ -22,10 +22,13 @@ 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> { + // 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)) +} diff --git a/himmelblaud/wscript_build b/himmelblaud/wscript_build index f302ab1e6c8..d269c08b83c 100644 --- a/himmelblaud/wscript_build +++ b/himmelblaud/wscript_build @@ -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')