diff options
-rw-r--r-- | source3/nsswitch/winbindd.h | 22 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_ads.c | 147 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_group.c | 10 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_proto.h | 10 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_rpc.c | 124 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_user.c | 6 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_util.c | 101 |
7 files changed, 250 insertions, 170 deletions
diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h index a00bf54cad..462a078fae 100644 --- a/source3/nsswitch/winbindd.h +++ b/source3/nsswitch/winbindd.h @@ -89,39 +89,51 @@ typedef struct { I'm just starting small */ struct winbindd_methods { + /* get a list of users, returning a WINBIND_USERINFO for each one */ NTSTATUS (*query_user_list)(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, uint32 *start_ndx, uint32 *num_entries, WINBIND_USERINFO **info); + /* get a list of groups */ NTSTATUS (*enum_dom_groups)(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, uint32 *start_ndx, uint32 *num_entries, struct acct_info **info); + /* convert one user or group name to a sid */ NTSTATUS (*name_to_sid)(struct winbindd_domain *domain, const char *name, DOM_SID *sid, enum SID_NAME_USE *type); + /* convert a sid to a user or group name */ NTSTATUS (*sid_to_name)(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, DOM_SID *sid, char **name, enum SID_NAME_USE *type); - /* query_user is a bit strange. The backend has a choice of - doing the lookup by user name or rid */ + /* lookup user info for a given rid */ NTSTATUS (*query_user)(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - const char *user_name, uint32 user_rid, + uint32 user_rid, WINBIND_USERINFO *user_info); - /* the backend can also choose for this function */ + /* lookup all groups that a user is a member of. The backend + can also choose to lookup by username or rid for this + function */ NTSTATUS (*lookup_usergroups)(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - const char *user_name, uint32 user_rid, + uint32 user_rid, uint32 *num_groups, uint32 **user_gids); + + /* find all members of the group with the specified group_rid */ + NTSTATUS (*lookup_groupmem)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 group_rid, uint32 *num_names, + uint32 **rid_mem, char ***names, + uint32 **name_types); }; /* Structures to hold per domain information */ diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index 3ae2f85b46..e90e590e8c 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -24,6 +24,27 @@ #ifdef HAVE_ADS +/* useful utility */ +static void sid_from_rid(struct winbindd_domain *domain, uint32 rid, DOM_SID *sid) +{ + sid_copy(sid, &domain->sid); + sid_append_rid(sid, rid); +} + +/* turn a sAMAccountType into a SID_NAME_USE */ +static enum SID_NAME_USE ads_atype_map(uint32 atype) +{ + switch (atype & 0xF0000000) { + case ATYPE_GROUP: + return SID_NAME_DOM_GRP; + case ATYPE_USER: + return SID_NAME_USER; + default: + DEBUG(1,("hmm, need to map account type 0x%x\n", atype)); + } + return SID_NAME_UNKNOWN; +} + /* Query display info for a realm. This is the basic user list fn */ static NTSTATUS query_user_list(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -254,28 +275,70 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, return NT_STATUS_UNSUCCESSFUL; } - switch (t & 0xF0000000) { - case ATYPE_GROUP: - *type = SID_NAME_DOM_GRP; - break; - case ATYPE_USER: - *type = SID_NAME_USER; - break; - default: - DEBUG(1,("hmm, need to map account type 0x%x\n", t)); - *type = SID_NAME_UNKNOWN; - break; - } + *type = ads_atype_map(t); ads_destroy(&ads); + + return NT_STATUS_OK; +} + +/* convert a sid to a user or group name */ +static NTSTATUS sid_to_name(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + DOM_SID *sid, + char **name, + enum SID_NAME_USE *type) +{ + ADS_STRUCT *ads; + const char *attrs[] = {"sAMAccountName", "sAMAccountType", NULL}; + int rc; + void *msg; + char *exp; + char *sidstr; + uint32 atype; + char *s; + + DEBUG(3,("ads: sid_to_name\n")); + + 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,("sid_to_name ads_connect: %s\n", ads_errstr(rc))); + return NT_STATUS_UNSUCCESSFUL; + } + + sidstr = ads_sid_binstring(sid); + asprintf(&exp, "(objectSid=%s)", sidstr); + rc = ads_search(ads, &msg, exp, attrs); + free(exp); + free(sidstr); + if (rc) { + DEBUG(1,("sid_to_name ads_search: %s\n", ads_errstr(rc))); + return NT_STATUS_UNSUCCESSFUL; + } + + if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype)) { + return NT_STATUS_UNSUCCESSFUL; + } + + s = ads_pull_string(ads, mem_ctx, msg, "sAMAccountName"); + *name = talloc_asprintf(mem_ctx, "%s%s%s", domain->name, lp_winbind_separator(), s); + *type = ads_atype_map(atype); + return NT_STATUS_OK; } -/* Lookup user information from a rid or username. */ + +/* Lookup user information from a rid */ static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - const char *user_name, uint32 user_rid, + uint32 user_rid, WINBIND_USERINFO *info) { ADS_STRUCT *ads; @@ -285,14 +348,12 @@ static NTSTATUS query_user(struct winbindd_domain *domain, void *msg; char *exp; DOM_SID sid; - fstring dom2, name2; + char *sidstr; - /* sigh. Need to fix interface to give us a raw name */ - if (!parse_domain_user(user_name, dom2, name2)) - return NT_STATUS_UNSUCCESSFUL; - DEBUG(3,("ads: query_user\n")); + sid_from_rid(domain, user_rid, &sid); + ads = ads_init(NULL, NULL, NULL); if (!ads) { DEBUG(1,("ads_init failed\n")); @@ -305,33 +366,35 @@ static NTSTATUS query_user(struct winbindd_domain *domain, return NT_STATUS_UNSUCCESSFUL; } - asprintf(&exp, "(sAMAccountName=%s)", name2); + sidstr = ads_sid_binstring(&sid); + asprintf(&exp, "(objectSid=%s)", sidstr); rc = ads_search(ads, &msg, exp, attrs); free(exp); + free(sidstr); if (rc) { - DEBUG(1,("query_user(%s) ads_search: %s\n", user_name, ads_errstr(rc))); + DEBUG(1,("query_user(rid=%d) ads_search: %s\n", user_rid, ads_errstr(rc))); return NT_STATUS_UNSUCCESSFUL; } count = ads_count_replies(ads, msg); if (count != 1) { - DEBUG(1,("query_user(%s): Not found\n", user_name)); + DEBUG(1,("query_user(rid=%d): Not found\n", user_rid)); return NT_STATUS_UNSUCCESSFUL; } info->acct_name = ads_pull_string(ads, mem_ctx, msg, "sAMAccountName"); info->full_name = ads_pull_string(ads, mem_ctx, msg, "name"); if (!ads_pull_sid(ads, msg, "objectSid", &sid)) { - DEBUG(1,("No sid for %s !?\n", user_name)); + DEBUG(1,("No sid for %d !?\n", user_rid)); goto error; } if (!ads_pull_uint32(ads, msg, "primaryGroupID", &info->group_rid)) { - DEBUG(1,("No primary group for %s !?\n", user_name)); + DEBUG(1,("No primary group for %d !?\n", user_rid)); goto error; } if (!sid_peek_rid(&sid, &info->user_rid)) { - DEBUG(1,("No rid for %s !?\n", user_name)); + DEBUG(1,("No rid for %d !?\n", user_rid)); goto error; } @@ -346,7 +409,7 @@ error: /* Lookup groups a user is a member of. */ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - const char *user_name, uint32 user_rid, + uint32 user_rid, uint32 *num_groups, uint32 **user_gids) { ADS_STRUCT *ads; @@ -359,11 +422,15 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, DOM_SID *sids; int i; uint32 primary_group; + DOM_SID sid; + char *sidstr; DEBUG(3,("ads: lookup_usergroups\n")); (*num_groups) = 0; + sid_from_rid(domain, user_rid, &sid); + ads = ads_init(NULL, NULL, NULL); if (!ads) { DEBUG(1,("ads_init failed\n")); @@ -376,11 +443,13 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, return NT_STATUS_UNSUCCESSFUL; } - asprintf(&exp, "(sAMAccountName=%s)", user_name); + sidstr = ads_sid_binstring(&sid); + asprintf(&exp, "(objectSid=%s)", sidstr); rc = ads_search(ads, &msg, exp, attrs); free(exp); + free(sidstr); if (rc) { - DEBUG(1,("lookup_usergroups(%s) ads_search: %s\n", user_name, ads_errstr(rc))); + DEBUG(1,("lookup_usergroups(rid=%d) ads_search: %s\n", user_rid, ads_errstr(rc))); return NT_STATUS_UNSUCCESSFUL; } @@ -388,12 +457,12 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, 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))); + DEBUG(1,("lookup_usergroups(rid=%d) ads_search tokenGroups: %s\n", user_rid, 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)); + DEBUG(1,("No primary group for rid=%d !?\n", user_rid)); return NT_STATUS_UNSUCCESSFUL; } @@ -412,17 +481,25 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, return NT_STATUS_OK; } + +static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 group_rid, uint32 *num_names, + uint32 **rid_mem, char ***names, + uint32 **name_types) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + /* the ADS backend methods are exposed via this structure */ struct winbindd_methods ads_methods = { query_user_list, enum_dom_groups, name_to_sid, - /* I can't see a good way to do a sid to name mapping with ldap, - and MS servers always allow RPC for this (even in native mode) so - just use RPC for sid_to_name. Maybe that's why they allow it? */ - winbindd_rpc_sid_to_name, + sid_to_name, query_user, - lookup_usergroups + lookup_usergroups, + lookup_groupmem }; #endif diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index b03e506494..440f009366 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/nsswitch/winbindd_group.c @@ -60,6 +60,7 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain, char **names = NULL, *buf; BOOL result = False; TALLOC_CTX *mem_ctx; + NTSTATUS status; if (!(mem_ctx = talloc_init())) return False; @@ -78,10 +79,9 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain, } /* Lookup group members */ - - if (!winbindd_lookup_groupmem(domain, mem_ctx, group_rid, &num_names, - &rid_mem, &names, &name_types)) { - + status = domain->methods->lookup_groupmem(domain, mem_ctx, group_rid, &num_names, + &rid_mem, &names, &name_types); + if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("fill_grent_mem(): could not lookup membership " "for group rid %d in domain %s\n", group_rid, domain->name)); @@ -958,7 +958,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, name_user, user_rid, &num_groups, &user_gids); + status = domain->methods->lookup_usergroups(domain, mem_ctx, user_rid, &num_groups, &user_gids); if (!NT_STATUS_IS_OK(status)) goto done; /* Copy data back to client */ diff --git a/source3/nsswitch/winbindd_proto.h b/source3/nsswitch/winbindd_proto.h index 4659ad69dd..893064b801 100644 --- a/source3/nsswitch/winbindd_proto.h +++ b/source3/nsswitch/winbindd_proto.h @@ -109,11 +109,6 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state); /* The following definitions come from nsswitch/winbindd_rpc.c */ -NTSTATUS winbindd_rpc_sid_to_name(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *sid, - char **name, - enum SID_NAME_USE *type); /* The following definitions come from nsswitch/winbindd_sid.c */ @@ -145,11 +140,6 @@ BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain, BOOL winbindd_lookup_name_by_sid(DOM_SID *sid, fstring name, enum SID_NAME_USE *type); -BOOL winbindd_lookup_groupmem(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 group_rid, uint32 *num_names, - uint32 **rid_mem, char ***names, - uint32 **name_types); void free_getent_state(struct getent_state *state); BOOL winbindd_param_init(void); BOOL check_domain_env(char *domain_env, char *domain); diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c index d783156815..c04bcdc954 100644 --- a/source3/nsswitch/winbindd_rpc.c +++ b/source3/nsswitch/winbindd_rpc.c @@ -156,11 +156,11 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, /* convert a domain SID to a user or group name */ -NTSTATUS winbindd_rpc_sid_to_name(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *sid, - char **name, - enum SID_NAME_USE *type) +static NTSTATUS sid_to_name(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + DOM_SID *sid, + char **name, + enum SID_NAME_USE *type) { CLI_POLICY_HND *hnd; char **names; @@ -187,7 +187,7 @@ NTSTATUS winbindd_rpc_sid_to_name(struct winbindd_domain *domain, /* Lookup user information from a rid or username. */ static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - const char *user_name, uint32 user_rid, + uint32 user_rid, WINBIND_USERINFO *user_info) { CLI_POLICY_HND *hnd; @@ -224,8 +224,9 @@ static NTSTATUS query_user(struct winbindd_domain *domain, cli_samr_close(hnd->cli, mem_ctx, &user_pol); - user_info->acct_name = talloc_strdup(mem_ctx, user_name); user_info->group_rid = ctr->info.id21->group_rid; + user_info->acct_name = unistr2_tdup(mem_ctx, + &ctr->info.id21->uni_user_name); user_info->full_name = unistr2_tdup(mem_ctx, &ctr->info.id21->uni_full_name); @@ -243,7 +244,7 @@ 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, - const char *user_name, uint32 user_rid, + uint32 user_rid, uint32 *num_groups, uint32 **user_gids) { CLI_POLICY_HND *hnd; @@ -300,13 +301,116 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, } +/* Lookup group membership given a rid. */ +static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 group_rid, uint32 *num_names, + uint32 **rid_mem, char ***names, + uint32 **name_types) +{ + CLI_POLICY_HND *hnd; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + uint32 i, total_names = 0; + POLICY_HND dom_pol, group_pol; + uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; + BOOL got_dom_pol = False, got_group_pol = False; + + /* Get sam handle */ + + if (!(hnd = cm_get_sam_handle(domain->name))) + goto done; + + /* Get domain handle */ + + result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, + des_access, &domain->sid, &dom_pol); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + got_dom_pol = True; + + /* Get group handle */ + + result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol, + des_access, group_rid, &group_pol); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + got_group_pol = True; + + /* Step #1: Get a list of user rids that are the members of the + group. */ + + result = cli_samr_query_groupmem(hnd->cli, mem_ctx, + &group_pol, num_names, rid_mem, + name_types); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + /* Step #2: Convert list of rids into list of usernames. Do this + in bunches of ~1000 to avoid crashing NT4. It looks like there + is a buffer overflow or something like that lurking around + somewhere. */ + +#define MAX_LOOKUP_RIDS 900 + + *names = talloc(mem_ctx, *num_names * sizeof(char *)); + *name_types = talloc(mem_ctx, *num_names * sizeof(uint32)); + + for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) { + int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS); + uint32 tmp_num_names = 0; + char **tmp_names = NULL; + uint32 *tmp_types = NULL; + + /* Lookup a chunk of rids */ + + result = cli_samr_lookup_rids(hnd->cli, mem_ctx, + &dom_pol, 1000, /* flags */ + num_lookup_rids, + &(*rid_mem)[i], + &tmp_num_names, + &tmp_names, &tmp_types); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + /* Copy result into array. The talloc system will take + care of freeing the temporary arrays later on. */ + + memcpy(&(*names)[i], tmp_names, sizeof(char *) * + tmp_num_names); + + memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) * + tmp_num_names); + + total_names += tmp_num_names; + } + + *num_names = total_names; + + done: + if (got_group_pol) + cli_samr_close(hnd->cli, mem_ctx, &group_pol); + + if (got_dom_pol) + cli_samr_close(hnd->cli, mem_ctx, &dom_pol); + + return result; +} + + /* the rpc backend methods are exposed via this structure */ struct winbindd_methods msrpc_methods = { query_user_list, enum_dom_groups, name_to_sid, - winbindd_rpc_sid_to_name, + sid_to_name, query_user, - lookup_usergroups + lookup_usergroups, + lookup_groupmem }; diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index 52122a4f29..d9b2b5a0e6 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/nsswitch/winbindd_user.c @@ -163,8 +163,7 @@ enum winbindd_result winbindd_getpwnam_from_user(struct winbindd_cli_state *stat sid_split_rid(&user_sid, &user_rid); - status = domain->methods->query_user(domain, mem_ctx, name_user, user_rid, - &user_info); + status = domain->methods->query_user(domain, mem_ctx, user_rid, &user_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("pwnam_from_user(): error getting user info for " "user '%s'\n", name_user)); @@ -259,8 +258,7 @@ enum winbindd_result winbindd_getpwnam_from_uid(struct winbindd_cli_state *state return WINBINDD_ERROR; } - status = domain->methods->query_user(domain, mem_ctx, user_name, user_rid, - &user_info); + status = domain->methods->query_user(domain, mem_ctx, user_rid, &user_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("pwnam_from_uid(): error getting user info for " "user '%s'\n", user_name)); diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index d49e0b5bc2..2ac090f8e5 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -478,107 +478,6 @@ BOOL winbindd_lookup_name_by_sid(DOM_SID *sid, return rv; } -/* Lookup group membership given a rid. */ - -BOOL winbindd_lookup_groupmem(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 group_rid, uint32 *num_names, - uint32 **rid_mem, char ***names, - uint32 **name_types) -{ - CLI_POLICY_HND *hnd; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - uint32 i, total_names = 0; - POLICY_HND dom_pol, group_pol; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - BOOL got_dom_pol = False, got_group_pol = False; - - /* Get sam handle */ - - if (!(hnd = cm_get_sam_handle(domain->name))) - goto done; - - /* Get domain handle */ - - result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, - des_access, &domain->sid, &dom_pol); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_dom_pol = True; - - /* Get group handle */ - - result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol, - des_access, group_rid, &group_pol); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_group_pol = True; - - /* Step #1: Get a list of user rids that are the members of the - group. */ - - result = cli_samr_query_groupmem(hnd->cli, mem_ctx, - &group_pol, num_names, rid_mem, - name_types); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - /* Step #2: Convert list of rids into list of usernames. Do this - in bunches of ~1000 to avoid crashing NT4. It looks like there - is a buffer overflow or something like that lurking around - somewhere. */ - -#define MAX_LOOKUP_RIDS 900 - - *names = talloc(mem_ctx, *num_names * sizeof(char *)); - *name_types = talloc(mem_ctx, *num_names * sizeof(uint32)); - - for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) { - int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS); - uint32 tmp_num_names = 0; - char **tmp_names = NULL; - uint32 *tmp_types = NULL; - - /* Lookup a chunk of rids */ - - result = cli_samr_lookup_rids(hnd->cli, mem_ctx, - &dom_pol, 1000, /* flags */ - num_lookup_rids, - &(*rid_mem)[i], - &tmp_num_names, - &tmp_names, &tmp_types); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - /* Copy result into array. The talloc system will take - care of freeing the temporary arrays later on. */ - - memcpy(&(*names)[i], tmp_names, sizeof(char *) * - tmp_num_names); - - memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) * - tmp_num_names); - - total_names += tmp_num_names; - } - - *num_names = total_names; - - done: - if (got_group_pol) - cli_samr_close(hnd->cli, mem_ctx, &group_pol); - - if (got_dom_pol) - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - - return NT_STATUS_IS_OK(result); -} /* Free state information held for {set,get,end}{pw,gr}ent() functions */ |