2 Unix SMB/CIFS implementation.
4 module to store/fetch session keys for the schannel client
6 Copyright (C) Stefan Metzmacher 2013
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "system/filesys.h"
25 #include "lib/util/tevent_ntstatus.h"
26 #include "lib/dbwrap/dbwrap.h"
27 #include "lib/dbwrap/dbwrap_rbt.h"
28 #include "lib/util/util_tdb.h"
29 #include "libcli/security/security.h"
30 #include "../lib/param/param.h"
31 #include "../libcli/auth/schannel.h"
32 #include "../librpc/gen_ndr/ndr_schannel.h"
33 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
34 #include "../librpc/gen_ndr/server_id.h"
35 #include "netlogon_creds_cli.h"
36 #include "source3/include/messages.h"
37 #include "source3/include/g_lock.h"
39 struct netlogon_creds_cli_locked_state
;
41 struct netlogon_creds_cli_context
{
45 uint32_t proposed_flags
;
46 uint32_t required_flags
;
47 enum netr_SchannelType type
;
48 enum dcerpc_AuthLevel auth_level
;
53 const char *netbios_domain
;
54 uint32_t cached_flags
;
63 struct db_context
*ctx
;
64 struct g_lock_ctx
*g_ctx
;
65 struct netlogon_creds_cli_locked_state
*locked_state
;
69 struct netlogon_creds_cli_locked_state
{
70 struct netlogon_creds_cli_context
*context
;
72 struct netlogon_creds_CredentialState
*creds
;
75 static int netlogon_creds_cli_locked_state_destructor(
76 struct netlogon_creds_cli_locked_state
*state
)
78 struct netlogon_creds_cli_context
*context
= state
->context
;
80 if (context
== NULL
) {
84 if (context
->db
.locked_state
== state
) {
85 context
->db
.locked_state
= NULL
;
88 if (state
->is_glocked
) {
89 g_lock_unlock(context
->db
.g_ctx
,
90 context
->db
.key_name
);
96 static NTSTATUS
netlogon_creds_cli_context_common(
97 const char *client_computer
,
98 const char *client_account
,
99 enum netr_SchannelType type
,
100 enum dcerpc_AuthLevel auth_level
,
101 uint32_t proposed_flags
,
102 uint32_t required_flags
,
103 const char *server_computer
,
104 const char *server_netbios_domain
,
106 struct netlogon_creds_cli_context
**_context
)
108 struct netlogon_creds_cli_context
*context
= NULL
;
109 TALLOC_CTX
*frame
= talloc_stackframe();
110 char *_key_name
= NULL
;
111 char *server_netbios_name
= NULL
;
116 context
= talloc_zero(mem_ctx
, struct netlogon_creds_cli_context
);
117 if (context
== NULL
) {
119 return NT_STATUS_NO_MEMORY
;
122 context
->client
.computer
= talloc_strdup(context
, client_computer
);
123 if (context
->client
.computer
== NULL
) {
124 TALLOC_FREE(context
);
126 return NT_STATUS_NO_MEMORY
;
129 context
->client
.account
= talloc_strdup(context
, client_account
);
130 if (context
->client
.account
== NULL
) {
131 TALLOC_FREE(context
);
133 return NT_STATUS_NO_MEMORY
;
136 context
->client
.proposed_flags
= proposed_flags
;
137 context
->client
.required_flags
= required_flags
;
138 context
->client
.type
= type
;
139 context
->client
.auth_level
= auth_level
;
141 context
->server
.computer
= talloc_strdup(context
, server_computer
);
142 if (context
->server
.computer
== NULL
) {
143 TALLOC_FREE(context
);
145 return NT_STATUS_NO_MEMORY
;
148 context
->server
.netbios_domain
= talloc_strdup(context
, server_netbios_domain
);
149 if (context
->server
.netbios_domain
== NULL
) {
150 TALLOC_FREE(context
);
152 return NT_STATUS_NO_MEMORY
;
157 * Force the callers to provide a unique
158 * value for server_computer and use this directly.
160 * For now we have to deal with
161 * "HOSTNAME" vs. "hostname.example.com".
163 server_netbios_name
= talloc_strdup(frame
, server_computer
);
164 if (server_netbios_name
== NULL
) {
165 TALLOC_FREE(context
);
167 return NT_STATUS_NO_MEMORY
;
170 p
= strchr(server_netbios_name
, '.');
175 _key_name
= talloc_asprintf(frame
, "CLI[%s/%s]/SRV[%s/%s]",
179 server_netbios_domain
);
180 if (_key_name
== NULL
) {
181 TALLOC_FREE(context
);
183 return NT_STATUS_NO_MEMORY
;
186 context
->db
.key_name
= talloc_strdup_upper(context
, _key_name
);
187 if (context
->db
.key_name
== NULL
) {
188 TALLOC_FREE(context
);
190 return NT_STATUS_NO_MEMORY
;
193 context
->db
.key_data
= string_term_tdb_data(context
->db
.key_name
);
200 static struct db_context
*netlogon_creds_cli_global_db
;
202 NTSTATUS
netlogon_creds_cli_set_global_db(struct db_context
**db
)
204 if (netlogon_creds_cli_global_db
!= NULL
) {
205 return NT_STATUS_INVALID_PARAMETER_MIX
;
208 netlogon_creds_cli_global_db
= talloc_move(talloc_autofree_context(), db
);
212 NTSTATUS
netlogon_creds_cli_open_global_db(struct loadparm_context
*lp_ctx
)
215 struct db_context
*global_db
;
217 if (netlogon_creds_cli_global_db
!= NULL
) {
221 fname
= lpcfg_private_db_path(talloc_autofree_context(), lp_ctx
, "netlogon_creds_cli");
223 return NT_STATUS_NO_MEMORY
;
226 global_db
= dbwrap_local_open(talloc_autofree_context(), lp_ctx
,
228 TDB_CLEAR_IF_FIRST
|TDB_INCOMPATIBLE_HASH
,
230 0600, DBWRAP_LOCK_ORDER_2
);
231 if (global_db
== NULL
) {
232 DEBUG(0,("netlogon_creds_cli_open_global_db: Failed to open %s - %s\n",
233 fname
, strerror(errno
)));
235 return NT_STATUS_NO_MEMORY
;
239 netlogon_creds_cli_global_db
= global_db
;
243 NTSTATUS
netlogon_creds_cli_context_global(struct loadparm_context
*lp_ctx
,
244 struct messaging_context
*msg_ctx
,
245 const char *client_account
,
246 enum netr_SchannelType type
,
247 const char *server_computer
,
248 const char *server_netbios_domain
,
250 struct netlogon_creds_cli_context
**_context
)
252 TALLOC_CTX
*frame
= talloc_stackframe();
254 struct netlogon_creds_cli_context
*context
= NULL
;
255 const char *client_computer
;
256 uint32_t proposed_flags
;
257 uint32_t required_flags
= 0;
258 bool reject_md5_servers
= false;
259 bool require_strong_key
= false;
260 int require_sign_or_seal
= true;
261 bool seal_secure_channel
= true;
262 enum dcerpc_AuthLevel auth_level
= DCERPC_AUTH_LEVEL_NONE
;
263 bool neutralize_nt4_emulation
= false;
267 client_computer
= lpcfg_netbios_name(lp_ctx
);
268 if (strlen(client_computer
) > 15) {
269 return NT_STATUS_INVALID_PARAMETER_MIX
;
273 * allow overwrite per domain
274 * reject md5 servers:<netbios_domain>
276 reject_md5_servers
= lpcfg_reject_md5_servers(lp_ctx
);
277 reject_md5_servers
= lpcfg_parm_bool(lp_ctx
, NULL
,
278 "reject md5 servers",
279 server_netbios_domain
,
283 * allow overwrite per domain
284 * require strong key:<netbios_domain>
286 require_strong_key
= lpcfg_require_strong_key(lp_ctx
);
287 require_strong_key
= lpcfg_parm_bool(lp_ctx
, NULL
,
288 "require strong key",
289 server_netbios_domain
,
293 * allow overwrite per domain
294 * client schannel:<netbios_domain>
296 require_sign_or_seal
= lpcfg_client_schannel(lp_ctx
);
297 require_sign_or_seal
= lpcfg_parm_int(lp_ctx
, NULL
,
299 server_netbios_domain
,
300 require_sign_or_seal
);
303 * allow overwrite per domain
304 * winbind sealed pipes:<netbios_domain>
306 seal_secure_channel
= lpcfg_winbind_sealed_pipes(lp_ctx
);
307 seal_secure_channel
= lpcfg_parm_bool(lp_ctx
, NULL
,
308 "winbind sealed pipes",
309 server_netbios_domain
,
310 seal_secure_channel
);
313 * allow overwrite per domain
314 * neutralize nt4 emulation:<netbios_domain>
316 neutralize_nt4_emulation
= lpcfg_neutralize_nt4_emulation(lp_ctx
);
317 neutralize_nt4_emulation
= lpcfg_parm_bool(lp_ctx
, NULL
,
318 "neutralize nt4 emulation",
319 server_netbios_domain
,
320 neutralize_nt4_emulation
);
322 proposed_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
323 proposed_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
327 if (lpcfg_security(lp_ctx
) == SEC_ADS
) {
329 * AD domains should be secure
331 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
332 require_sign_or_seal
= true;
333 require_strong_key
= true;
337 case SEC_CHAN_DOMAIN
:
340 case SEC_CHAN_DNS_DOMAIN
:
342 * AD domains should be secure
344 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
345 require_sign_or_seal
= true;
346 require_strong_key
= true;
347 neutralize_nt4_emulation
= true;
351 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
352 require_sign_or_seal
= true;
353 require_strong_key
= true;
357 required_flags
|= NETLOGON_NEG_RODC_PASSTHROUGH
;
358 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
359 require_sign_or_seal
= true;
360 require_strong_key
= true;
361 neutralize_nt4_emulation
= true;
366 return NT_STATUS_INVALID_PARAMETER
;
369 if (neutralize_nt4_emulation
) {
370 proposed_flags
|= NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION
;
373 if (require_sign_or_seal
== false) {
374 proposed_flags
&= ~NETLOGON_NEG_AUTHENTICATED_RPC
;
376 required_flags
|= NETLOGON_NEG_ARCFOUR
;
377 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
380 if (reject_md5_servers
) {
381 required_flags
|= NETLOGON_NEG_ARCFOUR
;
382 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
383 required_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
384 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
387 if (require_strong_key
) {
388 required_flags
|= NETLOGON_NEG_ARCFOUR
;
389 required_flags
|= NETLOGON_NEG_STRONG_KEYS
;
390 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
393 proposed_flags
|= required_flags
;
395 if (seal_secure_channel
) {
396 auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
398 auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
401 status
= netlogon_creds_cli_context_common(client_computer
,
408 server_netbios_domain
,
411 if (!NT_STATUS_IS_OK(status
)) {
416 if (msg_ctx
!= NULL
) {
417 context
->db
.g_ctx
= g_lock_ctx_init(context
, msg_ctx
);
418 if (context
->db
.g_ctx
== NULL
) {
419 TALLOC_FREE(context
);
421 return NT_STATUS_NO_MEMORY
;
425 if (netlogon_creds_cli_global_db
!= NULL
) {
426 context
->db
.ctx
= netlogon_creds_cli_global_db
;
432 status
= netlogon_creds_cli_open_global_db(lp_ctx
);
433 if (!NT_STATUS_IS_OK(status
)) {
434 TALLOC_FREE(context
);
436 return NT_STATUS_NO_MEMORY
;
439 context
->db
.ctx
= netlogon_creds_cli_global_db
;
445 NTSTATUS
netlogon_creds_cli_context_tmp(const char *client_computer
,
446 const char *client_account
,
447 enum netr_SchannelType type
,
448 uint32_t proposed_flags
,
449 uint32_t required_flags
,
450 enum dcerpc_AuthLevel auth_level
,
451 const char *server_computer
,
452 const char *server_netbios_domain
,
454 struct netlogon_creds_cli_context
**_context
)
457 struct netlogon_creds_cli_context
*context
= NULL
;
461 status
= netlogon_creds_cli_context_common(client_computer
,
468 server_netbios_domain
,
471 if (!NT_STATUS_IS_OK(status
)) {
475 context
->db
.ctx
= db_open_rbt(context
);
476 if (context
->db
.ctx
== NULL
) {
477 talloc_free(context
);
478 return NT_STATUS_NO_MEMORY
;
485 enum dcerpc_AuthLevel
netlogon_creds_cli_auth_level(
486 struct netlogon_creds_cli_context
*context
)
488 return context
->client
.auth_level
;
491 struct netlogon_creds_cli_fetch_state
{
493 struct netlogon_creds_CredentialState
*creds
;
494 uint32_t required_flags
;
498 static void netlogon_creds_cli_fetch_parser(TDB_DATA key
, TDB_DATA data
,
501 struct netlogon_creds_cli_fetch_state
*state
=
502 (struct netlogon_creds_cli_fetch_state
*)private_data
;
503 enum ndr_err_code ndr_err
;
507 state
->creds
= talloc_zero(state
->mem_ctx
,
508 struct netlogon_creds_CredentialState
);
509 if (state
->creds
== NULL
) {
510 state
->status
= NT_STATUS_NO_MEMORY
;
514 blob
.data
= data
.dptr
;
515 blob
.length
= data
.dsize
;
517 ndr_err
= ndr_pull_struct_blob(&blob
, state
->creds
, state
->creds
,
518 (ndr_pull_flags_fn_t
)ndr_pull_netlogon_creds_CredentialState
);
519 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
520 TALLOC_FREE(state
->creds
);
521 state
->status
= ndr_map_error2ntstatus(ndr_err
);
525 tmp_flags
= state
->creds
->negotiate_flags
;
526 tmp_flags
&= state
->required_flags
;
527 if (tmp_flags
!= state
->required_flags
) {
528 TALLOC_FREE(state
->creds
);
529 state
->status
= NT_STATUS_DOWNGRADE_DETECTED
;
533 state
->status
= NT_STATUS_OK
;
536 NTSTATUS
netlogon_creds_cli_get(struct netlogon_creds_cli_context
*context
,
538 struct netlogon_creds_CredentialState
**_creds
)
541 struct netlogon_creds_cli_fetch_state fstate
= {
543 .status
= NT_STATUS_INTERNAL_ERROR
,
544 .required_flags
= context
->client
.required_flags
,
546 static const struct netr_Credential zero_creds
;
550 status
= dbwrap_parse_record(context
->db
.ctx
,
551 context
->db
.key_data
,
552 netlogon_creds_cli_fetch_parser
,
554 if (!NT_STATUS_IS_OK(status
)) {
557 status
= fstate
.status
;
558 if (!NT_STATUS_IS_OK(status
)) {
563 * mark it as invalid for step operations.
565 fstate
.creds
->sequence
= 0;
566 fstate
.creds
->seed
= zero_creds
;
567 fstate
.creds
->client
= zero_creds
;
568 fstate
.creds
->server
= zero_creds
;
570 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
571 *_creds
= fstate
.creds
;
576 * It is really important to try SamLogonEx here,
577 * because multiple processes can talk to the same
578 * domain controller, without using the credential
581 * With a normal SamLogon call, we must keep the
582 * credentials chain updated and intact between all
583 * users of the machine account (which would imply
584 * cross-node communication for every NTLM logon).
586 * The credentials chain is not per NETLOGON pipe
587 * connection, but globally on the server/client pair
588 * by computer name, while the client is free to use
589 * any computer name. We include the cluster node number
590 * in our computer name in order to avoid cross node
591 * coordination of the credential chain.
593 * It's also important to use NetlogonValidationSamInfo4 (6),
594 * because it relies on the rpc transport encryption
595 * and avoids using the global netlogon schannel
596 * session key to en/decrypt secret information
597 * like the user_session_key for network logons.
599 * [MS-APDS] 3.1.5.2 NTLM Network Logon
600 * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and
601 * NETLOGON_NEG_AUTHENTICATED_RPC set together
602 * are the indication that the server supports
603 * NetlogonValidationSamInfo4 (6). And it must only
604 * be used if "SealSecureChannel" is used.
606 * The "SealSecureChannel" AUTH_TYPE_SCHANNEL/AUTH_LEVEL_PRIVACY
607 * check is done in netlogon_creds_cli_LogonSamLogon*().
609 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
610 context
->server
.try_validation6
= true;
611 context
->server
.try_logon_ex
= true;
612 context
->server
.try_logon_with
= true;
614 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
615 context
->server
.try_validation6
= false;
616 context
->server
.try_logon_ex
= false;
618 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
619 context
->server
.try_validation6
= false;
622 *_creds
= fstate
.creds
;
626 bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context
*context
,
627 const struct netlogon_creds_CredentialState
*creds1
)
629 TALLOC_CTX
*frame
= talloc_stackframe();
630 struct netlogon_creds_CredentialState
*creds2
;
634 enum ndr_err_code ndr_err
;
637 status
= netlogon_creds_cli_get(context
, frame
, &creds2
);
638 if (!NT_STATUS_IS_OK(status
)) {
643 ndr_err
= ndr_push_struct_blob(&blob1
, frame
, creds1
,
644 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
645 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
650 ndr_err
= ndr_push_struct_blob(&blob2
, frame
, creds2
,
651 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
652 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
657 if (blob1
.length
!= blob2
.length
) {
662 cmp
= memcmp(blob1
.data
, blob2
.data
, blob1
.length
);
672 NTSTATUS
netlogon_creds_cli_store(struct netlogon_creds_cli_context
*context
,
673 struct netlogon_creds_CredentialState
**_creds
)
675 struct netlogon_creds_CredentialState
*creds
= *_creds
;
677 enum ndr_err_code ndr_err
;
683 if (context
->db
.locked_state
== NULL
) {
685 * this was not the result of netlogon_creds_cli_lock*()
688 return NT_STATUS_INVALID_PAGE_PROTECTION
;
691 if (context
->db
.locked_state
->creds
!= creds
) {
693 * this was not the result of netlogon_creds_cli_lock*()
696 return NT_STATUS_INVALID_PAGE_PROTECTION
;
699 ndr_err
= ndr_push_struct_blob(&blob
, creds
, creds
,
700 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
701 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
703 status
= ndr_map_error2ntstatus(ndr_err
);
707 data
.dptr
= blob
.data
;
708 data
.dsize
= blob
.length
;
710 status
= dbwrap_store(context
->db
.ctx
,
711 context
->db
.key_data
,
714 if (!NT_STATUS_IS_OK(status
)) {
721 NTSTATUS
netlogon_creds_cli_delete(struct netlogon_creds_cli_context
*context
,
722 struct netlogon_creds_CredentialState
**_creds
)
724 struct netlogon_creds_CredentialState
*creds
= *_creds
;
729 if (context
->db
.locked_state
== NULL
) {
731 * this was not the result of netlogon_creds_cli_lock*()
734 return NT_STATUS_INVALID_PAGE_PROTECTION
;
737 if (context
->db
.locked_state
->creds
!= creds
) {
739 * this was not the result of netlogon_creds_cli_lock*()
742 return NT_STATUS_INVALID_PAGE_PROTECTION
;
745 status
= dbwrap_delete(context
->db
.ctx
,
746 context
->db
.key_data
);
748 if (!NT_STATUS_IS_OK(status
)) {
755 struct netlogon_creds_cli_lock_state
{
756 struct netlogon_creds_cli_locked_state
*locked_state
;
757 struct netlogon_creds_CredentialState
*creds
;
760 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
);
761 static void netlogon_creds_cli_lock_fetch(struct tevent_req
*req
);
763 struct tevent_req
*netlogon_creds_cli_lock_send(TALLOC_CTX
*mem_ctx
,
764 struct tevent_context
*ev
,
765 struct netlogon_creds_cli_context
*context
)
767 struct tevent_req
*req
;
768 struct netlogon_creds_cli_lock_state
*state
;
769 struct netlogon_creds_cli_locked_state
*locked_state
;
770 struct tevent_req
*subreq
;
772 req
= tevent_req_create(mem_ctx
, &state
,
773 struct netlogon_creds_cli_lock_state
);
778 if (context
->db
.locked_state
!= NULL
) {
779 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
780 return tevent_req_post(req
, ev
);
783 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
784 if (tevent_req_nomem(locked_state
, req
)) {
785 return tevent_req_post(req
, ev
);
787 talloc_set_destructor(locked_state
,
788 netlogon_creds_cli_locked_state_destructor
);
789 locked_state
->context
= context
;
791 context
->db
.locked_state
= locked_state
;
792 state
->locked_state
= locked_state
;
794 if (context
->db
.g_ctx
== NULL
) {
795 netlogon_creds_cli_lock_fetch(req
);
796 if (!tevent_req_is_in_progress(req
)) {
797 return tevent_req_post(req
, ev
);
803 subreq
= g_lock_lock_send(state
, ev
,
805 context
->db
.key_name
,
807 if (tevent_req_nomem(subreq
, req
)) {
808 return tevent_req_post(req
, ev
);
810 tevent_req_set_callback(subreq
, netlogon_creds_cli_lock_done
, req
);
815 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
)
817 struct tevent_req
*req
=
818 tevent_req_callback_data(subreq
,
820 struct netlogon_creds_cli_lock_state
*state
=
822 struct netlogon_creds_cli_lock_state
);
825 status
= g_lock_lock_recv(subreq
);
827 if (tevent_req_nterror(req
, status
)) {
830 state
->locked_state
->is_glocked
= true;
832 netlogon_creds_cli_lock_fetch(req
);
835 static void netlogon_creds_cli_lock_fetch(struct tevent_req
*req
)
837 struct netlogon_creds_cli_lock_state
*state
=
839 struct netlogon_creds_cli_lock_state
);
840 struct netlogon_creds_cli_context
*context
= state
->locked_state
->context
;
841 struct netlogon_creds_cli_fetch_state fstate
= {
842 .status
= NT_STATUS_INTERNAL_ERROR
,
843 .required_flags
= context
->client
.required_flags
,
847 fstate
.mem_ctx
= state
;
848 status
= dbwrap_parse_record(context
->db
.ctx
,
849 context
->db
.key_data
,
850 netlogon_creds_cli_fetch_parser
,
852 if (tevent_req_nterror(req
, status
)) {
855 status
= fstate
.status
;
856 if (tevent_req_nterror(req
, status
)) {
860 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
861 state
->creds
= fstate
.creds
;
862 tevent_req_done(req
);
866 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
867 context
->server
.try_validation6
= true;
868 context
->server
.try_logon_ex
= true;
869 context
->server
.try_logon_with
= true;
871 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
872 context
->server
.try_validation6
= false;
873 context
->server
.try_logon_ex
= false;
875 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
876 context
->server
.try_validation6
= false;
879 state
->creds
= fstate
.creds
;
880 tevent_req_done(req
);
884 NTSTATUS
netlogon_creds_cli_lock_recv(struct tevent_req
*req
,
886 struct netlogon_creds_CredentialState
**creds
)
888 struct netlogon_creds_cli_lock_state
*state
=
890 struct netlogon_creds_cli_lock_state
);
893 if (tevent_req_is_nterror(req
, &status
)) {
894 tevent_req_received(req
);
898 talloc_steal(state
->creds
, state
->locked_state
);
899 state
->locked_state
->creds
= state
->creds
;
900 *creds
= talloc_move(mem_ctx
, &state
->creds
);
901 tevent_req_received(req
);
905 NTSTATUS
netlogon_creds_cli_lock(struct netlogon_creds_cli_context
*context
,
907 struct netlogon_creds_CredentialState
**creds
)
909 TALLOC_CTX
*frame
= talloc_stackframe();
910 struct tevent_context
*ev
;
911 struct tevent_req
*req
;
912 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
914 ev
= samba_tevent_context_init(frame
);
918 req
= netlogon_creds_cli_lock_send(frame
, ev
, context
);
922 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
925 status
= netlogon_creds_cli_lock_recv(req
, mem_ctx
, creds
);
931 struct netlogon_creds_cli_auth_state
{
932 struct tevent_context
*ev
;
933 struct netlogon_creds_cli_context
*context
;
934 struct dcerpc_binding_handle
*binding_handle
;
935 struct samr_Password current_nt_hash
;
936 struct samr_Password previous_nt_hash
;
937 struct samr_Password used_nt_hash
;
938 char *srv_name_slash
;
939 uint32_t current_flags
;
940 struct netr_Credential client_challenge
;
941 struct netr_Credential server_challenge
;
942 struct netlogon_creds_CredentialState
*creds
;
943 struct netr_Credential client_credential
;
944 struct netr_Credential server_credential
;
949 bool try_previous_nt_hash
;
950 struct netlogon_creds_cli_locked_state
*locked_state
;
953 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
);
954 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
);
956 struct tevent_req
*netlogon_creds_cli_auth_send(TALLOC_CTX
*mem_ctx
,
957 struct tevent_context
*ev
,
958 struct netlogon_creds_cli_context
*context
,
959 struct dcerpc_binding_handle
*b
,
960 struct samr_Password current_nt_hash
,
961 const struct samr_Password
*previous_nt_hash
)
963 struct tevent_req
*req
;
964 struct netlogon_creds_cli_auth_state
*state
;
965 struct netlogon_creds_cli_locked_state
*locked_state
;
968 req
= tevent_req_create(mem_ctx
, &state
,
969 struct netlogon_creds_cli_auth_state
);
975 state
->context
= context
;
976 state
->binding_handle
= b
;
977 state
->current_nt_hash
= current_nt_hash
;
978 if (previous_nt_hash
!= NULL
) {
979 state
->previous_nt_hash
= *previous_nt_hash
;
980 state
->try_previous_nt_hash
= true;
983 if (context
->db
.locked_state
!= NULL
) {
984 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
985 return tevent_req_post(req
, ev
);
988 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
989 if (tevent_req_nomem(locked_state
, req
)) {
990 return tevent_req_post(req
, ev
);
992 talloc_set_destructor(locked_state
,
993 netlogon_creds_cli_locked_state_destructor
);
994 locked_state
->context
= context
;
996 context
->db
.locked_state
= locked_state
;
997 state
->locked_state
= locked_state
;
999 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1000 context
->server
.computer
);
1001 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1002 return tevent_req_post(req
, ev
);
1005 state
->try_auth3
= true;
1006 state
->try_auth2
= true;
1008 if (context
->client
.required_flags
!= 0) {
1009 state
->require_auth2
= true;
1012 state
->used_nt_hash
= state
->current_nt_hash
;
1013 state
->current_flags
= context
->client
.proposed_flags
;
1015 if (context
->db
.g_ctx
!= NULL
) {
1016 struct tevent_req
*subreq
;
1018 subreq
= g_lock_lock_send(state
, ev
,
1020 context
->db
.key_name
,
1022 if (tevent_req_nomem(subreq
, req
)) {
1023 return tevent_req_post(req
, ev
);
1025 tevent_req_set_callback(subreq
,
1026 netlogon_creds_cli_auth_locked
,
1032 status
= dbwrap_delete(state
->context
->db
.ctx
,
1033 state
->context
->db
.key_data
);
1034 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
1035 status
= NT_STATUS_OK
;
1037 if (tevent_req_nterror(req
, status
)) {
1038 return tevent_req_post(req
, ev
);
1041 netlogon_creds_cli_auth_challenge_start(req
);
1042 if (!tevent_req_is_in_progress(req
)) {
1043 return tevent_req_post(req
, ev
);
1049 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
)
1051 struct tevent_req
*req
=
1052 tevent_req_callback_data(subreq
,
1054 struct netlogon_creds_cli_auth_state
*state
=
1055 tevent_req_data(req
,
1056 struct netlogon_creds_cli_auth_state
);
1059 status
= g_lock_lock_recv(subreq
);
1060 TALLOC_FREE(subreq
);
1061 if (tevent_req_nterror(req
, status
)) {
1064 state
->locked_state
->is_glocked
= true;
1066 status
= dbwrap_delete(state
->context
->db
.ctx
,
1067 state
->context
->db
.key_data
);
1068 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
1069 status
= NT_STATUS_OK
;
1071 if (tevent_req_nterror(req
, status
)) {
1075 netlogon_creds_cli_auth_challenge_start(req
);
1078 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
);
1080 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
)
1082 struct netlogon_creds_cli_auth_state
*state
=
1083 tevent_req_data(req
,
1084 struct netlogon_creds_cli_auth_state
);
1085 struct tevent_req
*subreq
;
1087 TALLOC_FREE(state
->creds
);
1089 generate_random_buffer(state
->client_challenge
.data
,
1090 sizeof(state
->client_challenge
.data
));
1092 subreq
= dcerpc_netr_ServerReqChallenge_send(state
, state
->ev
,
1093 state
->binding_handle
,
1094 state
->srv_name_slash
,
1095 state
->context
->client
.computer
,
1096 &state
->client_challenge
,
1097 &state
->server_challenge
);
1098 if (tevent_req_nomem(subreq
, req
)) {
1101 tevent_req_set_callback(subreq
,
1102 netlogon_creds_cli_auth_challenge_done
,
1106 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
);
1108 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
)
1110 struct tevent_req
*req
=
1111 tevent_req_callback_data(subreq
,
1113 struct netlogon_creds_cli_auth_state
*state
=
1114 tevent_req_data(req
,
1115 struct netlogon_creds_cli_auth_state
);
1119 status
= dcerpc_netr_ServerReqChallenge_recv(subreq
, state
, &result
);
1120 TALLOC_FREE(subreq
);
1121 if (tevent_req_nterror(req
, status
)) {
1124 if (tevent_req_nterror(req
, result
)) {
1128 if (!state
->try_auth3
&& !state
->try_auth2
) {
1129 state
->current_flags
= 0;
1132 /* Calculate the session key and client credentials */
1134 state
->creds
= netlogon_creds_client_init(state
,
1135 state
->context
->client
.account
,
1136 state
->context
->client
.computer
,
1137 state
->context
->client
.type
,
1138 &state
->client_challenge
,
1139 &state
->server_challenge
,
1140 &state
->used_nt_hash
,
1141 &state
->client_credential
,
1142 state
->current_flags
);
1143 if (tevent_req_nomem(state
->creds
, req
)) {
1147 if (state
->try_auth3
) {
1148 subreq
= dcerpc_netr_ServerAuthenticate3_send(state
, state
->ev
,
1149 state
->binding_handle
,
1150 state
->srv_name_slash
,
1151 state
->context
->client
.account
,
1152 state
->context
->client
.type
,
1153 state
->context
->client
.computer
,
1154 &state
->client_credential
,
1155 &state
->server_credential
,
1156 &state
->creds
->negotiate_flags
,
1158 if (tevent_req_nomem(subreq
, req
)) {
1161 } else if (state
->try_auth2
) {
1164 subreq
= dcerpc_netr_ServerAuthenticate2_send(state
, state
->ev
,
1165 state
->binding_handle
,
1166 state
->srv_name_slash
,
1167 state
->context
->client
.account
,
1168 state
->context
->client
.type
,
1169 state
->context
->client
.computer
,
1170 &state
->client_credential
,
1171 &state
->server_credential
,
1172 &state
->creds
->negotiate_flags
);
1173 if (tevent_req_nomem(subreq
, req
)) {
1179 subreq
= dcerpc_netr_ServerAuthenticate_send(state
, state
->ev
,
1180 state
->binding_handle
,
1181 state
->srv_name_slash
,
1182 state
->context
->client
.account
,
1183 state
->context
->client
.type
,
1184 state
->context
->client
.computer
,
1185 &state
->client_credential
,
1186 &state
->server_credential
);
1187 if (tevent_req_nomem(subreq
, req
)) {
1191 tevent_req_set_callback(subreq
,
1192 netlogon_creds_cli_auth_srvauth_done
,
1196 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
)
1198 struct tevent_req
*req
=
1199 tevent_req_callback_data(subreq
,
1201 struct netlogon_creds_cli_auth_state
*state
=
1202 tevent_req_data(req
,
1203 struct netlogon_creds_cli_auth_state
);
1207 enum ndr_err_code ndr_err
;
1212 if (state
->try_auth3
) {
1213 status
= dcerpc_netr_ServerAuthenticate3_recv(subreq
, state
,
1215 TALLOC_FREE(subreq
);
1216 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1217 state
->try_auth3
= false;
1218 netlogon_creds_cli_auth_challenge_start(req
);
1221 if (tevent_req_nterror(req
, status
)) {
1224 } else if (state
->try_auth2
) {
1225 status
= dcerpc_netr_ServerAuthenticate2_recv(subreq
, state
,
1227 TALLOC_FREE(subreq
);
1228 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1229 state
->try_auth2
= false;
1230 if (state
->require_auth2
) {
1231 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1232 tevent_req_nterror(req
, status
);
1235 netlogon_creds_cli_auth_challenge_start(req
);
1238 if (tevent_req_nterror(req
, status
)) {
1242 status
= dcerpc_netr_ServerAuthenticate_recv(subreq
, state
,
1244 TALLOC_FREE(subreq
);
1245 if (tevent_req_nterror(req
, status
)) {
1250 if (!NT_STATUS_IS_OK(result
) &&
1251 !NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
))
1253 tevent_req_nterror(req
, result
);
1257 tmp_flags
= state
->creds
->negotiate_flags
;
1258 tmp_flags
&= state
->context
->client
.required_flags
;
1259 if (tmp_flags
!= state
->context
->client
.required_flags
) {
1260 if (NT_STATUS_IS_OK(result
)) {
1261 tevent_req_nterror(req
, NT_STATUS_DOWNGRADE_DETECTED
);
1264 tevent_req_nterror(req
, result
);
1268 if (NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
)) {
1270 tmp_flags
= state
->context
->client
.proposed_flags
;
1271 if ((state
->current_flags
== tmp_flags
) &&
1272 (state
->creds
->negotiate_flags
!= tmp_flags
))
1275 * lets retry with the negotiated flags
1277 state
->current_flags
= state
->creds
->negotiate_flags
;
1278 netlogon_creds_cli_auth_challenge_start(req
);
1282 if (!state
->try_previous_nt_hash
) {
1284 * we already retried, giving up...
1286 tevent_req_nterror(req
, result
);
1291 * lets retry with the old nt hash.
1293 state
->try_previous_nt_hash
= false;
1294 state
->used_nt_hash
= state
->previous_nt_hash
;
1295 state
->current_flags
= state
->context
->client
.proposed_flags
;
1296 netlogon_creds_cli_auth_challenge_start(req
);
1300 ok
= netlogon_creds_client_check(state
->creds
,
1301 &state
->server_credential
);
1303 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1307 ndr_err
= ndr_push_struct_blob(&blob
, state
, state
->creds
,
1308 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
1309 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1310 status
= ndr_map_error2ntstatus(ndr_err
);
1311 tevent_req_nterror(req
, status
);
1315 data
.dptr
= blob
.data
;
1316 data
.dsize
= blob
.length
;
1318 status
= dbwrap_store(state
->context
->db
.ctx
,
1319 state
->context
->db
.key_data
,
1321 TALLOC_FREE(state
->locked_state
);
1322 if (tevent_req_nterror(req
, status
)) {
1326 tevent_req_done(req
);
1329 NTSTATUS
netlogon_creds_cli_auth_recv(struct tevent_req
*req
)
1333 if (tevent_req_is_nterror(req
, &status
)) {
1334 tevent_req_received(req
);
1338 tevent_req_received(req
);
1339 return NT_STATUS_OK
;
1342 NTSTATUS
netlogon_creds_cli_auth(struct netlogon_creds_cli_context
*context
,
1343 struct dcerpc_binding_handle
*b
,
1344 struct samr_Password current_nt_hash
,
1345 const struct samr_Password
*previous_nt_hash
)
1347 TALLOC_CTX
*frame
= talloc_stackframe();
1348 struct tevent_context
*ev
;
1349 struct tevent_req
*req
;
1350 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1352 ev
= samba_tevent_context_init(frame
);
1356 req
= netlogon_creds_cli_auth_send(frame
, ev
, context
, b
,
1362 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1365 status
= netlogon_creds_cli_auth_recv(req
);
1371 struct netlogon_creds_cli_check_state
{
1372 struct tevent_context
*ev
;
1373 struct netlogon_creds_cli_context
*context
;
1374 struct dcerpc_binding_handle
*binding_handle
;
1376 char *srv_name_slash
;
1378 union netr_Capabilities caps
;
1380 struct netlogon_creds_CredentialState
*creds
;
1381 struct netlogon_creds_CredentialState tmp_creds
;
1382 struct netr_Authenticator req_auth
;
1383 struct netr_Authenticator rep_auth
;
1386 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1388 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
);
1390 struct tevent_req
*netlogon_creds_cli_check_send(TALLOC_CTX
*mem_ctx
,
1391 struct tevent_context
*ev
,
1392 struct netlogon_creds_cli_context
*context
,
1393 struct dcerpc_binding_handle
*b
)
1395 struct tevent_req
*req
;
1396 struct netlogon_creds_cli_check_state
*state
;
1397 struct tevent_req
*subreq
;
1398 enum dcerpc_AuthType auth_type
;
1399 enum dcerpc_AuthLevel auth_level
;
1401 req
= tevent_req_create(mem_ctx
, &state
,
1402 struct netlogon_creds_cli_check_state
);
1408 state
->context
= context
;
1409 state
->binding_handle
= b
;
1411 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1412 context
->server
.computer
);
1413 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1414 return tevent_req_post(req
, ev
);
1417 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1418 &auth_type
, &auth_level
);
1420 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
1421 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1422 return tevent_req_post(req
, ev
);
1425 switch (auth_level
) {
1426 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1427 case DCERPC_AUTH_LEVEL_PRIVACY
:
1430 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1431 return tevent_req_post(req
, ev
);
1434 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1436 if (tevent_req_nomem(subreq
, req
)) {
1437 return tevent_req_post(req
, ev
);
1440 tevent_req_set_callback(subreq
,
1441 netlogon_creds_cli_check_locked
,
1447 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1450 struct netlogon_creds_cli_check_state
*state
=
1451 tevent_req_data(req
,
1452 struct netlogon_creds_cli_check_state
);
1454 if (state
->creds
== NULL
) {
1458 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1459 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1460 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1461 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1462 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1463 TALLOC_FREE(state
->creds
);
1467 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
1470 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
);
1472 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
)
1474 struct tevent_req
*req
=
1475 tevent_req_callback_data(subreq
,
1477 struct netlogon_creds_cli_check_state
*state
=
1478 tevent_req_data(req
,
1479 struct netlogon_creds_cli_check_state
);
1482 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1484 TALLOC_FREE(subreq
);
1485 if (tevent_req_nterror(req
, status
)) {
1490 * we defer all callbacks in order to cleanup
1491 * the database record.
1493 tevent_req_defer_callback(req
, state
->ev
);
1495 state
->tmp_creds
= *state
->creds
;
1496 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1498 ZERO_STRUCT(state
->rep_auth
);
1500 subreq
= dcerpc_netr_LogonGetCapabilities_send(state
, state
->ev
,
1501 state
->binding_handle
,
1502 state
->srv_name_slash
,
1503 state
->context
->client
.computer
,
1508 if (tevent_req_nomem(subreq
, req
)) {
1509 status
= NT_STATUS_NO_MEMORY
;
1510 netlogon_creds_cli_check_cleanup(req
, status
);
1513 tevent_req_set_callback(subreq
,
1514 netlogon_creds_cli_check_caps
,
1518 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
)
1520 struct tevent_req
*req
=
1521 tevent_req_callback_data(subreq
,
1523 struct netlogon_creds_cli_check_state
*state
=
1524 tevent_req_data(req
,
1525 struct netlogon_creds_cli_check_state
);
1530 status
= dcerpc_netr_LogonGetCapabilities_recv(subreq
, state
,
1532 TALLOC_FREE(subreq
);
1533 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1535 * Note that the negotiated flags are already checked
1536 * for our required flags after the ServerAuthenticate3/2 call.
1538 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1540 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1542 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1543 * already, we expect this to work!
1545 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1546 tevent_req_nterror(req
, status
);
1547 netlogon_creds_cli_check_cleanup(req
, status
);
1551 if (negotiated
& NETLOGON_NEG_STRONG_KEYS
) {
1553 * If we have negotiated NETLOGON_NEG_STRONG_KEYS
1554 * we expect this to work at least as far as the
1555 * NOT_SUPPORTED error handled below!
1557 * NT 4.0 and Old Samba servers are not
1558 * allowed without "require strong key = no"
1560 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1561 tevent_req_nterror(req
, status
);
1562 netlogon_creds_cli_check_cleanup(req
, status
);
1567 * If we not require NETLOGON_NEG_SUPPORTS_AES or
1568 * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore
1569 * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
1571 * This is needed against NT 4.0 and old Samba servers.
1573 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
1574 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
1575 * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
1576 * with the next request as the sequence number processing
1579 netlogon_creds_cli_check_cleanup(req
, status
);
1580 tevent_req_done(req
);
1583 if (tevent_req_nterror(req
, status
)) {
1584 netlogon_creds_cli_check_cleanup(req
, status
);
1588 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOT_IMPLEMENTED
)) {
1590 * Note that the negotiated flags are already checked
1591 * for our required flags after the ServerAuthenticate3/2 call.
1593 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1595 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1597 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1598 * already, we expect this to work!
1600 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1601 tevent_req_nterror(req
, status
);
1602 netlogon_creds_cli_check_cleanup(req
, status
);
1607 * This is ok, the server does not support
1608 * NETLOGON_NEG_SUPPORTS_AES.
1610 * netr_LogonGetCapabilities() was
1611 * netr_LogonDummyRoutine1() before
1612 * NETLOGON_NEG_SUPPORTS_AES was invented.
1614 netlogon_creds_cli_check_cleanup(req
, result
);
1615 tevent_req_done(req
);
1619 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1620 &state
->rep_auth
.cred
);
1622 status
= NT_STATUS_ACCESS_DENIED
;
1623 tevent_req_nterror(req
, status
);
1624 netlogon_creds_cli_check_cleanup(req
, status
);
1628 if (tevent_req_nterror(req
, result
)) {
1629 netlogon_creds_cli_check_cleanup(req
, result
);
1633 if (state
->caps
.server_capabilities
!= state
->tmp_creds
.negotiate_flags
) {
1634 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1635 tevent_req_nterror(req
, status
);
1636 netlogon_creds_cli_check_cleanup(req
, status
);
1641 * This is the key check that makes this check secure. If we
1642 * get OK here (rather than NOT_SUPPORTED), then the server
1643 * did support AES. If the server only proposed STRONG_KEYS
1644 * and not AES, then it should have failed with
1645 * NOT_IMPLEMENTED. We always send AES as a client, so the
1646 * server should always have returned it.
1648 if (!(state
->caps
.server_capabilities
& NETLOGON_NEG_SUPPORTS_AES
)) {
1649 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1650 tevent_req_nterror(req
, status
);
1651 netlogon_creds_cli_check_cleanup(req
, status
);
1655 *state
->creds
= state
->tmp_creds
;
1656 status
= netlogon_creds_cli_store(state
->context
,
1658 netlogon_creds_cli_check_cleanup(req
, status
);
1659 if (tevent_req_nterror(req
, status
)) {
1663 tevent_req_done(req
);
1666 NTSTATUS
netlogon_creds_cli_check_recv(struct tevent_req
*req
)
1670 if (tevent_req_is_nterror(req
, &status
)) {
1671 netlogon_creds_cli_check_cleanup(req
, status
);
1672 tevent_req_received(req
);
1676 tevent_req_received(req
);
1677 return NT_STATUS_OK
;
1680 NTSTATUS
netlogon_creds_cli_check(struct netlogon_creds_cli_context
*context
,
1681 struct dcerpc_binding_handle
*b
)
1683 TALLOC_CTX
*frame
= talloc_stackframe();
1684 struct tevent_context
*ev
;
1685 struct tevent_req
*req
;
1686 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1688 ev
= samba_tevent_context_init(frame
);
1692 req
= netlogon_creds_cli_check_send(frame
, ev
, context
, b
);
1696 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1699 status
= netlogon_creds_cli_check_recv(req
);
1705 struct netlogon_creds_cli_ServerPasswordSet_state
{
1706 struct tevent_context
*ev
;
1707 struct netlogon_creds_cli_context
*context
;
1708 struct dcerpc_binding_handle
*binding_handle
;
1709 uint32_t old_timeout
;
1711 char *srv_name_slash
;
1712 enum dcerpc_AuthType auth_type
;
1713 enum dcerpc_AuthLevel auth_level
;
1715 struct samr_CryptPassword samr_crypt_password
;
1716 struct netr_CryptPassword netr_crypt_password
;
1717 struct samr_Password samr_password
;
1719 struct netlogon_creds_CredentialState
*creds
;
1720 struct netlogon_creds_CredentialState tmp_creds
;
1721 struct netr_Authenticator req_auth
;
1722 struct netr_Authenticator rep_auth
;
1725 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1727 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
);
1729 struct tevent_req
*netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX
*mem_ctx
,
1730 struct tevent_context
*ev
,
1731 struct netlogon_creds_cli_context
*context
,
1732 struct dcerpc_binding_handle
*b
,
1733 const char *new_password
,
1734 const uint32_t *new_version
)
1736 struct tevent_req
*req
;
1737 struct netlogon_creds_cli_ServerPasswordSet_state
*state
;
1738 struct tevent_req
*subreq
;
1741 req
= tevent_req_create(mem_ctx
, &state
,
1742 struct netlogon_creds_cli_ServerPasswordSet_state
);
1748 state
->context
= context
;
1749 state
->binding_handle
= b
;
1752 * netr_ServerPasswordSet
1754 E_md4hash(new_password
, state
->samr_password
.hash
);
1757 * netr_ServerPasswordSet2
1759 ok
= encode_pw_buffer(state
->samr_crypt_password
.data
,
1760 new_password
, STR_UNICODE
);
1762 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1763 return tevent_req_post(req
, ev
);
1766 if (new_version
!= NULL
) {
1767 struct NL_PASSWORD_VERSION version
;
1768 uint32_t len
= IVAL(state
->samr_crypt_password
.data
, 512);
1769 uint32_t ofs
= 512 - len
;
1773 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1774 return tevent_req_post(req
, ev
);
1778 version
.ReservedField
= 0;
1779 version
.PasswordVersionNumber
= *new_version
;
1780 version
.PasswordVersionPresent
=
1781 NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT
;
1783 p
= state
->samr_crypt_password
.data
+ ofs
;
1784 SIVAL(p
, 0, version
.ReservedField
);
1785 SIVAL(p
, 4, version
.PasswordVersionNumber
);
1786 SIVAL(p
, 8, version
.PasswordVersionPresent
);
1789 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1790 context
->server
.computer
);
1791 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1792 return tevent_req_post(req
, ev
);
1795 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1797 &state
->auth_level
);
1799 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1801 if (tevent_req_nomem(subreq
, req
)) {
1802 return tevent_req_post(req
, ev
);
1805 tevent_req_set_callback(subreq
,
1806 netlogon_creds_cli_ServerPasswordSet_locked
,
1812 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1815 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1816 tevent_req_data(req
,
1817 struct netlogon_creds_cli_ServerPasswordSet_state
);
1819 if (state
->creds
== NULL
) {
1823 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
1824 state
->old_timeout
);
1826 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1827 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1828 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1829 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1830 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1831 TALLOC_FREE(state
->creds
);
1835 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
1838 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
);
1840 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
)
1842 struct tevent_req
*req
=
1843 tevent_req_callback_data(subreq
,
1845 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1846 tevent_req_data(req
,
1847 struct netlogon_creds_cli_ServerPasswordSet_state
);
1850 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1852 TALLOC_FREE(subreq
);
1853 if (tevent_req_nterror(req
, status
)) {
1857 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
1858 switch (state
->auth_level
) {
1859 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1860 case DCERPC_AUTH_LEVEL_PRIVACY
:
1863 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1867 uint32_t tmp
= state
->creds
->negotiate_flags
;
1869 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
1871 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
1872 * it should be used, which means
1873 * we had a chance to verify no downgrade
1876 * This relies on netlogon_creds_cli_check*
1877 * being called before, as first request after
1880 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1885 state
->old_timeout
= dcerpc_binding_handle_set_timeout(
1886 state
->binding_handle
, 600000);
1889 * we defer all callbacks in order to cleanup
1890 * the database record.
1892 tevent_req_defer_callback(req
, state
->ev
);
1894 state
->tmp_creds
= *state
->creds
;
1895 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1897 ZERO_STRUCT(state
->rep_auth
);
1899 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1901 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1902 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
1903 state
->samr_crypt_password
.data
,
1906 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
1907 state
->samr_crypt_password
.data
,
1911 memcpy(state
->netr_crypt_password
.data
,
1912 state
->samr_crypt_password
.data
, 512);
1913 state
->netr_crypt_password
.length
=
1914 IVAL(state
->samr_crypt_password
.data
, 512);
1916 subreq
= dcerpc_netr_ServerPasswordSet2_send(state
, state
->ev
,
1917 state
->binding_handle
,
1918 state
->srv_name_slash
,
1919 state
->tmp_creds
.account_name
,
1920 state
->tmp_creds
.secure_channel_type
,
1921 state
->tmp_creds
.computer_name
,
1924 &state
->netr_crypt_password
);
1925 if (tevent_req_nomem(subreq
, req
)) {
1926 status
= NT_STATUS_NO_MEMORY
;
1927 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1931 netlogon_creds_des_encrypt(&state
->tmp_creds
,
1932 &state
->samr_password
);
1934 subreq
= dcerpc_netr_ServerPasswordSet_send(state
, state
->ev
,
1935 state
->binding_handle
,
1936 state
->srv_name_slash
,
1937 state
->tmp_creds
.account_name
,
1938 state
->tmp_creds
.secure_channel_type
,
1939 state
->tmp_creds
.computer_name
,
1942 &state
->samr_password
);
1943 if (tevent_req_nomem(subreq
, req
)) {
1944 status
= NT_STATUS_NO_MEMORY
;
1945 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1950 tevent_req_set_callback(subreq
,
1951 netlogon_creds_cli_ServerPasswordSet_done
,
1955 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
)
1957 struct tevent_req
*req
=
1958 tevent_req_callback_data(subreq
,
1960 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1961 tevent_req_data(req
,
1962 struct netlogon_creds_cli_ServerPasswordSet_state
);
1967 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1968 status
= dcerpc_netr_ServerPasswordSet2_recv(subreq
, state
,
1970 TALLOC_FREE(subreq
);
1971 if (tevent_req_nterror(req
, status
)) {
1972 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1976 status
= dcerpc_netr_ServerPasswordSet_recv(subreq
, state
,
1978 TALLOC_FREE(subreq
);
1979 if (tevent_req_nterror(req
, status
)) {
1980 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1985 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1986 &state
->rep_auth
.cred
);
1988 status
= NT_STATUS_ACCESS_DENIED
;
1989 tevent_req_nterror(req
, status
);
1990 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1994 if (tevent_req_nterror(req
, result
)) {
1995 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, result
);
1999 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
2000 state
->old_timeout
);
2002 *state
->creds
= state
->tmp_creds
;
2003 status
= netlogon_creds_cli_store(state
->context
,
2005 if (tevent_req_nterror(req
, status
)) {
2006 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2010 tevent_req_done(req
);
2013 NTSTATUS
netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req
*req
)
2017 if (tevent_req_is_nterror(req
, &status
)) {
2018 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2019 tevent_req_received(req
);
2023 tevent_req_received(req
);
2024 return NT_STATUS_OK
;
2027 NTSTATUS
netlogon_creds_cli_ServerPasswordSet(
2028 struct netlogon_creds_cli_context
*context
,
2029 struct dcerpc_binding_handle
*b
,
2030 const char *new_password
,
2031 const uint32_t *new_version
)
2033 TALLOC_CTX
*frame
= talloc_stackframe();
2034 struct tevent_context
*ev
;
2035 struct tevent_req
*req
;
2036 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2038 ev
= samba_tevent_context_init(frame
);
2042 req
= netlogon_creds_cli_ServerPasswordSet_send(frame
, ev
, context
, b
,
2048 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2051 status
= netlogon_creds_cli_ServerPasswordSet_recv(req
);
2057 struct netlogon_creds_cli_LogonSamLogon_state
{
2058 struct tevent_context
*ev
;
2059 struct netlogon_creds_cli_context
*context
;
2060 struct dcerpc_binding_handle
*binding_handle
;
2062 char *srv_name_slash
;
2064 enum netr_LogonInfoClass logon_level
;
2065 const union netr_LogonLevel
*const_logon
;
2066 union netr_LogonLevel
*logon
;
2069 uint16_t validation_level
;
2070 union netr_Validation
*validation
;
2071 uint8_t authoritative
;
2074 * do we need encryption at the application layer?
2078 bool try_validation6
;
2081 * the read only credentials before we started the operation
2083 struct netlogon_creds_CredentialState
*ro_creds
;
2085 struct netlogon_creds_CredentialState
*lk_creds
;
2087 struct netlogon_creds_CredentialState tmp_creds
;
2088 struct netr_Authenticator req_auth
;
2089 struct netr_Authenticator rep_auth
;
2092 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
);
2093 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2096 struct tevent_req
*netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX
*mem_ctx
,
2097 struct tevent_context
*ev
,
2098 struct netlogon_creds_cli_context
*context
,
2099 struct dcerpc_binding_handle
*b
,
2100 enum netr_LogonInfoClass logon_level
,
2101 const union netr_LogonLevel
*logon
,
2104 struct tevent_req
*req
;
2105 struct netlogon_creds_cli_LogonSamLogon_state
*state
;
2107 req
= tevent_req_create(mem_ctx
, &state
,
2108 struct netlogon_creds_cli_LogonSamLogon_state
);
2114 state
->context
= context
;
2115 state
->binding_handle
= b
;
2117 state
->logon_level
= logon_level
;
2118 state
->const_logon
= logon
;
2119 state
->flags
= flags
;
2121 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2122 context
->server
.computer
);
2123 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2124 return tevent_req_post(req
, ev
);
2127 switch (logon_level
) {
2128 case NetlogonInteractiveInformation
:
2129 case NetlogonInteractiveTransitiveInformation
:
2130 case NetlogonServiceInformation
:
2131 case NetlogonServiceTransitiveInformation
:
2132 case NetlogonGenericInformation
:
2133 state
->user_encrypt
= true;
2136 case NetlogonNetworkInformation
:
2137 case NetlogonNetworkTransitiveInformation
:
2141 state
->validation
= talloc_zero(state
, union netr_Validation
);
2142 if (tevent_req_nomem(state
->validation
, req
)) {
2143 return tevent_req_post(req
, ev
);
2146 netlogon_creds_cli_LogonSamLogon_start(req
);
2147 if (!tevent_req_is_in_progress(req
)) {
2148 return tevent_req_post(req
, ev
);
2152 * we defer all callbacks in order to cleanup
2153 * the database record.
2155 tevent_req_defer_callback(req
, state
->ev
);
2159 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2162 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2163 tevent_req_data(req
,
2164 struct netlogon_creds_cli_LogonSamLogon_state
);
2166 if (state
->lk_creds
== NULL
) {
2170 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2172 * This is a hack to recover from a bug in old
2173 * Samba servers, when LogonSamLogonEx() fails:
2175 * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
2177 * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2179 * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE,
2180 * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR
2181 * If the sign/seal check fails.
2183 * In that case we need to cleanup the netlogon session.
2185 * It's the job of the caller to disconnect the current
2186 * connection, if netlogon_creds_cli_LogonSamLogon()
2187 * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2189 if (!state
->context
->server
.try_logon_with
) {
2190 status
= NT_STATUS_NETWORK_ACCESS_DENIED
;
2194 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2195 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2196 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2197 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2198 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2199 TALLOC_FREE(state
->lk_creds
);
2203 netlogon_creds_cli_delete(state
->context
, &state
->lk_creds
);
2206 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
);
2208 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
)
2210 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2211 tevent_req_data(req
,
2212 struct netlogon_creds_cli_LogonSamLogon_state
);
2213 struct tevent_req
*subreq
;
2215 enum dcerpc_AuthType auth_type
;
2216 enum dcerpc_AuthLevel auth_level
;
2218 TALLOC_FREE(state
->ro_creds
);
2219 TALLOC_FREE(state
->logon
);
2220 ZERO_STRUCTP(state
->validation
);
2222 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2223 &auth_type
, &auth_level
);
2225 state
->try_logon_ex
= state
->context
->server
.try_logon_ex
;
2226 state
->try_validation6
= state
->context
->server
.try_validation6
;
2228 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
2229 state
->try_logon_ex
= false;
2232 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
2233 state
->try_validation6
= false;
2236 if (state
->try_logon_ex
) {
2237 if (state
->try_validation6
) {
2238 state
->validation_level
= 6;
2240 state
->validation_level
= 3;
2241 state
->user_encrypt
= true;
2244 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2246 state
->const_logon
);
2247 if (tevent_req_nomem(state
->logon
, req
)) {
2248 status
= NT_STATUS_NO_MEMORY
;
2249 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2253 if (state
->user_encrypt
) {
2254 status
= netlogon_creds_cli_get(state
->context
,
2257 if (!NT_STATUS_IS_OK(status
)) {
2258 status
= NT_STATUS_ACCESS_DENIED
;
2259 tevent_req_nterror(req
, status
);
2260 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2264 netlogon_creds_encrypt_samlogon_logon(state
->ro_creds
,
2269 subreq
= dcerpc_netr_LogonSamLogonEx_send(state
, state
->ev
,
2270 state
->binding_handle
,
2271 state
->srv_name_slash
,
2272 state
->context
->client
.computer
,
2275 state
->validation_level
,
2277 &state
->authoritative
,
2279 if (tevent_req_nomem(subreq
, req
)) {
2280 status
= NT_STATUS_NO_MEMORY
;
2281 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2284 tevent_req_set_callback(subreq
,
2285 netlogon_creds_cli_LogonSamLogon_done
,
2290 if (state
->lk_creds
== NULL
) {
2291 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2293 if (tevent_req_nomem(subreq
, req
)) {
2294 status
= NT_STATUS_NO_MEMORY
;
2295 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2298 tevent_req_set_callback(subreq
,
2299 netlogon_creds_cli_LogonSamLogon_done
,
2304 state
->tmp_creds
= *state
->lk_creds
;
2305 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2307 ZERO_STRUCT(state
->rep_auth
);
2309 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2311 state
->const_logon
);
2312 if (tevent_req_nomem(state
->logon
, req
)) {
2313 status
= NT_STATUS_NO_MEMORY
;
2314 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2318 netlogon_creds_encrypt_samlogon_logon(state
->ro_creds
,
2322 state
->validation_level
= 3;
2324 if (state
->context
->server
.try_logon_with
) {
2325 subreq
= dcerpc_netr_LogonSamLogonWithFlags_send(state
, state
->ev
,
2326 state
->binding_handle
,
2327 state
->srv_name_slash
,
2328 state
->context
->client
.computer
,
2333 state
->validation_level
,
2335 &state
->authoritative
,
2337 if (tevent_req_nomem(subreq
, req
)) {
2338 status
= NT_STATUS_NO_MEMORY
;
2339 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2345 subreq
= dcerpc_netr_LogonSamLogon_send(state
, state
->ev
,
2346 state
->binding_handle
,
2347 state
->srv_name_slash
,
2348 state
->context
->client
.computer
,
2353 state
->validation_level
,
2355 &state
->authoritative
);
2356 if (tevent_req_nomem(subreq
, req
)) {
2357 status
= NT_STATUS_NO_MEMORY
;
2358 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2363 tevent_req_set_callback(subreq
,
2364 netlogon_creds_cli_LogonSamLogon_done
,
2368 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
)
2370 struct tevent_req
*req
=
2371 tevent_req_callback_data(subreq
,
2373 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2374 tevent_req_data(req
,
2375 struct netlogon_creds_cli_LogonSamLogon_state
);
2380 if (state
->try_logon_ex
) {
2381 status
= dcerpc_netr_LogonSamLogonEx_recv(subreq
,
2384 TALLOC_FREE(subreq
);
2385 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2386 state
->context
->server
.try_validation6
= false;
2387 state
->context
->server
.try_logon_ex
= false;
2388 netlogon_creds_cli_LogonSamLogon_start(req
);
2391 if (tevent_req_nterror(req
, status
)) {
2392 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2396 if ((state
->validation_level
== 6) &&
2397 (NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_INFO_CLASS
) ||
2398 NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_PARAMETER
) ||
2399 NT_STATUS_EQUAL(result
, NT_STATUS_BUFFER_TOO_SMALL
)))
2401 state
->context
->server
.try_validation6
= false;
2402 netlogon_creds_cli_LogonSamLogon_start(req
);
2406 if (tevent_req_nterror(req
, result
)) {
2407 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2411 if (state
->ro_creds
== NULL
) {
2412 tevent_req_done(req
);
2416 ok
= netlogon_creds_cli_validate(state
->context
, state
->ro_creds
);
2419 * We got a race, lets retry with on authenticator
2422 TALLOC_FREE(state
->ro_creds
);
2423 state
->try_logon_ex
= false;
2424 netlogon_creds_cli_LogonSamLogon_start(req
);
2428 netlogon_creds_decrypt_samlogon_validation(state
->ro_creds
,
2429 state
->validation_level
,
2432 tevent_req_done(req
);
2436 if (state
->lk_creds
== NULL
) {
2437 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2439 TALLOC_FREE(subreq
);
2440 if (tevent_req_nterror(req
, status
)) {
2441 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2445 netlogon_creds_cli_LogonSamLogon_start(req
);
2449 if (state
->context
->server
.try_logon_with
) {
2450 status
= dcerpc_netr_LogonSamLogonWithFlags_recv(subreq
,
2453 TALLOC_FREE(subreq
);
2454 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2455 state
->context
->server
.try_logon_with
= false;
2456 netlogon_creds_cli_LogonSamLogon_start(req
);
2459 if (tevent_req_nterror(req
, status
)) {
2460 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2464 status
= dcerpc_netr_LogonSamLogon_recv(subreq
,
2467 TALLOC_FREE(subreq
);
2468 if (tevent_req_nterror(req
, status
)) {
2469 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2474 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2475 &state
->rep_auth
.cred
);
2477 status
= NT_STATUS_ACCESS_DENIED
;
2478 tevent_req_nterror(req
, status
);
2479 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2483 *state
->lk_creds
= state
->tmp_creds
;
2484 status
= netlogon_creds_cli_store(state
->context
,
2486 if (tevent_req_nterror(req
, status
)) {
2487 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2491 if (tevent_req_nterror(req
, result
)) {
2492 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2496 netlogon_creds_decrypt_samlogon_validation(&state
->tmp_creds
,
2497 state
->validation_level
,
2500 tevent_req_done(req
);
2503 NTSTATUS
netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req
*req
,
2504 TALLOC_CTX
*mem_ctx
,
2505 uint16_t *validation_level
,
2506 union netr_Validation
**validation
,
2507 uint8_t *authoritative
,
2510 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2511 tevent_req_data(req
,
2512 struct netlogon_creds_cli_LogonSamLogon_state
);
2515 /* authoritative is also returned on error */
2516 *authoritative
= state
->authoritative
;
2518 if (tevent_req_is_nterror(req
, &status
)) {
2519 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2520 tevent_req_received(req
);
2524 *validation_level
= state
->validation_level
;
2525 *validation
= talloc_move(mem_ctx
, &state
->validation
);
2526 *flags
= state
->flags
;
2528 tevent_req_received(req
);
2529 return NT_STATUS_OK
;
2532 NTSTATUS
netlogon_creds_cli_LogonSamLogon(
2533 struct netlogon_creds_cli_context
*context
,
2534 struct dcerpc_binding_handle
*b
,
2535 enum netr_LogonInfoClass logon_level
,
2536 const union netr_LogonLevel
*logon
,
2537 TALLOC_CTX
*mem_ctx
,
2538 uint16_t *validation_level
,
2539 union netr_Validation
**validation
,
2540 uint8_t *authoritative
,
2543 TALLOC_CTX
*frame
= talloc_stackframe();
2544 struct tevent_context
*ev
;
2545 struct tevent_req
*req
;
2546 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2548 ev
= samba_tevent_context_init(frame
);
2552 req
= netlogon_creds_cli_LogonSamLogon_send(frame
, ev
, context
, b
,
2558 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2561 status
= netlogon_creds_cli_LogonSamLogon_recv(req
, mem_ctx
,