This is a multi-part message in MIME format.
--------------060704000708000507020604
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Andrew Bartlett wrote:
> On Sat, 2004-09-25 at 04:13, Igor Belyi wrote:
>>Then get_memberuids() is doomed. To get the list of all users whose
>>primary group has a particular gid you need to either have their
>>posixAccount in LDAP to allow filter to do the work or list all users
>>via NSS as get_memberuids() function does now.

>
> Unfortunately we are now so far into the 3.0 series that we can't
> realistically break any 'working' configuration, no matter how much I
> may feel it's brain-dead or otherwise ;-). Naturally, that didn't stop
> the performance issue being introduced for correctness, but what we can
> do is guard the fix with 'ldap trust ids' (or a better name) as a
> smb.conf parameter.


Would you look at that! All 'query' backends (ldap, mysql, pgsql) has
primaryGroupSid in their Samba user databases and this is enough to have
the requested optimization.

The attached patch introduces yet another pdb interface method
enum_group_prmembers to retrieve SIDs of users with the given
primaryGroupSid. Its default implementation goes through all users as it
was done in get_memberuids(). Implementations in ldap, mysql, and pgsql
backends use correct filter and query.

get_memberuids() is adjusted to use this new method instead of going
through all users all the time.

This patch is made on top of my previous patch.

I've tested it a little - group members are shown correctly and smbd
doesn't crash.

Hope you like it. Note, no "ldap trust ids" is necessary. )
Igor

--------------060704000708000507020604
Content-Type: text/x-patch;
name="samba-3.0.7-enum_group_prmembers.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="samba-3.0.7-enum_group_prmembers.patch"

diff -ru samba-3.0.7.orig/source/groupdb/mapping.c samba-3.0.7/source/groupdb/mapping.c
--- samba-3.0.7.orig/source/groupdb/mapping.c 2004-09-25 23:31:18.000000000 -0400
+++ samba-3.0.7/source/groupdb/mapping.c 2004-09-25 23:30:47.000000000 -0400
@@ -1577,3 +1577,10 @@
return NT_STATUS_UNSUCCESSFUL;
}

+NTSTATUS pdb_nop_enum_group_prmembers(struct pdb_methods *methods,
+ const DOM_SID *group_sid,
+ DOM_SID **rsids, int *num_entries)
+{
+ return NT_STATUS_UNSUCCESSFUL;
+}
+
diff -ru samba-3.0.7.orig/source/include/passdb.h samba-3.0.7/source/include/passdb.h
--- samba-3.0.7.orig/source/include/passdb.h 2004-09-22 18:22:36.000000000 -0400
+++ samba-3.0.7/source/include/passdb.h 2004-09-25 12:41:21.000000000 -0400
@@ -293,6 +293,11 @@
GROUP_MAP **rmap, int *num_entries,
BOOL unix_only);

+ NTSTATUS (*pdb_enum_group_prmembers)(struct pdb_context *context,
+ const DOM_SID *group_sid,
+ DOM_SID **rsids,
+ int *num_entries);
+
NTSTATUS (*pdb_find_alias)(struct pdb_context *context,
const char *name, DOM_SID *sid);

@@ -390,6 +395,10 @@
GROUP_MAP **rmap, int *num_entries,
BOOL unix_only);

+ NTSTATUS (*enum_group_prmembers)(struct pdb_methods *methods,
+ const DOM_SID *group_sid,
+ DOM_SID **rsids, int *num_entries);
+
NTSTATUS (*find_alias)(struct pdb_methods *methods,
const char *name, DOM_SID *sid);

@@ -440,6 +449,6 @@
struct pdb_init_function_entry *prev, *next;
};

-enum sql_search_field { SQL_SEARCH_NONE = 0, SQL_SEARCH_USER_SID = 1, SQL_SEARCH_USER_NAME = 2};
+enum sql_search_field { SQL_SEARCH_NONE = 0, SQL_SEARCH_USER_SID = 1, SQL_SEARCH_USER_NAME = 2, SQL_SEARCH_GROUP_SID = 3 };

