r3705: Nobody has commented, so I'll take this as an ack...
authorVolker Lendecke <vlendec@samba.org>
Fri, 12 Nov 2004 15:49:47 +0000 (15:49 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:53:15 +0000 (10:53 -0500)
abartlet, I'd like to ask you to take a severe look at this!

We have solved the problem to find the global groups a user is in twice: Once
in auth_util.c and another time for the corresponding samr call. The attached
patch unifies these and sends them through the passdb backend (new function
pdb_enum_group_memberships). Thus it gives pdb_ldap.c the chance to further
optimize the corresponding call if the samba and posix accounts are unified by
issuing a specialized ldap query.

The parameter to activate this ldapsam behaviour is

ldapsam:trusted = yes

Volker
(This used to be commit b94838aff1a009f8d8c2c3efd48756a5b8f3f989)

source3/Makefile.in
source3/auth/auth_util.c
source3/include/passdb.h
source3/lib/system_smbd.c
source3/lib/util_smbd.c
source3/passdb/pdb_interface.c
source3/passdb/pdb_ldap.c
source3/rpc_server/srv_samr_nt.c
source3/rpc_server/srv_util.c
source3/smbd/lanman.c

index 0b39fd3dce83d8f1a9526e28ae1c97890265eee6..a6e434464feb0e488b23f5809415b275760dc04b 100644 (file)
@@ -208,8 +208,6 @@ LIB_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
          lib/module.o lib/ldap_escape.o @CHARSET_STATIC@ \
          lib/privileges.o lib/secdesc.o lib/secace.o lib/secacl.o
 
-LIB_SMBD_OBJ = lib/system_smbd.o lib/util_smbd.o 
-
 LIB_NONSMBD_OBJ = $(LIB_OBJ) lib/dummysmbd.o
 
 READLINE_OBJ = lib/readline.o
@@ -313,7 +311,8 @@ PASSDB_GET_SET_OBJ = passdb/pdb_get_set.o
 PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \
                passdb/util_sam_sid.o passdb/pdb_compat.o \
                passdb/privileges.o passdb/lookup_sid.o \
-               passdb/login_cache.o @PDB_STATIC@ passdb/pdb_sql.o
+               passdb/login_cache.o @PDB_STATIC@ passdb/pdb_sql.o \
+               lib/system_smbd.o
 
 XML_OBJ = passdb/pdb_xml.o
 MYSQL_OBJ = passdb/pdb_mysql.o
@@ -395,7 +394,7 @@ SMBD_OBJ_BASE = $(PARAM_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \
                $(NOTIFY_OBJ) $(GROUPDB_OBJ) $(AUTH_OBJ) \
                $(LIBMSRPC_OBJ) \
                $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(LIBADS_SERVER_OBJ) \
-               $(LIB_SMBD_OBJ) $(REGISTRY_OBJ) $(POPT_LIB_OBJ) \
+               $(REGISTRY_OBJ) $(POPT_LIB_OBJ) \
                $(BUILDOPT_OBJ) $(SMBLDAP_OBJ)
 
 PRINTING_OBJ = printing/pcap.o printing/print_svid.o \
@@ -619,7 +618,7 @@ PROTO_OBJ = $(SMBD_OBJ_MAIN) \
            $(PRINTING_OBJ) $(PRINTBACKEND_OBJ) $(OPLOCK_OBJ) $(NOTIFY_OBJ) \
            $(PASSDB_OBJ) $(GROUPDB_OBJ) \
            $(READLINE_OBJ) $(PROFILE_OBJ) $(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) \
-           $(LIB_SMBD_OBJ) $(AUTH_SAM_OBJ) $(REGISTRY_OBJ) $(POPT_LIB_OBJ) \
+           $(AUTH_SAM_OBJ) $(REGISTRY_OBJ) $(POPT_LIB_OBJ) \
            $(RPC_LSA_OBJ) $(RPC_NETLOG_OBJ) $(RPC_SAMR_OBJ) $(RPC_REG_OBJ) $(RPC_LSA_DS_OBJ) \
            $(RPC_SVC_OBJ) $(RPC_WKS_OBJ) $(RPC_DFS_OBJ) $(RPC_SPOOLSS_OBJ) \
            $(RPC_ECHO_OBJ) $(SMBLDAP_OBJ) $(IDMAP_OBJ) libsmb/spnego.o $(PASSCHANGE_OBJ)
index 96a229f0dce6702fb2c5302ea6590cae3a41d054..1ef64ab8458535f3e853a8d3fabca3b3add53930 100644 (file)
@@ -657,47 +657,27 @@ static NTSTATUS get_user_groups(const char *username, uid_t uid, gid_t gid,
 
        *n_groups = 0;
        *groups   = NULL;
-       
-       /* Try winbind first */
 
-       if ( strchr(username, *lp_winbind_separator()) ) {
-               n_unix_groups = winbind_getgroups( username, unix_groups );
+       if (strchr(username, *lp_winbind_separator()) == NULL) {
+               NTSTATUS result;
 
-               DEBUG(10,("get_user_groups: winbind_getgroups(%s): result = %s\n", username, 
-                         n_unix_groups == -1 ? "FAIL" : "SUCCESS"));
-                         
-               if ( n_unix_groups == -1 )
-                       return NT_STATUS_NO_SUCH_USER; /* what should this return value be? */  
+               become_root();
+               result = pdb_enum_group_memberships(username, gid, groups,
+                                                   unix_groups, n_groups);
+               unbecome_root();
+               return result;
        }
-       else {
-               /* fallback to getgrouplist() */
-               
-               n_unix_groups = groups_max();
-               
-               if ((*unix_groups = malloc( sizeof(gid_t) * n_unix_groups ) ) == NULL) {
-                       DEBUG(0, ("get_user_groups: Out of memory allocating unix group list\n"));
-                       return NT_STATUS_NO_MEMORY;
-               }
+
+       /* We have the separator, this must be winbind */
        
-               if (sys_getgrouplist(username, gid, *unix_groups, &n_unix_groups) == -1) {
-               
-                       gid_t *groups_tmp;
-                       
-                       groups_tmp = Realloc(*unix_groups, sizeof(gid_t) * n_unix_groups);
-                       
-                       if (!groups_tmp) {
-                               SAFE_FREE(*unix_groups);
-                               return NT_STATUS_NO_MEMORY;
-                       }
-                       *unix_groups = groups_tmp;
+       n_unix_groups = winbind_getgroups( username, unix_groups );
 
-                       if (sys_getgrouplist(username, gid, *unix_groups, &n_unix_groups) == -1) {
-                               DEBUG(0, ("get_user_groups: failed to get the unix group list\n"));
-                               SAFE_FREE(*unix_groups);
-                               return NT_STATUS_NO_SUCH_USER; /* what should this return value be? */
-                       }
-               }
-       }
+       DEBUG(10,("get_user_groups: winbind_getgroups(%s): result = %s\n",
+                 username,  n_unix_groups == -1 ? "FAIL" : "SUCCESS"));
+                         
+       if ( n_unix_groups == -1 )
+               return NT_STATUS_NO_SUCH_USER; /* what should this return
+                                               * value be? */  
 
        debug_unix_user_token(DBGC_CLASS, 5, uid, gid, n_unix_groups, *unix_groups);
        
index 8219e90f2bf71cb90da4756a7c2f743fc32c71a1..db6bc2ac75ec9d5d2a80df6887dabf030d136502 100644 (file)
@@ -287,6 +287,12 @@ typedef struct pdb_context
                                           GROUP_MAP **rmap, int *num_entries,
                                           BOOL unix_only);
 
+       NTSTATUS (*pdb_enum_group_memberships)(struct pdb_context *context,
+                                              const char *username,
+                                              gid_t primary_gid,
+                                              DOM_SID **sids, gid_t **gids,
+                                              int *num_groups);
+
        NTSTATUS (*pdb_find_alias)(struct pdb_context *context,
                                   const char *name, DOM_SID *sid);
 
@@ -379,6 +385,12 @@ typedef struct pdb_methods
                                       GROUP_MAP **rmap, int *num_entries,
                                       BOOL unix_only);
 
+       NTSTATUS (*enum_group_memberships)(struct pdb_methods *methods,
+                                          const char *username,
+                                          gid_t primary_gid,
+                                          DOM_SID **sids, gid_t **gids,
+                                          int *num_groups);
+
        NTSTATUS (*find_alias)(struct pdb_methods *methods,
                               const char *name, DOM_SID *sid);
 
index 55c2338ebd630ef2713d374da268542f542e6e3b..fd2ed24a17c3c57845ca2d195efb87ce53e3df6f 100644 (file)
@@ -109,7 +109,7 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, in
 }
 #endif
 
-int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt)
+static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt)
 {
        char *p;
        int retval;
@@ -139,3 +139,91 @@ int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt)
        
        return retval;
 }
