diff options
author | Andrew Bartlett <abartlet@samba.org> | 2014-05-26 11:58:38 +1200 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2014-07-04 02:52:35 +0200 |
commit | af7f88721a21fbe33cec2bc277f65a736f6cb9cc (patch) | |
tree | ae69c5d117289d1e77a51dbf787ba973ba86ef38 | |
parent | da3a79831afbd1b85592be36eb47de375e575643 (diff) | |
download | samba-af7f88721a21fbe33cec2bc277f65a736f6cb9cc.tar.gz samba-af7f88721a21fbe33cec2bc277f65a736f6cb9cc.tar.xz samba-af7f88721a21fbe33cec2bc277f65a736f6cb9cc.zip |
winbindd: Use a remote RPC server when we are an RODC when needed
This allows us to operate against the local cache where possible, but
to forward some operations to the read-write DC.
Andrew Bartlett
Change-Id: Idc78ae379a402969381758919fcede17568f094e
Pair-programmed-with: Garming Sam <garming@catalyst.net.nz>
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Signed-off-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Nadezhda Ivanova <nivanova@samba.org>
-rw-r--r-- | source3/winbindd/winbindd.h | 1 | ||||
-rw-r--r-- | source3/winbindd/winbindd_cache.c | 3 | ||||
-rw-r--r-- | source3/winbindd/winbindd_cm.c | 33 | ||||
-rw-r--r-- | source3/winbindd/winbindd_msrpc.c | 20 | ||||
-rw-r--r-- | source3/winbindd/winbindd_pam.c | 10 | ||||
-rw-r--r-- | source3/winbindd/winbindd_proto.h | 3 | ||||
-rw-r--r-- | source3/winbindd/winbindd_util.c | 37 |
7 files changed, 72 insertions, 35 deletions
diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index 07c87dbcf4..5b98928a25 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -164,6 +164,7 @@ struct winbindd_domain { bool active_directory; /* is this a win2k active directory ? */ bool primary; /* is this our primary domain ? */ bool internal; /* BUILTIN and member SAM */ + bool rodc; /* Are we an RODC for this AD domain? (do some operations locally) */ bool online; /* is this domain available ? */ time_t startup_time; /* When we set "startup" true. monotonic clock */ bool startup; /* are we in the first 30 seconds after startup_time ? */ diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index dfad8f5c08..bfd78daef5 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -132,7 +132,8 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain) } if ( !domain->initialized ) { - init_dc_connection( domain ); + /* We do not need a connection to an RW DC for cache operation */ + init_dc_connection(domain, false); } /* diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index a8ace52472..05205a7d48 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -94,7 +94,7 @@ struct dc_name_ip { extern struct winbindd_methods reconnect_methods; extern bool override_logfile; -static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain); +static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc); static void set_dc_type_and_flags( struct winbindd_domain *domain ); static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, struct dc_name_ip **dcs, int *num_dcs); @@ -176,7 +176,7 @@ static void msg_try_to_go_online(struct messaging_context *msg, the offline handler if false. Bypasses online check so always does network calls. */ - init_dc_connection_network(domain); + init_dc_connection_network(domain, true); break; } } @@ -1931,9 +1931,13 @@ static bool connection_ok(struct winbindd_domain *domain) /* Initialize a new connection up to the RPC BIND. Bypass online status check so always does network calls. */ -static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain) +static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc) { NTSTATUS result; + bool skip_connection = domain->internal; + if (need_rw_dc && domain->rodc) { + skip_connection = false; + } /* Internal connections never use the network. */ if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) { @@ -1941,7 +1945,7 @@ static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain) } /* Still ask the internal LSA and SAMR server about the local domain */ - if (domain->internal || connection_ok(domain)) { + if (skip_connection || connection_ok(domain)) { if (!domain->initialized) { set_dc_type_and_flags(domain); } @@ -1959,7 +1963,7 @@ static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain) return result; } -NTSTATUS init_dc_connection(struct winbindd_domain *domain) +NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc) { if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) { return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; @@ -1970,14 +1974,14 @@ NTSTATUS init_dc_connection(struct winbindd_domain *domain) return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; } - return init_dc_connection_network(domain); + return init_dc_connection_network(domain, need_rw_dc); } -static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain) +static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain, bool need_rw_dc) { NTSTATUS status; - status = init_dc_connection(domain); + status = init_dc_connection(domain, need_rw_dc); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -2382,6 +2386,7 @@ static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain, } NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + bool need_rw_dc, struct rpc_pipe_client **cli, struct policy_handle *sam_handle) { struct winbindd_cm_conn *conn; @@ -2392,10 +2397,12 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const char *domain_name = NULL; if (sid_check_is_our_sam(&domain->sid)) { - return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle); + if (domain->rodc == false || need_rw_dc == false) { + return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle); + } } - status = init_dc_connection_rpc(domain); + status = init_dc_connection_rpc(domain, need_rw_dc); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -2605,7 +2612,7 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain, DEBUG(10,("cm_connect_lsa_tcp\n")); - status = init_dc_connection_rpc(domain); + status = init_dc_connection_rpc(domain, false); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -2656,7 +2663,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; struct netlogon_creds_cli_context *p_creds; - result = init_dc_connection_rpc(domain); + result = init_dc_connection_rpc(domain, false); if (!NT_STATUS_IS_OK(result)) return result; @@ -2829,7 +2836,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, *cli = NULL; - result = init_dc_connection_rpc(domain); + result = init_dc_connection_rpc(domain, true); if (!NT_STATUS_IS_OK(result)) { return result; } diff --git a/source3/winbindd/winbindd_msrpc.c b/source3/winbindd/winbindd_msrpc.c index 426d64cf1f..9aef7ccdff 100644 --- a/source3/winbindd/winbindd_msrpc.c +++ b/source3/winbindd/winbindd_msrpc.c @@ -76,7 +76,7 @@ static NTSTATUS msrpc_query_user_list(struct winbindd_domain *domain, goto done; } - status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol); + status = cm_connect_sam(domain, tmp_ctx, false, &samr_pipe, &dom_pol); if (!NT_STATUS_IS_OK(status)) { goto done; } @@ -135,7 +135,7 @@ static NTSTATUS msrpc_enum_dom_groups(struct winbindd_domain *domain, goto done; } - status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol); + status = cm_connect_sam(domain, tmp_ctx, false, &samr_pipe, &dom_pol); if (!NT_STATUS_IS_OK(status)) { goto done; } @@ -194,7 +194,7 @@ static NTSTATUS msrpc_enum_local_groups(struct winbindd_domain *domain, goto done; } - status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol); + status = cm_connect_sam(domain, tmp_ctx, false, &samr_pipe, &dom_pol); if (!NT_STATUS_IS_OK(status)) { goto done; } @@ -452,7 +452,7 @@ static NTSTATUS msrpc_query_user(struct winbindd_domain *domain, } /* no cache; hit the wire */ - status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol); + status = cm_connect_sam(domain, tmp_ctx, false, &samr_pipe, &dom_pol); if (!NT_STATUS_IS_OK(status)) { goto done; } @@ -512,7 +512,7 @@ static NTSTATUS msrpc_lookup_usergroups(struct winbindd_domain *domain, } /* no cache; hit the wire */ - status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol); + status = cm_connect_sam(domain, tmp_ctx, false, &samr_pipe, &dom_pol); if (!NT_STATUS_IS_OK(status)) { goto done; } @@ -575,7 +575,7 @@ static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain, goto done; } - status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol); + status = cm_connect_sam(domain, tmp_ctx, false, &samr_pipe, &dom_pol); if (!NT_STATUS_IS_OK(status)) { goto done; } @@ -641,7 +641,7 @@ static NTSTATUS msrpc_lookup_groupmem(struct winbindd_domain *domain, *num_names = 0; - result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol); + result = cm_connect_sam(domain, mem_ctx, false, &cli, &dom_pol); if (!NT_STATUS_IS_OK(result)) return result; @@ -903,7 +903,7 @@ static NTSTATUS msrpc_sequence_number(struct winbindd_domain *domain, } #endif /* HAVE_LDAP */ - status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol); + status = cm_connect_sam(domain, tmp_ctx, false, &samr_pipe, &dom_pol); if (!NT_STATUS_IS_OK(status)) { goto done; } @@ -992,7 +992,7 @@ static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain, return NT_STATUS_NOT_SUPPORTED; } - status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol); + status = cm_connect_sam(domain, mem_ctx, false, &cli, &dom_pol); if (!NT_STATUS_IS_OK(status)) { goto done; } @@ -1042,7 +1042,7 @@ static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain, return NT_STATUS_NOT_SUPPORTED; } - status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol); + status = cm_connect_sam(domain, mem_ctx, false, &cli, &dom_pol); if (!NT_STATUS_IS_OK(status)) { goto done; } diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index dd8f442d3d..8387bdc758 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1185,7 +1185,7 @@ static NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain, } if (!contact_domain->initialized) { - init_dc_connection(contact_domain); + init_dc_connection(contact_domain, false); } if (!contact_domain->active_directory) { @@ -1541,7 +1541,7 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon(TALLOC_CTX *mem_ctx, uint32 acct_flags; struct dcerpc_binding_handle *b; - status_tmp = cm_connect_sam(domain, mem_ctx, + status_tmp = cm_connect_sam(domain, mem_ctx, false, &samr_pipe, &samr_domain_handle); if (!NT_STATUS_IS_OK(status_tmp)) { @@ -1664,7 +1664,7 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, "request in startup mode.\n", domain->name )); winbindd_flush_negative_conn_cache(domain); - result = init_dc_connection(domain); + result = init_dc_connection(domain, false); } } @@ -2079,7 +2079,7 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact /* Get sam handle */ - result = cm_connect_sam(contact_domain, state->mem_ctx, &cli, + result = cm_connect_sam(contact_domain, state->mem_ctx, true, &cli, &dom_pol); if (!NT_STATUS_IS_OK(result)) { DEBUG(1, ("could not get SAM handle on DC for %s\n", domain)); @@ -2352,7 +2352,7 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai /* Get sam handle */ - result = cm_connect_sam(contact_domain, state->mem_ctx, &cli, &dom_pol); + result = cm_connect_sam(contact_domain, state->mem_ctx, true, &cli, &dom_pol); if (!NT_STATUS_IS_OK(result)) { DEBUG(1, ("could not get SAM handle on DC for %s\n", domain)); goto done; diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index dfd61621c6..e1b32b7799 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -171,8 +171,9 @@ NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx, struct rpc_pipe_client **ret_pipe); void invalidate_cm_connection(struct winbindd_cm_conn *conn); void close_conns_after_fork(void); -NTSTATUS init_dc_connection(struct winbindd_domain *domain); +NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc); NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + bool need_rw_dc, struct rpc_pipe_client **cli, struct policy_handle *sam_handle); NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, struct rpc_pipe_client **cli, struct policy_handle *lsa_policy); diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 4e8ab92c00..35cc524bae 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -26,6 +26,7 @@ #include "../libcli/security/security.h" #include "../libcli/auth/pam_errors.h" #include "passdb/machine_sid.h" +#include "passdb.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND @@ -576,7 +577,7 @@ enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domai fstrcpy(domain->dcname, state->request->data.init_conn.dcname); } - init_dc_connection(domain); + init_dc_connection(domain, false); if (!domain->initialized) { /* If we return error here we can't do any cached authentication, @@ -618,8 +619,34 @@ bool init_domain_list(void) /* Local SAM */ if ( role == ROLE_ACTIVE_DIRECTORY_DC ) { - (void)add_trusted_domain(get_global_sam_name(), lp_dnsdomain(), - &cache_methods, get_global_sam_sid()); + struct winbindd_domain *domain; + enum netr_SchannelType sec_chan_type; + const char *account_name; + struct samr_Password current_nt_hash; + bool ok; + + domain = add_trusted_domain(get_global_sam_name(), lp_dnsdomain(), + &cache_methods, get_global_sam_sid()); + if (domain == NULL) { + DEBUG(0, ("Failed to add our own, local AD domain to winbindd's internal list\n")); + return false; + } + + /* + * We need to call this to find out if we are an RODC + */ + ok = get_trust_pw_hash(domain->name, + current_nt_hash.hash, + &account_name, + &sec_chan_type); + if (!ok) { + DEBUG(0, ("Failed to fetch our own, local AD domain join password for winbindd's internal use\n")); + return false; + } + if (sec_chan_type == SEC_CHAN_RODC) { + domain->rodc = true; + } + } else { (void)add_trusted_domain(get_global_sam_name(), NULL, &cache_methods, get_global_sam_sid()); @@ -692,7 +719,7 @@ struct winbindd_domain *find_domain_from_name(const char *domain_name) return NULL; if (!domain->initialized) - init_dc_connection(domain); + init_dc_connection(domain, false); return domain; } @@ -727,7 +754,7 @@ struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid) return NULL; if (!domain->initialized) - init_dc_connection(domain); + init_dc_connection(domain, false); return domain; } |