diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index b812d69aebc..0840e581fe6 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -176,6 +176,14 @@ struct winbindd_domain { time_t startup_time; /* When we set "startup" true. */ bool startup; /* are we in the first 30 seconds after startup_time ? */ + bool can_do_samlogon_ex; /* Due to the lack of finer control what type + * of DC we have, let us try to do a + * credential-chain less samlogon_ex call + * with AD and schannel. If this fails with + * DCERPC_FAULT_OP_RNG_ERROR, then set this + * to False. This variable is around so that + * we don't have to try _ex every time. */ + /* Lookup methods for this domain (LDAP or RPC) */ struct winbindd_methods *methods; diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 072b4ee98f6..c715ac08d82 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2403,6 +2403,11 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, no_schannel: if ((lp_client_schannel() == False) || ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { + /* + * NetSamLogonEx only works for schannel + */ + domain->can_do_samlogon_ex = False; + /* We're done - just keep the existing connection to NETLOGON * open */ conn->netlogon_pipe = netlogon_pipe; @@ -2434,6 +2439,11 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE; } + /* + * Try NetSamLogonEx for AD domains + */ + domain->can_do_samlogon_ex = domain->active_directory; + *cli = conn->netlogon_pipe; return NT_STATUS_OK; } diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index ef5a312eea9..c56eb1b3f89 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1283,6 +1283,17 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, /* check authentication loop */ do { + NTSTATUS (*logon_fn)(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + uint32 logon_parameters, + const char *server, + const char *username, + const char *domain, + const char *workstation, + const uint8 chal[8], + DATA_BLOB lm_response, + DATA_BLOB nt_response, + struct netr_SamInfo3 **info3); ZERO_STRUCTP(my_info3); retry = False; @@ -1294,19 +1305,32 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, goto done; } - result = rpccli_netlogon_sam_network_logon(netlogon_pipe, - state->mem_ctx, - 0, - contact_domain->dcname, /* server name */ - name_user, /* user name */ - name_domain, /* target domain */ - global_myname(), /* workstation */ - chal, - lm_resp, - nt_resp, - &my_info3); + logon_fn = contact_domain->can_do_samlogon_ex + ? rpccli_netlogon_sam_network_logon_ex + : rpccli_netlogon_sam_network_logon; + + result = logon_fn(netlogon_pipe, + state->mem_ctx, + 0, + contact_domain->dcname, /* server name */ + name_user, /* user name */ + name_domain, /* target domain */ + global_myname(), /* workstation */ + chal, + lm_resp, + nt_resp, + &my_info3); attempts += 1; + if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) + && contact_domain->can_do_samlogon_ex) { + DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " + "retrying with NetSamLogon\n")); + contact_domain->can_do_samlogon_ex = False; + retry = True; + continue; + } + /* We have to try a second time as cm_connect_netlogon might not yet have noticed that the DC has killed our connection. */ @@ -1804,6 +1828,18 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } do { + NTSTATUS (*logon_fn)(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + uint32 logon_parameters, + const char *server, + const char *username, + const char *domain, + const char *workstation, + const uint8 chal[8], + DATA_BLOB lm_response, + DATA_BLOB nt_response, + struct netr_SamInfo3 **info3); + retry = False; netlogon_pipe = NULL; @@ -1815,18 +1851,31 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, goto done; } - result = rpccli_netlogon_sam_network_logon(netlogon_pipe, - state->mem_ctx, - state->request.data.auth_crap.logon_parameters, - contact_domain->dcname, - name_user, - name_domain, - /* Bug #3248 - found by Stefan Burkei. */ - workstation, /* We carefully set this above so use it... */ - state->request.data.auth_crap.chal, - lm_resp, - nt_resp, - &info3); + logon_fn = contact_domain->can_do_samlogon_ex + ? rpccli_netlogon_sam_network_logon_ex + : rpccli_netlogon_sam_network_logon; + + result = logon_fn(netlogon_pipe, + state->mem_ctx, + state->request.data.auth_crap.logon_parameters, + contact_domain->dcname, + name_user, + name_domain, + /* Bug #3248 - found by Stefan Burkei. */ + workstation, /* We carefully set this above so use it... */ + state->request.data.auth_crap.chal, + lm_resp, + nt_resp, + &info3); + + if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) + && contact_domain->can_do_samlogon_ex) { + DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " + "retrying with NetSamLogon\n")); + contact_domain->can_do_samlogon_ex = False; + retry = True; + continue; + } attempts += 1;