+
+BOOL getgroups_user(const char *user, gid_t primary_gid,
+                   gid_t **ret_groups, int *ngroups)
+{
+       int ngrp, max_grp;
+       gid_t *temp_groups;
+       gid_t *groups;
+       int i;
+
+       max_grp = groups_max();
+       temp_groups = (gid_t *)malloc(sizeof(gid_t) * max_grp);
+       if (! temp_groups) {
+               return False;
+       }
+
+       if (sys_getgrouplist(user, primary_gid, temp_groups, &max_grp) == -1) {
+               
+               gid_t *groups_tmp;
+               
+               groups_tmp = Realloc(temp_groups, sizeof(gid_t) * max_grp);
+               
+               if (!groups_tmp) {
+                       SAFE_FREE(temp_groups);
+                       return False;
+               }
+               temp_groups = groups_tmp;
+               
+               if (sys_getgrouplist(user, primary_gid,
+                                    temp_groups, &max_grp) == -1) {
+                       DEBUG(0, ("get_user_groups: failed to get the unix "
+                                 "group list\n"));
+                       SAFE_FREE(temp_groups);
+                       return False;
+               }
+       }
+       
+       ngrp = 0;
+       groups = NULL;
+
+       /* Add in primary group first */
+       add_gid_to_array_unique(primary_gid, &groups, &ngrp);
+
+       for (i=0; i<max_grp; i++)
+               add_gid_to_array_unique(temp_groups[i], &groups, &ngrp);
+
+       *ngroups = ngrp;
+       *ret_groups = groups;
+       SAFE_FREE(temp_groups);
+       return True;
+}
+
+NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods,
+                                           const char *username,
+                                           gid_t primary_gid,
+                                           DOM_SID **sids,
+                                           gid_t **gids,
+                                           int *num_groups)
+{
+       int i;
+
+       if (!getgroups_user(username, primary_gid, gids, num_groups)) {
+               return NT_STATUS_NO_SUCH_USER;
+       }
+
+       if (*num_groups == 0) {
+               smb_panic("primary group missing");
+       }
+
+       *sids = malloc(sizeof(**sids) * *num_groups);
+
+       if (*sids == NULL) {
+               SAFE_FREE(gids);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i=0; i<*num_groups; i++) {
+               if (!NT_STATUS_IS_OK(gid_to_sid(&(*sids)[i], (*gids)[i]))) {
+                       DEBUG(1, ("get_user_groups: failed to convert "
+                                 "gid %ld to a sid!\n", 
+                                 (long int)(*gids)[i+1]));
+                       SAFE_FREE(*sids);
+                       SAFE_FREE(*gids);
+                       return NT_STATUS_NO_SUCH_USER;
+               }
+       }
+
+       return NT_STATUS_OK;
+}
index 36c3104e55a582e94cdd861e6705e69ac64a6eb4..fdb4cb3385920c93a7b4179ce32d4e3fae4f0330 100644 (file)
   NOTE! uses become_root() to gain correct priviages on systems
   that lack a native getgroups() call (uses initgroups and getgroups)
 */
