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/ndr_netlogon.h"
35 #include "../librpc/gen_ndr/server_id.h"
36 #include "netlogon_creds_cli.h"
37 #include "source3/include/messages.h"
38 #include "source3/include/g_lock.h"
39 #include "libds/common/roles.h"
40 #include "lib/crypto/crypto.h"
42 struct netlogon_creds_cli_locked_state
;
44 struct netlogon_creds_cli_context
{
48 uint32_t proposed_flags
;
49 uint32_t required_flags
;
50 enum netr_SchannelType type
;
51 enum dcerpc_AuthLevel auth_level
;
56 const char *netbios_domain
;
57 uint32_t cached_flags
;
66 struct db_context
*ctx
;
67 struct g_lock_ctx
*g_ctx
;
68 struct netlogon_creds_cli_locked_state
*locked_state
;
72 struct netlogon_creds_cli_locked_state
{
73 struct netlogon_creds_cli_context
*context
;
75 struct netlogon_creds_CredentialState
*creds
;
78 static int netlogon_creds_cli_locked_state_destructor(
79 struct netlogon_creds_cli_locked_state
*state
)
81 struct netlogon_creds_cli_context
*context
= state
->context
;
83 if (context
== NULL
) {
87 if (context
->db
.locked_state
== state
) {
88 context
->db
.locked_state
= NULL
;
91 if (state
->is_glocked
) {
92 g_lock_unlock(context
->db
.g_ctx
,
93 context
->db
.key_name
);
99 static NTSTATUS
netlogon_creds_cli_context_common(
100 const char *client_computer
,
101 const char *client_account
,
102 enum netr_SchannelType type
,
103 enum dcerpc_AuthLevel auth_level
,
104 uint32_t proposed_flags
,
105 uint32_t required_flags
,
106 const char *server_computer
,
107 const char *server_netbios_domain
,
109 struct netlogon_creds_cli_context
**_context
)
111 struct netlogon_creds_cli_context
*context
= NULL
;
112 TALLOC_CTX
*frame
= talloc_stackframe();
113 char *_key_name
= NULL
;
114 char *server_netbios_name
= NULL
;
119 context
= talloc_zero(mem_ctx
, struct netlogon_creds_cli_context
);
120 if (context
== NULL
) {
122 return NT_STATUS_NO_MEMORY
;
125 context
->client
.computer
= talloc_strdup(context
, client_computer
);
126 if (context
->client
.computer
== NULL
) {
127 TALLOC_FREE(context
);
129 return NT_STATUS_NO_MEMORY
;
132 context
->client
.account
= talloc_strdup(context
, client_account
);
133 if (context
->client
.account
== NULL
) {
134 TALLOC_FREE(context
);
136 return NT_STATUS_NO_MEMORY
;
139 context
->client
.proposed_flags
= proposed_flags
;
140 context
->client
.required_flags
= required_flags
;
141 context
->client
.type
= type
;
142 context
->client
.auth_level
= auth_level
;
144 context
->server
.computer
= talloc_strdup(context
, server_computer
);
145 if (context
->server
.computer
== NULL
) {
146 TALLOC_FREE(context
);
148 return NT_STATUS_NO_MEMORY
;
151 context
->server
.netbios_domain
= talloc_strdup(context
, server_netbios_domain
);
152 if (context
->server
.netbios_domain
== NULL
) {
153 TALLOC_FREE(context
);
155 return NT_STATUS_NO_MEMORY
;
160 * Force the callers to provide a unique
161 * value for server_computer and use this directly.
163 * For now we have to deal with
164 * "HOSTNAME" vs. "hostname.example.com".
166 server_netbios_name
= talloc_strdup(frame
, server_computer
);
167 if (server_netbios_name
== NULL
) {
168 TALLOC_FREE(context
);
170 return NT_STATUS_NO_MEMORY
;
173 p
= strchr(server_netbios_name
, '.');
178 _key_name
= talloc_asprintf(frame
, "CLI[%s/%s]/SRV[%s/%s]",
182 server_netbios_domain
);
183 if (_key_name
== NULL
) {
184 TALLOC_FREE(context
);
186 return NT_STATUS_NO_MEMORY
;
189 context
->db
.key_name
= talloc_strdup_upper(context
, _key_name
);
190 if (context
->db
.key_name
== NULL
) {
191 TALLOC_FREE(context
);
193 return NT_STATUS_NO_MEMORY
;
196 context
->db
.key_data
= string_term_tdb_data(context
->db
.key_name
);
203 static struct db_context
*netlogon_creds_cli_global_db
;
205 NTSTATUS
netlogon_creds_cli_set_global_db(struct db_context
**db
)
207 if (netlogon_creds_cli_global_db
!= NULL
) {
208 return NT_STATUS_INVALID_PARAMETER_MIX
;
211 netlogon_creds_cli_global_db
= talloc_move(NULL
, db
);
215 NTSTATUS
netlogon_creds_cli_open_global_db(struct loadparm_context
*lp_ctx
)
218 struct db_context
*global_db
;
220 if (netlogon_creds_cli_global_db
!= NULL
) {
224 fname
= lpcfg_private_db_path(NULL
, lp_ctx
, "netlogon_creds_cli");
226 return NT_STATUS_NO_MEMORY
;
229 global_db
= dbwrap_local_open(NULL
, lp_ctx
,
231 TDB_CLEAR_IF_FIRST
|TDB_INCOMPATIBLE_HASH
,
233 0600, DBWRAP_LOCK_ORDER_2
,
235 if (global_db
== NULL
) {
236 DEBUG(0,("netlogon_creds_cli_open_global_db: Failed to open %s - %s\n",
237 fname
, strerror(errno
)));
239 return NT_STATUS_NO_MEMORY
;
243 netlogon_creds_cli_global_db
= global_db
;
247 void netlogon_creds_cli_close_global_db(void)
249 TALLOC_FREE(netlogon_creds_cli_global_db
);
252 NTSTATUS
netlogon_creds_cli_context_global(struct loadparm_context
*lp_ctx
,
253 struct messaging_context
*msg_ctx
,
254 const char *client_account
,
255 enum netr_SchannelType type
,
256 const char *server_computer
,
257 const char *server_netbios_domain
,
259 struct netlogon_creds_cli_context
**_context
)
261 TALLOC_CTX
*frame
= talloc_stackframe();
263 struct netlogon_creds_cli_context
*context
= NULL
;
264 const char *client_computer
;
265 uint32_t proposed_flags
;
266 uint32_t required_flags
= 0;
267 bool reject_md5_servers
= false;
268 bool require_strong_key
= false;
269 int require_sign_or_seal
= true;
270 bool seal_secure_channel
= true;
271 enum dcerpc_AuthLevel auth_level
= DCERPC_AUTH_LEVEL_NONE
;
272 bool neutralize_nt4_emulation
= false;
276 client_computer
= lpcfg_netbios_name(lp_ctx
);
277 if (strlen(client_computer
) > 15) {
278 return NT_STATUS_INVALID_PARAMETER_MIX
;
282 * allow overwrite per domain
283 * reject md5 servers:<netbios_domain>
285 reject_md5_servers
= lpcfg_reject_md5_servers(lp_ctx
);
286 reject_md5_servers
= lpcfg_parm_bool(lp_ctx
, NULL
,
287 "reject md5 servers",
288 server_netbios_domain
,
292 * allow overwrite per domain
293 * require strong key:<netbios_domain>
295 require_strong_key
= lpcfg_require_strong_key(lp_ctx
);
296 require_strong_key
= lpcfg_parm_bool(lp_ctx
, NULL
,
297 "require strong key",
298 server_netbios_domain
,
302 * allow overwrite per domain
303 * client schannel:<netbios_domain>
305 require_sign_or_seal
= lpcfg_client_schannel(lp_ctx
);
306 require_sign_or_seal
= lpcfg_parm_int(lp_ctx
, NULL
,
308 server_netbios_domain
,
309 require_sign_or_seal
);
312 * allow overwrite per domain
313 * winbind sealed pipes:<netbios_domain>
315 seal_secure_channel
= lpcfg_winbind_sealed_pipes(lp_ctx
);
316 seal_secure_channel
= lpcfg_parm_bool(lp_ctx
, NULL
,
317 "winbind sealed pipes",
318 server_netbios_domain
,
319 seal_secure_channel
);
322 * allow overwrite per domain
323 * neutralize nt4 emulation:<netbios_domain>
325 neutralize_nt4_emulation
= lpcfg_neutralize_nt4_emulation(lp_ctx
);
326 neutralize_nt4_emulation
= lpcfg_parm_bool(lp_ctx
, NULL
,
327 "neutralize nt4 emulation",
328 server_netbios_domain
,
329 neutralize_nt4_emulation
);
331 proposed_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
332 proposed_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
336 if (lpcfg_security(lp_ctx
) == SEC_ADS
) {
338 * AD domains should be secure
340 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
341 require_sign_or_seal
= true;
342 require_strong_key
= true;
346 case SEC_CHAN_DOMAIN
:
349 case SEC_CHAN_DNS_DOMAIN
:
351 * AD domains should be secure
353 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
354 require_sign_or_seal
= true;
355 require_strong_key
= true;
356 neutralize_nt4_emulation
= true;
360 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
361 require_sign_or_seal
= true;
362 require_strong_key
= true;
366 required_flags
|= NETLOGON_NEG_RODC_PASSTHROUGH
;
367 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
368 require_sign_or_seal
= true;
369 require_strong_key
= true;
370 neutralize_nt4_emulation
= true;
375 return NT_STATUS_INVALID_PARAMETER
;
378 if (neutralize_nt4_emulation
) {
379 proposed_flags
|= NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION
;
382 if (require_sign_or_seal
== false) {
383 proposed_flags
&= ~NETLOGON_NEG_AUTHENTICATED_RPC
;
385 required_flags
|= NETLOGON_NEG_ARCFOUR
;
386 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
389 if (reject_md5_servers
) {
390 required_flags
|= NETLOGON_NEG_ARCFOUR
;
391 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
392 required_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
393 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
396 if (require_strong_key
) {
397 required_flags
|= NETLOGON_NEG_ARCFOUR
;
398 required_flags
|= NETLOGON_NEG_STRONG_KEYS
;
399 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
402 proposed_flags
|= required_flags
;
404 if (seal_secure_channel
) {
405 auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
407 auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
410 status
= netlogon_creds_cli_context_common(client_computer
,
417 server_netbios_domain
,
420 if (!NT_STATUS_IS_OK(status
)) {
425 if (msg_ctx
!= NULL
) {
426 context
->db
.g_ctx
= g_lock_ctx_init(context
, msg_ctx
);
427 if (context
->db
.g_ctx
== NULL
) {
428 TALLOC_FREE(context
);
430 return NT_STATUS_NO_MEMORY
;
434 if (netlogon_creds_cli_global_db
!= NULL
) {
435 context
->db
.ctx
= netlogon_creds_cli_global_db
;
441 status
= netlogon_creds_cli_open_global_db(lp_ctx
);
442 if (!NT_STATUS_IS_OK(status
)) {
443 TALLOC_FREE(context
);
445 return NT_STATUS_NO_MEMORY
;
448 context
->db
.ctx
= netlogon_creds_cli_global_db
;
454 NTSTATUS
netlogon_creds_cli_context_tmp(const char *client_computer
,
455 const char *client_account
,
456 enum netr_SchannelType type
,
457 uint32_t proposed_flags
,
458 uint32_t required_flags
,
459 enum dcerpc_AuthLevel auth_level
,
460 const char *server_computer
,
461 const char *server_netbios_domain
,
463 struct netlogon_creds_cli_context
**_context
)
466 struct netlogon_creds_cli_context
*context
= NULL
;
470 status
= netlogon_creds_cli_context_common(client_computer
,
477 server_netbios_domain
,
480 if (!NT_STATUS_IS_OK(status
)) {
484 context
->db
.ctx
= db_open_rbt(context
);
485 if (context
->db
.ctx
== NULL
) {
486 talloc_free(context
);
487 return NT_STATUS_NO_MEMORY
;
494 char *netlogon_creds_cli_debug_string(
495 const struct netlogon_creds_cli_context
*context
,
498 return talloc_asprintf(mem_ctx
, "netlogon_creds_cli:%s",
499 context
->db
.key_name
);
502 enum dcerpc_AuthLevel
netlogon_creds_cli_auth_level(
503 struct netlogon_creds_cli_context
*context
)
505 return context
->client
.auth_level
;
508 struct netlogon_creds_cli_fetch_state
{
510 struct netlogon_creds_CredentialState
*creds
;
511 uint32_t required_flags
;
515 static void netlogon_creds_cli_fetch_parser(TDB_DATA key
, TDB_DATA data
,
518 struct netlogon_creds_cli_fetch_state
*state
=
519 (struct netlogon_creds_cli_fetch_state
*)private_data
;
520 enum ndr_err_code ndr_err
;
524 state
->creds
= talloc_zero(state
->mem_ctx
,
525 struct netlogon_creds_CredentialState
);
526 if (state
->creds
== NULL
) {
527 state
->status
= NT_STATUS_NO_MEMORY
;
531 blob
.data
= data
.dptr
;
532 blob
.length
= data
.dsize
;
534 ndr_err
= ndr_pull_struct_blob(&blob
, state
->creds
, state
->creds
,
535 (ndr_pull_flags_fn_t
)ndr_pull_netlogon_creds_CredentialState
);
536 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
537 TALLOC_FREE(state
->creds
);
538 state
->status
= ndr_map_error2ntstatus(ndr_err
);
542 tmp_flags
= state
->creds
->negotiate_flags
;
543 tmp_flags
&= state
->required_flags
;
544 if (tmp_flags
!= state
->required_flags
) {
545 TALLOC_FREE(state
->creds
);
546 state
->status
= NT_STATUS_DOWNGRADE_DETECTED
;
550 state
->status
= NT_STATUS_OK
;
553 NTSTATUS
netlogon_creds_cli_get(struct netlogon_creds_cli_context
*context
,
555 struct netlogon_creds_CredentialState
**_creds
)
558 struct netlogon_creds_cli_fetch_state fstate
= {
560 .status
= NT_STATUS_INTERNAL_ERROR
,
561 .required_flags
= context
->client
.required_flags
,
563 static const struct netr_Credential zero_creds
;
567 status
= dbwrap_parse_record(context
->db
.ctx
,
568 context
->db
.key_data
,
569 netlogon_creds_cli_fetch_parser
,
571 if (!NT_STATUS_IS_OK(status
)) {
574 status
= fstate
.status
;
575 if (!NT_STATUS_IS_OK(status
)) {
580 * mark it as invalid for step operations.
582 fstate
.creds
->sequence
= 0;
583 fstate
.creds
->seed
= zero_creds
;
584 fstate
.creds
->client
= zero_creds
;
585 fstate
.creds
->server
= zero_creds
;
587 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
588 *_creds
= fstate
.creds
;
593 * It is really important to try SamLogonEx here,
594 * because multiple processes can talk to the same
595 * domain controller, without using the credential
598 * With a normal SamLogon call, we must keep the
599 * credentials chain updated and intact between all
600 * users of the machine account (which would imply
601 * cross-node communication for every NTLM logon).
603 * The credentials chain is not per NETLOGON pipe
604 * connection, but globally on the server/client pair
605 * by computer name, while the client is free to use
606 * any computer name. We include the cluster node number
607 * in our computer name in order to avoid cross node
608 * coordination of the credential chain.
610 * It's also important to use NetlogonValidationSamInfo4 (6),
611 * because it relies on the rpc transport encryption
612 * and avoids using the global netlogon schannel
613 * session key to en/decrypt secret information
614 * like the user_session_key for network logons.
616 * [MS-APDS] 3.1.5.2 NTLM Network Logon
617 * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and
618 * NETLOGON_NEG_AUTHENTICATED_RPC set together
619 * are the indication that the server supports
620 * NetlogonValidationSamInfo4 (6). And it must only
621 * be used if "SealSecureChannel" is used.
623 * The "SealSecureChannel" AUTH_TYPE_SCHANNEL/AUTH_LEVEL_PRIVACY
624 * check is done in netlogon_creds_cli_LogonSamLogon*().
626 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
627 context
->server
.try_validation6
= true;
628 context
->server
.try_logon_ex
= true;
629 context
->server
.try_logon_with
= true;
631 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
632 context
->server
.try_validation6
= false;
633 context
->server
.try_logon_ex
= false;
635 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
636 context
->server
.try_validation6
= false;
639 *_creds
= fstate
.creds
;
643 bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context
*context
,
644 const struct netlogon_creds_CredentialState
*creds1
)
646 TALLOC_CTX
*frame
= talloc_stackframe();
647 struct netlogon_creds_CredentialState
*creds2
;
651 enum ndr_err_code ndr_err
;
654 status
= netlogon_creds_cli_get(context
, frame
, &creds2
);
655 if (!NT_STATUS_IS_OK(status
)) {
660 ndr_err
= ndr_push_struct_blob(&blob1
, frame
, creds1
,
661 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
662 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
667 ndr_err
= ndr_push_struct_blob(&blob2
, frame
, creds2
,
668 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
669 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
674 if (blob1
.length
!= blob2
.length
) {
679 cmp
= memcmp(blob1
.data
, blob2
.data
, blob1
.length
);
689 NTSTATUS
netlogon_creds_cli_store(struct netlogon_creds_cli_context
*context
,
690 struct netlogon_creds_CredentialState
**_creds
)
692 struct netlogon_creds_CredentialState
*creds
= *_creds
;
694 enum ndr_err_code ndr_err
;
700 if (context
->db
.locked_state
== NULL
) {
702 * this was not the result of netlogon_creds_cli_lock*()
705 return NT_STATUS_INVALID_PAGE_PROTECTION
;
708 if (context
->db
.locked_state
->creds
!= creds
) {
710 * this was not the result of netlogon_creds_cli_lock*()
713 return NT_STATUS_INVALID_PAGE_PROTECTION
;
716 ndr_err
= ndr_push_struct_blob(&blob
, creds
, creds
,
717 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
718 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
720 status
= ndr_map_error2ntstatus(ndr_err
);
724 data
.dptr
= blob
.data
;
725 data
.dsize
= blob
.length
;
727 status
= dbwrap_store(context
->db
.ctx
,
728 context
->db
.key_data
,
731 if (!NT_STATUS_IS_OK(status
)) {
738 NTSTATUS
netlogon_creds_cli_delete(struct netlogon_creds_cli_context
*context
,
739 struct netlogon_creds_CredentialState
**_creds
)
741 struct netlogon_creds_CredentialState
*creds
= *_creds
;
746 if (context
->db
.locked_state
== NULL
) {
748 * this was not the result of netlogon_creds_cli_lock*()
751 return NT_STATUS_INVALID_PAGE_PROTECTION
;
754 if (context
->db
.locked_state
->creds
!= creds
) {
756 * this was not the result of netlogon_creds_cli_lock*()
759 return NT_STATUS_INVALID_PAGE_PROTECTION
;
762 status
= dbwrap_delete(context
->db
.ctx
,
763 context
->db
.key_data
);
765 if (!NT_STATUS_IS_OK(status
)) {
772 struct netlogon_creds_cli_lock_state
{
773 struct netlogon_creds_cli_locked_state
*locked_state
;
774 struct netlogon_creds_CredentialState
*creds
;
777 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
);
778 static void netlogon_creds_cli_lock_fetch(struct tevent_req
*req
);
780 struct tevent_req
*netlogon_creds_cli_lock_send(TALLOC_CTX
*mem_ctx
,
781 struct tevent_context
*ev
,
782 struct netlogon_creds_cli_context
*context
)
784 struct tevent_req
*req
;
785 struct netlogon_creds_cli_lock_state
*state
;
786 struct netlogon_creds_cli_locked_state
*locked_state
;
787 struct tevent_req
*subreq
;
789 req
= tevent_req_create(mem_ctx
, &state
,
790 struct netlogon_creds_cli_lock_state
);
795 if (context
->db
.locked_state
!= NULL
) {
796 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
797 return tevent_req_post(req
, ev
);
800 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
801 if (tevent_req_nomem(locked_state
, req
)) {
802 return tevent_req_post(req
, ev
);
804 talloc_set_destructor(locked_state
,
805 netlogon_creds_cli_locked_state_destructor
);
806 locked_state
->context
= context
;
808 context
->db
.locked_state
= locked_state
;
809 state
->locked_state
= locked_state
;
811 if (context
->db
.g_ctx
== NULL
) {
812 netlogon_creds_cli_lock_fetch(req
);
813 if (!tevent_req_is_in_progress(req
)) {
814 return tevent_req_post(req
, ev
);
820 subreq
= g_lock_lock_send(state
, ev
,
822 context
->db
.key_name
,
824 if (tevent_req_nomem(subreq
, req
)) {
825 return tevent_req_post(req
, ev
);
827 tevent_req_set_callback(subreq
, netlogon_creds_cli_lock_done
, req
);
832 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
)
834 struct tevent_req
*req
=
835 tevent_req_callback_data(subreq
,
837 struct netlogon_creds_cli_lock_state
*state
=
839 struct netlogon_creds_cli_lock_state
);
842 status
= g_lock_lock_recv(subreq
);
844 if (tevent_req_nterror(req
, status
)) {
847 state
->locked_state
->is_glocked
= true;
849 netlogon_creds_cli_lock_fetch(req
);
852 static void netlogon_creds_cli_lock_fetch(struct tevent_req
*req
)
854 struct netlogon_creds_cli_lock_state
*state
=
856 struct netlogon_creds_cli_lock_state
);
857 struct netlogon_creds_cli_context
*context
= state
->locked_state
->context
;
858 struct netlogon_creds_cli_fetch_state fstate
= {
859 .status
= NT_STATUS_INTERNAL_ERROR
,
860 .required_flags
= context
->client
.required_flags
,
864 fstate
.mem_ctx
= state
;
865 status
= dbwrap_parse_record(context
->db
.ctx
,
866 context
->db
.key_data
,
867 netlogon_creds_cli_fetch_parser
,
869 if (tevent_req_nterror(req
, status
)) {
872 status
= fstate
.status
;
873 if (tevent_req_nterror(req
, status
)) {
877 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
878 state
->creds
= fstate
.creds
;
879 tevent_req_done(req
);
883 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
884 context
->server
.try_validation6
= true;
885 context
->server
.try_logon_ex
= true;
886 context
->server
.try_logon_with
= true;
888 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
889 context
->server
.try_validation6
= false;
890 context
->server
.try_logon_ex
= false;
892 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
893 context
->server
.try_validation6
= false;
896 state
->creds
= fstate
.creds
;
897 tevent_req_done(req
);
901 NTSTATUS
netlogon_creds_cli_lock_recv(struct tevent_req
*req
,
903 struct netlogon_creds_CredentialState
**creds
)
905 struct netlogon_creds_cli_lock_state
*state
=
907 struct netlogon_creds_cli_lock_state
);
910 if (tevent_req_is_nterror(req
, &status
)) {
911 tevent_req_received(req
);
915 talloc_steal(state
->creds
, state
->locked_state
);
916 state
->locked_state
->creds
= state
->creds
;
917 *creds
= talloc_move(mem_ctx
, &state
->creds
);
918 tevent_req_received(req
);
922 NTSTATUS
netlogon_creds_cli_lock(struct netlogon_creds_cli_context
*context
,
924 struct netlogon_creds_CredentialState
**creds
)
926 TALLOC_CTX
*frame
= talloc_stackframe();
927 struct tevent_context
*ev
;
928 struct tevent_req
*req
;
929 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
931 ev
= samba_tevent_context_init(frame
);
935 req
= netlogon_creds_cli_lock_send(frame
, ev
, context
);
939 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
942 status
= netlogon_creds_cli_lock_recv(req
, mem_ctx
, creds
);
948 struct netlogon_creds_cli_auth_state
{
949 struct tevent_context
*ev
;
950 struct netlogon_creds_cli_context
*context
;
951 struct dcerpc_binding_handle
*binding_handle
;
952 uint8_t num_nt_hashes
;
953 uint8_t idx_nt_hashes
;
954 const struct samr_Password
* const *nt_hashes
;
955 const struct samr_Password
*used_nt_hash
;
956 char *srv_name_slash
;
957 uint32_t current_flags
;
958 struct netr_Credential client_challenge
;
959 struct netr_Credential server_challenge
;
960 struct netlogon_creds_CredentialState
*creds
;
961 struct netr_Credential client_credential
;
962 struct netr_Credential server_credential
;
967 struct netlogon_creds_cli_locked_state
*locked_state
;
970 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
);
971 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
);
973 struct tevent_req
*netlogon_creds_cli_auth_send(TALLOC_CTX
*mem_ctx
,
974 struct tevent_context
*ev
,
975 struct netlogon_creds_cli_context
*context
,
976 struct dcerpc_binding_handle
*b
,
977 uint8_t num_nt_hashes
,
978 const struct samr_Password
* const *nt_hashes
)
980 struct tevent_req
*req
;
981 struct netlogon_creds_cli_auth_state
*state
;
982 struct netlogon_creds_cli_locked_state
*locked_state
;
985 req
= tevent_req_create(mem_ctx
, &state
,
986 struct netlogon_creds_cli_auth_state
);
992 state
->context
= context
;
993 state
->binding_handle
= b
;
994 if (num_nt_hashes
< 1) {
995 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
996 return tevent_req_post(req
, ev
);
998 if (num_nt_hashes
> 4) {
999 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1000 return tevent_req_post(req
, ev
);
1003 state
->num_nt_hashes
= num_nt_hashes
;
1004 state
->idx_nt_hashes
= 0;
1005 state
->nt_hashes
= nt_hashes
;
1007 if (context
->db
.locked_state
!= NULL
) {
1008 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
1009 return tevent_req_post(req
, ev
);
1012 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
1013 if (tevent_req_nomem(locked_state
, req
)) {
1014 return tevent_req_post(req
, ev
);
1016 talloc_set_destructor(locked_state
,
1017 netlogon_creds_cli_locked_state_destructor
);
1018 locked_state
->context
= context
;
1020 context
->db
.locked_state
= locked_state
;
1021 state
->locked_state
= locked_state
;
1023 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1024 context
->server
.computer
);
1025 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1026 return tevent_req_post(req
, ev
);
1029 state
->try_auth3
= true;
1030 state
->try_auth2
= true;
1032 if (context
->client
.required_flags
!= 0) {
1033 state
->require_auth2
= true;
1036 state
->used_nt_hash
= state
->nt_hashes
[state
->idx_nt_hashes
];
1037 state
->current_flags
= context
->client
.proposed_flags
;
1039 if (context
->db
.g_ctx
!= NULL
) {
1040 struct tevent_req
*subreq
;
1042 subreq
= g_lock_lock_send(state
, ev
,
1044 context
->db
.key_name
,
1046 if (tevent_req_nomem(subreq
, req
)) {
1047 return tevent_req_post(req
, ev
);
1049 tevent_req_set_callback(subreq
,
1050 netlogon_creds_cli_auth_locked
,
1056 status
= dbwrap_purge(state
->context
->db
.ctx
,
1057 state
->context
->db
.key_data
);
1058 if (tevent_req_nterror(req
, status
)) {
1059 return tevent_req_post(req
, ev
);
1062 netlogon_creds_cli_auth_challenge_start(req
);
1063 if (!tevent_req_is_in_progress(req
)) {
1064 return tevent_req_post(req
, ev
);
1070 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
)
1072 struct tevent_req
*req
=
1073 tevent_req_callback_data(subreq
,
1075 struct netlogon_creds_cli_auth_state
*state
=
1076 tevent_req_data(req
,
1077 struct netlogon_creds_cli_auth_state
);
1080 status
= g_lock_lock_recv(subreq
);
1081 TALLOC_FREE(subreq
);
1082 if (tevent_req_nterror(req
, status
)) {
1085 state
->locked_state
->is_glocked
= true;
1087 status
= dbwrap_purge(state
->context
->db
.ctx
,
1088 state
->context
->db
.key_data
);
1089 if (tevent_req_nterror(req
, status
)) {
1093 netlogon_creds_cli_auth_challenge_start(req
);
1096 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
);
1098 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
)
1100 struct netlogon_creds_cli_auth_state
*state
=
1101 tevent_req_data(req
,
1102 struct netlogon_creds_cli_auth_state
);
1103 struct tevent_req
*subreq
;
1105 TALLOC_FREE(state
->creds
);
1107 generate_random_buffer(state
->client_challenge
.data
,
1108 sizeof(state
->client_challenge
.data
));
1110 subreq
= dcerpc_netr_ServerReqChallenge_send(state
, state
->ev
,
1111 state
->binding_handle
,
1112 state
->srv_name_slash
,
1113 state
->context
->client
.computer
,
1114 &state
->client_challenge
,
1115 &state
->server_challenge
);
1116 if (tevent_req_nomem(subreq
, req
)) {
1119 tevent_req_set_callback(subreq
,
1120 netlogon_creds_cli_auth_challenge_done
,
1124 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
);
1126 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
)
1128 struct tevent_req
*req
=
1129 tevent_req_callback_data(subreq
,
1131 struct netlogon_creds_cli_auth_state
*state
=
1132 tevent_req_data(req
,
1133 struct netlogon_creds_cli_auth_state
);
1137 status
= dcerpc_netr_ServerReqChallenge_recv(subreq
, state
, &result
);
1138 TALLOC_FREE(subreq
);
1139 if (tevent_req_nterror(req
, status
)) {
1142 if (tevent_req_nterror(req
, result
)) {
1146 if (!state
->try_auth3
&& !state
->try_auth2
) {
1147 state
->current_flags
= 0;
1150 /* Calculate the session key and client credentials */
1152 state
->creds
= netlogon_creds_client_init(state
,
1153 state
->context
->client
.account
,
1154 state
->context
->client
.computer
,
1155 state
->context
->client
.type
,
1156 &state
->client_challenge
,
1157 &state
->server_challenge
,
1158 state
->used_nt_hash
,
1159 &state
->client_credential
,
1160 state
->current_flags
);
1161 if (tevent_req_nomem(state
->creds
, req
)) {
1165 if (state
->try_auth3
) {
1166 subreq
= dcerpc_netr_ServerAuthenticate3_send(state
, state
->ev
,
1167 state
->binding_handle
,
1168 state
->srv_name_slash
,
1169 state
->context
->client
.account
,
1170 state
->context
->client
.type
,
1171 state
->context
->client
.computer
,
1172 &state
->client_credential
,
1173 &state
->server_credential
,
1174 &state
->creds
->negotiate_flags
,
1176 if (tevent_req_nomem(subreq
, req
)) {
1179 } else if (state
->try_auth2
) {
1182 subreq
= dcerpc_netr_ServerAuthenticate2_send(state
, state
->ev
,
1183 state
->binding_handle
,
1184 state
->srv_name_slash
,
1185 state
->context
->client
.account
,
1186 state
->context
->client
.type
,
1187 state
->context
->client
.computer
,
1188 &state
->client_credential
,
1189 &state
->server_credential
,
1190 &state
->creds
->negotiate_flags
);
1191 if (tevent_req_nomem(subreq
, req
)) {
1197 subreq
= dcerpc_netr_ServerAuthenticate_send(state
, state
->ev
,
1198 state
->binding_handle
,
1199 state
->srv_name_slash
,
1200 state
->context
->client
.account
,
1201 state
->context
->client
.type
,
1202 state
->context
->client
.computer
,
1203 &state
->client_credential
,
1204 &state
->server_credential
);
1205 if (tevent_req_nomem(subreq
, req
)) {
1209 tevent_req_set_callback(subreq
,
1210 netlogon_creds_cli_auth_srvauth_done
,
1214 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
)
1216 struct tevent_req
*req
=
1217 tevent_req_callback_data(subreq
,
1219 struct netlogon_creds_cli_auth_state
*state
=
1220 tevent_req_data(req
,
1221 struct netlogon_creds_cli_auth_state
);
1225 enum ndr_err_code ndr_err
;
1230 if (state
->try_auth3
) {
1231 status
= dcerpc_netr_ServerAuthenticate3_recv(subreq
, state
,
1233 TALLOC_FREE(subreq
);
1234 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1235 state
->try_auth3
= false;
1236 netlogon_creds_cli_auth_challenge_start(req
);
1239 if (tevent_req_nterror(req
, status
)) {
1242 } else if (state
->try_auth2
) {
1243 status
= dcerpc_netr_ServerAuthenticate2_recv(subreq
, state
,
1245 TALLOC_FREE(subreq
);
1246 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1247 state
->try_auth2
= false;
1248 if (state
->require_auth2
) {
1249 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1250 tevent_req_nterror(req
, status
);
1253 netlogon_creds_cli_auth_challenge_start(req
);
1256 if (tevent_req_nterror(req
, status
)) {
1260 status
= dcerpc_netr_ServerAuthenticate_recv(subreq
, state
,
1262 TALLOC_FREE(subreq
);
1263 if (tevent_req_nterror(req
, status
)) {
1268 if (!NT_STATUS_IS_OK(result
) &&
1269 !NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
))
1271 tevent_req_nterror(req
, result
);
1275 tmp_flags
= state
->creds
->negotiate_flags
;
1276 tmp_flags
&= state
->context
->client
.required_flags
;
1277 if (tmp_flags
!= state
->context
->client
.required_flags
) {
1278 if (NT_STATUS_IS_OK(result
)) {
1279 tevent_req_nterror(req
, NT_STATUS_DOWNGRADE_DETECTED
);
1282 tevent_req_nterror(req
, result
);
1286 if (NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
)) {
1288 tmp_flags
= state
->context
->client
.proposed_flags
;
1289 if ((state
->current_flags
== tmp_flags
) &&
1290 (state
->creds
->negotiate_flags
!= tmp_flags
))
1293 * lets retry with the negotiated flags
1295 state
->current_flags
= state
->creds
->negotiate_flags
;
1296 netlogon_creds_cli_auth_challenge_start(req
);
1300 state
->idx_nt_hashes
+= 1;
1301 if (state
->idx_nt_hashes
>= state
->num_nt_hashes
) {
1303 * we already retried, giving up...
1305 tevent_req_nterror(req
, result
);
1310 * lets retry with the old nt hash.
1312 state
->used_nt_hash
= state
->nt_hashes
[state
->idx_nt_hashes
];
1313 state
->current_flags
= state
->context
->client
.proposed_flags
;
1314 netlogon_creds_cli_auth_challenge_start(req
);
1318 ok
= netlogon_creds_client_check(state
->creds
,
1319 &state
->server_credential
);
1321 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1325 ndr_err
= ndr_push_struct_blob(&blob
, state
, state
->creds
,
1326 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
1327 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1328 status
= ndr_map_error2ntstatus(ndr_err
);
1329 tevent_req_nterror(req
, status
);
1333 data
.dptr
= blob
.data
;
1334 data
.dsize
= blob
.length
;
1336 status
= dbwrap_store(state
->context
->db
.ctx
,
1337 state
->context
->db
.key_data
,
1339 TALLOC_FREE(state
->locked_state
);
1340 if (tevent_req_nterror(req
, status
)) {
1344 tevent_req_done(req
);
1347 NTSTATUS
netlogon_creds_cli_auth_recv(struct tevent_req
*req
,
1348 uint8_t *idx_nt_hashes
)
1350 struct netlogon_creds_cli_auth_state
*state
=
1351 tevent_req_data(req
,
1352 struct netlogon_creds_cli_auth_state
);
1357 if (tevent_req_is_nterror(req
, &status
)) {
1358 tevent_req_received(req
);
1362 *idx_nt_hashes
= state
->idx_nt_hashes
;
1363 tevent_req_received(req
);
1364 return NT_STATUS_OK
;
1367 NTSTATUS
netlogon_creds_cli_auth(struct netlogon_creds_cli_context
*context
,
1368 struct dcerpc_binding_handle
*b
,
1369 uint8_t num_nt_hashes
,
1370 const struct samr_Password
* const *nt_hashes
,
1371 uint8_t *idx_nt_hashes
)
1373 TALLOC_CTX
*frame
= talloc_stackframe();
1374 struct tevent_context
*ev
;
1375 struct tevent_req
*req
;
1376 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1380 ev
= samba_tevent_context_init(frame
);
1384 req
= netlogon_creds_cli_auth_send(frame
, ev
, context
, b
,
1385 num_nt_hashes
, nt_hashes
);
1389 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1392 status
= netlogon_creds_cli_auth_recv(req
, idx_nt_hashes
);
1398 struct netlogon_creds_cli_check_state
{
1399 struct tevent_context
*ev
;
1400 struct netlogon_creds_cli_context
*context
;
1401 struct dcerpc_binding_handle
*binding_handle
;
1403 char *srv_name_slash
;
1405 union netr_Capabilities caps
;
1407 struct netlogon_creds_CredentialState
*creds
;
1408 struct netlogon_creds_CredentialState tmp_creds
;
1409 struct netr_Authenticator req_auth
;
1410 struct netr_Authenticator rep_auth
;
1413 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1415 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
);
1417 struct tevent_req
*netlogon_creds_cli_check_send(TALLOC_CTX
*mem_ctx
,
1418 struct tevent_context
*ev
,
1419 struct netlogon_creds_cli_context
*context
,
1420 struct dcerpc_binding_handle
*b
)
1422 struct tevent_req
*req
;
1423 struct netlogon_creds_cli_check_state
*state
;
1424 struct tevent_req
*subreq
;
1425 enum dcerpc_AuthType auth_type
;
1426 enum dcerpc_AuthLevel auth_level
;
1428 req
= tevent_req_create(mem_ctx
, &state
,
1429 struct netlogon_creds_cli_check_state
);
1435 state
->context
= context
;
1436 state
->binding_handle
= b
;
1438 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1439 context
->server
.computer
);
1440 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1441 return tevent_req_post(req
, ev
);
1444 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1445 &auth_type
, &auth_level
);
1447 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
1448 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1449 return tevent_req_post(req
, ev
);
1452 switch (auth_level
) {
1453 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1454 case DCERPC_AUTH_LEVEL_PRIVACY
:
1457 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1458 return tevent_req_post(req
, ev
);
1461 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1463 if (tevent_req_nomem(subreq
, req
)) {
1464 return tevent_req_post(req
, ev
);
1467 tevent_req_set_callback(subreq
,
1468 netlogon_creds_cli_check_locked
,
1474 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1477 struct netlogon_creds_cli_check_state
*state
=
1478 tevent_req_data(req
,
1479 struct netlogon_creds_cli_check_state
);
1481 if (state
->creds
== NULL
) {
1485 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1486 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1487 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1488 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1489 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1490 TALLOC_FREE(state
->creds
);
1494 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
1497 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
);
1499 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
)
1501 struct tevent_req
*req
=
1502 tevent_req_callback_data(subreq
,
1504 struct netlogon_creds_cli_check_state
*state
=
1505 tevent_req_data(req
,
1506 struct netlogon_creds_cli_check_state
);
1509 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1511 TALLOC_FREE(subreq
);
1512 if (tevent_req_nterror(req
, status
)) {
1517 * we defer all callbacks in order to cleanup
1518 * the database record.
1520 tevent_req_defer_callback(req
, state
->ev
);
1522 state
->tmp_creds
= *state
->creds
;
1523 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1525 ZERO_STRUCT(state
->rep_auth
);
1527 subreq
= dcerpc_netr_LogonGetCapabilities_send(state
, state
->ev
,
1528 state
->binding_handle
,
1529 state
->srv_name_slash
,
1530 state
->context
->client
.computer
,
1535 if (tevent_req_nomem(subreq
, req
)) {
1536 status
= NT_STATUS_NO_MEMORY
;
1537 netlogon_creds_cli_check_cleanup(req
, status
);
1540 tevent_req_set_callback(subreq
,
1541 netlogon_creds_cli_check_caps
,
1545 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
)
1547 struct tevent_req
*req
=
1548 tevent_req_callback_data(subreq
,
1550 struct netlogon_creds_cli_check_state
*state
=
1551 tevent_req_data(req
,
1552 struct netlogon_creds_cli_check_state
);
1557 status
= dcerpc_netr_LogonGetCapabilities_recv(subreq
, state
,
1559 TALLOC_FREE(subreq
);
1560 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1562 * Note that the negotiated flags are already checked
1563 * for our required flags after the ServerAuthenticate3/2 call.
1565 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1567 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1569 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1570 * already, we expect this to work!
1572 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1573 tevent_req_nterror(req
, status
);
1574 netlogon_creds_cli_check_cleanup(req
, status
);
1578 if (negotiated
& NETLOGON_NEG_STRONG_KEYS
) {
1580 * If we have negotiated NETLOGON_NEG_STRONG_KEYS
1581 * we expect this to work at least as far as the
1582 * NOT_SUPPORTED error handled below!
1584 * NT 4.0 and Old Samba servers are not
1585 * allowed without "require strong key = no"
1587 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1588 tevent_req_nterror(req
, status
);
1589 netlogon_creds_cli_check_cleanup(req
, status
);
1594 * If we not require NETLOGON_NEG_SUPPORTS_AES or
1595 * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore
1596 * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
1598 * This is needed against NT 4.0 and old Samba servers.
1600 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
1601 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
1602 * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
1603 * with the next request as the sequence number processing
1606 netlogon_creds_cli_check_cleanup(req
, status
);
1607 tevent_req_done(req
);
1610 if (tevent_req_nterror(req
, status
)) {
1611 netlogon_creds_cli_check_cleanup(req
, status
);
1615 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOT_IMPLEMENTED
)) {
1617 * Note that the negotiated flags are already checked
1618 * for our required flags after the ServerAuthenticate3/2 call.
1620 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1622 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1624 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1625 * already, we expect this to work!
1627 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1628 tevent_req_nterror(req
, status
);
1629 netlogon_creds_cli_check_cleanup(req
, status
);
1634 * This is ok, the server does not support
1635 * NETLOGON_NEG_SUPPORTS_AES.
1637 * netr_LogonGetCapabilities() was
1638 * netr_LogonDummyRoutine1() before
1639 * NETLOGON_NEG_SUPPORTS_AES was invented.
1641 netlogon_creds_cli_check_cleanup(req
, result
);
1642 tevent_req_done(req
);
1646 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1647 &state
->rep_auth
.cred
);
1649 status
= NT_STATUS_ACCESS_DENIED
;
1650 tevent_req_nterror(req
, status
);
1651 netlogon_creds_cli_check_cleanup(req
, status
);
1655 if (tevent_req_nterror(req
, result
)) {
1656 netlogon_creds_cli_check_cleanup(req
, result
);
1660 if (state
->caps
.server_capabilities
!= state
->tmp_creds
.negotiate_flags
) {
1661 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1662 tevent_req_nterror(req
, status
);
1663 netlogon_creds_cli_check_cleanup(req
, status
);
1668 * This is the key check that makes this check secure. If we
1669 * get OK here (rather than NOT_SUPPORTED), then the server
1670 * did support AES. If the server only proposed STRONG_KEYS
1671 * and not AES, then it should have failed with
1672 * NOT_IMPLEMENTED. We always send AES as a client, so the
1673 * server should always have returned it.
1675 if (!(state
->caps
.server_capabilities
& NETLOGON_NEG_SUPPORTS_AES
)) {
1676 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1677 tevent_req_nterror(req
, status
);
1678 netlogon_creds_cli_check_cleanup(req
, status
);
1682 *state
->creds
= state
->tmp_creds
;
1683 status
= netlogon_creds_cli_store(state
->context
,
1685 netlogon_creds_cli_check_cleanup(req
, status
);
1686 if (tevent_req_nterror(req
, status
)) {
1690 tevent_req_done(req
);
1693 NTSTATUS
netlogon_creds_cli_check_recv(struct tevent_req
*req
)
1697 if (tevent_req_is_nterror(req
, &status
)) {
1698 netlogon_creds_cli_check_cleanup(req
, status
);
1699 tevent_req_received(req
);
1703 tevent_req_received(req
);
1704 return NT_STATUS_OK
;
1707 NTSTATUS
netlogon_creds_cli_check(struct netlogon_creds_cli_context
*context
,
1708 struct dcerpc_binding_handle
*b
)
1710 TALLOC_CTX
*frame
= talloc_stackframe();
1711 struct tevent_context
*ev
;
1712 struct tevent_req
*req
;
1713 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1715 ev
= samba_tevent_context_init(frame
);
1719 req
= netlogon_creds_cli_check_send(frame
, ev
, context
, b
);
1723 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1726 status
= netlogon_creds_cli_check_recv(req
);
1732 struct netlogon_creds_cli_ServerPasswordSet_state
{
1733 struct tevent_context
*ev
;
1734 struct netlogon_creds_cli_context
*context
;
1735 struct dcerpc_binding_handle
*binding_handle
;
1736 uint32_t old_timeout
;
1738 char *srv_name_slash
;
1739 enum dcerpc_AuthType auth_type
;
1740 enum dcerpc_AuthLevel auth_level
;
1742 struct samr_CryptPassword samr_crypt_password
;
1743 struct netr_CryptPassword netr_crypt_password
;
1744 struct samr_Password samr_password
;
1746 struct netlogon_creds_CredentialState
*creds
;
1747 struct netlogon_creds_CredentialState tmp_creds
;
1748 struct netr_Authenticator req_auth
;
1749 struct netr_Authenticator rep_auth
;
1752 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1754 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
);
1756 struct tevent_req
*netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX
*mem_ctx
,
1757 struct tevent_context
*ev
,
1758 struct netlogon_creds_cli_context
*context
,
1759 struct dcerpc_binding_handle
*b
,
1760 const DATA_BLOB
*new_password
,
1761 const uint32_t *new_version
)
1763 struct tevent_req
*req
;
1764 struct netlogon_creds_cli_ServerPasswordSet_state
*state
;
1765 struct tevent_req
*subreq
;
1768 req
= tevent_req_create(mem_ctx
, &state
,
1769 struct netlogon_creds_cli_ServerPasswordSet_state
);
1775 state
->context
= context
;
1776 state
->binding_handle
= b
;
1778 if (new_password
->length
< 14) {
1779 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1780 return tevent_req_post(req
, ev
);
1784 * netr_ServerPasswordSet
1786 mdfour(state
->samr_password
.hash
, new_password
->data
, new_password
->length
);
1789 * netr_ServerPasswordSet2
1791 ok
= set_pw_in_buffer(state
->samr_crypt_password
.data
,
1794 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1795 return tevent_req_post(req
, ev
);
1798 if (new_version
!= NULL
) {
1799 struct NL_PASSWORD_VERSION version
;
1800 uint32_t len
= IVAL(state
->samr_crypt_password
.data
, 512);
1801 uint32_t ofs
= 512 - len
;
1805 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1806 return tevent_req_post(req
, ev
);
1810 version
.ReservedField
= 0;
1811 version
.PasswordVersionNumber
= *new_version
;
1812 version
.PasswordVersionPresent
=
1813 NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT
;
1815 p
= state
->samr_crypt_password
.data
+ ofs
;
1816 SIVAL(p
, 0, version
.ReservedField
);
1817 SIVAL(p
, 4, version
.PasswordVersionNumber
);
1818 SIVAL(p
, 8, version
.PasswordVersionPresent
);
1821 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1822 context
->server
.computer
);
1823 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1824 return tevent_req_post(req
, ev
);
1827 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1829 &state
->auth_level
);
1831 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1833 if (tevent_req_nomem(subreq
, req
)) {
1834 return tevent_req_post(req
, ev
);
1837 tevent_req_set_callback(subreq
,
1838 netlogon_creds_cli_ServerPasswordSet_locked
,
1844 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1847 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1848 tevent_req_data(req
,
1849 struct netlogon_creds_cli_ServerPasswordSet_state
);
1851 if (state
->creds
== NULL
) {
1855 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
1856 state
->old_timeout
);
1858 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1859 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1860 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1861 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1862 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1863 TALLOC_FREE(state
->creds
);
1867 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
1870 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
);
1872 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
)
1874 struct tevent_req
*req
=
1875 tevent_req_callback_data(subreq
,
1877 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1878 tevent_req_data(req
,
1879 struct netlogon_creds_cli_ServerPasswordSet_state
);
1882 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1884 TALLOC_FREE(subreq
);
1885 if (tevent_req_nterror(req
, status
)) {
1889 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
1890 switch (state
->auth_level
) {
1891 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1892 case DCERPC_AUTH_LEVEL_PRIVACY
:
1895 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1899 uint32_t tmp
= state
->creds
->negotiate_flags
;
1901 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
1903 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
1904 * it should be used, which means
1905 * we had a chance to verify no downgrade
1908 * This relies on netlogon_creds_cli_check*
1909 * being called before, as first request after
1912 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1917 state
->old_timeout
= dcerpc_binding_handle_set_timeout(
1918 state
->binding_handle
, 600000);
1921 * we defer all callbacks in order to cleanup
1922 * the database record.
1924 tevent_req_defer_callback(req
, state
->ev
);
1926 state
->tmp_creds
= *state
->creds
;
1927 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1929 ZERO_STRUCT(state
->rep_auth
);
1931 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1933 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1934 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
1935 state
->samr_crypt_password
.data
,
1938 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
1939 state
->samr_crypt_password
.data
,
1943 memcpy(state
->netr_crypt_password
.data
,
1944 state
->samr_crypt_password
.data
, 512);
1945 state
->netr_crypt_password
.length
=
1946 IVAL(state
->samr_crypt_password
.data
, 512);
1948 subreq
= dcerpc_netr_ServerPasswordSet2_send(state
, state
->ev
,
1949 state
->binding_handle
,
1950 state
->srv_name_slash
,
1951 state
->tmp_creds
.account_name
,
1952 state
->tmp_creds
.secure_channel_type
,
1953 state
->tmp_creds
.computer_name
,
1956 &state
->netr_crypt_password
);
1957 if (tevent_req_nomem(subreq
, req
)) {
1958 status
= NT_STATUS_NO_MEMORY
;
1959 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1963 netlogon_creds_des_encrypt(&state
->tmp_creds
,
1964 &state
->samr_password
);
1966 subreq
= dcerpc_netr_ServerPasswordSet_send(state
, state
->ev
,
1967 state
->binding_handle
,
1968 state
->srv_name_slash
,
1969 state
->tmp_creds
.account_name
,
1970 state
->tmp_creds
.secure_channel_type
,
1971 state
->tmp_creds
.computer_name
,
1974 &state
->samr_password
);
1975 if (tevent_req_nomem(subreq
, req
)) {
1976 status
= NT_STATUS_NO_MEMORY
;
1977 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1982 tevent_req_set_callback(subreq
,
1983 netlogon_creds_cli_ServerPasswordSet_done
,
1987 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
)
1989 struct tevent_req
*req
=
1990 tevent_req_callback_data(subreq
,
1992 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1993 tevent_req_data(req
,
1994 struct netlogon_creds_cli_ServerPasswordSet_state
);
1999 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
2000 status
= dcerpc_netr_ServerPasswordSet2_recv(subreq
, state
,
2002 TALLOC_FREE(subreq
);
2003 if (tevent_req_nterror(req
, status
)) {
2004 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2008 status
= dcerpc_netr_ServerPasswordSet_recv(subreq
, state
,
2010 TALLOC_FREE(subreq
);
2011 if (tevent_req_nterror(req
, status
)) {
2012 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2017 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2018 &state
->rep_auth
.cred
);
2020 status
= NT_STATUS_ACCESS_DENIED
;
2021 tevent_req_nterror(req
, status
);
2022 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2026 if (tevent_req_nterror(req
, result
)) {
2027 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, result
);
2031 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
2032 state
->old_timeout
);
2034 *state
->creds
= state
->tmp_creds
;
2035 status
= netlogon_creds_cli_store(state
->context
,
2037 if (tevent_req_nterror(req
, status
)) {
2038 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2042 tevent_req_done(req
);
2045 NTSTATUS
netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req
*req
)
2049 if (tevent_req_is_nterror(req
, &status
)) {
2050 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2051 tevent_req_received(req
);
2055 tevent_req_received(req
);
2056 return NT_STATUS_OK
;
2059 NTSTATUS
netlogon_creds_cli_ServerPasswordSet(
2060 struct netlogon_creds_cli_context
*context
,
2061 struct dcerpc_binding_handle
*b
,
2062 const DATA_BLOB
*new_password
,
2063 const uint32_t *new_version
)
2065 TALLOC_CTX
*frame
= talloc_stackframe();
2066 struct tevent_context
*ev
;
2067 struct tevent_req
*req
;
2068 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2070 ev
= samba_tevent_context_init(frame
);
2074 req
= netlogon_creds_cli_ServerPasswordSet_send(frame
, ev
, context
, b
,
2080 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2083 status
= netlogon_creds_cli_ServerPasswordSet_recv(req
);
2089 struct netlogon_creds_cli_LogonSamLogon_state
{
2090 struct tevent_context
*ev
;
2091 struct netlogon_creds_cli_context
*context
;
2092 struct dcerpc_binding_handle
*binding_handle
;
2094 char *srv_name_slash
;
2096 enum netr_LogonInfoClass logon_level
;
2097 const union netr_LogonLevel
*const_logon
;
2098 union netr_LogonLevel
*logon
;
2101 uint16_t validation_level
;
2102 union netr_Validation
*validation
;
2103 uint8_t authoritative
;
2106 * do we need encryption at the application layer?
2110 bool try_validation6
;
2113 * the read only credentials before we started the operation
2114 * used for netr_LogonSamLogonEx() if required (validation_level = 3).
2116 struct netlogon_creds_CredentialState
*ro_creds
;
2119 * The (locked) credentials used for the credential chain
2120 * used for netr_LogonSamLogonWithFlags() or
2121 * netr_LogonSamLogonWith().
2123 struct netlogon_creds_CredentialState
*lk_creds
;
2126 * While we have locked the global credentials (lk_creds above)
2127 * we operate an a temporary copy, because a server
2128 * may not support netr_LogonSamLogonWithFlags() and
2129 * didn't process our netr_Authenticator, so we need to
2130 * restart from lk_creds.
2132 struct netlogon_creds_CredentialState tmp_creds
;
2133 struct netr_Authenticator req_auth
;
2134 struct netr_Authenticator rep_auth
;
2137 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
);
2138 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2141 struct tevent_req
*netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX
*mem_ctx
,
2142 struct tevent_context
*ev
,
2143 struct netlogon_creds_cli_context
*context
,
2144 struct dcerpc_binding_handle
*b
,
2145 enum netr_LogonInfoClass logon_level
,
2146 const union netr_LogonLevel
*logon
,
2149 struct tevent_req
*req
;
2150 struct netlogon_creds_cli_LogonSamLogon_state
*state
;
2152 req
= tevent_req_create(mem_ctx
, &state
,
2153 struct netlogon_creds_cli_LogonSamLogon_state
);
2159 state
->context
= context
;
2160 state
->binding_handle
= b
;
2162 state
->logon_level
= logon_level
;
2163 state
->const_logon
= logon
;
2164 state
->flags
= flags
;
2166 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2167 context
->server
.computer
);
2168 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2169 return tevent_req_post(req
, ev
);
2172 switch (logon_level
) {
2173 case NetlogonInteractiveInformation
:
2174 case NetlogonInteractiveTransitiveInformation
:
2175 case NetlogonServiceInformation
:
2176 case NetlogonServiceTransitiveInformation
:
2177 case NetlogonGenericInformation
:
2178 state
->user_encrypt
= true;
2181 case NetlogonNetworkInformation
:
2182 case NetlogonNetworkTransitiveInformation
:
2186 state
->validation
= talloc_zero(state
, union netr_Validation
);
2187 if (tevent_req_nomem(state
->validation
, req
)) {
2188 return tevent_req_post(req
, ev
);
2191 netlogon_creds_cli_LogonSamLogon_start(req
);
2192 if (!tevent_req_is_in_progress(req
)) {
2193 return tevent_req_post(req
, ev
);
2197 * we defer all callbacks in order to cleanup
2198 * the database record.
2200 tevent_req_defer_callback(req
, state
->ev
);
2204 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2207 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2208 tevent_req_data(req
,
2209 struct netlogon_creds_cli_LogonSamLogon_state
);
2211 if (state
->lk_creds
== NULL
) {
2215 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2217 * This is a hack to recover from a bug in old
2218 * Samba servers, when LogonSamLogonEx() fails:
2220 * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
2222 * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2224 * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE,
2225 * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR
2226 * If the sign/seal check fails.
2228 * In that case we need to cleanup the netlogon session.
2230 * It's the job of the caller to disconnect the current
2231 * connection, if netlogon_creds_cli_LogonSamLogon()
2232 * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2234 if (!state
->context
->server
.try_logon_with
) {
2235 status
= NT_STATUS_NETWORK_ACCESS_DENIED
;
2239 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2240 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2241 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2242 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2243 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2244 TALLOC_FREE(state
->lk_creds
);
2248 netlogon_creds_cli_delete(state
->context
, &state
->lk_creds
);
2251 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
);
2253 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
)
2255 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2256 tevent_req_data(req
,
2257 struct netlogon_creds_cli_LogonSamLogon_state
);
2258 struct tevent_req
*subreq
;
2260 enum dcerpc_AuthType auth_type
;
2261 enum dcerpc_AuthLevel auth_level
;
2263 TALLOC_FREE(state
->ro_creds
);
2264 TALLOC_FREE(state
->logon
);
2265 ZERO_STRUCTP(state
->validation
);
2267 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2268 &auth_type
, &auth_level
);
2270 state
->try_logon_ex
= state
->context
->server
.try_logon_ex
;
2271 state
->try_validation6
= state
->context
->server
.try_validation6
;
2273 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
2274 state
->try_logon_ex
= false;
2277 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
2278 state
->try_validation6
= false;
2281 if (state
->try_logon_ex
) {
2282 if (state
->try_validation6
) {
2283 state
->validation_level
= 6;
2285 state
->validation_level
= 3;
2286 state
->user_encrypt
= true;
2289 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2291 state
->const_logon
);
2292 if (tevent_req_nomem(state
->logon
, req
)) {
2293 status
= NT_STATUS_NO_MEMORY
;
2294 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2298 if (state
->user_encrypt
) {
2299 status
= netlogon_creds_cli_get(state
->context
,
2302 if (!NT_STATUS_IS_OK(status
)) {
2303 status
= NT_STATUS_ACCESS_DENIED
;
2304 tevent_req_nterror(req
, status
);
2305 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2309 netlogon_creds_encrypt_samlogon_logon(state
->ro_creds
,
2314 subreq
= dcerpc_netr_LogonSamLogonEx_send(state
, state
->ev
,
2315 state
->binding_handle
,
2316 state
->srv_name_slash
,
2317 state
->context
->client
.computer
,
2320 state
->validation_level
,
2322 &state
->authoritative
,
2324 if (tevent_req_nomem(subreq
, req
)) {
2325 status
= NT_STATUS_NO_MEMORY
;
2326 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2329 tevent_req_set_callback(subreq
,
2330 netlogon_creds_cli_LogonSamLogon_done
,
2335 if (state
->lk_creds
== NULL
) {
2336 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2338 if (tevent_req_nomem(subreq
, req
)) {
2339 status
= NT_STATUS_NO_MEMORY
;
2340 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2343 tevent_req_set_callback(subreq
,
2344 netlogon_creds_cli_LogonSamLogon_done
,
2349 state
->tmp_creds
= *state
->lk_creds
;
2350 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2352 ZERO_STRUCT(state
->rep_auth
);
2354 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2356 state
->const_logon
);
2357 if (tevent_req_nomem(state
->logon
, req
)) {
2358 status
= NT_STATUS_NO_MEMORY
;
2359 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2363 netlogon_creds_encrypt_samlogon_logon(&state
->tmp_creds
,
2367 state
->validation_level
= 3;
2369 if (state
->context
->server
.try_logon_with
) {
2370 subreq
= dcerpc_netr_LogonSamLogonWithFlags_send(state
, state
->ev
,
2371 state
->binding_handle
,
2372 state
->srv_name_slash
,
2373 state
->context
->client
.computer
,
2378 state
->validation_level
,
2380 &state
->authoritative
,
2382 if (tevent_req_nomem(subreq
, req
)) {
2383 status
= NT_STATUS_NO_MEMORY
;
2384 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2390 subreq
= dcerpc_netr_LogonSamLogon_send(state
, state
->ev
,
2391 state
->binding_handle
,
2392 state
->srv_name_slash
,
2393 state
->context
->client
.computer
,
2398 state
->validation_level
,
2400 &state
->authoritative
);
2401 if (tevent_req_nomem(subreq
, req
)) {
2402 status
= NT_STATUS_NO_MEMORY
;
2403 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2408 tevent_req_set_callback(subreq
,
2409 netlogon_creds_cli_LogonSamLogon_done
,
2413 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
)
2415 struct tevent_req
*req
=
2416 tevent_req_callback_data(subreq
,
2418 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2419 tevent_req_data(req
,
2420 struct netlogon_creds_cli_LogonSamLogon_state
);
2425 if (state
->try_logon_ex
) {
2426 status
= dcerpc_netr_LogonSamLogonEx_recv(subreq
,
2429 TALLOC_FREE(subreq
);
2430 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2431 state
->context
->server
.try_validation6
= false;
2432 state
->context
->server
.try_logon_ex
= false;
2433 netlogon_creds_cli_LogonSamLogon_start(req
);
2436 if (tevent_req_nterror(req
, status
)) {
2437 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2441 if ((state
->validation_level
== 6) &&
2442 (NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_INFO_CLASS
) ||
2443 NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_PARAMETER
) ||
2444 NT_STATUS_EQUAL(result
, NT_STATUS_BUFFER_TOO_SMALL
)))
2446 state
->context
->server
.try_validation6
= false;
2447 netlogon_creds_cli_LogonSamLogon_start(req
);
2451 if (tevent_req_nterror(req
, result
)) {
2452 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2456 if (state
->ro_creds
== NULL
) {
2457 tevent_req_done(req
);
2461 ok
= netlogon_creds_cli_validate(state
->context
, state
->ro_creds
);
2464 * We got a race, lets retry with on authenticator
2467 * netlogon_creds_cli_LogonSamLogon_start()
2468 * will TALLOC_FREE(state->ro_creds);
2470 state
->try_logon_ex
= false;
2471 netlogon_creds_cli_LogonSamLogon_start(req
);
2475 netlogon_creds_decrypt_samlogon_validation(state
->ro_creds
,
2476 state
->validation_level
,
2479 tevent_req_done(req
);
2483 if (state
->lk_creds
== NULL
) {
2484 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2486 TALLOC_FREE(subreq
);
2487 if (tevent_req_nterror(req
, status
)) {
2488 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2492 netlogon_creds_cli_LogonSamLogon_start(req
);
2496 if (state
->context
->server
.try_logon_with
) {
2497 status
= dcerpc_netr_LogonSamLogonWithFlags_recv(subreq
,
2500 TALLOC_FREE(subreq
);
2501 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2502 state
->context
->server
.try_logon_with
= false;
2503 netlogon_creds_cli_LogonSamLogon_start(req
);
2506 if (tevent_req_nterror(req
, status
)) {
2507 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2511 status
= dcerpc_netr_LogonSamLogon_recv(subreq
,
2514 TALLOC_FREE(subreq
);
2515 if (tevent_req_nterror(req
, status
)) {
2516 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2521 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2522 &state
->rep_auth
.cred
);
2524 status
= NT_STATUS_ACCESS_DENIED
;
2525 tevent_req_nterror(req
, status
);
2526 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2530 *state
->lk_creds
= state
->tmp_creds
;
2531 status
= netlogon_creds_cli_store(state
->context
,
2533 if (tevent_req_nterror(req
, status
)) {
2534 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2538 if (tevent_req_nterror(req
, result
)) {
2539 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2543 netlogon_creds_decrypt_samlogon_validation(&state
->tmp_creds
,
2544 state
->validation_level
,
2547 tevent_req_done(req
);
2550 NTSTATUS
netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req
*req
,
2551 TALLOC_CTX
*mem_ctx
,
2552 uint16_t *validation_level
,
2553 union netr_Validation
**validation
,
2554 uint8_t *authoritative
,
2557 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2558 tevent_req_data(req
,
2559 struct netlogon_creds_cli_LogonSamLogon_state
);
2562 /* authoritative is also returned on error */
2563 *authoritative
= state
->authoritative
;
2565 if (tevent_req_is_nterror(req
, &status
)) {
2566 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2567 tevent_req_received(req
);
2571 *validation_level
= state
->validation_level
;
2572 *validation
= talloc_move(mem_ctx
, &state
->validation
);
2573 *flags
= state
->flags
;
2575 tevent_req_received(req
);
2576 return NT_STATUS_OK
;
2579 NTSTATUS
netlogon_creds_cli_LogonSamLogon(
2580 struct netlogon_creds_cli_context
*context
,
2581 struct dcerpc_binding_handle
*b
,
2582 enum netr_LogonInfoClass logon_level
,
2583 const union netr_LogonLevel
*logon
,
2584 TALLOC_CTX
*mem_ctx
,
2585 uint16_t *validation_level
,
2586 union netr_Validation
**validation
,
2587 uint8_t *authoritative
,
2590 TALLOC_CTX
*frame
= talloc_stackframe();
2591 struct tevent_context
*ev
;
2592 struct tevent_req
*req
;
2593 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2595 ev
= samba_tevent_context_init(frame
);
2599 req
= netlogon_creds_cli_LogonSamLogon_send(frame
, ev
, context
, b
,
2605 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2608 status
= netlogon_creds_cli_LogonSamLogon_recv(req
, mem_ctx
,
2618 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
{
2619 struct tevent_context
*ev
;
2620 struct netlogon_creds_cli_context
*context
;
2621 struct dcerpc_binding_handle
*binding_handle
;
2623 char *srv_name_slash
;
2624 enum dcerpc_AuthType auth_type
;
2625 enum dcerpc_AuthLevel auth_level
;
2627 const char *site_name
;
2629 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
;
2631 struct netlogon_creds_CredentialState
*creds
;
2632 struct netlogon_creds_CredentialState tmp_creds
;
2633 struct netr_Authenticator req_auth
;
2634 struct netr_Authenticator rep_auth
;
2637 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2639 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
);
2641 struct tevent_req
*netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(TALLOC_CTX
*mem_ctx
,
2642 struct tevent_context
*ev
,
2643 struct netlogon_creds_cli_context
*context
,
2644 struct dcerpc_binding_handle
*b
,
2645 const char *site_name
,
2647 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2649 struct tevent_req
*req
;
2650 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
;
2651 struct tevent_req
*subreq
;
2653 req
= tevent_req_create(mem_ctx
, &state
,
2654 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2660 state
->context
= context
;
2661 state
->binding_handle
= b
;
2663 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2664 context
->server
.computer
);
2665 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2666 return tevent_req_post(req
, ev
);
2669 state
->site_name
= site_name
;
2670 state
->dns_ttl
= dns_ttl
;
2671 state
->dns_names
= dns_names
;
2673 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2675 &state
->auth_level
);
2677 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2679 if (tevent_req_nomem(subreq
, req
)) {
2680 return tevent_req_post(req
, ev
);
2683 tevent_req_set_callback(subreq
,
2684 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked
,
2690 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2693 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2694 tevent_req_data(req
,
2695 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2697 if (state
->creds
== NULL
) {
2701 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2702 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2703 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2704 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2705 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2706 TALLOC_FREE(state
->creds
);
2710 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
2713 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
);
2715 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
)
2717 struct tevent_req
*req
=
2718 tevent_req_callback_data(subreq
,
2720 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2721 tevent_req_data(req
,
2722 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2725 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2727 TALLOC_FREE(subreq
);
2728 if (tevent_req_nterror(req
, status
)) {
2732 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
2733 switch (state
->auth_level
) {
2734 case DCERPC_AUTH_LEVEL_INTEGRITY
:
2735 case DCERPC_AUTH_LEVEL_PRIVACY
:
2738 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2742 uint32_t tmp
= state
->creds
->negotiate_flags
;
2744 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
2746 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
2747 * it should be used, which means
2748 * we had a chance to verify no downgrade
2751 * This relies on netlogon_creds_cli_check*
2752 * being called before, as first request after
2755 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2761 * we defer all callbacks in order to cleanup
2762 * the database record.
2764 tevent_req_defer_callback(req
, state
->ev
);
2766 state
->tmp_creds
= *state
->creds
;
2767 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2769 ZERO_STRUCT(state
->rep_auth
);
2771 subreq
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_send(state
, state
->ev
,
2772 state
->binding_handle
,
2773 state
->srv_name_slash
,
2774 state
->tmp_creds
.computer_name
,
2780 if (tevent_req_nomem(subreq
, req
)) {
2781 status
= NT_STATUS_NO_MEMORY
;
2782 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2786 tevent_req_set_callback(subreq
,
2787 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done
,
2791 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
)
2793 struct tevent_req
*req
=
2794 tevent_req_callback_data(subreq
,
2796 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2797 tevent_req_data(req
,
2798 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2804 * We use state->dns_names as the memory context, as this is
2805 * the only in/out variable and it has been overwritten by the
2806 * out parameter from the server.
2808 * We need to preserve the return value until the caller can use it.
2810 status
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_recv(subreq
, state
->dns_names
,
2812 TALLOC_FREE(subreq
);
2813 if (tevent_req_nterror(req
, status
)) {
2814 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2818 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2819 &state
->rep_auth
.cred
);
2821 status
= NT_STATUS_ACCESS_DENIED
;
2822 tevent_req_nterror(req
, status
);
2823 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2827 *state
->creds
= state
->tmp_creds
;
2828 status
= netlogon_creds_cli_store(state
->context
,
2831 if (tevent_req_nterror(req
, status
)) {
2832 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2836 if (tevent_req_nterror(req
, result
)) {
2837 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, result
);
2841 tevent_req_done(req
);
2844 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(struct tevent_req
*req
)
2848 if (tevent_req_is_nterror(req
, &status
)) {
2849 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2850 tevent_req_received(req
);
2854 tevent_req_received(req
);
2855 return NT_STATUS_OK
;
2858 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(
2859 struct netlogon_creds_cli_context
*context
,
2860 struct dcerpc_binding_handle
*b
,
2861 const char *site_name
,
2863 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2865 TALLOC_CTX
*frame
= talloc_stackframe();
2866 struct tevent_context
*ev
;
2867 struct tevent_req
*req
;
2868 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2870 ev
= samba_tevent_context_init(frame
);
2874 req
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(frame
, ev
, context
, b
,
2881 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2884 status
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(req
);
2890 struct netlogon_creds_cli_ServerGetTrustInfo_state
{
2891 struct tevent_context
*ev
;
2892 struct netlogon_creds_cli_context
*context
;
2893 struct dcerpc_binding_handle
*binding_handle
;
2895 char *srv_name_slash
;
2896 enum dcerpc_AuthType auth_type
;
2897 enum dcerpc_AuthLevel auth_level
;
2899 struct samr_Password new_owf_password
;
2900 struct samr_Password old_owf_password
;
2901 struct netr_TrustInfo
*trust_info
;
2903 struct netlogon_creds_CredentialState
*creds
;
2904 struct netlogon_creds_CredentialState tmp_creds
;
2905 struct netr_Authenticator req_auth
;
2906 struct netr_Authenticator rep_auth
;
2909 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
2911 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
);
2913 struct tevent_req
*netlogon_creds_cli_ServerGetTrustInfo_send(TALLOC_CTX
*mem_ctx
,
2914 struct tevent_context
*ev
,
2915 struct netlogon_creds_cli_context
*context
,
2916 struct dcerpc_binding_handle
*b
)
2918 struct tevent_req
*req
;
2919 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
;
2920 struct tevent_req
*subreq
;
2922 req
= tevent_req_create(mem_ctx
, &state
,
2923 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2929 state
->context
= context
;
2930 state
->binding_handle
= b
;
2932 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2933 context
->server
.computer
);
2934 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2935 return tevent_req_post(req
, ev
);
2938 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2940 &state
->auth_level
);
2942 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2944 if (tevent_req_nomem(subreq
, req
)) {
2945 return tevent_req_post(req
, ev
);
2948 tevent_req_set_callback(subreq
,
2949 netlogon_creds_cli_ServerGetTrustInfo_locked
,
2955 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
2958 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2959 tevent_req_data(req
,
2960 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2962 if (state
->creds
== NULL
) {
2966 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2967 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2968 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2969 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2970 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2971 TALLOC_FREE(state
->creds
);
2975 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
2978 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
);
2980 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
)
2982 struct tevent_req
*req
=
2983 tevent_req_callback_data(subreq
,
2985 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2986 tevent_req_data(req
,
2987 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2990 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2992 TALLOC_FREE(subreq
);
2993 if (tevent_req_nterror(req
, status
)) {
2997 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
2998 switch (state
->auth_level
) {
2999 case DCERPC_AUTH_LEVEL_PRIVACY
:
3002 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3006 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3011 * we defer all callbacks in order to cleanup
3012 * the database record.
3014 tevent_req_defer_callback(req
, state
->ev
);
3016 state
->tmp_creds
= *state
->creds
;
3017 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3019 ZERO_STRUCT(state
->rep_auth
);
3021 subreq
= dcerpc_netr_ServerGetTrustInfo_send(state
, state
->ev
,
3022 state
->binding_handle
,
3023 state
->srv_name_slash
,
3024 state
->tmp_creds
.account_name
,
3025 state
->tmp_creds
.secure_channel_type
,
3026 state
->tmp_creds
.computer_name
,
3029 &state
->new_owf_password
,
3030 &state
->old_owf_password
,
3031 &state
->trust_info
);
3032 if (tevent_req_nomem(subreq
, req
)) {
3033 status
= NT_STATUS_NO_MEMORY
;
3034 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3038 tevent_req_set_callback(subreq
,
3039 netlogon_creds_cli_ServerGetTrustInfo_done
,
3043 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
)
3045 struct tevent_req
*req
=
3046 tevent_req_callback_data(subreq
,
3048 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3049 tevent_req_data(req
,
3050 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3053 const struct samr_Password zero
= {};
3058 * We use state->dns_names as the memory context, as this is
3059 * the only in/out variable and it has been overwritten by the
3060 * out parameter from the server.
3062 * We need to preserve the return value until the caller can use it.
3064 status
= dcerpc_netr_ServerGetTrustInfo_recv(subreq
, state
, &result
);
3065 TALLOC_FREE(subreq
);
3066 if (tevent_req_nterror(req
, status
)) {
3067 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3071 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3072 &state
->rep_auth
.cred
);
3074 status
= NT_STATUS_ACCESS_DENIED
;
3075 tevent_req_nterror(req
, status
);
3076 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3080 cmp
= memcmp(state
->new_owf_password
.hash
,
3081 zero
.hash
, sizeof(zero
.hash
));
3083 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3084 &state
->new_owf_password
);
3086 cmp
= memcmp(state
->old_owf_password
.hash
,
3087 zero
.hash
, sizeof(zero
.hash
));
3089 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3090 &state
->old_owf_password
);
3093 *state
->creds
= state
->tmp_creds
;
3094 status
= netlogon_creds_cli_store(state
->context
,
3096 if (tevent_req_nterror(req
, status
)) {
3097 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3101 if (tevent_req_nterror(req
, result
)) {
3102 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, result
);
3106 tevent_req_done(req
);
3109 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo_recv(struct tevent_req
*req
,
3110 TALLOC_CTX
*mem_ctx
,
3111 struct samr_Password
*new_owf_password
,
3112 struct samr_Password
*old_owf_password
,
3113 struct netr_TrustInfo
**trust_info
)
3115 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3116 tevent_req_data(req
,
3117 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3120 if (tevent_req_is_nterror(req
, &status
)) {
3121 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3122 tevent_req_received(req
);
3126 if (new_owf_password
!= NULL
) {
3127 *new_owf_password
= state
->new_owf_password
;
3129 if (old_owf_password
!= NULL
) {
3130 *old_owf_password
= state
->old_owf_password
;
3132 if (trust_info
!= NULL
) {
3133 *trust_info
= talloc_move(mem_ctx
, &state
->trust_info
);
3136 tevent_req_received(req
);
3137 return NT_STATUS_OK
;
3140 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo(
3141 struct netlogon_creds_cli_context
*context
,
3142 struct dcerpc_binding_handle
*b
,
3143 TALLOC_CTX
*mem_ctx
,
3144 struct samr_Password
*new_owf_password
,
3145 struct samr_Password
*old_owf_password
,
3146 struct netr_TrustInfo
**trust_info
)
3148 TALLOC_CTX
*frame
= talloc_stackframe();
3149 struct tevent_context
*ev
;
3150 struct tevent_req
*req
;
3151 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3153 ev
= samba_tevent_context_init(frame
);
3157 req
= netlogon_creds_cli_ServerGetTrustInfo_send(frame
, ev
, context
, b
);
3161 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3164 status
= netlogon_creds_cli_ServerGetTrustInfo_recv(req
,
3174 struct netlogon_creds_cli_GetForestTrustInformation_state
{
3175 struct tevent_context
*ev
;
3176 struct netlogon_creds_cli_context
*context
;
3177 struct dcerpc_binding_handle
*binding_handle
;
3179 char *srv_name_slash
;
3180 enum dcerpc_AuthType auth_type
;
3181 enum dcerpc_AuthLevel auth_level
;
3184 struct lsa_ForestTrustInformation
*forest_trust_info
;
3186 struct netlogon_creds_CredentialState
*creds
;
3187 struct netlogon_creds_CredentialState tmp_creds
;
3188 struct netr_Authenticator req_auth
;
3189 struct netr_Authenticator rep_auth
;
3192 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3194 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
);
3196 struct tevent_req
*netlogon_creds_cli_GetForestTrustInformation_send(TALLOC_CTX
*mem_ctx
,
3197 struct tevent_context
*ev
,
3198 struct netlogon_creds_cli_context
*context
,
3199 struct dcerpc_binding_handle
*b
)
3201 struct tevent_req
*req
;
3202 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
;
3203 struct tevent_req
*subreq
;
3205 req
= tevent_req_create(mem_ctx
, &state
,
3206 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3212 state
->context
= context
;
3213 state
->binding_handle
= b
;
3215 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3216 context
->server
.computer
);
3217 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3218 return tevent_req_post(req
, ev
);
3223 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3225 &state
->auth_level
);
3227 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3229 if (tevent_req_nomem(subreq
, req
)) {
3230 return tevent_req_post(req
, ev
);
3233 tevent_req_set_callback(subreq
,
3234 netlogon_creds_cli_GetForestTrustInformation_locked
,
3240 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3243 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3244 tevent_req_data(req
,
3245 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3247 if (state
->creds
== NULL
) {
3251 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3252 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3253 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3254 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3255 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3256 TALLOC_FREE(state
->creds
);
3260 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
3263 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
);
3265 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
)
3267 struct tevent_req
*req
=
3268 tevent_req_callback_data(subreq
,
3270 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3271 tevent_req_data(req
,
3272 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3275 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3277 TALLOC_FREE(subreq
);
3278 if (tevent_req_nterror(req
, status
)) {
3282 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3283 switch (state
->auth_level
) {
3284 case DCERPC_AUTH_LEVEL_INTEGRITY
:
3285 case DCERPC_AUTH_LEVEL_PRIVACY
:
3288 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3292 uint32_t tmp
= state
->creds
->negotiate_flags
;
3294 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
3296 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3297 * it should be used, which means
3298 * we had a chance to verify no downgrade
3301 * This relies on netlogon_creds_cli_check*
3302 * being called before, as first request after
3305 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3311 * we defer all callbacks in order to cleanup
3312 * the database record.
3314 tevent_req_defer_callback(req
, state
->ev
);
3316 state
->tmp_creds
= *state
->creds
;
3317 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3319 ZERO_STRUCT(state
->rep_auth
);
3321 subreq
= dcerpc_netr_GetForestTrustInformation_send(state
, state
->ev
,
3322 state
->binding_handle
,
3323 state
->srv_name_slash
,
3324 state
->tmp_creds
.computer_name
,
3328 &state
->forest_trust_info
);
3329 if (tevent_req_nomem(subreq
, req
)) {
3330 status
= NT_STATUS_NO_MEMORY
;
3331 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3335 tevent_req_set_callback(subreq
,
3336 netlogon_creds_cli_GetForestTrustInformation_done
,
3340 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
)
3342 struct tevent_req
*req
=
3343 tevent_req_callback_data(subreq
,
3345 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3346 tevent_req_data(req
,
3347 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3353 * We use state->dns_names as the memory context, as this is
3354 * the only in/out variable and it has been overwritten by the
3355 * out parameter from the server.
3357 * We need to preserve the return value until the caller can use it.
3359 status
= dcerpc_netr_GetForestTrustInformation_recv(subreq
, state
, &result
);
3360 TALLOC_FREE(subreq
);
3361 if (tevent_req_nterror(req
, status
)) {
3362 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3366 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3367 &state
->rep_auth
.cred
);
3369 status
= NT_STATUS_ACCESS_DENIED
;
3370 tevent_req_nterror(req
, status
);
3371 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3375 *state
->creds
= state
->tmp_creds
;
3376 status
= netlogon_creds_cli_store(state
->context
,
3379 if (tevent_req_nterror(req
, status
)) {
3380 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3384 if (tevent_req_nterror(req
, result
)) {
3385 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, result
);
3389 tevent_req_done(req
);
3392 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation_recv(struct tevent_req
*req
,
3393 TALLOC_CTX
*mem_ctx
,
3394 struct lsa_ForestTrustInformation
**forest_trust_info
)
3396 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3397 tevent_req_data(req
,
3398 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3401 if (tevent_req_is_nterror(req
, &status
)) {
3402 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3403 tevent_req_received(req
);
3407 *forest_trust_info
= talloc_move(mem_ctx
, &state
->forest_trust_info
);
3409 tevent_req_received(req
);
3410 return NT_STATUS_OK
;
3413 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation(
3414 struct netlogon_creds_cli_context
*context
,
3415 struct dcerpc_binding_handle
*b
,
3416 TALLOC_CTX
*mem_ctx
,
3417 struct lsa_ForestTrustInformation
**forest_trust_info
)
3419 TALLOC_CTX
*frame
= talloc_stackframe();
3420 struct tevent_context
*ev
;
3421 struct tevent_req
*req
;
3422 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3424 ev
= samba_tevent_context_init(frame
);
3428 req
= netlogon_creds_cli_GetForestTrustInformation_send(frame
, ev
, context
, b
);
3432 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3435 status
= netlogon_creds_cli_GetForestTrustInformation_recv(req
,
3443 struct netlogon_creds_cli_SendToSam_state
{
3444 struct tevent_context
*ev
;
3445 struct netlogon_creds_cli_context
*context
;
3446 struct dcerpc_binding_handle
*binding_handle
;
3448 char *srv_name_slash
;
3449 enum dcerpc_AuthType auth_type
;
3450 enum dcerpc_AuthLevel auth_level
;
3454 struct netlogon_creds_CredentialState
*creds
;
3455 struct netlogon_creds_CredentialState tmp_creds
;
3456 struct netr_Authenticator req_auth
;
3457 struct netr_Authenticator rep_auth
;
3460 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req
*req
,
3462 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req
*subreq
);
3464 struct tevent_req
*netlogon_creds_cli_SendToSam_send(TALLOC_CTX
*mem_ctx
,
3465 struct tevent_context
*ev
,
3466 struct netlogon_creds_cli_context
*context
,
3467 struct dcerpc_binding_handle
*b
,
3468 struct netr_SendToSamBase
*message
)
3470 struct tevent_req
*req
;
3471 struct netlogon_creds_cli_SendToSam_state
*state
;
3472 struct tevent_req
*subreq
;
3473 enum ndr_err_code ndr_err
;
3475 req
= tevent_req_create(mem_ctx
, &state
,
3476 struct netlogon_creds_cli_SendToSam_state
);
3482 state
->context
= context
;
3483 state
->binding_handle
= b
;
3485 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3486 context
->server
.computer
);
3487 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3488 return tevent_req_post(req
, ev
);
3491 ndr_err
= ndr_push_struct_blob(&state
->opaque
, mem_ctx
, message
,
3492 (ndr_push_flags_fn_t
)ndr_push_netr_SendToSamBase
);
3493 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
3494 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
3495 tevent_req_nterror(req
, status
);
3496 return tevent_req_post(req
, ev
);
3499 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3501 &state
->auth_level
);
3503 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3505 if (tevent_req_nomem(subreq
, req
)) {
3506 return tevent_req_post(req
, ev
);
3509 tevent_req_set_callback(subreq
,
3510 netlogon_creds_cli_SendToSam_locked
,
3516 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req
*req
,
3519 struct netlogon_creds_cli_SendToSam_state
*state
=
3520 tevent_req_data(req
,
3521 struct netlogon_creds_cli_SendToSam_state
);
3523 if (state
->creds
== NULL
) {
3527 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3528 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3529 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3530 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3531 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3532 TALLOC_FREE(state
->creds
);
3536 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
3539 static void netlogon_creds_cli_SendToSam_done(struct tevent_req
*subreq
);
3541 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req
*subreq
)
3543 struct tevent_req
*req
=
3544 tevent_req_callback_data(subreq
,
3546 struct netlogon_creds_cli_SendToSam_state
*state
=
3547 tevent_req_data(req
,
3548 struct netlogon_creds_cli_SendToSam_state
);
3551 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3553 TALLOC_FREE(subreq
);
3554 if (tevent_req_nterror(req
, status
)) {
3558 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3559 switch (state
->auth_level
) {
3560 case DCERPC_AUTH_LEVEL_INTEGRITY
:
3561 case DCERPC_AUTH_LEVEL_PRIVACY
:
3564 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3568 uint32_t tmp
= state
->creds
->negotiate_flags
;
3570 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
3572 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3573 * it should be used, which means
3574 * we had a chance to verify no downgrade
3577 * This relies on netlogon_creds_cli_check*
3578 * being called before, as first request after
3581 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3587 * we defer all callbacks in order to cleanup
3588 * the database record.
3590 tevent_req_defer_callback(req
, state
->ev
);
3592 state
->tmp_creds
= *state
->creds
;
3593 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3595 ZERO_STRUCT(state
->rep_auth
);
3597 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
3598 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
3600 state
->opaque
.length
);
3602 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
3604 state
->opaque
.length
);
3607 subreq
= dcerpc_netr_NetrLogonSendToSam_send(state
, state
->ev
,
3608 state
->binding_handle
,
3609 state
->srv_name_slash
,
3610 state
->tmp_creds
.computer_name
,
3614 state
->opaque
.length
);
3615 if (tevent_req_nomem(subreq
, req
)) {
3616 status
= NT_STATUS_NO_MEMORY
;
3617 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3621 tevent_req_set_callback(subreq
,
3622 netlogon_creds_cli_SendToSam_done
,
3626 static void netlogon_creds_cli_SendToSam_done(struct tevent_req
*subreq
)
3628 struct tevent_req
*req
=
3629 tevent_req_callback_data(subreq
,
3631 struct netlogon_creds_cli_SendToSam_state
*state
=
3632 tevent_req_data(req
,
3633 struct netlogon_creds_cli_SendToSam_state
);
3638 status
= dcerpc_netr_NetrLogonSendToSam_recv(subreq
, state
, &result
);
3639 TALLOC_FREE(subreq
);
3640 if (tevent_req_nterror(req
, status
)) {
3641 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3645 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3646 &state
->rep_auth
.cred
);
3648 status
= NT_STATUS_ACCESS_DENIED
;
3649 tevent_req_nterror(req
, status
);
3650 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3654 *state
->creds
= state
->tmp_creds
;
3655 status
= netlogon_creds_cli_store(state
->context
,
3658 if (tevent_req_nterror(req
, status
)) {
3659 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3664 * Creds must be stored before we send back application errors
3665 * e.g. NT_STATUS_NOT_IMPLEMENTED
3667 if (tevent_req_nterror(req
, result
)) {
3668 netlogon_creds_cli_SendToSam_cleanup(req
, result
);
3672 tevent_req_done(req
);
3675 NTSTATUS
netlogon_creds_cli_SendToSam(struct netlogon_creds_cli_context
*context
,
3676 struct dcerpc_binding_handle
*b
,
3677 struct netr_SendToSamBase
*message
)
3679 TALLOC_CTX
*frame
= talloc_stackframe();
3680 struct tevent_context
*ev
;
3681 struct tevent_req
*req
;
3682 NTSTATUS status
= NT_STATUS_OK
;
3684 ev
= samba_tevent_context_init(frame
);
3688 req
= netlogon_creds_cli_SendToSam_send(frame
, ev
, context
, b
, message
);
3692 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3696 /* Ignore the result */