summaryrefslogtreecommitdiff
path: root/source4/librpc/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'source4/librpc/rpc')
-rw-r--r--source4/librpc/rpc/dcerpc_schannel.c49
1 files changed, 40 insertions, 9 deletions
diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c
index fc56eccf7c..9501e3e047 100644
--- a/source4/librpc/rpc/dcerpc_schannel.c
+++ b/source4/librpc/rpc/dcerpc_schannel.c
@@ -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 */