-BOOL getgroups_user(const char *user, gid_t **ret_groups, int *ngroups)
+BOOL getgroups_user(const char *user, gid_t primary_gid, gid_t **ret_groups, int *ngroups)
 {
-       struct passwd *pwd;
        int ngrp, max_grp;
        gid_t *temp_groups;
        gid_t *groups;
        int i;
 
-       pwd = getpwnam_alloc(user);
-       if (!pwd) return False;
-
        max_grp = groups_max();
        temp_groups = (gid_t *)malloc(sizeof(gid_t) * max_grp);
        if (! temp_groups) {
-               passwd_free(&pwd);
                return False;
        }
 
-       if (sys_getgrouplist(user, pwd->pw_gid, temp_groups, &max_grp) == -1) {
+       if (sys_getgrouplist(user, primary_gid, temp_groups, &max_grp) == -1) {
                
                gid_t *groups_tmp;
                
@@ -67,9 +62,8 @@ BOOL getgroups_user(const char *user, gid_t **ret_groups, int *ngroups)
                }
                temp_groups = groups_tmp;
                
-               if (sys_getgrouplist(user, pwd->pw_gid, temp_groups, &max_grp) == -1) {
+               if (sys_getgrouplist(user, primary_gid, temp_groups, &max_grp) == -1) {
                        DEBUG(0, ("get_user_groups: failed to get the unix group list\n"));
-                       passwd_free(&pwd);
                        SAFE_FREE(temp_groups);
                        return False;
                }
@@ -79,9 +73,7 @@ BOOL getgroups_user(const char *user, gid_t **ret_groups, int *ngroups)
        groups = NULL;
 
        /* Add in primary group first */
-       add_gid_to_array_unique(pwd->pw_gid, &groups, &ngrp);
-
-       passwd_free(&pwd);
+       add_gid_to_array_unique(primary_gid, &groups, &ngrp);
 
        for (i=0; i<max_grp; i++)
                add_gid_to_array_unique(temp_groups[i], &groups, &ngrp);
index 082e57ecc0ad7a8a576c465ce9270c2e2645c790..f18ef616f0b52d898f7f3daedd455e9a87a9c502 100644 (file)
@@ -452,6 +452,24 @@ static NTSTATUS context_enum_group_mapping(struct pdb_context *context,
                                                        num_entries, unix_only);
 }
 
+static NTSTATUS context_enum_group_memberships(struct pdb_context *context,
+                                              const char *username,
+                                              gid_t primary_gid,
+                                              DOM_SID **sids, gid_t **gids,
+                                              int *num_groups)
+{
+       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+       if ((!context) || (!context->pdb_methods)) {
+               DEBUG(0, ("invalid pdb_context specified!\n"));
+               return ret;
+       }
+
+       return context->pdb_methods->
+               enum_group_memberships(context->pdb_methods, username,
+                                      primary_gid, sids, gids, num_groups);
+}
+
 static NTSTATUS context_find_alias(struct pdb_context *context,
                                   const char *name, DOM_SID *sid)
 {
@@ -718,6 +736,7 @@ static NTSTATUS make_pdb_context(struct pdb_context **context)
        (*context)->pdb_update_group_mapping_entry = context_update_group_mapping_entry;
        (*context)->pdb_delete_group_mapping_entry = context_delete_group_mapping_entry;
        (*context)->pdb_enum_group_mapping = context_enum_group_mapping;
+       (*context)->pdb_enum_group_memberships = context_enum_group_memberships;
 
        (*context)->pdb_find_alias = context_find_alias;
        (*context)->pdb_create_alias = context_create_alias;
@@ -1038,6 +1057,21 @@ BOOL pdb_enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap,
                                                      rmap, num_entries, unix_only));
 }
 
