summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/nsswitch/winbindd_group.c129
1 files changed, 120 insertions, 9 deletions
diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c
index 676bf918b4..79d8e2970e 100644
--- a/source3/nsswitch/winbindd_group.c
+++ b/source3/nsswitch/winbindd_group.c
@@ -57,6 +57,7 @@ static BOOL fill_grent(struct winbindd_gr *gr, const char *dom_name,
/* Fill in the group membership field of a NT group given by group_sid */
static BOOL fill_grent_mem(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state,
DOM_SID *group_sid,
enum lsa_SidType group_name_type,
size_t *num_gr_mem, char **gr_mem, size_t *gr_mem_len)
@@ -64,11 +65,12 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
DOM_SID *sid_mem = NULL;
uint32 num_names = 0;
uint32 *name_types = NULL;
- unsigned int buf_len, buf_ndx, i;
- char **names = NULL, *buf;
+ unsigned int buf_len = 0, buf_ndx = 0, i;
+ char **names = NULL, *buf = NULL;
BOOL result = False;
TALLOC_CTX *mem_ctx;
NTSTATUS status;
+ uint32 group_rid;
fstring sid_string;
if (!(mem_ctx = talloc_init("fill_grent_mem(%s)", domain->name)))
@@ -98,13 +100,124 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
goto done;
}
+ /* OPTIMIZATION / HACK. */
+ /* If "enum users" is set to false, and the group being looked
+ up is the Domain Users SID: S-1-5-domain-513, then for the
+ list of members check if the querying user is in that group,
+ and if so only return that user as the gr_mem array.
+ We can change this to a different parameter than "enum users"
+ if neccessaey, or parameterize the group list we do this for. */
+
+ sid_peek_rid( group_sid, &group_rid );
+ if (!lp_winbind_enum_users() && group_rid == DOMAIN_GROUP_RID_USERS) {
+ DOM_SID querying_user_sid;
+ DOM_SID *pquerying_user_sid = NULL;
+ uint32 num_groups = 0;
+ DOM_SID *user_sids = NULL;
+ BOOL u_in_group = False;
+
+ DEBUG(10,("fill_grent_mem: optimized lookup for sid %s domain %s\n",
+ sid_to_string(sid_string, group_sid), domain->name ));
+
+ if (state) {
+ uid_t ret_uid = (uid_t)-1;
+ if (sys_getpeereid(state->sock, &ret_uid)==0) {
+ /* We know who's asking - look up their SID if
+ it's one we've mapped before. */
+ status = idmap_uid_to_sid(&querying_user_sid,
+ ret_uid,
+ IDMAP_FLAG_QUERY_ONLY|IDMAP_FLAG_CACHE_ONLY);
+ if (NT_STATUS_IS_OK(status)) {
+ pquerying_user_sid = &querying_user_sid;
+ DEBUG(10,("fill_grent_mem: querying uid %u -> %s\n",
+ (unsigned int)ret_uid,
+ sid_to_string(sid_string, pquerying_user_sid) ));
+ }
+ }
+ }
+
+ /* Only look up if it was a winbindd user in this domain. */
+ if (pquerying_user_sid &&
+ (sid_compare_domain(pquerying_user_sid, &domain->sid) == 0)) {
+
+ DEBUG(10,("fill_grent_mem: querying user = %s\n",
+ sid_to_string(sid_string, pquerying_user_sid) ));
+
+ status = domain->methods->lookup_usergroups(domain,
+ mem_ctx,
+ pquerying_user_sid,
+ &num_groups,
+ &user_sids);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("fill_grent_mem: lookup_usergroups failed "
+ "for sid %s in domain %s (error: %s)\n",
+ sid_to_string(sid_string, pquerying_user_sid),
+ domain->name,
+ nt_errstr(status)));
+ goto done;
+ }
+
+ for (i = 0; i < num_groups; i++) {
+ if (sid_equal(group_sid, &user_sids[i])) {
+ /* User is in Domain Users, add their name
+ as the only group member. */
+ u_in_group = True;
+ break;
+ }
+ }
+ }
+
+ if (u_in_group) {
+ size_t len = 0;
+ char *domainname = NULL;
+ char *username = NULL;
+ fstring name;
+ enum lsa_SidType type;
+
+ DEBUG(10,("fill_grent_mem: sid %s in 'Domain Users' in domain %s\n",
+ sid_to_string(sid_string, pquerying_user_sid), domain->name ));
+
+ status = domain->methods->sid_to_name(domain, mem_ctx,
+ pquerying_user_sid,
+ &domainname,
+ &username,
+ &type);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("could not lookup username for user "
+ "sid %s in domain %s (error: %s)\n",
+ sid_to_string(sid_string, pquerying_user_sid),
+ domain->name,
+ nt_errstr(status)));
+ goto done;
+ }
+ fill_domain_username(name, domain->name, username, True);
+ len = strlen(name);
+ buf_len = len + 1;
+ if (!(buf = (char *)SMB_MALLOC(buf_len))) {
+ DEBUG(1, ("out of memory\n"));
+ goto done;
+ }
+ memcpy(buf, name, buf_len);
+
+ DEBUG(10,("fill_grent_mem: user %s in 'Domain Users' in domain %s\n",
+ name, domain->name ));
+ }
+
+ *gr_mem = buf;
+ *gr_mem_len = buf_len;
+
+ DEBUG(10, ("num_mem = %u, len = %u, mem = %s\n", (unsigned int)*num_gr_mem,
+ (unsigned int)buf_len, *num_gr_mem ? buf : "NULL"));
+ result = True;
+ goto done;
+ }
+
/* Lookup group members */
status = domain->methods->lookup_groupmem(domain, mem_ctx, group_sid, &num_names,
&sid_mem, &names, &name_types);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("could not lookup membership for group rid %s in domain %s (error: %s)\n",
+ DEBUG(1, ("could not lookup membership for group sid %s in domain %s (error: %s)\n",
sid_to_string(sid_string, group_sid), domain->name, nt_errstr(status)));
-
goto done;
}
@@ -119,9 +232,6 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
/* Add members to list */
- buf = NULL;
- buf_len = buf_ndx = 0;
-
again:
for (i = 0; i < num_names; i++) {
@@ -311,7 +421,7 @@ void winbindd_getgrnam(struct winbindd_cli_state *state)
if (!fill_grent(&state->response.data.gr, name_domain,
name_group, gid) ||
- !fill_grent_mem(domain, &group_sid, name_type,
+ !fill_grent_mem(domain, state, &group_sid, name_type,
&num_gr_mem,
&gr_mem, &gr_mem_len)) {
request_error(state);
@@ -370,7 +480,7 @@ static void getgrgid_got_sid(struct winbindd_cli_state *state, DOM_SID group_sid
if (!fill_grent(&state->response.data.gr, dom_name, group_name,
state->request.data.gid) ||
- !fill_grent_mem(domain, &group_sid, name_type,
+ !fill_grent_mem(domain, state, &group_sid, name_type,
&num_gr_mem,
&gr_mem, &gr_mem_len)) {
request_error(state);
@@ -802,6 +912,7 @@ void winbindd_getgrent(struct winbindd_cli_state *state)
sid_append_rid(&member_sid, name_list[ent->sam_entry_index].rid);
result = fill_grent_mem(
domain,
+ NULL,
&member_sid,
SID_NAME_DOM_GRP,
&num_gr_mem,