diff options
-rw-r--r-- | source3/nsswitch/winbindd.c | 2 | ||||
-rw-r--r-- | source3/nsswitch/winbindd.h | 3 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_ads.c | 46 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cache.c | 25 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cm.c | 80 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_group.c | 17 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_passdb.c | 60 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_rpc.c | 21 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_sid.c | 8 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_user.c | 2 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_util.c | 104 |
11 files changed, 239 insertions, 129 deletions
diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index 283b2e4a89..a98bd29406 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/nsswitch/winbindd.c @@ -880,6 +880,8 @@ int main(int argc, char **argv) if (!idmap_init(lp_idmap_backend())) return 1; + generate_wellknown_sids(); + /* Unblock all signals we are interested in as they may have been blocked by the parent process. */ diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h index 5c05a1b045..e884ea8380 100644 --- a/source3/nsswitch/winbindd.h +++ b/source3/nsswitch/winbindd.h @@ -94,6 +94,7 @@ struct winbindd_domain { fstring name; /* Domain name */ fstring alt_name; /* alt Domain name (if any) */ DOM_SID sid; /* SID for this domain */ + BOOL initialized; /* Did we already ask for the domain mode? */ BOOL native_mode; /* is this a win2k domain in native mode ? */ BOOL active_directory; /* is this a win2k active directory ? */ BOOL primary; /* is this our primary domain ? */ @@ -149,6 +150,7 @@ struct winbindd_methods { /* convert one user or group name to a sid */ NTSTATUS (*name_to_sid)(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + const char *domain_name, const char *name, DOM_SID *sid, enum SID_NAME_USE *type); @@ -157,6 +159,7 @@ struct winbindd_methods { NTSTATUS (*sid_to_name)(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *sid, + char **domain_name, char **name, enum SID_NAME_USE *type); diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index cd8b8e0e24..2d3a9e760c 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -323,48 +323,6 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain, return NT_STATUS_OK; } -/* convert a single name to a sid in a domain */ -static NTSTATUS name_to_sid(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - const char *name, - DOM_SID *sid, - enum SID_NAME_USE *type) -{ - ADS_STRUCT *ads; - - DEBUG(3,("ads: name_to_sid\n")); - - ads = ads_cached_connection(domain); - - if (!ads) { - domain->last_status = NT_STATUS_SERVER_DISABLED; - return NT_STATUS_UNSUCCESSFUL; - } - - return ads_name_to_sid(ads, name, sid, type); -} - -/* convert a sid to a user or group name */ -static NTSTATUS sid_to_name(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - const DOM_SID *sid, - char **name, - enum SID_NAME_USE *type) -{ - ADS_STRUCT *ads = NULL; - DEBUG(3,("ads: sid_to_name\n")); - - ads = ads_cached_connection(domain); - - if (!ads) { - domain->last_status = NT_STATUS_SERVER_DISABLED; - return NT_STATUS_UNSUCCESSFUL; - } - - return ads_sid_to_name(ads, mem_ctx, sid, name, type); -} - - /* convert a DN to a name, SID and name type this might become a major speed bottleneck if groups have lots of users, in which case we could cache the results @@ -1004,8 +962,8 @@ struct winbindd_methods ads_methods = { query_user_list, enum_dom_groups, enum_local_groups, - name_to_sid, - sid_to_name, + msrpc_name_to_sid, + msrpc_sid_to_name, query_user, lookup_usergroups, lookup_groupmem, diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index 43a0f9cf39..e10fa2255c 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -595,7 +595,7 @@ static void centry_end(struct cache_entry *centry, const char *format, ...) } static void wcache_save_name_to_sid(struct winbindd_domain *domain, - NTSTATUS status, + NTSTATUS status, const char *domain_name, const char *name, const DOM_SID *sid, enum SID_NAME_USE type) { @@ -610,13 +610,13 @@ static void wcache_save_name_to_sid(struct winbindd_domain *domain, centry_put_sid(centry, sid); fstrcpy(uname, name); strupper_m(uname); - centry_end(centry, "NS/%s/%s", domain->name, uname); + centry_end(centry, "NS/%s/%s", domain_name, uname); DEBUG(10,("wcache_save_name_to_sid: %s -> %s\n", uname, sid_string)); centry_free(centry); } static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS status, - const DOM_SID *sid, const char *name, enum SID_NAME_USE type) + const DOM_SID *sid, const char *domain_name, const char *name, enum SID_NAME_USE type) { struct cache_entry *centry; fstring sid_string; @@ -626,6 +626,7 @@ static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS sta return; if (NT_STATUS_IS_OK(status)) { centry_put_uint32(centry, type); + centry_put_string(centry, domain_name); centry_put_string(centry, name); } centry_end(centry, "SN/%s", sid_to_string(sid_string, sid)); @@ -743,10 +744,12 @@ do_query: /* when the backend is consistent we can pre-prime some mappings */ wcache_save_name_to_sid(domain, NT_STATUS_OK, (*info)[i].acct_name, + domain->name, (*info)[i].user_sid, SID_NAME_USER); wcache_save_sid_to_name(domain, NT_STATUS_OK, (*info)[i].user_sid, + domain->name, (*info)[i].acct_name, SID_NAME_USER); wcache_save_user(domain, NT_STATUS_OK, &(*info)[i]); @@ -918,6 +921,7 @@ skip_save: /* convert a single name to a sid in a domain */ static NTSTATUS name_to_sid(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + const char *domain_name, const char *name, DOM_SID *sid, enum SID_NAME_USE *type) @@ -933,7 +937,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, fstrcpy(uname, name); strupper_m(uname); - centry = wcache_fetch(cache, domain, "NS/%s/%s", domain->name, uname); + centry = wcache_fetch(cache, domain, "NS/%s/%s", domain_name, uname); if (!centry) goto do_query; *type = (enum SID_NAME_USE)centry_uint32(centry); @@ -969,10 +973,10 @@ do_query: DEBUG(10,("name_to_sid: [Cached] - doing backend query for name for domain %s\n", domain->name )); - status = domain->backend->name_to_sid(domain, mem_ctx, name, sid, type); + status = domain->backend->name_to_sid(domain, mem_ctx, domain_name, name, sid, type); /* and save it */ - wcache_save_name_to_sid(domain, status, name, sid, *type); + wcache_save_name_to_sid(domain, status, domain_name, name, sid, *type); /* We can't save the sid to name mapping as we don't know the correct case of the name without looking it up */ @@ -985,6 +989,7 @@ do_query: static NTSTATUS sid_to_name(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *sid, + char **domain_name, char **name, enum SID_NAME_USE *type) { @@ -1001,6 +1006,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, goto do_query; if (NT_STATUS_IS_OK(centry->status)) { *type = (enum SID_NAME_USE)centry_uint32(centry); + *domain_name = centry_string(centry, mem_ctx); *name = centry_string(centry, mem_ctx); } status = centry->status; @@ -1013,6 +1019,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, do_query: *name = NULL; + *domain_name = NULL; /* If the seq number check indicated that there is a problem * with this DC, then return that status... except for @@ -1028,12 +1035,12 @@ do_query: DEBUG(10,("sid_to_name: [Cached] - doing backend query for name for domain %s\n", domain->name )); - status = domain->backend->sid_to_name(domain, mem_ctx, sid, name, type); + status = domain->backend->sid_to_name(domain, mem_ctx, sid, domain_name, name, type); /* and save it */ refresh_sequence_number(domain, False); - wcache_save_sid_to_name(domain, status, sid, *name, *type); - wcache_save_name_to_sid(domain, status, *name, sid, *type); + wcache_save_sid_to_name(domain, status, sid, *domain_name, *name, *type); + wcache_save_name_to_sid(domain, status, *domain_name, *name, sid, *type); return status; } diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index 56810f221e..eda962088d 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -77,6 +77,9 @@ struct winbindd_cm_conn { static struct winbindd_cm_conn *cm_conns = NULL; +static NTSTATUS get_connection_from_cache(struct winbindd_domain *domain, + const char *pipe_name, + struct winbindd_cm_conn **conn_out); /* Choose between anonymous or authenticated connections. We need to use an authenticated connection if DCs have the RestrictAnonymous registry @@ -133,6 +136,53 @@ static NTSTATUS setup_schannel(struct cli_state *cli) return ret; } +static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain, + fstring dcname, struct in_addr *dc_ip) +{ + struct winbindd_domain *our_domain; + NTSTATUS result; + struct winbindd_cm_conn *conn; + TALLOC_CTX *mem_ctx; + + fstring tmp; + char *p; + + if (IS_DC) + return False; + + if (domain->primary) + return False; + + if ((our_domain = find_our_domain()) == NULL) + return False; + + result = get_connection_from_cache(our_domain, PIPE_NETLOGON, &conn); + if (!NT_STATUS_IS_OK(result)) + return False; + + if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) + return False; + + result = cli_netlogon_getdcname(conn->cli, mem_ctx, domain->name, tmp); + + talloc_destroy(mem_ctx); + + if (!NT_STATUS_IS_OK(result)) + return False; + + /* cli_netlogon_getdcname gives us a name with \\ */ + p = tmp; + if (*p == '\\') p+=1; + if (*p == '\\') p+=1; + + fstrcpy(dcname, p); + + if (!resolve_name(dcname, dc_ip, 0x20)) + return False; + + return True; +} + /* Open a connction to the remote server, cache failures for 30 seconds */ static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const int pipe_index, @@ -148,15 +198,19 @@ static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const i ZERO_STRUCT(dc_ip); fstrcpy(new_conn->domain, domain->name); - - /* connection failure cache has been moved inside of get_dc_name - so we can deal with half dead DC's --jerry */ - if (!get_dc_name(domain->name, domain->alt_name[0] ? domain->alt_name : NULL, - new_conn->controller, &dc_ip)) { - result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; - add_failed_connection_entry(domain->name, "", result); - return result; + if (!get_dc_name_via_netlogon(domain, new_conn->controller, &dc_ip)) { + + /* connection failure cache has been moved inside of + get_dc_name so we can deal with half dead DC's --jerry */ + + if (!get_dc_name(domain->name, domain->alt_name[0] ? + domain->alt_name : NULL, + new_conn->controller, &dc_ip)) { + result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; + add_failed_connection_entry(domain->name, "", result); + return result; + } } /* Initialise SMB connection */ @@ -282,7 +336,7 @@ static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const i failed. This allows existing setups to continue working, while solving the win2003 '100 user' limit for systems that are joined properly */ - if (NT_STATUS_IS_OK(result)) { + if (NT_STATUS_IS_OK(result) && (domain->primary)) { NTSTATUS status = setup_schannel(new_conn->cli); if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("schannel refused - continuing without schannel (%s)\n", @@ -461,10 +515,16 @@ void set_dc_type_and_flags( struct winbindd_domain *domain ) domain->native_mode = False; domain->active_directory = False; + + if (domain->internal) { + domain->initialized = True; + return; + } if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) { DEBUG(5, ("set_dc_type_and_flags: Could not open a connection to %s for PIPE_LSARPC (%s)\n", domain->name, nt_errstr(result))); + domain->initialized = True; return; } @@ -551,6 +611,8 @@ done: cli_shutdown( conn.cli ); talloc_destroy(mem_ctx); + + domain->initialized = True; return; } diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index 8f5306321a..ec77d2db34 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/nsswitch/winbindd_group.c @@ -292,7 +292,7 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state) /* Get rid and name type from name */ - if (!winbindd_lookup_sid_by_name(domain, name_group, &group_sid, + if (!winbindd_lookup_sid_by_name(domain, domain->name, name_group, &group_sid, &name_type)) { DEBUG(1, ("group %s in domain %s does not exist\n", name_group, name_domain)); @@ -446,17 +446,16 @@ enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state) for (domain = domain_list(); domain != NULL; domain = domain->next) { struct getent_state *domain_state; - + /* Create a state record for this domain */ + /* don't add our domaina if we are a PDC or if we are a member of a Samba domain */ - if ( (IS_DC || lp_winbind_trusted_domains_only()) - && domain->primary ) + if ( lp_winbind_trusted_domains_only() && domain->primary ) { continue; } - /* Create a state record for this domain */ if ((domain_state = (struct getent_state *) malloc(sizeof(struct getent_state))) == NULL) { @@ -945,12 +944,10 @@ static void add_gids_from_sid(DOM_SID *sid, gid_t **gids, int *num) if (NT_STATUS_IS_OK(idmap_sid_to_gid(sid, &gid, 0))) add_gid_to_array_unique(gid, gids, num); - /* Don't expand aliases if not explicitly activated -- for now */ - /* we don't support windows local nested groups if we are a DC. - refer to to sid_to_gid() in the smbd server code to see why + /* Don't expand aliases if not explicitly activated -- for now -- jerry */ - if (!lp_winbind_nested_groups() || IS_DC) + if (!lp_winbind_nested_groups()) return; /* Add nested group memberships */ @@ -1021,7 +1018,7 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) /* Get rid and name type from name. The following costs 1 packet */ - if (!winbindd_lookup_sid_by_name(domain, name_user, &user_sid, + if (!winbindd_lookup_sid_by_name(domain, domain->name, name_user, &user_sid, &name_type)) { DEBUG(1, ("user '%s' does not exist\n", name_user)); goto done; diff --git a/source3/nsswitch/winbindd_passdb.c b/source3/nsswitch/winbindd_passdb.c index 36f5297efe..12f5e0bae2 100644 --- a/source3/nsswitch/winbindd_passdb.c +++ b/source3/nsswitch/winbindd_passdb.c @@ -52,6 +52,7 @@ add_expanded_sid(const DOM_SID *sid, char **members, int *num_members) struct winbindd_domain *domain; int i; + char *domain_name = NULL; char *name = NULL; enum SID_NAME_USE type; @@ -72,7 +73,7 @@ add_expanded_sid(const DOM_SID *sid, char **members, int *num_members) sid_copy(&dom_sid, sid); sid_split_rid(&dom_sid, &rid); - domain = find_domain_from_sid(&dom_sid); + domain = find_lookup_domain_from_sid(sid); if (domain == NULL) { DEBUG(3, ("Could not find domain for sid %s\n", @@ -81,7 +82,7 @@ add_expanded_sid(const DOM_SID *sid, char **members, int *num_members) } result = domain->methods->sid_to_name(domain, mem_ctx, sid, - &name, &type); + &domain_name, &name, &type); if (!NT_STATUS_IS_OK(result)) { DEBUG(3, ("sid_to_name failed for sid %s\n", @@ -92,7 +93,7 @@ add_expanded_sid(const DOM_SID *sid, char **members, int *num_members) DEBUG(10, ("Found name %s, type %d\n", name, type)); if (type == SID_NAME_USER) { - add_member(domain->name, name, members, num_members); + add_member(domain_name, name, members, num_members); goto done; } @@ -102,7 +103,15 @@ add_expanded_sid(const DOM_SID *sid, char **members, int *num_members) goto done; } - /* Expand the domain group */ + /* Expand the domain group, this must be done via the target domain */ + + domain = find_domain_from_sid(sid); + + if (domain == NULL) { + DEBUG(3, ("Could not find domain from SID %s\n", + sid_string_static(sid))); + goto done; + } result = domain->methods->lookup_groupmem(domain, mem_ctx, sid, &num_names, @@ -221,6 +230,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain, /* convert a single name to a sid in a domain */ static NTSTATUS name_to_sid(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + const char *domain_name, const char *name, DOM_SID *sid, enum SID_NAME_USE *type) @@ -240,6 +250,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, static NTSTATUS sid_to_name(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *sid, + char **domain_name, char **name, enum SID_NAME_USE *type) { @@ -250,6 +261,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, if (!pdb_get_aliasinfo(sid, &info)) return NT_STATUS_NONE_MAPPED; + *domain_name = talloc_strdup(mem_ctx, domain->name); *name = talloc_strdup(mem_ctx, info.acct_name); *type = SID_NAME_ALIAS; @@ -300,7 +312,45 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, char ***alt_names, DOM_SID **dom_sids) { - return NT_STATUS_OK; + NTSTATUS nt_status; + int enum_ctx = 0; + int num_sec_domains; + TRUSTDOM **domains; + *num_domains = 0; + *names = NULL; + *alt_names = NULL; + *dom_sids = NULL; + do { + int i; + nt_status = secrets_get_trusted_domains(mem_ctx, &enum_ctx, 1, + &num_sec_domains, + &domains); + *names = talloc_realloc(mem_ctx, *names, + sizeof(*names) * + (num_sec_domains + *num_domains)); + *alt_names = talloc_realloc(mem_ctx, *alt_names, + sizeof(*alt_names) * + (num_sec_domains + *num_domains)); + *dom_sids = talloc_realloc(mem_ctx, *dom_sids, + sizeof(**dom_sids) * + (num_sec_domains + *num_domains)); + + for (i=0; i< num_sec_domains; i++) { + if (pull_ucs2_talloc(mem_ctx, &(*names)[*num_domains], + domains[i]->name) == -1) { + return NT_STATUS_NO_MEMORY; + } + (*alt_names)[*num_domains] = NULL; + (*dom_sids)[*num_domains] = domains[i]->sid; + (*num_domains)++; + } + + } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES)); + + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MORE_ENTRIES)) { + return NT_STATUS_OK; + } + return nt_status; } /* find the domain sid for a domain */ diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c index 25d5f64df6..7668844920 100644 --- a/source3/nsswitch/winbindd_rpc.c +++ b/source3/nsswitch/winbindd_rpc.c @@ -274,8 +274,9 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain, } /* convert a single name to a sid in a domain */ -static NTSTATUS name_to_sid(struct winbindd_domain *domain, +NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + const char *domain_name, const char *name, DOM_SID *sid, enum SID_NAME_USE *type) @@ -289,14 +290,14 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, DEBUG(3,("rpc: name_to_sid name=%s\n", name)); - full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain->name, name); + full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name); if (!full_name) { DEBUG(0, ("talloc_asprintf failed!\n")); return NT_STATUS_NO_MEMORY; } - DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", name, domain->name )); + DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", name, domain_name )); retry = 0; do { @@ -322,9 +323,10 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, /* convert a domain SID to a user or group name */ -static NTSTATUS sid_to_name(struct winbindd_domain *domain, +NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *sid, + char **domain_name, char **name, enum SID_NAME_USE *type) { @@ -350,14 +352,9 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, if (NT_STATUS_IS_OK(result)) { *type = (enum SID_NAME_USE)types[0]; + *domain_name = domains[0]; *name = names[0]; DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name)); - - /* Paranoia */ - if (!strequal(domain->name, domains[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; - } } return result; @@ -995,8 +992,8 @@ struct winbindd_methods msrpc_methods = { query_user_list, enum_dom_groups, enum_local_groups, - name_to_sid, - sid_to_name, + msrpc_name_to_sid, + msrpc_sid_to_name, query_user, lookup_usergroups, lookup_groupmem, diff --git a/source3/nsswitch/winbindd_sid.c b/source3/nsswitch/winbindd_sid.c index d4206558c5..61da9b3d92 100644 --- a/source3/nsswitch/winbindd_sid.c +++ b/source3/nsswitch/winbindd_sid.c @@ -95,14 +95,14 @@ enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state) DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid, name_domain, lp_winbind_separator(), name_user)); - if ((domain = find_domain_from_name(name_domain)) == NULL) { + if ((domain = find_lookup_domain_from_name(name_domain)) == NULL) { DEBUG(0, ("could not find domain entry for domain %s\n", name_domain)); return WINBINDD_ERROR; } /* Lookup name from PDC using lsa_lookup_names() */ - if (!winbindd_lookup_sid_by_name(domain, name_user, &sid, &type)) { + if (!winbindd_lookup_sid_by_name(domain, name_domain, name_user, &sid, &type)) { return WINBINDD_ERROR; } @@ -335,7 +335,7 @@ enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state) return WINBINDD_ERROR; } - if ( !winbindd_lookup_sid_by_name(domain, pw->pw_name, &sid, &type) ) + if ( !winbindd_lookup_sid_by_name(domain, domain->name, pw->pw_name, &sid, &type) ) return WINBINDD_ERROR; if ( type != SID_NAME_USER ) @@ -405,7 +405,7 @@ enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state) return WINBINDD_ERROR; } - if ( !winbindd_lookup_sid_by_name(domain, grp->gr_name, &sid, &type) ) + if ( !winbindd_lookup_sid_by_name(domain, domain->name, grp->gr_name, &sid, &type) ) return WINBINDD_ERROR; if ( type!=SID_NAME_DOM_GRP && type!=SID_NAME_ALIAS ) diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index d08377c888..d10fd5664b 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/nsswitch/winbindd_user.c @@ -153,7 +153,7 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state) /* Get rid and name type from name */ - if (!winbindd_lookup_sid_by_name(domain, name_user, &user_sid, &name_type)) { + if (!winbindd_lookup_sid_by_name(domain, domain->name, name_user, &user_sid, &name_type)) { DEBUG(1, ("user '%s' does not exist\n", name_user)); return WINBINDD_ERROR; } diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index 7e3fd99dac..96b8ed8c93 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -85,13 +85,15 @@ void free_domain_list(void) static BOOL is_internal_domain(const DOM_SID *sid) { - DOM_SID tmp_sid; + extern DOM_SID global_sid_Builtin; - if (sid_equal(sid, get_global_sam_sid())) + if (sid == NULL) + return False; + + if (sid_compare_domain(sid, get_global_sam_sid()) == 0) return True; - string_to_sid(&tmp_sid, "S-1-5-32"); - if (sid_equal(sid, &tmp_sid)) + if (sid_compare_domain(sid, &global_sid_Builtin) == 0) return True; return False; @@ -160,15 +162,11 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const domain->internal = is_internal_domain(sid); domain->sequence_number = DOM_SEQUENCE_NONE; domain->last_seq_check = 0; + domain->initialized = False; if (sid) { sid_copy(&domain->sid, sid); } - /* set flags about native_mode, active_directory */ - - if (!domain->internal) - set_dc_type_and_flags( domain ); - DEBUG(3,("add_trusted_domain: %s is an %s %s domain\n", domain->name, domain->active_directory ? "ADS" : "NT4", domain->native_mode ? "native mode" : @@ -190,6 +188,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const static void add_trusted_domains( struct winbindd_domain *domain ) { + extern struct winbindd_methods cache_methods; TALLOC_CTX *mem_ctx; NTSTATUS result; time_t t; @@ -226,7 +225,7 @@ static void add_trusted_domains( struct winbindd_domain *domain ) for(i = 0; i < num_domains; i++) { DEBUG(10,("Found domain %s\n", names[i])); add_trusted_domain(names[i], alt_names?alt_names[i]:NULL, - domain->methods, &dom_sids[i]); + &cache_methods, &dom_sids[i]); /* if the SID was empty, we better set it now */ @@ -290,16 +289,28 @@ void rescan_trusted_domains( void ) /* Look up global info for the winbind daemon */ BOOL init_domain_list(void) { + extern DOM_SID global_sid_Builtin; extern struct winbindd_methods cache_methods; + extern struct winbindd_methods passdb_methods; struct winbindd_domain *domain; /* Free existing list */ free_domain_list(); /* Add ourselves as the first entry. */ + + if (IS_DC) { + domain = add_trusted_domain(get_global_sam_name(), NULL, + &passdb_methods, get_global_sam_sid()); + } else { - domain = add_trusted_domain( lp_workgroup(), lp_realm(), &cache_methods, NULL); + domain = add_trusted_domain( lp_workgroup(), lp_realm(), + &cache_methods, NULL); + /* set flags about native_mode, active_directory */ + set_dc_type_and_flags(domain); + } + domain->primary = True; /* get any alternate name for the primary domain */ @@ -320,27 +331,15 @@ BOOL init_domain_list(void) /* do an initial scan for trusted domains */ add_trusted_domains(domain); - /* Don't expand aliases if not explicitly activated -- for now */ - /* we don't support windows local nested groups if we are a DC. - refer to to sid_to_gid() in the smbd server code to see why - -- jerry */ - - if (lp_winbind_nested_groups() || IS_DC) { + /* Add our local SAM domains */ - /* Add our local SAM domains */ - DOM_SID sid; - extern struct winbindd_methods passdb_methods; - struct winbindd_domain *dom; + add_trusted_domain("BUILTIN", NULL, &passdb_methods, + &global_sid_Builtin); - string_to_sid(&sid, "S-1-5-32"); - - dom = add_trusted_domain("BUILTIN", NULL, &passdb_methods, - &sid); - - dom = add_trusted_domain(get_global_sam_name(), NULL, - &passdb_methods, - get_global_sam_sid()); + if (!IS_DC) { + add_trusted_domain(get_global_sam_name(), NULL, + &passdb_methods, get_global_sam_sid()); } /* avoid rescanning this right away */ @@ -369,6 +368,9 @@ struct winbindd_domain *find_domain_from_name(const char *domain_name) for (domain = domain_list(); domain != NULL; domain = domain->next) { if (strequal(domain_name, domain->name) || (domain->alt_name[0] && strequal(domain_name, domain->alt_name))) { + if (!domain->initialized) + set_dc_type_and_flags(domain); + return domain; } } @@ -387,8 +389,11 @@ struct winbindd_domain *find_domain_from_sid(const DOM_SID *sid) /* Search through list */ for (domain = domain_list(); domain != NULL; domain = domain->next) { - if (sid_compare_domain(sid, &domain->sid) == 0) + if (sid_compare_domain(sid, &domain->sid) == 0) { + if (!domain->initialized) + set_dc_type_and_flags(domain); return domain; + } } /* Not found */ @@ -414,21 +419,49 @@ struct winbindd_domain *find_our_domain(void) return NULL; } +/* Find the appropriate domain to lookup a name or SID */ + +struct winbindd_domain *find_lookup_domain_from_sid(const DOM_SID *sid) +{ + /* A DC can't ask the local smbd for remote SIDs, here winbindd is the + * one to contact the external DC's. On member servers the internal + * domains are different: These are part of the local SAM. */ + + if (IS_DC || is_internal_domain(sid)) + return find_domain_from_sid(sid); + + /* On a member server a query for SID or name can always go to our + * primary DC. */ + + return find_our_domain(); +} + +struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name) +{ + if (IS_DC || strequal(domain_name, "BUILTIN") || + strequal(domain_name, get_global_sam_name())) + return find_domain_from_name(domain_name); + + return find_our_domain(); +} + /* Lookup a sid in a domain from a name */ BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain, + const char *domain_name, const char *name, DOM_SID *sid, enum SID_NAME_USE *type) { NTSTATUS result; TALLOC_CTX *mem_ctx; - mem_ctx = talloc_init("lookup_sid_by_name for %s\n", name); + mem_ctx = talloc_init("lookup_sid_by_name for %s\\%s\n", + domain_name, name); if (!mem_ctx) return False; /* Lookup name */ - result = domain->methods->name_to_sid(domain, mem_ctx, name, sid, type); + result = domain->methods->name_to_sid(domain, mem_ctx, domain_name, name, sid, type); talloc_destroy(mem_ctx); @@ -457,12 +490,13 @@ BOOL winbindd_lookup_name_by_sid(DOM_SID *sid, enum SID_NAME_USE *type) { char *names; + char *dom_names; NTSTATUS result; TALLOC_CTX *mem_ctx; BOOL rv = False; struct winbindd_domain *domain; - domain = find_domain_from_sid(sid); + domain = find_lookup_domain_from_sid(sid); if (!domain) { DEBUG(1,("Can't find domain from sid\n")); @@ -474,12 +508,12 @@ BOOL winbindd_lookup_name_by_sid(DOM_SID *sid, if (!(mem_ctx = talloc_init("winbindd_lookup_name_by_sid"))) return False; - result = domain->methods->sid_to_name(domain, mem_ctx, sid, &names, type); + result = domain->methods->sid_to_name(domain, mem_ctx, sid, &dom_names, &names, type); /* Return name and type if successful */ if ((rv = NT_STATUS_IS_OK(result))) { - fstrcpy(dom_name, domain->name); + fstrcpy(dom_name, dom_names); fstrcpy(name, names); } else { *type = SID_NAME_UNKNOWN; |