+NTSTATUS pdb_enum_group_memberships(const char *username, gid_t primary_gid,
+                                   DOM_SID **sids, gid_t **gids,
+                                   int *num_groups)
+{
+       struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+       if (!pdb_context) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       return pdb_context->pdb_enum_group_memberships(pdb_context, username,
+                                                      primary_gid, sids, gids,
+                                                      num_groups);
+}
+
 BOOL pdb_find_alias(const char *name, DOM_SID *sid)
 {
        struct pdb_context *pdb_context = pdb_get_static_context(False);
@@ -1250,6 +1284,7 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
        (*methods)->update_group_mapping_entry = pdb_default_update_group_mapping_entry;
        (*methods)->delete_group_mapping_entry = pdb_default_delete_group_mapping_entry;
        (*methods)->enum_group_mapping = pdb_default_enum_group_mapping;
+       (*methods)->enum_group_memberships = pdb_default_enum_group_memberships;
        (*methods)->find_alias = pdb_default_find_alias;
        (*methods)->create_alias = pdb_default_create_alias;
        (*methods)->delete_alias = pdb_default_delete_alias;
index 41d650fad5260ef081b08188d3082643c616c757..685d393eb9c8971066896bf1da7836ea6578f778 100644 (file)
@@ -2199,6 +2199,113 @@ static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
        return ldapsam_getgroup(methods, filter, map);
 }
 
