diff --git a/unix_integration/common/src/unix_proto.rs b/unix_integration/common/src/unix_proto.rs index 337f83acd..9ff949f8a 100644 --- a/unix_integration/common/src/unix_proto.rs +++ b/unix_integration/common/src/unix_proto.rs @@ -121,6 +121,7 @@ pub enum ClientRequest { NssGroups, NssGroupByGid(u32), NssGroupByName(String), + NssGroupsByMember(String), PamAuthenticateInit { account_id: String, info: PamServiceInfo, @@ -147,6 +148,7 @@ impl ClientRequest { ClientRequest::NssGroups => "NssGroups".to_string(), ClientRequest::NssGroupByGid(id) => format!("NssGroupByGid({id})"), ClientRequest::NssGroupByName(id) => format!("NssGroupByName({id})"), + ClientRequest::NssGroupsByMember(id) => format!("NssGroupsByMember({id})"), ClientRequest::PamAuthenticateInit { account_id, info } => format!( "PamAuthenticateInit{{ account_id={} tty={} pam_secvice{} rhost={} }}", account_id, diff --git a/unix_integration/nss_sparkle_common/src/core.rs b/unix_integration/nss_sparkle_common/src/core.rs index 272f7e895..f409e1566 100644 --- a/unix_integration/nss_sparkle_common/src/core.rs +++ b/unix_integration/nss_sparkle_common/src/core.rs @@ -313,6 +313,45 @@ pub fn get_group_entry_by_name(name: String, req_options: RequestOptions) -> Res } } +pub fn get_group_entries_by_member( + member: String, + req_options: RequestOptions, +) -> Response> { + match req_options.connect_to_daemon() { + Source::Daemon(daemon_client) => { + let req = ClientRequest::NssGroupsByMember(member); + daemon_client + .call_and_wait(req, None) + .map(|r| match r { + ClientResponse::NssGroups(l) => { + l.into_iter().map(group_from_nssgroup).collect() + } + _ => Vec::new(), + }) + .map(Response::Success) + .unwrap_or_else(|_| Response::Success(vec![])) + } + Source::Fallback { users: _, groups } => { + if groups.is_empty() { + return Response::Unavail; + } + + let membergroups = groups + .into_iter() + .filter_map(|etcgroup| { + if etcgroup.members.contains(&member) { + Some(group_from_etcgroup(etcgroup)) + } else { + None + } + }) + .collect(); + + Response::Success(membergroups) + } + } +} + fn passwd_from_etcuser(etc: EtcUser) -> Passwd { Passwd { name: etc.name, diff --git a/unix_integration/nss_sparkle_common/src/hooks.rs b/unix_integration/nss_sparkle_common/src/hooks.rs index 98de274d4..7bca5fd6e 100644 --- a/unix_integration/nss_sparkle_common/src/hooks.rs +++ b/unix_integration/nss_sparkle_common/src/hooks.rs @@ -2,6 +2,7 @@ use crate::core::{self, RequestOptions}; use libnss::group::{Group, GroupHooks}; use libnss::interop::Response; use libnss::passwd::{Passwd, PasswdHooks}; +use libnss::initgroups::{InitgroupsHooks}; use sparkle_unix_common::constants::DEFAULT_CONFIG_PATH; pub struct SparklePasswd; @@ -59,3 +60,16 @@ impl GroupHooks for SparkleGroup { core::get_group_entry_by_name(name, req_opt) } } + +pub struct KanidmInitgroups; +libnss::libnss_initgroups_hooks!(kanidm, KanidmInitgroups); + +impl InitgroupsHooks for KanidmInitgroups { + fn get_entries_by_user(user: String) -> Response> { + let req_opt = RequestOptions::Main { + config_path: DEFAULT_CONFIG_PATH, + }; + + core::get_group_entries_by_member(user, req_opt) + } +} diff --git a/unix_integration/resolver_common/src/cli/resolver.rs b/unix_integration/resolver_common/src/cli/resolver.rs index 7cdf0fbae..5e96361e9 100644 --- a/unix_integration/resolver_common/src/cli/resolver.rs +++ b/unix_integration/resolver_common/src/cli/resolver.rs @@ -252,6 +252,14 @@ async fn handle_client( error!("unable to load group, returning empty."); ClientResponse::NssGroup(None) }), + ClientRequest::NssGroupsByMember(account_id) => cachelayer + .get_nssgroups_member_name(account_id.as_str()) + .await + .map(ClientResponse::NssGroups) + .unwrap_or_else(|_| { + error!("unable to enum groups"); + ClientResponse::NssGroups(Vec::new()) + }), ClientRequest::PamAuthenticateInit { account_id, info } => { #[allow(clippy::disallowed_methods)] // Allowed as this is the time check for the remainder of the function and check. diff --git a/unix_integration/resolver_common/src/resolver.rs b/unix_integration/resolver_common/src/resolver.rs index 4a6c542a3..ae929cd1f 100644 --- a/unix_integration/resolver_common/src/resolver.rs +++ b/unix_integration/resolver_common/src/resolver.rs @@ -908,6 +908,17 @@ impl Resolver { Ok(r) } + pub async fn get_nssgroups_member_name(&self, account_id: &str) -> Result, ()> { + let account_name = account_id.to_string(); + Ok(self + .get_nssgroups() + .await + .unwrap_or_default() + .into_iter() + .filter(|g| g.members.contains(&account_name)) + .collect()) + } + #[instrument(level = "trace", skip_all)] async fn get_nssgroup(&self, grp_id: Id) -> Result, ()> { if let Some(mut nss_group) = self.system_provider.get_nssgroup(&grp_id).await {