mirror of
https://github.com/samba-team/samba.git
synced 2025-03-27 22:50:26 +03:00
s4-librpc: Fix NETLOGON credential chain with Windows 2008.
Windows Server 2008 returns NT_STATUS_DOWNGRADE_DETECTED if you call netrServerAuthenticate2 during a domain join without setting the strong keys flag (128bit crypto). Only for NT4 we need to do a downgrade to the returned negotiate flags. See also 0970369ca0cb9ae465cff40e5c75739824daf1d0.
This commit is contained in:
parent
ffa996e479
commit
17d124490b
@ -107,6 +107,9 @@ struct dcerpc_binding {
|
||||
/* specify binding interface */
|
||||
#define DCERPC_LOCALADDRESS (1<<22)
|
||||
|
||||
/* handle upgrades or downgrades automatically */
|
||||
#define DCERPC_SCHANNEL_AUTO (1<<23)
|
||||
|
||||
/* The following definitions come from ../librpc/rpc/dcerpc_error.c */
|
||||
|
||||
const char *dcerpc_errstr(TALLOC_CTX *mem_ctx, uint32_t fault_code);
|
||||
|
@ -36,9 +36,11 @@ struct schannel_key_state {
|
||||
struct dcerpc_pipe *pipe;
|
||||
struct dcerpc_pipe *pipe2;
|
||||
struct dcerpc_binding *binding;
|
||||
bool dcerpc_schannel_auto;
|
||||
struct cli_credentials *credentials;
|
||||
struct netlogon_creds_CredentialState *creds;
|
||||
uint32_t negotiate_flags;
|
||||
uint32_t local_negotiate_flags;
|
||||
uint32_t remote_negotiate_flags;
|
||||
struct netr_Credential credentials1;
|
||||
struct netr_Credential credentials2;
|
||||
struct netr_Credential credentials3;
|
||||
@ -176,16 +178,17 @@ static void continue_srv_challenge(struct tevent_req *subreq)
|
||||
s->a.in.secure_channel_type =
|
||||
cli_credentials_get_secure_channel_type(s->credentials);
|
||||
s->a.in.computer_name = cli_credentials_get_workstation(s->credentials);
|
||||
s->a.in.negotiate_flags = &s->negotiate_flags;
|
||||
s->a.in.negotiate_flags = &s->local_negotiate_flags;
|
||||
s->a.in.credentials = &s->credentials3;
|
||||
s->a.out.negotiate_flags = &s->negotiate_flags;
|
||||
s->a.out.negotiate_flags = &s->remote_negotiate_flags;
|
||||
s->a.out.return_credentials = &s->credentials3;
|
||||
|
||||
s->creds = netlogon_creds_client_init(s,
|
||||
s->a.in.account_name,
|
||||
s->a.in.computer_name,
|
||||
&s->credentials1, &s->credentials2,
|
||||
s->mach_pwd, &s->credentials3, s->negotiate_flags);
|
||||
s->mach_pwd, &s->credentials3,
|
||||
s->local_negotiate_flags);
|
||||
if (composite_nomem(s->creds, c)) {
|
||||
return;
|
||||
}
|
||||
@ -218,6 +221,30 @@ static void continue_srv_auth2(struct tevent_req *subreq)
|
||||
TALLOC_FREE(subreq);
|
||||
if (!composite_is_ok(c)) return;
|
||||
|
||||
/*
|
||||
* Strong keys could be unsupported (NT4) or disables. So retry with the
|
||||
* flags returned by the server. - asn
|
||||
*/
|
||||
if (NT_STATUS_EQUAL(s->a.out.result, NT_STATUS_ACCESS_DENIED) &&
|
||||
s->dcerpc_schannel_auto &&
|
||||
(s->local_negotiate_flags & NETLOGON_NEG_STRONG_KEYS)) {
|
||||
DEBUG(3, ("Server doesn't support strong keys, "
|
||||
"downgrade and retry!\n"));
|
||||
s->local_negotiate_flags = s->remote_negotiate_flags;
|
||||
|
||||
generate_random_buffer(s->credentials1.data,
|
||||
sizeof(s->credentials1.data));
|
||||
|
||||
subreq = dcerpc_netr_ServerReqChallenge_r_send(s,
|
||||
c->event_ctx,
|
||||
s->pipe2->binding_handle,
|
||||
&s->r);
|
||||
if (composite_nomem(subreq, c)) return;
|
||||
|
||||
tevent_req_set_callback(subreq, continue_srv_challenge, c);
|
||||
return;
|
||||
}
|
||||
|
||||
/* verify credentials */
|
||||
if (!netlogon_creds_client_check(s->creds, s->a.out.return_credentials)) {
|
||||
composite_error(c, NT_STATUS_UNSUCCESSFUL);
|
||||
@ -256,15 +283,19 @@ struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx,
|
||||
/* store parameters in the state structure */
|
||||
s->pipe = p;
|
||||
s->credentials = credentials;
|
||||
s->local_negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS;
|
||||
|
||||
/* allocate credentials */
|
||||
/* type of authentication depends on schannel type */
|
||||
if (schannel_type == SEC_CHAN_RODC) {
|
||||
s->negotiate_flags = NETLOGON_NEG_AUTH2_RODC_FLAGS;
|
||||
} else if (s->pipe->conn->flags & DCERPC_SCHANNEL_128) {
|
||||
s->negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
|
||||
} else {
|
||||
s->negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS;
|
||||
s->local_negotiate_flags = NETLOGON_NEG_AUTH2_RODC_FLAGS;
|
||||
}
|
||||
if (s->pipe->conn->flags & DCERPC_SCHANNEL_128) {
|
||||
s->local_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
|
||||
}
|
||||
if (s->pipe->conn->flags & DCERPC_SCHANNEL_AUTO) {
|
||||
s->local_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
|
||||
s->dcerpc_schannel_auto = true;
|
||||
}
|
||||
|
||||
/* allocate binding structure */
|
||||
|
@ -154,7 +154,7 @@ struct composite_context *wb_init_domain_send(TALLOC_CTX *mem_ctx,
|
||||
(lpcfg_server_role(service->task->lp_ctx) == ROLE_DOMAIN_CONTROLLER)) &&
|
||||
(dom_sid_equal(state->domain->info->sid,
|
||||
state->service->primary_sid))) {
|
||||
state->domain->netlogon_binding->flags |= DCERPC_SCHANNEL | DCERPC_SCHANNEL_128;
|
||||
state->domain->netlogon_binding->flags |= DCERPC_SCHANNEL | DCERPC_SCHANNEL_AUTO;
|
||||
|
||||
/* For debugging, it can be a real pain if all the traffic is encrypted */
|
||||
if (lpcfg_winbind_sealed_pipes(service->task->lp_ctx)) {
|
||||
@ -236,7 +236,7 @@ static bool retry_with_schannel(struct init_domain_state *state,
|
||||
* NTLMSSP binds */
|
||||
|
||||
/* Try again with schannel */
|
||||
binding->flags |= DCERPC_SCHANNEL;
|
||||
binding->flags |= DCERPC_SCHANNEL | DCERPC_SCHANNEL_AUTO;
|
||||
|
||||
/* Try again, likewise on the same IPC$ share,
|
||||
secured with SCHANNEL */
|
||||
|
Loading…
x
Reference in New Issue
Block a user