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 const char *dns_domain
;
58 uint32_t cached_flags
;
67 struct db_context
*ctx
;
68 struct g_lock_ctx
*g_ctx
;
69 struct netlogon_creds_cli_locked_state
*locked_state
;
73 struct netlogon_creds_cli_locked_state
{
74 struct netlogon_creds_cli_context
*context
;
76 struct netlogon_creds_CredentialState
*creds
;
79 static int netlogon_creds_cli_locked_state_destructor(
80 struct netlogon_creds_cli_locked_state
*state
)
82 struct netlogon_creds_cli_context
*context
= state
->context
;
84 if (context
== NULL
) {
88 if (context
->db
.locked_state
== state
) {
89 context
->db
.locked_state
= NULL
;
92 if (state
->is_glocked
) {
93 g_lock_unlock(context
->db
.g_ctx
,
94 context
->db
.key_name
);
100 static NTSTATUS
netlogon_creds_cli_context_common(
101 const char *client_computer
,
102 const char *client_account
,
103 enum netr_SchannelType type
,
104 enum dcerpc_AuthLevel auth_level
,
105 uint32_t proposed_flags
,
106 uint32_t required_flags
,
107 const char *server_computer
,
108 const char *server_netbios_domain
,
109 const char *server_dns_domain
,
111 struct netlogon_creds_cli_context
**_context
)
113 struct netlogon_creds_cli_context
*context
= NULL
;
114 char *_key_name
= NULL
;
115 size_t server_netbios_name_len
;
120 context
= talloc_zero(mem_ctx
, struct netlogon_creds_cli_context
);
121 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
);
128 return NT_STATUS_NO_MEMORY
;
131 context
->client
.account
= talloc_strdup(context
, client_account
);
132 if (context
->client
.account
== NULL
) {
133 TALLOC_FREE(context
);
134 return NT_STATUS_NO_MEMORY
;
137 context
->client
.proposed_flags
= proposed_flags
;
138 context
->client
.required_flags
= required_flags
;
139 context
->client
.type
= type
;
140 context
->client
.auth_level
= auth_level
;
142 context
->server
.computer
= talloc_strdup(context
, server_computer
);
143 if (context
->server
.computer
== NULL
) {
144 TALLOC_FREE(context
);
145 return NT_STATUS_NO_MEMORY
;
148 context
->server
.netbios_domain
= talloc_strdup(context
, server_netbios_domain
);
149 if (context
->server
.netbios_domain
== NULL
) {
150 TALLOC_FREE(context
);
151 return NT_STATUS_NO_MEMORY
;
154 context
->server
.dns_domain
= talloc_strdup(context
, server_dns_domain
);
155 if (context
->server
.dns_domain
== NULL
) {
156 TALLOC_FREE(context
);
157 return NT_STATUS_NO_MEMORY
;
162 * Force the callers to provide a unique
163 * value for server_computer and use this directly.
165 * For now we have to deal with
166 * "HOSTNAME" vs. "hostname.example.com".
169 p
= strchr(server_computer
, '.');
171 server_netbios_name_len
= p
-server_computer
;
173 server_netbios_name_len
= strlen(server_computer
);
176 _key_name
= talloc_asprintf(context
, "CLI[%s/%s]/SRV[%.*s/%s]",
179 (int)server_netbios_name_len
,
181 server_netbios_domain
);
182 if (_key_name
== NULL
) {
183 TALLOC_FREE(context
);
184 return NT_STATUS_NO_MEMORY
;
187 context
->db
.key_name
= talloc_strdup_upper(context
, _key_name
);
188 TALLOC_FREE(_key_name
);
189 if (context
->db
.key_name
== NULL
) {
190 TALLOC_FREE(context
);
191 return NT_STATUS_NO_MEMORY
;
194 context
->db
.key_data
= string_term_tdb_data(context
->db
.key_name
);
200 static struct db_context
*netlogon_creds_cli_global_db
;
202 NTSTATUS
netlogon_creds_cli_set_global_db(struct db_context
**db
)
204 if (netlogon_creds_cli_global_db
!= NULL
) {
205 return NT_STATUS_INVALID_PARAMETER_MIX
;
208 netlogon_creds_cli_global_db
= talloc_move(NULL
, db
);
212 NTSTATUS
netlogon_creds_cli_open_global_db(struct loadparm_context
*lp_ctx
)
215 struct db_context
*global_db
;
217 if (netlogon_creds_cli_global_db
!= NULL
) {
221 fname
= lpcfg_private_db_path(NULL
, lp_ctx
, "netlogon_creds_cli");
223 return NT_STATUS_NO_MEMORY
;
226 global_db
= dbwrap_local_open(NULL
, lp_ctx
,
228 TDB_CLEAR_IF_FIRST
|TDB_INCOMPATIBLE_HASH
,
230 0600, DBWRAP_LOCK_ORDER_2
,
232 if (global_db
== NULL
) {
233 DEBUG(0,("netlogon_creds_cli_open_global_db: Failed to open %s - %s\n",
234 fname
, strerror(errno
)));
236 return NT_STATUS_NO_MEMORY
;
240 netlogon_creds_cli_global_db
= global_db
;
244 void netlogon_creds_cli_close_global_db(void)
246 TALLOC_FREE(netlogon_creds_cli_global_db
);
249 NTSTATUS
netlogon_creds_cli_context_global(struct loadparm_context
*lp_ctx
,
250 struct messaging_context
*msg_ctx
,
251 const char *client_account
,
252 enum netr_SchannelType type
,
253 const char *server_computer
,
254 const char *server_netbios_domain
,
255 const char *server_dns_domain
,
257 struct netlogon_creds_cli_context
**_context
)
259 TALLOC_CTX
*frame
= talloc_stackframe();
261 struct netlogon_creds_cli_context
*context
= NULL
;
262 const char *client_computer
;
263 uint32_t proposed_flags
;
264 uint32_t required_flags
= 0;
265 bool reject_md5_servers
= false;
266 bool require_strong_key
= false;
267 int require_sign_or_seal
= true;
268 bool seal_secure_channel
= true;
269 enum dcerpc_AuthLevel auth_level
= DCERPC_AUTH_LEVEL_NONE
;
270 bool neutralize_nt4_emulation
= false;
274 if (msg_ctx
== NULL
) {
276 return NT_STATUS_INVALID_PARAMETER_MIX
;
279 client_computer
= lpcfg_netbios_name(lp_ctx
);
280 if (strlen(client_computer
) > 15) {
282 return NT_STATUS_INVALID_PARAMETER_MIX
;
286 * allow overwrite per domain
287 * reject md5 servers:<netbios_domain>
289 reject_md5_servers
= lpcfg_reject_md5_servers(lp_ctx
);
290 reject_md5_servers
= lpcfg_parm_bool(lp_ctx
, NULL
,
291 "reject md5 servers",
292 server_netbios_domain
,
296 * allow overwrite per domain
297 * require strong key:<netbios_domain>
299 require_strong_key
= lpcfg_require_strong_key(lp_ctx
);
300 require_strong_key
= lpcfg_parm_bool(lp_ctx
, NULL
,
301 "require strong key",
302 server_netbios_domain
,
306 * allow overwrite per domain
307 * client schannel:<netbios_domain>
309 require_sign_or_seal
= lpcfg_client_schannel(lp_ctx
);
310 require_sign_or_seal
= lpcfg_parm_int(lp_ctx
, NULL
,
312 server_netbios_domain
,
313 require_sign_or_seal
);
316 * allow overwrite per domain
317 * winbind sealed pipes:<netbios_domain>
319 seal_secure_channel
= lpcfg_winbind_sealed_pipes(lp_ctx
);
320 seal_secure_channel
= lpcfg_parm_bool(lp_ctx
, NULL
,
321 "winbind sealed pipes",
322 server_netbios_domain
,
323 seal_secure_channel
);
326 * allow overwrite per domain
327 * neutralize nt4 emulation:<netbios_domain>
329 neutralize_nt4_emulation
= lpcfg_neutralize_nt4_emulation(lp_ctx
);
330 neutralize_nt4_emulation
= lpcfg_parm_bool(lp_ctx
, NULL
,
331 "neutralize nt4 emulation",
332 server_netbios_domain
,
333 neutralize_nt4_emulation
);
335 proposed_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
336 proposed_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
340 if (lpcfg_security(lp_ctx
) == SEC_ADS
) {
342 * AD domains should be secure
344 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
345 require_sign_or_seal
= true;
346 require_strong_key
= true;
350 case SEC_CHAN_DOMAIN
:
353 case SEC_CHAN_DNS_DOMAIN
:
355 * AD domains should be secure
357 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
358 require_sign_or_seal
= true;
359 require_strong_key
= true;
360 neutralize_nt4_emulation
= true;
364 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
365 require_sign_or_seal
= true;
366 require_strong_key
= true;
370 required_flags
|= NETLOGON_NEG_RODC_PASSTHROUGH
;
371 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
372 require_sign_or_seal
= true;
373 require_strong_key
= true;
374 neutralize_nt4_emulation
= true;
379 return NT_STATUS_INVALID_PARAMETER
;
382 if (neutralize_nt4_emulation
) {
383 proposed_flags
|= NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION
;
386 if (require_sign_or_seal
) {
387 required_flags
|= NETLOGON_NEG_ARCFOUR
;
388 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
390 proposed_flags
&= ~NETLOGON_NEG_AUTHENTICATED_RPC
;
393 if (reject_md5_servers
) {
394 required_flags
|= NETLOGON_NEG_ARCFOUR
;
395 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
396 required_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
397 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
400 if (require_strong_key
) {
401 required_flags
|= NETLOGON_NEG_ARCFOUR
;
402 required_flags
|= NETLOGON_NEG_STRONG_KEYS
;
403 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
406 proposed_flags
|= required_flags
;
408 if (seal_secure_channel
) {
409 auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
411 auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
414 status
= netlogon_creds_cli_context_common(client_computer
,
421 server_netbios_domain
,
425 if (!NT_STATUS_IS_OK(status
)) {
430 context
->db
.g_ctx
= g_lock_ctx_init(context
, msg_ctx
);
431 if (context
->db
.g_ctx
== NULL
) {
432 TALLOC_FREE(context
);
434 return NT_STATUS_NO_MEMORY
;
437 status
= netlogon_creds_cli_open_global_db(lp_ctx
);
438 if (!NT_STATUS_IS_OK(status
)) {
439 TALLOC_FREE(context
);
441 return NT_STATUS_NO_MEMORY
;
444 context
->db
.ctx
= netlogon_creds_cli_global_db
;
450 NTSTATUS
netlogon_creds_cli_context_tmp(const char *client_computer
,
451 const char *client_account
,
452 enum netr_SchannelType type
,
453 uint32_t proposed_flags
,
454 uint32_t required_flags
,
455 enum dcerpc_AuthLevel auth_level
,
456 const char *server_computer
,
457 const char *server_netbios_domain
,
459 struct netlogon_creds_cli_context
**_context
)
462 struct netlogon_creds_cli_context
*context
= NULL
;
466 status
= netlogon_creds_cli_context_common(client_computer
,
473 server_netbios_domain
,
477 if (!NT_STATUS_IS_OK(status
)) {
481 context
->db
.ctx
= db_open_rbt(context
);
482 if (context
->db
.ctx
== NULL
) {
483 talloc_free(context
);
484 return NT_STATUS_NO_MEMORY
;
491 char *netlogon_creds_cli_debug_string(
492 const struct netlogon_creds_cli_context
*context
,
495 return talloc_asprintf(mem_ctx
, "netlogon_creds_cli:%s",
496 context
->db
.key_name
);
499 enum dcerpc_AuthLevel
netlogon_creds_cli_auth_level(
500 struct netlogon_creds_cli_context
*context
)
502 return context
->client
.auth_level
;
505 struct netlogon_creds_cli_fetch_state
{
507 struct netlogon_creds_CredentialState
*creds
;
508 uint32_t required_flags
;
512 static void netlogon_creds_cli_fetch_parser(TDB_DATA key
, TDB_DATA data
,
515 struct netlogon_creds_cli_fetch_state
*state
=
516 (struct netlogon_creds_cli_fetch_state
*)private_data
;
517 enum ndr_err_code ndr_err
;
521 state
->creds
= talloc_zero(state
->mem_ctx
,
522 struct netlogon_creds_CredentialState
);
523 if (state
->creds
== NULL
) {
524 state
->status
= NT_STATUS_NO_MEMORY
;
528 blob
.data
= data
.dptr
;
529 blob
.length
= data
.dsize
;
531 ndr_err
= ndr_pull_struct_blob(&blob
, state
->creds
, state
->creds
,
532 (ndr_pull_flags_fn_t
)ndr_pull_netlogon_creds_CredentialState
);
533 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
534 TALLOC_FREE(state
->creds
);
535 state
->status
= ndr_map_error2ntstatus(ndr_err
);
539 tmp_flags
= state
->creds
->negotiate_flags
;
540 tmp_flags
&= state
->required_flags
;
541 if (tmp_flags
!= state
->required_flags
) {
542 TALLOC_FREE(state
->creds
);
543 state
->status
= NT_STATUS_DOWNGRADE_DETECTED
;
547 state
->status
= NT_STATUS_OK
;
550 NTSTATUS
netlogon_creds_cli_get(struct netlogon_creds_cli_context
*context
,
552 struct netlogon_creds_CredentialState
**_creds
)
555 struct netlogon_creds_cli_fetch_state fstate
= {
557 .status
= NT_STATUS_INTERNAL_ERROR
,
558 .required_flags
= context
->client
.required_flags
,
563 status
= dbwrap_parse_record(context
->db
.ctx
,
564 context
->db
.key_data
,
565 netlogon_creds_cli_fetch_parser
,
567 if (!NT_STATUS_IS_OK(status
)) {
570 status
= fstate
.status
;
571 if (!NT_STATUS_IS_OK(status
)) {
576 * mark it as invalid for step operations.
578 fstate
.creds
->sequence
= 0;
579 fstate
.creds
->seed
= (struct netr_Credential
) {{0}};
580 fstate
.creds
->client
= (struct netr_Credential
) {{0}};
581 fstate
.creds
->server
= (struct netr_Credential
) {{0}};
583 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
584 *_creds
= fstate
.creds
;
589 * It is really important to try SamLogonEx here,
590 * because multiple processes can talk to the same
591 * domain controller, without using the credential
594 * With a normal SamLogon call, we must keep the
595 * credentials chain updated and intact between all
596 * users of the machine account (which would imply
597 * cross-node communication for every NTLM logon).
599 * The credentials chain is not per NETLOGON pipe
600 * connection, but globally on the server/client pair
603 * It's also important to use NetlogonValidationSamInfo4 (6),
604 * because it relies on the rpc transport encryption
605 * and avoids using the global netlogon schannel
606 * session key to en/decrypt secret information
607 * like the user_session_key for network logons.
609 * [MS-APDS] 3.1.5.2 NTLM Network Logon
610 * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and
611 * NETLOGON_NEG_AUTHENTICATED_RPC set together
612 * are the indication that the server supports
613 * NetlogonValidationSamInfo4 (6). And it must only
614 * be used if "SealSecureChannel" is used.
616 * The "SealSecureChannel" AUTH_TYPE_SCHANNEL/AUTH_LEVEL_PRIVACY
617 * check is done in netlogon_creds_cli_LogonSamLogon*().
619 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
620 context
->server
.try_validation6
= true;
621 context
->server
.try_logon_ex
= true;
622 context
->server
.try_logon_with
= true;
624 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
625 context
->server
.try_validation6
= false;
626 context
->server
.try_logon_ex
= false;
628 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
629 context
->server
.try_validation6
= false;
632 *_creds
= fstate
.creds
;
636 bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context
*context
,
637 const struct netlogon_creds_CredentialState
*creds1
)
639 TALLOC_CTX
*frame
= talloc_stackframe();
640 struct netlogon_creds_CredentialState
*creds2
;
644 enum ndr_err_code ndr_err
;
647 status
= netlogon_creds_cli_get(context
, frame
, &creds2
);
648 if (!NT_STATUS_IS_OK(status
)) {
653 ndr_err
= ndr_push_struct_blob(&blob1
, frame
, creds1
,
654 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
655 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
660 ndr_err
= ndr_push_struct_blob(&blob2
, frame
, creds2
,
661 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
662 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
667 cmp
= data_blob_cmp(&blob1
, &blob2
);
674 NTSTATUS
netlogon_creds_cli_store(struct netlogon_creds_cli_context
*context
,
675 struct netlogon_creds_CredentialState
*creds
)
678 enum ndr_err_code ndr_err
;
682 if (context
->db
.locked_state
== NULL
) {
684 * this was not the result of netlogon_creds_cli_lock*()
686 return NT_STATUS_INVALID_PAGE_PROTECTION
;
689 if (context
->db
.locked_state
->creds
!= creds
) {
691 * this was not the result of netlogon_creds_cli_lock*()
693 return NT_STATUS_INVALID_PAGE_PROTECTION
;
696 ndr_err
= ndr_push_struct_blob(&blob
, creds
, creds
,
697 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
698 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
699 status
= ndr_map_error2ntstatus(ndr_err
);
703 data
.dptr
= blob
.data
;
704 data
.dsize
= blob
.length
;
706 status
= dbwrap_store(context
->db
.ctx
,
707 context
->db
.key_data
,
709 TALLOC_FREE(data
.dptr
);
710 if (!NT_STATUS_IS_OK(status
)) {
717 NTSTATUS
netlogon_creds_cli_delete(struct netlogon_creds_cli_context
*context
,
718 struct netlogon_creds_CredentialState
*creds
)
722 if (context
->db
.locked_state
== NULL
) {
724 * this was not the result of netlogon_creds_cli_lock*()
726 return NT_STATUS_INVALID_PAGE_PROTECTION
;
729 if (context
->db
.locked_state
->creds
!= creds
) {
731 * this was not the result of netlogon_creds_cli_lock*()
733 return NT_STATUS_INVALID_PAGE_PROTECTION
;
736 status
= dbwrap_delete(context
->db
.ctx
,
737 context
->db
.key_data
);
738 if (!NT_STATUS_IS_OK(status
)) {
745 struct netlogon_creds_cli_lock_state
{
746 struct netlogon_creds_cli_locked_state
*locked_state
;
747 struct netlogon_creds_CredentialState
*creds
;
750 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
);
751 static void netlogon_creds_cli_lock_fetch(struct tevent_req
*req
);
753 struct tevent_req
*netlogon_creds_cli_lock_send(TALLOC_CTX
*mem_ctx
,
754 struct tevent_context
*ev
,
755 struct netlogon_creds_cli_context
*context
)
757 struct tevent_req
*req
;
758 struct netlogon_creds_cli_lock_state
*state
;
759 struct netlogon_creds_cli_locked_state
*locked_state
;
760 struct tevent_req
*subreq
;
762 req
= tevent_req_create(mem_ctx
, &state
,
763 struct netlogon_creds_cli_lock_state
);
768 if (context
->db
.locked_state
!= NULL
) {
769 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
770 return tevent_req_post(req
, ev
);
773 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
774 if (tevent_req_nomem(locked_state
, req
)) {
775 return tevent_req_post(req
, ev
);
777 talloc_set_destructor(locked_state
,
778 netlogon_creds_cli_locked_state_destructor
);
779 locked_state
->context
= context
;
781 context
->db
.locked_state
= locked_state
;
782 state
->locked_state
= locked_state
;
784 if (context
->db
.g_ctx
== NULL
) {
785 netlogon_creds_cli_lock_fetch(req
);
786 if (!tevent_req_is_in_progress(req
)) {
787 return tevent_req_post(req
, ev
);
793 subreq
= g_lock_lock_send(state
, ev
,
795 context
->db
.key_name
,
797 if (tevent_req_nomem(subreq
, req
)) {
798 return tevent_req_post(req
, ev
);
800 tevent_req_set_callback(subreq
, netlogon_creds_cli_lock_done
, req
);
805 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
)
807 struct tevent_req
*req
=
808 tevent_req_callback_data(subreq
,
810 struct netlogon_creds_cli_lock_state
*state
=
812 struct netlogon_creds_cli_lock_state
);
815 status
= g_lock_lock_recv(subreq
);
817 if (tevent_req_nterror(req
, status
)) {
820 state
->locked_state
->is_glocked
= true;
822 netlogon_creds_cli_lock_fetch(req
);
825 static void netlogon_creds_cli_lock_fetch(struct tevent_req
*req
)
827 struct netlogon_creds_cli_lock_state
*state
=
829 struct netlogon_creds_cli_lock_state
);
830 struct netlogon_creds_cli_context
*context
= state
->locked_state
->context
;
831 struct netlogon_creds_cli_fetch_state fstate
= {
832 .status
= NT_STATUS_INTERNAL_ERROR
,
833 .required_flags
= context
->client
.required_flags
,
837 fstate
.mem_ctx
= state
;
838 status
= dbwrap_parse_record(context
->db
.ctx
,
839 context
->db
.key_data
,
840 netlogon_creds_cli_fetch_parser
,
842 if (tevent_req_nterror(req
, status
)) {
845 status
= fstate
.status
;
846 if (tevent_req_nterror(req
, status
)) {
850 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
851 state
->creds
= fstate
.creds
;
852 tevent_req_done(req
);
856 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
857 context
->server
.try_validation6
= true;
858 context
->server
.try_logon_ex
= true;
859 context
->server
.try_logon_with
= true;
861 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
862 context
->server
.try_validation6
= false;
863 context
->server
.try_logon_ex
= false;
865 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
866 context
->server
.try_validation6
= false;
869 state
->creds
= fstate
.creds
;
870 tevent_req_done(req
);
874 NTSTATUS
netlogon_creds_cli_lock_recv(struct tevent_req
*req
,
876 struct netlogon_creds_CredentialState
**creds
)
878 struct netlogon_creds_cli_lock_state
*state
=
880 struct netlogon_creds_cli_lock_state
);
883 if (tevent_req_is_nterror(req
, &status
)) {
884 tevent_req_received(req
);
888 talloc_steal(state
->creds
, state
->locked_state
);
889 state
->locked_state
->creds
= state
->creds
;
890 *creds
= talloc_move(mem_ctx
, &state
->creds
);
891 tevent_req_received(req
);
895 NTSTATUS
netlogon_creds_cli_lock(struct netlogon_creds_cli_context
*context
,
897 struct netlogon_creds_CredentialState
**creds
)
899 TALLOC_CTX
*frame
= talloc_stackframe();
900 struct tevent_context
*ev
;
901 struct tevent_req
*req
;
902 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
904 ev
= samba_tevent_context_init(frame
);
908 req
= netlogon_creds_cli_lock_send(frame
, ev
, context
);
912 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
915 status
= netlogon_creds_cli_lock_recv(req
, mem_ctx
, creds
);
921 struct netlogon_creds_cli_auth_state
{
922 struct tevent_context
*ev
;
923 struct netlogon_creds_cli_context
*context
;
924 struct dcerpc_binding_handle
*binding_handle
;
925 uint8_t num_nt_hashes
;
926 uint8_t idx_nt_hashes
;
927 const struct samr_Password
* const *nt_hashes
;
928 const struct samr_Password
*used_nt_hash
;
929 char *srv_name_slash
;
930 uint32_t current_flags
;
931 struct netr_Credential client_challenge
;
932 struct netr_Credential server_challenge
;
933 struct netlogon_creds_CredentialState
*creds
;
934 struct netr_Credential client_credential
;
935 struct netr_Credential server_credential
;
940 struct netlogon_creds_cli_locked_state
*locked_state
;
943 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
);
944 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
);
946 struct tevent_req
*netlogon_creds_cli_auth_send(TALLOC_CTX
*mem_ctx
,
947 struct tevent_context
*ev
,
948 struct netlogon_creds_cli_context
*context
,
949 struct dcerpc_binding_handle
*b
,
950 uint8_t num_nt_hashes
,
951 const struct samr_Password
* const *nt_hashes
)
953 struct tevent_req
*req
;
954 struct netlogon_creds_cli_auth_state
*state
;
955 struct netlogon_creds_cli_locked_state
*locked_state
;
958 req
= tevent_req_create(mem_ctx
, &state
,
959 struct netlogon_creds_cli_auth_state
);
965 state
->context
= context
;
966 state
->binding_handle
= b
;
967 if (num_nt_hashes
< 1) {
968 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
969 return tevent_req_post(req
, ev
);
971 if (num_nt_hashes
> 4) {
972 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
973 return tevent_req_post(req
, ev
);
976 state
->num_nt_hashes
= num_nt_hashes
;
977 state
->idx_nt_hashes
= 0;
978 state
->nt_hashes
= nt_hashes
;
980 if (context
->db
.locked_state
!= NULL
) {
981 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
982 return tevent_req_post(req
, ev
);
985 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
986 if (tevent_req_nomem(locked_state
, req
)) {
987 return tevent_req_post(req
, ev
);
989 talloc_set_destructor(locked_state
,
990 netlogon_creds_cli_locked_state_destructor
);
991 locked_state
->context
= context
;
993 context
->db
.locked_state
= locked_state
;
994 state
->locked_state
= locked_state
;
996 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
997 context
->server
.computer
);
998 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
999 return tevent_req_post(req
, ev
);
1002 state
->try_auth3
= true;
1003 state
->try_auth2
= true;
1005 if (context
->client
.required_flags
!= 0) {
1006 state
->require_auth2
= true;
1009 state
->used_nt_hash
= state
->nt_hashes
[state
->idx_nt_hashes
];
1010 state
->current_flags
= context
->client
.proposed_flags
;
1012 if (context
->db
.g_ctx
!= NULL
) {
1013 struct tevent_req
*subreq
;
1015 subreq
= g_lock_lock_send(state
, ev
,
1017 context
->db
.key_name
,
1019 if (tevent_req_nomem(subreq
, req
)) {
1020 return tevent_req_post(req
, ev
);
1022 tevent_req_set_callback(subreq
,
1023 netlogon_creds_cli_auth_locked
,
1029 status
= dbwrap_purge(state
->context
->db
.ctx
,
1030 state
->context
->db
.key_data
);
1031 if (tevent_req_nterror(req
, status
)) {
1032 return tevent_req_post(req
, ev
);
1035 netlogon_creds_cli_auth_challenge_start(req
);
1036 if (!tevent_req_is_in_progress(req
)) {
1037 return tevent_req_post(req
, ev
);
1043 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
)
1045 struct tevent_req
*req
=
1046 tevent_req_callback_data(subreq
,
1048 struct netlogon_creds_cli_auth_state
*state
=
1049 tevent_req_data(req
,
1050 struct netlogon_creds_cli_auth_state
);
1053 status
= g_lock_lock_recv(subreq
);
1054 TALLOC_FREE(subreq
);
1055 if (tevent_req_nterror(req
, status
)) {
1058 state
->locked_state
->is_glocked
= true;
1060 status
= dbwrap_purge(state
->context
->db
.ctx
,
1061 state
->context
->db
.key_data
);
1062 if (tevent_req_nterror(req
, status
)) {
1066 netlogon_creds_cli_auth_challenge_start(req
);
1069 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
);
1071 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
)
1073 struct netlogon_creds_cli_auth_state
*state
=
1074 tevent_req_data(req
,
1075 struct netlogon_creds_cli_auth_state
);
1076 struct tevent_req
*subreq
;
1078 TALLOC_FREE(state
->creds
);
1080 generate_random_buffer(state
->client_challenge
.data
,
1081 sizeof(state
->client_challenge
.data
));
1083 subreq
= dcerpc_netr_ServerReqChallenge_send(state
, state
->ev
,
1084 state
->binding_handle
,
1085 state
->srv_name_slash
,
1086 state
->context
->client
.computer
,
1087 &state
->client_challenge
,
1088 &state
->server_challenge
);
1089 if (tevent_req_nomem(subreq
, req
)) {
1092 tevent_req_set_callback(subreq
,
1093 netlogon_creds_cli_auth_challenge_done
,
1097 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
);
1099 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
)
1101 struct tevent_req
*req
=
1102 tevent_req_callback_data(subreq
,
1104 struct netlogon_creds_cli_auth_state
*state
=
1105 tevent_req_data(req
,
1106 struct netlogon_creds_cli_auth_state
);
1110 status
= dcerpc_netr_ServerReqChallenge_recv(subreq
, state
, &result
);
1111 TALLOC_FREE(subreq
);
1112 if (tevent_req_nterror(req
, status
)) {
1115 if (tevent_req_nterror(req
, result
)) {
1119 if (!state
->try_auth3
&& !state
->try_auth2
) {
1120 state
->current_flags
= 0;
1123 /* Calculate the session key and client credentials */
1125 state
->creds
= netlogon_creds_client_init(state
,
1126 state
->context
->client
.account
,
1127 state
->context
->client
.computer
,
1128 state
->context
->client
.type
,
1129 &state
->client_challenge
,
1130 &state
->server_challenge
,
1131 state
->used_nt_hash
,
1132 &state
->client_credential
,
1133 state
->current_flags
);
1134 if (tevent_req_nomem(state
->creds
, req
)) {
1138 if (state
->try_auth3
) {
1139 subreq
= dcerpc_netr_ServerAuthenticate3_send(state
, state
->ev
,
1140 state
->binding_handle
,
1141 state
->srv_name_slash
,
1142 state
->context
->client
.account
,
1143 state
->context
->client
.type
,
1144 state
->context
->client
.computer
,
1145 &state
->client_credential
,
1146 &state
->server_credential
,
1147 &state
->creds
->negotiate_flags
,
1149 if (tevent_req_nomem(subreq
, req
)) {
1152 } else if (state
->try_auth2
) {
1155 subreq
= dcerpc_netr_ServerAuthenticate2_send(state
, state
->ev
,
1156 state
->binding_handle
,
1157 state
->srv_name_slash
,
1158 state
->context
->client
.account
,
1159 state
->context
->client
.type
,
1160 state
->context
->client
.computer
,
1161 &state
->client_credential
,
1162 &state
->server_credential
,
1163 &state
->creds
->negotiate_flags
);
1164 if (tevent_req_nomem(subreq
, req
)) {
1170 subreq
= dcerpc_netr_ServerAuthenticate_send(state
, state
->ev
,
1171 state
->binding_handle
,
1172 state
->srv_name_slash
,
1173 state
->context
->client
.account
,
1174 state
->context
->client
.type
,
1175 state
->context
->client
.computer
,
1176 &state
->client_credential
,
1177 &state
->server_credential
);
1178 if (tevent_req_nomem(subreq
, req
)) {
1182 tevent_req_set_callback(subreq
,
1183 netlogon_creds_cli_auth_srvauth_done
,
1187 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
)
1189 struct tevent_req
*req
=
1190 tevent_req_callback_data(subreq
,
1192 struct netlogon_creds_cli_auth_state
*state
=
1193 tevent_req_data(req
,
1194 struct netlogon_creds_cli_auth_state
);
1198 enum ndr_err_code ndr_err
;
1203 if (state
->try_auth3
) {
1204 status
= dcerpc_netr_ServerAuthenticate3_recv(subreq
, state
,
1206 TALLOC_FREE(subreq
);
1207 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1208 state
->try_auth3
= false;
1209 netlogon_creds_cli_auth_challenge_start(req
);
1212 if (tevent_req_nterror(req
, status
)) {
1215 } else if (state
->try_auth2
) {
1216 status
= dcerpc_netr_ServerAuthenticate2_recv(subreq
, state
,
1218 TALLOC_FREE(subreq
);
1219 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1220 state
->try_auth2
= false;
1221 if (state
->require_auth2
) {
1222 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1223 tevent_req_nterror(req
, status
);
1226 netlogon_creds_cli_auth_challenge_start(req
);
1229 if (tevent_req_nterror(req
, status
)) {
1233 status
= dcerpc_netr_ServerAuthenticate_recv(subreq
, state
,
1235 TALLOC_FREE(subreq
);
1236 if (tevent_req_nterror(req
, status
)) {
1241 if (!NT_STATUS_IS_OK(result
) &&
1242 !NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
))
1244 tevent_req_nterror(req
, result
);
1248 tmp_flags
= state
->creds
->negotiate_flags
;
1249 tmp_flags
&= state
->context
->client
.required_flags
;
1250 if (tmp_flags
!= state
->context
->client
.required_flags
) {
1251 if (NT_STATUS_IS_OK(result
)) {
1252 tevent_req_nterror(req
, NT_STATUS_DOWNGRADE_DETECTED
);
1255 tevent_req_nterror(req
, result
);
1259 if (NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
)) {
1261 tmp_flags
= state
->context
->client
.proposed_flags
;
1262 if ((state
->current_flags
== tmp_flags
) &&
1263 (state
->creds
->negotiate_flags
!= tmp_flags
))
1266 * lets retry with the negotiated flags
1268 state
->current_flags
= state
->creds
->negotiate_flags
;
1269 netlogon_creds_cli_auth_challenge_start(req
);
1273 state
->idx_nt_hashes
+= 1;
1274 if (state
->idx_nt_hashes
>= state
->num_nt_hashes
) {
1276 * we already retried, giving up...
1278 tevent_req_nterror(req
, result
);
1283 * lets retry with the old nt hash.
1285 state
->used_nt_hash
= state
->nt_hashes
[state
->idx_nt_hashes
];
1286 state
->current_flags
= state
->context
->client
.proposed_flags
;
1287 netlogon_creds_cli_auth_challenge_start(req
);
1291 ok
= netlogon_creds_client_check(state
->creds
,
1292 &state
->server_credential
);
1294 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1298 ndr_err
= ndr_push_struct_blob(&blob
, state
, state
->creds
,
1299 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
1300 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1301 status
= ndr_map_error2ntstatus(ndr_err
);
1302 tevent_req_nterror(req
, status
);
1306 data
.dptr
= blob
.data
;
1307 data
.dsize
= blob
.length
;
1309 status
= dbwrap_store(state
->context
->db
.ctx
,
1310 state
->context
->db
.key_data
,
1312 TALLOC_FREE(state
->locked_state
);
1313 if (tevent_req_nterror(req
, status
)) {
1317 tevent_req_done(req
);
1320 NTSTATUS
netlogon_creds_cli_auth_recv(struct tevent_req
*req
,
1321 uint8_t *idx_nt_hashes
)
1323 struct netlogon_creds_cli_auth_state
*state
=
1324 tevent_req_data(req
,
1325 struct netlogon_creds_cli_auth_state
);
1330 if (tevent_req_is_nterror(req
, &status
)) {
1331 tevent_req_received(req
);
1335 *idx_nt_hashes
= state
->idx_nt_hashes
;
1336 tevent_req_received(req
);
1337 return NT_STATUS_OK
;
1340 NTSTATUS
netlogon_creds_cli_auth(struct netlogon_creds_cli_context
*context
,
1341 struct dcerpc_binding_handle
*b
,
1342 uint8_t num_nt_hashes
,
1343 const struct samr_Password
* const *nt_hashes
,
1344 uint8_t *idx_nt_hashes
)
1346 TALLOC_CTX
*frame
= talloc_stackframe();
1347 struct tevent_context
*ev
;
1348 struct tevent_req
*req
;
1349 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1353 ev
= samba_tevent_context_init(frame
);
1357 req
= netlogon_creds_cli_auth_send(frame
, ev
, context
, b
,
1358 num_nt_hashes
, nt_hashes
);
1362 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1365 status
= netlogon_creds_cli_auth_recv(req
, idx_nt_hashes
);
1371 struct netlogon_creds_cli_check_state
{
1372 struct tevent_context
*ev
;
1373 struct netlogon_creds_cli_context
*context
;
1374 struct dcerpc_binding_handle
*binding_handle
;
1376 char *srv_name_slash
;
1378 union netr_Capabilities caps
;
1380 struct netlogon_creds_CredentialState
*creds
;
1381 struct netlogon_creds_CredentialState tmp_creds
;
1382 struct netr_Authenticator req_auth
;
1383 struct netr_Authenticator rep_auth
;
1386 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1388 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
);
1390 struct tevent_req
*netlogon_creds_cli_check_send(TALLOC_CTX
*mem_ctx
,
1391 struct tevent_context
*ev
,
1392 struct netlogon_creds_cli_context
*context
,
1393 struct dcerpc_binding_handle
*b
)
1395 struct tevent_req
*req
;
1396 struct netlogon_creds_cli_check_state
*state
;
1397 struct tevent_req
*subreq
;
1398 enum dcerpc_AuthType auth_type
;
1399 enum dcerpc_AuthLevel auth_level
;
1401 req
= tevent_req_create(mem_ctx
, &state
,
1402 struct netlogon_creds_cli_check_state
);
1408 state
->context
= context
;
1409 state
->binding_handle
= b
;
1411 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1412 context
->server
.computer
);
1413 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1414 return tevent_req_post(req
, ev
);
1417 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1418 &auth_type
, &auth_level
);
1420 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
1421 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1422 return tevent_req_post(req
, ev
);
1425 switch (auth_level
) {
1426 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1427 case DCERPC_AUTH_LEVEL_PRIVACY
:
1430 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1431 return tevent_req_post(req
, ev
);
1434 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1436 if (tevent_req_nomem(subreq
, req
)) {
1437 return tevent_req_post(req
, ev
);
1440 tevent_req_set_callback(subreq
,
1441 netlogon_creds_cli_check_locked
,
1447 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1450 struct netlogon_creds_cli_check_state
*state
=
1451 tevent_req_data(req
,
1452 struct netlogon_creds_cli_check_state
);
1454 if (state
->creds
== NULL
) {
1458 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1459 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1460 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1461 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1462 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1463 TALLOC_FREE(state
->creds
);
1467 netlogon_creds_cli_delete(state
->context
, state
->creds
);
1468 TALLOC_FREE(state
->creds
);
1471 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
);
1473 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
)
1475 struct tevent_req
*req
=
1476 tevent_req_callback_data(subreq
,
1478 struct netlogon_creds_cli_check_state
*state
=
1479 tevent_req_data(req
,
1480 struct netlogon_creds_cli_check_state
);
1483 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1485 TALLOC_FREE(subreq
);
1486 if (tevent_req_nterror(req
, status
)) {
1491 * we defer all callbacks in order to cleanup
1492 * the database record.
1494 tevent_req_defer_callback(req
, state
->ev
);
1496 state
->tmp_creds
= *state
->creds
;
1497 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1499 ZERO_STRUCT(state
->rep_auth
);
1501 subreq
= dcerpc_netr_LogonGetCapabilities_send(state
, state
->ev
,
1502 state
->binding_handle
,
1503 state
->srv_name_slash
,
1504 state
->context
->client
.computer
,
1509 if (tevent_req_nomem(subreq
, req
)) {
1510 status
= NT_STATUS_NO_MEMORY
;
1511 netlogon_creds_cli_check_cleanup(req
, status
);
1514 tevent_req_set_callback(subreq
,
1515 netlogon_creds_cli_check_caps
,
1519 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
)
1521 struct tevent_req
*req
=
1522 tevent_req_callback_data(subreq
,
1524 struct netlogon_creds_cli_check_state
*state
=
1525 tevent_req_data(req
,
1526 struct netlogon_creds_cli_check_state
);
1531 status
= dcerpc_netr_LogonGetCapabilities_recv(subreq
, state
,
1533 TALLOC_FREE(subreq
);
1534 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1536 * Note that the negotiated flags are already checked
1537 * for our required flags after the ServerAuthenticate3/2 call.
1539 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1541 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1543 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1544 * already, we expect this to work!
1546 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1547 tevent_req_nterror(req
, status
);
1548 netlogon_creds_cli_check_cleanup(req
, status
);
1552 if (negotiated
& NETLOGON_NEG_STRONG_KEYS
) {
1554 * If we have negotiated NETLOGON_NEG_STRONG_KEYS
1555 * we expect this to work at least as far as the
1556 * NOT_SUPPORTED error handled below!
1558 * NT 4.0 and Old Samba servers are not
1559 * allowed without "require strong key = no"
1561 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1562 tevent_req_nterror(req
, status
);
1563 netlogon_creds_cli_check_cleanup(req
, status
);
1568 * If we not require NETLOGON_NEG_SUPPORTS_AES or
1569 * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore
1570 * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
1572 * This is needed against NT 4.0 and old Samba servers.
1574 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
1575 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
1576 * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
1577 * with the next request as the sequence number processing
1580 netlogon_creds_cli_check_cleanup(req
, status
);
1581 tevent_req_done(req
);
1584 if (tevent_req_nterror(req
, status
)) {
1585 netlogon_creds_cli_check_cleanup(req
, status
);
1589 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOT_IMPLEMENTED
)) {
1591 * Note that the negotiated flags are already checked
1592 * for our required flags after the ServerAuthenticate3/2 call.
1594 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1596 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1598 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1599 * already, we expect this to work!
1601 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1602 tevent_req_nterror(req
, status
);
1603 netlogon_creds_cli_check_cleanup(req
, status
);
1608 * This is ok, the server does not support
1609 * NETLOGON_NEG_SUPPORTS_AES.
1611 * netr_LogonGetCapabilities() was
1612 * netr_LogonDummyRoutine1() before
1613 * NETLOGON_NEG_SUPPORTS_AES was invented.
1615 netlogon_creds_cli_check_cleanup(req
, result
);
1616 tevent_req_done(req
);
1620 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1621 &state
->rep_auth
.cred
);
1623 status
= NT_STATUS_ACCESS_DENIED
;
1624 tevent_req_nterror(req
, status
);
1625 netlogon_creds_cli_check_cleanup(req
, status
);
1629 if (tevent_req_nterror(req
, result
)) {
1630 netlogon_creds_cli_check_cleanup(req
, result
);
1634 if (state
->caps
.server_capabilities
!= state
->tmp_creds
.negotiate_flags
) {
1635 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1636 tevent_req_nterror(req
, status
);
1637 netlogon_creds_cli_check_cleanup(req
, status
);
1642 * This is the key check that makes this check secure. If we
1643 * get OK here (rather than NOT_SUPPORTED), then the server
1644 * did support AES. If the server only proposed STRONG_KEYS
1645 * and not AES, then it should have failed with
1646 * NOT_IMPLEMENTED. We always send AES as a client, so the
1647 * server should always have returned it.
1649 if (!(state
->caps
.server_capabilities
& NETLOGON_NEG_SUPPORTS_AES
)) {
1650 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1651 tevent_req_nterror(req
, status
);
1652 netlogon_creds_cli_check_cleanup(req
, status
);
1656 *state
->creds
= state
->tmp_creds
;
1657 status
= netlogon_creds_cli_store(state
->context
,
1659 TALLOC_FREE(state
->creds
);
1660 if (tevent_req_nterror(req
, status
)) {
1664 tevent_req_done(req
);
1667 NTSTATUS
netlogon_creds_cli_check_recv(struct tevent_req
*req
)
1671 if (tevent_req_is_nterror(req
, &status
)) {
1672 netlogon_creds_cli_check_cleanup(req
, status
);
1673 tevent_req_received(req
);
1677 tevent_req_received(req
);
1678 return NT_STATUS_OK
;
1681 NTSTATUS
netlogon_creds_cli_check(struct netlogon_creds_cli_context
*context
,
1682 struct dcerpc_binding_handle
*b
)
1684 TALLOC_CTX
*frame
= talloc_stackframe();
1685 struct tevent_context
*ev
;
1686 struct tevent_req
*req
;
1687 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1689 ev
= samba_tevent_context_init(frame
);
1693 req
= netlogon_creds_cli_check_send(frame
, ev
, context
, b
);
1697 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1700 status
= netlogon_creds_cli_check_recv(req
);
1706 struct netlogon_creds_cli_ServerPasswordSet_state
{
1707 struct tevent_context
*ev
;
1708 struct netlogon_creds_cli_context
*context
;
1709 struct dcerpc_binding_handle
*binding_handle
;
1710 uint32_t old_timeout
;
1712 char *srv_name_slash
;
1713 enum dcerpc_AuthType auth_type
;
1714 enum dcerpc_AuthLevel auth_level
;
1716 struct samr_CryptPassword samr_crypt_password
;
1717 struct netr_CryptPassword netr_crypt_password
;
1718 struct samr_Password samr_password
;
1720 struct netlogon_creds_CredentialState
*creds
;
1721 struct netlogon_creds_CredentialState tmp_creds
;
1722 struct netr_Authenticator req_auth
;
1723 struct netr_Authenticator rep_auth
;
1726 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1728 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
);
1730 struct tevent_req
*netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX
*mem_ctx
,
1731 struct tevent_context
*ev
,
1732 struct netlogon_creds_cli_context
*context
,
1733 struct dcerpc_binding_handle
*b
,
1734 const DATA_BLOB
*new_password
,
1735 const uint32_t *new_version
)
1737 struct tevent_req
*req
;
1738 struct netlogon_creds_cli_ServerPasswordSet_state
*state
;
1739 struct tevent_req
*subreq
;
1742 req
= tevent_req_create(mem_ctx
, &state
,
1743 struct netlogon_creds_cli_ServerPasswordSet_state
);
1749 state
->context
= context
;
1750 state
->binding_handle
= b
;
1752 if (new_password
->length
< 14) {
1753 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1754 return tevent_req_post(req
, ev
);
1758 * netr_ServerPasswordSet
1760 mdfour(state
->samr_password
.hash
, new_password
->data
, new_password
->length
);
1763 * netr_ServerPasswordSet2
1765 ok
= set_pw_in_buffer(state
->samr_crypt_password
.data
,
1768 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1769 return tevent_req_post(req
, ev
);
1772 if (new_version
!= NULL
) {
1773 struct NL_PASSWORD_VERSION version
;
1774 uint32_t len
= IVAL(state
->samr_crypt_password
.data
, 512);
1775 uint32_t ofs
= 512 - len
;
1779 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1780 return tevent_req_post(req
, ev
);
1784 version
.ReservedField
= 0;
1785 version
.PasswordVersionNumber
= *new_version
;
1786 version
.PasswordVersionPresent
=
1787 NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT
;
1789 p
= state
->samr_crypt_password
.data
+ ofs
;
1790 SIVAL(p
, 0, version
.ReservedField
);
1791 SIVAL(p
, 4, version
.PasswordVersionNumber
);
1792 SIVAL(p
, 8, version
.PasswordVersionPresent
);
1795 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1796 context
->server
.computer
);
1797 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1798 return tevent_req_post(req
, ev
);
1801 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1803 &state
->auth_level
);
1805 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1807 if (tevent_req_nomem(subreq
, req
)) {
1808 return tevent_req_post(req
, ev
);
1811 tevent_req_set_callback(subreq
,
1812 netlogon_creds_cli_ServerPasswordSet_locked
,
1818 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1821 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1822 tevent_req_data(req
,
1823 struct netlogon_creds_cli_ServerPasswordSet_state
);
1825 if (state
->creds
== NULL
) {
1829 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
1830 state
->old_timeout
);
1832 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1833 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1834 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1835 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1836 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1837 TALLOC_FREE(state
->creds
);
1841 netlogon_creds_cli_delete(state
->context
, state
->creds
);
1842 TALLOC_FREE(state
->creds
);
1845 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
);
1847 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
)
1849 struct tevent_req
*req
=
1850 tevent_req_callback_data(subreq
,
1852 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1853 tevent_req_data(req
,
1854 struct netlogon_creds_cli_ServerPasswordSet_state
);
1857 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1859 TALLOC_FREE(subreq
);
1860 if (tevent_req_nterror(req
, status
)) {
1864 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
1865 switch (state
->auth_level
) {
1866 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1867 case DCERPC_AUTH_LEVEL_PRIVACY
:
1870 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1874 uint32_t tmp
= state
->creds
->negotiate_flags
;
1876 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
1878 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
1879 * it should be used, which means
1880 * we had a chance to verify no downgrade
1883 * This relies on netlogon_creds_cli_check*
1884 * being called before, as first request after
1887 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1892 state
->old_timeout
= dcerpc_binding_handle_set_timeout(
1893 state
->binding_handle
, 600000);
1896 * we defer all callbacks in order to cleanup
1897 * the database record.
1899 tevent_req_defer_callback(req
, state
->ev
);
1901 state
->tmp_creds
= *state
->creds
;
1902 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1904 ZERO_STRUCT(state
->rep_auth
);
1906 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1908 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1909 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
1910 state
->samr_crypt_password
.data
,
1913 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
1914 state
->samr_crypt_password
.data
,
1918 memcpy(state
->netr_crypt_password
.data
,
1919 state
->samr_crypt_password
.data
, 512);
1920 state
->netr_crypt_password
.length
=
1921 IVAL(state
->samr_crypt_password
.data
, 512);
1923 subreq
= dcerpc_netr_ServerPasswordSet2_send(state
, state
->ev
,
1924 state
->binding_handle
,
1925 state
->srv_name_slash
,
1926 state
->tmp_creds
.account_name
,
1927 state
->tmp_creds
.secure_channel_type
,
1928 state
->tmp_creds
.computer_name
,
1931 &state
->netr_crypt_password
);
1932 if (tevent_req_nomem(subreq
, req
)) {
1933 status
= NT_STATUS_NO_MEMORY
;
1934 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1938 netlogon_creds_des_encrypt(&state
->tmp_creds
,
1939 &state
->samr_password
);
1941 subreq
= dcerpc_netr_ServerPasswordSet_send(state
, state
->ev
,
1942 state
->binding_handle
,
1943 state
->srv_name_slash
,
1944 state
->tmp_creds
.account_name
,
1945 state
->tmp_creds
.secure_channel_type
,
1946 state
->tmp_creds
.computer_name
,
1949 &state
->samr_password
);
1950 if (tevent_req_nomem(subreq
, req
)) {
1951 status
= NT_STATUS_NO_MEMORY
;
1952 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1957 tevent_req_set_callback(subreq
,
1958 netlogon_creds_cli_ServerPasswordSet_done
,
1962 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
)
1964 struct tevent_req
*req
=
1965 tevent_req_callback_data(subreq
,
1967 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1968 tevent_req_data(req
,
1969 struct netlogon_creds_cli_ServerPasswordSet_state
);
1974 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1975 status
= dcerpc_netr_ServerPasswordSet2_recv(subreq
, state
,
1977 TALLOC_FREE(subreq
);
1978 if (tevent_req_nterror(req
, status
)) {
1979 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1983 status
= dcerpc_netr_ServerPasswordSet_recv(subreq
, state
,
1985 TALLOC_FREE(subreq
);
1986 if (tevent_req_nterror(req
, status
)) {
1987 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1992 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1993 &state
->rep_auth
.cred
);
1995 status
= NT_STATUS_ACCESS_DENIED
;
1996 tevent_req_nterror(req
, status
);
1997 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2001 if (tevent_req_nterror(req
, result
)) {
2002 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, result
);
2006 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
2007 state
->old_timeout
);
2009 *state
->creds
= state
->tmp_creds
;
2010 status
= netlogon_creds_cli_store(state
->context
,
2012 TALLOC_FREE(state
->creds
);
2013 if (tevent_req_nterror(req
, status
)) {
2014 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2018 tevent_req_done(req
);
2021 NTSTATUS
netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req
*req
)
2025 if (tevent_req_is_nterror(req
, &status
)) {
2026 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2027 tevent_req_received(req
);
2031 tevent_req_received(req
);
2032 return NT_STATUS_OK
;
2035 NTSTATUS
netlogon_creds_cli_ServerPasswordSet(
2036 struct netlogon_creds_cli_context
*context
,
2037 struct dcerpc_binding_handle
*b
,
2038 const DATA_BLOB
*new_password
,
2039 const uint32_t *new_version
)
2041 TALLOC_CTX
*frame
= talloc_stackframe();
2042 struct tevent_context
*ev
;
2043 struct tevent_req
*req
;
2044 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2046 ev
= samba_tevent_context_init(frame
);
2050 req
= netlogon_creds_cli_ServerPasswordSet_send(frame
, ev
, context
, b
,
2056 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2059 status
= netlogon_creds_cli_ServerPasswordSet_recv(req
);
2065 struct netlogon_creds_cli_LogonSamLogon_state
{
2066 struct tevent_context
*ev
;
2067 struct netlogon_creds_cli_context
*context
;
2068 struct dcerpc_binding_handle
*binding_handle
;
2070 char *srv_name_slash
;
2072 enum netr_LogonInfoClass logon_level
;
2073 const union netr_LogonLevel
*const_logon
;
2074 union netr_LogonLevel
*logon
;
2077 uint16_t validation_level
;
2078 union netr_Validation
*validation
;
2079 uint8_t authoritative
;
2082 * do we need encryption at the application layer?
2086 bool try_validation6
;
2089 * the read only credentials before we started the operation
2090 * used for netr_LogonSamLogonEx() if required (validation_level = 3).
2092 struct netlogon_creds_CredentialState
*ro_creds
;
2095 * The (locked) credentials used for the credential chain
2096 * used for netr_LogonSamLogonWithFlags() or
2097 * netr_LogonSamLogonWith().
2099 struct netlogon_creds_CredentialState
*lk_creds
;
2102 * While we have locked the global credentials (lk_creds above)
2103 * we operate an a temporary copy, because a server
2104 * may not support netr_LogonSamLogonWithFlags() and
2105 * didn't process our netr_Authenticator, so we need to
2106 * restart from lk_creds.
2108 struct netlogon_creds_CredentialState tmp_creds
;
2109 struct netr_Authenticator req_auth
;
2110 struct netr_Authenticator rep_auth
;
2113 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
);
2114 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2117 struct tevent_req
*netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX
*mem_ctx
,
2118 struct tevent_context
*ev
,
2119 struct netlogon_creds_cli_context
*context
,
2120 struct dcerpc_binding_handle
*b
,
2121 enum netr_LogonInfoClass logon_level
,
2122 const union netr_LogonLevel
*logon
,
2125 struct tevent_req
*req
;
2126 struct netlogon_creds_cli_LogonSamLogon_state
*state
;
2128 req
= tevent_req_create(mem_ctx
, &state
,
2129 struct netlogon_creds_cli_LogonSamLogon_state
);
2135 state
->context
= context
;
2136 state
->binding_handle
= b
;
2138 state
->logon_level
= logon_level
;
2139 state
->const_logon
= logon
;
2140 state
->flags
= flags
;
2142 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2143 context
->server
.computer
);
2144 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2145 return tevent_req_post(req
, ev
);
2148 switch (logon_level
) {
2149 case NetlogonInteractiveInformation
:
2150 case NetlogonInteractiveTransitiveInformation
:
2151 case NetlogonServiceInformation
:
2152 case NetlogonServiceTransitiveInformation
:
2153 case NetlogonGenericInformation
:
2154 state
->user_encrypt
= true;
2157 case NetlogonNetworkInformation
:
2158 case NetlogonNetworkTransitiveInformation
:
2162 state
->validation
= talloc_zero(state
, union netr_Validation
);
2163 if (tevent_req_nomem(state
->validation
, req
)) {
2164 return tevent_req_post(req
, ev
);
2167 netlogon_creds_cli_LogonSamLogon_start(req
);
2168 if (!tevent_req_is_in_progress(req
)) {
2169 return tevent_req_post(req
, ev
);
2173 * we defer all callbacks in order to cleanup
2174 * the database record.
2176 tevent_req_defer_callback(req
, state
->ev
);
2180 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2183 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2184 tevent_req_data(req
,
2185 struct netlogon_creds_cli_LogonSamLogon_state
);
2187 if (state
->lk_creds
== NULL
) {
2191 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2193 * This is a hack to recover from a bug in old
2194 * Samba servers, when LogonSamLogonEx() fails:
2196 * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
2198 * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2200 * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE,
2201 * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR
2202 * If the sign/seal check fails.
2204 * In that case we need to cleanup the netlogon session.
2206 * It's the job of the caller to disconnect the current
2207 * connection, if netlogon_creds_cli_LogonSamLogon()
2208 * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2210 if (!state
->context
->server
.try_logon_with
) {
2211 status
= NT_STATUS_NETWORK_ACCESS_DENIED
;
2215 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2216 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2217 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2218 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2219 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2220 TALLOC_FREE(state
->lk_creds
);
2224 netlogon_creds_cli_delete(state
->context
, state
->lk_creds
);
2225 TALLOC_FREE(state
->lk_creds
);
2228 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
);
2230 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
)
2232 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2233 tevent_req_data(req
,
2234 struct netlogon_creds_cli_LogonSamLogon_state
);
2235 struct tevent_req
*subreq
;
2237 enum dcerpc_AuthType auth_type
;
2238 enum dcerpc_AuthLevel auth_level
;
2240 TALLOC_FREE(state
->ro_creds
);
2241 TALLOC_FREE(state
->logon
);
2242 ZERO_STRUCTP(state
->validation
);
2244 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2245 &auth_type
, &auth_level
);
2247 state
->try_logon_ex
= state
->context
->server
.try_logon_ex
;
2248 state
->try_validation6
= state
->context
->server
.try_validation6
;
2250 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
2251 state
->try_logon_ex
= false;
2254 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
2255 state
->try_validation6
= false;
2258 if (state
->try_logon_ex
) {
2259 if (state
->try_validation6
) {
2260 state
->validation_level
= 6;
2262 state
->validation_level
= 3;
2263 state
->user_encrypt
= true;
2266 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2268 state
->const_logon
);
2269 if (tevent_req_nomem(state
->logon
, req
)) {
2270 status
= NT_STATUS_NO_MEMORY
;
2271 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2275 if (state
->user_encrypt
) {
2276 status
= netlogon_creds_cli_get(state
->context
,
2279 if (!NT_STATUS_IS_OK(status
)) {
2280 status
= NT_STATUS_ACCESS_DENIED
;
2281 tevent_req_nterror(req
, status
);
2282 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2286 netlogon_creds_encrypt_samlogon_logon(state
->ro_creds
,
2291 subreq
= dcerpc_netr_LogonSamLogonEx_send(state
, state
->ev
,
2292 state
->binding_handle
,
2293 state
->srv_name_slash
,
2294 state
->context
->client
.computer
,
2297 state
->validation_level
,
2299 &state
->authoritative
,
2301 if (tevent_req_nomem(subreq
, req
)) {
2302 status
= NT_STATUS_NO_MEMORY
;
2303 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2306 tevent_req_set_callback(subreq
,
2307 netlogon_creds_cli_LogonSamLogon_done
,
2312 if (state
->lk_creds
== NULL
) {
2313 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2315 if (tevent_req_nomem(subreq
, req
)) {
2316 status
= NT_STATUS_NO_MEMORY
;
2317 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2320 tevent_req_set_callback(subreq
,
2321 netlogon_creds_cli_LogonSamLogon_done
,
2326 state
->tmp_creds
= *state
->lk_creds
;
2327 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2329 ZERO_STRUCT(state
->rep_auth
);
2331 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2333 state
->const_logon
);
2334 if (tevent_req_nomem(state
->logon
, req
)) {
2335 status
= NT_STATUS_NO_MEMORY
;
2336 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2340 netlogon_creds_encrypt_samlogon_logon(&state
->tmp_creds
,
2344 state
->validation_level
= 3;
2346 if (state
->context
->server
.try_logon_with
) {
2347 subreq
= dcerpc_netr_LogonSamLogonWithFlags_send(state
, state
->ev
,
2348 state
->binding_handle
,
2349 state
->srv_name_slash
,
2350 state
->context
->client
.computer
,
2355 state
->validation_level
,
2357 &state
->authoritative
,
2359 if (tevent_req_nomem(subreq
, req
)) {
2360 status
= NT_STATUS_NO_MEMORY
;
2361 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2367 subreq
= dcerpc_netr_LogonSamLogon_send(state
, state
->ev
,
2368 state
->binding_handle
,
2369 state
->srv_name_slash
,
2370 state
->context
->client
.computer
,
2375 state
->validation_level
,
2377 &state
->authoritative
);
2378 if (tevent_req_nomem(subreq
, req
)) {
2379 status
= NT_STATUS_NO_MEMORY
;
2380 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2385 tevent_req_set_callback(subreq
,
2386 netlogon_creds_cli_LogonSamLogon_done
,
2390 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
)
2392 struct tevent_req
*req
=
2393 tevent_req_callback_data(subreq
,
2395 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2396 tevent_req_data(req
,
2397 struct netlogon_creds_cli_LogonSamLogon_state
);
2402 if (state
->try_logon_ex
) {
2403 status
= dcerpc_netr_LogonSamLogonEx_recv(subreq
,
2406 TALLOC_FREE(subreq
);
2407 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2408 state
->context
->server
.try_validation6
= false;
2409 state
->context
->server
.try_logon_ex
= false;
2410 netlogon_creds_cli_LogonSamLogon_start(req
);
2413 if (tevent_req_nterror(req
, status
)) {
2414 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2418 if ((state
->validation_level
== 6) &&
2419 (NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_INFO_CLASS
) ||
2420 NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_PARAMETER
) ||
2421 NT_STATUS_EQUAL(result
, NT_STATUS_BUFFER_TOO_SMALL
)))
2423 state
->context
->server
.try_validation6
= false;
2424 netlogon_creds_cli_LogonSamLogon_start(req
);
2428 if (tevent_req_nterror(req
, result
)) {
2429 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2433 if (state
->ro_creds
== NULL
) {
2434 tevent_req_done(req
);
2438 ok
= netlogon_creds_cli_validate(state
->context
, state
->ro_creds
);
2441 * We got a race, lets retry with on authenticator
2444 * netlogon_creds_cli_LogonSamLogon_start()
2445 * will TALLOC_FREE(state->ro_creds);
2447 state
->try_logon_ex
= false;
2448 netlogon_creds_cli_LogonSamLogon_start(req
);
2452 netlogon_creds_decrypt_samlogon_validation(state
->ro_creds
,
2453 state
->validation_level
,
2456 tevent_req_done(req
);
2460 if (state
->lk_creds
== NULL
) {
2461 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2463 TALLOC_FREE(subreq
);
2464 if (tevent_req_nterror(req
, status
)) {
2465 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2469 netlogon_creds_cli_LogonSamLogon_start(req
);
2473 if (state
->context
->server
.try_logon_with
) {
2474 status
= dcerpc_netr_LogonSamLogonWithFlags_recv(subreq
,
2477 TALLOC_FREE(subreq
);
2478 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2479 state
->context
->server
.try_logon_with
= false;
2480 netlogon_creds_cli_LogonSamLogon_start(req
);
2483 if (tevent_req_nterror(req
, status
)) {
2484 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2488 status
= dcerpc_netr_LogonSamLogon_recv(subreq
,
2491 TALLOC_FREE(subreq
);
2492 if (tevent_req_nterror(req
, status
)) {
2493 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2498 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2499 &state
->rep_auth
.cred
);
2501 status
= NT_STATUS_ACCESS_DENIED
;
2502 tevent_req_nterror(req
, status
);
2503 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2507 *state
->lk_creds
= state
->tmp_creds
;
2508 status
= netlogon_creds_cli_store(state
->context
,
2510 TALLOC_FREE(state
->lk_creds
);
2512 if (tevent_req_nterror(req
, status
)) {
2513 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2517 if (tevent_req_nterror(req
, result
)) {
2518 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2522 netlogon_creds_decrypt_samlogon_validation(&state
->tmp_creds
,
2523 state
->validation_level
,
2526 tevent_req_done(req
);
2529 NTSTATUS
netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req
*req
,
2530 TALLOC_CTX
*mem_ctx
,
2531 uint16_t *validation_level
,
2532 union netr_Validation
**validation
,
2533 uint8_t *authoritative
,
2536 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2537 tevent_req_data(req
,
2538 struct netlogon_creds_cli_LogonSamLogon_state
);
2541 /* authoritative is also returned on error */
2542 *authoritative
= state
->authoritative
;
2544 if (tevent_req_is_nterror(req
, &status
)) {
2545 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2546 tevent_req_received(req
);
2550 *validation_level
= state
->validation_level
;
2551 *validation
= talloc_move(mem_ctx
, &state
->validation
);
2552 *flags
= state
->flags
;
2554 tevent_req_received(req
);
2555 return NT_STATUS_OK
;
2558 NTSTATUS
netlogon_creds_cli_LogonSamLogon(
2559 struct netlogon_creds_cli_context
*context
,
2560 struct dcerpc_binding_handle
*b
,
2561 enum netr_LogonInfoClass logon_level
,
2562 const union netr_LogonLevel
*logon
,
2563 TALLOC_CTX
*mem_ctx
,
2564 uint16_t *validation_level
,
2565 union netr_Validation
**validation
,
2566 uint8_t *authoritative
,
2569 TALLOC_CTX
*frame
= talloc_stackframe();
2570 struct tevent_context
*ev
;
2571 struct tevent_req
*req
;
2572 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2574 ev
= samba_tevent_context_init(frame
);
2578 req
= netlogon_creds_cli_LogonSamLogon_send(frame
, ev
, context
, b
,
2584 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2587 status
= netlogon_creds_cli_LogonSamLogon_recv(req
, mem_ctx
,
2597 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
{
2598 struct tevent_context
*ev
;
2599 struct netlogon_creds_cli_context
*context
;
2600 struct dcerpc_binding_handle
*binding_handle
;
2602 char *srv_name_slash
;
2603 enum dcerpc_AuthType auth_type
;
2604 enum dcerpc_AuthLevel auth_level
;
2606 const char *site_name
;
2608 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
;
2610 struct netlogon_creds_CredentialState
*creds
;
2611 struct netlogon_creds_CredentialState tmp_creds
;
2612 struct netr_Authenticator req_auth
;
2613 struct netr_Authenticator rep_auth
;
2616 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2618 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
);
2620 struct tevent_req
*netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(TALLOC_CTX
*mem_ctx
,
2621 struct tevent_context
*ev
,
2622 struct netlogon_creds_cli_context
*context
,
2623 struct dcerpc_binding_handle
*b
,
2624 const char *site_name
,
2626 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2628 struct tevent_req
*req
;
2629 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
;
2630 struct tevent_req
*subreq
;
2632 req
= tevent_req_create(mem_ctx
, &state
,
2633 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2639 state
->context
= context
;
2640 state
->binding_handle
= b
;
2642 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2643 context
->server
.computer
);
2644 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2645 return tevent_req_post(req
, ev
);
2648 state
->site_name
= site_name
;
2649 state
->dns_ttl
= dns_ttl
;
2650 state
->dns_names
= dns_names
;
2652 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2654 &state
->auth_level
);
2656 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2658 if (tevent_req_nomem(subreq
, req
)) {
2659 return tevent_req_post(req
, ev
);
2662 tevent_req_set_callback(subreq
,
2663 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked
,
2669 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2672 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2673 tevent_req_data(req
,
2674 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2676 if (state
->creds
== NULL
) {
2680 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2681 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2682 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2683 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2684 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2685 TALLOC_FREE(state
->creds
);
2689 netlogon_creds_cli_delete(state
->context
, state
->creds
);
2690 TALLOC_FREE(state
->creds
);
2693 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
);
2695 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
)
2697 struct tevent_req
*req
=
2698 tevent_req_callback_data(subreq
,
2700 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2701 tevent_req_data(req
,
2702 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2705 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2707 TALLOC_FREE(subreq
);
2708 if (tevent_req_nterror(req
, status
)) {
2712 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
2713 switch (state
->auth_level
) {
2714 case DCERPC_AUTH_LEVEL_INTEGRITY
:
2715 case DCERPC_AUTH_LEVEL_PRIVACY
:
2718 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2722 uint32_t tmp
= state
->creds
->negotiate_flags
;
2724 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
2726 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
2727 * it should be used, which means
2728 * we had a chance to verify no downgrade
2731 * This relies on netlogon_creds_cli_check*
2732 * being called before, as first request after
2735 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2741 * we defer all callbacks in order to cleanup
2742 * the database record.
2744 tevent_req_defer_callback(req
, state
->ev
);
2746 state
->tmp_creds
= *state
->creds
;
2747 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2749 ZERO_STRUCT(state
->rep_auth
);
2751 subreq
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_send(state
, state
->ev
,
2752 state
->binding_handle
,
2753 state
->srv_name_slash
,
2754 state
->tmp_creds
.computer_name
,
2760 if (tevent_req_nomem(subreq
, req
)) {
2761 status
= NT_STATUS_NO_MEMORY
;
2762 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2766 tevent_req_set_callback(subreq
,
2767 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done
,
2771 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
)
2773 struct tevent_req
*req
=
2774 tevent_req_callback_data(subreq
,
2776 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2777 tevent_req_data(req
,
2778 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2784 * We use state->dns_names as the memory context, as this is
2785 * the only in/out variable and it has been overwritten by the
2786 * out parameter from the server.
2788 * We need to preserve the return value until the caller can use it.
2790 status
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_recv(subreq
, state
->dns_names
,
2792 TALLOC_FREE(subreq
);
2793 if (tevent_req_nterror(req
, status
)) {
2794 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2798 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2799 &state
->rep_auth
.cred
);
2801 status
= NT_STATUS_ACCESS_DENIED
;
2802 tevent_req_nterror(req
, status
);
2803 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2807 *state
->creds
= state
->tmp_creds
;
2808 status
= netlogon_creds_cli_store(state
->context
,
2810 TALLOC_FREE(state
->creds
);
2812 if (tevent_req_nterror(req
, status
)) {
2813 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2817 if (tevent_req_nterror(req
, result
)) {
2818 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, result
);
2822 tevent_req_done(req
);
2825 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(struct tevent_req
*req
)
2829 if (tevent_req_is_nterror(req
, &status
)) {
2830 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2831 tevent_req_received(req
);
2835 tevent_req_received(req
);
2836 return NT_STATUS_OK
;
2839 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(
2840 struct netlogon_creds_cli_context
*context
,
2841 struct dcerpc_binding_handle
*b
,
2842 const char *site_name
,
2844 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2846 TALLOC_CTX
*frame
= talloc_stackframe();
2847 struct tevent_context
*ev
;
2848 struct tevent_req
*req
;
2849 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2851 ev
= samba_tevent_context_init(frame
);
2855 req
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(frame
, ev
, context
, b
,
2862 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2865 status
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(req
);
2871 struct netlogon_creds_cli_ServerGetTrustInfo_state
{
2872 struct tevent_context
*ev
;
2873 struct netlogon_creds_cli_context
*context
;
2874 struct dcerpc_binding_handle
*binding_handle
;
2876 char *srv_name_slash
;
2877 enum dcerpc_AuthType auth_type
;
2878 enum dcerpc_AuthLevel auth_level
;
2880 struct samr_Password new_owf_password
;
2881 struct samr_Password old_owf_password
;
2882 struct netr_TrustInfo
*trust_info
;
2884 struct netlogon_creds_CredentialState
*creds
;
2885 struct netlogon_creds_CredentialState tmp_creds
;
2886 struct netr_Authenticator req_auth
;
2887 struct netr_Authenticator rep_auth
;
2890 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
2892 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
);
2894 struct tevent_req
*netlogon_creds_cli_ServerGetTrustInfo_send(TALLOC_CTX
*mem_ctx
,
2895 struct tevent_context
*ev
,
2896 struct netlogon_creds_cli_context
*context
,
2897 struct dcerpc_binding_handle
*b
)
2899 struct tevent_req
*req
;
2900 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
;
2901 struct tevent_req
*subreq
;
2903 req
= tevent_req_create(mem_ctx
, &state
,
2904 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2910 state
->context
= context
;
2911 state
->binding_handle
= b
;
2913 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2914 context
->server
.computer
);
2915 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2916 return tevent_req_post(req
, ev
);
2919 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2921 &state
->auth_level
);
2923 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2925 if (tevent_req_nomem(subreq
, req
)) {
2926 return tevent_req_post(req
, ev
);
2929 tevent_req_set_callback(subreq
,
2930 netlogon_creds_cli_ServerGetTrustInfo_locked
,
2936 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
2939 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2940 tevent_req_data(req
,
2941 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2943 if (state
->creds
== NULL
) {
2947 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2948 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2949 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2950 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2951 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2952 TALLOC_FREE(state
->creds
);
2956 netlogon_creds_cli_delete(state
->context
, state
->creds
);
2957 TALLOC_FREE(state
->creds
);
2960 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
);
2962 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
)
2964 struct tevent_req
*req
=
2965 tevent_req_callback_data(subreq
,
2967 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2968 tevent_req_data(req
,
2969 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2972 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2974 TALLOC_FREE(subreq
);
2975 if (tevent_req_nterror(req
, status
)) {
2979 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
2980 switch (state
->auth_level
) {
2981 case DCERPC_AUTH_LEVEL_PRIVACY
:
2984 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2988 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2993 * we defer all callbacks in order to cleanup
2994 * the database record.
2996 tevent_req_defer_callback(req
, state
->ev
);
2998 state
->tmp_creds
= *state
->creds
;
2999 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3001 ZERO_STRUCT(state
->rep_auth
);
3003 subreq
= dcerpc_netr_ServerGetTrustInfo_send(state
, state
->ev
,
3004 state
->binding_handle
,
3005 state
->srv_name_slash
,
3006 state
->tmp_creds
.account_name
,
3007 state
->tmp_creds
.secure_channel_type
,
3008 state
->tmp_creds
.computer_name
,
3011 &state
->new_owf_password
,
3012 &state
->old_owf_password
,
3013 &state
->trust_info
);
3014 if (tevent_req_nomem(subreq
, req
)) {
3015 status
= NT_STATUS_NO_MEMORY
;
3016 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3020 tevent_req_set_callback(subreq
,
3021 netlogon_creds_cli_ServerGetTrustInfo_done
,
3025 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
)
3027 struct tevent_req
*req
=
3028 tevent_req_callback_data(subreq
,
3030 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3031 tevent_req_data(req
,
3032 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3035 const struct samr_Password zero
= {};
3040 * We use state->dns_names as the memory context, as this is
3041 * the only in/out variable and it has been overwritten by the
3042 * out parameter from the server.
3044 * We need to preserve the return value until the caller can use it.
3046 status
= dcerpc_netr_ServerGetTrustInfo_recv(subreq
, state
, &result
);
3047 TALLOC_FREE(subreq
);
3048 if (tevent_req_nterror(req
, status
)) {
3049 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3053 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3054 &state
->rep_auth
.cred
);
3056 status
= NT_STATUS_ACCESS_DENIED
;
3057 tevent_req_nterror(req
, status
);
3058 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3062 cmp
= memcmp(state
->new_owf_password
.hash
,
3063 zero
.hash
, sizeof(zero
.hash
));
3065 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3066 &state
->new_owf_password
);
3068 cmp
= memcmp(state
->old_owf_password
.hash
,
3069 zero
.hash
, sizeof(zero
.hash
));
3071 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3072 &state
->old_owf_password
);
3075 *state
->creds
= state
->tmp_creds
;
3076 status
= netlogon_creds_cli_store(state
->context
,
3078 TALLOC_FREE(state
->creds
);
3079 if (tevent_req_nterror(req
, status
)) {
3080 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3084 if (tevent_req_nterror(req
, result
)) {
3085 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, result
);
3089 tevent_req_done(req
);
3092 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo_recv(struct tevent_req
*req
,
3093 TALLOC_CTX
*mem_ctx
,
3094 struct samr_Password
*new_owf_password
,
3095 struct samr_Password
*old_owf_password
,
3096 struct netr_TrustInfo
**trust_info
)
3098 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3099 tevent_req_data(req
,
3100 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3103 if (tevent_req_is_nterror(req
, &status
)) {
3104 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3105 tevent_req_received(req
);
3109 if (new_owf_password
!= NULL
) {
3110 *new_owf_password
= state
->new_owf_password
;
3112 if (old_owf_password
!= NULL
) {
3113 *old_owf_password
= state
->old_owf_password
;
3115 if (trust_info
!= NULL
) {
3116 *trust_info
= talloc_move(mem_ctx
, &state
->trust_info
);
3119 tevent_req_received(req
);
3120 return NT_STATUS_OK
;
3123 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo(
3124 struct netlogon_creds_cli_context
*context
,
3125 struct dcerpc_binding_handle
*b
,
3126 TALLOC_CTX
*mem_ctx
,
3127 struct samr_Password
*new_owf_password
,
3128 struct samr_Password
*old_owf_password
,
3129 struct netr_TrustInfo
**trust_info
)
3131 TALLOC_CTX
*frame
= talloc_stackframe();
3132 struct tevent_context
*ev
;
3133 struct tevent_req
*req
;
3134 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3136 ev
= samba_tevent_context_init(frame
);
3140 req
= netlogon_creds_cli_ServerGetTrustInfo_send(frame
, ev
, context
, b
);
3144 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3147 status
= netlogon_creds_cli_ServerGetTrustInfo_recv(req
,
3157 struct netlogon_creds_cli_GetForestTrustInformation_state
{
3158 struct tevent_context
*ev
;
3159 struct netlogon_creds_cli_context
*context
;
3160 struct dcerpc_binding_handle
*binding_handle
;
3162 char *srv_name_slash
;
3163 enum dcerpc_AuthType auth_type
;
3164 enum dcerpc_AuthLevel auth_level
;
3167 struct lsa_ForestTrustInformation
*forest_trust_info
;
3169 struct netlogon_creds_CredentialState
*creds
;
3170 struct netlogon_creds_CredentialState tmp_creds
;
3171 struct netr_Authenticator req_auth
;
3172 struct netr_Authenticator rep_auth
;
3175 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3177 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
);
3179 struct tevent_req
*netlogon_creds_cli_GetForestTrustInformation_send(TALLOC_CTX
*mem_ctx
,
3180 struct tevent_context
*ev
,
3181 struct netlogon_creds_cli_context
*context
,
3182 struct dcerpc_binding_handle
*b
)
3184 struct tevent_req
*req
;
3185 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
;
3186 struct tevent_req
*subreq
;
3188 req
= tevent_req_create(mem_ctx
, &state
,
3189 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3195 state
->context
= context
;
3196 state
->binding_handle
= b
;
3198 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3199 context
->server
.computer
);
3200 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3201 return tevent_req_post(req
, ev
);
3206 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3208 &state
->auth_level
);
3210 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3212 if (tevent_req_nomem(subreq
, req
)) {
3213 return tevent_req_post(req
, ev
);
3216 tevent_req_set_callback(subreq
,
3217 netlogon_creds_cli_GetForestTrustInformation_locked
,
3223 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3226 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3227 tevent_req_data(req
,
3228 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3230 if (state
->creds
== NULL
) {
3234 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3235 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3236 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3237 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3238 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3239 TALLOC_FREE(state
->creds
);
3243 netlogon_creds_cli_delete(state
->context
, state
->creds
);
3244 TALLOC_FREE(state
->creds
);
3247 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
);
3249 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
)
3251 struct tevent_req
*req
=
3252 tevent_req_callback_data(subreq
,
3254 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3255 tevent_req_data(req
,
3256 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3259 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3261 TALLOC_FREE(subreq
);
3262 if (tevent_req_nterror(req
, status
)) {
3266 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3267 switch (state
->auth_level
) {
3268 case DCERPC_AUTH_LEVEL_INTEGRITY
:
3269 case DCERPC_AUTH_LEVEL_PRIVACY
:
3272 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3276 uint32_t tmp
= state
->creds
->negotiate_flags
;
3278 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
3280 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3281 * it should be used, which means
3282 * we had a chance to verify no downgrade
3285 * This relies on netlogon_creds_cli_check*
3286 * being called before, as first request after
3289 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3295 * we defer all callbacks in order to cleanup
3296 * the database record.
3298 tevent_req_defer_callback(req
, state
->ev
);
3300 state
->tmp_creds
= *state
->creds
;
3301 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3303 ZERO_STRUCT(state
->rep_auth
);
3305 subreq
= dcerpc_netr_GetForestTrustInformation_send(state
, state
->ev
,
3306 state
->binding_handle
,
3307 state
->srv_name_slash
,
3308 state
->tmp_creds
.computer_name
,
3312 &state
->forest_trust_info
);
3313 if (tevent_req_nomem(subreq
, req
)) {
3314 status
= NT_STATUS_NO_MEMORY
;
3315 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3319 tevent_req_set_callback(subreq
,
3320 netlogon_creds_cli_GetForestTrustInformation_done
,
3324 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
)
3326 struct tevent_req
*req
=
3327 tevent_req_callback_data(subreq
,
3329 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3330 tevent_req_data(req
,
3331 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3337 * We use state->dns_names as the memory context, as this is
3338 * the only in/out variable and it has been overwritten by the
3339 * out parameter from the server.
3341 * We need to preserve the return value until the caller can use it.
3343 status
= dcerpc_netr_GetForestTrustInformation_recv(subreq
, state
, &result
);
3344 TALLOC_FREE(subreq
);
3345 if (tevent_req_nterror(req
, status
)) {
3346 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3350 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3351 &state
->rep_auth
.cred
);
3353 status
= NT_STATUS_ACCESS_DENIED
;
3354 tevent_req_nterror(req
, status
);
3355 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3359 *state
->creds
= state
->tmp_creds
;
3360 status
= netlogon_creds_cli_store(state
->context
,
3362 TALLOC_FREE(state
->creds
);
3364 if (tevent_req_nterror(req
, status
)) {
3365 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3369 if (tevent_req_nterror(req
, result
)) {
3370 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, result
);
3374 tevent_req_done(req
);
3377 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation_recv(struct tevent_req
*req
,
3378 TALLOC_CTX
*mem_ctx
,
3379 struct lsa_ForestTrustInformation
**forest_trust_info
)
3381 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3382 tevent_req_data(req
,
3383 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3386 if (tevent_req_is_nterror(req
, &status
)) {
3387 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3388 tevent_req_received(req
);
3392 *forest_trust_info
= talloc_move(mem_ctx
, &state
->forest_trust_info
);
3394 tevent_req_received(req
);
3395 return NT_STATUS_OK
;
3398 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation(
3399 struct netlogon_creds_cli_context
*context
,
3400 struct dcerpc_binding_handle
*b
,
3401 TALLOC_CTX
*mem_ctx
,
3402 struct lsa_ForestTrustInformation
**forest_trust_info
)
3404 TALLOC_CTX
*frame
= talloc_stackframe();
3405 struct tevent_context
*ev
;
3406 struct tevent_req
*req
;
3407 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3409 ev
= samba_tevent_context_init(frame
);
3413 req
= netlogon_creds_cli_GetForestTrustInformation_send(frame
, ev
, context
, b
);
3417 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3420 status
= netlogon_creds_cli_GetForestTrustInformation_recv(req
,
3428 struct netlogon_creds_cli_SendToSam_state
{
3429 struct tevent_context
*ev
;
3430 struct netlogon_creds_cli_context
*context
;
3431 struct dcerpc_binding_handle
*binding_handle
;
3433 char *srv_name_slash
;
3434 enum dcerpc_AuthType auth_type
;
3435 enum dcerpc_AuthLevel auth_level
;
3439 struct netlogon_creds_CredentialState
*creds
;
3440 struct netlogon_creds_CredentialState tmp_creds
;
3441 struct netr_Authenticator req_auth
;
3442 struct netr_Authenticator rep_auth
;
3445 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req
*req
,
3447 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req
*subreq
);
3449 struct tevent_req
*netlogon_creds_cli_SendToSam_send(TALLOC_CTX
*mem_ctx
,
3450 struct tevent_context
*ev
,
3451 struct netlogon_creds_cli_context
*context
,
3452 struct dcerpc_binding_handle
*b
,
3453 struct netr_SendToSamBase
*message
)
3455 struct tevent_req
*req
;
3456 struct netlogon_creds_cli_SendToSam_state
*state
;
3457 struct tevent_req
*subreq
;
3458 enum ndr_err_code ndr_err
;
3460 req
= tevent_req_create(mem_ctx
, &state
,
3461 struct netlogon_creds_cli_SendToSam_state
);
3467 state
->context
= context
;
3468 state
->binding_handle
= b
;
3470 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3471 context
->server
.computer
);
3472 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3473 return tevent_req_post(req
, ev
);
3476 ndr_err
= ndr_push_struct_blob(&state
->opaque
, mem_ctx
, message
,
3477 (ndr_push_flags_fn_t
)ndr_push_netr_SendToSamBase
);
3478 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
3479 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
3480 tevent_req_nterror(req
, status
);
3481 return tevent_req_post(req
, ev
);
3484 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3486 &state
->auth_level
);
3488 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3490 if (tevent_req_nomem(subreq
, req
)) {
3491 return tevent_req_post(req
, ev
);
3494 tevent_req_set_callback(subreq
,
3495 netlogon_creds_cli_SendToSam_locked
,
3501 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req
*req
,
3504 struct netlogon_creds_cli_SendToSam_state
*state
=
3505 tevent_req_data(req
,
3506 struct netlogon_creds_cli_SendToSam_state
);
3508 if (state
->creds
== NULL
) {
3512 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3513 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3514 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3515 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3516 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3517 TALLOC_FREE(state
->creds
);
3521 netlogon_creds_cli_delete(state
->context
, state
->creds
);
3522 TALLOC_FREE(state
->creds
);
3525 static void netlogon_creds_cli_SendToSam_done(struct tevent_req
*subreq
);
3527 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req
*subreq
)
3529 struct tevent_req
*req
=
3530 tevent_req_callback_data(subreq
,
3532 struct netlogon_creds_cli_SendToSam_state
*state
=
3533 tevent_req_data(req
,
3534 struct netlogon_creds_cli_SendToSam_state
);
3537 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3539 TALLOC_FREE(subreq
);
3540 if (tevent_req_nterror(req
, status
)) {
3544 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3545 switch (state
->auth_level
) {
3546 case DCERPC_AUTH_LEVEL_INTEGRITY
:
3547 case DCERPC_AUTH_LEVEL_PRIVACY
:
3550 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3554 uint32_t tmp
= state
->creds
->negotiate_flags
;
3556 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
3558 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3559 * it should be used, which means
3560 * we had a chance to verify no downgrade
3563 * This relies on netlogon_creds_cli_check*
3564 * being called before, as first request after
3567 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3573 * we defer all callbacks in order to cleanup
3574 * the database record.
3576 tevent_req_defer_callback(req
, state
->ev
);
3578 state
->tmp_creds
= *state
->creds
;
3579 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3581 ZERO_STRUCT(state
->rep_auth
);
3583 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
3584 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
3586 state
->opaque
.length
);
3588 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
3590 state
->opaque
.length
);
3593 subreq
= dcerpc_netr_NetrLogonSendToSam_send(state
, state
->ev
,
3594 state
->binding_handle
,
3595 state
->srv_name_slash
,
3596 state
->tmp_creds
.computer_name
,
3600 state
->opaque
.length
);
3601 if (tevent_req_nomem(subreq
, req
)) {
3602 status
= NT_STATUS_NO_MEMORY
;
3603 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3607 tevent_req_set_callback(subreq
,
3608 netlogon_creds_cli_SendToSam_done
,
3612 static void netlogon_creds_cli_SendToSam_done(struct tevent_req
*subreq
)
3614 struct tevent_req
*req
=
3615 tevent_req_callback_data(subreq
,
3617 struct netlogon_creds_cli_SendToSam_state
*state
=
3618 tevent_req_data(req
,
3619 struct netlogon_creds_cli_SendToSam_state
);
3624 status
= dcerpc_netr_NetrLogonSendToSam_recv(subreq
, state
, &result
);
3625 TALLOC_FREE(subreq
);
3626 if (tevent_req_nterror(req
, status
)) {
3627 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3631 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3632 &state
->rep_auth
.cred
);
3634 status
= NT_STATUS_ACCESS_DENIED
;
3635 tevent_req_nterror(req
, status
);
3636 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3640 *state
->creds
= state
->tmp_creds
;
3641 status
= netlogon_creds_cli_store(state
->context
,
3643 TALLOC_FREE(state
->creds
);
3645 if (tevent_req_nterror(req
, status
)) {
3646 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3651 * Creds must be stored before we send back application errors
3652 * e.g. NT_STATUS_NOT_IMPLEMENTED
3654 if (tevent_req_nterror(req
, result
)) {
3655 netlogon_creds_cli_SendToSam_cleanup(req
, result
);
3659 tevent_req_done(req
);
3662 NTSTATUS
netlogon_creds_cli_SendToSam(struct netlogon_creds_cli_context
*context
,
3663 struct dcerpc_binding_handle
*b
,
3664 struct netr_SendToSamBase
*message
)
3666 TALLOC_CTX
*frame
= talloc_stackframe();
3667 struct tevent_context
*ev
;
3668 struct tevent_req
*req
;
3669 NTSTATUS status
= NT_STATUS_OK
;
3671 ev
= samba_tevent_context_init(frame
);
3675 req
= netlogon_creds_cli_SendToSam_send(frame
, ev
, context
, b
, message
);
3679 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3683 /* Ignore the result */