summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vlendec@samba.org>2004-11-12 15:49:47 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 10:53:15 -0500
commitf9e87b9ba65f37bafa45eacb1a6c9b8c5483d46b (patch)
tree226655c957de8578b3c3e0c854930b03e90d37a1
parent69ddbbf97b4c37cba879f7dd9ce8cb5f4d336857 (diff)
downloadsamba-f9e87b9ba65f37bafa45eacb1a6c9b8c5483d46b.tar.gz
samba-f9e87b9ba65f37bafa45eacb1a6c9b8c5483d46b.tar.bz2
samba-f9e87b9ba65f37bafa45eacb1a6c9b8c5483d46b.zip
r3705: Nobody has commented, so I'll take this as an ack...
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)
-rw-r--r--source3/Makefile.in9
-rw-r--r--source3/auth/auth_util.c52
-rw-r--r--source3/include/passdb.h12
-rw-r--r--source3/lib/system_smbd.c90
-rw-r--r--source3/lib/util_smbd.c16
-rw-r--r--source3/passdb/pdb_interface.c35
-rw-r--r--source3/passdb/pdb_ldap.c108
-rw-r--r--source3/rpc_server/srv_samr_nt.c49
-rw-r--r--source3/rpc_server/srv_util.c59
-rw-r--r--source3/smbd/lanman.c45
10 files changed, 334 insertions, 141 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 0b39fd3dce..a6e434464f 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -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)
diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index 96a229f0dc..1ef64ab845 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -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);
diff --git a/source3/include/passdb.h b/source3/include/passdb.h
index 8219e90f2b..db6bc2ac75 100644
--- a/source3/include/passdb.h
+++ b/source3/include/passdb.h
@@ -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);
diff --git a/source3/lib/system_smbd.c b/source3/lib/system_smbd.c
index 55c2338ebd..fd2ed24a17 100644
--- a/source3/lib/system_smbd.c
+++ b/source3/lib/system_smbd.c
@@ -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;
+}
diff --git a/source3/lib/util_smbd.c b/source3/lib/util_smbd.c
index 36c3104e55..fdb4cb3385 100644
--- a/source3/lib/util_smbd.c
+++ b/source3/lib/util_smbd.c
@@ -37,25 +37,20 @@
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);
diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c
index 082e57ecc0..f18ef616f0 100644
--- a/source3/passdb/pdb_interface.c
+++ b/source3/passdb/pdb_interface.c
@@ -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;
diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index 41d650fad5..685d393eb9 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -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 */
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c
index f4348fc83e..0c52e859ca 100644
--- a/source3/rpc_server/srv_samr_nt.c
+++ b/source3/rpc_server/srv_samr_nt.c
@@ -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;
}
diff --git a/source3/rpc_server/srv_util.c b/source3/rpc_server/srv_util.c
index 215471b444..2689d89972 100644
--- a/source3/rpc_server/srv_util.c
+++ b/source3/rpc_server/srv_util.c
@@ -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
diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c
index e7aa05b54a..1379877efc 100644
--- a/source3/smbd/lanman.c
+++ b/source3/smbd/lanman.c
@@ -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;
}