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 enum dcerpc_AuthLevel
netlogon_creds_cli_auth_level(
488 struct netlogon_creds_cli_context
*context
)
490 return context
->client
.auth_level
;
493 struct netlogon_creds_cli_fetch_state
{
495 struct netlogon_creds_CredentialState
*creds
;
496 uint32_t required_flags
;
500 static void netlogon_creds_cli_fetch_parser(TDB_DATA key
, TDB_DATA data
,
503 struct netlogon_creds_cli_fetch_state
*state
=
504 (struct netlogon_creds_cli_fetch_state
*)private_data
;
505 enum ndr_err_code ndr_err
;
509 state
->creds
= talloc_zero(state
->mem_ctx
,
510 struct netlogon_creds_CredentialState
);
511 if (state
->creds
== NULL
) {
512 state
->status
= NT_STATUS_NO_MEMORY
;
516 blob
.data
= data
.dptr
;
517 blob
.length
= data
.dsize
;
519 ndr_err
= ndr_pull_struct_blob(&blob
, state
->creds
, state
->creds
,
520 (ndr_pull_flags_fn_t
)ndr_pull_netlogon_creds_CredentialState
);
521 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
522 TALLOC_FREE(state
->creds
);
523 state
->status
= ndr_map_error2ntstatus(ndr_err
);
527 tmp_flags
= state
->creds
->negotiate_flags
;
528 tmp_flags
&= state
->required_flags
;
529 if (tmp_flags
!= state
->required_flags
) {
530 TALLOC_FREE(state
->creds
);
531 state
->status
= NT_STATUS_DOWNGRADE_DETECTED
;
535 state
->status
= NT_STATUS_OK
;
538 NTSTATUS
netlogon_creds_cli_get(struct netlogon_creds_cli_context
*context
,
540 struct netlogon_creds_CredentialState
**_creds
)
543 struct netlogon_creds_cli_fetch_state fstate
= {
545 .status
= NT_STATUS_INTERNAL_ERROR
,
546 .required_flags
= context
->client
.required_flags
,
548 static const struct netr_Credential zero_creds
;
552 status
= dbwrap_parse_record(context
->db
.ctx
,
553 context
->db
.key_data
,
554 netlogon_creds_cli_fetch_parser
,
556 if (!NT_STATUS_IS_OK(status
)) {
559 status
= fstate
.status
;
560 if (!NT_STATUS_IS_OK(status
)) {
565 * mark it as invalid for step operations.
567 fstate
.creds
->sequence
= 0;
568 fstate
.creds
->seed
= zero_creds
;
569 fstate
.creds
->client
= zero_creds
;
570 fstate
.creds
->server
= zero_creds
;
572 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
573 *_creds
= fstate
.creds
;
578 * It is really important to try SamLogonEx here,
579 * because multiple processes can talk to the same
580 * domain controller, without using the credential
583 * With a normal SamLogon call, we must keep the
584 * credentials chain updated and intact between all
585 * users of the machine account (which would imply
586 * cross-node communication for every NTLM logon).
588 * The credentials chain is not per NETLOGON pipe
589 * connection, but globally on the server/client pair
590 * by computer name, while the client is free to use
591 * any computer name. We include the cluster node number
592 * in our computer name in order to avoid cross node
593 * coordination of the credential chain.
595 * It's also important to use NetlogonValidationSamInfo4 (6),
596 * because it relies on the rpc transport encryption
597 * and avoids using the global netlogon schannel
598 * session key to en/decrypt secret information
599 * like the user_session_key for network logons.
601 * [MS-APDS] 3.1.5.2 NTLM Network Logon
602 * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and
603 * NETLOGON_NEG_AUTHENTICATED_RPC set together
604 * are the indication that the server supports
605 * NetlogonValidationSamInfo4 (6). And it must only
606 * be used if "SealSecureChannel" is used.
608 * The "SealSecureChannel" AUTH_TYPE_SCHANNEL/AUTH_LEVEL_PRIVACY
609 * check is done in netlogon_creds_cli_LogonSamLogon*().
611 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
612 context
->server
.try_validation6
= true;
613 context
->server
.try_logon_ex
= true;
614 context
->server
.try_logon_with
= true;
616 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
617 context
->server
.try_validation6
= false;
618 context
->server
.try_logon_ex
= false;
620 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
621 context
->server
.try_validation6
= false;
624 *_creds
= fstate
.creds
;
628 bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context
*context
,
629 const struct netlogon_creds_CredentialState
*creds1
)
631 TALLOC_CTX
*frame
= talloc_stackframe();
632 struct netlogon_creds_CredentialState
*creds2
;
636 enum ndr_err_code ndr_err
;
639 status
= netlogon_creds_cli_get(context
, frame
, &creds2
);
640 if (!NT_STATUS_IS_OK(status
)) {
645 ndr_err
= ndr_push_struct_blob(&blob1
, frame
, creds1
,
646 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
647 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
652 ndr_err
= ndr_push_struct_blob(&blob2
, frame
, creds2
,
653 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
654 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
659 if (blob1
.length
!= blob2
.length
) {
664 cmp
= memcmp(blob1
.data
, blob2
.data
, blob1
.length
);
674 NTSTATUS
netlogon_creds_cli_store(struct netlogon_creds_cli_context
*context
,
675 struct netlogon_creds_CredentialState
**_creds
)
677 struct netlogon_creds_CredentialState
*creds
= *_creds
;
679 enum ndr_err_code ndr_err
;
685 if (context
->db
.locked_state
== NULL
) {
687 * this was not the result of netlogon_creds_cli_lock*()
690 return NT_STATUS_INVALID_PAGE_PROTECTION
;
693 if (context
->db
.locked_state
->creds
!= creds
) {
695 * this was not the result of netlogon_creds_cli_lock*()
698 return NT_STATUS_INVALID_PAGE_PROTECTION
;
701 ndr_err
= ndr_push_struct_blob(&blob
, creds
, creds
,
702 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
703 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
705 status
= ndr_map_error2ntstatus(ndr_err
);
709 data
.dptr
= blob
.data
;
710 data
.dsize
= blob
.length
;
712 status
= dbwrap_store(context
->db
.ctx
,
713 context
->db
.key_data
,
716 if (!NT_STATUS_IS_OK(status
)) {
723 NTSTATUS
netlogon_creds_cli_delete(struct netlogon_creds_cli_context
*context
,
724 struct netlogon_creds_CredentialState
**_creds
)
726 struct netlogon_creds_CredentialState
*creds
= *_creds
;
731 if (context
->db
.locked_state
== NULL
) {
733 * this was not the result of netlogon_creds_cli_lock*()
736 return NT_STATUS_INVALID_PAGE_PROTECTION
;
739 if (context
->db
.locked_state
->creds
!= creds
) {
741 * this was not the result of netlogon_creds_cli_lock*()
744 return NT_STATUS_INVALID_PAGE_PROTECTION
;
747 status
= dbwrap_delete(context
->db
.ctx
,
748 context
->db
.key_data
);
750 if (!NT_STATUS_IS_OK(status
)) {
757 struct netlogon_creds_cli_lock_state
{
758 struct netlogon_creds_cli_locked_state
*locked_state
;
759 struct netlogon_creds_CredentialState
*creds
;
762 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
);
763 static void netlogon_creds_cli_lock_fetch(struct tevent_req
*req
);
765 struct tevent_req
*netlogon_creds_cli_lock_send(TALLOC_CTX
*mem_ctx
,
766 struct tevent_context
*ev
,
767 struct netlogon_creds_cli_context
*context
)
769 struct tevent_req
*req
;
770 struct netlogon_creds_cli_lock_state
*state
;
771 struct netlogon_creds_cli_locked_state
*locked_state
;
772 struct tevent_req
*subreq
;
774 req
= tevent_req_create(mem_ctx
, &state
,
775 struct netlogon_creds_cli_lock_state
);
780 if (context
->db
.locked_state
!= NULL
) {
781 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
782 return tevent_req_post(req
, ev
);
785 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
786 if (tevent_req_nomem(locked_state
, req
)) {
787 return tevent_req_post(req
, ev
);
789 talloc_set_destructor(locked_state
,
790 netlogon_creds_cli_locked_state_destructor
);
791 locked_state
->context
= context
;
793 context
->db
.locked_state
= locked_state
;
794 state
->locked_state
= locked_state
;
796 if (context
->db
.g_ctx
== NULL
) {
797 netlogon_creds_cli_lock_fetch(req
);
798 if (!tevent_req_is_in_progress(req
)) {
799 return tevent_req_post(req
, ev
);
805 subreq
= g_lock_lock_send(state
, ev
,
807 context
->db
.key_name
,
809 if (tevent_req_nomem(subreq
, req
)) {
810 return tevent_req_post(req
, ev
);
812 tevent_req_set_callback(subreq
, netlogon_creds_cli_lock_done
, req
);
817 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
)
819 struct tevent_req
*req
=
820 tevent_req_callback_data(subreq
,
822 struct netlogon_creds_cli_lock_state
*state
=
824 struct netlogon_creds_cli_lock_state
);
827 status
= g_lock_lock_recv(subreq
);
829 if (tevent_req_nterror(req
, status
)) {
832 state
->locked_state
->is_glocked
= true;
834 netlogon_creds_cli_lock_fetch(req
);
837 static void netlogon_creds_cli_lock_fetch(struct tevent_req
*req
)
839 struct netlogon_creds_cli_lock_state
*state
=
841 struct netlogon_creds_cli_lock_state
);
842 struct netlogon_creds_cli_context
*context
= state
->locked_state
->context
;
843 struct netlogon_creds_cli_fetch_state fstate
= {
844 .status
= NT_STATUS_INTERNAL_ERROR
,
845 .required_flags
= context
->client
.required_flags
,
849 fstate
.mem_ctx
= state
;
850 status
= dbwrap_parse_record(context
->db
.ctx
,
851 context
->db
.key_data
,
852 netlogon_creds_cli_fetch_parser
,
854 if (tevent_req_nterror(req
, status
)) {
857 status
= fstate
.status
;
858 if (tevent_req_nterror(req
, status
)) {
862 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
863 state
->creds
= fstate
.creds
;
864 tevent_req_done(req
);
868 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
869 context
->server
.try_validation6
= true;
870 context
->server
.try_logon_ex
= true;
871 context
->server
.try_logon_with
= true;
873 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
874 context
->server
.try_validation6
= false;
875 context
->server
.try_logon_ex
= false;
877 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
878 context
->server
.try_validation6
= false;
881 state
->creds
= fstate
.creds
;
882 tevent_req_done(req
);
886 NTSTATUS
netlogon_creds_cli_lock_recv(struct tevent_req
*req
,
888 struct netlogon_creds_CredentialState
**creds
)
890 struct netlogon_creds_cli_lock_state
*state
=
892 struct netlogon_creds_cli_lock_state
);
895 if (tevent_req_is_nterror(req
, &status
)) {
896 tevent_req_received(req
);
900 talloc_steal(state
->creds
, state
->locked_state
);
901 state
->locked_state
->creds
= state
->creds
;
902 *creds
= talloc_move(mem_ctx
, &state
->creds
);
903 tevent_req_received(req
);
907 NTSTATUS
netlogon_creds_cli_lock(struct netlogon_creds_cli_context
*context
,
909 struct netlogon_creds_CredentialState
**creds
)
911 TALLOC_CTX
*frame
= talloc_stackframe();
912 struct tevent_context
*ev
;
913 struct tevent_req
*req
;
914 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
916 ev
= samba_tevent_context_init(frame
);
920 req
= netlogon_creds_cli_lock_send(frame
, ev
, context
);
924 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
927 status
= netlogon_creds_cli_lock_recv(req
, mem_ctx
, creds
);
933 struct netlogon_creds_cli_auth_state
{
934 struct tevent_context
*ev
;
935 struct netlogon_creds_cli_context
*context
;
936 struct dcerpc_binding_handle
*binding_handle
;
937 struct samr_Password current_nt_hash
;
938 struct samr_Password previous_nt_hash
;
939 struct samr_Password used_nt_hash
;
940 char *srv_name_slash
;
941 uint32_t current_flags
;
942 struct netr_Credential client_challenge
;
943 struct netr_Credential server_challenge
;
944 struct netlogon_creds_CredentialState
*creds
;
945 struct netr_Credential client_credential
;
946 struct netr_Credential server_credential
;
951 bool try_previous_nt_hash
;
952 struct netlogon_creds_cli_locked_state
*locked_state
;
955 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
);
956 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
);
958 struct tevent_req
*netlogon_creds_cli_auth_send(TALLOC_CTX
*mem_ctx
,
959 struct tevent_context
*ev
,
960 struct netlogon_creds_cli_context
*context
,
961 struct dcerpc_binding_handle
*b
,
962 struct samr_Password current_nt_hash
,
963 const struct samr_Password
*previous_nt_hash
)
965 struct tevent_req
*req
;
966 struct netlogon_creds_cli_auth_state
*state
;
967 struct netlogon_creds_cli_locked_state
*locked_state
;
970 req
= tevent_req_create(mem_ctx
, &state
,
971 struct netlogon_creds_cli_auth_state
);
977 state
->context
= context
;
978 state
->binding_handle
= b
;
979 state
->current_nt_hash
= current_nt_hash
;
980 if (previous_nt_hash
!= NULL
) {
981 state
->previous_nt_hash
= *previous_nt_hash
;
982 state
->try_previous_nt_hash
= true;
985 if (context
->db
.locked_state
!= NULL
) {
986 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
987 return tevent_req_post(req
, ev
);
990 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
991 if (tevent_req_nomem(locked_state
, req
)) {
992 return tevent_req_post(req
, ev
);
994 talloc_set_destructor(locked_state
,
995 netlogon_creds_cli_locked_state_destructor
);
996 locked_state
->context
= context
;
998 context
->db
.locked_state
= locked_state
;
999 state
->locked_state
= locked_state
;
1001 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1002 context
->server
.computer
);
1003 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1004 return tevent_req_post(req
, ev
);
1007 state
->try_auth3
= true;
1008 state
->try_auth2
= true;
1010 if (context
->client
.required_flags
!= 0) {
1011 state
->require_auth2
= true;
1014 state
->used_nt_hash
= state
->current_nt_hash
;
1015 state
->current_flags
= context
->client
.proposed_flags
;
1017 if (context
->db
.g_ctx
!= NULL
) {
1018 struct tevent_req
*subreq
;
1020 subreq
= g_lock_lock_send(state
, ev
,
1022 context
->db
.key_name
,
1024 if (tevent_req_nomem(subreq
, req
)) {
1025 return tevent_req_post(req
, ev
);
1027 tevent_req_set_callback(subreq
,
1028 netlogon_creds_cli_auth_locked
,
1034 status
= dbwrap_purge(state
->context
->db
.ctx
,
1035 state
->context
->db
.key_data
);
1036 if (tevent_req_nterror(req
, status
)) {
1037 return tevent_req_post(req
, ev
);
1040 netlogon_creds_cli_auth_challenge_start(req
);
1041 if (!tevent_req_is_in_progress(req
)) {
1042 return tevent_req_post(req
, ev
);
1048 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
)
1050 struct tevent_req
*req
=
1051 tevent_req_callback_data(subreq
,
1053 struct netlogon_creds_cli_auth_state
*state
=
1054 tevent_req_data(req
,
1055 struct netlogon_creds_cli_auth_state
);
1058 status
= g_lock_lock_recv(subreq
);
1059 TALLOC_FREE(subreq
);
1060 if (tevent_req_nterror(req
, status
)) {
1063 state
->locked_state
->is_glocked
= true;
1065 status
= dbwrap_purge(state
->context
->db
.ctx
,
1066 state
->context
->db
.key_data
);
1067 if (tevent_req_nterror(req
, status
)) {
1071 netlogon_creds_cli_auth_challenge_start(req
);
1074 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
);
1076 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
)
1078 struct netlogon_creds_cli_auth_state
*state
=
1079 tevent_req_data(req
,
1080 struct netlogon_creds_cli_auth_state
);
1081 struct tevent_req
*subreq
;
1083 TALLOC_FREE(state
->creds
);
1085 generate_random_buffer(state
->client_challenge
.data
,
1086 sizeof(state
->client_challenge
.data
));
1088 subreq
= dcerpc_netr_ServerReqChallenge_send(state
, state
->ev
,
1089 state
->binding_handle
,
1090 state
->srv_name_slash
,
1091 state
->context
->client
.computer
,
1092 &state
->client_challenge
,
1093 &state
->server_challenge
);
1094 if (tevent_req_nomem(subreq
, req
)) {
1097 tevent_req_set_callback(subreq
,
1098 netlogon_creds_cli_auth_challenge_done
,
1102 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
);
1104 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
)
1106 struct tevent_req
*req
=
1107 tevent_req_callback_data(subreq
,
1109 struct netlogon_creds_cli_auth_state
*state
=
1110 tevent_req_data(req
,
1111 struct netlogon_creds_cli_auth_state
);
1115 status
= dcerpc_netr_ServerReqChallenge_recv(subreq
, state
, &result
);
1116 TALLOC_FREE(subreq
);
1117 if (tevent_req_nterror(req
, status
)) {
1120 if (tevent_req_nterror(req
, result
)) {
1124 if (!state
->try_auth3
&& !state
->try_auth2
) {
1125 state
->current_flags
= 0;
1128 /* Calculate the session key and client credentials */
1130 state
->creds
= netlogon_creds_client_init(state
,
1131 state
->context
->client
.account
,
1132 state
->context
->client
.computer
,
1133 state
->context
->client
.type
,
1134 &state
->client_challenge
,
1135 &state
->server_challenge
,
1136 &state
->used_nt_hash
,
1137 &state
->client_credential
,
1138 state
->current_flags
);
1139 if (tevent_req_nomem(state
->creds
, req
)) {
1143 if (state
->try_auth3
) {
1144 subreq
= dcerpc_netr_ServerAuthenticate3_send(state
, state
->ev
,
1145 state
->binding_handle
,
1146 state
->srv_name_slash
,
1147 state
->context
->client
.account
,
1148 state
->context
->client
.type
,
1149 state
->context
->client
.computer
,
1150 &state
->client_credential
,
1151 &state
->server_credential
,
1152 &state
->creds
->negotiate_flags
,
1154 if (tevent_req_nomem(subreq
, req
)) {
1157 } else if (state
->try_auth2
) {
1160 subreq
= dcerpc_netr_ServerAuthenticate2_send(state
, state
->ev
,
1161 state
->binding_handle
,
1162 state
->srv_name_slash
,
1163 state
->context
->client
.account
,
1164 state
->context
->client
.type
,
1165 state
->context
->client
.computer
,
1166 &state
->client_credential
,
1167 &state
->server_credential
,
1168 &state
->creds
->negotiate_flags
);
1169 if (tevent_req_nomem(subreq
, req
)) {
1175 subreq
= dcerpc_netr_ServerAuthenticate_send(state
, state
->ev
,
1176 state
->binding_handle
,
1177 state
->srv_name_slash
,
1178 state
->context
->client
.account
,
1179 state
->context
->client
.type
,
1180 state
->context
->client
.computer
,
1181 &state
->client_credential
,
1182 &state
->server_credential
);
1183 if (tevent_req_nomem(subreq
, req
)) {
1187 tevent_req_set_callback(subreq
,
1188 netlogon_creds_cli_auth_srvauth_done
,
1192 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
)
1194 struct tevent_req
*req
=
1195 tevent_req_callback_data(subreq
,
1197 struct netlogon_creds_cli_auth_state
*state
=
1198 tevent_req_data(req
,
1199 struct netlogon_creds_cli_auth_state
);
1203 enum ndr_err_code ndr_err
;
1208 if (state
->try_auth3
) {
1209 status
= dcerpc_netr_ServerAuthenticate3_recv(subreq
, state
,
1211 TALLOC_FREE(subreq
);
1212 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1213 state
->try_auth3
= false;
1214 netlogon_creds_cli_auth_challenge_start(req
);
1217 if (tevent_req_nterror(req
, status
)) {
1220 } else if (state
->try_auth2
) {
1221 status
= dcerpc_netr_ServerAuthenticate2_recv(subreq
, state
,
1223 TALLOC_FREE(subreq
);
1224 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1225 state
->try_auth2
= false;
1226 if (state
->require_auth2
) {
1227 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1228 tevent_req_nterror(req
, status
);
1231 netlogon_creds_cli_auth_challenge_start(req
);
1234 if (tevent_req_nterror(req
, status
)) {
1238 status
= dcerpc_netr_ServerAuthenticate_recv(subreq
, state
,
1240 TALLOC_FREE(subreq
);
1241 if (tevent_req_nterror(req
, status
)) {
1246 if (!NT_STATUS_IS_OK(result
) &&
1247 !NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
))
1249 tevent_req_nterror(req
, result
);
1253 tmp_flags
= state
->creds
->negotiate_flags
;
1254 tmp_flags
&= state
->context
->client
.required_flags
;
1255 if (tmp_flags
!= state
->context
->client
.required_flags
) {
1256 if (NT_STATUS_IS_OK(result
)) {
1257 tevent_req_nterror(req
, NT_STATUS_DOWNGRADE_DETECTED
);
1260 tevent_req_nterror(req
, result
);
1264 if (NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
)) {
1266 tmp_flags
= state
->context
->client
.proposed_flags
;
1267 if ((state
->current_flags
== tmp_flags
) &&
1268 (state
->creds
->negotiate_flags
!= tmp_flags
))
1271 * lets retry with the negotiated flags
1273 state
->current_flags
= state
->creds
->negotiate_flags
;
1274 netlogon_creds_cli_auth_challenge_start(req
);
1278 if (!state
->try_previous_nt_hash
) {
1280 * we already retried, giving up...
1282 tevent_req_nterror(req
, result
);
1287 * lets retry with the old nt hash.
1289 state
->try_previous_nt_hash
= false;
1290 state
->used_nt_hash
= state
->previous_nt_hash
;
1291 state
->current_flags
= state
->context
->client
.proposed_flags
;
1292 netlogon_creds_cli_auth_challenge_start(req
);
1296 ok
= netlogon_creds_client_check(state
->creds
,
1297 &state
->server_credential
);
1299 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1303 ndr_err
= ndr_push_struct_blob(&blob
, state
, state
->creds
,
1304 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
1305 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1306 status
= ndr_map_error2ntstatus(ndr_err
);
1307 tevent_req_nterror(req
, status
);
1311 data
.dptr
= blob
.data
;
1312 data
.dsize
= blob
.length
;
1314 status
= dbwrap_store(state
->context
->db
.ctx
,
1315 state
->context
->db
.key_data
,
1317 TALLOC_FREE(state
->locked_state
);
1318 if (tevent_req_nterror(req
, status
)) {
1322 tevent_req_done(req
);
1325 NTSTATUS
netlogon_creds_cli_auth_recv(struct tevent_req
*req
)
1329 if (tevent_req_is_nterror(req
, &status
)) {
1330 tevent_req_received(req
);
1334 tevent_req_received(req
);
1335 return NT_STATUS_OK
;
1338 NTSTATUS
netlogon_creds_cli_auth(struct netlogon_creds_cli_context
*context
,
1339 struct dcerpc_binding_handle
*b
,
1340 struct samr_Password current_nt_hash
,
1341 const struct samr_Password
*previous_nt_hash
)
1343 TALLOC_CTX
*frame
= talloc_stackframe();
1344 struct tevent_context
*ev
;
1345 struct tevent_req
*req
;
1346 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1348 ev
= samba_tevent_context_init(frame
);
1352 req
= netlogon_creds_cli_auth_send(frame
, ev
, context
, b
,
1358 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1361 status
= netlogon_creds_cli_auth_recv(req
);
1367 struct netlogon_creds_cli_check_state
{
1368 struct tevent_context
*ev
;
1369 struct netlogon_creds_cli_context
*context
;
1370 struct dcerpc_binding_handle
*binding_handle
;
1372 char *srv_name_slash
;
1374 union netr_Capabilities caps
;
1376 struct netlogon_creds_CredentialState
*creds
;
1377 struct netlogon_creds_CredentialState tmp_creds
;
1378 struct netr_Authenticator req_auth
;
1379 struct netr_Authenticator rep_auth
;
1382 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1384 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
);
1386 struct tevent_req
*netlogon_creds_cli_check_send(TALLOC_CTX
*mem_ctx
,
1387 struct tevent_context
*ev
,
1388 struct netlogon_creds_cli_context
*context
,
1389 struct dcerpc_binding_handle
*b
)
1391 struct tevent_req
*req
;
1392 struct netlogon_creds_cli_check_state
*state
;
1393 struct tevent_req
*subreq
;
1394 enum dcerpc_AuthType auth_type
;
1395 enum dcerpc_AuthLevel auth_level
;
1397 req
= tevent_req_create(mem_ctx
, &state
,
1398 struct netlogon_creds_cli_check_state
);
1404 state
->context
= context
;
1405 state
->binding_handle
= b
;
1407 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1408 context
->server
.computer
);
1409 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1410 return tevent_req_post(req
, ev
);
1413 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1414 &auth_type
, &auth_level
);
1416 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
1417 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1418 return tevent_req_post(req
, ev
);
1421 switch (auth_level
) {
1422 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1423 case DCERPC_AUTH_LEVEL_PRIVACY
:
1426 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1427 return tevent_req_post(req
, ev
);
1430 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1432 if (tevent_req_nomem(subreq
, req
)) {
1433 return tevent_req_post(req
, ev
);
1436 tevent_req_set_callback(subreq
,
1437 netlogon_creds_cli_check_locked
,
1443 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1446 struct netlogon_creds_cli_check_state
*state
=
1447 tevent_req_data(req
,
1448 struct netlogon_creds_cli_check_state
);
1450 if (state
->creds
== NULL
) {
1454 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1455 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1456 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1457 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1458 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1459 TALLOC_FREE(state
->creds
);
1463 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
1466 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
);
1468 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
)
1470 struct tevent_req
*req
=
1471 tevent_req_callback_data(subreq
,
1473 struct netlogon_creds_cli_check_state
*state
=
1474 tevent_req_data(req
,
1475 struct netlogon_creds_cli_check_state
);
1478 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1480 TALLOC_FREE(subreq
);
1481 if (tevent_req_nterror(req
, status
)) {
1486 * we defer all callbacks in order to cleanup
1487 * the database record.
1489 tevent_req_defer_callback(req
, state
->ev
);
1491 state
->tmp_creds
= *state
->creds
;
1492 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1494 ZERO_STRUCT(state
->rep_auth
);
1496 subreq
= dcerpc_netr_LogonGetCapabilities_send(state
, state
->ev
,
1497 state
->binding_handle
,
1498 state
->srv_name_slash
,
1499 state
->context
->client
.computer
,
1504 if (tevent_req_nomem(subreq
, req
)) {
1505 status
= NT_STATUS_NO_MEMORY
;
1506 netlogon_creds_cli_check_cleanup(req
, status
);
1509 tevent_req_set_callback(subreq
,
1510 netlogon_creds_cli_check_caps
,
1514 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
)
1516 struct tevent_req
*req
=
1517 tevent_req_callback_data(subreq
,
1519 struct netlogon_creds_cli_check_state
*state
=
1520 tevent_req_data(req
,
1521 struct netlogon_creds_cli_check_state
);
1526 status
= dcerpc_netr_LogonGetCapabilities_recv(subreq
, state
,
1528 TALLOC_FREE(subreq
);
1529 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1531 * Note that the negotiated flags are already checked
1532 * for our required flags after the ServerAuthenticate3/2 call.
1534 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1536 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1538 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1539 * already, we expect this to work!
1541 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1542 tevent_req_nterror(req
, status
);
1543 netlogon_creds_cli_check_cleanup(req
, status
);
1547 if (negotiated
& NETLOGON_NEG_STRONG_KEYS
) {
1549 * If we have negotiated NETLOGON_NEG_STRONG_KEYS
1550 * we expect this to work at least as far as the
1551 * NOT_SUPPORTED error handled below!
1553 * NT 4.0 and Old Samba servers are not
1554 * allowed without "require strong key = no"
1556 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1557 tevent_req_nterror(req
, status
);
1558 netlogon_creds_cli_check_cleanup(req
, status
);
1563 * If we not require NETLOGON_NEG_SUPPORTS_AES or
1564 * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore
1565 * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
1567 * This is needed against NT 4.0 and old Samba servers.
1569 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
1570 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
1571 * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
1572 * with the next request as the sequence number processing
1575 netlogon_creds_cli_check_cleanup(req
, status
);
1576 tevent_req_done(req
);
1579 if (tevent_req_nterror(req
, status
)) {
1580 netlogon_creds_cli_check_cleanup(req
, status
);
1584 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOT_IMPLEMENTED
)) {
1586 * Note that the negotiated flags are already checked
1587 * for our required flags after the ServerAuthenticate3/2 call.
1589 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1591 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1593 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1594 * already, we expect this to work!
1596 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1597 tevent_req_nterror(req
, status
);
1598 netlogon_creds_cli_check_cleanup(req
, status
);
1603 * This is ok, the server does not support
1604 * NETLOGON_NEG_SUPPORTS_AES.
1606 * netr_LogonGetCapabilities() was
1607 * netr_LogonDummyRoutine1() before
1608 * NETLOGON_NEG_SUPPORTS_AES was invented.
1610 netlogon_creds_cli_check_cleanup(req
, result
);
1611 tevent_req_done(req
);
1615 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1616 &state
->rep_auth
.cred
);
1618 status
= NT_STATUS_ACCESS_DENIED
;
1619 tevent_req_nterror(req
, status
);
1620 netlogon_creds_cli_check_cleanup(req
, status
);
1624 if (tevent_req_nterror(req
, result
)) {
1625 netlogon_creds_cli_check_cleanup(req
, result
);
1629 if (state
->caps
.server_capabilities
!= state
->tmp_creds
.negotiate_flags
) {
1630 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1631 tevent_req_nterror(req
, status
);
1632 netlogon_creds_cli_check_cleanup(req
, status
);
1637 * This is the key check that makes this check secure. If we
1638 * get OK here (rather than NOT_SUPPORTED), then the server
1639 * did support AES. If the server only proposed STRONG_KEYS
1640 * and not AES, then it should have failed with
1641 * NOT_IMPLEMENTED. We always send AES as a client, so the
1642 * server should always have returned it.
1644 if (!(state
->caps
.server_capabilities
& NETLOGON_NEG_SUPPORTS_AES
)) {
1645 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1646 tevent_req_nterror(req
, status
);
1647 netlogon_creds_cli_check_cleanup(req
, status
);
1651 *state
->creds
= state
->tmp_creds
;
1652 status
= netlogon_creds_cli_store(state
->context
,
1654 netlogon_creds_cli_check_cleanup(req
, status
);
1655 if (tevent_req_nterror(req
, status
)) {
1659 tevent_req_done(req
);
1662 NTSTATUS
netlogon_creds_cli_check_recv(struct tevent_req
*req
)
1666 if (tevent_req_is_nterror(req
, &status
)) {
1667 netlogon_creds_cli_check_cleanup(req
, status
);
1668 tevent_req_received(req
);
1672 tevent_req_received(req
);
1673 return NT_STATUS_OK
;
1676 NTSTATUS
netlogon_creds_cli_check(struct netlogon_creds_cli_context
*context
,
1677 struct dcerpc_binding_handle
*b
)
1679 TALLOC_CTX
*frame
= talloc_stackframe();
1680 struct tevent_context
*ev
;
1681 struct tevent_req
*req
;
1682 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1684 ev
= samba_tevent_context_init(frame
);
1688 req
= netlogon_creds_cli_check_send(frame
, ev
, context
, b
);
1692 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1695 status
= netlogon_creds_cli_check_recv(req
);
1701 struct netlogon_creds_cli_ServerPasswordSet_state
{
1702 struct tevent_context
*ev
;
1703 struct netlogon_creds_cli_context
*context
;
1704 struct dcerpc_binding_handle
*binding_handle
;
1705 uint32_t old_timeout
;
1707 char *srv_name_slash
;
1708 enum dcerpc_AuthType auth_type
;
1709 enum dcerpc_AuthLevel auth_level
;
1711 struct samr_CryptPassword samr_crypt_password
;
1712 struct netr_CryptPassword netr_crypt_password
;
1713 struct samr_Password samr_password
;
1715 struct netlogon_creds_CredentialState
*creds
;
1716 struct netlogon_creds_CredentialState tmp_creds
;
1717 struct netr_Authenticator req_auth
;
1718 struct netr_Authenticator rep_auth
;
1721 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1723 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
);
1725 struct tevent_req
*netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX
*mem_ctx
,
1726 struct tevent_context
*ev
,
1727 struct netlogon_creds_cli_context
*context
,
1728 struct dcerpc_binding_handle
*b
,
1729 const char *new_password
,
1730 const uint32_t *new_version
)
1732 struct tevent_req
*req
;
1733 struct netlogon_creds_cli_ServerPasswordSet_state
*state
;
1734 struct tevent_req
*subreq
;
1737 req
= tevent_req_create(mem_ctx
, &state
,
1738 struct netlogon_creds_cli_ServerPasswordSet_state
);
1744 state
->context
= context
;
1745 state
->binding_handle
= b
;
1748 * netr_ServerPasswordSet
1750 E_md4hash(new_password
, state
->samr_password
.hash
);
1753 * netr_ServerPasswordSet2
1755 ok
= encode_pw_buffer(state
->samr_crypt_password
.data
,
1756 new_password
, STR_UNICODE
);
1758 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1759 return tevent_req_post(req
, ev
);
1762 if (new_version
!= NULL
) {
1763 struct NL_PASSWORD_VERSION version
;
1764 uint32_t len
= IVAL(state
->samr_crypt_password
.data
, 512);
1765 uint32_t ofs
= 512 - len
;
1769 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1770 return tevent_req_post(req
, ev
);
1774 version
.ReservedField
= 0;
1775 version
.PasswordVersionNumber
= *new_version
;
1776 version
.PasswordVersionPresent
=
1777 NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT
;
1779 p
= state
->samr_crypt_password
.data
+ ofs
;
1780 SIVAL(p
, 0, version
.ReservedField
);
1781 SIVAL(p
, 4, version
.PasswordVersionNumber
);
1782 SIVAL(p
, 8, version
.PasswordVersionPresent
);
1785 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1786 context
->server
.computer
);
1787 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1788 return tevent_req_post(req
, ev
);
1791 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1793 &state
->auth_level
);
1795 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1797 if (tevent_req_nomem(subreq
, req
)) {
1798 return tevent_req_post(req
, ev
);
1801 tevent_req_set_callback(subreq
,
1802 netlogon_creds_cli_ServerPasswordSet_locked
,
1808 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1811 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1812 tevent_req_data(req
,
1813 struct netlogon_creds_cli_ServerPasswordSet_state
);
1815 if (state
->creds
== NULL
) {
1819 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
1820 state
->old_timeout
);
1822 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1823 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1824 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1825 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1826 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1827 TALLOC_FREE(state
->creds
);
1831 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
1834 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
);
1836 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
)
1838 struct tevent_req
*req
=
1839 tevent_req_callback_data(subreq
,
1841 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1842 tevent_req_data(req
,
1843 struct netlogon_creds_cli_ServerPasswordSet_state
);
1846 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1848 TALLOC_FREE(subreq
);
1849 if (tevent_req_nterror(req
, status
)) {
1853 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
1854 switch (state
->auth_level
) {
1855 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1856 case DCERPC_AUTH_LEVEL_PRIVACY
:
1859 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1863 uint32_t tmp
= state
->creds
->negotiate_flags
;
1865 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
1867 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
1868 * it should be used, which means
1869 * we had a chance to verify no downgrade
1872 * This relies on netlogon_creds_cli_check*
1873 * being called before, as first request after
1876 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1881 state
->old_timeout
= dcerpc_binding_handle_set_timeout(
1882 state
->binding_handle
, 600000);
1885 * we defer all callbacks in order to cleanup
1886 * the database record.
1888 tevent_req_defer_callback(req
, state
->ev
);
1890 state
->tmp_creds
= *state
->creds
;
1891 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1893 ZERO_STRUCT(state
->rep_auth
);
1895 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1897 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1898 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
1899 state
->samr_crypt_password
.data
,
1902 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
1903 state
->samr_crypt_password
.data
,
1907 memcpy(state
->netr_crypt_password
.data
,
1908 state
->samr_crypt_password
.data
, 512);
1909 state
->netr_crypt_password
.length
=
1910 IVAL(state
->samr_crypt_password
.data
, 512);
1912 subreq
= dcerpc_netr_ServerPasswordSet2_send(state
, state
->ev
,
1913 state
->binding_handle
,
1914 state
->srv_name_slash
,
1915 state
->tmp_creds
.account_name
,
1916 state
->tmp_creds
.secure_channel_type
,
1917 state
->tmp_creds
.computer_name
,
1920 &state
->netr_crypt_password
);
1921 if (tevent_req_nomem(subreq
, req
)) {
1922 status
= NT_STATUS_NO_MEMORY
;
1923 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1927 netlogon_creds_des_encrypt(&state
->tmp_creds
,
1928 &state
->samr_password
);
1930 subreq
= dcerpc_netr_ServerPasswordSet_send(state
, state
->ev
,
1931 state
->binding_handle
,
1932 state
->srv_name_slash
,
1933 state
->tmp_creds
.account_name
,
1934 state
->tmp_creds
.secure_channel_type
,
1935 state
->tmp_creds
.computer_name
,
1938 &state
->samr_password
);
1939 if (tevent_req_nomem(subreq
, req
)) {
1940 status
= NT_STATUS_NO_MEMORY
;
1941 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1946 tevent_req_set_callback(subreq
,
1947 netlogon_creds_cli_ServerPasswordSet_done
,
1951 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
)
1953 struct tevent_req
*req
=
1954 tevent_req_callback_data(subreq
,
1956 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1957 tevent_req_data(req
,
1958 struct netlogon_creds_cli_ServerPasswordSet_state
);
1963 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1964 status
= dcerpc_netr_ServerPasswordSet2_recv(subreq
, state
,
1966 TALLOC_FREE(subreq
);
1967 if (tevent_req_nterror(req
, status
)) {
1968 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1972 status
= dcerpc_netr_ServerPasswordSet_recv(subreq
, state
,
1974 TALLOC_FREE(subreq
);
1975 if (tevent_req_nterror(req
, status
)) {
1976 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1981 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1982 &state
->rep_auth
.cred
);
1984 status
= NT_STATUS_ACCESS_DENIED
;
1985 tevent_req_nterror(req
, status
);
1986 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1990 if (tevent_req_nterror(req
, result
)) {
1991 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, result
);
1995 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
1996 state
->old_timeout
);
1998 *state
->creds
= state
->tmp_creds
;
1999 status
= netlogon_creds_cli_store(state
->context
,
2001 if (tevent_req_nterror(req
, status
)) {
2002 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2006 tevent_req_done(req
);
2009 NTSTATUS
netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req
*req
)
2013 if (tevent_req_is_nterror(req
, &status
)) {
2014 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2015 tevent_req_received(req
);
2019 tevent_req_received(req
);
2020 return NT_STATUS_OK
;
2023 NTSTATUS
netlogon_creds_cli_ServerPasswordSet(
2024 struct netlogon_creds_cli_context
*context
,
2025 struct dcerpc_binding_handle
*b
,
2026 const char *new_password
,
2027 const uint32_t *new_version
)
2029 TALLOC_CTX
*frame
= talloc_stackframe();
2030 struct tevent_context
*ev
;
2031 struct tevent_req
*req
;
2032 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2034 ev
= samba_tevent_context_init(frame
);
2038 req
= netlogon_creds_cli_ServerPasswordSet_send(frame
, ev
, context
, b
,
2044 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2047 status
= netlogon_creds_cli_ServerPasswordSet_recv(req
);
2053 struct netlogon_creds_cli_LogonSamLogon_state
{
2054 struct tevent_context
*ev
;
2055 struct netlogon_creds_cli_context
*context
;
2056 struct dcerpc_binding_handle
*binding_handle
;
2058 char *srv_name_slash
;
2060 enum netr_LogonInfoClass logon_level
;
2061 const union netr_LogonLevel
*const_logon
;
2062 union netr_LogonLevel
*logon
;
2065 uint16_t validation_level
;
2066 union netr_Validation
*validation
;
2067 uint8_t authoritative
;
2070 * do we need encryption at the application layer?
2074 bool try_validation6
;
2077 * the read only credentials before we started the operation
2079 struct netlogon_creds_CredentialState
*ro_creds
;
2081 struct netlogon_creds_CredentialState
*lk_creds
;
2083 struct netlogon_creds_CredentialState tmp_creds
;
2084 struct netr_Authenticator req_auth
;
2085 struct netr_Authenticator rep_auth
;
2088 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
);
2089 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2092 struct tevent_req
*netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX
*mem_ctx
,
2093 struct tevent_context
*ev
,
2094 struct netlogon_creds_cli_context
*context
,
2095 struct dcerpc_binding_handle
*b
,
2096 enum netr_LogonInfoClass logon_level
,
2097 const union netr_LogonLevel
*logon
,
2100 struct tevent_req
*req
;
2101 struct netlogon_creds_cli_LogonSamLogon_state
*state
;
2103 req
= tevent_req_create(mem_ctx
, &state
,
2104 struct netlogon_creds_cli_LogonSamLogon_state
);
2110 state
->context
= context
;
2111 state
->binding_handle
= b
;
2113 state
->logon_level
= logon_level
;
2114 state
->const_logon
= logon
;
2115 state
->flags
= flags
;
2117 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2118 context
->server
.computer
);
2119 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2120 return tevent_req_post(req
, ev
);
2123 switch (logon_level
) {
2124 case NetlogonInteractiveInformation
:
2125 case NetlogonInteractiveTransitiveInformation
:
2126 case NetlogonServiceInformation
:
2127 case NetlogonServiceTransitiveInformation
:
2128 case NetlogonGenericInformation
:
2129 state
->user_encrypt
= true;
2132 case NetlogonNetworkInformation
:
2133 case NetlogonNetworkTransitiveInformation
:
2137 state
->validation
= talloc_zero(state
, union netr_Validation
);
2138 if (tevent_req_nomem(state
->validation
, req
)) {
2139 return tevent_req_post(req
, ev
);
2142 netlogon_creds_cli_LogonSamLogon_start(req
);
2143 if (!tevent_req_is_in_progress(req
)) {
2144 return tevent_req_post(req
, ev
);
2148 * we defer all callbacks in order to cleanup
2149 * the database record.
2151 tevent_req_defer_callback(req
, state
->ev
);
2155 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2158 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2159 tevent_req_data(req
,
2160 struct netlogon_creds_cli_LogonSamLogon_state
);
2162 if (state
->lk_creds
== NULL
) {
2166 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2168 * This is a hack to recover from a bug in old
2169 * Samba servers, when LogonSamLogonEx() fails:
2171 * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
2173 * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2175 * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE,
2176 * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR
2177 * If the sign/seal check fails.
2179 * In that case we need to cleanup the netlogon session.
2181 * It's the job of the caller to disconnect the current
2182 * connection, if netlogon_creds_cli_LogonSamLogon()
2183 * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2185 if (!state
->context
->server
.try_logon_with
) {
2186 status
= NT_STATUS_NETWORK_ACCESS_DENIED
;
2190 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2191 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2192 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2193 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2194 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2195 TALLOC_FREE(state
->lk_creds
);
2199 netlogon_creds_cli_delete(state
->context
, &state
->lk_creds
);
2202 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
);
2204 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
)
2206 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2207 tevent_req_data(req
,
2208 struct netlogon_creds_cli_LogonSamLogon_state
);
2209 struct tevent_req
*subreq
;
2211 enum dcerpc_AuthType auth_type
;
2212 enum dcerpc_AuthLevel auth_level
;
2214 TALLOC_FREE(state
->ro_creds
);
2215 TALLOC_FREE(state
->logon
);
2216 ZERO_STRUCTP(state
->validation
);
2218 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2219 &auth_type
, &auth_level
);
2221 state
->try_logon_ex
= state
->context
->server
.try_logon_ex
;
2222 state
->try_validation6
= state
->context
->server
.try_validation6
;
2224 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
2225 state
->try_logon_ex
= false;
2228 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
2229 state
->try_validation6
= false;
2232 if (state
->try_logon_ex
) {
2233 if (state
->try_validation6
) {
2234 state
->validation_level
= 6;
2236 state
->validation_level
= 3;
2237 state
->user_encrypt
= true;
2240 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2242 state
->const_logon
);
2243 if (tevent_req_nomem(state
->logon
, req
)) {
2244 status
= NT_STATUS_NO_MEMORY
;
2245 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2249 if (state
->user_encrypt
) {
2250 status
= netlogon_creds_cli_get(state
->context
,
2253 if (!NT_STATUS_IS_OK(status
)) {
2254 status
= NT_STATUS_ACCESS_DENIED
;
2255 tevent_req_nterror(req
, status
);
2256 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2260 netlogon_creds_encrypt_samlogon_logon(state
->ro_creds
,
2265 subreq
= dcerpc_netr_LogonSamLogonEx_send(state
, state
->ev
,
2266 state
->binding_handle
,
2267 state
->srv_name_slash
,
2268 state
->context
->client
.computer
,
2271 state
->validation_level
,
2273 &state
->authoritative
,
2275 if (tevent_req_nomem(subreq
, req
)) {
2276 status
= NT_STATUS_NO_MEMORY
;
2277 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2280 tevent_req_set_callback(subreq
,
2281 netlogon_creds_cli_LogonSamLogon_done
,
2286 if (state
->lk_creds
== NULL
) {
2287 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2289 if (tevent_req_nomem(subreq
, req
)) {
2290 status
= NT_STATUS_NO_MEMORY
;
2291 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2294 tevent_req_set_callback(subreq
,
2295 netlogon_creds_cli_LogonSamLogon_done
,
2300 state
->tmp_creds
= *state
->lk_creds
;
2301 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2303 ZERO_STRUCT(state
->rep_auth
);
2305 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2307 state
->const_logon
);
2308 if (tevent_req_nomem(state
->logon
, req
)) {
2309 status
= NT_STATUS_NO_MEMORY
;
2310 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2314 netlogon_creds_encrypt_samlogon_logon(state
->ro_creds
,
2318 state
->validation_level
= 3;
2320 if (state
->context
->server
.try_logon_with
) {
2321 subreq
= dcerpc_netr_LogonSamLogonWithFlags_send(state
, state
->ev
,
2322 state
->binding_handle
,
2323 state
->srv_name_slash
,
2324 state
->context
->client
.computer
,
2329 state
->validation_level
,
2331 &state
->authoritative
,
2333 if (tevent_req_nomem(subreq
, req
)) {
2334 status
= NT_STATUS_NO_MEMORY
;
2335 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2341 subreq
= dcerpc_netr_LogonSamLogon_send(state
, state
->ev
,
2342 state
->binding_handle
,
2343 state
->srv_name_slash
,
2344 state
->context
->client
.computer
,
2349 state
->validation_level
,
2351 &state
->authoritative
);
2352 if (tevent_req_nomem(subreq
, req
)) {
2353 status
= NT_STATUS_NO_MEMORY
;
2354 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2359 tevent_req_set_callback(subreq
,
2360 netlogon_creds_cli_LogonSamLogon_done
,
2364 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
)
2366 struct tevent_req
*req
=
2367 tevent_req_callback_data(subreq
,
2369 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2370 tevent_req_data(req
,
2371 struct netlogon_creds_cli_LogonSamLogon_state
);
2376 if (state
->try_logon_ex
) {
2377 status
= dcerpc_netr_LogonSamLogonEx_recv(subreq
,
2380 TALLOC_FREE(subreq
);
2381 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2382 state
->context
->server
.try_validation6
= false;
2383 state
->context
->server
.try_logon_ex
= false;
2384 netlogon_creds_cli_LogonSamLogon_start(req
);
2387 if (tevent_req_nterror(req
, status
)) {
2388 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2392 if ((state
->validation_level
== 6) &&
2393 (NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_INFO_CLASS
) ||
2394 NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_PARAMETER
) ||
2395 NT_STATUS_EQUAL(result
, NT_STATUS_BUFFER_TOO_SMALL
)))
2397 state
->context
->server
.try_validation6
= false;
2398 netlogon_creds_cli_LogonSamLogon_start(req
);
2402 if (tevent_req_nterror(req
, result
)) {
2403 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2407 if (state
->ro_creds
== NULL
) {
2408 tevent_req_done(req
);
2412 ok
= netlogon_creds_cli_validate(state
->context
, state
->ro_creds
);
2415 * We got a race, lets retry with on authenticator
2418 TALLOC_FREE(state
->ro_creds
);
2419 state
->try_logon_ex
= false;
2420 netlogon_creds_cli_LogonSamLogon_start(req
);
2424 netlogon_creds_decrypt_samlogon_validation(state
->ro_creds
,
2425 state
->validation_level
,
2428 tevent_req_done(req
);
2432 if (state
->lk_creds
== NULL
) {
2433 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2435 TALLOC_FREE(subreq
);
2436 if (tevent_req_nterror(req
, status
)) {
2437 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2441 netlogon_creds_cli_LogonSamLogon_start(req
);
2445 if (state
->context
->server
.try_logon_with
) {
2446 status
= dcerpc_netr_LogonSamLogonWithFlags_recv(subreq
,
2449 TALLOC_FREE(subreq
);
2450 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2451 state
->context
->server
.try_logon_with
= false;
2452 netlogon_creds_cli_LogonSamLogon_start(req
);
2455 if (tevent_req_nterror(req
, status
)) {
2456 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2460 status
= dcerpc_netr_LogonSamLogon_recv(subreq
,
2463 TALLOC_FREE(subreq
);
2464 if (tevent_req_nterror(req
, status
)) {
2465 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2470 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2471 &state
->rep_auth
.cred
);
2473 status
= NT_STATUS_ACCESS_DENIED
;
2474 tevent_req_nterror(req
, status
);
2475 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2479 *state
->lk_creds
= state
->tmp_creds
;
2480 status
= netlogon_creds_cli_store(state
->context
,
2482 if (tevent_req_nterror(req
, status
)) {
2483 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2487 if (tevent_req_nterror(req
, result
)) {
2488 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2492 netlogon_creds_decrypt_samlogon_validation(&state
->tmp_creds
,
2493 state
->validation_level
,
2496 tevent_req_done(req
);
2499 NTSTATUS
netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req
*req
,
2500 TALLOC_CTX
*mem_ctx
,
2501 uint16_t *validation_level
,
2502 union netr_Validation
**validation
,
2503 uint8_t *authoritative
,
2506 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2507 tevent_req_data(req
,
2508 struct netlogon_creds_cli_LogonSamLogon_state
);
2511 /* authoritative is also returned on error */
2512 *authoritative
= state
->authoritative
;
2514 if (tevent_req_is_nterror(req
, &status
)) {
2515 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2516 tevent_req_received(req
);
2520 *validation_level
= state
->validation_level
;
2521 *validation
= talloc_move(mem_ctx
, &state
->validation
);
2522 *flags
= state
->flags
;
2524 tevent_req_received(req
);
2525 return NT_STATUS_OK
;
2528 NTSTATUS
netlogon_creds_cli_LogonSamLogon(
2529 struct netlogon_creds_cli_context
*context
,
2530 struct dcerpc_binding_handle
*b
,
2531 enum netr_LogonInfoClass logon_level
,
2532 const union netr_LogonLevel
*logon
,
2533 TALLOC_CTX
*mem_ctx
,
2534 uint16_t *validation_level
,
2535 union netr_Validation
**validation
,
2536 uint8_t *authoritative
,
2539 TALLOC_CTX
*frame
= talloc_stackframe();
2540 struct tevent_context
*ev
;
2541 struct tevent_req
*req
;
2542 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2544 ev
= samba_tevent_context_init(frame
);
2548 req
= netlogon_creds_cli_LogonSamLogon_send(frame
, ev
, context
, b
,
2554 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2557 status
= netlogon_creds_cli_LogonSamLogon_recv(req
, mem_ctx
,
2567 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
{
2568 struct tevent_context
*ev
;
2569 struct netlogon_creds_cli_context
*context
;
2570 struct dcerpc_binding_handle
*binding_handle
;
2572 char *srv_name_slash
;
2573 enum dcerpc_AuthType auth_type
;
2574 enum dcerpc_AuthLevel auth_level
;
2576 const char *site_name
;
2578 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
;
2580 struct netlogon_creds_CredentialState
*creds
;
2581 struct netlogon_creds_CredentialState tmp_creds
;
2582 struct netr_Authenticator req_auth
;
2583 struct netr_Authenticator rep_auth
;
2586 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2588 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
);
2590 struct tevent_req
*netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(TALLOC_CTX
*mem_ctx
,
2591 struct tevent_context
*ev
,
2592 struct netlogon_creds_cli_context
*context
,
2593 struct dcerpc_binding_handle
*b
,
2594 const char *site_name
,
2596 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2598 struct tevent_req
*req
;
2599 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
;
2600 struct tevent_req
*subreq
;
2602 req
= tevent_req_create(mem_ctx
, &state
,
2603 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2609 state
->context
= context
;
2610 state
->binding_handle
= b
;
2612 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2613 context
->server
.computer
);
2614 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2615 return tevent_req_post(req
, ev
);
2618 state
->site_name
= site_name
;
2619 state
->dns_ttl
= dns_ttl
;
2620 state
->dns_names
= dns_names
;
2622 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2624 &state
->auth_level
);
2626 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2628 if (tevent_req_nomem(subreq
, req
)) {
2629 return tevent_req_post(req
, ev
);
2632 tevent_req_set_callback(subreq
,
2633 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked
,
2639 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2642 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2643 tevent_req_data(req
,
2644 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2646 if (state
->creds
== NULL
) {
2650 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2651 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2652 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2653 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2654 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2655 TALLOC_FREE(state
->creds
);
2659 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
2662 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
);
2664 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
)
2666 struct tevent_req
*req
=
2667 tevent_req_callback_data(subreq
,
2669 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2670 tevent_req_data(req
,
2671 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2674 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2676 TALLOC_FREE(subreq
);
2677 if (tevent_req_nterror(req
, status
)) {
2681 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
2682 switch (state
->auth_level
) {
2683 case DCERPC_AUTH_LEVEL_INTEGRITY
:
2684 case DCERPC_AUTH_LEVEL_PRIVACY
:
2687 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2691 uint32_t tmp
= state
->creds
->negotiate_flags
;
2693 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
2695 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
2696 * it should be used, which means
2697 * we had a chance to verify no downgrade
2700 * This relies on netlogon_creds_cli_check*
2701 * being called before, as first request after
2704 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2710 * we defer all callbacks in order to cleanup
2711 * the database record.
2713 tevent_req_defer_callback(req
, state
->ev
);
2715 state
->tmp_creds
= *state
->creds
;
2716 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2718 ZERO_STRUCT(state
->rep_auth
);
2720 subreq
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_send(state
, state
->ev
,
2721 state
->binding_handle
,
2722 state
->srv_name_slash
,
2723 state
->tmp_creds
.computer_name
,
2729 if (tevent_req_nomem(subreq
, req
)) {
2730 status
= NT_STATUS_NO_MEMORY
;
2731 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2735 tevent_req_set_callback(subreq
,
2736 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done
,
2740 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
)
2742 struct tevent_req
*req
=
2743 tevent_req_callback_data(subreq
,
2745 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2746 tevent_req_data(req
,
2747 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2753 * We use state->dns_names as the memory context, as this is
2754 * the only in/out variable and it has been overwritten by the
2755 * out parameter from the server.
2757 * We need to preserve the return value until the caller can use it.
2759 status
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_recv(subreq
, state
->dns_names
,
2761 TALLOC_FREE(subreq
);
2762 if (tevent_req_nterror(req
, status
)) {
2763 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2767 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2768 &state
->rep_auth
.cred
);
2770 status
= NT_STATUS_ACCESS_DENIED
;
2771 tevent_req_nterror(req
, status
);
2772 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2776 if (tevent_req_nterror(req
, result
)) {
2777 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, result
);
2781 *state
->creds
= state
->tmp_creds
;
2782 status
= netlogon_creds_cli_store(state
->context
,
2784 if (tevent_req_nterror(req
, status
)) {
2785 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2789 tevent_req_done(req
);
2792 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(struct tevent_req
*req
)
2796 if (tevent_req_is_nterror(req
, &status
)) {
2797 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2798 tevent_req_received(req
);
2802 tevent_req_received(req
);
2803 return NT_STATUS_OK
;
2806 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(
2807 struct netlogon_creds_cli_context
*context
,
2808 struct dcerpc_binding_handle
*b
,
2809 const char *site_name
,
2811 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2813 TALLOC_CTX
*frame
= talloc_stackframe();
2814 struct tevent_context
*ev
;
2815 struct tevent_req
*req
;
2816 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2818 ev
= samba_tevent_context_init(frame
);
2822 req
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(frame
, ev
, context
, b
,
2829 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2832 status
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(req
);
2838 struct netlogon_creds_cli_ServerGetTrustInfo_state
{
2839 struct tevent_context
*ev
;
2840 struct netlogon_creds_cli_context
*context
;
2841 struct dcerpc_binding_handle
*binding_handle
;
2843 char *srv_name_slash
;
2844 enum dcerpc_AuthType auth_type
;
2845 enum dcerpc_AuthLevel auth_level
;
2847 struct samr_Password new_owf_password
;
2848 struct samr_Password old_owf_password
;
2849 struct netr_TrustInfo
*trust_info
;
2851 struct netlogon_creds_CredentialState
*creds
;
2852 struct netlogon_creds_CredentialState tmp_creds
;
2853 struct netr_Authenticator req_auth
;
2854 struct netr_Authenticator rep_auth
;
2857 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
2859 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
);
2861 struct tevent_req
*netlogon_creds_cli_ServerGetTrustInfo_send(TALLOC_CTX
*mem_ctx
,
2862 struct tevent_context
*ev
,
2863 struct netlogon_creds_cli_context
*context
,
2864 struct dcerpc_binding_handle
*b
)
2866 struct tevent_req
*req
;
2867 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
;
2868 struct tevent_req
*subreq
;
2870 req
= tevent_req_create(mem_ctx
, &state
,
2871 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2877 state
->context
= context
;
2878 state
->binding_handle
= b
;
2880 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2881 context
->server
.computer
);
2882 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2883 return tevent_req_post(req
, ev
);
2886 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2888 &state
->auth_level
);
2890 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2892 if (tevent_req_nomem(subreq
, req
)) {
2893 return tevent_req_post(req
, ev
);
2896 tevent_req_set_callback(subreq
,
2897 netlogon_creds_cli_ServerGetTrustInfo_locked
,
2903 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
2906 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2907 tevent_req_data(req
,
2908 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2910 if (state
->creds
== NULL
) {
2914 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2915 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2916 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2917 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2918 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2919 TALLOC_FREE(state
->creds
);
2923 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
2926 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
);
2928 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
)
2930 struct tevent_req
*req
=
2931 tevent_req_callback_data(subreq
,
2933 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2934 tevent_req_data(req
,
2935 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2938 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2940 TALLOC_FREE(subreq
);
2941 if (tevent_req_nterror(req
, status
)) {
2945 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
2946 switch (state
->auth_level
) {
2947 case DCERPC_AUTH_LEVEL_PRIVACY
:
2950 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2954 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2959 * we defer all callbacks in order to cleanup
2960 * the database record.
2962 tevent_req_defer_callback(req
, state
->ev
);
2964 state
->tmp_creds
= *state
->creds
;
2965 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2967 ZERO_STRUCT(state
->rep_auth
);
2969 subreq
= dcerpc_netr_ServerGetTrustInfo_send(state
, state
->ev
,
2970 state
->binding_handle
,
2971 state
->srv_name_slash
,
2972 state
->tmp_creds
.account_name
,
2973 state
->tmp_creds
.secure_channel_type
,
2974 state
->tmp_creds
.computer_name
,
2977 &state
->new_owf_password
,
2978 &state
->old_owf_password
,
2979 &state
->trust_info
);
2980 if (tevent_req_nomem(subreq
, req
)) {
2981 status
= NT_STATUS_NO_MEMORY
;
2982 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
2986 tevent_req_set_callback(subreq
,
2987 netlogon_creds_cli_ServerGetTrustInfo_done
,
2991 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
)
2993 struct tevent_req
*req
=
2994 tevent_req_callback_data(subreq
,
2996 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2997 tevent_req_data(req
,
2998 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3001 const struct samr_Password zero
= {};
3006 * We use state->dns_names as the memory context, as this is
3007 * the only in/out variable and it has been overwritten by the
3008 * out parameter from the server.
3010 * We need to preserve the return value until the caller can use it.
3012 status
= dcerpc_netr_ServerGetTrustInfo_recv(subreq
, state
, &result
);
3013 TALLOC_FREE(subreq
);
3014 if (tevent_req_nterror(req
, status
)) {
3015 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3019 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3020 &state
->rep_auth
.cred
);
3022 status
= NT_STATUS_ACCESS_DENIED
;
3023 tevent_req_nterror(req
, status
);
3024 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3028 if (tevent_req_nterror(req
, result
)) {
3029 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, result
);
3033 cmp
= memcmp(state
->new_owf_password
.hash
,
3034 zero
.hash
, sizeof(zero
.hash
));
3036 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3037 &state
->new_owf_password
);
3039 cmp
= memcmp(state
->old_owf_password
.hash
,
3040 zero
.hash
, sizeof(zero
.hash
));
3042 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3043 &state
->old_owf_password
);
3046 *state
->creds
= state
->tmp_creds
;
3047 status
= netlogon_creds_cli_store(state
->context
,
3049 if (tevent_req_nterror(req
, status
)) {
3050 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3054 tevent_req_done(req
);
3057 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo_recv(struct tevent_req
*req
,
3058 TALLOC_CTX
*mem_ctx
,
3059 struct samr_Password
*new_owf_password
,
3060 struct samr_Password
*old_owf_password
,
3061 struct netr_TrustInfo
**trust_info
)
3063 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3064 tevent_req_data(req
,
3065 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3068 if (tevent_req_is_nterror(req
, &status
)) {
3069 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3070 tevent_req_received(req
);
3074 if (new_owf_password
!= NULL
) {
3075 *new_owf_password
= state
->new_owf_password
;
3077 if (old_owf_password
!= NULL
) {
3078 *old_owf_password
= state
->old_owf_password
;
3080 if (trust_info
!= NULL
) {
3081 *trust_info
= talloc_move(mem_ctx
, &state
->trust_info
);
3084 tevent_req_received(req
);
3085 return NT_STATUS_OK
;
3088 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo(
3089 struct netlogon_creds_cli_context
*context
,
3090 struct dcerpc_binding_handle
*b
,
3091 TALLOC_CTX
*mem_ctx
,
3092 struct samr_Password
*new_owf_password
,
3093 struct samr_Password
*old_owf_password
,
3094 struct netr_TrustInfo
**trust_info
)
3096 TALLOC_CTX
*frame
= talloc_stackframe();
3097 struct tevent_context
*ev
;
3098 struct tevent_req
*req
;
3099 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3101 ev
= samba_tevent_context_init(frame
);
3105 req
= netlogon_creds_cli_ServerGetTrustInfo_send(frame
, ev
, context
, b
);
3109 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3112 status
= netlogon_creds_cli_ServerGetTrustInfo_recv(req
,
3122 struct netlogon_creds_cli_GetForestTrustInformation_state
{
3123 struct tevent_context
*ev
;
3124 struct netlogon_creds_cli_context
*context
;
3125 struct dcerpc_binding_handle
*binding_handle
;
3127 char *srv_name_slash
;
3128 enum dcerpc_AuthType auth_type
;
3129 enum dcerpc_AuthLevel auth_level
;
3132 struct lsa_ForestTrustInformation
*forest_trust_info
;
3134 struct netlogon_creds_CredentialState
*creds
;
3135 struct netlogon_creds_CredentialState tmp_creds
;
3136 struct netr_Authenticator req_auth
;
3137 struct netr_Authenticator rep_auth
;
3140 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3142 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
);
3144 struct tevent_req
*netlogon_creds_cli_GetForestTrustInformation_send(TALLOC_CTX
*mem_ctx
,
3145 struct tevent_context
*ev
,
3146 struct netlogon_creds_cli_context
*context
,
3147 struct dcerpc_binding_handle
*b
)
3149 struct tevent_req
*req
;
3150 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
;
3151 struct tevent_req
*subreq
;
3153 req
= tevent_req_create(mem_ctx
, &state
,
3154 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3160 state
->context
= context
;
3161 state
->binding_handle
= b
;
3163 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3164 context
->server
.computer
);
3165 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3166 return tevent_req_post(req
, ev
);
3171 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3173 &state
->auth_level
);
3175 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3177 if (tevent_req_nomem(subreq
, req
)) {
3178 return tevent_req_post(req
, ev
);
3181 tevent_req_set_callback(subreq
,
3182 netlogon_creds_cli_GetForestTrustInformation_locked
,
3188 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3191 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3192 tevent_req_data(req
,
3193 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3195 if (state
->creds
== NULL
) {
3199 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3200 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3201 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3202 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3203 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3204 TALLOC_FREE(state
->creds
);
3208 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
3211 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
);
3213 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
)
3215 struct tevent_req
*req
=
3216 tevent_req_callback_data(subreq
,
3218 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3219 tevent_req_data(req
,
3220 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3223 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3225 TALLOC_FREE(subreq
);
3226 if (tevent_req_nterror(req
, status
)) {
3230 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3231 switch (state
->auth_level
) {
3232 case DCERPC_AUTH_LEVEL_INTEGRITY
:
3233 case DCERPC_AUTH_LEVEL_PRIVACY
:
3236 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3240 uint32_t tmp
= state
->creds
->negotiate_flags
;
3242 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
3244 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3245 * it should be used, which means
3246 * we had a chance to verify no downgrade
3249 * This relies on netlogon_creds_cli_check*
3250 * being called before, as first request after
3253 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3259 * we defer all callbacks in order to cleanup
3260 * the database record.
3262 tevent_req_defer_callback(req
, state
->ev
);
3264 state
->tmp_creds
= *state
->creds
;
3265 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3267 ZERO_STRUCT(state
->rep_auth
);
3269 subreq
= dcerpc_netr_GetForestTrustInformation_send(state
, state
->ev
,
3270 state
->binding_handle
,
3271 state
->srv_name_slash
,
3272 state
->tmp_creds
.computer_name
,
3276 &state
->forest_trust_info
);
3277 if (tevent_req_nomem(subreq
, req
)) {
3278 status
= NT_STATUS_NO_MEMORY
;
3279 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3283 tevent_req_set_callback(subreq
,
3284 netlogon_creds_cli_GetForestTrustInformation_done
,
3288 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
)
3290 struct tevent_req
*req
=
3291 tevent_req_callback_data(subreq
,
3293 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3294 tevent_req_data(req
,
3295 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3301 * We use state->dns_names as the memory context, as this is
3302 * the only in/out variable and it has been overwritten by the
3303 * out parameter from the server.
3305 * We need to preserve the return value until the caller can use it.
3307 status
= dcerpc_netr_GetForestTrustInformation_recv(subreq
, state
, &result
);
3308 TALLOC_FREE(subreq
);
3309 if (tevent_req_nterror(req
, status
)) {
3310 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3314 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3315 &state
->rep_auth
.cred
);
3317 status
= NT_STATUS_ACCESS_DENIED
;
3318 tevent_req_nterror(req
, status
);
3319 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3323 if (tevent_req_nterror(req
, result
)) {
3324 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, result
);
3328 *state
->creds
= state
->tmp_creds
;
3329 status
= netlogon_creds_cli_store(state
->context
,
3331 if (tevent_req_nterror(req
, status
)) {
3332 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3336 tevent_req_done(req
);
3339 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation_recv(struct tevent_req
*req
,
3340 TALLOC_CTX
*mem_ctx
,
3341 struct lsa_ForestTrustInformation
**forest_trust_info
)
3343 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3344 tevent_req_data(req
,
3345 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3348 if (tevent_req_is_nterror(req
, &status
)) {
3349 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3350 tevent_req_received(req
);
3354 *forest_trust_info
= talloc_move(mem_ctx
, &state
->forest_trust_info
);
3356 tevent_req_received(req
);
3357 return NT_STATUS_OK
;
3360 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation(
3361 struct netlogon_creds_cli_context
*context
,
3362 struct dcerpc_binding_handle
*b
,
3363 TALLOC_CTX
*mem_ctx
,
3364 struct lsa_ForestTrustInformation
**forest_trust_info
)
3366 TALLOC_CTX
*frame
= talloc_stackframe();
3367 struct tevent_context
*ev
;
3368 struct tevent_req
*req
;
3369 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3371 ev
= samba_tevent_context_init(frame
);
3375 req
= netlogon_creds_cli_GetForestTrustInformation_send(frame
, ev
, context
, b
);
3379 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3382 status
= netlogon_creds_cli_GetForestTrustInformation_recv(req
,