2 Unix SMB/CIFS implementation.
4 module to store/fetch session keys for the schannel client
6 Copyright (C) Stefan Metzmacher 2013
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "system/filesys.h"
25 #include "lib/util/tevent_ntstatus.h"
26 #include "lib/dbwrap/dbwrap.h"
27 #include "lib/dbwrap/dbwrap_rbt.h"
28 #include "lib/util/util_tdb.h"
29 #include "libcli/security/security.h"
30 #include "../lib/param/param.h"
31 #include "../libcli/auth/schannel.h"
32 #include "../librpc/gen_ndr/ndr_schannel.h"
33 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
34 #include "../librpc/gen_ndr/server_id.h"
35 #include "netlogon_creds_cli.h"
36 #include "source3/include/messages.h"
37 #include "source3/include/g_lock.h"
39 struct netlogon_creds_cli_locked_state
;
41 struct netlogon_creds_cli_context
{
45 uint32_t proposed_flags
;
46 uint32_t required_flags
;
47 enum netr_SchannelType type
;
48 enum dcerpc_AuthLevel auth_level
;
53 const char *netbios_domain
;
54 uint32_t cached_flags
;
63 struct db_context
*ctx
;
64 struct g_lock_ctx
*g_ctx
;
65 struct netlogon_creds_cli_locked_state
*locked_state
;
69 struct netlogon_creds_cli_locked_state
{
70 struct netlogon_creds_cli_context
*context
;
72 struct netlogon_creds_CredentialState
*creds
;
75 static int netlogon_creds_cli_locked_state_destructor(
76 struct netlogon_creds_cli_locked_state
*state
)
78 struct netlogon_creds_cli_context
*context
= state
->context
;
80 if (context
== NULL
) {
84 if (context
->db
.locked_state
== state
) {
85 context
->db
.locked_state
= NULL
;
88 if (state
->is_glocked
) {
89 g_lock_unlock(context
->db
.g_ctx
,
90 context
->db
.key_name
);
96 static NTSTATUS
netlogon_creds_cli_context_common(
97 const char *client_computer
,
98 const char *client_account
,
99 enum netr_SchannelType type
,
100 enum dcerpc_AuthLevel auth_level
,
101 uint32_t proposed_flags
,
102 uint32_t required_flags
,
103 const char *server_computer
,
104 const char *server_netbios_domain
,
106 struct netlogon_creds_cli_context
**_context
)
108 struct netlogon_creds_cli_context
*context
= NULL
;
109 TALLOC_CTX
*frame
= talloc_stackframe();
110 char *_key_name
= NULL
;
111 char *server_netbios_name
= NULL
;
116 context
= talloc_zero(mem_ctx
, struct netlogon_creds_cli_context
);
117 if (context
== NULL
) {
119 return NT_STATUS_NO_MEMORY
;
122 context
->client
.computer
= talloc_strdup(context
, client_computer
);
123 if (context
->client
.computer
== NULL
) {
124 TALLOC_FREE(context
);
126 return NT_STATUS_NO_MEMORY
;
129 context
->client
.account
= talloc_strdup(context
, client_account
);
130 if (context
->client
.account
== NULL
) {
131 TALLOC_FREE(context
);
133 return NT_STATUS_NO_MEMORY
;
136 context
->client
.proposed_flags
= proposed_flags
;
137 context
->client
.required_flags
= required_flags
;
138 context
->client
.type
= type
;
139 context
->client
.auth_level
= auth_level
;
141 context
->server
.computer
= talloc_strdup(context
, server_computer
);
142 if (context
->server
.computer
== NULL
) {
143 TALLOC_FREE(context
);
145 return NT_STATUS_NO_MEMORY
;
148 context
->server
.netbios_domain
= talloc_strdup(context
, server_netbios_domain
);
149 if (context
->server
.netbios_domain
== NULL
) {
150 TALLOC_FREE(context
);
152 return NT_STATUS_NO_MEMORY
;
157 * Force the callers to provide a unique
158 * value for server_computer and use this directly.
160 * For now we have to deal with
161 * "HOSTNAME" vs. "hostname.example.com".
163 server_netbios_name
= talloc_strdup(frame
, server_computer
);
164 if (server_netbios_name
== NULL
) {
165 TALLOC_FREE(context
);
167 return NT_STATUS_NO_MEMORY
;
170 p
= strchr(server_netbios_name
, '.');
175 _key_name
= talloc_asprintf(frame
, "CLI[%s/%s]/SRV[%s/%s]",
179 server_netbios_domain
);
180 if (_key_name
== NULL
) {
181 TALLOC_FREE(context
);
183 return NT_STATUS_NO_MEMORY
;
186 context
->db
.key_name
= talloc_strdup_upper(context
, _key_name
);
187 if (context
->db
.key_name
== NULL
) {
188 TALLOC_FREE(context
);
190 return NT_STATUS_NO_MEMORY
;
193 context
->db
.key_data
= string_term_tdb_data(context
->db
.key_name
);
200 static struct db_context
*netlogon_creds_cli_global_db
;
202 NTSTATUS
netlogon_creds_cli_set_global_db(struct db_context
**db
)
204 if (netlogon_creds_cli_global_db
!= NULL
) {
205 return NT_STATUS_INVALID_PARAMETER_MIX
;
208 netlogon_creds_cli_global_db
= talloc_move(talloc_autofree_context(), db
);
212 NTSTATUS
netlogon_creds_cli_open_global_db(struct loadparm_context
*lp_ctx
)
215 struct db_context
*global_db
;
217 if (netlogon_creds_cli_global_db
!= NULL
) {
221 fname
= lpcfg_private_db_path(talloc_autofree_context(), lp_ctx
, "netlogon_creds_cli");
223 return NT_STATUS_NO_MEMORY
;
226 global_db
= dbwrap_local_open(talloc_autofree_context(), lp_ctx
,
228 TDB_CLEAR_IF_FIRST
|TDB_INCOMPATIBLE_HASH
,
230 0600, DBWRAP_LOCK_ORDER_2
,
232 if (global_db
== NULL
) {
233 DEBUG(0,("netlogon_creds_cli_open_global_db: Failed to open %s - %s\n",
234 fname
, strerror(errno
)));
236 return NT_STATUS_NO_MEMORY
;
240 netlogon_creds_cli_global_db
= global_db
;
244 NTSTATUS
netlogon_creds_cli_context_global(struct loadparm_context
*lp_ctx
,
245 struct messaging_context
*msg_ctx
,
246 const char *client_account
,
247 enum netr_SchannelType type
,
248 const char *server_computer
,
249 const char *server_netbios_domain
,
251 struct netlogon_creds_cli_context
**_context
)
253 TALLOC_CTX
*frame
= talloc_stackframe();
255 struct netlogon_creds_cli_context
*context
= NULL
;
256 const char *client_computer
;
257 uint32_t proposed_flags
;
258 uint32_t required_flags
= 0;
259 bool reject_md5_servers
= false;
260 bool require_strong_key
= false;
261 int require_sign_or_seal
= true;
262 bool seal_secure_channel
= true;
263 enum dcerpc_AuthLevel auth_level
= DCERPC_AUTH_LEVEL_NONE
;
264 bool neutralize_nt4_emulation
= false;
268 client_computer
= lpcfg_netbios_name(lp_ctx
);
269 if (strlen(client_computer
) > 15) {
270 return NT_STATUS_INVALID_PARAMETER_MIX
;
274 * allow overwrite per domain
275 * reject md5 servers:<netbios_domain>
277 reject_md5_servers
= lpcfg_reject_md5_servers(lp_ctx
);
278 reject_md5_servers
= lpcfg_parm_bool(lp_ctx
, NULL
,
279 "reject md5 servers",
280 server_netbios_domain
,
284 * allow overwrite per domain
285 * require strong key:<netbios_domain>
287 require_strong_key
= lpcfg_require_strong_key(lp_ctx
);
288 require_strong_key
= lpcfg_parm_bool(lp_ctx
, NULL
,
289 "require strong key",
290 server_netbios_domain
,
294 * allow overwrite per domain
295 * client schannel:<netbios_domain>
297 require_sign_or_seal
= lpcfg_client_schannel(lp_ctx
);
298 require_sign_or_seal
= lpcfg_parm_int(lp_ctx
, NULL
,
300 server_netbios_domain
,
301 require_sign_or_seal
);
304 * allow overwrite per domain
305 * winbind sealed pipes:<netbios_domain>
307 seal_secure_channel
= lpcfg_winbind_sealed_pipes(lp_ctx
);
308 seal_secure_channel
= lpcfg_parm_bool(lp_ctx
, NULL
,
309 "winbind sealed pipes",
310 server_netbios_domain
,
311 seal_secure_channel
);
314 * allow overwrite per domain
315 * neutralize nt4 emulation:<netbios_domain>
317 neutralize_nt4_emulation
= lpcfg_neutralize_nt4_emulation(lp_ctx
);
318 neutralize_nt4_emulation
= lpcfg_parm_bool(lp_ctx
, NULL
,
319 "neutralize nt4 emulation",
320 server_netbios_domain
,
321 neutralize_nt4_emulation
);
323 proposed_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
324 proposed_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
328 if (lpcfg_security(lp_ctx
) == SEC_ADS
) {
330 * AD domains should be secure
332 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
333 require_sign_or_seal
= true;
334 require_strong_key
= true;
338 case SEC_CHAN_DOMAIN
:
341 case SEC_CHAN_DNS_DOMAIN
:
343 * AD domains should be secure
345 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
346 require_sign_or_seal
= true;
347 require_strong_key
= true;
348 neutralize_nt4_emulation
= true;
352 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
353 require_sign_or_seal
= true;
354 require_strong_key
= true;
358 required_flags
|= NETLOGON_NEG_RODC_PASSTHROUGH
;
359 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
360 require_sign_or_seal
= true;
361 require_strong_key
= true;
362 neutralize_nt4_emulation
= true;
367 return NT_STATUS_INVALID_PARAMETER
;
370 if (neutralize_nt4_emulation
) {
371 proposed_flags
|= NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION
;
374 if (require_sign_or_seal
== false) {
375 proposed_flags
&= ~NETLOGON_NEG_AUTHENTICATED_RPC
;
377 required_flags
|= NETLOGON_NEG_ARCFOUR
;
378 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
381 if (reject_md5_servers
) {
382 required_flags
|= NETLOGON_NEG_ARCFOUR
;
383 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
384 required_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
385 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
388 if (require_strong_key
) {
389 required_flags
|= NETLOGON_NEG_ARCFOUR
;
390 required_flags
|= NETLOGON_NEG_STRONG_KEYS
;
391 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
394 proposed_flags
|= required_flags
;
396 if (seal_secure_channel
) {
397 auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
399 auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
402 status
= netlogon_creds_cli_context_common(client_computer
,
409 server_netbios_domain
,
412 if (!NT_STATUS_IS_OK(status
)) {
417 if (msg_ctx
!= NULL
) {
418 context
->db
.g_ctx
= g_lock_ctx_init(context
, msg_ctx
);
419 if (context
->db
.g_ctx
== NULL
) {
420 TALLOC_FREE(context
);
422 return NT_STATUS_NO_MEMORY
;
426 if (netlogon_creds_cli_global_db
!= NULL
) {
427 context
->db
.ctx
= netlogon_creds_cli_global_db
;
433 status
= netlogon_creds_cli_open_global_db(lp_ctx
);
434 if (!NT_STATUS_IS_OK(status
)) {
435 TALLOC_FREE(context
);
437 return NT_STATUS_NO_MEMORY
;
440 context
->db
.ctx
= netlogon_creds_cli_global_db
;
446 NTSTATUS
netlogon_creds_cli_context_tmp(const char *client_computer
,
447 const char *client_account
,
448 enum netr_SchannelType type
,
449 uint32_t proposed_flags
,
450 uint32_t required_flags
,
451 enum dcerpc_AuthLevel auth_level
,
452 const char *server_computer
,
453 const char *server_netbios_domain
,
455 struct netlogon_creds_cli_context
**_context
)
458 struct netlogon_creds_cli_context
*context
= NULL
;
462 status
= netlogon_creds_cli_context_common(client_computer
,
469 server_netbios_domain
,
472 if (!NT_STATUS_IS_OK(status
)) {
476 context
->db
.ctx
= db_open_rbt(context
);
477 if (context
->db
.ctx
== NULL
) {
478 talloc_free(context
);
479 return NT_STATUS_NO_MEMORY
;
486 enum dcerpc_AuthLevel
netlogon_creds_cli_auth_level(
487 struct netlogon_creds_cli_context
*context
)
489 return context
->client
.auth_level
;
492 struct netlogon_creds_cli_fetch_state
{
494 struct netlogon_creds_CredentialState
*creds
;
495 uint32_t required_flags
;
499 static void netlogon_creds_cli_fetch_parser(TDB_DATA key
, TDB_DATA data
,
502 struct netlogon_creds_cli_fetch_state
*state
=
503 (struct netlogon_creds_cli_fetch_state
*)private_data
;
504 enum ndr_err_code ndr_err
;
508 state
->creds
= talloc_zero(state
->mem_ctx
,
509 struct netlogon_creds_CredentialState
);
510 if (state
->creds
== NULL
) {
511 state
->status
= NT_STATUS_NO_MEMORY
;
515 blob
.data
= data
.dptr
;
516 blob
.length
= data
.dsize
;
518 ndr_err
= ndr_pull_struct_blob(&blob
, state
->creds
, state
->creds
,
519 (ndr_pull_flags_fn_t
)ndr_pull_netlogon_creds_CredentialState
);
520 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
521 TALLOC_FREE(state
->creds
);
522 state
->status
= ndr_map_error2ntstatus(ndr_err
);
526 tmp_flags
= state
->creds
->negotiate_flags
;
527 tmp_flags
&= state
->required_flags
;
528 if (tmp_flags
!= state
->required_flags
) {
529 TALLOC_FREE(state
->creds
);
530 state
->status
= NT_STATUS_DOWNGRADE_DETECTED
;
534 state
->status
= NT_STATUS_OK
;
537 NTSTATUS
netlogon_creds_cli_get(struct netlogon_creds_cli_context
*context
,
539 struct netlogon_creds_CredentialState
**_creds
)
542 struct netlogon_creds_cli_fetch_state fstate
= {
544 .status
= NT_STATUS_INTERNAL_ERROR
,
545 .required_flags
= context
->client
.required_flags
,
547 static const struct netr_Credential zero_creds
;
551 status
= dbwrap_parse_record(context
->db
.ctx
,
552 context
->db
.key_data
,
553 netlogon_creds_cli_fetch_parser
,
555 if (!NT_STATUS_IS_OK(status
)) {
558 status
= fstate
.status
;
559 if (!NT_STATUS_IS_OK(status
)) {
564 * mark it as invalid for step operations.
566 fstate
.creds
->sequence
= 0;
567 fstate
.creds
->seed
= zero_creds
;
568 fstate
.creds
->client
= zero_creds
;
569 fstate
.creds
->server
= zero_creds
;
571 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
572 *_creds
= fstate
.creds
;
577 * It is really important to try SamLogonEx here,
578 * because multiple processes can talk to the same
579 * domain controller, without using the credential
582 * With a normal SamLogon call, we must keep the
583 * credentials chain updated and intact between all
584 * users of the machine account (which would imply
585 * cross-node communication for every NTLM logon).
587 * The credentials chain is not per NETLOGON pipe
588 * connection, but globally on the server/client pair
589 * by computer name, while the client is free to use
590 * any computer name. We include the cluster node number
591 * in our computer name in order to avoid cross node
592 * coordination of the credential chain.
594 * It's also important to use NetlogonValidationSamInfo4 (6),
595 * because it relies on the rpc transport encryption
596 * and avoids using the global netlogon schannel
597 * session key to en/decrypt secret information
598 * like the user_session_key for network logons.
600 * [MS-APDS] 3.1.5.2 NTLM Network Logon
601 * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and
602 * NETLOGON_NEG_AUTHENTICATED_RPC set together
603 * are the indication that the server supports
604 * NetlogonValidationSamInfo4 (6). And it must only
605 * be used if "SealSecureChannel" is used.
607 * The "SealSecureChannel" AUTH_TYPE_SCHANNEL/AUTH_LEVEL_PRIVACY
608 * check is done in netlogon_creds_cli_LogonSamLogon*().
610 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
611 context
->server
.try_validation6
= true;
612 context
->server
.try_logon_ex
= true;
613 context
->server
.try_logon_with
= true;
615 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
616 context
->server
.try_validation6
= false;
617 context
->server
.try_logon_ex
= false;
619 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
620 context
->server
.try_validation6
= false;
623 *_creds
= fstate
.creds
;
627 bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context
*context
,
628 const struct netlogon_creds_CredentialState
*creds1
)
630 TALLOC_CTX
*frame
= talloc_stackframe();
631 struct netlogon_creds_CredentialState
*creds2
;
635 enum ndr_err_code ndr_err
;
638 status
= netlogon_creds_cli_get(context
, frame
, &creds2
);
639 if (!NT_STATUS_IS_OK(status
)) {
644 ndr_err
= ndr_push_struct_blob(&blob1
, frame
, creds1
,
645 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
646 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
651 ndr_err
= ndr_push_struct_blob(&blob2
, frame
, creds2
,
652 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
653 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
658 if (blob1
.length
!= blob2
.length
) {
663 cmp
= memcmp(blob1
.data
, blob2
.data
, blob1
.length
);
673 NTSTATUS
netlogon_creds_cli_store(struct netlogon_creds_cli_context
*context
,
674 struct netlogon_creds_CredentialState
**_creds
)
676 struct netlogon_creds_CredentialState
*creds
= *_creds
;
678 enum ndr_err_code ndr_err
;
684 if (context
->db
.locked_state
== NULL
) {
686 * this was not the result of netlogon_creds_cli_lock*()
689 return NT_STATUS_INVALID_PAGE_PROTECTION
;
692 if (context
->db
.locked_state
->creds
!= creds
) {
694 * this was not the result of netlogon_creds_cli_lock*()
697 return NT_STATUS_INVALID_PAGE_PROTECTION
;
700 ndr_err
= ndr_push_struct_blob(&blob
, creds
, creds
,
701 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
702 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
704 status
= ndr_map_error2ntstatus(ndr_err
);
708 data
.dptr
= blob
.data
;
709 data
.dsize
= blob
.length
;
711 status
= dbwrap_store(context
->db
.ctx
,
712 context
->db
.key_data
,
715 if (!NT_STATUS_IS_OK(status
)) {
722 NTSTATUS
netlogon_creds_cli_delete(struct netlogon_creds_cli_context
*context
,
723 struct netlogon_creds_CredentialState
**_creds
)
725 struct netlogon_creds_CredentialState
*creds
= *_creds
;
730 if (context
->db
.locked_state
== NULL
) {
732 * this was not the result of netlogon_creds_cli_lock*()
735 return NT_STATUS_INVALID_PAGE_PROTECTION
;
738 if (context
->db
.locked_state
->creds
!= creds
) {
740 * this was not the result of netlogon_creds_cli_lock*()
743 return NT_STATUS_INVALID_PAGE_PROTECTION
;
746 status
= dbwrap_delete(context
->db
.ctx
,
747 context
->db
.key_data
);
749 if (!NT_STATUS_IS_OK(status
)) {
756 struct netlogon_creds_cli_lock_state
{
757 struct netlogon_creds_cli_locked_state
*locked_state
;
758 struct netlogon_creds_CredentialState
*creds
;
761 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
);
762 static void netlogon_creds_cli_lock_fetch(struct tevent_req
*req
);
764 struct tevent_req
*netlogon_creds_cli_lock_send(TALLOC_CTX
*mem_ctx
,
765 struct tevent_context
*ev
,
766 struct netlogon_creds_cli_context
*context
)
768 struct tevent_req
*req
;
769 struct netlogon_creds_cli_lock_state
*state
;
770 struct netlogon_creds_cli_locked_state
*locked_state
;
771 struct tevent_req
*subreq
;
773 req
= tevent_req_create(mem_ctx
, &state
,
774 struct netlogon_creds_cli_lock_state
);
779 if (context
->db
.locked_state
!= NULL
) {
780 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
781 return tevent_req_post(req
, ev
);
784 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
785 if (tevent_req_nomem(locked_state
, req
)) {
786 return tevent_req_post(req
, ev
);
788 talloc_set_destructor(locked_state
,
789 netlogon_creds_cli_locked_state_destructor
);
790 locked_state
->context
= context
;
792 context
->db
.locked_state
= locked_state
;
793 state
->locked_state
= locked_state
;
795 if (context
->db
.g_ctx
== NULL
) {
796 netlogon_creds_cli_lock_fetch(req
);
797 if (!tevent_req_is_in_progress(req
)) {
798 return tevent_req_post(req
, ev
);
804 subreq
= g_lock_lock_send(state
, ev
,
806 context
->db
.key_name
,
808 if (tevent_req_nomem(subreq
, req
)) {
809 return tevent_req_post(req
, ev
);
811 tevent_req_set_callback(subreq
, netlogon_creds_cli_lock_done
, req
);
816 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
)
818 struct tevent_req
*req
=
819 tevent_req_callback_data(subreq
,
821 struct netlogon_creds_cli_lock_state
*state
=
823 struct netlogon_creds_cli_lock_state
);
826 status
= g_lock_lock_recv(subreq
);
828 if (tevent_req_nterror(req
, status
)) {
831 state
->locked_state
->is_glocked
= true;
833 netlogon_creds_cli_lock_fetch(req
);
836 static void netlogon_creds_cli_lock_fetch(struct tevent_req
*req
)
838 struct netlogon_creds_cli_lock_state
*state
=
840 struct netlogon_creds_cli_lock_state
);
841 struct netlogon_creds_cli_context
*context
= state
->locked_state
->context
;
842 struct netlogon_creds_cli_fetch_state fstate
= {
843 .status
= NT_STATUS_INTERNAL_ERROR
,
844 .required_flags
= context
->client
.required_flags
,
848 fstate
.mem_ctx
= state
;
849 status
= dbwrap_parse_record(context
->db
.ctx
,
850 context
->db
.key_data
,
851 netlogon_creds_cli_fetch_parser
,
853 if (tevent_req_nterror(req
, status
)) {
856 status
= fstate
.status
;
857 if (tevent_req_nterror(req
, status
)) {
861 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
862 state
->creds
= fstate
.creds
;
863 tevent_req_done(req
);
867 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
868 context
->server
.try_validation6
= true;
869 context
->server
.try_logon_ex
= true;
870 context
->server
.try_logon_with
= true;
872 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
873 context
->server
.try_validation6
= false;
874 context
->server
.try_logon_ex
= false;
876 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
877 context
->server
.try_validation6
= false;
880 state
->creds
= fstate
.creds
;
881 tevent_req_done(req
);
885 NTSTATUS
netlogon_creds_cli_lock_recv(struct tevent_req
*req
,
887 struct netlogon_creds_CredentialState
**creds
)
889 struct netlogon_creds_cli_lock_state
*state
=
891 struct netlogon_creds_cli_lock_state
);
894 if (tevent_req_is_nterror(req
, &status
)) {
895 tevent_req_received(req
);
899 talloc_steal(state
->creds
, state
->locked_state
);
900 state
->locked_state
->creds
= state
->creds
;
901 *creds
= talloc_move(mem_ctx
, &state
->creds
);
902 tevent_req_received(req
);
906 NTSTATUS
netlogon_creds_cli_lock(struct netlogon_creds_cli_context
*context
,
908 struct netlogon_creds_CredentialState
**creds
)
910 TALLOC_CTX
*frame
= talloc_stackframe();
911 struct tevent_context
*ev
;
912 struct tevent_req
*req
;
913 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
915 ev
= samba_tevent_context_init(frame
);
919 req
= netlogon_creds_cli_lock_send(frame
, ev
, context
);
923 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
926 status
= netlogon_creds_cli_lock_recv(req
, mem_ctx
, creds
);
932 struct netlogon_creds_cli_auth_state
{
933 struct tevent_context
*ev
;
934 struct netlogon_creds_cli_context
*context
;
935 struct dcerpc_binding_handle
*binding_handle
;
936 struct samr_Password current_nt_hash
;
937 struct samr_Password previous_nt_hash
;
938 struct samr_Password used_nt_hash
;
939 char *srv_name_slash
;
940 uint32_t current_flags
;
941 struct netr_Credential client_challenge
;
942 struct netr_Credential server_challenge
;
943 struct netlogon_creds_CredentialState
*creds
;
944 struct netr_Credential client_credential
;
945 struct netr_Credential server_credential
;
950 bool try_previous_nt_hash
;
951 struct netlogon_creds_cli_locked_state
*locked_state
;
954 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
);
955 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
);
957 struct tevent_req
*netlogon_creds_cli_auth_send(TALLOC_CTX
*mem_ctx
,
958 struct tevent_context
*ev
,
959 struct netlogon_creds_cli_context
*context
,
960 struct dcerpc_binding_handle
*b
,
961 struct samr_Password current_nt_hash
,
962 const struct samr_Password
*previous_nt_hash
)
964 struct tevent_req
*req
;
965 struct netlogon_creds_cli_auth_state
*state
;
966 struct netlogon_creds_cli_locked_state
*locked_state
;
969 req
= tevent_req_create(mem_ctx
, &state
,
970 struct netlogon_creds_cli_auth_state
);
976 state
->context
= context
;
977 state
->binding_handle
= b
;
978 state
->current_nt_hash
= current_nt_hash
;
979 if (previous_nt_hash
!= NULL
) {
980 state
->previous_nt_hash
= *previous_nt_hash
;
981 state
->try_previous_nt_hash
= true;
984 if (context
->db
.locked_state
!= NULL
) {
985 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
986 return tevent_req_post(req
, ev
);
989 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
990 if (tevent_req_nomem(locked_state
, req
)) {
991 return tevent_req_post(req
, ev
);
993 talloc_set_destructor(locked_state
,
994 netlogon_creds_cli_locked_state_destructor
);
995 locked_state
->context
= context
;
997 context
->db
.locked_state
= locked_state
;
998 state
->locked_state
= locked_state
;
1000 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1001 context
->server
.computer
);
1002 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1003 return tevent_req_post(req
, ev
);
1006 state
->try_auth3
= true;
1007 state
->try_auth2
= true;
1009 if (context
->client
.required_flags
!= 0) {
1010 state
->require_auth2
= true;
1013 state
->used_nt_hash
= state
->current_nt_hash
;
1014 state
->current_flags
= context
->client
.proposed_flags
;
1016 if (context
->db
.g_ctx
!= NULL
) {
1017 struct tevent_req
*subreq
;
1019 subreq
= g_lock_lock_send(state
, ev
,
1021 context
->db
.key_name
,
1023 if (tevent_req_nomem(subreq
, req
)) {
1024 return tevent_req_post(req
, ev
);
1026 tevent_req_set_callback(subreq
,
1027 netlogon_creds_cli_auth_locked
,
1033 status
= dbwrap_delete(state
->context
->db
.ctx
,
1034 state
->context
->db
.key_data
);
1035 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
1036 status
= NT_STATUS_OK
;
1038 if (tevent_req_nterror(req
, status
)) {
1039 return tevent_req_post(req
, ev
);
1042 netlogon_creds_cli_auth_challenge_start(req
);
1043 if (!tevent_req_is_in_progress(req
)) {
1044 return tevent_req_post(req
, ev
);
1050 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
)
1052 struct tevent_req
*req
=
1053 tevent_req_callback_data(subreq
,
1055 struct netlogon_creds_cli_auth_state
*state
=
1056 tevent_req_data(req
,
1057 struct netlogon_creds_cli_auth_state
);
1060 status
= g_lock_lock_recv(subreq
);
1061 TALLOC_FREE(subreq
);
1062 if (tevent_req_nterror(req
, status
)) {
1065 state
->locked_state
->is_glocked
= true;
1067 status
= dbwrap_delete(state
->context
->db
.ctx
,
1068 state
->context
->db
.key_data
);
1069 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
1070 status
= NT_STATUS_OK
;
1072 if (tevent_req_nterror(req
, status
)) {
1076 netlogon_creds_cli_auth_challenge_start(req
);
1079 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
);
1081 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
)
1083 struct netlogon_creds_cli_auth_state
*state
=
1084 tevent_req_data(req
,
1085 struct netlogon_creds_cli_auth_state
);
1086 struct tevent_req
*subreq
;
1088 TALLOC_FREE(state
->creds
);
1090 generate_random_buffer(state
->client_challenge
.data
,
1091 sizeof(state
->client_challenge
.data
));
1093 subreq
= dcerpc_netr_ServerReqChallenge_send(state
, state
->ev
,
1094 state
->binding_handle
,
1095 state
->srv_name_slash
,
1096 state
->context
->client
.computer
,
1097 &state
->client_challenge
,
1098 &state
->server_challenge
);
1099 if (tevent_req_nomem(subreq
, req
)) {
1102 tevent_req_set_callback(subreq
,
1103 netlogon_creds_cli_auth_challenge_done
,
1107 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
);
1109 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
)
1111 struct tevent_req
*req
=
1112 tevent_req_callback_data(subreq
,
1114 struct netlogon_creds_cli_auth_state
*state
=
1115 tevent_req_data(req
,
1116 struct netlogon_creds_cli_auth_state
);
1120 status
= dcerpc_netr_ServerReqChallenge_recv(subreq
, state
, &result
);
1121 TALLOC_FREE(subreq
);
1122 if (tevent_req_nterror(req
, status
)) {
1125 if (tevent_req_nterror(req
, result
)) {
1129 if (!state
->try_auth3
&& !state
->try_auth2
) {
1130 state
->current_flags
= 0;
1133 /* Calculate the session key and client credentials */
1135 state
->creds
= netlogon_creds_client_init(state
,
1136 state
->context
->client
.account
,
1137 state
->context
->client
.computer
,
1138 state
->context
->client
.type
,
1139 &state
->client_challenge
,
1140 &state
->server_challenge
,
1141 &state
->used_nt_hash
,
1142 &state
->client_credential
,
1143 state
->current_flags
);
1144 if (tevent_req_nomem(state
->creds
, req
)) {
1148 if (state
->try_auth3
) {
1149 subreq
= dcerpc_netr_ServerAuthenticate3_send(state
, state
->ev
,
1150 state
->binding_handle
,
1151 state
->srv_name_slash
,
1152 state
->context
->client
.account
,
1153 state
->context
->client
.type
,
1154 state
->context
->client
.computer
,
1155 &state
->client_credential
,
1156 &state
->server_credential
,
1157 &state
->creds
->negotiate_flags
,
1159 if (tevent_req_nomem(subreq
, req
)) {
1162 } else if (state
->try_auth2
) {
1165 subreq
= dcerpc_netr_ServerAuthenticate2_send(state
, state
->ev
,
1166 state
->binding_handle
,
1167 state
->srv_name_slash
,
1168 state
->context
->client
.account
,
1169 state
->context
->client
.type
,
1170 state
->context
->client
.computer
,
1171 &state
->client_credential
,
1172 &state
->server_credential
,
1173 &state
->creds
->negotiate_flags
);
1174 if (tevent_req_nomem(subreq
, req
)) {
1180 subreq
= dcerpc_netr_ServerAuthenticate_send(state
, state
->ev
,
1181 state
->binding_handle
,
1182 state
->srv_name_slash
,
1183 state
->context
->client
.account
,
1184 state
->context
->client
.type
,
1185 state
->context
->client
.computer
,
1186 &state
->client_credential
,
1187 &state
->server_credential
);
1188 if (tevent_req_nomem(subreq
, req
)) {
1192 tevent_req_set_callback(subreq
,
1193 netlogon_creds_cli_auth_srvauth_done
,
1197 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
)
1199 struct tevent_req
*req
=
1200 tevent_req_callback_data(subreq
,
1202 struct netlogon_creds_cli_auth_state
*state
=
1203 tevent_req_data(req
,
1204 struct netlogon_creds_cli_auth_state
);
1208 enum ndr_err_code ndr_err
;
1213 if (state
->try_auth3
) {
1214 status
= dcerpc_netr_ServerAuthenticate3_recv(subreq
, state
,
1216 TALLOC_FREE(subreq
);
1217 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1218 state
->try_auth3
= false;
1219 netlogon_creds_cli_auth_challenge_start(req
);
1222 if (tevent_req_nterror(req
, status
)) {
1225 } else if (state
->try_auth2
) {
1226 status
= dcerpc_netr_ServerAuthenticate2_recv(subreq
, state
,
1228 TALLOC_FREE(subreq
);
1229 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1230 state
->try_auth2
= false;
1231 if (state
->require_auth2
) {
1232 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1233 tevent_req_nterror(req
, status
);
1236 netlogon_creds_cli_auth_challenge_start(req
);
1239 if (tevent_req_nterror(req
, status
)) {
1243 status
= dcerpc_netr_ServerAuthenticate_recv(subreq
, state
,
1245 TALLOC_FREE(subreq
);
1246 if (tevent_req_nterror(req
, status
)) {
1251 if (!NT_STATUS_IS_OK(result
) &&
1252 !NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
))
1254 tevent_req_nterror(req
, result
);
1258 tmp_flags
= state
->creds
->negotiate_flags
;
1259 tmp_flags
&= state
->context
->client
.required_flags
;
1260 if (tmp_flags
!= state
->context
->client
.required_flags
) {
1261 if (NT_STATUS_IS_OK(result
)) {
1262 tevent_req_nterror(req
, NT_STATUS_DOWNGRADE_DETECTED
);
1265 tevent_req_nterror(req
, result
);
1269 if (NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
)) {
1271 tmp_flags
= state
->context
->client
.proposed_flags
;
1272 if ((state
->current_flags
== tmp_flags
) &&
1273 (state
->creds
->negotiate_flags
!= tmp_flags
))
1276 * lets retry with the negotiated flags
1278 state
->current_flags
= state
->creds
->negotiate_flags
;
1279 netlogon_creds_cli_auth_challenge_start(req
);
1283 if (!state
->try_previous_nt_hash
) {
1285 * we already retried, giving up...
1287 tevent_req_nterror(req
, result
);
1292 * lets retry with the old nt hash.
1294 state
->try_previous_nt_hash
= false;
1295 state
->used_nt_hash
= state
->previous_nt_hash
;
1296 state
->current_flags
= state
->context
->client
.proposed_flags
;
1297 netlogon_creds_cli_auth_challenge_start(req
);
1301 ok
= netlogon_creds_client_check(state
->creds
,
1302 &state
->server_credential
);
1304 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1308 ndr_err
= ndr_push_struct_blob(&blob
, state
, state
->creds
,
1309 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
1310 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1311 status
= ndr_map_error2ntstatus(ndr_err
);
1312 tevent_req_nterror(req
, status
);
1316 data
.dptr
= blob
.data
;
1317 data
.dsize
= blob
.length
;
1319 status
= dbwrap_store(state
->context
->db
.ctx
,
1320 state
->context
->db
.key_data
,
1322 TALLOC_FREE(state
->locked_state
);
1323 if (tevent_req_nterror(req
, status
)) {
1327 tevent_req_done(req
);
1330 NTSTATUS
netlogon_creds_cli_auth_recv(struct tevent_req
*req
)
1334 if (tevent_req_is_nterror(req
, &status
)) {
1335 tevent_req_received(req
);
1339 tevent_req_received(req
);
1340 return NT_STATUS_OK
;
1343 NTSTATUS
netlogon_creds_cli_auth(struct netlogon_creds_cli_context
*context
,
1344 struct dcerpc_binding_handle
*b
,
1345 struct samr_Password current_nt_hash
,
1346 const struct samr_Password
*previous_nt_hash
)
1348 TALLOC_CTX
*frame
= talloc_stackframe();
1349 struct tevent_context
*ev
;
1350 struct tevent_req
*req
;
1351 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1353 ev
= samba_tevent_context_init(frame
);
1357 req
= netlogon_creds_cli_auth_send(frame
, ev
, context
, b
,
1363 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1366 status
= netlogon_creds_cli_auth_recv(req
);
1372 struct netlogon_creds_cli_check_state
{
1373 struct tevent_context
*ev
;
1374 struct netlogon_creds_cli_context
*context
;
1375 struct dcerpc_binding_handle
*binding_handle
;
1377 char *srv_name_slash
;
1379 union netr_Capabilities caps
;
1381 struct netlogon_creds_CredentialState
*creds
;
1382 struct netlogon_creds_CredentialState tmp_creds
;
1383 struct netr_Authenticator req_auth
;
1384 struct netr_Authenticator rep_auth
;
1387 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1389 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
);
1391 struct tevent_req
*netlogon_creds_cli_check_send(TALLOC_CTX
*mem_ctx
,
1392 struct tevent_context
*ev
,
1393 struct netlogon_creds_cli_context
*context
,
1394 struct dcerpc_binding_handle
*b
)
1396 struct tevent_req
*req
;
1397 struct netlogon_creds_cli_check_state
*state
;
1398 struct tevent_req
*subreq
;
1399 enum dcerpc_AuthType auth_type
;
1400 enum dcerpc_AuthLevel auth_level
;
1402 req
= tevent_req_create(mem_ctx
, &state
,
1403 struct netlogon_creds_cli_check_state
);
1409 state
->context
= context
;
1410 state
->binding_handle
= b
;
1412 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1413 context
->server
.computer
);
1414 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1415 return tevent_req_post(req
, ev
);
1418 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1419 &auth_type
, &auth_level
);
1421 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
1422 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1423 return tevent_req_post(req
, ev
);
1426 switch (auth_level
) {
1427 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1428 case DCERPC_AUTH_LEVEL_PRIVACY
:
1431 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1432 return tevent_req_post(req
, ev
);
1435 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1437 if (tevent_req_nomem(subreq
, req
)) {
1438 return tevent_req_post(req
, ev
);
1441 tevent_req_set_callback(subreq
,
1442 netlogon_creds_cli_check_locked
,
1448 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1451 struct netlogon_creds_cli_check_state
*state
=
1452 tevent_req_data(req
,
1453 struct netlogon_creds_cli_check_state
);
1455 if (state
->creds
== NULL
) {
1459 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1460 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1461 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1462 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1463 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1464 TALLOC_FREE(state
->creds
);
1468 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
1471 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
);
1473 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
)
1475 struct tevent_req
*req
=
1476 tevent_req_callback_data(subreq
,
1478 struct netlogon_creds_cli_check_state
*state
=
1479 tevent_req_data(req
,
1480 struct netlogon_creds_cli_check_state
);
1483 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1485 TALLOC_FREE(subreq
);
1486 if (tevent_req_nterror(req
, status
)) {
1491 * we defer all callbacks in order to cleanup
1492 * the database record.
1494 tevent_req_defer_callback(req
, state
->ev
);
1496 state
->tmp_creds
= *state
->creds
;
1497 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1499 ZERO_STRUCT(state
->rep_auth
);
1501 subreq
= dcerpc_netr_LogonGetCapabilities_send(state
, state
->ev
,
1502 state
->binding_handle
,
1503 state
->srv_name_slash
,
1504 state
->context
->client
.computer
,
1509 if (tevent_req_nomem(subreq
, req
)) {
1510 status
= NT_STATUS_NO_MEMORY
;
1511 netlogon_creds_cli_check_cleanup(req
, status
);
1514 tevent_req_set_callback(subreq
,
1515 netlogon_creds_cli_check_caps
,
1519 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
)
1521 struct tevent_req
*req
=
1522 tevent_req_callback_data(subreq
,
1524 struct netlogon_creds_cli_check_state
*state
=
1525 tevent_req_data(req
,
1526 struct netlogon_creds_cli_check_state
);
1531 status
= dcerpc_netr_LogonGetCapabilities_recv(subreq
, state
,
1533 TALLOC_FREE(subreq
);
1534 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1536 * Note that the negotiated flags are already checked
1537 * for our required flags after the ServerAuthenticate3/2 call.
1539 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1541 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1543 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1544 * already, we expect this to work!
1546 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1547 tevent_req_nterror(req
, status
);
1548 netlogon_creds_cli_check_cleanup(req
, status
);
1552 if (negotiated
& NETLOGON_NEG_STRONG_KEYS
) {
1554 * If we have negotiated NETLOGON_NEG_STRONG_KEYS
1555 * we expect this to work at least as far as the
1556 * NOT_SUPPORTED error handled below!
1558 * NT 4.0 and Old Samba servers are not
1559 * allowed without "require strong key = no"
1561 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1562 tevent_req_nterror(req
, status
);
1563 netlogon_creds_cli_check_cleanup(req
, status
);
1568 * If we not require NETLOGON_NEG_SUPPORTS_AES or
1569 * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore
1570 * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
1572 * This is needed against NT 4.0 and old Samba servers.
1574 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
1575 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
1576 * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
1577 * with the next request as the sequence number processing
1580 netlogon_creds_cli_check_cleanup(req
, status
);
1581 tevent_req_done(req
);
1584 if (tevent_req_nterror(req
, status
)) {
1585 netlogon_creds_cli_check_cleanup(req
, status
);
1589 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOT_IMPLEMENTED
)) {
1591 * Note that the negotiated flags are already checked
1592 * for our required flags after the ServerAuthenticate3/2 call.
1594 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1596 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1598 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1599 * already, we expect this to work!
1601 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1602 tevent_req_nterror(req
, status
);
1603 netlogon_creds_cli_check_cleanup(req
, status
);
1608 * This is ok, the server does not support
1609 * NETLOGON_NEG_SUPPORTS_AES.
1611 * netr_LogonGetCapabilities() was
1612 * netr_LogonDummyRoutine1() before
1613 * NETLOGON_NEG_SUPPORTS_AES was invented.
1615 netlogon_creds_cli_check_cleanup(req
, result
);
1616 tevent_req_done(req
);
1620 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1621 &state
->rep_auth
.cred
);
1623 status
= NT_STATUS_ACCESS_DENIED
;
1624 tevent_req_nterror(req
, status
);
1625 netlogon_creds_cli_check_cleanup(req
, status
);
1629 if (tevent_req_nterror(req
, result
)) {
1630 netlogon_creds_cli_check_cleanup(req
, result
);
1634 if (state
->caps
.server_capabilities
!= state
->tmp_creds
.negotiate_flags
) {
1635 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1636 tevent_req_nterror(req
, status
);
1637 netlogon_creds_cli_check_cleanup(req
, status
);
1642 * This is the key check that makes this check secure. If we
1643 * get OK here (rather than NOT_SUPPORTED), then the server
1644 * did support AES. If the server only proposed STRONG_KEYS
1645 * and not AES, then it should have failed with
1646 * NOT_IMPLEMENTED. We always send AES as a client, so the
1647 * server should always have returned it.
1649 if (!(state
->caps
.server_capabilities
& NETLOGON_NEG_SUPPORTS_AES
)) {
1650 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1651 tevent_req_nterror(req
, status
);
1652 netlogon_creds_cli_check_cleanup(req
, status
);
1656 *state
->creds
= state
->tmp_creds
;
1657 status
= netlogon_creds_cli_store(state
->context
,
1659 netlogon_creds_cli_check_cleanup(req
, status
);
1660 if (tevent_req_nterror(req
, status
)) {
1664 tevent_req_done(req
);
1667 NTSTATUS
netlogon_creds_cli_check_recv(struct tevent_req
*req
)
1671 if (tevent_req_is_nterror(req
, &status
)) {
1672 netlogon_creds_cli_check_cleanup(req
, status
);
1673 tevent_req_received(req
);
1677 tevent_req_received(req
);
1678 return NT_STATUS_OK
;
1681 NTSTATUS
netlogon_creds_cli_check(struct netlogon_creds_cli_context
*context
,
1682 struct dcerpc_binding_handle
*b
)
1684 TALLOC_CTX
*frame
= talloc_stackframe();
1685 struct tevent_context
*ev
;
1686 struct tevent_req
*req
;
1687 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1689 ev
= samba_tevent_context_init(frame
);
1693 req
= netlogon_creds_cli_check_send(frame
, ev
, context
, b
);
1697 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1700 status
= netlogon_creds_cli_check_recv(req
);
1706 struct netlogon_creds_cli_ServerPasswordSet_state
{
1707 struct tevent_context
*ev
;
1708 struct netlogon_creds_cli_context
*context
;
1709 struct dcerpc_binding_handle
*binding_handle
;
1710 uint32_t old_timeout
;
1712 char *srv_name_slash
;
1713 enum dcerpc_AuthType auth_type
;
1714 enum dcerpc_AuthLevel auth_level
;
1716 struct samr_CryptPassword samr_crypt_password
;
1717 struct netr_CryptPassword netr_crypt_password
;
1718 struct samr_Password samr_password
;
1720 struct netlogon_creds_CredentialState
*creds
;
1721 struct netlogon_creds_CredentialState tmp_creds
;
1722 struct netr_Authenticator req_auth
;
1723 struct netr_Authenticator rep_auth
;
1726 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1728 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
);
1730 struct tevent_req
*netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX
*mem_ctx
,
1731 struct tevent_context
*ev
,
1732 struct netlogon_creds_cli_context
*context
,
1733 struct dcerpc_binding_handle
*b
,
1734 const char *new_password
,
1735 const uint32_t *new_version
)
1737 struct tevent_req
*req
;
1738 struct netlogon_creds_cli_ServerPasswordSet_state
*state
;
1739 struct tevent_req
*subreq
;
1742 req
= tevent_req_create(mem_ctx
, &state
,
1743 struct netlogon_creds_cli_ServerPasswordSet_state
);
1749 state
->context
= context
;
1750 state
->binding_handle
= b
;
1753 * netr_ServerPasswordSet
1755 E_md4hash(new_password
, state
->samr_password
.hash
);
1758 * netr_ServerPasswordSet2
1760 ok
= encode_pw_buffer(state
->samr_crypt_password
.data
,
1761 new_password
, STR_UNICODE
);
1763 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1764 return tevent_req_post(req
, ev
);
1767 if (new_version
!= NULL
) {
1768 struct NL_PASSWORD_VERSION version
;
1769 uint32_t len
= IVAL(state
->samr_crypt_password
.data
, 512);
1770 uint32_t ofs
= 512 - len
;
1774 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1775 return tevent_req_post(req
, ev
);
1779 version
.ReservedField
= 0;
1780 version
.PasswordVersionNumber
= *new_version
;
1781 version
.PasswordVersionPresent
=
1782 NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT
;
1784 p
= state
->samr_crypt_password
.data
+ ofs
;
1785 SIVAL(p
, 0, version
.ReservedField
);
1786 SIVAL(p
, 4, version
.PasswordVersionNumber
);
1787 SIVAL(p
, 8, version
.PasswordVersionPresent
);
1790 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1791 context
->server
.computer
);
1792 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1793 return tevent_req_post(req
, ev
);
1796 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1798 &state
->auth_level
);
1800 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1802 if (tevent_req_nomem(subreq
, req
)) {
1803 return tevent_req_post(req
, ev
);
1806 tevent_req_set_callback(subreq
,
1807 netlogon_creds_cli_ServerPasswordSet_locked
,
1813 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1816 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1817 tevent_req_data(req
,
1818 struct netlogon_creds_cli_ServerPasswordSet_state
);
1820 if (state
->creds
== NULL
) {
1824 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
1825 state
->old_timeout
);
1827 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1828 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1829 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1830 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1831 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1832 TALLOC_FREE(state
->creds
);
1836 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
1839 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
);
1841 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
)
1843 struct tevent_req
*req
=
1844 tevent_req_callback_data(subreq
,
1846 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1847 tevent_req_data(req
,
1848 struct netlogon_creds_cli_ServerPasswordSet_state
);
1851 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1853 TALLOC_FREE(subreq
);
1854 if (tevent_req_nterror(req
, status
)) {
1858 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
1859 switch (state
->auth_level
) {
1860 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1861 case DCERPC_AUTH_LEVEL_PRIVACY
:
1864 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1868 uint32_t tmp
= state
->creds
->negotiate_flags
;
1870 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
1872 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
1873 * it should be used, which means
1874 * we had a chance to verify no downgrade
1877 * This relies on netlogon_creds_cli_check*
1878 * being called before, as first request after
1881 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1886 state
->old_timeout
= dcerpc_binding_handle_set_timeout(
1887 state
->binding_handle
, 600000);
1890 * we defer all callbacks in order to cleanup
1891 * the database record.
1893 tevent_req_defer_callback(req
, state
->ev
);
1895 state
->tmp_creds
= *state
->creds
;
1896 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1898 ZERO_STRUCT(state
->rep_auth
);
1900 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1902 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1903 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
1904 state
->samr_crypt_password
.data
,
1907 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
1908 state
->samr_crypt_password
.data
,
1912 memcpy(state
->netr_crypt_password
.data
,
1913 state
->samr_crypt_password
.data
, 512);
1914 state
->netr_crypt_password
.length
=
1915 IVAL(state
->samr_crypt_password
.data
, 512);
1917 subreq
= dcerpc_netr_ServerPasswordSet2_send(state
, state
->ev
,
1918 state
->binding_handle
,
1919 state
->srv_name_slash
,
1920 state
->tmp_creds
.account_name
,
1921 state
->tmp_creds
.secure_channel_type
,
1922 state
->tmp_creds
.computer_name
,
1925 &state
->netr_crypt_password
);
1926 if (tevent_req_nomem(subreq
, req
)) {
1927 status
= NT_STATUS_NO_MEMORY
;
1928 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1932 netlogon_creds_des_encrypt(&state
->tmp_creds
,
1933 &state
->samr_password
);
1935 subreq
= dcerpc_netr_ServerPasswordSet_send(state
, state
->ev
,
1936 state
->binding_handle
,
1937 state
->srv_name_slash
,
1938 state
->tmp_creds
.account_name
,
1939 state
->tmp_creds
.secure_channel_type
,
1940 state
->tmp_creds
.computer_name
,
1943 &state
->samr_password
);
1944 if (tevent_req_nomem(subreq
, req
)) {
1945 status
= NT_STATUS_NO_MEMORY
;
1946 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1951 tevent_req_set_callback(subreq
,
1952 netlogon_creds_cli_ServerPasswordSet_done
,
1956 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
)
1958 struct tevent_req
*req
=
1959 tevent_req_callback_data(subreq
,
1961 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1962 tevent_req_data(req
,
1963 struct netlogon_creds_cli_ServerPasswordSet_state
);
1968 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1969 status
= dcerpc_netr_ServerPasswordSet2_recv(subreq
, state
,
1971 TALLOC_FREE(subreq
);
1972 if (tevent_req_nterror(req
, status
)) {
1973 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1977 status
= dcerpc_netr_ServerPasswordSet_recv(subreq
, state
,
1979 TALLOC_FREE(subreq
);
1980 if (tevent_req_nterror(req
, status
)) {
1981 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1986 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1987 &state
->rep_auth
.cred
);
1989 status
= NT_STATUS_ACCESS_DENIED
;
1990 tevent_req_nterror(req
, status
);
1991 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1995 if (tevent_req_nterror(req
, result
)) {
1996 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, result
);
2000 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
2001 state
->old_timeout
);
2003 *state
->creds
= state
->tmp_creds
;
2004 status
= netlogon_creds_cli_store(state
->context
,
2006 if (tevent_req_nterror(req
, status
)) {
2007 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2011 tevent_req_done(req
);
2014 NTSTATUS
netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req
*req
)
2018 if (tevent_req_is_nterror(req
, &status
)) {
2019 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2020 tevent_req_received(req
);
2024 tevent_req_received(req
);
2025 return NT_STATUS_OK
;
2028 NTSTATUS
netlogon_creds_cli_ServerPasswordSet(
2029 struct netlogon_creds_cli_context
*context
,
2030 struct dcerpc_binding_handle
*b
,
2031 const char *new_password
,
2032 const uint32_t *new_version
)
2034 TALLOC_CTX
*frame
= talloc_stackframe();
2035 struct tevent_context
*ev
;
2036 struct tevent_req
*req
;
2037 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2039 ev
= samba_tevent_context_init(frame
);
2043 req
= netlogon_creds_cli_ServerPasswordSet_send(frame
, ev
, context
, b
,
2049 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2052 status
= netlogon_creds_cli_ServerPasswordSet_recv(req
);
2058 struct netlogon_creds_cli_LogonSamLogon_state
{
2059 struct tevent_context
*ev
;
2060 struct netlogon_creds_cli_context
*context
;
2061 struct dcerpc_binding_handle
*binding_handle
;
2063 char *srv_name_slash
;
2065 enum netr_LogonInfoClass logon_level
;
2066 const union netr_LogonLevel
*const_logon
;
2067 union netr_LogonLevel
*logon
;
2070 uint16_t validation_level
;
2071 union netr_Validation
*validation
;
2072 uint8_t authoritative
;
2075 * do we need encryption at the application layer?
2079 bool try_validation6
;
2082 * the read only credentials before we started the operation
2084 struct netlogon_creds_CredentialState
*ro_creds
;
2086 struct netlogon_creds_CredentialState
*lk_creds
;
2088 struct netlogon_creds_CredentialState tmp_creds
;
2089 struct netr_Authenticator req_auth
;
2090 struct netr_Authenticator rep_auth
;
2093 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
);
2094 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2097 struct tevent_req
*netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX
*mem_ctx
,
2098 struct tevent_context
*ev
,
2099 struct netlogon_creds_cli_context
*context
,
2100 struct dcerpc_binding_handle
*b
,
2101 enum netr_LogonInfoClass logon_level
,
2102 const union netr_LogonLevel
*logon
,
2105 struct tevent_req
*req
;
2106 struct netlogon_creds_cli_LogonSamLogon_state
*state
;
2108 req
= tevent_req_create(mem_ctx
, &state
,
2109 struct netlogon_creds_cli_LogonSamLogon_state
);
2115 state
->context
= context
;
2116 state
->binding_handle
= b
;
2118 state
->logon_level
= logon_level
;
2119 state
->const_logon
= logon
;
2120 state
->flags
= flags
;
2122 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2123 context
->server
.computer
);
2124 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2125 return tevent_req_post(req
, ev
);
2128 switch (logon_level
) {
2129 case NetlogonInteractiveInformation
:
2130 case NetlogonInteractiveTransitiveInformation
:
2131 case NetlogonServiceInformation
:
2132 case NetlogonServiceTransitiveInformation
:
2133 case NetlogonGenericInformation
:
2134 state
->user_encrypt
= true;
2137 case NetlogonNetworkInformation
:
2138 case NetlogonNetworkTransitiveInformation
:
2142 state
->validation
= talloc_zero(state
, union netr_Validation
);
2143 if (tevent_req_nomem(state
->validation
, req
)) {
2144 return tevent_req_post(req
, ev
);
2147 netlogon_creds_cli_LogonSamLogon_start(req
);
2148 if (!tevent_req_is_in_progress(req
)) {
2149 return tevent_req_post(req
, ev
);
2153 * we defer all callbacks in order to cleanup
2154 * the database record.
2156 tevent_req_defer_callback(req
, state
->ev
);
2160 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2163 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2164 tevent_req_data(req
,
2165 struct netlogon_creds_cli_LogonSamLogon_state
);
2167 if (state
->lk_creds
== NULL
) {
2171 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2173 * This is a hack to recover from a bug in old
2174 * Samba servers, when LogonSamLogonEx() fails:
2176 * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
2178 * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2180 * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE,
2181 * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR
2182 * If the sign/seal check fails.
2184 * In that case we need to cleanup the netlogon session.
2186 * It's the job of the caller to disconnect the current
2187 * connection, if netlogon_creds_cli_LogonSamLogon()
2188 * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2190 if (!state
->context
->server
.try_logon_with
) {
2191 status
= NT_STATUS_NETWORK_ACCESS_DENIED
;
2195 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2196 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2197 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2198 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2199 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2200 TALLOC_FREE(state
->lk_creds
);
2204 netlogon_creds_cli_delete(state
->context
, &state
->lk_creds
);
2207 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
);
2209 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
)
2211 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2212 tevent_req_data(req
,
2213 struct netlogon_creds_cli_LogonSamLogon_state
);
2214 struct tevent_req
*subreq
;
2216 enum dcerpc_AuthType auth_type
;
2217 enum dcerpc_AuthLevel auth_level
;
2219 TALLOC_FREE(state
->ro_creds
);
2220 TALLOC_FREE(state
->logon
);
2221 ZERO_STRUCTP(state
->validation
);
2223 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2224 &auth_type
, &auth_level
);
2226 state
->try_logon_ex
= state
->context
->server
.try_logon_ex
;
2227 state
->try_validation6
= state
->context
->server
.try_validation6
;
2229 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
2230 state
->try_logon_ex
= false;
2233 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
2234 state
->try_validation6
= false;
2237 if (state
->try_logon_ex
) {
2238 if (state
->try_validation6
) {
2239 state
->validation_level
= 6;
2241 state
->validation_level
= 3;
2242 state
->user_encrypt
= true;
2245 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2247 state
->const_logon
);
2248 if (tevent_req_nomem(state
->logon
, req
)) {
2249 status
= NT_STATUS_NO_MEMORY
;
2250 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2254 if (state
->user_encrypt
) {
2255 status
= netlogon_creds_cli_get(state
->context
,
2258 if (!NT_STATUS_IS_OK(status
)) {
2259 status
= NT_STATUS_ACCESS_DENIED
;
2260 tevent_req_nterror(req
, status
);
2261 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2265 netlogon_creds_encrypt_samlogon_logon(state
->ro_creds
,
2270 subreq
= dcerpc_netr_LogonSamLogonEx_send(state
, state
->ev
,
2271 state
->binding_handle
,
2272 state
->srv_name_slash
,
2273 state
->context
->client
.computer
,
2276 state
->validation_level
,
2278 &state
->authoritative
,
2280 if (tevent_req_nomem(subreq
, req
)) {
2281 status
= NT_STATUS_NO_MEMORY
;
2282 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2285 tevent_req_set_callback(subreq
,
2286 netlogon_creds_cli_LogonSamLogon_done
,
2291 if (state
->lk_creds
== NULL
) {
2292 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2294 if (tevent_req_nomem(subreq
, req
)) {
2295 status
= NT_STATUS_NO_MEMORY
;
2296 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2299 tevent_req_set_callback(subreq
,
2300 netlogon_creds_cli_LogonSamLogon_done
,
2305 state
->tmp_creds
= *state
->lk_creds
;
2306 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2308 ZERO_STRUCT(state
->rep_auth
);
2310 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2312 state
->const_logon
);
2313 if (tevent_req_nomem(state
->logon
, req
)) {
2314 status
= NT_STATUS_NO_MEMORY
;
2315 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2319 netlogon_creds_encrypt_samlogon_logon(state
->ro_creds
,
2323 state
->validation_level
= 3;
2325 if (state
->context
->server
.try_logon_with
) {
2326 subreq
= dcerpc_netr_LogonSamLogonWithFlags_send(state
, state
->ev
,
2327 state
->binding_handle
,
2328 state
->srv_name_slash
,
2329 state
->context
->client
.computer
,
2334 state
->validation_level
,
2336 &state
->authoritative
,
2338 if (tevent_req_nomem(subreq
, req
)) {
2339 status
= NT_STATUS_NO_MEMORY
;
2340 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2346 subreq
= dcerpc_netr_LogonSamLogon_send(state
, state
->ev
,
2347 state
->binding_handle
,
2348 state
->srv_name_slash
,
2349 state
->context
->client
.computer
,
2354 state
->validation_level
,
2356 &state
->authoritative
);
2357 if (tevent_req_nomem(subreq
, req
)) {
2358 status
= NT_STATUS_NO_MEMORY
;
2359 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2364 tevent_req_set_callback(subreq
,
2365 netlogon_creds_cli_LogonSamLogon_done
,
2369 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
)
2371 struct tevent_req
*req
=
2372 tevent_req_callback_data(subreq
,
2374 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2375 tevent_req_data(req
,
2376 struct netlogon_creds_cli_LogonSamLogon_state
);
2381 if (state
->try_logon_ex
) {
2382 status
= dcerpc_netr_LogonSamLogonEx_recv(subreq
,
2385 TALLOC_FREE(subreq
);
2386 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2387 state
->context
->server
.try_validation6
= false;
2388 state
->context
->server
.try_logon_ex
= false;
2389 netlogon_creds_cli_LogonSamLogon_start(req
);
2392 if (tevent_req_nterror(req
, status
)) {
2393 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2397 if ((state
->validation_level
== 6) &&
2398 (NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_INFO_CLASS
) ||
2399 NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_PARAMETER
) ||
2400 NT_STATUS_EQUAL(result
, NT_STATUS_BUFFER_TOO_SMALL
)))
2402 state
->context
->server
.try_validation6
= false;
2403 netlogon_creds_cli_LogonSamLogon_start(req
);
2407 if (tevent_req_nterror(req
, result
)) {
2408 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2412 if (state
->ro_creds
== NULL
) {
2413 tevent_req_done(req
);
2417 ok
= netlogon_creds_cli_validate(state
->context
, state
->ro_creds
);
2420 * We got a race, lets retry with on authenticator
2423 TALLOC_FREE(state
->ro_creds
);
2424 state
->try_logon_ex
= false;
2425 netlogon_creds_cli_LogonSamLogon_start(req
);
2429 netlogon_creds_decrypt_samlogon_validation(state
->ro_creds
,
2430 state
->validation_level
,
2433 tevent_req_done(req
);
2437 if (state
->lk_creds
== NULL
) {
2438 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2440 TALLOC_FREE(subreq
);
2441 if (tevent_req_nterror(req
, status
)) {
2442 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2446 netlogon_creds_cli_LogonSamLogon_start(req
);
2450 if (state
->context
->server
.try_logon_with
) {
2451 status
= dcerpc_netr_LogonSamLogonWithFlags_recv(subreq
,
2454 TALLOC_FREE(subreq
);
2455 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2456 state
->context
->server
.try_logon_with
= false;
2457 netlogon_creds_cli_LogonSamLogon_start(req
);
2460 if (tevent_req_nterror(req
, status
)) {
2461 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2465 status
= dcerpc_netr_LogonSamLogon_recv(subreq
,
2468 TALLOC_FREE(subreq
);
2469 if (tevent_req_nterror(req
, status
)) {
2470 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2475 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2476 &state
->rep_auth
.cred
);
2478 status
= NT_STATUS_ACCESS_DENIED
;
2479 tevent_req_nterror(req
, status
);
2480 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2484 *state
->lk_creds
= state
->tmp_creds
;
2485 status
= netlogon_creds_cli_store(state
->context
,
2487 if (tevent_req_nterror(req
, status
)) {
2488 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2492 if (tevent_req_nterror(req
, result
)) {
2493 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2497 netlogon_creds_decrypt_samlogon_validation(&state
->tmp_creds
,
2498 state
->validation_level
,
2501 tevent_req_done(req
);
2504 NTSTATUS
netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req
*req
,
2505 TALLOC_CTX
*mem_ctx
,
2506 uint16_t *validation_level
,
2507 union netr_Validation
**validation
,
2508 uint8_t *authoritative
,
2511 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2512 tevent_req_data(req
,
2513 struct netlogon_creds_cli_LogonSamLogon_state
);
2516 /* authoritative is also returned on error */
2517 *authoritative
= state
->authoritative
;
2519 if (tevent_req_is_nterror(req
, &status
)) {
2520 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2521 tevent_req_received(req
);
2525 *validation_level
= state
->validation_level
;
2526 *validation
= talloc_move(mem_ctx
, &state
->validation
);
2527 *flags
= state
->flags
;
2529 tevent_req_received(req
);
2530 return NT_STATUS_OK
;
2533 NTSTATUS
netlogon_creds_cli_LogonSamLogon(
2534 struct netlogon_creds_cli_context
*context
,
2535 struct dcerpc_binding_handle
*b
,
2536 enum netr_LogonInfoClass logon_level
,
2537 const union netr_LogonLevel
*logon
,
2538 TALLOC_CTX
*mem_ctx
,
2539 uint16_t *validation_level
,
2540 union netr_Validation
**validation
,
2541 uint8_t *authoritative
,
2544 TALLOC_CTX
*frame
= talloc_stackframe();
2545 struct tevent_context
*ev
;
2546 struct tevent_req
*req
;
2547 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2549 ev
= samba_tevent_context_init(frame
);
2553 req
= netlogon_creds_cli_LogonSamLogon_send(frame
, ev
, context
, b
,
2559 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2562 status
= netlogon_creds_cli_LogonSamLogon_recv(req
, mem_ctx
,