diff options
Diffstat (limited to 'source3/winbindd')
-rw-r--r-- | source3/winbindd/winbindd.c | 4 | ||||
-rw-r--r-- | source3/winbindd/winbindd_cm.c | 47 | ||||
-rw-r--r-- | source3/winbindd/winbindd_dual.c | 91 | ||||
-rw-r--r-- | source3/winbindd/winbindd_ndr.c | 153 | ||||
-rw-r--r-- | source3/winbindd/winbindd_util.c | 53 |
5 files changed, 318 insertions, 30 deletions
diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 5e9900d1d6..615f4a918e 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1227,6 +1227,10 @@ int main(int argc, char **argv, char **envp) MSG_WINBIND_VALIDATE_CACHE, winbind_msg_validate_cache); + messaging_register(winbind_messaging_context(), NULL, + MSG_WINBIND_DUMP_DOMAIN_LIST, + winbind_msg_dump_domain_list); + netsamlogon_cache_init(); /* Non-critical */ /* clear the cached list of trusted domains */ diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index dbc664da8c..94910072c3 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -679,8 +679,22 @@ static NTSTATUS get_trust_creds(const struct winbindd_domain *domain, char **machine_krb5_principal) { const char *account_name; + const char *name = NULL; + + /* If we are a DC and this is not our own domain */ - if (!get_trust_pw_clear(domain->name, machine_password, + if (IS_DC) { + name = domain->name; + } else { + struct winbindd_domain *our_domain = find_our_domain(); + + if (!our_domain) + return NT_STATUS_INVALID_SERVER_STATE; + + name = our_domain->name; + } + + if (!get_trust_pw_clear(name, machine_password, &account_name, NULL)) { return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; @@ -1805,17 +1819,17 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain ) static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) { NTSTATUS result; - DS_DOMINFO_CTR ctr; + WERROR werr; TALLOC_CTX *mem_ctx = NULL; struct rpc_pipe_client *cli; POLICY_HND pol; + union dssetup_DsRoleInfo info; const char *domain_name = NULL; const char *dns_name = NULL; const char *forest_name = NULL; DOM_SID *dom_sid = NULL; - ZERO_STRUCT( ctr ); if (!connection_ok(domain)) { return; @@ -1830,24 +1844,25 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name )); - cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS, + cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_DSSETUP, &result); if (cli == NULL) { DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to " - "PI_LSARPC_DS on domain %s: (%s)\n", + "PI_DSSETUP on domain %s: (%s)\n", domain->name, nt_errstr(result))); /* if this is just a non-AD domain we need to continue * identifying so that we can in the end return with * domain->initialized = True - gd */ - goto no_lsarpc_ds; + goto no_dssetup; } - result = rpccli_ds_getprimarydominfo(cli, mem_ctx, - DsRolePrimaryDomainInfoBasic, - &ctr); + result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx, + DS_ROLE_BASIC_INFORMATION, + &info, + &werr); cli_rpc_pipe_close(cli); if (!NT_STATUS_IS_OK(result)) { @@ -1856,26 +1871,26 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) domain->name, nt_errstr(result))); /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for - * every opcode on the LSARPC_DS pipe, continue with - * no_lsarpc_ds mode here as well to get domain->initialized + * every opcode on the DSSETUP pipe, continue with + * no_dssetup mode here as well to get domain->initialized * set - gd */ if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) { - goto no_lsarpc_ds; + goto no_dssetup; } TALLOC_FREE(mem_ctx); return; } - - if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) && - !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) { + + if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) && + !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) { domain->native_mode = True; } else { domain->native_mode = False; } -no_lsarpc_ds: +no_dssetup: cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result); if (cli == NULL) { diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index e21524689b..15ca564c6a 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -676,6 +676,88 @@ void winbind_msg_dump_event_list(struct messaging_context *msg_ctx, } +void winbind_msg_dump_domain_list(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + TALLOC_CTX *mem_ctx; + const char *message = NULL; + struct server_id *sender = NULL; + const char *domain = NULL; + char *s = NULL; + NTSTATUS status; + struct winbindd_domain *dom = NULL; + + DEBUG(5,("winbind_msg_dump_domain_list received.\n")); + + if (!data || !data->data) { + return; + } + + if (data->length < sizeof(struct server_id)) { + return; + } + + mem_ctx = talloc_init("winbind_msg_dump_domain_list"); + if (!mem_ctx) { + return; + } + + sender = (struct server_id *)data->data; + if (data->length > sizeof(struct server_id)) { + domain = (const char *)data->data+sizeof(struct server_id); + } + + if (domain) { + + DEBUG(5,("winbind_msg_dump_domain_list for domain: %s\n", + domain)); + + message = NDR_PRINT_STRUCT_STRING(mem_ctx, winbindd_domain, + find_domain_from_name_noinit(domain)); + if (!message) { + talloc_destroy(mem_ctx); + return; + } + + messaging_send_buf(msg_ctx, *sender, + MSG_WINBIND_DUMP_DOMAIN_LIST, + (uint8_t *)message, strlen(message) + 1); + + talloc_destroy(mem_ctx); + + return; + } + + DEBUG(5,("winbind_msg_dump_domain_list all domains\n")); + + for (dom = domain_list(); dom; dom=dom->next) { + message = NDR_PRINT_STRUCT_STRING(mem_ctx, winbindd_domain, dom); + if (!message) { + talloc_destroy(mem_ctx); + return; + } + + s = talloc_asprintf_append(s, "%s\n", message); + if (!s) { + talloc_destroy(mem_ctx); + return; + } + } + + status = messaging_send_buf(msg_ctx, *sender, + MSG_WINBIND_DUMP_DOMAIN_LIST, + (uint8_t *)s, strlen(s) + 1); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("failed to send message: %s\n", + nt_errstr(status))); + } + + talloc_destroy(mem_ctx); +} + static void account_lockout_policy_handler(struct event_context *ctx, struct timed_event *te, const struct timeval *now, @@ -877,6 +959,13 @@ static bool fork_domain_child(struct winbindd_child *child) struct winbindd_cli_state state; struct winbindd_domain *domain; + if (child->domain) { + DEBUG(10, ("fork_domain_child called for domain '%s'\n", + child->domain->name)); + } else { + DEBUG(10, ("fork_domain_child called without domain.\n")); + } + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) != 0) { DEBUG(0, ("Could not open child pipe: %s\n", strerror(errno))); @@ -946,6 +1035,8 @@ static bool fork_domain_child(struct winbindd_child *child) MSG_WINBIND_ONLINESTATUS, NULL); messaging_deregister(winbind_messaging_context(), MSG_DUMP_EVENT_LIST, NULL); + messaging_deregister(winbind_messaging_context(), + MSG_WINBIND_DUMP_DOMAIN_LIST, NULL); /* Handle online/offline messages. */ messaging_register(winbind_messaging_context(), NULL, diff --git a/source3/winbindd/winbindd_ndr.c b/source3/winbindd/winbindd_ndr.c new file mode 100644 index 0000000000..842c915c5f --- /dev/null +++ b/source3/winbindd/winbindd_ndr.c @@ -0,0 +1,153 @@ +/* + * Unix SMB/CIFS implementation. + * winbindd debug helper + * Copyright (C) Guenther Deschner 2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +/**************************************************************** +****************************************************************/ + +void ndr_print_winbindd_child(struct ndr_print *ndr, + const char *name, + const struct winbindd_child *r) +{ + ndr_print_struct(ndr, name, "winbindd_child"); + ndr->depth++; + ndr_print_ptr(ndr, "next", r->next); + ndr_print_ptr(ndr, "prev", r->prev); + ndr_print_uint32(ndr, "pid", (uint32_t)r->pid); +#if 0 + ndr_print_winbindd_domain(ndr, "domain", r->domain); +#else + ndr_print_ptr(ndr, "domain", r->domain); +#endif + ndr_print_string(ndr, "logfilename", r->logfilename); + /* struct fd_event event; */ + ndr_print_ptr(ndr, "lockout_policy_event", r->lockout_policy_event); + ndr_print_ptr(ndr, "requests", r->requests); + ndr_print_ptr(ndr, "table", r->table); + ndr->depth--; +} + +/**************************************************************** +****************************************************************/ + +void ndr_print_winbindd_cm_conn(struct ndr_print *ndr, + const char *name, + const struct winbindd_cm_conn *r) +{ + ndr_print_struct(ndr, name, "winbindd_cm_conn"); + ndr->depth++; + ndr_print_ptr(ndr, "cli", r->cli); + ndr_print_ptr(ndr, "samr_pipe", r->samr_pipe); + ndr_print_policy_handle(ndr, "sam_connect_handle", &r->sam_connect_handle); + ndr_print_policy_handle(ndr, "sam_domain_handle", &r->sam_domain_handle); + ndr_print_ptr(ndr, "lsa_pipe", r->lsa_pipe); + ndr_print_policy_handle(ndr, "lsa_policy", &r->lsa_policy); + ndr_print_ptr(ndr, "netlogon_pipe", r->netlogon_pipe); + ndr->depth--; +} + +/**************************************************************** +****************************************************************/ + +void ndr_print_winbindd_methods(struct ndr_print *ndr, + const char *name, + const struct winbindd_methods *r) +{ +#ifdef HAVE_ADS + extern struct winbindd_methods ads_methods; +#endif + extern struct winbindd_methods msrpc_methods; + extern struct winbindd_methods passdb_methods; + extern struct winbindd_methods reconnect_methods; + extern struct winbindd_methods cache_methods; + + ndr_print_struct(ndr, name, "winbindd_methods"); + ndr->depth++; + + if (r == NULL) { + ndr_print_string(ndr, name, "(NULL)"); + ndr->depth--; + return; + } + + if (r == &msrpc_methods) { + ndr_print_string(ndr, name, "msrpc_methods"); +#ifdef HAVE_ADS + } else if (r == &ads_methods) { + ndr_print_string(ndr, name, "ads_methods"); +#endif + } else if (r == &passdb_methods) { + ndr_print_string(ndr, name, "passdb_methods"); + } else if (r == &reconnect_methods) { + ndr_print_string(ndr, name, "reconnect_methods"); + } else if (r == &cache_methods) { + ndr_print_string(ndr, name, "cache_methods"); + } else { + ndr_print_string(ndr, name, "UNKNOWN"); + } + ndr->depth--; +} + +/**************************************************************** +****************************************************************/ + +void ndr_print_winbindd_domain(struct ndr_print *ndr, + const char *name, + const struct winbindd_domain *r) +{ + if (!r) { + return; + } + + ndr_print_struct(ndr, name, "winbindd_domain"); + ndr->depth++; + ndr_print_string(ndr, "name", r->name); + ndr_print_string(ndr, "alt_name", r->alt_name); + ndr_print_string(ndr, "forest_name", r->forest_name); + ndr_print_dom_sid(ndr, "sid", &r->sid); + ndr_print_netr_TrustFlags(ndr, "domain_flags", r->domain_flags); + ndr_print_netr_TrustType(ndr, "domain_type", r->domain_type); + ndr_print_netr_TrustAttributes(ndr, "domain_trust_attribs", r->domain_trust_attribs); + ndr_print_bool(ndr, "initialized", r->initialized); + ndr_print_bool(ndr, "native_mode", r->native_mode); + ndr_print_bool(ndr, "active_directory", r->active_directory); + ndr_print_bool(ndr, "primary", r->primary); + ndr_print_bool(ndr, "internal", r->internal); + ndr_print_bool(ndr, "online", r->online); + ndr_print_time_t(ndr, "startup_time", r->startup_time); + ndr_print_bool(ndr, "startup", r->startup); + ndr_print_winbindd_methods(ndr, "methods", r->methods); + ndr_print_winbindd_methods(ndr, "backend", r->backend); + ndr_print_ptr(ndr, "private_data", r->private_data); + ndr_print_string(ndr, "dcname", r->dcname); + ndr_print_sockaddr_storage(ndr, "dcaddr", &r->dcaddr); + ndr_print_time_t(ndr, "last_seq_check", r->last_seq_check); + ndr_print_uint32(ndr, "sequence_number", r->sequence_number); + ndr_print_NTSTATUS(ndr, "last_status", r->last_status); + ndr_print_winbindd_cm_conn(ndr, "conn", &r->conn); + ndr_print_winbindd_child(ndr, "child", &r->child); + ndr_print_uint32(ndr, "check_online_timeout", r->check_online_timeout); + ndr_print_ptr(ndr, "check_online_event", r->check_online_event); + ndr->depth--; +} diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 0381053331..f6bb5750ea 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -571,7 +571,7 @@ enum winbindd_result init_child_connection(struct winbindd_domain *domain, /* The primary domain has to find the DC name itself */ request->cmd = WINBINDD_INIT_CONNECTION; fstrcpy(request->domain_name, domain->name); - request->data.init_conn.is_primary = domain->internal ? False : True; + request->data.init_conn.is_primary = domain->primary ? true : false; fstrcpy(request->data.init_conn.dcname, ""); async_request(mem_ctx, &domain->child, request, response, init_child_recv, state); @@ -1386,31 +1386,56 @@ void ws_name_return( char *name, char replace ) /********************************************************************* ********************************************************************/ -bool winbindd_can_contact_domain( struct winbindd_domain *domain ) +bool winbindd_can_contact_domain(struct winbindd_domain *domain) { + struct winbindd_tdc_domain *tdc = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + bool ret = false; + /* We can contact the domain if it is our primary domain */ - if ( domain->primary ) - return True; + if (domain->primary) { + return true; + } - /* Can always contact a domain that is in out forest */ + /* Trust the TDC cache and not the winbindd_domain flags */ - if ( domain->domain_flags & DS_DOMAIN_IN_FOREST ) - return True; + if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) { + DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n", + domain->name)); + return false; + } - /* We cannot contact the domain if it is running AD and - we have no inbound trust */ + /* Can always contact a domain that is in out forest */ - if ( domain->active_directory && - ((domain->domain_flags&DS_DOMAIN_DIRECT_INBOUND) != DS_DOMAIN_DIRECT_INBOUND) ) - { - return False; + if (tdc->trust_flags & DS_DOMAIN_IN_FOREST) { + ret = true; + goto done; } + /* + * On a _member_ server, we cannot contact the domain if it + * is running AD and we have no inbound trust. + */ + + if (!IS_DC && + domain->active_directory && + ((tdc->trust_flags&DS_DOMAIN_DIRECT_INBOUND) != DS_DOMAIN_DIRECT_INBOUND)) + { + DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain " + "and we have no inbound trust.\n", domain->name)); + goto done; + } + /* Assume everything else is ok (probably not true but what can you do?) */ + + ret = true; + +done: + talloc_destroy(frame); - return True; + return ret; } /********************************************************************* |