Index: Makefile.in =================================================================== RCS file: /home/cvs/samba/source/Makefile.in,v retrieving revision 1.468.2.184 diff -u -u -r1.468.2.184 Makefile.in --- Makefile.in 6 Oct 2003 16:31:38 -0000 1.468.2.184 +++ Makefile.in 9 Oct 2003 04:55:59 -0000 @@ -706,6 +706,11 @@ -o $@ @BROKEN_CC@ -mv `echo $@ | sed 's%^.*/%%g'` $@ +# this adds support for precompiled headers. To use it, install a snapshot +# of gcc-3.4 and run 'make pch' before you do the main build. +pch: + $(CC) -I. -I$(srcdir) $(FLAGS) -c $(srcdir)/include/includes.h -o $(srcdir)/include/includes.h.gch + # These dependencies are only approximately correct: we want to make # sure Samba's paths are updated if ./configure is re-run. Really it # would be nice if "make prefix=/opt/samba all" also rebuilt things, Index: nsswitch/winbindd.h =================================================================== RCS file: /home/cvs/samba/source/nsswitch/winbindd.h,v retrieving revision 1.33.2.14 diff -u -u -r1.33.2.14 winbindd.h --- nsswitch/winbindd.h 1 Aug 2003 15:28:36 -0000 1.33.2.14 +++ nsswitch/winbindd.h 9 Oct 2003 04:56:00 -0000 @@ -89,6 +89,25 @@ DOM_SID *group_sid; } WINBIND_USERINFO; + +#define ALIAS_CACHE_TIME 3600 + +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; + } *per_alias; +}; + + /* Structures to hold per domain information */ struct winbindd_domain { @@ -117,6 +136,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.51.2.25 diff -u -u -r1.51.2.25 winbindd_group.c --- nsswitch/winbindd_group.c 10 Aug 2003 22:01:11 -0000 1.51.2.25 +++ nsswitch/winbindd_group.c 9 Oct 2003 04:56:01 -0000 @@ -105,7 +105,7 @@ *num_gr_mem = 0; if ( !((group_name_type==SID_NAME_DOM_GRP) || - ((group_name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) ) + ((group_name_type==SID_NAME_ALIAS)))) { DEBUG(1, ("SID %s in domain %s isn't a domain group (%d)\n", sid_to_string(sid_string, group_sid), domain->name, @@ -165,7 +165,16 @@ /* Append domain name */ - fill_domain_username(name, domain->name, the_name); + if (sid_compare_domain(&domain->sid, sid_mem[i]) == 0) { + fill_domain_username(name, domain->name, the_name); + } else { + struct winbindd_domain *dom2 = find_domain_from_sid(sid_mem[i]); + if (!dom2) { + DEBUG(5, ("Unknown foreign SID %s\n", sid_string_static(sid_mem[i]))); + continue; + } + fill_domain_username(name, dom2->name, the_name); + } len = strlen(name); @@ -291,7 +300,7 @@ } if ( !((name_type==SID_NAME_DOM_GRP) || - ((name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) ) + ((name_type==SID_NAME_ALIAS)))) { DEBUG(1, ("name '%s' is not a local or domain group: %d\n", name_group, name_type)); @@ -382,7 +391,7 @@ } if ( !((name_type==SID_NAME_DOM_GRP) || - ((name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) ) + ((name_type==SID_NAME_ALIAS)))) { DEBUG(1, ("name '%s' is not a local or domain group: %d\n", group_name, name_type)); @@ -546,7 +555,7 @@ and are not using LDAP to get the groups */ if ( lp_security() != SEC_ADS && domain->native_mode - && strequal(lp_workgroup(), domain->name) ) + /* && strequal(lp_workgroup(), domain->name) */ ) { DEBUG(4,("get_sam_group_entries: Native Mode 2k domain; enumerating local groups as well\n")); @@ -969,7 +978,7 @@ /* Treat the info3 cache as authoritative as the lookup_usergroups() function may return cached data. */ - if ((info3 = netsamlogon_cache_get(mem_ctx, &user_sid))) { + if (0 && (info3 = netsamlogon_cache_get(mem_ctx, &user_sid))) { DEBUG(10, ("winbindd_getgroups: info3 has %d groups, %d other sids\n", info3->num_groups2, info3->num_other_sids)); Index: nsswitch/winbindd_rpc.c =================================================================== RCS file: /home/cvs/samba/source/nsswitch/winbindd_rpc.c,v retrieving revision 1.25.2.17 diff -u -u -r1.25.2.17 winbindd_rpc.c --- nsswitch/winbindd_rpc.c 15 Aug 2003 04:42:04 -0000 1.25.2.17 +++ nsswitch/winbindd_rpc.c 9 Oct 2003 04:56:02 -0000 @@ -26,6 +26,12 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND +/* Lookup sids in an alias given an alias sid */ +static NTSTATUS lookup_alias_sids(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + DOM_SID *group_sid, uint32 *num_names, + DOM_SID **sids); + /* 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 @@ -335,11 +341,13 @@ *name = names[0]; DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name)); +#if 0 /* Paranoia */ if (strcasecmp(domain->name, domains[0]) != 0) { DEBUG(1, ("domain name from domain param and PDC lookup return differ! (%s vs %s)\n", domain->name, domains[0])); return NT_STATUS_UNSUCCESSFUL; } +#endif } return result; @@ -368,7 +376,7 @@ /* try netsamlogon cache first */ - if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) + if ( 0 && (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) { DEBUG(5,("query_user: Cache lookup succeeded for %s\n", @@ -444,6 +452,194 @@ 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"); + + do { + /* Get sam handle */ + + if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd))) { + talloc_destroy(mem_ctx); + 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); + + domain->alias_cache->num_dom_aliases = 0; + domain->alias_cache->dom_aliases = NULL; + + do { + struct acct_info *dom_aliases; + uint32 num_dom_aliases; + TALLOC_CTX *mem_ctx2; + + mem_ctx2 = talloc_init("init_alias_cache temp"); + + result = cli_samr_enum_als_groups(hnd->cli, mem_ctx2, + &dom_pol, &idx, + 0xffff, + &dom_aliases, + &num_dom_aliases); + + if (!NT_STATUS_IS_ERR(result)) { + domain->alias_cache->dom_aliases = talloc_realloc(mem_ctx, + domain->alias_cache->dom_aliases, + sizeof(struct acct_info) * + (domain->alias_cache->num_dom_aliases + + num_dom_aliases)); + memcpy(domain->alias_cache->dom_aliases + domain->alias_cache->num_dom_aliases, + dom_aliases, + num_dom_aliases * sizeof(struct acct_info)); + domain->alias_cache->num_dom_aliases += num_dom_aliases; + } + talloc_destroy(mem_ctx2); + } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); + + 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; + + status = lookup_alias_sids(domain, mem_ctx, + rid_to_talloced_sid(domain, mem_ctx, + domain->alias_cache->dom_aliases[i].rid), + &domain->alias_cache->per_alias[i].num_members, + &domain->alias_cache->per_alias[i].alias_sid_mem); + 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) && domain->alias_cache) { + 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 void add_local_groups(TALLOC_CTX *mem_ctx, DOM_SID *user_sid, + uint32 n_groups, DOM_GID *user_groups, + uint32 *groups_out, DOM_SID ***sids_out) +{ + int i; + struct winbindd_domain *dom; + DOM_SID user_dom; + + sid_copy(&user_dom, user_sid); + user_dom.num_auths--; + + for (dom=domain_list(); dom; dom=dom->next) { + init_alias_cache(dom); + if (!dom->alias_cache) { + continue; + } + + for (i=0;ialias_cache->num_dom_aliases;i++) { + int j, k; + struct alias_cache_info *alias = &dom->alias_cache->per_alias[i]; + BOOL added = False; + + for (j=0;!added && jnum_members;j++) { + uint32 alias_rid; + BOOL add_alias = False; + + if (sid_compare(user_sid, &alias->alias_sid_mem[j]) == 0) { + add_alias = True; + } + + + sid_peek_rid(&alias->alias_sid_mem[j], &alias_rid); + + if (!add_alias && + sid_compare_domain(&user_dom, + &alias->alias_sid_mem[j]) == 0) { + for (k=0;kalias_cache->dom_aliases[i].rid); + (*groups_out)++; + added = True; + } + } + } + } +} + + /* Lookup groups a user is a member of. I wish Unix had a call like this! */ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -456,7 +652,7 @@ uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; BOOL got_dom_pol = False, got_user_pol = False; DOM_GID *user_groups; - unsigned int i; + unsigned int i, n_groups; unsigned int retry; fstring sid_string; uint32 user_rid; @@ -469,7 +665,7 @@ /* so lets see if we have a cached user_info_3 */ - if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) + if (0 && (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) { DEBUG(5,("query_user: Cache lookup succeeded for %s\n", sid_string_static(user_sid))); @@ -521,22 +717,26 @@ got_user_pol = True; - /* Query user rids */ + /* Query user group 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_grpsids) = talloc(mem_ctx, sizeof(DOM_SID*) * (*num_groups)); + (*user_grpsids) = talloc(mem_ctx, sizeof(DOM_SID*) * n_groups); if (!(*user_grpsids)) { result = NT_STATUS_NO_MEMORY; goto done; } - for (i=0;i<(*num_groups);i++) { + for (i=0;iname, sid_string_static(group_sid))); + + *num_names = 0; + + if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) { + goto done; + } + + retry = 0; + do { + /* Get sam handle */ + + if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd))) + 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; + + result = cli_samr_query_aliasmem(hnd->cli, mem_ctx, + &group_pol, num_names, sids); + + 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 alias membership given a rid. */ +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) +{ + NTSTATUS result; + uint32 i, total_names = 0; + DOM_SID *sids; + + + result = lookup_alias_sids(domain, mem_ctx, group_sid, num_names, &sids); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + if (*num_names == 0) { + goto done; + } + + *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: + return result; +} + + /* Lookup group membership given a rid. */ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -599,8 +912,12 @@ 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; Index: nsswitch/winbindd_util.c =================================================================== RCS file: /home/cvs/samba/source/nsswitch/winbindd_util.c,v retrieving revision 1.73.2.35 diff -u -u -r1.73.2.35 winbindd_util.c --- nsswitch/winbindd_util.c 22 Sep 2003 17:53:59 -0000 1.73.2.35 +++ nsswitch/winbindd_util.c 9 Oct 2003 04:56:03 -0000 @@ -137,6 +137,11 @@ contact_name = *domain->alt_name ? domain->alt_name : domain->name; domain->native_mode = cm_check_for_native_mode_win2k( contact_name ); + +#if 1 + DEBUG(1,("Forcing native mode\n")); + domain->native_mode = True; +#endif DEBUG(3,("add_trusted_domain: %s is a %s mode domain\n", contact_name, domain->native_mode ? "native" : "mixed (or NT4)" )); Index: rpc_client/cli_samr.c =================================================================== RCS file: /home/cvs/samba/source/rpc_client/cli_samr.c,v retrieving revision 1.68.2.12 diff -u -u -r1.68.2.12 cli_samr.c --- rpc_client/cli_samr.c 22 Sep 2003 17:53:59 -0000 1.68.2.12 +++ rpc_client/cli_samr.c 9 Oct 2003 04:56:04 -0000 @@ -865,7 +865,7 @@ *num_mem = r.num_sids; - if (!(*sids = talloc(mem_ctx, sizeof(DOM_SID) * *num_mem))) { + if (*num_mem && !(*sids = talloc(mem_ctx, sizeof(DOM_SID) * *num_mem))) { result = NT_STATUS_UNSUCCESSFUL; goto done; } Index: rpc_parse/parse_lsa.c =================================================================== RCS file: /home/cvs/samba/source/rpc_parse/parse_lsa.c,v retrieving revision 1.75.2.12 diff -u -u -r1.75.2.12 parse_lsa.c --- rpc_parse/parse_lsa.c 7 Oct 2003 05:06:58 -0000 1.75.2.12 +++ rpc_parse/parse_lsa.c 9 Oct 2003 04:56:05 -0000 @@ -1816,7 +1816,8 @@ r_u->ptr = 1; r_u->count = count; - if (!NT_STATUS_IS_OK(ret = init_priv_with_ctx(mem_ctx, &(r_u->set)))) + ret = init_priv_with_ctx(mem_ctx, &(r_u->set)); + if (!NT_STATUS_IS_OK(ret)) return ret; if (!NT_STATUS_IS_OK(ret = dupalloc_luid_attr(r_u->set->mem_ctx, &(r_u->set->set), set))) Index: rpc_server/srv_lsa_nt.c =================================================================== RCS file: /home/cvs/samba/source/rpc_server/srv_lsa_nt.c,v retrieving revision 1.52.2.16 diff -u -u -r1.52.2.16 srv_lsa_nt.c --- rpc_server/srv_lsa_nt.c 6 Oct 2003 01:38:46 -0000 1.52.2.16 +++ rpc_server/srv_lsa_nt.c 9 Oct 2003 04:56:06 -0000 @@ -558,11 +558,11 @@ return NT_STATUS_ACCESS_DENIED; /* Request PolicyPrimaryDomainInformation. */ - switch (lp_server_role()) { + switch (fake_server_role()) { case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: - name = get_global_sam_name(); - sid = get_global_sam_sid(); + name = fake_global_sam_name(); + sid = fake_global_sam_sid(); break; case ROLE_DOMAIN_MEMBER: name = lp_workgroup(); @@ -587,8 +587,8 @@ return NT_STATUS_ACCESS_DENIED; /* Request PolicyAccountDomainInformation. */ - name = get_global_sam_name(); - sid = get_global_sam_sid(); + name = fake_global_sam_name(); + sid = fake_global_sam_sid(); init_dom_query(&r_u->dom.id5, name, sid); break; case 0x06: @@ -596,7 +596,7 @@ if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION)) return NT_STATUS_ACCESS_DENIED; - switch (lp_server_role()) { + switch (fake_server_role()) { case ROLE_DOMAIN_BDC: /* * only a BDC is a backup controller @@ -1235,10 +1235,10 @@ return NT_STATUS_ACCESS_DENIED; /* Request PolicyPrimaryDomainInformation. */ - switch (lp_server_role()) { + switch (fake_server_role()) { case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: - nb_name = get_global_sam_name(); + nb_name = fake_global_sam_name(); /* ugly temp hack for these next two */ /* This should be a 'netbios domain -> DNS domain' mapping */ Index: rpc_server/srv_reg.c =================================================================== RCS file: /home/cvs/samba/source/rpc_server/srv_reg.c,v retrieving revision 1.35.2.8 diff -u -u -r1.35.2.8 srv_reg.c --- rpc_server/srv_reg.c 14 Aug 2003 21:14:27 -0000 1.35.2.8 +++ rpc_server/srv_reg.c 9 Oct 2003 04:56:06 -0000 @@ -400,3 +400,5 @@ return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "winreg", "winreg", api_reg_cmds, sizeof(api_reg_cmds) / sizeof(struct api_struct)); } + + Index: rpc_server/srv_reg_nt.c =================================================================== RCS file: /home/cvs/samba/source/rpc_server/srv_reg_nt.c,v retrieving revision 1.17.2.10 diff -u -u -r1.17.2.10 srv_reg_nt.c --- rpc_server/srv_reg_nt.c 23 Jul 2003 12:33:58 -0000 1.17.2.10 +++ rpc_server/srv_reg_nt.c 9 Oct 2003 04:56:06 -0000 @@ -387,7 +387,7 @@ /* which tells clients that we have our own local user and */ /* group databases and helps with ACL support. */ - switch (lp_server_role()) { + switch (fake_server_role()) { case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: value_ascii = REG_PT_LANMANNT; @@ -662,3 +662,24 @@ } + + +/* + this is a hack to force us to appear as a BDC for the purposes of local + group enumeration +*/ + +int fake_server_role(void) +{ + return ROLE_DOMAIN_BDC; +} + +const char *fake_global_sam_name(void) +{ + return lp_workgroup(); +} + +DOM_SID *fake_global_sam_sid(void) +{ + return get_global_sam_sid(); +} Index: rpc_server/srv_samr_nt.c =================================================================== RCS file: /home/cvs/samba/source/rpc_server/srv_samr_nt.c,v retrieving revision 1.86.2.47 diff -u -u -r1.86.2.47 srv_samr_nt.c --- rpc_server/srv_samr_nt.c 25 Sep 2003 21:26:16 -0000 1.86.2.47 +++ rpc_server/srv_samr_nt.c 9 Oct 2003 04:56:11 -0000 @@ -2597,7 +2597,7 @@ return r_u->status; } - name = get_global_sam_name(); + name = fake_global_sam_name(); fstrcpy(dom[0],name); strupper_m(dom[0]);