#endif /* _PASSDB_H */
diff -ru samba-3.0.7.orig/source/lib/util_sid.c samba-3.0.7/source/lib/util_sid.c
--- samba-3.0.7.orig/source/lib/util_sid.c 2004-04-29 03:34:48.000000000 -0400
+++ samba-3.0.7/source/lib/util_sid.c 2004-09-25 21:36:40.000000000 -0400
@@ -647,3 +647,26 @@

return dst;
}
+
+/************************************************** *****************
+ Add SID to the list.
+************************************************* *******************/
+
+BOOL add_sid_to_list(DOM_SID newsid, DOM_SID **rsids, int *num_entries)
+{
+ DOM_SID *sidst;
+
+ sidst=(DOM_SID *)Realloc((*rsids), (*num_entries+1)*sizeof(DOM_SID));
+ if (!sidst) {
+ DEBUG(0,("add_sid_to_list: Unable to enlarge sid list!\n"));
+ return False;
+ }
+ else
+ (*rsids) = sidst;
+
+ sidst[*num_entries] = newsid;
+
+ *num_entries += 1;
+
+ return True;
+}
diff -ru samba-3.0.7.orig/source/passdb/pdb_guest.c samba-3.0.7/source/passdb/pdb_guest.c
--- samba-3.0.7.orig/source/passdb/pdb_guest.c 2004-09-22 18:22:36.000000000 -0400
+++ samba-3.0.7/source/passdb/pdb_guest.c 2004-09-24 23:53:01.000000000 -0400
@@ -151,7 +151,8 @@
(*pdb_method)->update_group_mapping_entry = pdb_nop_update_group_mapping_entry;
(*pdb_method)->delete_group_mapping_entry = pdb_nop_delete_group_mapping_entry;
(*pdb_method)->enum_group_mapping = pdb_nop_enum_group_mapping;
- (*pdb_method)->enum_group_mapping = pdb_nop_enum_user_groups;
+ (*pdb_method)->enum_user_groups = pdb_nop_enum_user_groups;
+ (*pdb_method)->enum_group_prmembers = pdb_nop_enum_group_prmembers;


/* There's not very much to initialise here */
diff -ru samba-3.0.7.orig/source/passdb/pdb_interface.c samba-3.0.7/source/passdb/pdb_interface.c
--- samba-3.0.7.orig/source/passdb/pdb_interface.c 2004-09-22 18:22:36.000000000 -0400
+++ samba-3.0.7/source/passdb/pdb_interface.c 2004-09-25 22:46:03.000000000 -0400
@@ -470,6 +470,22 @@
num_entries, unix_only);
}

+static NTSTATUS context_enum_group_prmembers(struct pdb_context *context,
+ const DOM_SID *group_sid,
+ DOM_SID **rsids, int *num_entries)
+{
+ 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_prmembers(context->pdb_methods,
+ group_sid, rsids,
+ num_entries);
+}
+
static NTSTATUS context_find_alias(struct pdb_context *context,
const char *name, DOM_SID *sid)
{
@@ -736,6 +752,7 @@
(*context)->pdb_delete_group_mapping_entry = context_delete_group_mapping_entry;
(*context)->pdb_enum_group_mapping = context_enum_group_mapping;
(*context)->pdb_enum_user_groups = context_enum_user_groups;
+ (*context)->pdb_enum_group_prmembers = context_enum_group_prmembers;

(*context)->pdb_find_alias = context_find_alias;
(*context)->pdb_create_alias = context_create_alias;
@@ -1044,6 +1061,20 @@
rmap, num_entries, unix_only));
}

+BOOL pdb_enum_group_prmembers(const DOM_SID *group_sid,
+ DOM_SID **rsids, int *num_entries)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return NT_STATUS_IS_OK(pdb_context->
+ pdb_enum_group_prmembers(pdb_context, group_sid,
+ rsids, num_entries));
+}
+
BOOL pdb_find_alias(const char *name, DOM_SID *sid)
{
struct pdb_context *pdb_context = pdb_get_static_context(False);
@@ -1229,6 +1260,45 @@
return; /* NT_STATUS_NOT_IMPLEMENTED; */
}

