diff -u -u -r1.41 winbindd.h --- nsswitch/winbindd.h 28 Feb 2003 00:26:20 -0000 1.41 +++ nsswitch/winbindd.h 3 Apr 2003 11:55:20 -0000 @@ -87,6 +87,25 @@ DOM_SID *group_sid; } WINBIND_USERINFO; +#define ALIAS_CACHE_TIME 300 + +struct alias_cache { + TALLOC_CTX *mem_ctx; + + uint32 sequence_number; + time_t last_cache_time; + + struct acct_info *dom_aliases; + uint32 num_dom_aliases; + + struct alias_cache_info { + uint32 num_members; + DOM_SID **alias_sid_mem; + char **alias_names; + uint32 *alias_types; + } *per_alias; +}; + /* Structures to hold per domain information */ struct winbindd_domain { @@ -111,6 +130,8 @@ /* Linked list info */ struct winbindd_domain *prev, *next; + + struct alias_cache *alias_cache; }; /* per-domain methods. This is how LDAP vs RPC is selected Index: nsswitch/winbindd_group.c =================================================================== RCS file: /home/cvs/samba/source/nsswitch/winbindd_group.c,v retrieving revision 1.62 diff -u -u -r1.62 winbindd_group.c --- nsswitch/winbindd_group.c 26 Feb 2003 12:21:01 -0000 1.62 +++ nsswitch/winbindd_group.c 3 Apr 2003 11:55:21 -0000 @@ -75,12 +75,6 @@ *num_gr_mem = 0; - if (group_name_type != SID_NAME_DOM_GRP) { - DEBUG(1, ("SID %s in domain %s isn't a domain group\n", - sid_to_string(sid_string, group_sid), domain->name)); - goto done; - } - /* Lookup group members */ status = domain->methods->lookup_groupmem(domain, mem_ctx, group_sid, &num_names, &sid_mem, &names, &name_types); @@ -88,7 +82,7 @@ DEBUG(1, ("could not lookup membership for group rid %s in domain %s (error: %s)\n", sid_to_string(sid_string, group_sid), domain->name, nt_errstr(status))); - goto done; + num_names = 0; } DEBUG(10, ("looked up %d names\n", num_names)); @@ -454,7 +448,7 @@ /* get the domain local groups if we are a member of a native win2k domain */ - if ( domain->native_mode && domain->methods->enum_local_groups ) + if ( domain->methods->enum_local_groups ) { DEBUG(4,("get_sam_group_entries: Native Mode 2k domain; enumerating local groups as well\n")); Index: nsswitch/winbindd_rpc.c =================================================================== RCS file: /home/cvs/samba/source/nsswitch/winbindd_rpc.c,v retrieving revision 1.42 diff -u -u -r1.42 winbindd_rpc.c --- nsswitch/winbindd_rpc.c 3 Mar 2003 19:36:16 -0000 1.42 +++ nsswitch/winbindd_rpc.c 3 Apr 2003 11:55:22 -0000 @@ -27,6 +27,13 @@ #define DBGC_CLASS DBGC_WINBIND +static NTSTATUS lookup_aliasmem(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + DOM_SID *group_sid, uint32 *num_names, + DOM_SID ***sid_mem, char ***names, + uint32 **name_types); + + /* Query display info for a domain. This returns enough information plus a bit extra to give an overview of domain users for the User Manager application. */ @@ -413,10 +420,160 @@ return result; } + +/* initialise the alias cache for this domain */ +static NTSTATUS init_alias_cache(struct winbindd_domain *domain) +{ + CLI_POLICY_HND *hnd; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + POLICY_HND dom_pol; + uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; + uint32 idx = 0; + unsigned int retry; + BOOL got_dom_pol = False; + int i; + TALLOC_CTX *mem_ctx; + + if (domain->alias_cache) { + if (domain->alias_cache->sequence_number == domain->sequence_number) { + return NT_STATUS_OK; + } + /* fill the alias cache at most every 5 minutes */ + if (domain->alias_cache->last_cache_time + ALIAS_CACHE_TIME > time(NULL)) { + return NT_STATUS_OK; + } + talloc_destroy(domain->alias_cache->mem_ctx); + domain->alias_cache = NULL; + } + + mem_ctx = talloc_init("init_alias_cache(%s)", domain->name); + + do { + /* 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); + } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); + + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + domain->alias_cache = (struct alias_cache *)talloc(mem_ctx, sizeof(struct alias_cache)); + domain->alias_cache->mem_ctx = mem_ctx; + domain->alias_cache->last_cache_time = time(NULL); + domain->alias_cache->sequence_number = domain->sequence_number; + + + got_dom_pol = True; + + domain->alias_cache->last_cache_time = time(NULL); + + result = cli_samr_enum_als_groups(hnd->cli, mem_ctx, + &dom_pol, &idx, + 0xffff, + &domain->alias_cache->dom_aliases, + &domain->alias_cache->num_dom_aliases); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + domain->alias_cache->per_alias = + (struct alias_cache_info *)talloc(mem_ctx, + domain->alias_cache->num_dom_aliases * + sizeof(struct alias_cache_info)); + if (!domain->alias_cache->per_alias) { + goto done; + } + + + for (i=0;ialias_cache->num_dom_aliases;i++) { + NTSTATUS status; + int j, k; + DOM_SID *alias_sid; + + alias_sid = rid_to_talloced_sid(domain, mem_ctx, domain->alias_cache->dom_aliases[i].rid); + + status = lookup_aliasmem(domain, mem_ctx, alias_sid, + &domain->alias_cache->per_alias[i].num_members, + &domain->alias_cache->per_alias[i].alias_sid_mem, + &domain->alias_cache->per_alias[i].alias_names, + &domain->alias_cache->per_alias[i].alias_types); + if (!NT_STATUS_IS_OK(status)) { + continue; + } + } + + done: + /* Clean up policy handles */ + if (got_dom_pol) + cli_samr_close(hnd->cli, mem_ctx, &dom_pol); + + if (!NT_STATUS_IS_OK(result)) { + talloc_destroy(domain->alias_cache->mem_ctx); + domain->alias_cache = NULL; + } + + return result; +} + + +/* add any local groups that the user should be a member of */ +static NTSTATUS add_local_groups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 n_groups, DOM_GID *user_groups, + uint32 *groups_out, DOM_SID ***gids_out) +{ + int i; + + init_alias_cache(domain); + if (!domain->alias_cache) { + return NT_STATUS_UNSUCCESSFUL; + } + + for (i=0;ialias_cache->num_dom_aliases;i++) { + int j, k; + DOM_SID *alias_sid; + + alias_sid = rid_to_talloced_sid(domain, mem_ctx, domain->alias_cache->dom_aliases[i].rid); + + for (j=0;jalias_cache->per_alias[i].num_members;j++) { + uint32 alias_rid; + if (domain->alias_cache->per_alias[i].alias_types[j] != SID_NAME_DOM_GRP) { + continue; + } + if (!sid_peek_check_rid(&domain->sid, + domain->alias_cache->per_alias[i].alias_sid_mem[j], + &alias_rid)) { + continue; + } + for (k=0;ksid, user_sid, mem_ctx, num_groups); - if((*num_groups > 0) && *user_gids) { - return NT_STATUS_OK; - } else { - *user_gids = NULL; - *num_groups = 0; - } + *user_gids = NULL; + *num_groups = 0; retry = 0; do { @@ -475,21 +629,38 @@ /* Query user rids */ result = cli_samr_query_usergroups(hnd->cli, mem_ctx, &user_pol, - num_groups, &user_groups); + &n_groups, &user_groups); - if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0) + if (!NT_STATUS_IS_OK(result)) goto done; - (*user_gids) = talloc(mem_ctx, sizeof(uint32) * (*num_groups)); + n_aliases = 0; + + init_dom_sid2(&sid2, user_sid); + + result = cli_samr_query_useraliases(hnd->cli, mem_ctx, &dom_pol, 1, &sid2, + &n_aliases, &alias_rids); + + /* ignore errors from this */ + + (*num_groups) = n_groups + n_aliases; + + (*user_gids) = talloc(mem_ctx, sizeof(DOM_SID *) * (*num_groups)); if (!(*user_gids)) { result = NT_STATUS_NO_MEMORY; goto done; } - for (i=0;i<(*num_groups);i++) { + for (i=0;iname, + sid_to_string(sid_string, group_sid))); + + if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) { + goto done; + } + + *num_names = 0; + + retry = 0; + do { + /* 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); + } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + got_dom_pol = True; + + /* Get alias handle */ + result = cli_samr_open_alias(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_aliasmem(hnd->cli, mem_ctx, + &group_pol, num_names, &sids); + + + DEBUG(0,("query aliasmem -> %s\n", nt_errstr(result))); + + 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_zero(mem_ctx, *num_names * sizeof(char *)); + *name_types = talloc_zero(mem_ctx, *num_names * sizeof(uint32)); + *sid_mem = talloc_zero(mem_ctx, *num_names * sizeof(DOM_SID *)); + + if (!*names || !*name_types) { + result = NT_STATUS_NO_MEMORY; + goto done; + } + + for (i = 0; i < *num_names; i++) { + enum SID_NAME_USE ntype; + NTSTATUS status; + + status = sid_to_name(domain, mem_ctx, + &sids[i], &(*names)[total_names], &ntype); + if (NT_STATUS_IS_OK(status)) { + (*name_types)[total_names] = ntype; + (*sid_mem)[total_names] = &sids[i]; + total_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; +} + + /* Lookup group membership given a rid. */ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -551,8 +830,11 @@ 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; + if (!NT_STATUS_IS_OK(result)) { + result = lookup_aliasmem(domain, mem_ctx, group_sid, num_names, + sid_mem, names, name_types); + goto done; + } got_group_pol = True; @@ -612,11 +894,16 @@ memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) * tmp_num_names); - + total_names += tmp_num_names; } *num_names = total_names; + + for (i=0;inum_sids)) + if(!prs_uint32("num_sids1 ", ps, depth, &r_u->num_sids1)) return False; if(!prs_uint32("ptr", ps, depth, &r_u->ptr)) return False; if (r_u->ptr != 0) { - SMB_ASSERT_ARRAY(ptr_sid, r_u->num_sids); + SMB_ASSERT_ARRAY(ptr_sid, r_u->num_sids1); - if (r_u->num_sids != 0) { - if(!prs_uint32("num_sids1", ps, depth, &r_u->num_sids1)) + if (r_u->num_sids1 != 0) { + if(!prs_uint32("num_sids", ps, depth, &r_u->num_sids)) return False; - for (i = 0; i < r_u->num_sids1; i++) { + for (i = 0; i < r_u->num_sids; i++) { ptr_sid[i] = 1; if(!prs_uint32("ptr_sid", ps, depth, &ptr_sid[i])) return False; } if (UNMARSHALLING(ps)) { - r_u->sid = talloc(ps->mem_ctx, r_u->num_sids1 * sizeof(DOM_SID)); + r_u->sid = talloc(ps->mem_ctx, r_u->num_sids * sizeof(DOM_SID2)); } - for (i = 0; i < r_u->num_sids1; i++) { + for (i = 0; i < r_u->num_sids; i++) { if (ptr_sid[i] != 0) { if(!smb_io_dom_sid2("sid", &r_u->sid[i], ps, depth)) return False; Index: rpc_server/srv_reg_nt.c =================================================================== RCS file: /home/cvs/samba/source/rpc_server/srv_reg_nt.c,v retrieving revision 1.39 diff -u -u -r1.39 srv_reg_nt.c --- rpc_server/srv_reg_nt.c 21 Jan 2003 03:42:38 -0000 1.39 +++ rpc_server/srv_reg_nt.c 3 Apr 2003 11:55:25 -0000 @@ -396,7 +396,9 @@ value_ascii = REG_PT_SERVERNT; break; case ROLE_DOMAIN_MEMBER: - value_ascii = REG_PT_WINNT; + /* hack! this forced other DCs to show the local + groups in the ACL editor. (tridge) */ + value_ascii = REG_PT_LANMANNT; break; } value_length = push_ucs2(value, value, value_ascii, Index: smbd/posix_acls.c =================================================================== RCS file: /home/cvs/samba/source/smbd/posix_acls.c,v retrieving revision 1.77 diff -u -u -r1.77 posix_acls.c --- smbd/posix_acls.c 7 Mar 2003 19:46:51 -0000 1.77 +++ smbd/posix_acls.c 3 Apr 2003 11:55:27 -0000 @@ -1003,12 +1003,12 @@ if (nt4_compatible_acls()) psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY; - } else if (sid_to_uid( ¤t_ace->trustee, ¤t_ace->unix_ug.uid, &sid_type)) { - current_ace->owner_type = UID_ACE; - current_ace->type = SMB_ACL_USER; } else if (sid_to_gid( ¤t_ace->trustee, ¤t_ace->unix_ug.gid, &sid_type)) { current_ace->owner_type = GID_ACE; current_ace->type = SMB_ACL_GROUP; + } else if (sid_to_uid( ¤t_ace->trustee, ¤t_ace->unix_ug.uid, &sid_type)) { + current_ace->owner_type = UID_ACE; + current_ace->type = SMB_ACL_USER; } else { fstring str; @@ -2464,6 +2464,12 @@ DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); sd_size = 0; } else { +#if 0 + /* + tridge: I have disabled this to allow recursive ACL application using + explorer from win2k workstations + */ + /* * Windows 2000: The DACL_PROTECTED flag in the security * descriptor marks the ACL as non-inheriting, i.e., no @@ -2474,6 +2480,7 @@ * flag doesn't seem to bother Windows NT. */ (*ppdesc)->type |= SE_DESC_DACL_PROTECTED; +#endif } done: