mirror of
https://github.com/samba-team/samba.git
synced 2025-05-27 17:05:51 +03:00
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>
This commit is contained in:
parent
da3a79831a
commit
af7f88721a
@ -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 ? */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user