summaryrefslogtreecommitdiffstats
path: root/source/nsswitch
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2001-12-04 12:10:05 +0000
committerAndrew Tridgell <tridge@samba.org>2001-12-04 12:10:05 +0000
commit43edeaca9f3a42699131939ed0d917111f57b678 (patch)
tree97c23dfe1fac5d2e121e9e1e69d908c13ca90640 /source/nsswitch
parentbc83d55f4400cdcdfed44622954f11580b6d2f87 (diff)
downloadsamba-43edeaca9f3a42699131939ed0d917111f57b678.tar.gz
samba-43edeaca9f3a42699131939ed0d917111f57b678.tar.xz
samba-43edeaca9f3a42699131939ed0d917111f57b678.zip
added lookup_groups() to the ads backend
winbindd/ADS can now do initgroups()
Diffstat (limited to 'source/nsswitch')
-rw-r--r--source/nsswitch/winbindd.h5
-rw-r--r--source/nsswitch/winbindd_ads.c66
-rw-r--r--source/nsswitch/winbindd_group.c2
-rw-r--r--source/nsswitch/winbindd_rpc.c4
4 files changed, 69 insertions, 8 deletions
diff --git a/source/nsswitch/winbindd.h b/source/nsswitch/winbindd.h
index e290796e67b..a00bf54cad7 100644
--- a/source/nsswitch/winbindd.h
+++ b/source/nsswitch/winbindd.h
@@ -117,10 +117,11 @@ struct winbindd_methods {
const char *user_name, uint32 user_rid,
WINBIND_USERINFO *user_info);
+ /* the backend can also choose for this function */
NTSTATUS (*lookup_usergroups)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- uint32 user_rid, uint32 *num_groups,
- uint32 **user_gids);
+ const char *user_name, uint32 user_rid,
+ uint32 *num_groups, uint32 **user_gids);
};
/* Structures to hold per domain information */
diff --git a/source/nsswitch/winbindd_ads.c b/source/nsswitch/winbindd_ads.c
index a1c34bee66b..1c498d394d1 100644
--- a/source/nsswitch/winbindd_ads.c
+++ b/source/nsswitch/winbindd_ads.c
@@ -344,10 +344,70 @@ error:
/* Lookup groups a user is a member of. */
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- uint32 user_rid, uint32 *num_groups,
- uint32 **user_gids)
+ const char *user_name, uint32 user_rid,
+ uint32 *num_groups, uint32 **user_gids)
{
- return NT_STATUS_NOT_IMPLEMENTED;
+ ADS_STRUCT *ads;
+ const char *attrs[] = {"distinguishedName", NULL};
+ const char *attrs2[] = {"tokenGroups", "primaryGroupID", NULL};
+ int rc, count;
+ void *msg;
+ char *exp;
+ char *user_dn;
+ DOM_SID *sids;
+ int i;
+ uint32 primary_group;
+
+ DEBUG(3,("ads: lookup_usergroups\n"));
+
+ (*num_groups) = 0;
+
+ ads = ads_init(NULL, NULL, NULL);
+ if (!ads) {
+ DEBUG(1,("ads_init failed\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ rc = ads_connect(ads);
+ if (rc) {
+ DEBUG(1,("lookup_usergroups ads_connect: %s\n", ads_errstr(rc)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ asprintf(&exp, "(sAMAccountName=%s)", user_name);
+ rc = ads_search(ads, &msg, exp, attrs);
+ free(exp);
+ if (rc) {
+ DEBUG(1,("lookup_usergroups(%s) ads_search: %s\n", user_name, ads_errstr(rc)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ user_dn = ads_pull_string(ads, mem_ctx, msg, "distinguishedName");
+
+ rc = ads_search_dn(ads, &msg, user_dn, attrs2);
+ if (rc) {
+ DEBUG(1,("lookup_usergroups(%s) ads_search tokenGroups: %s\n", user_name, ads_errstr(rc)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group)) {
+ DEBUG(1,("No primary group for %s !?\n", user_name));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids) + 1;
+ (*user_gids) = (uint32 *)talloc(mem_ctx, sizeof(uint32) * count);
+ (*user_gids)[(*num_groups)++] = primary_group;
+
+ for (i=1;i<count;i++) {
+ uint32 rid;
+ if (!sid_peek_rid(&sids[i-1], &rid)) continue;
+ (*user_gids)[*num_groups] = rid;
+ (*num_groups)++;
+ }
+
+ ads_destroy(&ads);
+ return NT_STATUS_OK;
}
/* the ADS backend methods are exposed via this structure */
diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c
index 9d29fee67c6..d800456d9dd 100644
--- a/source/nsswitch/winbindd_group.c
+++ b/source/nsswitch/winbindd_group.c
@@ -968,7 +968,7 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
sid_split_rid(&user_sid, &user_rid);
- status = domain->methods->lookup_usergroups(domain, mem_ctx, user_rid, &num_groups, &user_gids);
+ status = domain->methods->lookup_usergroups(domain, mem_ctx, name_user, user_rid, &num_groups, &user_gids);
if (!NT_STATUS_IS_OK(status)) goto done;
/* Copy data back to client */
diff --git a/source/nsswitch/winbindd_rpc.c b/source/nsswitch/winbindd_rpc.c
index f7d8253fd05..d7831568152 100644
--- a/source/nsswitch/winbindd_rpc.c
+++ b/source/nsswitch/winbindd_rpc.c
@@ -243,8 +243,8 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
/* Lookup groups a user is a member of. I wish Unix had a call like this! */
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- uint32 user_rid, uint32 *num_groups,
- uint32 **user_gids)
+ const char *user_name, uint32 user_rid,
+ uint32 *num_groups, uint32 **user_gids)
{
CLI_POLICY_HND *hnd;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;