+static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
+                                              const char *username,
+                                              gid_t primary_gid,
+                                              DOM_SID **sids, gid_t **gids,
+                                              int *num_groups)
+{
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)methods->private_data;
+       struct smbldap_state *conn = ldap_state->smbldap_state;
+       pstring filter;
+       char *attrs[] = { "gidNumber", "sambaSID", NULL };
+       char *escape_name = escape_ldap_string_alloc(username);
+       int rc;
+       LDAPMessage *msg = NULL;
+       LDAPMessage *entry;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       int num_sids, num_gids;
+       extern DOM_SID global_sid_NULL;
+
+       if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
+               return pdb_default_enum_group_memberships(methods, username,
+                                                         primary_gid, sids,
+                                                         gids, num_groups);
+
+       *sids = NULL;
+       num_sids = 0;
+
+       if (escape_name == NULL)
+               return NT_STATUS_UNSUCCESSFUL;
+
+       pstr_sprintf(filter, "(&(objectClass=posixGroup)"
+                    "(|(memberUid=%s)(gidNumber=%d)))",
+                    username, primary_gid);
+
+       rc = smbldap_search(conn, lp_ldap_group_suffix(),
+                           LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg);
+
+       if (rc != LDAP_SUCCESS)
+               goto done;
+
+       num_gids = 0;
+       *gids = NULL;
+
+       num_sids = 0;
+       *sids = NULL;
+
+       /* We need to add the primary group as the first gid/sid */
+
+       add_gid_to_array_unique(primary_gid, gids, &num_gids);
+
+       /* This sid will be replaced later */
+
+       add_sid_to_array_unique(&global_sid_NULL, sids, &num_sids);
+
+       for (entry = ldap_first_entry(conn->ldap_struct, msg);
+            entry != NULL;
+            entry = ldap_next_entry(conn->ldap_struct, entry))
+       {
+               fstring str;
+               DOM_SID sid;
+               gid_t gid;
+               char *end;
+
+               if (!smbldap_get_single_attribute(conn->ldap_struct,
+                                                 entry, "sambaSID",
+                                                 str, sizeof(str)-1))
+                       goto done;
+
+               if (!string_to_sid(&sid, str))
+                       goto done;
+
+               if (!smbldap_get_single_attribute(conn->ldap_struct,
+                                                 entry, "gidNumber",
+                                                 str, sizeof(str)-1))
+                       goto done;
+
+               gid = strtoul(str, &end, 10);
+
+               if (PTR_DIFF(end, str) != strlen(str))
+                       goto done;
+
+               if (gid == primary_gid) {
+                       sid_copy(&(*sids)[0], &sid);
+               } else {
+                       add_gid_to_array_unique(gid, gids, &num_gids);
+                       add_sid_to_array_unique(&sid, sids, &num_sids);
+               }
+       }
+
+       if (sid_compare(&global_sid_NULL, &(*sids)[0]) == 0) {
+               DEBUG(3, ("primary group not found\n"));
+               goto done;
+       }
+
+       *num_groups = num_sids;
+
+       result = NT_STATUS_OK;
+
+ done:
+
+       SAFE_FREE(escape_name);
+       if (msg != NULL)
+               ldap_msgfree(msg);
+
+       return result;
+}
+
 /**********************************************************************
  *********************************************************************/
 
