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
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
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
);
88 /* send a request for secondary rpc connection */
89 sec_conn_req
= dcerpc_secondary_connection_send(s
->pipe
,
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
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
,
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
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
);
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
)) {
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
,
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
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
;
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
,
238 /* receive rpc request result - auth2 credentials */
239 c
->status
= dcerpc_netr_ServerAuthenticate2_r_recv(subreq
, s
);
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
);
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",
267 composite_error(c
, NT_STATUS_DOWNGRADE_DETECTED
);
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
);
294 s
->dcerpc_schannel_auto
= false;
296 if (lf
& NETLOGON_NEG_SUPPORTS_AES
) {
298 if (rf
& NETLOGON_NEG_SUPPORTS_AES
) {
299 composite_error(c
, s
->a
.out
.result
);
302 } else if (lf
& NETLOGON_NEG_STRONG_KEYS
) {
304 if (rf
& NETLOGON_NEG_STRONG_KEYS
) {
305 composite_error(c
, s
->a
.out
.result
);
312 if (rf
& NETLOGON_NEG_SUPPORTS_AES
) {
314 } else if (rf
& NETLOGON_NEG_STRONG_KEYS
) {
320 DEBUG(3, ("Server doesn't support %s keys, downgrade to %s"
321 "and retry! local[0x%08X] remote[0x%08X]\n",
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
,
331 s
->pipe2
->binding_handle
,
333 if (composite_nomem(subreq
, c
)) return;
335 tevent_req_set_callback(subreq
, continue_srv_challenge
, c
);
339 /* verify credentials */
340 status
= netlogon_creds_client_verify(s
->creds
,
341 s
->a
.out
.return_credentials
,
344 if (!NT_STATUS_IS_OK(status
)) {
345 composite_error(c
, status
);
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
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
);
370 Initiate establishing a schannel key using netlogon challenge
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
;
394 /* store parameters in the state structure */
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
,
460 s
->pipe
->conn
->event_ctx
,
462 if (composite_nomem(epm_map_req
, c
)) return c
;
464 composite_continue(c
, epm_map_req
, continue_epm_map_binding
, c
);
470 Receive result of schannel key request
472 static NTSTATUS
dcerpc_schannel_key_recv(struct composite_context
*c
,
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
);
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
;
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
);
524 /* receive schannel key */
525 c
->status
= dcerpc_schannel_key_recv(ctx
,
529 if (!composite_is_ok(c
)) {
530 DEBUG(1, ("Failed to setup credentials: %s\n", nt_errstr(status
)));
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
,
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
)) {
569 ZERO_STRUCT(s
->return_auth
);
571 s
->save_creds_state
= *s
->creds_state
;
572 status
= netlogon_creds_client_authenticator(&s
->save_creds_state
,
574 if (!NT_STATUS_IS_OK(status
)) {
575 composite_error(c
, status
);
579 s
->c
.in
.server_name
= talloc_asprintf(c
,
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 "
594 subreq
= dcerpc_netr_LogonGetCapabilities_r_send(s
,
596 s
->pipe
->binding_handle
,
598 if (composite_nomem(subreq
, c
)) return;
600 tevent_req_set_callback(subreq
,
601 continue_get_negotiated_capabilities
,
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
;
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
,
629 /* receive rpc request result */
630 c
->status
= dcerpc_netr_LogonGetCapabilities_r_recv(subreq
, s
);
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
);
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
);
643 /* This is probably NT */
644 continue_logon_control_do(c
);
646 } else if (!composite_is_ok(c
)) {
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
);
658 /* This is probably an old Samba version */
663 /* verify credentials */
664 status
= netlogon_creds_client_verify(&s
->save_creds_state
,
665 &s
->c
.out
.return_authenticator
->cred
,
668 if (!NT_STATUS_IS_OK(status
)) {
669 composite_error(c
, status
);
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
);
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
);
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
);
699 ZERO_STRUCT(s
->return_auth
);
701 s
->save_creds_state
= *s
->creds_state
;
702 status
= netlogon_creds_client_authenticator(&s
->save_creds_state
,
704 if (!NT_STATUS_IS_OK(status
)) {
705 composite_error(c
, status
);
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
,
718 s
->pipe
->binding_handle
,
720 if (composite_nomem(subreq
, c
)) return;
722 tevent_req_set_callback(subreq
, continue_get_client_capabilities
, c
);
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
;
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
,
741 /* receive rpc request result */
742 c
->status
= dcerpc_netr_LogonGetCapabilities_r_recv(subreq
, s
);
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
765 * So we'll do a LogonControl message to check that...
767 continue_logon_control_do(c
);
770 if (!composite_is_ok(c
)) {
774 /* verify credentials */
775 status
= netlogon_creds_client_verify(&s
->save_creds_state
,
776 &s
->c
.out
.return_authenticator
->cred
,
779 if (!NT_STATUS_IS_OK(status
)) {
780 composite_error(c
, status
);
784 if (!NT_STATUS_IS_OK(s
->c
.out
.result
)) {
785 composite_error(c
, s
->c
.out
.result
);
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
);
799 *s
->creds_state
= s
->save_creds_state
;
800 cli_credentials_set_netlogon_creds(s
->credentials
, s
->creds_state
);
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
,
816 s
->pipe
->binding_handle
,
818 NETLOGON_CONTROL_QUERY
,
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
;
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
);
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
);
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
);
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
,
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
;
875 /* store parameters in the state structure */
877 s
->credentials
= credentials
;
879 s
->auth_level
= auth_level
;
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
);
892 Receive result of schannel authentication request
894 NTSTATUS
dcerpc_bind_auth_schannel_recv(struct composite_context
*c
)
896 NTSTATUS status
= composite_wait(c
);