+static NTSTATUS pdb_default_enum_group_prmembers(struct pdb_methods *methods,
+ const DOM_SID *group_sid,
+ DOM_SID **rsids, int *num_entries)
+{
+ SAM_ACCOUNT *sampw = NULL;
+ gid_t gid;
+ struct sys_pwent *userlist, *user;
+ int entries = 0;
+
+ *num_entries = 0;
+ *rsids = NULL;
+
+ if (!NT_STATUS_IS_OK(sid_to_gid(group_sid, &gid)))
+ return NT_STATUS_NO_SUCH_GROUP;
+
+ userlist = getpwent_list();
+ pdb_init_sam(&sampw);
+ for (user = userlist; user != NULL; user = user->next) {
+ if (user->pw_gid != gid)
+ continue;
+
+ if(!pdb_getsampwnam(sampw, user->pw_name))
+ continue;
+
+ if(!add_sid_to_list(*(pdb_get_user_sid(sampw)), rsids, &entries)) {
+ DEBUG(0,("pdb_default_enum_group_prmembers: Unable to add user to the list!\n"));
+ SAFE_FREE(*rsids);
+ pdb_free_sam(&sampw);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+ pdb_free_sam(&sampw);
+ pwent_free(userlist);
+
+ *num_entries = entries;
+
+ return NT_STATUS_OK;
+}
+
NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
{
*methods = talloc(mem_ctx, sizeof(struct pdb_methods));
@@ -1256,6 +1326,7 @@
(*methods)->delete_group_mapping_entry = pdb_default_delete_group_mapping_entry;
(*methods)->enum_group_mapping = pdb_default_enum_group_mapping;
(*methods)->enum_user_groups = pdb_default_enum_user_groups;
+ (*methods)->enum_group_prmembers = pdb_default_enum_group_prmembers;
(*methods)->find_alias = pdb_default_find_alias;
(*methods)->create_alias = pdb_default_create_alias;
(*methods)->delete_alias = pdb_default_delete_alias;
diff -ru samba-3.0.7.orig/source/passdb/pdb_ldap.c samba-3.0.7/source/passdb/pdb_ldap.c
--- samba-3.0.7.orig/source/passdb/pdb_ldap.c 2004-09-22 19:15:28.000000000 -0400
+++ samba-3.0.7/source/passdb/pdb_ldap.c 2004-09-25 22:40:45.000000000 -0400
@@ -1153,7 +1153,7 @@
Connect to LDAP server for password enumeration.
************************************************** *******************/

-static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
+static NTSTATUS ldapsam_common_setsampwent(struct pdb_methods *my_methods, const char *extra_filter)
{
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
int rc;
@@ -1164,6 +1164,13 @@
get_objclass_filter(ldap_state->schema_ver));
all_string_sub(filter, "%u", "*", sizeof(pstring));

+ if(extra_filter != NULL) {
+ pstring temp_str;
+ pstrcpy(temp_str, filter);
+ pstr_sprintf( filter, "(&%s%s)", temp_str, extra_filter);
+ }
+
+
attr_list = get_userattr_list(ldap_state->schema_ver);
rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
attr_list, &ldap_state->result);
@@ -1188,6 +1195,11 @@
return NT_STATUS_OK;
}

+static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
+{
+ return ldapsam_common_setsampwent(my_methods, NULL);
+}
+
/************************************************** ********************
End enumeration of the LDAP password list.
************************************************** *******************/
@@ -2476,6 +2488,73 @@
rmap, num_entries, unix_only);
}

