| 1 | diff --git a/unix_integration/common/src/unix_proto.rs b/unix_integration/common/src/unix_proto.rs
|
| 2 | index 337f83acd..9ff949f8a 100644
|
| 3 | |
| 4 | |
| 5 | @@ -121,6 +121,7 @@ pub enum ClientRequest {
|
| 6 | NssGroups,
|
| 7 | NssGroupByGid(u32),
|
| 8 | NssGroupByName(String),
|
| 9 | + NssGroupsByMember(String),
|
| 10 | PamAuthenticateInit {
|
| 11 | account_id: String,
|
| 12 | info: PamServiceInfo,
|
| 13 | @@ -147,6 +148,7 @@ impl ClientRequest {
|
| 14 | ClientRequest::NssGroups => "NssGroups".to_string(),
|
| 15 | ClientRequest::NssGroupByGid(id) => format!("NssGroupByGid({id})"),
|
| 16 | ClientRequest::NssGroupByName(id) => format!("NssGroupByName({id})"),
|
| 17 | + ClientRequest::NssGroupsByMember(id) => format!("NssGroupsByMember({id})"),
|
| 18 | ClientRequest::PamAuthenticateInit { account_id, info } => format!(
|
| 19 | "PamAuthenticateInit{{ account_id={} tty={} pam_secvice{} rhost={} }}",
|
| 20 | account_id,
|
| 21 | diff --git a/unix_integration/nss_sparkle_common/src/core.rs b/unix_integration/nss_sparkle_common/src/core.rs
|
| 22 | index 272f7e895..f409e1566 100644
|
| 23 | |
| 24 | |
| 25 | @@ -313,6 +313,45 @@ pub fn get_group_entry_by_name(name: String, req_options: RequestOptions) -> Res
|
| 26 | }
|
| 27 | }
|
| 28 |
|
| 29 | +pub fn get_group_entries_by_member(
|
| 30 | + member: String,
|
| 31 | + req_options: RequestOptions,
|
| 32 | +) -> Response<Vec<Group>> {
|
| 33 | + match req_options.connect_to_daemon() {
|
| 34 | + Source::Daemon(daemon_client) => {
|
| 35 | + let req = ClientRequest::NssGroupsByMember(member);
|
| 36 | + daemon_client
|
| 37 | + .call_and_wait(req, None)
|
| 38 | + .map(|r| match r {
|
| 39 | + ClientResponse::NssGroups(l) => {
|
| 40 | + l.into_iter().map(group_from_nssgroup).collect()
|
| 41 | + }
|
| 42 | + _ => Vec::new(),
|
| 43 | + })
|
| 44 | + .map(Response::Success)
|
| 45 | + .unwrap_or_else(|_| Response::Success(vec![]))
|
| 46 | + }
|
| 47 | + Source::Fallback { users: _, groups } => {
|
| 48 | + if groups.is_empty() {
|
| 49 | + return Response::Unavail;
|
| 50 | + }
|
| 51 | +
|
| 52 | + let membergroups = groups
|
| 53 | + .into_iter()
|
| 54 | + .filter_map(|etcgroup| {
|
| 55 | + if etcgroup.members.contains(&member) {
|
| 56 | + Some(group_from_etcgroup(etcgroup))
|
| 57 | + } else {
|
| 58 | + None
|
| 59 | + }
|
| 60 | + })
|
| 61 | + .collect();
|
| 62 | +
|
| 63 | + Response::Success(membergroups)
|
| 64 | + }
|
| 65 | + }
|
| 66 | +}
|
| 67 | +
|
| 68 | fn passwd_from_etcuser(etc: EtcUser) -> Passwd {
|
| 69 | Passwd {
|
| 70 | name: etc.name,
|
| 71 | diff --git a/unix_integration/nss_sparkle_common/src/hooks.rs b/unix_integration/nss_sparkle_common/src/hooks.rs
|
| 72 | index 98de274d4..7bca5fd6e 100644
|
| 73 | |
| 74 | |
| 75 | @@ -2,6 +2,7 @@ use crate::core::{self, RequestOptions};
|
| 76 | use libnss::group::{Group, GroupHooks};
|
| 77 | use libnss::interop::Response;
|
| 78 | use libnss::passwd::{Passwd, PasswdHooks};
|
| 79 | +use libnss::initgroups::{InitgroupsHooks};
|
| 80 | use sparkle_unix_common::constants::DEFAULT_CONFIG_PATH;
|
| 81 |
|
| 82 | pub struct SparklePasswd;
|
| 83 | @@ -59,3 +60,16 @@ impl GroupHooks for SparkleGroup {
|
| 84 | core::get_group_entry_by_name(name, req_opt)
|
| 85 | }
|
| 86 | }
|
| 87 | +
|
| 88 | +pub struct KanidmInitgroups;
|
| 89 | +libnss::libnss_initgroups_hooks!(kanidm, KanidmInitgroups);
|
| 90 | +
|
| 91 | +impl InitgroupsHooks for KanidmInitgroups {
|
| 92 | + fn get_entries_by_user(user: String) -> Response<Vec<Group>> {
|
| 93 | + let req_opt = RequestOptions::Main {
|
| 94 | + config_path: DEFAULT_CONFIG_PATH,
|
| 95 | + };
|
| 96 | +
|
| 97 | + core::get_group_entries_by_member(user, req_opt)
|
| 98 | + }
|
| 99 | +}
|
| 100 | diff --git a/unix_integration/resolver_common/src/cli/resolver.rs b/unix_integration/resolver_common/src/cli/resolver.rs
|
| 101 | index 7cdf0fbae..5e96361e9 100644
|
| 102 | |
| 103 | |
| 104 | @@ -252,6 +252,14 @@ async fn handle_client(
|
| 105 | error!("unable to load group, returning empty.");
|
| 106 | ClientResponse::NssGroup(None)
|
| 107 | }),
|
| 108 | + ClientRequest::NssGroupsByMember(account_id) => cachelayer
|
| 109 | + .get_nssgroups_member_name(account_id.as_str())
|
| 110 | + .await
|
| 111 | + .map(ClientResponse::NssGroups)
|
| 112 | + .unwrap_or_else(|_| {
|
| 113 | + error!("unable to enum groups");
|
| 114 | + ClientResponse::NssGroups(Vec::new())
|
| 115 | + }),
|
| 116 | ClientRequest::PamAuthenticateInit { account_id, info } => {
|
| 117 | #[allow(clippy::disallowed_methods)]
|
| 118 | // Allowed as this is the time check for the remainder of the function and check.
|
| 119 | diff --git a/unix_integration/resolver_common/src/resolver.rs b/unix_integration/resolver_common/src/resolver.rs
|
| 120 | index 4a6c542a3..ae929cd1f 100644
|
| 121 | |
| 122 | |
| 123 | @@ -908,6 +908,17 @@ impl Resolver {
|
| 124 | Ok(r)
|
| 125 | }
|
| 126 |
|
| 127 | + pub async fn get_nssgroups_member_name(&self, account_id: &str) -> Result<Vec<NssGroup>, ()> {
|
| 128 | + let account_name = account_id.to_string();
|
| 129 | + Ok(self
|
| 130 | + .get_nssgroups()
|
| 131 | + .await
|
| 132 | + .unwrap_or_default()
|
| 133 | + .into_iter()
|
| 134 | + .filter(|g| g.members.contains(&account_name))
|
| 135 | + .collect())
|
| 136 | + }
|
| 137 | +
|
| 138 | #[instrument(level = "trace", skip_all)]
|
| 139 | async fn get_nssgroup(&self, grp_id: Id) -> Result<Option<NssGroup>, ()> {
|
| 140 | if let Some(mut nss_group) = self.system_provider.get_nssgroup(&grp_id).await {
|
| 141 |
|