ctdb-scripts: Support storing statd-callout state in cluster filesystem
[samba4-gss.git] / source4 / librpc / rpc / dcerpc_schannel.c
blob42d072b90c3c301f2cfbed804768947bb3223e05
1 /*
2 Unix SMB/CIFS implementation.
4 dcerpc schannel operations
6 Copyright (C) Andrew Tridgell 2004
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
8 Copyright (C) Rafal Szczesniak 2006
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #define SOURCE4_LIBRPC_INTERNALS 1
26 #include "includes.h"
27 #include <tevent.h>
28 #include "auth/auth.h"
29 #include "libcli/composite/composite.h"
30 #include "libcli/auth/libcli_auth.h"
31 #include "librpc/gen_ndr/ndr_netlogon.h"
32 #include "librpc/gen_ndr/ndr_netlogon_c.h"
33 #include "auth/credentials/credentials.h"
34 #include "librpc/rpc/dcerpc_proto.h"
35 #include "param/param.h"
36 #include "lib/param/loadparm.h"
38 struct schannel_key_state {
39 struct dcerpc_pipe *pipe;
40 struct dcerpc_pipe *pipe2;
41 struct dcerpc_binding *binding;
42 bool dcerpc_schannel_auto;
43 struct cli_credentials *credentials;
44 struct netlogon_creds_CredentialState *creds;
45 uint32_t requested_negotiate_flags;
46 uint32_t required_negotiate_flags;
47 uint32_t local_negotiate_flags;
48 uint32_t remote_negotiate_flags;
49 struct netr_Credential credentials1;
50 struct netr_Credential credentials2;
51 struct netr_Credential credentials3;
52 struct netr_ServerReqChallenge r;
53 struct netr_ServerAuthenticate2 a;
54 const struct samr_Password *mach_pwd;
58 static void continue_secondary_connection(struct composite_context *ctx);
59 static void continue_bind_auth_none(struct composite_context *ctx);
60 static void continue_srv_challenge(struct tevent_req *subreq);
61 static void continue_srv_auth2(struct tevent_req *subreq);
62 static void continue_get_negotiated_capabilities(struct tevent_req *subreq);
63 static void continue_get_client_capabilities(struct tevent_req *subreq);
67 Stage 2 of schannel_key: Receive endpoint mapping and request secondary
68 rpc connection
70 static void continue_epm_map_binding(struct composite_context *ctx)
72 struct composite_context *c;
73 struct schannel_key_state *s;
74 struct composite_context *sec_conn_req;
76 c = talloc_get_type(ctx->async.private_data, struct composite_context);
77 s = talloc_get_type(c->private_data, struct schannel_key_state);
79 /* receive endpoint mapping */
80 c->status = dcerpc_epm_map_binding_recv(ctx);
81 if (!NT_STATUS_IS_OK(c->status)) {
82 DEBUG(0,("Failed to map DCERPC/TCP NCACN_NP pipe for '%s' - %s\n",
83 NDR_NETLOGON_UUID, nt_errstr(c->status)));
84 composite_error(c, c->status);
85 return;
88 /* send a request for secondary rpc connection */
89 sec_conn_req = dcerpc_secondary_connection_send(s->pipe,
90 s->binding);
91 if (composite_nomem(sec_conn_req, c)) return;
93 composite_continue(c, sec_conn_req, continue_secondary_connection, c);
98 Stage 3 of schannel_key: Receive secondary rpc connection and perform
99 non-authenticated bind request
101 static void continue_secondary_connection(struct composite_context *ctx)
103 struct composite_context *c;
104 struct schannel_key_state *s;
105 struct composite_context *auth_none_req;
107 c = talloc_get_type(ctx->async.private_data, struct composite_context);
108 s = talloc_get_type(c->private_data, struct schannel_key_state);
110 /* receive secondary rpc connection */
111 c->status = dcerpc_secondary_connection_recv(ctx, &s->pipe2);
112 if (!composite_is_ok(c)) return;
114 talloc_steal(s, s->pipe2);
116 /* initiate a non-authenticated bind */
117 auth_none_req = dcerpc_bind_auth_none_send(c, s->pipe2, &ndr_table_netlogon);
118 if (composite_nomem(auth_none_req, c)) return;
120 composite_continue(c, auth_none_req, continue_bind_auth_none, c);
125 Stage 4 of schannel_key: Receive non-authenticated bind and get
126 a netlogon challenge
128 static void continue_bind_auth_none(struct composite_context *ctx)
130 struct composite_context *c;
131 struct schannel_key_state *s;
132 struct tevent_req *subreq;
134 c = talloc_get_type(ctx->async.private_data, struct composite_context);
135 s = talloc_get_type(c->private_data, struct schannel_key_state);
137 /* receive result of non-authenticated bind request */
138 c->status = dcerpc_bind_auth_none_recv(ctx);
139 if (!composite_is_ok(c)) return;
141 /* prepare a challenge request */
142 s->r.in.server_name = talloc_asprintf(c, "\\\\%s", dcerpc_server_name(s->pipe));
143 if (composite_nomem(s->r.in.server_name, c)) return;
144 s->r.in.computer_name = cli_credentials_get_workstation(s->credentials);
145 s->r.in.credentials = &s->credentials1;
146 s->r.out.return_credentials = &s->credentials2;
148 generate_random_buffer(s->credentials1.data, sizeof(s->credentials1.data));
151 request a netlogon challenge - a rpc request over opened secondary pipe
153 subreq = dcerpc_netr_ServerReqChallenge_r_send(s, c->event_ctx,
154 s->pipe2->binding_handle,
155 &s->r);
156 if (composite_nomem(subreq, c)) return;
158 tevent_req_set_callback(subreq, continue_srv_challenge, c);
163 Stage 5 of schannel_key: Receive a challenge and perform authentication
164 on the netlogon pipe
166 static void continue_srv_challenge(struct tevent_req *subreq)
168 struct composite_context *c;
169 struct schannel_key_state *s;
171 c = tevent_req_callback_data(subreq, struct composite_context);
172 s = talloc_get_type(c->private_data, struct schannel_key_state);
174 /* receive rpc request result - netlogon challenge */
175 c->status = dcerpc_netr_ServerReqChallenge_r_recv(subreq, s);
176 TALLOC_FREE(subreq);
177 if (!composite_is_ok(c)) return;
179 /* prepare credentials for auth2 request */
180 s->mach_pwd = cli_credentials_get_nt_hash(s->credentials, c);
181 if (s->mach_pwd == NULL) {
182 return composite_error(c, NT_STATUS_INTERNAL_ERROR);
185 /* auth2 request arguments */
186 s->a.in.server_name = s->r.in.server_name;
187 s->a.in.account_name = cli_credentials_get_username(s->credentials);
188 s->a.in.secure_channel_type =
189 cli_credentials_get_secure_channel_type(s->credentials);
190 s->a.in.computer_name = cli_credentials_get_workstation(s->credentials);
191 s->a.in.negotiate_flags = &s->requested_negotiate_flags;
192 s->a.in.credentials = &s->credentials3;
193 s->a.out.negotiate_flags = &s->remote_negotiate_flags;
194 s->a.out.return_credentials = &s->credentials3;
196 s->creds = netlogon_creds_client_init(s,
197 s->a.in.account_name,
198 s->a.in.computer_name,
199 s->a.in.secure_channel_type,
200 &s->credentials1, &s->credentials2,
201 s->mach_pwd, &s->credentials3,
202 s->requested_negotiate_flags,
203 s->local_negotiate_flags);
204 if (composite_nomem(s->creds, c)) {
205 return;
208 authenticate on the netlogon pipe - a rpc request over secondary pipe
210 subreq = dcerpc_netr_ServerAuthenticate2_r_send(s, c->event_ctx,
211 s->pipe2->binding_handle,
212 &s->a);
213 if (composite_nomem(subreq, c)) return;
215 tevent_req_set_callback(subreq, continue_srv_auth2, c);
220 Stage 6 of schannel_key: Receive authentication request result and verify
221 received credentials
223 static void continue_srv_auth2(struct tevent_req *subreq)
225 struct composite_context *c;
226 struct schannel_key_state *s;
227 enum dcerpc_AuthType auth_type;
228 enum dcerpc_AuthLevel auth_level;
229 NTSTATUS status;
231 c = tevent_req_callback_data(subreq, struct composite_context);
232 s = talloc_get_type(c->private_data, struct schannel_key_state);
234 dcerpc_binding_handle_auth_info(s->pipe2->binding_handle,
235 &auth_type,
236 &auth_level);
238 /* receive rpc request result - auth2 credentials */
239 c->status = dcerpc_netr_ServerAuthenticate2_r_recv(subreq, s);
240 TALLOC_FREE(subreq);
241 if (!composite_is_ok(c)) return;
243 if (!NT_STATUS_EQUAL(s->a.out.result, NT_STATUS_ACCESS_DENIED) &&
244 !NT_STATUS_IS_OK(s->a.out.result)) {
245 composite_error(c, s->a.out.result);
246 return;
250 uint32_t rqf = s->required_negotiate_flags;
251 uint32_t rf = s->remote_negotiate_flags;
252 uint32_t lf = s->local_negotiate_flags;
254 if ((rf & NETLOGON_NEG_SUPPORTS_AES) &&
255 (lf & NETLOGON_NEG_SUPPORTS_AES))
257 rqf &= ~NETLOGON_NEG_ARCFOUR;
258 rqf &= ~NETLOGON_NEG_STRONG_KEYS;
261 if ((rqf & rf) != rqf) {
262 rqf = s->required_negotiate_flags;
263 DBG_ERR("The client capabilities don't match "
264 "the server capabilities: local[0x%08X] "
265 "required[0x%08X] remote[0x%08X]\n",
266 lf, rqf, rf);
267 composite_error(c, NT_STATUS_DOWNGRADE_DETECTED);
268 return;
273 * Strong keys could be unsupported (NT4) or disabled. So retry with the
274 * flags returned by the server. - asn
276 if (NT_STATUS_EQUAL(s->a.out.result, NT_STATUS_ACCESS_DENIED)) {
277 uint32_t lf = s->local_negotiate_flags;
278 const char *ln = NULL;
279 uint32_t rf = s->remote_negotiate_flags;
280 const char *rn = NULL;
282 if ((lf & rf) == lf) {
284 * without a change in flags
285 * there's no need to retry...
287 s->dcerpc_schannel_auto = false;
290 if (!s->dcerpc_schannel_auto) {
291 composite_error(c, s->a.out.result);
292 return;
294 s->dcerpc_schannel_auto = false;
296 if (lf & NETLOGON_NEG_SUPPORTS_AES) {
297 ln = "aes";
298 if (rf & NETLOGON_NEG_SUPPORTS_AES) {
299 composite_error(c, s->a.out.result);
300 return;
302 } else if (lf & NETLOGON_NEG_STRONG_KEYS) {
303 ln = "strong";
304 if (rf & NETLOGON_NEG_STRONG_KEYS) {
305 composite_error(c, s->a.out.result);
306 return;
308 } else {
309 ln = "des";
312 if (rf & NETLOGON_NEG_SUPPORTS_AES) {
313 rn = "aes";
314 } else if (rf & NETLOGON_NEG_STRONG_KEYS) {
315 rn = "strong";
316 } else {
317 rn = "des";
320 DEBUG(3, ("Server doesn't support %s keys, downgrade to %s"
321 "and retry! local[0x%08X] remote[0x%08X]\n",
322 ln, rn, lf, rf));
324 s->local_negotiate_flags &= s->remote_negotiate_flags;
326 generate_random_buffer(s->credentials1.data,
327 sizeof(s->credentials1.data));
329 subreq = dcerpc_netr_ServerReqChallenge_r_send(s,
330 c->event_ctx,
331 s->pipe2->binding_handle,
332 &s->r);
333 if (composite_nomem(subreq, c)) return;
335 tevent_req_set_callback(subreq, continue_srv_challenge, c);
336 return;
339 /* verify credentials */
340 status = netlogon_creds_client_verify(s->creds,
341 s->a.out.return_credentials,
342 auth_type,
343 auth_level);
344 if (!NT_STATUS_IS_OK(status)) {
345 composite_error(c, status);
346 return;
349 if (s->requested_negotiate_flags == s->local_negotiate_flags) {
351 * Without a downgrade in the crypto we proposed
352 * we can adjust the otherwise downgraded flags
353 * before storing.
355 s->creds->negotiate_flags &= s->remote_negotiate_flags;
356 } else if (s->local_negotiate_flags != s->remote_negotiate_flags) {
358 * We downgraded our crypto once, we should not
359 * allow any additional downgrade!
361 DBG_ERR("%s: NT_STATUS_DOWNGRADE_DETECTED\n", __location__);
362 composite_error(c, NT_STATUS_DOWNGRADE_DETECTED);
363 return;
366 composite_done(c);
370 Initiate establishing a schannel key using netlogon challenge
371 on a secondary pipe
373 static struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx,
374 struct dcerpc_pipe *p,
375 struct cli_credentials *credentials,
376 struct loadparm_context *lp_ctx)
378 struct composite_context *c;
379 struct schannel_key_state *s;
380 struct composite_context *epm_map_req;
381 enum netr_SchannelType schannel_type = cli_credentials_get_secure_channel_type(credentials);
382 struct cli_credentials *epm_creds = NULL;
383 bool reject_md5_servers = false;
384 bool require_strong_key = false;
386 /* composite context allocation and setup */
387 c = composite_create(mem_ctx, p->conn->event_ctx);
388 if (c == NULL) return NULL;
390 s = talloc_zero(c, struct schannel_key_state);
391 if (composite_nomem(s, c)) return c;
392 c->private_data = s;
394 /* store parameters in the state structure */
395 s->pipe = p;
396 s->credentials = credentials;
397 s->local_negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS;
398 s->required_negotiate_flags = NETLOGON_NEG_AUTHENTICATED_RPC;
400 /* allocate credentials */
401 if (s->pipe->conn->flags & DCERPC_SCHANNEL_128) {
402 s->local_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
403 require_strong_key = true;
405 if (s->pipe->conn->flags & DCERPC_SCHANNEL_AES) {
406 s->local_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
407 reject_md5_servers = true;
409 if (s->pipe->conn->flags & DCERPC_SCHANNEL_AUTO) {
410 s->local_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
411 s->local_negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES;
412 s->dcerpc_schannel_auto = true;
413 reject_md5_servers = lpcfg_reject_md5_servers(lp_ctx);
414 require_strong_key = lpcfg_require_strong_key(lp_ctx);
417 if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) {
418 reject_md5_servers = true;
421 if (reject_md5_servers) {
422 require_strong_key = true;
425 if (require_strong_key) {
426 s->required_negotiate_flags |= NETLOGON_NEG_ARCFOUR;
427 s->required_negotiate_flags |= NETLOGON_NEG_STRONG_KEYS;
430 if (reject_md5_servers) {
431 s->required_negotiate_flags |= NETLOGON_NEG_PASSWORD_SET2;
432 s->required_negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES;
435 s->local_negotiate_flags |= s->required_negotiate_flags;
437 if (s->required_negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
438 s->required_negotiate_flags &= ~NETLOGON_NEG_ARCFOUR;
439 s->required_negotiate_flags &= ~NETLOGON_NEG_STRONG_KEYS;
442 /* type of authentication depends on schannel type */
443 if (schannel_type == SEC_CHAN_RODC) {
444 s->local_negotiate_flags |= NETLOGON_NEG_RODC_PASSTHROUGH;
447 s->requested_negotiate_flags = s->local_negotiate_flags;
449 epm_creds = cli_credentials_init_anon(s);
450 if (composite_nomem(epm_creds, c)) return c;
452 /* allocate binding structure */
453 s->binding = dcerpc_binding_dup(s, s->pipe->binding);
454 if (composite_nomem(s->binding, c)) return c;
456 /* request the netlogon endpoint mapping */
457 epm_map_req = dcerpc_epm_map_binding_send(c, s->binding,
458 &ndr_table_netlogon,
459 epm_creds,
460 s->pipe->conn->event_ctx,
461 lp_ctx);
462 if (composite_nomem(epm_map_req, c)) return c;
464 composite_continue(c, epm_map_req, continue_epm_map_binding, c);
465 return c;
470 Receive result of schannel key request
472 static NTSTATUS dcerpc_schannel_key_recv(struct composite_context *c,
473 TALLOC_CTX *mem_ctx,
474 struct netlogon_creds_CredentialState **creds)
476 NTSTATUS status = composite_wait(c);
478 if (NT_STATUS_IS_OK(status)) {
479 struct schannel_key_state *s =
480 talloc_get_type_abort(c->private_data,
481 struct schannel_key_state);
482 *creds = talloc_move(mem_ctx, &s->creds);
485 talloc_free(c);
486 return status;
490 struct auth_schannel_state {
491 struct dcerpc_pipe *pipe;
492 struct cli_credentials *credentials;
493 uint32_t requested_negotiate_flags;
494 const struct ndr_interface_table *table;
495 struct loadparm_context *lp_ctx;
496 uint8_t auth_level;
497 struct netlogon_creds_CredentialState *creds_state;
498 struct netlogon_creds_CredentialState save_creds_state;
499 struct netr_Authenticator auth;
500 struct netr_Authenticator return_auth;
501 union netr_Capabilities capabilities;
502 union netr_Capabilities client_caps;
503 struct netr_LogonGetCapabilities c;
504 union netr_CONTROL_QUERY_INFORMATION ctrl_info;
508 static void continue_bind_auth(struct composite_context *ctx);
512 Stage 2 of auth_schannel: Receive schannel key and initiate an
513 authenticated bind using received credentials
515 static void continue_schannel_key(struct composite_context *ctx)
517 struct composite_context *auth_req;
518 struct composite_context *c = talloc_get_type(ctx->async.private_data,
519 struct composite_context);
520 struct auth_schannel_state *s = talloc_get_type(c->private_data,
521 struct auth_schannel_state);
522 NTSTATUS status;
524 /* receive schannel key */
525 c->status = dcerpc_schannel_key_recv(ctx,
527 &s->creds_state);
528 status = c->status;
529 if (!composite_is_ok(c)) {
530 DEBUG(1, ("Failed to setup credentials: %s\n", nt_errstr(status)));
531 return;
534 s->requested_negotiate_flags =
535 s->creds_state->client_requested_flags;
537 /* send bind auth request with received creds */
538 cli_credentials_set_netlogon_creds(s->credentials, s->creds_state);
540 auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table, s->credentials,
541 lpcfg_gensec_settings(c, s->lp_ctx),
542 DCERPC_AUTH_TYPE_SCHANNEL, s->auth_level,
543 NULL);
544 if (composite_nomem(auth_req, c)) return;
546 composite_continue(c, auth_req, continue_bind_auth, c);
551 Stage 3 of auth_schannel: Receive result of authenticated bind
552 and say if we're done ok.
554 static void continue_bind_auth(struct composite_context *ctx)
556 struct composite_context *c = talloc_get_type(ctx->async.private_data,
557 struct composite_context);
558 struct auth_schannel_state *s = talloc_get_type(c->private_data,
559 struct auth_schannel_state);
560 struct tevent_req *subreq;
562 c->status = dcerpc_bind_auth_recv(ctx);
563 if (!composite_is_ok(c)) return;
565 /* if we have a AES encrypted connection, verify the capabilities */
566 if (ndr_syntax_id_equal(&s->table->syntax_id,
567 &ndr_table_netlogon.syntax_id)) {
568 NTSTATUS status;
569 ZERO_STRUCT(s->return_auth);
571 s->save_creds_state = *s->creds_state;
572 status = netlogon_creds_client_authenticator(&s->save_creds_state,
573 &s->auth);
574 if (!NT_STATUS_IS_OK(status)) {
575 composite_error(c, status);
576 return;
579 s->c.in.server_name = talloc_asprintf(c,
580 "\\\\%s",
581 dcerpc_server_name(s->pipe));
582 if (composite_nomem(s->c.in.server_name, c)) return;
583 s->c.in.computer_name = cli_credentials_get_workstation(s->credentials);
584 s->c.in.credential = &s->auth;
585 s->c.in.return_authenticator = &s->return_auth;
586 s->c.in.query_level = 1;
588 s->c.out.capabilities = &s->capabilities;
589 s->c.out.return_authenticator = &s->return_auth;
591 DEBUG(5, ("We established a AES connection, verifying logon "
592 "capabilities\n"));
594 subreq = dcerpc_netr_LogonGetCapabilities_r_send(s,
595 c->event_ctx,
596 s->pipe->binding_handle,
597 &s->c);
598 if (composite_nomem(subreq, c)) return;
600 tevent_req_set_callback(subreq,
601 continue_get_negotiated_capabilities,
603 return;
606 composite_done(c);
609 static void continue_logon_control_do(struct composite_context *c);
612 Stage 4 of auth_schannel: Get the Logon Capabilities and verify them.
614 static void continue_get_negotiated_capabilities(struct tevent_req *subreq)
616 struct composite_context *c;
617 struct auth_schannel_state *s;
618 enum dcerpc_AuthType auth_type;
619 enum dcerpc_AuthLevel auth_level;
620 NTSTATUS status;
622 c = tevent_req_callback_data(subreq, struct composite_context);
623 s = talloc_get_type(c->private_data, struct auth_schannel_state);
625 dcerpc_binding_handle_auth_info(s->pipe->binding_handle,
626 &auth_type,
627 &auth_level);
629 /* receive rpc request result */
630 c->status = dcerpc_netr_LogonGetCapabilities_r_recv(subreq, s);
631 TALLOC_FREE(subreq);
632 if (NT_STATUS_EQUAL(c->status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
633 if (s->creds_state->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
634 DBG_ERR("%s: NT_STATUS_DOWNGRADE_DETECTED\n", __location__);
635 composite_error(c, NT_STATUS_DOWNGRADE_DETECTED);
636 return;
637 } else if (s->creds_state->negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
638 DBG_ERR("%s: NT_STATUS_DOWNGRADE_DETECTED\n", __location__);
639 composite_error(c, NT_STATUS_DOWNGRADE_DETECTED);
640 return;
643 /* This is probably NT */
644 continue_logon_control_do(c);
645 return;
646 } else if (!composite_is_ok(c)) {
647 return;
650 if (NT_STATUS_EQUAL(s->c.out.result, NT_STATUS_NOT_IMPLEMENTED)) {
651 if (s->creds_state->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
652 /* This means AES isn't supported. */
653 DBG_ERR("%s: NT_STATUS_DOWNGRADE_DETECTED\n", __location__);
654 composite_error(c, NT_STATUS_DOWNGRADE_DETECTED);
655 return;
658 /* This is probably an old Samba version */
659 composite_done(c);
660 return;
663 /* verify credentials */
664 status = netlogon_creds_client_verify(&s->save_creds_state,
665 &s->c.out.return_authenticator->cred,
666 auth_type,
667 auth_level);
668 if (!NT_STATUS_IS_OK(status)) {
669 composite_error(c, status);
670 return;
673 *s->creds_state = s->save_creds_state;
674 cli_credentials_set_netlogon_creds(s->credentials, s->creds_state);
676 if (!NT_STATUS_IS_OK(s->c.out.result)) {
677 composite_error(c, s->c.out.result);
678 return;
681 /* compare capabilities */
682 if (s->creds_state->negotiate_flags != s->capabilities.server_capabilities) {
683 DBG_ERR("The client capabilities don't match the server "
684 "capabilities: local[0x%08X] remote[0x%08X]\n",
685 s->creds_state->negotiate_flags,
686 s->capabilities.server_capabilities);
687 composite_error(c, NT_STATUS_DOWNGRADE_DETECTED);
688 return;
691 if ((s->requested_negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) &&
692 (!(s->creds_state->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES)))
694 DBG_ERR("%s: NT_STATUS_DOWNGRADE_DETECTED\n", __location__);
695 composite_error(c, NT_STATUS_DOWNGRADE_DETECTED);
696 return;
699 ZERO_STRUCT(s->return_auth);
701 s->save_creds_state = *s->creds_state;
702 status = netlogon_creds_client_authenticator(&s->save_creds_state,
703 &s->auth);
704 if (!NT_STATUS_IS_OK(status)) {
705 composite_error(c, status);
706 return;
709 s->c.in.credential = &s->auth;
710 s->c.in.return_authenticator = &s->return_auth;
711 s->c.in.query_level = 2;
713 s->c.out.capabilities = &s->client_caps;
714 s->c.out.return_authenticator = &s->return_auth;
716 subreq = dcerpc_netr_LogonGetCapabilities_r_send(s,
717 c->event_ctx,
718 s->pipe->binding_handle,
719 &s->c);
720 if (composite_nomem(subreq, c)) return;
722 tevent_req_set_callback(subreq, continue_get_client_capabilities, c);
723 return;
726 static void continue_get_client_capabilities(struct tevent_req *subreq)
728 struct composite_context *c;
729 struct auth_schannel_state *s;
730 enum dcerpc_AuthType auth_type;
731 enum dcerpc_AuthLevel auth_level;
732 NTSTATUS status;
734 c = tevent_req_callback_data(subreq, struct composite_context);
735 s = talloc_get_type(c->private_data, struct auth_schannel_state);
737 dcerpc_binding_handle_auth_info(s->pipe->binding_handle,
738 &auth_type,
739 &auth_level);
741 /* receive rpc request result */
742 c->status = dcerpc_netr_LogonGetCapabilities_r_recv(subreq, s);
743 TALLOC_FREE(subreq);
744 if (NT_STATUS_EQUAL(c->status, NT_STATUS_RPC_BAD_STUB_DATA)) {
746 * unpatched Samba server, see
747 * https://bugzilla.samba.org/show_bug.cgi?id=15418
749 c->status = NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE;
751 if (NT_STATUS_EQUAL(c->status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE)) {
753 * Here we know the negotiated flags were already
754 * verified with query_level=1, which means
755 * the server supported NETLOGON_NEG_SUPPORTS_AES
756 * and also NETLOGON_NEG_AUTHENTICATED_RPC
758 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
759 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
760 * we should detect a faked
761 * NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE
762 * with the next request as the sequence number processing
763 * gets out of sync.
765 * So we'll do a LogonControl message to check that...
767 continue_logon_control_do(c);
768 return;
770 if (!composite_is_ok(c)) {
771 return;
774 /* verify credentials */
775 status = netlogon_creds_client_verify(&s->save_creds_state,
776 &s->c.out.return_authenticator->cred,
777 auth_type,
778 auth_level);
779 if (!NT_STATUS_IS_OK(status)) {
780 composite_error(c, status);
781 return;
784 if (!NT_STATUS_IS_OK(s->c.out.result)) {
785 composite_error(c, s->c.out.result);
786 return;
789 /* compare capabilities */
790 if (s->requested_negotiate_flags != s->client_caps.requested_flags) {
791 DBG_ERR("The client requested capabilities did not reach"
792 "the server! local[0x%08X] remote[0x%08X]\n",
793 s->requested_negotiate_flags,
794 s->client_caps.requested_flags);
795 composite_error(c, NT_STATUS_DOWNGRADE_DETECTED);
796 return;
799 *s->creds_state = s->save_creds_state;
800 cli_credentials_set_netlogon_creds(s->credentials, s->creds_state);
802 composite_done(c);
805 static void continue_logon_control_done(struct tevent_req *subreq);
807 static void continue_logon_control_do(struct composite_context *c)
809 struct auth_schannel_state *s = NULL;
810 struct tevent_req *subreq = NULL;
812 s = talloc_get_type(c->private_data, struct auth_schannel_state);
814 subreq = dcerpc_netr_LogonControl_send(s,
815 c->event_ctx,
816 s->pipe->binding_handle,
817 s->c.in.server_name,
818 NETLOGON_CONTROL_QUERY,
820 &s->ctrl_info);
821 if (composite_nomem(subreq, c)) return;
823 tevent_req_set_callback(subreq, continue_logon_control_done, c);
826 static void continue_logon_control_done(struct tevent_req *subreq)
828 struct composite_context *c = NULL;
829 struct auth_schannel_state *s = NULL;
830 WERROR werr;
832 c = tevent_req_callback_data(subreq, struct composite_context);
833 s = talloc_get_type(c->private_data, struct auth_schannel_state);
835 /* receive rpc request result */
836 c->status = dcerpc_netr_LogonControl_recv(subreq, s, &werr);
837 TALLOC_FREE(subreq);
838 if (!NT_STATUS_IS_OK(c->status)) {
839 DBG_ERR("%s: NT_STATUS_DOWNGRADE_DETECTED\n", __location__);
840 composite_error(c, NT_STATUS_DOWNGRADE_DETECTED);
841 return;
844 if (!W_ERROR_EQUAL(werr, WERR_NOT_SUPPORTED)) {
845 DBG_ERR("%s: NT_STATUS_DOWNGRADE_DETECTED\n", __location__);
846 composite_error(c, NT_STATUS_DOWNGRADE_DETECTED);
847 return;
850 composite_done(c);
854 Initiate schannel authentication request
856 struct composite_context *dcerpc_bind_auth_schannel_send(TALLOC_CTX *tmp_ctx,
857 struct dcerpc_pipe *p,
858 const struct ndr_interface_table *table,
859 struct cli_credentials *credentials,
860 struct loadparm_context *lp_ctx,
861 uint8_t auth_level)
863 struct composite_context *c;
864 struct auth_schannel_state *s;
865 struct composite_context *schan_key_req;
867 /* composite context allocation and setup */
868 c = composite_create(tmp_ctx, p->conn->event_ctx);
869 if (c == NULL) return NULL;
871 s = talloc_zero(c, struct auth_schannel_state);
872 if (composite_nomem(s, c)) return c;
873 c->private_data = s;
875 /* store parameters in the state structure */
876 s->pipe = p;
877 s->credentials = credentials;
878 s->table = table;
879 s->auth_level = auth_level;
880 s->lp_ctx = lp_ctx;
882 /* start getting schannel key first */
883 schan_key_req = dcerpc_schannel_key_send(c, p, credentials, lp_ctx);
884 if (composite_nomem(schan_key_req, c)) return c;
886 composite_continue(c, schan_key_req, continue_schannel_key, c);
887 return c;
892 Receive result of schannel authentication request
894 NTSTATUS dcerpc_bind_auth_schannel_recv(struct composite_context *c)
896 NTSTATUS status = composite_wait(c);
898 talloc_free(c);
899 return status;