+static NTSTATUS ldapsam_enum_group_prmembers(struct pdb_methods *methods,
+ const DOM_SID *group_sid,
+ DOM_SID **rsids, int *num_entries)
+{
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
+ fstring filter;
+ fstring sid_string;
+ fstring dom_sid_string;
+ SAM_ACCOUNT *user = NULL;
+ uint32 rid;
+ int entries = 0;
+
+ *num_entries = 0;
+ *rsids = NULL;
+
+ /* Check that group's SID belongs to us and retrieve RID */
+ if (!sid_peek_check_rid(&ldap_state->domain_sid, group_sid, &rid)) {
+ DEBUG(1, ("ldapsam_enum_group_prmembers: Group SID (%s) is not for this domain (%s)!\n",
+ sid_to_string(sid_string, group_sid),
+ sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
+ return NT_STATUS_NO_SUCH_GROUP;
+ }
+
+ switch ( ldap_state->schema_ver ) {
+ case SCHEMAVER_SAMBAACCOUNT:
+ pstr_sprintf(filter, "(%s=%i)",
+ get_userattr_key2string(ldap_state->schema_ver,
+ LDAP_ATTR_PRIMARY_GROUP_RID),
+ rid);
+ break;
+
+ case SCHEMAVER_SAMBASAMACCOUNT:
+ pstr_sprintf(filter, "(%s=%s)",
+ get_userattr_key2string(ldap_state->schema_ver,
+ LDAP_ATTR_PRIMARY_GROUP_SID),
+ sid_to_string(sid_string, group_sid));
+ break;
+
+ default:
+ DEBUG(0,("ldapsam_enum_group_prmembers: unknown schema version specified\n"));
+ return NT_STATUS_NO_SUCH_GROUP;
+ }
+
+ if (!NT_STATUS_IS_OK(ldapsam_common_setsampwent(metho ds, filter))) {
+ DEBUG(0, ("ldapsam_enum_group_prmembers: Unable to open passdb\n"));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ pdb_init_sam(&user);
+ while (NT_STATUS_IS_OK(ldapsam_getsampwent(methods, user))) {
+ if(!add_sid_to_list(*(pdb_get_user_sid(user)), rsids, &entries)) {
+ DEBUG(0,("ldapsam_enum_group_prmembers: Unable to add user to the list!\n"));
+ SAFE_FREE(*rsids);
+ pdb_free_sam(&user);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+ pdb_free_sam(&user);
+ ldapsam_endsampwent(methods);
+
+ *num_entries = entries;
+
+ return NT_STATUS_OK;
+}
+
+
static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
const DOM_SID *alias,
const DOM_SID *member,
@@ -2777,6 +2856,7 @@
(*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
(*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
(*pdb_method)->enum_user_groups = ldapsam_enum_user_groups;
+ (*pdb_method)->enum_group_prmembers = ldapsam_enum_group_prmembers;

/* TODO: Setup private data and free */

diff -ru samba-3.0.7.orig/source/passdb/pdb_mysql.c samba-3.0.7/source/passdb/pdb_mysql.c
--- samba-3.0.7.orig/source/passdb/pdb_mysql.c 2004-04-04 03:37:36.000000000 -0400
+++ samba-3.0.7/source/passdb/pdb_mysql.c 2004-09-25 22:41:48.000000000 -0400
@@ -120,7 +120,8 @@
return NT_STATUS_OK;
}

-static NTSTATUS mysqlsam_setsampwent(struct pdb_methods *methods, BOOL update)
+static NTSTATUS mysqlsam_common_setsampwent(struct pdb_methods *methods, BOOL update,
+ enum sql_search_field field, const char *value)
{
struct pdb_mysql_data *data =
(struct pdb_mysql_data *) methods->private_data;
@@ -132,7 +133,7 @@
return NT_STATUS_INVALID_HANDLE;
}

- query = sql_account_query_select(data->location, update, SQL_SEARCH_NONE, NULL);
+ query = sql_account_query_select(data->location, update, field, value);

ret = mysql_query(data->handle, query);
SAFE_FREE(query);
@@ -158,6 +159,11 @@
return NT_STATUS_OK;
}

+static NTSTATUS mysqlsam_setsampwent(struct pdb_methods *methods, BOOL update)
+{
+ return mysqlsam_common_setsampwent(methods, update, SQL_SEARCH_NONE, NULL);
+}
+
/************************************************** *************
End enumeration of the passwd list.
************************************************** **************/
@@ -406,6 +412,39 @@
return mysqlsam_replace_sam_account(methods, newpwd, 1);
}

+static NTSTATUS mysqlsam_enum_group_prmembers(struct pdb_methods *methods,
+ const DOM_SID *group_sid,
+ DOM_SID **rsids, int *num_entries)
+{
+ SAM_ACCOUNT *user = NULL;
+ int entries = 0;
+ fstring gsid;
+
+ *num_entries = 0;
+ *rsids = NULL;
+
+ if (!NT_STATUS_IS_OK(mysqlsam_common_setsampwent(meth ods, False, SQL_SEARCH_GROUP_SID, sid_to_string(fstring, group_sid)))) {
+ DEBUG(0, ("mysqlsam_enum_group_prmembers: Unable to open passdb\n"));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ pdb_init_sam(&user);
+ while (NT_STATUS_IS_OK(mysqlsam_getsampwent(methods, user))) {
+ if(!add_sid_to_list(*(pdb_get_user_sid(user)), rsids, &entries)) {
+ DEBUG(0,("mysqlsam_enum_group_prmembers: Unable to add user to the list!\n"));
+ SAFE_FREE(*rsids);
+ pdb_free_sam(&user);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+ pdb_free_sam(&user);
+ mysqlsam_endsampwent(methods);
+
+ *num_entries = entries;
+
+ return NT_STATUS_OK;
+}
+
static NTSTATUS mysqlsam_init(struct pdb_context * pdb_context, struct pdb_methods ** pdb_method,
const char *location)
{
@@ -441,6 +480,8 @@
(*pdb_method)->update_sam_account = mysqlsam_update_sam_account;
(*pdb_method)->delete_sam_account = mysqlsam_delete_sam_account;

+ (*pdb_method)->enum_group_prmembers = mysqlsam_enum_group_prmembers;
+
data = talloc(pdb_context->mem_ctx, sizeof(struct pdb_mysql_data));
(*pdb_method)->private_data = data;
data->handle = NULL;
diff -ru samba-3.0.7.orig/source/passdb/pdb_pgsql.c samba-3.0.7/source/passdb/pdb_pgsql.c
--- samba-3.0.7.orig/source/passdb/pdb_pgsql.c 2004-04-04 03:37:36.000000000 -0400
+++ samba-3.0.7/source/passdb/pdb_pgsql.c 2004-09-25 22:42:36.000000000 -0400
@@ -117,7 +117,8 @@
return NT_STATUS_OK ;
}

-static NTSTATUS pgsqlsam_setsampwent(struct pdb_methods *methods, BOOL update)
+static NTSTATUS pgsqlsam_common_setsampwent(struct pdb_methods *methods, BOOL update,
+ enum sql_search_field field, const char *value)
{
struct pdb_pgsql_data *data ;
char *query ;
@@ -125,7 +126,7 @@

SET_DATA( data, methods ) ;

- query = sql_account_query_select(data->location, update, SQL_SEARCH_NONE, NULL);
+ query = sql_account_query_select(data->location, update, field, value);

/* Do it */
DEBUG( 5, ("Executing query %s\n", query) ) ;
@@ -153,6 +154,11 @@
return retval ;
}

+static NTSTATUS pgsqlsam_setsampwent(struct pdb_methods *methods, BOOL update)
+{
+ return pgsqlsam_common_setsampwent(methods, update, SQL_SEARCH_NONE, NULL);
+}
+
/************************************************** *************
End enumeration of the passwd list.
************************************************** **************/
@@ -405,6 +411,39 @@
return pgsqlsam_replace_sam_account( methods, newpwd, 1 ) ;
}

+static NTSTATUS pgsqlsam_enum_group_prmembers(struct pdb_methods *methods,
+ const DOM_SID *group_sid,
+ DOM_SID **rsids, int *num_entries)
+{
+ SAM_ACCOUNT *user = NULL;
+ int entries = 0;
+ fstring gsid;
+
+ *num_entries = 0;
+ *rsids = NULL;
+
+ if (!NT_STATUS_IS_OK(pgsqlsam_common_setsampwent(meth ods, False, SQL_SEARCH_GROUP_SID, sid_to_string(fstring, group_sid)))) {
+ DEBUG(0, ("pgsqlsam_enum_group_prmembers: Unable to open passdb\n"));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ pdb_init_sam(&user);
+ while (NT_STATUS_IS_OK(pgsqlsam_getsampwent(methods, user))) {
+ if(!add_sid_to_list(*(pdb_get_user_sid(user)), rsids, &entries)) {
+ DEBUG(0,("pgsqlsam_enum_group_prmembers: Unable to add user to the list!\n"));
+ SAFE_FREE(*rsids);
+ pdb_free_sam(&user);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+ pdb_free_sam(&user);
+ pgsqlsam_endsampwent(methods);
+
+ *num_entries = entries;
+
+ return NT_STATUS_OK;
+}
+
static NTSTATUS pgsqlsam_init ( struct pdb_context *pdb_context, struct pdb_methods **pdb_method, const char *location )
{
NTSTATUS nt_status ;
@@ -432,6 +471,8 @@
(*pdb_method)->update_sam_account = pgsqlsam_update_sam_account ;
(*pdb_method)->delete_sam_account = pgsqlsam_delete_sam_account ;

+ (*pdb_method)->enum_group_prmembers = pgsqlsam_enum_group_prmembers ;
+
data = talloc( pdb_context->mem_ctx, sizeof( struct pdb_pgsql_data ) ) ;
(*pdb_method)->private_data = data ;
data->handle = NULL ;
diff -ru samba-3.0.7.orig/source/passdb/pdb_sql.c samba-3.0.7/source/passdb/pdb_sql.c
--- samba-3.0.7.orig/source/passdb/pdb_sql.c 2004-04-04 03:37:36.000000000 -0400
+++ samba-3.0.7/source/passdb/pdb_sql.c 2004-09-25 12:42:47.000000000 -0400
@@ -201,6 +201,11 @@
field_string = config_value_read(data, "username column",
CONFIG_USERNAME_DEFAULT);
break;
+
+ case SQL_SEARCH_GROUP_SID:
+ field_string = config_value_read(data, "group sid column",
+ CONFIG_GROUP_SID_DEFAULT);
+ break;
}

asprintf(&query,
diff -ru samba-3.0.7.orig/source/passdb/pdb_xml.c samba-3.0.7/source/passdb/pdb_xml.c
--- samba-3.0.7.orig/source/passdb/pdb_xml.c 2004-09-22 18:22:36.000000000 -0400
+++ samba-3.0.7/source/passdb/pdb_xml.c 2004-09-24 23:42:33.000000000 -0400
@@ -542,6 +542,7 @@
(*pdb_method)->delete_group_mapping_entry = NULL;
(*pdb_method)->enum_group_mapping = NULL;
(*pdb_method)->enum_user_groups = NULL;
+ (*pdb_method)->enum_group_prmembers = NULL;

data = talloc(pdb_context->mem_ctx, sizeof(pdb_xml));
data->location = talloc_strdup(pdb_context->mem_ctx, (location ? location : "passdb.xml"));
diff -ru samba-3.0.7.orig/source/rpc_server/srv_samr_nt.c samba-3.0.7/source/rpc_server/srv_samr_nt.c
--- samba-3.0.7.orig/source/rpc_server/srv_samr_nt.c 2004-09-22 19:16:33.000000000 -0400
+++ samba-3.0.7/source/rpc_server/srv_samr_nt.c 2004-09-25 22:41:08.000000000 -0400
@@ -3241,64 +3241,63 @@
return NT_STATUS_OK;
}

-static void add_uid_to_array_unique(uid_t uid, uid_t **uids, int *num)
-{
- int i;
-
- for (i=0; i<*num; i++) {
- if ((*uids)[i] == uid)
- return;
- }
-
- *uids = Realloc(*uids, (*num+1) * sizeof(uid_t));
-
- if (*uids == NULL)
- return;
-
- (*uids)[*num] = uid;
- *num += 1;
-}
-
-
-static BOOL get_memberuids(gid_t gid, uid_t **uids, int *num)
+static BOOL get_memberuids(const DOM_SID *gsid, DOM_SID **sids, int *num)
{
+ SAM_ACCOUNT *sampw = NULL;
struct group *grp;
char **gr;
- struct sys_pwent *userlist, *user;
+ int i;
+ gid_t gid;

- *uids = NULL;
+ *sids = NULL;
*num = 0;

/* We only look at our own sam, so don't care about imported stuff */

winbind_off();

- if ((grp = getgrgid(gid)) == NULL) {
+ DEBUG(10, ("lookup on Domain SID\n"));
+
+ if (!NT_STATUS_IS_OK(sid_to_gid(gsid, &gid)) ||
+ !pdb_enum_group_prmembers(gsid, sids, num)) {
winbind_on();
return False;
}

- /* Primary group members */
-
- userlist = getpwent_list();
-
- for (user = userlist; user != NULL; user = user->next) {
- if (user->pw_gid != gid)
- continue;
- add_uid_to_array_unique(user->pw_uid, uids, num);
+ if ((grp = getgrgid(gid)) == NULL) {
+ SAFE_FREE(*sids);
+ *num = 0;
+ winbind_on();
+ return False;
}

- pwent_free(userlist);
-
/* Secondary group members */

+ pdb_init_sam(&sampw);
for (gr = grp->gr_mem; (*gr != NULL) && ((*gr)[0] != '\0'); gr += 1) {
- struct passwd *pw = getpwnam(*gr);

- if (pw == NULL)
+ if(!pdb_getsampwnam(sampw, *gr))
+ continue;
+
+ for (i=0; i<*num; i++) {
+ if (sid_compare(&((*sids)[i]), pdb_get_user_sid(sampw)) == 0)
+ break;
+ }
+
+ if(i<*num)
continue;
- add_uid_to_array_unique(pw->pw_uid, uids, num);
+
+ if(!add_sid_to_list(*(pdb_get_user_sid(sampw)), sids, num)) {
+ DEBUG(0,("get_memberuids: Unable to add user to the list!\n"));
+ SAFE_FREE(*sids);
+ *num = 0;
+ pdb_free_sam(&sampw);
+ winbind_on();
+ return False;
+ }
+
}
+ pdb_free_sam(&sampw);

winbind_on();

@@ -3314,9 +3313,8 @@
int final_num_rids, i;
DOM_SID group_sid;
fstring group_sid_str;
- uid_t *uids;
+ DOM_SID *sids;
int num;
- gid_t gid;

uint32 *rid=NULL;
uint32 *attr=NULL;
@@ -3339,37 +3337,27 @@
return NT_STATUS_NO_SUCH_GROUP;
}

- DEBUG(10, ("lookup on Domain SID\n"));
-
- if (!NT_STATUS_IS_OK(sid_to_gid(&group_sid, &gid)))
- return NT_STATUS_NO_SUCH_GROUP;
-
- if(!get_memberuids(gid, &uids, &num))
+ if(!get_memberuids(&group_sid, &sids, &num))
return NT_STATUS_NO_SUCH_GROUP;

rid=talloc_zero(p->mem_ctx, sizeof(uint32)*num);
attr=talloc_zero(p->mem_ctx, sizeof(uint32)*num);

- if (num!=0 && (rid==NULL || attr==NULL))
+ if (num!=0 && (rid==NULL || attr==NULL)) {
+ SAFE_FREE(sids);
return NT_STATUS_NO_MEMORY;
+ }

final_num_rids = 0;

for (i=0; i - DOM_SID sid;
-
- if (!NT_STATUS_IS_OK(uid_to_sid(&sid, uids[i]))) {
- DEBUG(1, ("Could not map member uid to SID\n"));
- continue;
- }
-
- if (!sid_check_is_in_our_domain(&sid)) {
+ if (!sid_check_is_in_our_domain(&(sids[i]))) {
DEBUG(1, ("Inconsistent SAM -- group member uid not "
"in our domain\n"));
continue;
}

- sid_peek_rid(&sid, &rid[final_num_rids]);
+ sid_peek_rid(&(sids[i]), &rid[final_num_rids]);

/* Hmm. In a trace I got the constant 7 here from NT. */
attr[final_num_rids] = SID_NAME_USER;
@@ -3377,7 +3365,7 @@
final_num_rids += 1;
}

- SAFE_FREE(uids);
+ SAFE_FREE(sids);

init_samr_r_query_groupmem(r_u, final_num_rids, rid, attr,
NT_STATUS_OK);
@@ -3918,7 +3906,6 @@
DOM_SID group_sid;
GROUP_MAP map;
DOM_SID *sids=NULL;
- uid_t *uids;
int num=0;
GROUP_INFO_CTR *ctr;
uint32 acc_granted;
@@ -3944,11 +3931,10 @@
switch (q_u->switch_level) {
case 1:
ctr->switch_value1 = 1;
- if(!get_memberuids(map.gid, &uids, &num))
+ if(!get_memberuids(&group_sid, &sids, &num))
return NT_STATUS_NO_SUCH_GROUP;
- SAFE_FREE(uids);
- init_samr_group_info1(&ctr->group.info1, map.nt_name, map.comment, num);
SAFE_FREE(sids);
+ init_samr_group_info1(&ctr->group.info1, map.nt_name, map.comment, num);
break;
case 3:
ctr->switch_value1 = 3;

--------------060704000708000507020604--