2 Unix SMB/CIFS implementation.
4 module to store/fetch session keys for the schannel client
6 Copyright (C) Stefan Metzmacher 2013
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "system/filesys.h"
25 #include "lib/util/tevent_ntstatus.h"
26 #include "lib/dbwrap/dbwrap.h"
27 #include "lib/dbwrap/dbwrap_rbt.h"
28 #include "lib/util/util_tdb.h"
29 #include "libcli/security/security.h"
30 #include "../lib/param/param.h"
31 #include "../libcli/auth/schannel.h"
32 #include "../librpc/gen_ndr/ndr_schannel.h"
33 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
34 #include "../librpc/gen_ndr/server_id.h"
35 #include "netlogon_creds_cli.h"
36 #include "source3/include/messages.h"
37 #include "source3/include/g_lock.h"
38 #include "libds/common/roles.h"
40 struct netlogon_creds_cli_locked_state
;
42 struct netlogon_creds_cli_context
{
46 uint32_t proposed_flags
;
47 uint32_t required_flags
;
48 enum netr_SchannelType type
;
49 enum dcerpc_AuthLevel auth_level
;
54 const char *netbios_domain
;
55 uint32_t cached_flags
;
64 struct db_context
*ctx
;
65 struct g_lock_ctx
*g_ctx
;
66 struct netlogon_creds_cli_locked_state
*locked_state
;
70 struct netlogon_creds_cli_locked_state
{
71 struct netlogon_creds_cli_context
*context
;
73 struct netlogon_creds_CredentialState
*creds
;
76 static int netlogon_creds_cli_locked_state_destructor(
77 struct netlogon_creds_cli_locked_state
*state
)
79 struct netlogon_creds_cli_context
*context
= state
->context
;
81 if (context
== NULL
) {
85 if (context
->db
.locked_state
== state
) {
86 context
->db
.locked_state
= NULL
;
89 if (state
->is_glocked
) {
90 g_lock_unlock(context
->db
.g_ctx
,
91 context
->db
.key_name
);
97 static NTSTATUS
netlogon_creds_cli_context_common(
98 const char *client_computer
,
99 const char *client_account
,
100 enum netr_SchannelType type
,
101 enum dcerpc_AuthLevel auth_level
,
102 uint32_t proposed_flags
,
103 uint32_t required_flags
,
104 const char *server_computer
,
105 const char *server_netbios_domain
,
107 struct netlogon_creds_cli_context
**_context
)
109 struct netlogon_creds_cli_context
*context
= NULL
;
110 TALLOC_CTX
*frame
= talloc_stackframe();
111 char *_key_name
= NULL
;
112 char *server_netbios_name
= NULL
;
117 context
= talloc_zero(mem_ctx
, struct netlogon_creds_cli_context
);
118 if (context
== NULL
) {
120 return NT_STATUS_NO_MEMORY
;
123 context
->client
.computer
= talloc_strdup(context
, client_computer
);
124 if (context
->client
.computer
== NULL
) {
125 TALLOC_FREE(context
);
127 return NT_STATUS_NO_MEMORY
;
130 context
->client
.account
= talloc_strdup(context
, client_account
);
131 if (context
->client
.account
== NULL
) {
132 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
);
146 return NT_STATUS_NO_MEMORY
;
149 context
->server
.netbios_domain
= talloc_strdup(context
, server_netbios_domain
);
150 if (context
->server
.netbios_domain
== NULL
) {
151 TALLOC_FREE(context
);
153 return NT_STATUS_NO_MEMORY
;
158 * Force the callers to provide a unique
159 * value for server_computer and use this directly.
161 * For now we have to deal with
162 * "HOSTNAME" vs. "hostname.example.com".
164 server_netbios_name
= talloc_strdup(frame
, server_computer
);
165 if (server_netbios_name
== NULL
) {
166 TALLOC_FREE(context
);
168 return NT_STATUS_NO_MEMORY
;
171 p
= strchr(server_netbios_name
, '.');
176 _key_name
= talloc_asprintf(frame
, "CLI[%s/%s]/SRV[%s/%s]",
180 server_netbios_domain
);
181 if (_key_name
== NULL
) {
182 TALLOC_FREE(context
);
184 return NT_STATUS_NO_MEMORY
;
187 context
->db
.key_name
= talloc_strdup_upper(context
, _key_name
);
188 if (context
->db
.key_name
== NULL
) {
189 TALLOC_FREE(context
);
191 return NT_STATUS_NO_MEMORY
;
194 context
->db
.key_data
= string_term_tdb_data(context
->db
.key_name
);
201 static struct db_context
*netlogon_creds_cli_global_db
;
203 NTSTATUS
netlogon_creds_cli_set_global_db(struct db_context
**db
)
205 if (netlogon_creds_cli_global_db
!= NULL
) {
206 return NT_STATUS_INVALID_PARAMETER_MIX
;
209 netlogon_creds_cli_global_db
= talloc_move(talloc_autofree_context(), db
);
213 NTSTATUS
netlogon_creds_cli_open_global_db(struct loadparm_context
*lp_ctx
)
216 struct db_context
*global_db
;
218 if (netlogon_creds_cli_global_db
!= NULL
) {
222 fname
= lpcfg_private_db_path(talloc_autofree_context(), lp_ctx
, "netlogon_creds_cli");
224 return NT_STATUS_NO_MEMORY
;
227 global_db
= dbwrap_local_open(talloc_autofree_context(), lp_ctx
,
229 TDB_CLEAR_IF_FIRST
|TDB_INCOMPATIBLE_HASH
,
231 0600, DBWRAP_LOCK_ORDER_2
,
233 if (global_db
== NULL
) {
234 DEBUG(0,("netlogon_creds_cli_open_global_db: Failed to open %s - %s\n",
235 fname
, strerror(errno
)));
237 return NT_STATUS_NO_MEMORY
;
241 netlogon_creds_cli_global_db
= global_db
;
245 NTSTATUS
netlogon_creds_cli_context_global(struct loadparm_context
*lp_ctx
,
246 struct messaging_context
*msg_ctx
,
247 const char *client_account
,
248 enum netr_SchannelType type
,
249 const char *server_computer
,
250 const char *server_netbios_domain
,
252 struct netlogon_creds_cli_context
**_context
)
254 TALLOC_CTX
*frame
= talloc_stackframe();
256 struct netlogon_creds_cli_context
*context
= NULL
;
257 const char *client_computer
;
258 uint32_t proposed_flags
;
259 uint32_t required_flags
= 0;
260 bool reject_md5_servers
= false;
261 bool require_strong_key
= false;
262 int require_sign_or_seal
= true;
263 bool seal_secure_channel
= true;
264 enum dcerpc_AuthLevel auth_level
= DCERPC_AUTH_LEVEL_NONE
;
265 bool neutralize_nt4_emulation
= false;
269 client_computer
= lpcfg_netbios_name(lp_ctx
);
270 if (strlen(client_computer
) > 15) {
271 return NT_STATUS_INVALID_PARAMETER_MIX
;
275 * allow overwrite per domain
276 * reject md5 servers:<netbios_domain>
278 reject_md5_servers
= lpcfg_reject_md5_servers(lp_ctx
);
279 reject_md5_servers
= lpcfg_parm_bool(lp_ctx
, NULL
,
280 "reject md5 servers",
281 server_netbios_domain
,
285 * allow overwrite per domain
286 * require strong key:<netbios_domain>
288 require_strong_key
= lpcfg_require_strong_key(lp_ctx
);
289 require_strong_key
= lpcfg_parm_bool(lp_ctx
, NULL
,
290 "require strong key",
291 server_netbios_domain
,
295 * allow overwrite per domain
296 * client schannel:<netbios_domain>
298 require_sign_or_seal
= lpcfg_client_schannel(lp_ctx
);
299 require_sign_or_seal
= lpcfg_parm_int(lp_ctx
, NULL
,
301 server_netbios_domain
,
302 require_sign_or_seal
);
305 * allow overwrite per domain
306 * winbind sealed pipes:<netbios_domain>
308 seal_secure_channel
= lpcfg_winbind_sealed_pipes(lp_ctx
);
309 seal_secure_channel
= lpcfg_parm_bool(lp_ctx
, NULL
,
310 "winbind sealed pipes",
311 server_netbios_domain
,
312 seal_secure_channel
);
315 * allow overwrite per domain
316 * neutralize nt4 emulation:<netbios_domain>
318 neutralize_nt4_emulation
= lpcfg_neutralize_nt4_emulation(lp_ctx
);
319 neutralize_nt4_emulation
= lpcfg_parm_bool(lp_ctx
, NULL
,
320 "neutralize nt4 emulation",
321 server_netbios_domain
,
322 neutralize_nt4_emulation
);
324 proposed_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
325 proposed_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
329 if (lpcfg_security(lp_ctx
) == SEC_ADS
) {
331 * AD domains should be secure
333 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
334 require_sign_or_seal
= true;
335 require_strong_key
= true;
339 case SEC_CHAN_DOMAIN
:
342 case SEC_CHAN_DNS_DOMAIN
:
344 * AD domains should be secure
346 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
347 require_sign_or_seal
= true;
348 require_strong_key
= true;
349 neutralize_nt4_emulation
= true;
353 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
354 require_sign_or_seal
= true;
355 require_strong_key
= true;
359 required_flags
|= NETLOGON_NEG_RODC_PASSTHROUGH
;
360 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
361 require_sign_or_seal
= true;
362 require_strong_key
= true;
363 neutralize_nt4_emulation
= true;
368 return NT_STATUS_INVALID_PARAMETER
;
371 if (neutralize_nt4_emulation
) {
372 proposed_flags
|= NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION
;
375 if (require_sign_or_seal
== false) {
376 proposed_flags
&= ~NETLOGON_NEG_AUTHENTICATED_RPC
;
378 required_flags
|= NETLOGON_NEG_ARCFOUR
;
379 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
382 if (reject_md5_servers
) {
383 required_flags
|= NETLOGON_NEG_ARCFOUR
;
384 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
385 required_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
386 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
389 if (require_strong_key
) {
390 required_flags
|= NETLOGON_NEG_ARCFOUR
;
391 required_flags
|= NETLOGON_NEG_STRONG_KEYS
;
392 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
395 proposed_flags
|= required_flags
;
397 if (seal_secure_channel
) {
398 auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
400 auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
403 status
= netlogon_creds_cli_context_common(client_computer
,
410 server_netbios_domain
,
413 if (!NT_STATUS_IS_OK(status
)) {
418 if (msg_ctx
!= NULL
) {
419 context
->db
.g_ctx
= g_lock_ctx_init(context
, msg_ctx
);
420 if (context
->db
.g_ctx
== NULL
) {
421 TALLOC_FREE(context
);
423 return NT_STATUS_NO_MEMORY
;
427 if (netlogon_creds_cli_global_db
!= NULL
) {
428 context
->db
.ctx
= netlogon_creds_cli_global_db
;
434 status
= netlogon_creds_cli_open_global_db(lp_ctx
);
435 if (!NT_STATUS_IS_OK(status
)) {
436 TALLOC_FREE(context
);
438 return NT_STATUS_NO_MEMORY
;
441 context
->db
.ctx
= netlogon_creds_cli_global_db
;
447 NTSTATUS
netlogon_creds_cli_context_tmp(const char *client_computer
,
448 const char *client_account
,
449 enum netr_SchannelType type
,
450 uint32_t proposed_flags
,
451 uint32_t required_flags
,
452 enum dcerpc_AuthLevel auth_level
,
453 const char *server_computer
,
454 const char *server_netbios_domain
,
456 struct netlogon_creds_cli_context
**_context
)
459 struct netlogon_creds_cli_context
*context
= NULL
;
463 status
= netlogon_creds_cli_context_common(client_computer
,
470 server_netbios_domain
,
473 if (!NT_STATUS_IS_OK(status
)) {
477 context
->db
.ctx
= db_open_rbt(context
);
478 if (context
->db
.ctx
== NULL
) {
479 talloc_free(context
);
480 return NT_STATUS_NO_MEMORY
;
487 char *netlogon_creds_cli_debug_string(
488 const struct netlogon_creds_cli_context
*context
,
491 return talloc_asprintf(mem_ctx
, "netlogon_creds_cli:%s",
492 context
->db
.key_name
);
495 enum dcerpc_AuthLevel
netlogon_creds_cli_auth_level(
496 struct netlogon_creds_cli_context
*context
)
498 return context
->client
.auth_level
;
501 struct netlogon_creds_cli_fetch_state
{
503 struct netlogon_creds_CredentialState
*creds
;
504 uint32_t required_flags
;
508 static void netlogon_creds_cli_fetch_parser(TDB_DATA key
, TDB_DATA data
,
511 struct netlogon_creds_cli_fetch_state
*state
=
512 (struct netlogon_creds_cli_fetch_state
*)private_data
;
513 enum ndr_err_code ndr_err
;
517 state
->creds
= talloc_zero(state
->mem_ctx
,
518 struct netlogon_creds_CredentialState
);
519 if (state
->creds
== NULL
) {
520 state
->status
= NT_STATUS_NO_MEMORY
;
524 blob
.data
= data
.dptr
;
525 blob
.length
= data
.dsize
;
527 ndr_err
= ndr_pull_struct_blob(&blob
, state
->creds
, state
->creds
,
528 (ndr_pull_flags_fn_t
)ndr_pull_netlogon_creds_CredentialState
);
529 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
530 TALLOC_FREE(state
->creds
);
531 state
->status
= ndr_map_error2ntstatus(ndr_err
);
535 tmp_flags
= state
->creds
->negotiate_flags
;
536 tmp_flags
&= state
->required_flags
;
537 if (tmp_flags
!= state
->required_flags
) {
538 TALLOC_FREE(state
->creds
);
539 state
->status
= NT_STATUS_DOWNGRADE_DETECTED
;
543 state
->status
= NT_STATUS_OK
;
546 NTSTATUS
netlogon_creds_cli_get(struct netlogon_creds_cli_context
*context
,
548 struct netlogon_creds_CredentialState
**_creds
)
551 struct netlogon_creds_cli_fetch_state fstate
= {
553 .status
= NT_STATUS_INTERNAL_ERROR
,
554 .required_flags
= context
->client
.required_flags
,
556 static const struct netr_Credential zero_creds
;
560 status
= dbwrap_parse_record(context
->db
.ctx
,
561 context
->db
.key_data
,
562 netlogon_creds_cli_fetch_parser
,
564 if (!NT_STATUS_IS_OK(status
)) {
567 status
= fstate
.status
;
568 if (!NT_STATUS_IS_OK(status
)) {
573 * mark it as invalid for step operations.
575 fstate
.creds
->sequence
= 0;
576 fstate
.creds
->seed
= zero_creds
;
577 fstate
.creds
->client
= zero_creds
;
578 fstate
.creds
->server
= zero_creds
;
580 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
581 *_creds
= fstate
.creds
;
586 * It is really important to try SamLogonEx here,
587 * because multiple processes can talk to the same
588 * domain controller, without using the credential
591 * With a normal SamLogon call, we must keep the
592 * credentials chain updated and intact between all
593 * users of the machine account (which would imply
594 * cross-node communication for every NTLM logon).
596 * The credentials chain is not per NETLOGON pipe
597 * connection, but globally on the server/client pair
598 * by computer name, while the client is free to use
599 * any computer name. We include the cluster node number
600 * in our computer name in order to avoid cross node
601 * coordination of the credential chain.
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 if (blob1
.length
!= blob2
.length
) {
672 cmp
= memcmp(blob1
.data
, blob2
.data
, blob1
.length
);
682 NTSTATUS
netlogon_creds_cli_store(struct netlogon_creds_cli_context
*context
,
683 struct netlogon_creds_CredentialState
**_creds
)
685 struct netlogon_creds_CredentialState
*creds
= *_creds
;
687 enum ndr_err_code ndr_err
;
693 if (context
->db
.locked_state
== NULL
) {
695 * this was not the result of netlogon_creds_cli_lock*()
698 return NT_STATUS_INVALID_PAGE_PROTECTION
;
701 if (context
->db
.locked_state
->creds
!= creds
) {
703 * this was not the result of netlogon_creds_cli_lock*()
706 return NT_STATUS_INVALID_PAGE_PROTECTION
;
709 ndr_err
= ndr_push_struct_blob(&blob
, creds
, creds
,
710 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
711 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
713 status
= ndr_map_error2ntstatus(ndr_err
);
717 data
.dptr
= blob
.data
;
718 data
.dsize
= blob
.length
;
720 status
= dbwrap_store(context
->db
.ctx
,
721 context
->db
.key_data
,
724 if (!NT_STATUS_IS_OK(status
)) {
731 NTSTATUS
netlogon_creds_cli_delete(struct netlogon_creds_cli_context
*context
,
732 struct netlogon_creds_CredentialState
**_creds
)
734 struct netlogon_creds_CredentialState
*creds
= *_creds
;
739 if (context
->db
.locked_state
== NULL
) {
741 * this was not the result of netlogon_creds_cli_lock*()
744 return NT_STATUS_INVALID_PAGE_PROTECTION
;
747 if (context
->db
.locked_state
->creds
!= creds
) {
749 * this was not the result of netlogon_creds_cli_lock*()
752 return NT_STATUS_INVALID_PAGE_PROTECTION
;
755 status
= dbwrap_delete(context
->db
.ctx
,
756 context
->db
.key_data
);
758 if (!NT_STATUS_IS_OK(status
)) {
765 struct netlogon_creds_cli_lock_state
{
766 struct netlogon_creds_cli_locked_state
*locked_state
;
767 struct netlogon_creds_CredentialState
*creds
;
770 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
);
771 static void netlogon_creds_cli_lock_fetch(struct tevent_req
*req
);
773 struct tevent_req
*netlogon_creds_cli_lock_send(TALLOC_CTX
*mem_ctx
,
774 struct tevent_context
*ev
,
775 struct netlogon_creds_cli_context
*context
)
777 struct tevent_req
*req
;
778 struct netlogon_creds_cli_lock_state
*state
;
779 struct netlogon_creds_cli_locked_state
*locked_state
;
780 struct tevent_req
*subreq
;
782 req
= tevent_req_create(mem_ctx
, &state
,
783 struct netlogon_creds_cli_lock_state
);
788 if (context
->db
.locked_state
!= NULL
) {
789 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
790 return tevent_req_post(req
, ev
);
793 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
794 if (tevent_req_nomem(locked_state
, req
)) {
795 return tevent_req_post(req
, ev
);
797 talloc_set_destructor(locked_state
,
798 netlogon_creds_cli_locked_state_destructor
);
799 locked_state
->context
= context
;
801 context
->db
.locked_state
= locked_state
;
802 state
->locked_state
= locked_state
;
804 if (context
->db
.g_ctx
== NULL
) {
805 netlogon_creds_cli_lock_fetch(req
);
806 if (!tevent_req_is_in_progress(req
)) {
807 return tevent_req_post(req
, ev
);
813 subreq
= g_lock_lock_send(state
, ev
,
815 context
->db
.key_name
,
817 if (tevent_req_nomem(subreq
, req
)) {
818 return tevent_req_post(req
, ev
);
820 tevent_req_set_callback(subreq
, netlogon_creds_cli_lock_done
, req
);
825 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
)
827 struct tevent_req
*req
=
828 tevent_req_callback_data(subreq
,
830 struct netlogon_creds_cli_lock_state
*state
=
832 struct netlogon_creds_cli_lock_state
);
835 status
= g_lock_lock_recv(subreq
);
837 if (tevent_req_nterror(req
, status
)) {
840 state
->locked_state
->is_glocked
= true;
842 netlogon_creds_cli_lock_fetch(req
);
845 static void netlogon_creds_cli_lock_fetch(struct tevent_req
*req
)
847 struct netlogon_creds_cli_lock_state
*state
=
849 struct netlogon_creds_cli_lock_state
);
850 struct netlogon_creds_cli_context
*context
= state
->locked_state
->context
;
851 struct netlogon_creds_cli_fetch_state fstate
= {
852 .status
= NT_STATUS_INTERNAL_ERROR
,
853 .required_flags
= context
->client
.required_flags
,
857 fstate
.mem_ctx
= state
;
858 status
= dbwrap_parse_record(context
->db
.ctx
,
859 context
->db
.key_data
,
860 netlogon_creds_cli_fetch_parser
,
862 if (tevent_req_nterror(req
, status
)) {
865 status
= fstate
.status
;
866 if (tevent_req_nterror(req
, status
)) {
870 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
871 state
->creds
= fstate
.creds
;
872 tevent_req_done(req
);
876 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
877 context
->server
.try_validation6
= true;
878 context
->server
.try_logon_ex
= true;
879 context
->server
.try_logon_with
= true;
881 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
882 context
->server
.try_validation6
= false;
883 context
->server
.try_logon_ex
= false;
885 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
886 context
->server
.try_validation6
= false;
889 state
->creds
= fstate
.creds
;
890 tevent_req_done(req
);
894 NTSTATUS
netlogon_creds_cli_lock_recv(struct tevent_req
*req
,
896 struct netlogon_creds_CredentialState
**creds
)
898 struct netlogon_creds_cli_lock_state
*state
=
900 struct netlogon_creds_cli_lock_state
);
903 if (tevent_req_is_nterror(req
, &status
)) {
904 tevent_req_received(req
);
908 talloc_steal(state
->creds
, state
->locked_state
);
909 state
->locked_state
->creds
= state
->creds
;
910 *creds
= talloc_move(mem_ctx
, &state
->creds
);
911 tevent_req_received(req
);
915 NTSTATUS
netlogon_creds_cli_lock(struct netlogon_creds_cli_context
*context
,
917 struct netlogon_creds_CredentialState
**creds
)
919 TALLOC_CTX
*frame
= talloc_stackframe();
920 struct tevent_context
*ev
;
921 struct tevent_req
*req
;
922 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
924 ev
= samba_tevent_context_init(frame
);
928 req
= netlogon_creds_cli_lock_send(frame
, ev
, context
);
932 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
935 status
= netlogon_creds_cli_lock_recv(req
, mem_ctx
, creds
);
941 struct netlogon_creds_cli_auth_state
{
942 struct tevent_context
*ev
;
943 struct netlogon_creds_cli_context
*context
;
944 struct dcerpc_binding_handle
*binding_handle
;
945 struct samr_Password current_nt_hash
;
946 struct samr_Password previous_nt_hash
;
947 struct samr_Password used_nt_hash
;
948 char *srv_name_slash
;
949 uint32_t current_flags
;
950 struct netr_Credential client_challenge
;
951 struct netr_Credential server_challenge
;
952 struct netlogon_creds_CredentialState
*creds
;
953 struct netr_Credential client_credential
;
954 struct netr_Credential server_credential
;
959 bool try_previous_nt_hash
;
960 struct netlogon_creds_cli_locked_state
*locked_state
;
963 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
);
964 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
);
966 struct tevent_req
*netlogon_creds_cli_auth_send(TALLOC_CTX
*mem_ctx
,
967 struct tevent_context
*ev
,
968 struct netlogon_creds_cli_context
*context
,
969 struct dcerpc_binding_handle
*b
,
970 struct samr_Password current_nt_hash
,
971 const struct samr_Password
*previous_nt_hash
)
973 struct tevent_req
*req
;
974 struct netlogon_creds_cli_auth_state
*state
;
975 struct netlogon_creds_cli_locked_state
*locked_state
;
978 req
= tevent_req_create(mem_ctx
, &state
,
979 struct netlogon_creds_cli_auth_state
);
985 state
->context
= context
;
986 state
->binding_handle
= b
;
987 state
->current_nt_hash
= current_nt_hash
;
988 if (previous_nt_hash
!= NULL
) {
989 state
->previous_nt_hash
= *previous_nt_hash
;
990 state
->try_previous_nt_hash
= true;
993 if (context
->db
.locked_state
!= NULL
) {
994 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
995 return tevent_req_post(req
, ev
);
998 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
999 if (tevent_req_nomem(locked_state
, req
)) {
1000 return tevent_req_post(req
, ev
);
1002 talloc_set_destructor(locked_state
,
1003 netlogon_creds_cli_locked_state_destructor
);
1004 locked_state
->context
= context
;
1006 context
->db
.locked_state
= locked_state
;
1007 state
->locked_state
= locked_state
;
1009 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1010 context
->server
.computer
);
1011 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1012 return tevent_req_post(req
, ev
);
1015 state
->try_auth3
= true;
1016 state
->try_auth2
= true;
1018 if (context
->client
.required_flags
!= 0) {
1019 state
->require_auth2
= true;
1022 state
->used_nt_hash
= state
->current_nt_hash
;
1023 state
->current_flags
= context
->client
.proposed_flags
;
1025 if (context
->db
.g_ctx
!= NULL
) {
1026 struct tevent_req
*subreq
;
1028 subreq
= g_lock_lock_send(state
, ev
,
1030 context
->db
.key_name
,
1032 if (tevent_req_nomem(subreq
, req
)) {
1033 return tevent_req_post(req
, ev
);
1035 tevent_req_set_callback(subreq
,
1036 netlogon_creds_cli_auth_locked
,
1042 status
= dbwrap_purge(state
->context
->db
.ctx
,
1043 state
->context
->db
.key_data
);
1044 if (tevent_req_nterror(req
, status
)) {
1045 return tevent_req_post(req
, ev
);
1048 netlogon_creds_cli_auth_challenge_start(req
);
1049 if (!tevent_req_is_in_progress(req
)) {
1050 return tevent_req_post(req
, ev
);
1056 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
)
1058 struct tevent_req
*req
=
1059 tevent_req_callback_data(subreq
,
1061 struct netlogon_creds_cli_auth_state
*state
=
1062 tevent_req_data(req
,
1063 struct netlogon_creds_cli_auth_state
);
1066 status
= g_lock_lock_recv(subreq
);
1067 TALLOC_FREE(subreq
);
1068 if (tevent_req_nterror(req
, status
)) {
1071 state
->locked_state
->is_glocked
= true;
1073 status
= dbwrap_purge(state
->context
->db
.ctx
,
1074 state
->context
->db
.key_data
);
1075 if (tevent_req_nterror(req
, status
)) {
1079 netlogon_creds_cli_auth_challenge_start(req
);
1082 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
);
1084 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
)
1086 struct netlogon_creds_cli_auth_state
*state
=
1087 tevent_req_data(req
,
1088 struct netlogon_creds_cli_auth_state
);
1089 struct tevent_req
*subreq
;
1091 TALLOC_FREE(state
->creds
);
1093 generate_random_buffer(state
->client_challenge
.data
,
1094 sizeof(state
->client_challenge
.data
));
1096 subreq
= dcerpc_netr_ServerReqChallenge_send(state
, state
->ev
,
1097 state
->binding_handle
,
1098 state
->srv_name_slash
,
1099 state
->context
->client
.computer
,
1100 &state
->client_challenge
,
1101 &state
->server_challenge
);
1102 if (tevent_req_nomem(subreq
, req
)) {
1105 tevent_req_set_callback(subreq
,
1106 netlogon_creds_cli_auth_challenge_done
,
1110 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
);
1112 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
)
1114 struct tevent_req
*req
=
1115 tevent_req_callback_data(subreq
,
1117 struct netlogon_creds_cli_auth_state
*state
=
1118 tevent_req_data(req
,
1119 struct netlogon_creds_cli_auth_state
);
1123 status
= dcerpc_netr_ServerReqChallenge_recv(subreq
, state
, &result
);
1124 TALLOC_FREE(subreq
);
1125 if (tevent_req_nterror(req
, status
)) {
1128 if (tevent_req_nterror(req
, result
)) {
1132 if (!state
->try_auth3
&& !state
->try_auth2
) {
1133 state
->current_flags
= 0;
1136 /* Calculate the session key and client credentials */
1138 state
->creds
= netlogon_creds_client_init(state
,
1139 state
->context
->client
.account
,
1140 state
->context
->client
.computer
,
1141 state
->context
->client
.type
,
1142 &state
->client_challenge
,
1143 &state
->server_challenge
,
1144 &state
->used_nt_hash
,
1145 &state
->client_credential
,
1146 state
->current_flags
);
1147 if (tevent_req_nomem(state
->creds
, req
)) {
1151 if (state
->try_auth3
) {
1152 subreq
= dcerpc_netr_ServerAuthenticate3_send(state
, state
->ev
,
1153 state
->binding_handle
,
1154 state
->srv_name_slash
,
1155 state
->context
->client
.account
,
1156 state
->context
->client
.type
,
1157 state
->context
->client
.computer
,
1158 &state
->client_credential
,
1159 &state
->server_credential
,
1160 &state
->creds
->negotiate_flags
,
1162 if (tevent_req_nomem(subreq
, req
)) {
1165 } else if (state
->try_auth2
) {
1168 subreq
= dcerpc_netr_ServerAuthenticate2_send(state
, state
->ev
,
1169 state
->binding_handle
,
1170 state
->srv_name_slash
,
1171 state
->context
->client
.account
,
1172 state
->context
->client
.type
,
1173 state
->context
->client
.computer
,
1174 &state
->client_credential
,
1175 &state
->server_credential
,
1176 &state
->creds
->negotiate_flags
);
1177 if (tevent_req_nomem(subreq
, req
)) {
1183 subreq
= dcerpc_netr_ServerAuthenticate_send(state
, state
->ev
,
1184 state
->binding_handle
,
1185 state
->srv_name_slash
,
1186 state
->context
->client
.account
,
1187 state
->context
->client
.type
,
1188 state
->context
->client
.computer
,
1189 &state
->client_credential
,
1190 &state
->server_credential
);
1191 if (tevent_req_nomem(subreq
, req
)) {
1195 tevent_req_set_callback(subreq
,
1196 netlogon_creds_cli_auth_srvauth_done
,
1200 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
)
1202 struct tevent_req
*req
=
1203 tevent_req_callback_data(subreq
,
1205 struct netlogon_creds_cli_auth_state
*state
=
1206 tevent_req_data(req
,
1207 struct netlogon_creds_cli_auth_state
);
1211 enum ndr_err_code ndr_err
;
1216 if (state
->try_auth3
) {
1217 status
= dcerpc_netr_ServerAuthenticate3_recv(subreq
, state
,
1219 TALLOC_FREE(subreq
);
1220 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1221 state
->try_auth3
= false;
1222 netlogon_creds_cli_auth_challenge_start(req
);
1225 if (tevent_req_nterror(req
, status
)) {
1228 } else if (state
->try_auth2
) {
1229 status
= dcerpc_netr_ServerAuthenticate2_recv(subreq
, state
,
1231 TALLOC_FREE(subreq
);
1232 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1233 state
->try_auth2
= false;
1234 if (state
->require_auth2
) {
1235 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1236 tevent_req_nterror(req
, status
);
1239 netlogon_creds_cli_auth_challenge_start(req
);
1242 if (tevent_req_nterror(req
, status
)) {
1246 status
= dcerpc_netr_ServerAuthenticate_recv(subreq
, state
,
1248 TALLOC_FREE(subreq
);
1249 if (tevent_req_nterror(req
, status
)) {
1254 if (!NT_STATUS_IS_OK(result
) &&
1255 !NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
))
1257 tevent_req_nterror(req
, result
);
1261 tmp_flags
= state
->creds
->negotiate_flags
;
1262 tmp_flags
&= state
->context
->client
.required_flags
;
1263 if (tmp_flags
!= state
->context
->client
.required_flags
) {
1264 if (NT_STATUS_IS_OK(result
)) {
1265 tevent_req_nterror(req
, NT_STATUS_DOWNGRADE_DETECTED
);
1268 tevent_req_nterror(req
, result
);
1272 if (NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
)) {
1274 tmp_flags
= state
->context
->client
.proposed_flags
;
1275 if ((state
->current_flags
== tmp_flags
) &&
1276 (state
->creds
->negotiate_flags
!= tmp_flags
))
1279 * lets retry with the negotiated flags
1281 state
->current_flags
= state
->creds
->negotiate_flags
;
1282 netlogon_creds_cli_auth_challenge_start(req
);
1286 if (!state
->try_previous_nt_hash
) {
1288 * we already retried, giving up...
1290 tevent_req_nterror(req
, result
);
1295 * lets retry with the old nt hash.
1297 state
->try_previous_nt_hash
= false;
1298 state
->used_nt_hash
= state
->previous_nt_hash
;
1299 state
->current_flags
= state
->context
->client
.proposed_flags
;
1300 netlogon_creds_cli_auth_challenge_start(req
);
1304 ok
= netlogon_creds_client_check(state
->creds
,
1305 &state
->server_credential
);
1307 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1311 ndr_err
= ndr_push_struct_blob(&blob
, state
, state
->creds
,
1312 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
1313 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1314 status
= ndr_map_error2ntstatus(ndr_err
);
1315 tevent_req_nterror(req
, status
);
1319 data
.dptr
= blob
.data
;
1320 data
.dsize
= blob
.length
;
1322 status
= dbwrap_store(state
->context
->db
.ctx
,
1323 state
->context
->db
.key_data
,
1325 TALLOC_FREE(state
->locked_state
);
1326 if (tevent_req_nterror(req
, status
)) {
1330 tevent_req_done(req
);
1333 NTSTATUS
netlogon_creds_cli_auth_recv(struct tevent_req
*req
)
1337 if (tevent_req_is_nterror(req
, &status
)) {
1338 tevent_req_received(req
);
1342 tevent_req_received(req
);
1343 return NT_STATUS_OK
;
1346 NTSTATUS
netlogon_creds_cli_auth(struct netlogon_creds_cli_context
*context
,
1347 struct dcerpc_binding_handle
*b
,
1348 struct samr_Password current_nt_hash
,
1349 const struct samr_Password
*previous_nt_hash
)
1351 TALLOC_CTX
*frame
= talloc_stackframe();
1352 struct tevent_context
*ev
;
1353 struct tevent_req
*req
;
1354 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1356 ev
= samba_tevent_context_init(frame
);
1360 req
= netlogon_creds_cli_auth_send(frame
, ev
, context
, b
,
1366 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1369 status
= netlogon_creds_cli_auth_recv(req
);
1375 struct netlogon_creds_cli_check_state
{
1376 struct tevent_context
*ev
;
1377 struct netlogon_creds_cli_context
*context
;
1378 struct dcerpc_binding_handle
*binding_handle
;
1380 char *srv_name_slash
;
1382 union netr_Capabilities caps
;
1384 struct netlogon_creds_CredentialState
*creds
;
1385 struct netlogon_creds_CredentialState tmp_creds
;
1386 struct netr_Authenticator req_auth
;
1387 struct netr_Authenticator rep_auth
;
1390 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1392 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
);
1394 struct tevent_req
*netlogon_creds_cli_check_send(TALLOC_CTX
*mem_ctx
,
1395 struct tevent_context
*ev
,
1396 struct netlogon_creds_cli_context
*context
,
1397 struct dcerpc_binding_handle
*b
)
1399 struct tevent_req
*req
;
1400 struct netlogon_creds_cli_check_state
*state
;
1401 struct tevent_req
*subreq
;
1402 enum dcerpc_AuthType auth_type
;
1403 enum dcerpc_AuthLevel auth_level
;
1405 req
= tevent_req_create(mem_ctx
, &state
,
1406 struct netlogon_creds_cli_check_state
);
1412 state
->context
= context
;
1413 state
->binding_handle
= b
;
1415 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1416 context
->server
.computer
);
1417 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1418 return tevent_req_post(req
, ev
);
1421 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1422 &auth_type
, &auth_level
);
1424 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
1425 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1426 return tevent_req_post(req
, ev
);
1429 switch (auth_level
) {
1430 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1431 case DCERPC_AUTH_LEVEL_PRIVACY
:
1434 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1435 return tevent_req_post(req
, ev
);
1438 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1440 if (tevent_req_nomem(subreq
, req
)) {
1441 return tevent_req_post(req
, ev
);
1444 tevent_req_set_callback(subreq
,
1445 netlogon_creds_cli_check_locked
,
1451 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1454 struct netlogon_creds_cli_check_state
*state
=
1455 tevent_req_data(req
,
1456 struct netlogon_creds_cli_check_state
);
1458 if (state
->creds
== NULL
) {
1462 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1463 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1464 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1465 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1466 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1467 TALLOC_FREE(state
->creds
);
1471 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
1474 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
);
1476 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
)
1478 struct tevent_req
*req
=
1479 tevent_req_callback_data(subreq
,
1481 struct netlogon_creds_cli_check_state
*state
=
1482 tevent_req_data(req
,
1483 struct netlogon_creds_cli_check_state
);
1486 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1488 TALLOC_FREE(subreq
);
1489 if (tevent_req_nterror(req
, status
)) {
1494 * we defer all callbacks in order to cleanup
1495 * the database record.
1497 tevent_req_defer_callback(req
, state
->ev
);
1499 state
->tmp_creds
= *state
->creds
;
1500 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1502 ZERO_STRUCT(state
->rep_auth
);
1504 subreq
= dcerpc_netr_LogonGetCapabilities_send(state
, state
->ev
,
1505 state
->binding_handle
,
1506 state
->srv_name_slash
,
1507 state
->context
->client
.computer
,
1512 if (tevent_req_nomem(subreq
, req
)) {
1513 status
= NT_STATUS_NO_MEMORY
;
1514 netlogon_creds_cli_check_cleanup(req
, status
);
1517 tevent_req_set_callback(subreq
,
1518 netlogon_creds_cli_check_caps
,
1522 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
)
1524 struct tevent_req
*req
=
1525 tevent_req_callback_data(subreq
,
1527 struct netlogon_creds_cli_check_state
*state
=
1528 tevent_req_data(req
,
1529 struct netlogon_creds_cli_check_state
);
1534 status
= dcerpc_netr_LogonGetCapabilities_recv(subreq
, state
,
1536 TALLOC_FREE(subreq
);
1537 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1539 * Note that the negotiated flags are already checked
1540 * for our required flags after the ServerAuthenticate3/2 call.
1542 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1544 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1546 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1547 * already, we expect this to work!
1549 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1550 tevent_req_nterror(req
, status
);
1551 netlogon_creds_cli_check_cleanup(req
, status
);
1555 if (negotiated
& NETLOGON_NEG_STRONG_KEYS
) {
1557 * If we have negotiated NETLOGON_NEG_STRONG_KEYS
1558 * we expect this to work at least as far as the
1559 * NOT_SUPPORTED error handled below!
1561 * NT 4.0 and Old Samba servers are not
1562 * allowed without "require strong key = no"
1564 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1565 tevent_req_nterror(req
, status
);
1566 netlogon_creds_cli_check_cleanup(req
, status
);
1571 * If we not require NETLOGON_NEG_SUPPORTS_AES or
1572 * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore
1573 * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
1575 * This is needed against NT 4.0 and old Samba servers.
1577 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
1578 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
1579 * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
1580 * with the next request as the sequence number processing
1583 netlogon_creds_cli_check_cleanup(req
, status
);
1584 tevent_req_done(req
);
1587 if (tevent_req_nterror(req
, status
)) {
1588 netlogon_creds_cli_check_cleanup(req
, status
);
1592 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOT_IMPLEMENTED
)) {
1594 * Note that the negotiated flags are already checked
1595 * for our required flags after the ServerAuthenticate3/2 call.
1597 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1599 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1601 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1602 * already, we expect this to work!
1604 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1605 tevent_req_nterror(req
, status
);
1606 netlogon_creds_cli_check_cleanup(req
, status
);
1611 * This is ok, the server does not support
1612 * NETLOGON_NEG_SUPPORTS_AES.
1614 * netr_LogonGetCapabilities() was
1615 * netr_LogonDummyRoutine1() before
1616 * NETLOGON_NEG_SUPPORTS_AES was invented.
1618 netlogon_creds_cli_check_cleanup(req
, result
);
1619 tevent_req_done(req
);
1623 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1624 &state
->rep_auth
.cred
);
1626 status
= NT_STATUS_ACCESS_DENIED
;
1627 tevent_req_nterror(req
, status
);
1628 netlogon_creds_cli_check_cleanup(req
, status
);
1632 if (tevent_req_nterror(req
, result
)) {
1633 netlogon_creds_cli_check_cleanup(req
, result
);
1637 if (state
->caps
.server_capabilities
!= state
->tmp_creds
.negotiate_flags
) {
1638 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1639 tevent_req_nterror(req
, status
);
1640 netlogon_creds_cli_check_cleanup(req
, status
);
1645 * This is the key check that makes this check secure. If we
1646 * get OK here (rather than NOT_SUPPORTED), then the server
1647 * did support AES. If the server only proposed STRONG_KEYS
1648 * and not AES, then it should have failed with
1649 * NOT_IMPLEMENTED. We always send AES as a client, so the
1650 * server should always have returned it.
1652 if (!(state
->caps
.server_capabilities
& NETLOGON_NEG_SUPPORTS_AES
)) {
1653 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1654 tevent_req_nterror(req
, status
);
1655 netlogon_creds_cli_check_cleanup(req
, status
);
1659 *state
->creds
= state
->tmp_creds
;
1660 status
= netlogon_creds_cli_store(state
->context
,
1662 netlogon_creds_cli_check_cleanup(req
, status
);
1663 if (tevent_req_nterror(req
, status
)) {
1667 tevent_req_done(req
);
1670 NTSTATUS
netlogon_creds_cli_check_recv(struct tevent_req
*req
)
1674 if (tevent_req_is_nterror(req
, &status
)) {
1675 netlogon_creds_cli_check_cleanup(req
, status
);
1676 tevent_req_received(req
);
1680 tevent_req_received(req
);
1681 return NT_STATUS_OK
;
1684 NTSTATUS
netlogon_creds_cli_check(struct netlogon_creds_cli_context
*context
,
1685 struct dcerpc_binding_handle
*b
)
1687 TALLOC_CTX
*frame
= talloc_stackframe();
1688 struct tevent_context
*ev
;
1689 struct tevent_req
*req
;
1690 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1692 ev
= samba_tevent_context_init(frame
);
1696 req
= netlogon_creds_cli_check_send(frame
, ev
, context
, b
);
1700 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1703 status
= netlogon_creds_cli_check_recv(req
);
1709 struct netlogon_creds_cli_ServerPasswordSet_state
{
1710 struct tevent_context
*ev
;
1711 struct netlogon_creds_cli_context
*context
;
1712 struct dcerpc_binding_handle
*binding_handle
;
1713 uint32_t old_timeout
;
1715 char *srv_name_slash
;
1716 enum dcerpc_AuthType auth_type
;
1717 enum dcerpc_AuthLevel auth_level
;
1719 struct samr_CryptPassword samr_crypt_password
;
1720 struct netr_CryptPassword netr_crypt_password
;
1721 struct samr_Password samr_password
;
1723 struct netlogon_creds_CredentialState
*creds
;
1724 struct netlogon_creds_CredentialState tmp_creds
;
1725 struct netr_Authenticator req_auth
;
1726 struct netr_Authenticator rep_auth
;
1729 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1731 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
);
1733 struct tevent_req
*netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX
*mem_ctx
,
1734 struct tevent_context
*ev
,
1735 struct netlogon_creds_cli_context
*context
,
1736 struct dcerpc_binding_handle
*b
,
1737 const char *new_password
,
1738 const uint32_t *new_version
)
1740 struct tevent_req
*req
;
1741 struct netlogon_creds_cli_ServerPasswordSet_state
*state
;
1742 struct tevent_req
*subreq
;
1745 req
= tevent_req_create(mem_ctx
, &state
,
1746 struct netlogon_creds_cli_ServerPasswordSet_state
);
1752 state
->context
= context
;
1753 state
->binding_handle
= b
;
1756 * netr_ServerPasswordSet
1758 ok
= E_md4hash(new_password
, state
->samr_password
.hash
);
1760 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1761 return tevent_req_post(req
, ev
);
1765 * netr_ServerPasswordSet2
1767 ok
= encode_pw_buffer(state
->samr_crypt_password
.data
,
1768 new_password
, STR_UNICODE
);
1770 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1771 return tevent_req_post(req
, ev
);
1774 if (new_version
!= NULL
) {
1775 struct NL_PASSWORD_VERSION version
;
1776 uint32_t len
= IVAL(state
->samr_crypt_password
.data
, 512);
1777 uint32_t ofs
= 512 - len
;
1781 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1782 return tevent_req_post(req
, ev
);
1786 version
.ReservedField
= 0;
1787 version
.PasswordVersionNumber
= *new_version
;
1788 version
.PasswordVersionPresent
=
1789 NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT
;
1791 p
= state
->samr_crypt_password
.data
+ ofs
;
1792 SIVAL(p
, 0, version
.ReservedField
);
1793 SIVAL(p
, 4, version
.PasswordVersionNumber
);
1794 SIVAL(p
, 8, version
.PasswordVersionPresent
);
1797 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1798 context
->server
.computer
);
1799 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1800 return tevent_req_post(req
, ev
);
1803 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1805 &state
->auth_level
);
1807 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1809 if (tevent_req_nomem(subreq
, req
)) {
1810 return tevent_req_post(req
, ev
);
1813 tevent_req_set_callback(subreq
,
1814 netlogon_creds_cli_ServerPasswordSet_locked
,
1820 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1823 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1824 tevent_req_data(req
,
1825 struct netlogon_creds_cli_ServerPasswordSet_state
);
1827 if (state
->creds
== NULL
) {
1831 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
1832 state
->old_timeout
);
1834 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1835 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1836 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1837 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1838 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1839 TALLOC_FREE(state
->creds
);
1843 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
1846 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
);
1848 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
)
1850 struct tevent_req
*req
=
1851 tevent_req_callback_data(subreq
,
1853 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1854 tevent_req_data(req
,
1855 struct netlogon_creds_cli_ServerPasswordSet_state
);
1858 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1860 TALLOC_FREE(subreq
);
1861 if (tevent_req_nterror(req
, status
)) {
1865 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
1866 switch (state
->auth_level
) {
1867 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1868 case DCERPC_AUTH_LEVEL_PRIVACY
:
1871 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1875 uint32_t tmp
= state
->creds
->negotiate_flags
;
1877 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
1879 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
1880 * it should be used, which means
1881 * we had a chance to verify no downgrade
1884 * This relies on netlogon_creds_cli_check*
1885 * being called before, as first request after
1888 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1893 state
->old_timeout
= dcerpc_binding_handle_set_timeout(
1894 state
->binding_handle
, 600000);
1897 * we defer all callbacks in order to cleanup
1898 * the database record.
1900 tevent_req_defer_callback(req
, state
->ev
);
1902 state
->tmp_creds
= *state
->creds
;
1903 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1905 ZERO_STRUCT(state
->rep_auth
);
1907 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1909 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1910 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
1911 state
->samr_crypt_password
.data
,
1914 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
1915 state
->samr_crypt_password
.data
,
1919 memcpy(state
->netr_crypt_password
.data
,
1920 state
->samr_crypt_password
.data
, 512);
1921 state
->netr_crypt_password
.length
=
1922 IVAL(state
->samr_crypt_password
.data
, 512);
1924 subreq
= dcerpc_netr_ServerPasswordSet2_send(state
, state
->ev
,
1925 state
->binding_handle
,
1926 state
->srv_name_slash
,
1927 state
->tmp_creds
.account_name
,
1928 state
->tmp_creds
.secure_channel_type
,
1929 state
->tmp_creds
.computer_name
,
1932 &state
->netr_crypt_password
);
1933 if (tevent_req_nomem(subreq
, req
)) {
1934 status
= NT_STATUS_NO_MEMORY
;
1935 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1939 netlogon_creds_des_encrypt(&state
->tmp_creds
,
1940 &state
->samr_password
);
1942 subreq
= dcerpc_netr_ServerPasswordSet_send(state
, state
->ev
,
1943 state
->binding_handle
,
1944 state
->srv_name_slash
,
1945 state
->tmp_creds
.account_name
,
1946 state
->tmp_creds
.secure_channel_type
,
1947 state
->tmp_creds
.computer_name
,
1950 &state
->samr_password
);
1951 if (tevent_req_nomem(subreq
, req
)) {
1952 status
= NT_STATUS_NO_MEMORY
;
1953 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1958 tevent_req_set_callback(subreq
,
1959 netlogon_creds_cli_ServerPasswordSet_done
,
1963 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
)
1965 struct tevent_req
*req
=
1966 tevent_req_callback_data(subreq
,
1968 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1969 tevent_req_data(req
,
1970 struct netlogon_creds_cli_ServerPasswordSet_state
);
1975 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1976 status
= dcerpc_netr_ServerPasswordSet2_recv(subreq
, state
,
1978 TALLOC_FREE(subreq
);
1979 if (tevent_req_nterror(req
, status
)) {
1980 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1984 status
= dcerpc_netr_ServerPasswordSet_recv(subreq
, state
,
1986 TALLOC_FREE(subreq
);
1987 if (tevent_req_nterror(req
, status
)) {
1988 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1993 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1994 &state
->rep_auth
.cred
);
1996 status
= NT_STATUS_ACCESS_DENIED
;
1997 tevent_req_nterror(req
, status
);
1998 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2002 if (tevent_req_nterror(req
, result
)) {
2003 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, result
);
2007 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
2008 state
->old_timeout
);
2010 *state
->creds
= state
->tmp_creds
;
2011 status
= netlogon_creds_cli_store(state
->context
,
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 char *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
);
2227 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
);
2229 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
)
2231 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2232 tevent_req_data(req
,
2233 struct netlogon_creds_cli_LogonSamLogon_state
);
2234 struct tevent_req
*subreq
;
2236 enum dcerpc_AuthType auth_type
;
2237 enum dcerpc_AuthLevel auth_level
;
2239 TALLOC_FREE(state
->ro_creds
);
2240 TALLOC_FREE(state
->logon
);
2241 ZERO_STRUCTP(state
->validation
);
2243 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2244 &auth_type
, &auth_level
);
2246 state
->try_logon_ex
= state
->context
->server
.try_logon_ex
;
2247 state
->try_validation6
= state
->context
->server
.try_validation6
;
2249 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
2250 state
->try_logon_ex
= false;
2253 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
2254 state
->try_validation6
= false;
2257 if (state
->try_logon_ex
) {
2258 if (state
->try_validation6
) {
2259 state
->validation_level
= 6;
2261 state
->validation_level
= 3;
2262 state
->user_encrypt
= true;
2265 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2267 state
->const_logon
);
2268 if (tevent_req_nomem(state
->logon
, req
)) {
2269 status
= NT_STATUS_NO_MEMORY
;
2270 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2274 if (state
->user_encrypt
) {
2275 status
= netlogon_creds_cli_get(state
->context
,
2278 if (!NT_STATUS_IS_OK(status
)) {
2279 status
= NT_STATUS_ACCESS_DENIED
;
2280 tevent_req_nterror(req
, status
);
2281 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2285 netlogon_creds_encrypt_samlogon_logon(state
->ro_creds
,
2290 subreq
= dcerpc_netr_LogonSamLogonEx_send(state
, state
->ev
,
2291 state
->binding_handle
,
2292 state
->srv_name_slash
,
2293 state
->context
->client
.computer
,
2296 state
->validation_level
,
2298 &state
->authoritative
,
2300 if (tevent_req_nomem(subreq
, req
)) {
2301 status
= NT_STATUS_NO_MEMORY
;
2302 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2305 tevent_req_set_callback(subreq
,
2306 netlogon_creds_cli_LogonSamLogon_done
,
2311 if (state
->lk_creds
== NULL
) {
2312 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2314 if (tevent_req_nomem(subreq
, req
)) {
2315 status
= NT_STATUS_NO_MEMORY
;
2316 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2319 tevent_req_set_callback(subreq
,
2320 netlogon_creds_cli_LogonSamLogon_done
,
2325 state
->tmp_creds
= *state
->lk_creds
;
2326 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2328 ZERO_STRUCT(state
->rep_auth
);
2330 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2332 state
->const_logon
);
2333 if (tevent_req_nomem(state
->logon
, req
)) {
2334 status
= NT_STATUS_NO_MEMORY
;
2335 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2339 netlogon_creds_encrypt_samlogon_logon(&state
->tmp_creds
,
2343 state
->validation_level
= 3;
2345 if (state
->context
->server
.try_logon_with
) {
2346 subreq
= dcerpc_netr_LogonSamLogonWithFlags_send(state
, state
->ev
,
2347 state
->binding_handle
,
2348 state
->srv_name_slash
,
2349 state
->context
->client
.computer
,
2354 state
->validation_level
,
2356 &state
->authoritative
,
2358 if (tevent_req_nomem(subreq
, req
)) {
2359 status
= NT_STATUS_NO_MEMORY
;
2360 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2366 subreq
= dcerpc_netr_LogonSamLogon_send(state
, state
->ev
,
2367 state
->binding_handle
,
2368 state
->srv_name_slash
,
2369 state
->context
->client
.computer
,
2374 state
->validation_level
,
2376 &state
->authoritative
);
2377 if (tevent_req_nomem(subreq
, req
)) {
2378 status
= NT_STATUS_NO_MEMORY
;
2379 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2384 tevent_req_set_callback(subreq
,
2385 netlogon_creds_cli_LogonSamLogon_done
,
2389 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
)
2391 struct tevent_req
*req
=
2392 tevent_req_callback_data(subreq
,
2394 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2395 tevent_req_data(req
,
2396 struct netlogon_creds_cli_LogonSamLogon_state
);
2401 if (state
->try_logon_ex
) {
2402 status
= dcerpc_netr_LogonSamLogonEx_recv(subreq
,
2405 TALLOC_FREE(subreq
);
2406 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2407 state
->context
->server
.try_validation6
= false;
2408 state
->context
->server
.try_logon_ex
= false;
2409 netlogon_creds_cli_LogonSamLogon_start(req
);
2412 if (tevent_req_nterror(req
, status
)) {
2413 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2417 if ((state
->validation_level
== 6) &&
2418 (NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_INFO_CLASS
) ||
2419 NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_PARAMETER
) ||
2420 NT_STATUS_EQUAL(result
, NT_STATUS_BUFFER_TOO_SMALL
)))
2422 state
->context
->server
.try_validation6
= false;
2423 netlogon_creds_cli_LogonSamLogon_start(req
);
2427 if (tevent_req_nterror(req
, result
)) {
2428 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2432 if (state
->ro_creds
== NULL
) {
2433 tevent_req_done(req
);
2437 ok
= netlogon_creds_cli_validate(state
->context
, state
->ro_creds
);
2440 * We got a race, lets retry with on authenticator
2443 * netlogon_creds_cli_LogonSamLogon_start()
2444 * will TALLOC_FREE(state->ro_creds);
2446 state
->try_logon_ex
= false;
2447 netlogon_creds_cli_LogonSamLogon_start(req
);
2451 netlogon_creds_decrypt_samlogon_validation(state
->ro_creds
,
2452 state
->validation_level
,
2455 tevent_req_done(req
);
2459 if (state
->lk_creds
== NULL
) {
2460 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2462 TALLOC_FREE(subreq
);
2463 if (tevent_req_nterror(req
, status
)) {
2464 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2468 netlogon_creds_cli_LogonSamLogon_start(req
);
2472 if (state
->context
->server
.try_logon_with
) {
2473 status
= dcerpc_netr_LogonSamLogonWithFlags_recv(subreq
,
2476 TALLOC_FREE(subreq
);
2477 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2478 state
->context
->server
.try_logon_with
= false;
2479 netlogon_creds_cli_LogonSamLogon_start(req
);
2482 if (tevent_req_nterror(req
, status
)) {
2483 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2487 status
= dcerpc_netr_LogonSamLogon_recv(subreq
,
2490 TALLOC_FREE(subreq
);
2491 if (tevent_req_nterror(req
, status
)) {
2492 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2497 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2498 &state
->rep_auth
.cred
);
2500 status
= NT_STATUS_ACCESS_DENIED
;
2501 tevent_req_nterror(req
, status
);
2502 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2506 *state
->lk_creds
= state
->tmp_creds
;
2507 status
= netlogon_creds_cli_store(state
->context
,
2509 if (tevent_req_nterror(req
, status
)) {
2510 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2514 if (tevent_req_nterror(req
, result
)) {
2515 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2519 netlogon_creds_decrypt_samlogon_validation(&state
->tmp_creds
,
2520 state
->validation_level
,
2523 tevent_req_done(req
);
2526 NTSTATUS
netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req
*req
,
2527 TALLOC_CTX
*mem_ctx
,
2528 uint16_t *validation_level
,
2529 union netr_Validation
**validation
,
2530 uint8_t *authoritative
,
2533 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2534 tevent_req_data(req
,
2535 struct netlogon_creds_cli_LogonSamLogon_state
);
2538 /* authoritative is also returned on error */
2539 *authoritative
= state
->authoritative
;
2541 if (tevent_req_is_nterror(req
, &status
)) {
2542 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2543 tevent_req_received(req
);
2547 *validation_level
= state
->validation_level
;
2548 *validation
= talloc_move(mem_ctx
, &state
->validation
);
2549 *flags
= state
->flags
;
2551 tevent_req_received(req
);
2552 return NT_STATUS_OK
;
2555 NTSTATUS
netlogon_creds_cli_LogonSamLogon(
2556 struct netlogon_creds_cli_context
*context
,
2557 struct dcerpc_binding_handle
*b
,
2558 enum netr_LogonInfoClass logon_level
,
2559 const union netr_LogonLevel
*logon
,
2560 TALLOC_CTX
*mem_ctx
,
2561 uint16_t *validation_level
,
2562 union netr_Validation
**validation
,
2563 uint8_t *authoritative
,
2566 TALLOC_CTX
*frame
= talloc_stackframe();
2567 struct tevent_context
*ev
;
2568 struct tevent_req
*req
;
2569 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2571 ev
= samba_tevent_context_init(frame
);
2575 req
= netlogon_creds_cli_LogonSamLogon_send(frame
, ev
, context
, b
,
2581 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2584 status
= netlogon_creds_cli_LogonSamLogon_recv(req
, mem_ctx
,
2594 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
{
2595 struct tevent_context
*ev
;
2596 struct netlogon_creds_cli_context
*context
;
2597 struct dcerpc_binding_handle
*binding_handle
;
2599 char *srv_name_slash
;
2600 enum dcerpc_AuthType auth_type
;
2601 enum dcerpc_AuthLevel auth_level
;
2603 const char *site_name
;
2605 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
;
2607 struct netlogon_creds_CredentialState
*creds
;
2608 struct netlogon_creds_CredentialState tmp_creds
;
2609 struct netr_Authenticator req_auth
;
2610 struct netr_Authenticator rep_auth
;
2613 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2615 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
);
2617 struct tevent_req
*netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(TALLOC_CTX
*mem_ctx
,
2618 struct tevent_context
*ev
,
2619 struct netlogon_creds_cli_context
*context
,
2620 struct dcerpc_binding_handle
*b
,
2621 const char *site_name
,
2623 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2625 struct tevent_req
*req
;
2626 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
;
2627 struct tevent_req
*subreq
;
2629 req
= tevent_req_create(mem_ctx
, &state
,
2630 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2636 state
->context
= context
;
2637 state
->binding_handle
= b
;
2639 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2640 context
->server
.computer
);
2641 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2642 return tevent_req_post(req
, ev
);
2645 state
->site_name
= site_name
;
2646 state
->dns_ttl
= dns_ttl
;
2647 state
->dns_names
= dns_names
;
2649 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2651 &state
->auth_level
);
2653 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2655 if (tevent_req_nomem(subreq
, req
)) {
2656 return tevent_req_post(req
, ev
);
2659 tevent_req_set_callback(subreq
,
2660 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked
,
2666 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2669 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2670 tevent_req_data(req
,
2671 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2673 if (state
->creds
== NULL
) {
2677 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2678 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2679 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2680 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2681 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2682 TALLOC_FREE(state
->creds
);
2686 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
2689 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
);
2691 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
)
2693 struct tevent_req
*req
=
2694 tevent_req_callback_data(subreq
,
2696 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2697 tevent_req_data(req
,
2698 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2701 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2703 TALLOC_FREE(subreq
);
2704 if (tevent_req_nterror(req
, status
)) {
2708 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
2709 switch (state
->auth_level
) {
2710 case DCERPC_AUTH_LEVEL_INTEGRITY
:
2711 case DCERPC_AUTH_LEVEL_PRIVACY
:
2714 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2718 uint32_t tmp
= state
->creds
->negotiate_flags
;
2720 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
2722 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
2723 * it should be used, which means
2724 * we had a chance to verify no downgrade
2727 * This relies on netlogon_creds_cli_check*
2728 * being called before, as first request after
2731 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2737 * we defer all callbacks in order to cleanup
2738 * the database record.
2740 tevent_req_defer_callback(req
, state
->ev
);
2742 state
->tmp_creds
= *state
->creds
;
2743 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2745 ZERO_STRUCT(state
->rep_auth
);
2747 subreq
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_send(state
, state
->ev
,
2748 state
->binding_handle
,
2749 state
->srv_name_slash
,
2750 state
->tmp_creds
.computer_name
,
2756 if (tevent_req_nomem(subreq
, req
)) {
2757 status
= NT_STATUS_NO_MEMORY
;
2758 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2762 tevent_req_set_callback(subreq
,
2763 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done
,
2767 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
)
2769 struct tevent_req
*req
=
2770 tevent_req_callback_data(subreq
,
2772 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2773 tevent_req_data(req
,
2774 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2780 * We use state->dns_names as the memory context, as this is
2781 * the only in/out variable and it has been overwritten by the
2782 * out parameter from the server.
2784 * We need to preserve the return value until the caller can use it.
2786 status
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_recv(subreq
, state
->dns_names
,
2788 TALLOC_FREE(subreq
);
2789 if (tevent_req_nterror(req
, status
)) {
2790 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2794 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2795 &state
->rep_auth
.cred
);
2797 status
= NT_STATUS_ACCESS_DENIED
;
2798 tevent_req_nterror(req
, status
);
2799 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2803 if (tevent_req_nterror(req
, result
)) {
2804 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, result
);
2808 *state
->creds
= state
->tmp_creds
;
2809 status
= netlogon_creds_cli_store(state
->context
,
2811 if (tevent_req_nterror(req
, status
)) {
2812 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2816 tevent_req_done(req
);
2819 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(struct tevent_req
*req
)
2823 if (tevent_req_is_nterror(req
, &status
)) {
2824 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2825 tevent_req_received(req
);
2829 tevent_req_received(req
);
2830 return NT_STATUS_OK
;
2833 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(
2834 struct netlogon_creds_cli_context
*context
,
2835 struct dcerpc_binding_handle
*b
,
2836 const char *site_name
,
2838 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2840 TALLOC_CTX
*frame
= talloc_stackframe();
2841 struct tevent_context
*ev
;
2842 struct tevent_req
*req
;
2843 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2845 ev
= samba_tevent_context_init(frame
);
2849 req
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(frame
, ev
, context
, b
,
2856 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2859 status
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(req
);
2865 struct netlogon_creds_cli_ServerGetTrustInfo_state
{
2866 struct tevent_context
*ev
;
2867 struct netlogon_creds_cli_context
*context
;
2868 struct dcerpc_binding_handle
*binding_handle
;
2870 char *srv_name_slash
;
2871 enum dcerpc_AuthType auth_type
;
2872 enum dcerpc_AuthLevel auth_level
;
2874 struct samr_Password new_owf_password
;
2875 struct samr_Password old_owf_password
;
2876 struct netr_TrustInfo
*trust_info
;
2878 struct netlogon_creds_CredentialState
*creds
;
2879 struct netlogon_creds_CredentialState tmp_creds
;
2880 struct netr_Authenticator req_auth
;
2881 struct netr_Authenticator rep_auth
;
2884 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
2886 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
);
2888 struct tevent_req
*netlogon_creds_cli_ServerGetTrustInfo_send(TALLOC_CTX
*mem_ctx
,
2889 struct tevent_context
*ev
,
2890 struct netlogon_creds_cli_context
*context
,
2891 struct dcerpc_binding_handle
*b
)
2893 struct tevent_req
*req
;
2894 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
;
2895 struct tevent_req
*subreq
;
2897 req
= tevent_req_create(mem_ctx
, &state
,
2898 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2904 state
->context
= context
;
2905 state
->binding_handle
= b
;
2907 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2908 context
->server
.computer
);
2909 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2910 return tevent_req_post(req
, ev
);
2913 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2915 &state
->auth_level
);
2917 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2919 if (tevent_req_nomem(subreq
, req
)) {
2920 return tevent_req_post(req
, ev
);
2923 tevent_req_set_callback(subreq
,
2924 netlogon_creds_cli_ServerGetTrustInfo_locked
,
2930 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
2933 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2934 tevent_req_data(req
,
2935 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2937 if (state
->creds
== NULL
) {
2941 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2942 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2943 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2944 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2945 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2946 TALLOC_FREE(state
->creds
);
2950 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
2953 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
);
2955 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
)
2957 struct tevent_req
*req
=
2958 tevent_req_callback_data(subreq
,
2960 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2961 tevent_req_data(req
,
2962 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2965 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2967 TALLOC_FREE(subreq
);
2968 if (tevent_req_nterror(req
, status
)) {
2972 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
2973 switch (state
->auth_level
) {
2974 case DCERPC_AUTH_LEVEL_PRIVACY
:
2977 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2981 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2986 * we defer all callbacks in order to cleanup
2987 * the database record.
2989 tevent_req_defer_callback(req
, state
->ev
);
2991 state
->tmp_creds
= *state
->creds
;
2992 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2994 ZERO_STRUCT(state
->rep_auth
);
2996 subreq
= dcerpc_netr_ServerGetTrustInfo_send(state
, state
->ev
,
2997 state
->binding_handle
,
2998 state
->srv_name_slash
,
2999 state
->tmp_creds
.account_name
,
3000 state
->tmp_creds
.secure_channel_type
,
3001 state
->tmp_creds
.computer_name
,
3004 &state
->new_owf_password
,
3005 &state
->old_owf_password
,
3006 &state
->trust_info
);
3007 if (tevent_req_nomem(subreq
, req
)) {
3008 status
= NT_STATUS_NO_MEMORY
;
3009 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3013 tevent_req_set_callback(subreq
,
3014 netlogon_creds_cli_ServerGetTrustInfo_done
,
3018 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
)
3020 struct tevent_req
*req
=
3021 tevent_req_callback_data(subreq
,
3023 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3024 tevent_req_data(req
,
3025 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3028 const struct samr_Password zero
= {};
3033 * We use state->dns_names as the memory context, as this is
3034 * the only in/out variable and it has been overwritten by the
3035 * out parameter from the server.
3037 * We need to preserve the return value until the caller can use it.
3039 status
= dcerpc_netr_ServerGetTrustInfo_recv(subreq
, state
, &result
);
3040 TALLOC_FREE(subreq
);
3041 if (tevent_req_nterror(req
, status
)) {
3042 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3046 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3047 &state
->rep_auth
.cred
);
3049 status
= NT_STATUS_ACCESS_DENIED
;
3050 tevent_req_nterror(req
, status
);
3051 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3055 if (tevent_req_nterror(req
, result
)) {
3056 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, result
);
3060 cmp
= memcmp(state
->new_owf_password
.hash
,
3061 zero
.hash
, sizeof(zero
.hash
));
3063 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3064 &state
->new_owf_password
);
3066 cmp
= memcmp(state
->old_owf_password
.hash
,
3067 zero
.hash
, sizeof(zero
.hash
));
3069 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3070 &state
->old_owf_password
);
3073 *state
->creds
= state
->tmp_creds
;
3074 status
= netlogon_creds_cli_store(state
->context
,
3076 if (tevent_req_nterror(req
, status
)) {
3077 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3081 tevent_req_done(req
);
3084 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo_recv(struct tevent_req
*req
,
3085 TALLOC_CTX
*mem_ctx
,
3086 struct samr_Password
*new_owf_password
,
3087 struct samr_Password
*old_owf_password
,
3088 struct netr_TrustInfo
**trust_info
)
3090 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3091 tevent_req_data(req
,
3092 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3095 if (tevent_req_is_nterror(req
, &status
)) {
3096 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3097 tevent_req_received(req
);
3101 if (new_owf_password
!= NULL
) {
3102 *new_owf_password
= state
->new_owf_password
;
3104 if (old_owf_password
!= NULL
) {
3105 *old_owf_password
= state
->old_owf_password
;
3107 if (trust_info
!= NULL
) {
3108 *trust_info
= talloc_move(mem_ctx
, &state
->trust_info
);
3111 tevent_req_received(req
);
3112 return NT_STATUS_OK
;
3115 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo(
3116 struct netlogon_creds_cli_context
*context
,
3117 struct dcerpc_binding_handle
*b
,
3118 TALLOC_CTX
*mem_ctx
,
3119 struct samr_Password
*new_owf_password
,
3120 struct samr_Password
*old_owf_password
,
3121 struct netr_TrustInfo
**trust_info
)
3123 TALLOC_CTX
*frame
= talloc_stackframe();
3124 struct tevent_context
*ev
;
3125 struct tevent_req
*req
;
3126 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3128 ev
= samba_tevent_context_init(frame
);
3132 req
= netlogon_creds_cli_ServerGetTrustInfo_send(frame
, ev
, context
, b
);
3136 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3139 status
= netlogon_creds_cli_ServerGetTrustInfo_recv(req
,
3149 struct netlogon_creds_cli_GetForestTrustInformation_state
{
3150 struct tevent_context
*ev
;
3151 struct netlogon_creds_cli_context
*context
;
3152 struct dcerpc_binding_handle
*binding_handle
;
3154 char *srv_name_slash
;
3155 enum dcerpc_AuthType auth_type
;
3156 enum dcerpc_AuthLevel auth_level
;
3159 struct lsa_ForestTrustInformation
*forest_trust_info
;
3161 struct netlogon_creds_CredentialState
*creds
;
3162 struct netlogon_creds_CredentialState tmp_creds
;
3163 struct netr_Authenticator req_auth
;
3164 struct netr_Authenticator rep_auth
;
3167 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3169 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
);
3171 struct tevent_req
*netlogon_creds_cli_GetForestTrustInformation_send(TALLOC_CTX
*mem_ctx
,
3172 struct tevent_context
*ev
,
3173 struct netlogon_creds_cli_context
*context
,
3174 struct dcerpc_binding_handle
*b
)
3176 struct tevent_req
*req
;
3177 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
;
3178 struct tevent_req
*subreq
;
3180 req
= tevent_req_create(mem_ctx
, &state
,
3181 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3187 state
->context
= context
;
3188 state
->binding_handle
= b
;
3190 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3191 context
->server
.computer
);
3192 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3193 return tevent_req_post(req
, ev
);
3198 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3200 &state
->auth_level
);
3202 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3204 if (tevent_req_nomem(subreq
, req
)) {
3205 return tevent_req_post(req
, ev
);
3208 tevent_req_set_callback(subreq
,
3209 netlogon_creds_cli_GetForestTrustInformation_locked
,
3215 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3218 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3219 tevent_req_data(req
,
3220 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3222 if (state
->creds
== NULL
) {
3226 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3227 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3228 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3229 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3230 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3231 TALLOC_FREE(state
->creds
);
3235 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
3238 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
);
3240 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
)
3242 struct tevent_req
*req
=
3243 tevent_req_callback_data(subreq
,
3245 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3246 tevent_req_data(req
,
3247 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3250 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3252 TALLOC_FREE(subreq
);
3253 if (tevent_req_nterror(req
, status
)) {
3257 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3258 switch (state
->auth_level
) {
3259 case DCERPC_AUTH_LEVEL_INTEGRITY
:
3260 case DCERPC_AUTH_LEVEL_PRIVACY
:
3263 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3267 uint32_t tmp
= state
->creds
->negotiate_flags
;
3269 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
3271 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3272 * it should be used, which means
3273 * we had a chance to verify no downgrade
3276 * This relies on netlogon_creds_cli_check*
3277 * being called before, as first request after
3280 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3286 * we defer all callbacks in order to cleanup
3287 * the database record.
3289 tevent_req_defer_callback(req
, state
->ev
);
3291 state
->tmp_creds
= *state
->creds
;
3292 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3294 ZERO_STRUCT(state
->rep_auth
);
3296 subreq
= dcerpc_netr_GetForestTrustInformation_send(state
, state
->ev
,
3297 state
->binding_handle
,
3298 state
->srv_name_slash
,
3299 state
->tmp_creds
.computer_name
,
3303 &state
->forest_trust_info
);
3304 if (tevent_req_nomem(subreq
, req
)) {
3305 status
= NT_STATUS_NO_MEMORY
;
3306 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3310 tevent_req_set_callback(subreq
,
3311 netlogon_creds_cli_GetForestTrustInformation_done
,
3315 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
)
3317 struct tevent_req
*req
=
3318 tevent_req_callback_data(subreq
,
3320 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3321 tevent_req_data(req
,
3322 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3328 * We use state->dns_names as the memory context, as this is
3329 * the only in/out variable and it has been overwritten by the
3330 * out parameter from the server.
3332 * We need to preserve the return value until the caller can use it.
3334 status
= dcerpc_netr_GetForestTrustInformation_recv(subreq
, state
, &result
);
3335 TALLOC_FREE(subreq
);
3336 if (tevent_req_nterror(req
, status
)) {
3337 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3341 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3342 &state
->rep_auth
.cred
);
3344 status
= NT_STATUS_ACCESS_DENIED
;
3345 tevent_req_nterror(req
, status
);
3346 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3350 if (tevent_req_nterror(req
, result
)) {
3351 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, result
);
3355 *state
->creds
= state
->tmp_creds
;
3356 status
= netlogon_creds_cli_store(state
->context
,
3358 if (tevent_req_nterror(req
, status
)) {
3359 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3363 tevent_req_done(req
);
3366 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation_recv(struct tevent_req
*req
,
3367 TALLOC_CTX
*mem_ctx
,
3368 struct lsa_ForestTrustInformation
**forest_trust_info
)
3370 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3371 tevent_req_data(req
,
3372 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3375 if (tevent_req_is_nterror(req
, &status
)) {
3376 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3377 tevent_req_received(req
);
3381 *forest_trust_info
= talloc_move(mem_ctx
, &state
->forest_trust_info
);
3383 tevent_req_received(req
);
3384 return NT_STATUS_OK
;
3387 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation(
3388 struct netlogon_creds_cli_context
*context
,
3389 struct dcerpc_binding_handle
*b
,
3390 TALLOC_CTX
*mem_ctx
,
3391 struct lsa_ForestTrustInformation
**forest_trust_info
)
3393 TALLOC_CTX
*frame
= talloc_stackframe();
3394 struct tevent_context
*ev
;
3395 struct tevent_req
*req
;
3396 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3398 ev
= samba_tevent_context_init(frame
);
3402 req
= netlogon_creds_cli_GetForestTrustInformation_send(frame
, ev
, context
, b
);
3406 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3409 status
= netlogon_creds_cli_GetForestTrustInformation_recv(req
,