@@ -2858,6 +2965,7 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **
        (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
        (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
        (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
+       (*pdb_method)->enum_group_memberships = ldapsam_enum_group_memberships;
 
        /* TODO: Setup private data and free */
 
index f4348fc83effa192bc0e11452d3d979ed88ee834..0c52e859ca80e3d177746ed11a3122bc95f6a818 100644 (file)
@@ -1943,11 +1943,16 @@ NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_
 NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, SAMR_R_QUERY_USERGROUPS *r_u)
 {
        SAM_ACCOUNT *sam_pass=NULL;
+       struct passwd *passwd;
        DOM_SID  sid;
+       DOM_SID *sids;
        DOM_GID *gids = NULL;
        int num_groups = 0;
+       gid_t *unix_gids;
+       int i, num_gids, num_sids;
        uint32 acc_granted;
        BOOL ret;
+       NTSTATUS result;
 
        /*
         * from the SID in the request:
@@ -1986,19 +1991,53 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S
                pdb_free_sam(&sam_pass);
                return NT_STATUS_NO_SUCH_USER;
        }
-       
-       if(!get_domain_user_groups(p->mem_ctx, &num_groups, &gids, sam_pass)) {
+
+       passwd = getpwnam_alloc(pdb_get_username(sam_pass));
+       if (passwd == NULL) {
                pdb_free_sam(&sam_pass);
-               return NT_STATUS_NO_SUCH_GROUP;
+               return NT_STATUS_NO_SUCH_USER;
        }
+
+       sids = NULL;
+       num_sids = 0;
+
+       become_root();
+       result = pdb_enum_group_memberships(pdb_get_username(sam_pass),
+                                           passwd->pw_gid,
+                                           &sids, &unix_gids, &num_groups);
+       unbecome_root();
+
+       pdb_free_sam(&sam_pass);
+       passwd_free(&passwd);
+
+       if (!NT_STATUS_IS_OK(result))
+               return result;
+
+       SAFE_FREE(unix_gids);
+
+       gids = NULL;
+       num_gids = 0;
+
+       for (i=0; i<num_groups; i++) {
+               uint32 rid;
+
+               if (!sid_peek_check_rid(get_global_sam_sid(),
+                                       &(sids[i]), &rid))
+                       continue;
+
+               gids = talloc_realloc(p->mem_ctx, gids,
+                                     sizeof(*gids) * (num_gids+1));
+               gids[num_gids].attr=7;
+               gids[num_gids].g_rid = rid;
+               num_gids += 1;
+       }
+       SAFE_FREE(sids);
        
        /* construct the response.  lkclXXXX: gids are not copied! */
        init_samr_r_query_usergroups(r_u, num_groups, gids, r_u->status);
        
        DEBUG(5,("_samr_query_usergroups: %d\n", __LINE__));
        
-       pdb_free_sam(&sam_pass);
-       
        return r_u->status;
 }
 
index 215471b444c886abba121e5e0c7f6927ebf1dc59..2689d89972343a74f16a66e15381478486933069 100644 (file)
@@ -79,65 +79,6 @@ static const rid_name domain_group_rids[] =
     { 0                             , NULL }
 };
 
-/*******************************************************************
- gets a domain user's groups
- ********************************************************************/
-BOOL get_domain_user_groups(TALLOC_CTX *ctx, int *numgroups, DOM_GID **pgids, SAM_ACCOUNT *sam_pass)
-{
-
-       const char *username = pdb_get_username(sam_pass);
-       int             n_unix_groups;
-       int             i,j;
-       gid_t *unix_groups;
-
-       *numgroups = 0;
-       *pgids   = NULL;
-       
-       if (!getgroups_user(username, &unix_groups, &n_unix_groups)) {
-               return False;
-       }
-
-       /* now setup the space for storing the SIDS */
-       
-       if (n_unix_groups > 0) {
-       
-               *pgids   = talloc(ctx, sizeof(DOM_GID) * n_unix_groups);
-               
-               if (!*pgids) {
-                       DEBUG(0, ("get_user_group: malloc() failed for DOM_GID list!\n"));
-                       SAFE_FREE(unix_groups);
-                       return False;
-               }
-       }
-
-       become_root();
-       j = 0;
-       for (i = 0; i < n_unix_groups; i++) {
-               GROUP_MAP map;
-               uint32 rid;
-               
-               if (!pdb_getgrgid(&map, unix_groups[i])) {
-                       DEBUG(3, ("get_user_groups: failed to convert gid %ld to a domain group!\n", 
-                               (long int)unix_groups[i+1]));
-                       if (i == 0) {
-                               DEBUG(1,("get_domain_user_groups: primary gid of user [%s] is not a Domain group !\n", username));
-                               DEBUGADD(1,("get_domain_user_groups: You should fix it, NT doesn't like that\n"));
-                       }
-               } else if ((map.sid_name_use == SID_NAME_DOM_GRP)
-                          && sid_peek_check_rid(get_global_sam_sid(), &map.sid, &rid)) {
-                       (*pgids)[j].attr=7;
-                       (*pgids)[j].g_rid=rid;
-                       j++;
-               }
-       }
-       unbecome_root();
-
-       *numgroups = j;
-
-       SAFE_FREE(unix_groups);
-
-       return True;
-}
 
 /*******************************************************************
  gets a domain user's groups from their already-calculated NT_USER_TOKEN
index e7aa05b54a681c79d6ff713c1b63d1e2c7c373ea..1379877efcd3f476123d5b56fa7af4ff571ca220 100644 (file)
@@ -1741,13 +1741,15 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
        int count=0;
        SAM_ACCOUNT *sampw = NULL;
        BOOL ret = False;
-        DOM_GID *gids = NULL;
-        int num_groups = 0;
+       DOM_SID *sids;
+       gid_t *gids;
+       int num_groups;
        int i;
        fstring grp_domain;
        fstring grp_name;
        enum SID_NAME_USE grp_type;
-       DOM_SID sid, dom_sid;
+       struct passwd *passwd;
+       NTSTATUS result;
 
        *rparam_len = 8;
        *rparam = REALLOC(*rparam,*rparam_len);
@@ -1778,6 +1780,11 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
 
        /* Lookup the user information; This should only be one of 
           our accounts (not remote domains) */
+
+       passwd = getpwnam_alloc(UserName);
+
+       if (passwd == NULL)
+               return False;
           
        pdb_init_sam( &sampw );
        
@@ -1786,35 +1793,26 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
        if ( !pdb_getsampwnam(sampw, UserName) )
                goto out;
 
-       /* this next set of code is horribly inefficient, but since 
-          it is rarely called, I'm going to leave it like this since 
-          it easier to follow      --jerry                          */
-          
-       /* get the list of group SIDs */
-       
-       if ( !get_domain_user_groups(conn->mem_ctx, &num_groups, &gids, sampw) ) {
-               DEBUG(1,("api_NetUserGetGroups: get_domain_user_groups() failed!\n"));
+       sids = NULL;
+       num_groups = 0;
+
+       result = pdb_enum_group_memberships(pdb_get_username(sampw),
+                                           passwd->pw_gid,
+                                           &sids, &gids, &num_groups);
+
+       if (!NT_STATUS_IS_OK(result))
                goto out;
-        }
 
-       /* convert to names (we don't support universal groups so the domain
-          can only be ours) */
-       
-       sid_copy( &dom_sid, get_global_sam_sid() );
        for (i=0; i<num_groups; i++) {
        
-               /* make the DOM_GID into a DOM_SID and then lookup 
-                  the name */
-               
-               sid_copy( &sid, &dom_sid );
-               sid_append_rid( &sid, gids[i].g_rid );
-               
-               if ( lookup_sid(&sid, grp_domain, grp_name, &grp_type) ) {
+               if ( lookup_sid(&sids[i], grp_domain, grp_name, &grp_type) ) {
                        pstrcpy(p, grp_name); 
                        p += 21; 
                        count++;
                }
        }
+
+       SAFE_FREE(sids);
        
        *rdata_len = PTR_DIFF(p,*rdata);
 
@@ -1827,6 +1825,7 @@ out:
        unbecome_root();                                /* END ROOT BLOCK */
 
        pdb_free_sam( &sampw );
+       passwd_free(&passwd);
 
        return ret;
 }