finally worked out how to do ldap lookups by binary blobs, so I can
authorAndrew Tridgell <tridge@samba.org>
Wed, 5 Dec 2001 04:48:51 +0000 (04:48 +0000)
committerAndrew Tridgell <tridge@samba.org>
Wed, 5 Dec 2001 04:48:51 +0000 (04:48 +0000)
now do searches on SID. This allows me to do a true ldap sid_to_name()
function

one one function to go!
(This used to be commit 7d44aa3915bc88fd2b2f8454f190b11677cbb848)

source3/nsswitch/winbindd.h
source3/nsswitch/winbindd_ads.c
source3/nsswitch/winbindd_group.c
source3/nsswitch/winbindd_proto.h
source3/nsswitch/winbindd_rpc.c
source3/nsswitch/winbindd_user.c
source3/nsswitch/winbindd_util.c

index a00bf54cad72c63b8b5f60bc50be27bc6a557b8f..462a078fae2e51ba8a6d9462ccc74d5894948d4a 100644 (file)
@@ -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 */
index 3ae2f85b4691c9122768195244c08dac614c2afa..e90e590e8c60570314dad4e5b31fa8ca431dd4b9 100644 (file)
 
 #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
index b03e506494995c17458ea198ef01add7fa756c56..440f0093669c848c50f356192b11cbd7cc831bc9 100644 (file)
@@ -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 */
index 4659ad69ddfecf1392f46f99da80e877c453bf45..893064b80179297804de2afb01c423870f82b0a1 100644 (file)
@@ -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);
index d78315681526c962602c805fdd908694269ced1a..c04bcdc954d789d408723b2c08dd067c32d6d92e 100644 (file)
@@ -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
 };
 
index 52122a4f29745568997653fcebdaba1a91af7c31..d9b2b5a0e6e7e9da4f9585c2312298f3a5dd1ea6 100644 (file)
@@ -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));
index d49e0b5bc22366a95cb9ebb67b71803223c15eff..2ac090f8e56f847b5dd05acb3c50c7ef7802b98e 100644 (file)
@@ -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 */