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_open_global_db(struct loadparm_context
*lp_ctx
)
205 struct db_context
*global_db
;
207 if (netlogon_creds_cli_global_db
!= NULL
) {
211 fname
= lpcfg_private_db_path(talloc_autofree_context(), lp_ctx
, "netlogon_creds_cli");
213 return NT_STATUS_NO_MEMORY
;
216 global_db
= dbwrap_local_open(talloc_autofree_context(), lp_ctx
,
218 TDB_CLEAR_IF_FIRST
|TDB_INCOMPATIBLE_HASH
,
220 0600, DBWRAP_LOCK_ORDER_2
);
221 if (global_db
== NULL
) {
222 DEBUG(0,("netlogon_creds_cli_open_global_db: Failed to open %s - %s\n",
223 fname
, strerror(errno
)));
225 return NT_STATUS_NO_MEMORY
;
229 netlogon_creds_cli_global_db
= global_db
;
233 NTSTATUS
netlogon_creds_cli_context_global(struct loadparm_context
*lp_ctx
,
234 struct messaging_context
*msg_ctx
,
235 const char *client_account
,
236 enum netr_SchannelType type
,
237 const char *server_computer
,
238 const char *server_netbios_domain
,
240 struct netlogon_creds_cli_context
**_context
)
242 TALLOC_CTX
*frame
= talloc_stackframe();
244 struct netlogon_creds_cli_context
*context
= NULL
;
245 const char *client_computer
;
246 uint32_t proposed_flags
;
247 uint32_t required_flags
= 0;
248 bool reject_md5_servers
= false;
249 bool require_strong_key
= false;
250 int require_sign_or_seal
= true;
251 bool seal_secure_channel
= true;
252 enum dcerpc_AuthLevel auth_level
= DCERPC_AUTH_LEVEL_NONE
;
253 bool neutralize_nt4_emulation
= false;
254 struct server_id self
= {
255 .vnn
= NONCLUSTER_VNN
,
256 .unique_id
= SERVERID_UNIQUE_ID_NOT_TO_VERIFY
,
259 if (msg_ctx
!= NULL
) {
260 self
= messaging_server_id(msg_ctx
);
265 if (self
.vnn
!= NONCLUSTER_VNN
) {
266 client_computer
= talloc_asprintf(frame
,
268 lpcfg_netbios_name(lp_ctx
),
270 if (client_computer
== NULL
) {
272 return NT_STATUS_NO_MEMORY
;
275 client_computer
= lpcfg_netbios_name(lp_ctx
);
279 * allow overwrite per domain
280 * reject md5 servers:<netbios_domain>
282 reject_md5_servers
= lpcfg_reject_md5_servers(lp_ctx
);
283 reject_md5_servers
= lpcfg_parm_bool(lp_ctx
, NULL
,
284 "reject md5 servers",
285 server_netbios_domain
,
289 * allow overwrite per domain
290 * require strong key:<netbios_domain>
292 require_strong_key
= lpcfg_require_strong_key(lp_ctx
);
293 require_strong_key
= lpcfg_parm_bool(lp_ctx
, NULL
,
294 "require strong key",
295 server_netbios_domain
,
299 * allow overwrite per domain
300 * client schannel:<netbios_domain>
302 require_sign_or_seal
= lpcfg_client_schannel(lp_ctx
);
303 require_sign_or_seal
= lpcfg_parm_int(lp_ctx
, NULL
,
305 server_netbios_domain
,
306 require_sign_or_seal
);
309 * allow overwrite per domain
310 * winbind sealed pipes:<netbios_domain>
312 seal_secure_channel
= lpcfg_winbind_sealed_pipes(lp_ctx
);
313 seal_secure_channel
= lpcfg_parm_bool(lp_ctx
, NULL
,
314 "winbind sealed pipes",
315 server_netbios_domain
,
316 seal_secure_channel
);
319 * allow overwrite per domain
320 * neutralize nt4 emulation:<netbios_domain>
322 neutralize_nt4_emulation
= lpcfg_neutralize_nt4_emulation(lp_ctx
);
323 neutralize_nt4_emulation
= lpcfg_parm_bool(lp_ctx
, NULL
,
324 "neutralize nt4 emulation",
325 server_netbios_domain
,
326 neutralize_nt4_emulation
);
328 proposed_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
329 proposed_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
333 if (lpcfg_security(lp_ctx
) == SEC_ADS
) {
335 * AD domains should be secure
337 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
338 require_sign_or_seal
= true;
339 require_strong_key
= true;
343 case SEC_CHAN_DOMAIN
:
346 case SEC_CHAN_DNS_DOMAIN
:
348 * AD domains should be secure
350 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
351 require_sign_or_seal
= true;
352 require_strong_key
= true;
353 neutralize_nt4_emulation
= true;
357 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
358 require_sign_or_seal
= true;
359 require_strong_key
= true;
363 required_flags
|= NETLOGON_NEG_RODC_PASSTHROUGH
;
364 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
365 require_sign_or_seal
= true;
366 require_strong_key
= true;
367 neutralize_nt4_emulation
= true;
372 return NT_STATUS_INVALID_PARAMETER
;
375 if (neutralize_nt4_emulation
) {
376 proposed_flags
|= NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION
;
379 if (require_sign_or_seal
== false) {
380 proposed_flags
&= ~NETLOGON_NEG_AUTHENTICATED_RPC
;
382 required_flags
|= NETLOGON_NEG_ARCFOUR
;
383 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
386 if (reject_md5_servers
) {
387 required_flags
|= NETLOGON_NEG_ARCFOUR
;
388 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
389 required_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
390 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
393 if (require_strong_key
) {
394 required_flags
|= NETLOGON_NEG_ARCFOUR
;
395 required_flags
|= NETLOGON_NEG_STRONG_KEYS
;
396 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
399 proposed_flags
|= required_flags
;
401 if (seal_secure_channel
) {
402 auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
404 auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
407 status
= netlogon_creds_cli_context_common(client_computer
,
414 server_netbios_domain
,
417 if (!NT_STATUS_IS_OK(status
)) {
422 if (msg_ctx
!= NULL
) {
423 context
->db
.g_ctx
= g_lock_ctx_init(context
, msg_ctx
);
424 if (context
->db
.g_ctx
== NULL
) {
425 TALLOC_FREE(context
);
427 return NT_STATUS_NO_MEMORY
;
431 if (netlogon_creds_cli_global_db
!= NULL
) {
432 context
->db
.ctx
= netlogon_creds_cli_global_db
;
438 status
= netlogon_creds_cli_open_global_db(lp_ctx
);
439 if (!NT_STATUS_IS_OK(status
)) {
440 TALLOC_FREE(context
);
442 return NT_STATUS_NO_MEMORY
;
445 context
->db
.ctx
= netlogon_creds_cli_global_db
;
451 NTSTATUS
netlogon_creds_cli_context_tmp(const char *client_computer
,
452 const char *client_account
,
453 enum netr_SchannelType type
,
454 uint32_t proposed_flags
,
455 uint32_t required_flags
,
456 enum dcerpc_AuthLevel auth_level
,
457 const char *server_computer
,
458 const char *server_netbios_domain
,
460 struct netlogon_creds_cli_context
**_context
)
463 struct netlogon_creds_cli_context
*context
= NULL
;
467 status
= netlogon_creds_cli_context_common(client_computer
,
474 server_netbios_domain
,
477 if (!NT_STATUS_IS_OK(status
)) {
481 context
->db
.ctx
= db_open_rbt(context
);
482 if (context
->db
.ctx
== NULL
) {
483 talloc_free(context
);
484 return NT_STATUS_NO_MEMORY
;
491 enum dcerpc_AuthLevel
netlogon_creds_cli_auth_level(
492 struct netlogon_creds_cli_context
*context
)
494 return context
->client
.auth_level
;
497 struct netlogon_creds_cli_fetch_state
{
499 struct netlogon_creds_CredentialState
*creds
;
500 uint32_t required_flags
;
504 static void netlogon_creds_cli_fetch_parser(TDB_DATA key
, TDB_DATA data
,
507 struct netlogon_creds_cli_fetch_state
*state
=
508 (struct netlogon_creds_cli_fetch_state
*)private_data
;
509 enum ndr_err_code ndr_err
;
513 state
->creds
= talloc_zero(state
->mem_ctx
,
514 struct netlogon_creds_CredentialState
);
515 if (state
->creds
== NULL
) {
516 state
->status
= NT_STATUS_NO_MEMORY
;
520 blob
.data
= data
.dptr
;
521 blob
.length
= data
.dsize
;
523 ndr_err
= ndr_pull_struct_blob(&blob
, state
->creds
, state
->creds
,
524 (ndr_pull_flags_fn_t
)ndr_pull_netlogon_creds_CredentialState
);
525 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
526 TALLOC_FREE(state
->creds
);
527 state
->status
= ndr_map_error2ntstatus(ndr_err
);
531 tmp_flags
= state
->creds
->negotiate_flags
;
532 tmp_flags
&= state
->required_flags
;
533 if (tmp_flags
!= state
->required_flags
) {
534 TALLOC_FREE(state
->creds
);
535 state
->status
= NT_STATUS_DOWNGRADE_DETECTED
;
539 state
->status
= NT_STATUS_OK
;
542 NTSTATUS
netlogon_creds_cli_get(struct netlogon_creds_cli_context
*context
,
544 struct netlogon_creds_CredentialState
**_creds
)
547 struct netlogon_creds_cli_fetch_state fstate
= {
549 .status
= NT_STATUS_INTERNAL_ERROR
,
550 .required_flags
= context
->client
.required_flags
,
552 static const struct netr_Credential zero_creds
;
556 status
= dbwrap_parse_record(context
->db
.ctx
,
557 context
->db
.key_data
,
558 netlogon_creds_cli_fetch_parser
,
560 if (!NT_STATUS_IS_OK(status
)) {
563 status
= fstate
.status
;
564 if (!NT_STATUS_IS_OK(status
)) {
569 * mark it as invalid for step operations.
571 fstate
.creds
->sequence
= 0;
572 fstate
.creds
->seed
= zero_creds
;
573 fstate
.creds
->client
= zero_creds
;
574 fstate
.creds
->server
= zero_creds
;
576 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
577 *_creds
= fstate
.creds
;
582 * It is really important to try SamLogonEx here,
583 * because multiple processes can talk to the same
584 * domain controller, without using the credential
587 * With a normal SamLogon call, we must keep the
588 * credentials chain updated and intact between all
589 * users of the machine account (which would imply
590 * cross-node communication for every NTLM logon).
592 * The credentials chain is not per NETLOGON pipe
593 * connection, but globally on the server/client pair
594 * by computer name, while the client is free to use
595 * any computer name. We include the cluster node number
596 * in our computer name in order to avoid cross node
597 * coordination of the credential chain.
599 * It's also important to use NetlogonValidationSamInfo4 (6),
600 * because it relies on the rpc transport encryption
601 * and avoids using the global netlogon schannel
602 * session key to en/decrypt secret information
603 * like the user_session_key for network logons.
605 * [MS-APDS] 3.1.5.2 NTLM Network Logon
606 * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and
607 * NETLOGON_NEG_AUTHENTICATED_RPC set together
608 * are the indication that the server supports
609 * NetlogonValidationSamInfo4 (6). And it must only
610 * be used if "SealSecureChannel" is used.
612 * The "SealSecureChannel" AUTH_TYPE_SCHANNEL/AUTH_LEVEL_PRIVACY
613 * check is done in netlogon_creds_cli_LogonSamLogon*().
615 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
616 context
->server
.try_validation6
= true;
617 context
->server
.try_logon_ex
= true;
618 context
->server
.try_logon_with
= true;
620 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
621 context
->server
.try_validation6
= false;
622 context
->server
.try_logon_ex
= false;
624 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
625 context
->server
.try_validation6
= false;
628 *_creds
= fstate
.creds
;
632 bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context
*context
,
633 const struct netlogon_creds_CredentialState
*creds1
)
635 TALLOC_CTX
*frame
= talloc_stackframe();
636 struct netlogon_creds_CredentialState
*creds2
;
640 enum ndr_err_code ndr_err
;
643 status
= netlogon_creds_cli_get(context
, frame
, &creds2
);
644 if (!NT_STATUS_IS_OK(status
)) {
649 ndr_err
= ndr_push_struct_blob(&blob1
, frame
, creds1
,
650 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
651 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
656 ndr_err
= ndr_push_struct_blob(&blob2
, frame
, creds2
,
657 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
658 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
663 if (blob1
.length
!= blob2
.length
) {
668 cmp
= memcmp(blob1
.data
, blob2
.data
, blob1
.length
);
678 NTSTATUS
netlogon_creds_cli_store(struct netlogon_creds_cli_context
*context
,
679 struct netlogon_creds_CredentialState
**_creds
)
681 struct netlogon_creds_CredentialState
*creds
= *_creds
;
683 enum ndr_err_code ndr_err
;
689 if (context
->db
.locked_state
== NULL
) {
691 * this was not the result of netlogon_creds_cli_lock*()
694 return NT_STATUS_INVALID_PAGE_PROTECTION
;
697 if (context
->db
.locked_state
->creds
!= creds
) {
699 * this was not the result of netlogon_creds_cli_lock*()
702 return NT_STATUS_INVALID_PAGE_PROTECTION
;
705 ndr_err
= ndr_push_struct_blob(&blob
, creds
, creds
,
706 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
707 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
709 status
= ndr_map_error2ntstatus(ndr_err
);
713 data
.dptr
= blob
.data
;
714 data
.dsize
= blob
.length
;
716 status
= dbwrap_store(context
->db
.ctx
,
717 context
->db
.key_data
,
720 if (!NT_STATUS_IS_OK(status
)) {
727 NTSTATUS
netlogon_creds_cli_delete(struct netlogon_creds_cli_context
*context
,
728 struct netlogon_creds_CredentialState
**_creds
)
730 struct netlogon_creds_CredentialState
*creds
= *_creds
;
735 if (context
->db
.locked_state
== NULL
) {
737 * this was not the result of netlogon_creds_cli_lock*()
740 return NT_STATUS_INVALID_PAGE_PROTECTION
;
743 if (context
->db
.locked_state
->creds
!= creds
) {
745 * this was not the result of netlogon_creds_cli_lock*()
748 return NT_STATUS_INVALID_PAGE_PROTECTION
;
751 status
= dbwrap_delete(context
->db
.ctx
,
752 context
->db
.key_data
);
754 if (!NT_STATUS_IS_OK(status
)) {
761 struct netlogon_creds_cli_lock_state
{
762 struct netlogon_creds_cli_locked_state
*locked_state
;
763 struct netlogon_creds_CredentialState
*creds
;
766 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
);
767 static void netlogon_creds_cli_lock_fetch(struct tevent_req
*req
);
769 struct tevent_req
*netlogon_creds_cli_lock_send(TALLOC_CTX
*mem_ctx
,
770 struct tevent_context
*ev
,
771 struct netlogon_creds_cli_context
*context
)
773 struct tevent_req
*req
;
774 struct netlogon_creds_cli_lock_state
*state
;
775 struct netlogon_creds_cli_locked_state
*locked_state
;
776 struct tevent_req
*subreq
;
778 req
= tevent_req_create(mem_ctx
, &state
,
779 struct netlogon_creds_cli_lock_state
);
784 if (context
->db
.locked_state
!= NULL
) {
785 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
786 return tevent_req_post(req
, ev
);
789 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
790 if (tevent_req_nomem(locked_state
, req
)) {
791 return tevent_req_post(req
, ev
);
793 talloc_set_destructor(locked_state
,
794 netlogon_creds_cli_locked_state_destructor
);
795 locked_state
->context
= context
;
797 context
->db
.locked_state
= locked_state
;
798 state
->locked_state
= locked_state
;
800 if (context
->db
.g_ctx
== NULL
) {
801 netlogon_creds_cli_lock_fetch(req
);
802 if (!tevent_req_is_in_progress(req
)) {
803 return tevent_req_post(req
, ev
);
809 subreq
= g_lock_lock_send(state
, ev
,
811 context
->db
.key_name
,
813 if (tevent_req_nomem(subreq
, req
)) {
814 return tevent_req_post(req
, ev
);
816 tevent_req_set_callback(subreq
, netlogon_creds_cli_lock_done
, req
);
821 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
)
823 struct tevent_req
*req
=
824 tevent_req_callback_data(subreq
,
826 struct netlogon_creds_cli_lock_state
*state
=
828 struct netlogon_creds_cli_lock_state
);
831 status
= g_lock_lock_recv(subreq
);
833 if (tevent_req_nterror(req
, status
)) {
836 state
->locked_state
->is_glocked
= true;
838 netlogon_creds_cli_lock_fetch(req
);
841 static void netlogon_creds_cli_lock_fetch(struct tevent_req
*req
)
843 struct netlogon_creds_cli_lock_state
*state
=
845 struct netlogon_creds_cli_lock_state
);
846 struct netlogon_creds_cli_context
*context
= state
->locked_state
->context
;
847 struct netlogon_creds_cli_fetch_state fstate
= {
848 .status
= NT_STATUS_INTERNAL_ERROR
,
849 .required_flags
= context
->client
.required_flags
,
853 fstate
.mem_ctx
= state
;
854 status
= dbwrap_parse_record(context
->db
.ctx
,
855 context
->db
.key_data
,
856 netlogon_creds_cli_fetch_parser
,
858 if (tevent_req_nterror(req
, status
)) {
861 status
= fstate
.status
;
862 if (tevent_req_nterror(req
, status
)) {
866 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
867 state
->creds
= fstate
.creds
;
868 tevent_req_done(req
);
872 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
873 context
->server
.try_validation6
= true;
874 context
->server
.try_logon_ex
= true;
875 context
->server
.try_logon_with
= true;
877 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
878 context
->server
.try_validation6
= false;
879 context
->server
.try_logon_ex
= false;
881 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
882 context
->server
.try_validation6
= false;
885 state
->creds
= fstate
.creds
;
886 tevent_req_done(req
);
890 NTSTATUS
netlogon_creds_cli_lock_recv(struct tevent_req
*req
,
892 struct netlogon_creds_CredentialState
**creds
)
894 struct netlogon_creds_cli_lock_state
*state
=
896 struct netlogon_creds_cli_lock_state
);
899 if (tevent_req_is_nterror(req
, &status
)) {
900 tevent_req_received(req
);
904 talloc_steal(state
->creds
, state
->locked_state
);
905 state
->locked_state
->creds
= state
->creds
;
906 *creds
= talloc_move(mem_ctx
, &state
->creds
);
907 tevent_req_received(req
);
911 NTSTATUS
netlogon_creds_cli_lock(struct netlogon_creds_cli_context
*context
,
913 struct netlogon_creds_CredentialState
**creds
)
915 TALLOC_CTX
*frame
= talloc_stackframe();
916 struct tevent_context
*ev
;
917 struct tevent_req
*req
;
918 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
920 ev
= samba_tevent_context_init(frame
);
924 req
= netlogon_creds_cli_lock_send(frame
, ev
, context
);
928 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
931 status
= netlogon_creds_cli_lock_recv(req
, mem_ctx
, creds
);
937 struct netlogon_creds_cli_auth_state
{
938 struct tevent_context
*ev
;
939 struct netlogon_creds_cli_context
*context
;
940 struct dcerpc_binding_handle
*binding_handle
;
941 struct samr_Password current_nt_hash
;
942 struct samr_Password previous_nt_hash
;
943 struct samr_Password used_nt_hash
;
944 char *srv_name_slash
;
945 uint32_t current_flags
;
946 struct netr_Credential client_challenge
;
947 struct netr_Credential server_challenge
;
948 struct netlogon_creds_CredentialState
*creds
;
949 struct netr_Credential client_credential
;
950 struct netr_Credential server_credential
;
955 bool try_previous_nt_hash
;
956 struct netlogon_creds_cli_locked_state
*locked_state
;
959 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
);
960 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
);
962 struct tevent_req
*netlogon_creds_cli_auth_send(TALLOC_CTX
*mem_ctx
,
963 struct tevent_context
*ev
,
964 struct netlogon_creds_cli_context
*context
,
965 struct dcerpc_binding_handle
*b
,
966 struct samr_Password current_nt_hash
,
967 const struct samr_Password
*previous_nt_hash
)
969 struct tevent_req
*req
;
970 struct netlogon_creds_cli_auth_state
*state
;
971 struct netlogon_creds_cli_locked_state
*locked_state
;
974 req
= tevent_req_create(mem_ctx
, &state
,
975 struct netlogon_creds_cli_auth_state
);
981 state
->context
= context
;
982 state
->binding_handle
= b
;
983 state
->current_nt_hash
= current_nt_hash
;
984 if (previous_nt_hash
!= NULL
) {
985 state
->previous_nt_hash
= *previous_nt_hash
;
986 state
->try_previous_nt_hash
= true;
989 if (context
->db
.locked_state
!= NULL
) {
990 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
991 return tevent_req_post(req
, ev
);
994 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
995 if (tevent_req_nomem(locked_state
, req
)) {
996 return tevent_req_post(req
, ev
);
998 talloc_set_destructor(locked_state
,
999 netlogon_creds_cli_locked_state_destructor
);
1000 locked_state
->context
= context
;
1002 context
->db
.locked_state
= locked_state
;
1003 state
->locked_state
= locked_state
;
1005 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1006 context
->server
.computer
);
1007 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1008 return tevent_req_post(req
, ev
);
1011 state
->try_auth3
= true;
1012 state
->try_auth2
= true;
1014 if (context
->client
.required_flags
!= 0) {
1015 state
->require_auth2
= true;
1018 state
->used_nt_hash
= state
->current_nt_hash
;
1019 state
->current_flags
= context
->client
.proposed_flags
;
1021 if (context
->db
.g_ctx
!= NULL
) {
1022 struct tevent_req
*subreq
;
1024 subreq
= g_lock_lock_send(state
, ev
,
1026 context
->db
.key_name
,
1028 if (tevent_req_nomem(subreq
, req
)) {
1029 return tevent_req_post(req
, ev
);
1031 tevent_req_set_callback(subreq
,
1032 netlogon_creds_cli_auth_locked
,
1038 status
= dbwrap_delete(state
->context
->db
.ctx
,
1039 state
->context
->db
.key_data
);
1040 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
1041 status
= NT_STATUS_OK
;
1043 if (tevent_req_nterror(req
, status
)) {
1044 return tevent_req_post(req
, ev
);
1047 netlogon_creds_cli_auth_challenge_start(req
);
1048 if (!tevent_req_is_in_progress(req
)) {
1049 return tevent_req_post(req
, ev
);
1055 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
)
1057 struct tevent_req
*req
=
1058 tevent_req_callback_data(subreq
,
1060 struct netlogon_creds_cli_auth_state
*state
=
1061 tevent_req_data(req
,
1062 struct netlogon_creds_cli_auth_state
);
1065 status
= g_lock_lock_recv(subreq
);
1066 TALLOC_FREE(subreq
);
1067 if (tevent_req_nterror(req
, status
)) {
1070 state
->locked_state
->is_glocked
= true;
1072 status
= dbwrap_delete(state
->context
->db
.ctx
,
1073 state
->context
->db
.key_data
);
1074 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
1075 status
= NT_STATUS_OK
;
1077 if (tevent_req_nterror(req
, status
)) {
1081 netlogon_creds_cli_auth_challenge_start(req
);
1084 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
);
1086 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
)
1088 struct netlogon_creds_cli_auth_state
*state
=
1089 tevent_req_data(req
,
1090 struct netlogon_creds_cli_auth_state
);
1091 struct tevent_req
*subreq
;
1093 TALLOC_FREE(state
->creds
);
1095 generate_random_buffer(state
->client_challenge
.data
,
1096 sizeof(state
->client_challenge
.data
));
1098 subreq
= dcerpc_netr_ServerReqChallenge_send(state
, state
->ev
,
1099 state
->binding_handle
,
1100 state
->srv_name_slash
,
1101 state
->context
->client
.computer
,
1102 &state
->client_challenge
,
1103 &state
->server_challenge
);
1104 if (tevent_req_nomem(subreq
, req
)) {
1107 tevent_req_set_callback(subreq
,
1108 netlogon_creds_cli_auth_challenge_done
,
1112 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
);
1114 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
)
1116 struct tevent_req
*req
=
1117 tevent_req_callback_data(subreq
,
1119 struct netlogon_creds_cli_auth_state
*state
=
1120 tevent_req_data(req
,
1121 struct netlogon_creds_cli_auth_state
);
1125 status
= dcerpc_netr_ServerReqChallenge_recv(subreq
, state
, &result
);
1126 TALLOC_FREE(subreq
);
1127 if (tevent_req_nterror(req
, status
)) {
1130 if (tevent_req_nterror(req
, result
)) {
1134 if (!state
->try_auth3
&& !state
->try_auth2
) {
1135 state
->current_flags
= 0;
1138 /* Calculate the session key and client credentials */
1140 state
->creds
= netlogon_creds_client_init(state
,
1141 state
->context
->client
.account
,
1142 state
->context
->client
.computer
,
1143 state
->context
->client
.type
,
1144 &state
->client_challenge
,
1145 &state
->server_challenge
,
1146 &state
->used_nt_hash
,
1147 &state
->client_credential
,
1148 state
->current_flags
);
1149 if (tevent_req_nomem(state
->creds
, req
)) {
1153 if (state
->try_auth3
) {
1154 subreq
= dcerpc_netr_ServerAuthenticate3_send(state
, state
->ev
,
1155 state
->binding_handle
,
1156 state
->srv_name_slash
,
1157 state
->context
->client
.account
,
1158 state
->context
->client
.type
,
1159 state
->context
->client
.computer
,
1160 &state
->client_credential
,
1161 &state
->server_credential
,
1162 &state
->creds
->negotiate_flags
,
1164 if (tevent_req_nomem(subreq
, req
)) {
1167 } else if (state
->try_auth2
) {
1170 subreq
= dcerpc_netr_ServerAuthenticate2_send(state
, state
->ev
,
1171 state
->binding_handle
,
1172 state
->srv_name_slash
,
1173 state
->context
->client
.account
,
1174 state
->context
->client
.type
,
1175 state
->context
->client
.computer
,
1176 &state
->client_credential
,
1177 &state
->server_credential
,
1178 &state
->creds
->negotiate_flags
);
1179 if (tevent_req_nomem(subreq
, req
)) {
1185 subreq
= dcerpc_netr_ServerAuthenticate_send(state
, state
->ev
,
1186 state
->binding_handle
,
1187 state
->srv_name_slash
,
1188 state
->context
->client
.account
,
1189 state
->context
->client
.type
,
1190 state
->context
->client
.computer
,
1191 &state
->client_credential
,
1192 &state
->server_credential
);
1193 if (tevent_req_nomem(subreq
, req
)) {
1197 tevent_req_set_callback(subreq
,
1198 netlogon_creds_cli_auth_srvauth_done
,
1202 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
)
1204 struct tevent_req
*req
=
1205 tevent_req_callback_data(subreq
,
1207 struct netlogon_creds_cli_auth_state
*state
=
1208 tevent_req_data(req
,
1209 struct netlogon_creds_cli_auth_state
);
1213 enum ndr_err_code ndr_err
;
1218 if (state
->try_auth3
) {
1219 status
= dcerpc_netr_ServerAuthenticate3_recv(subreq
, state
,
1221 TALLOC_FREE(subreq
);
1222 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1223 state
->try_auth3
= false;
1224 netlogon_creds_cli_auth_challenge_start(req
);
1227 if (tevent_req_nterror(req
, status
)) {
1230 } else if (state
->try_auth2
) {
1231 status
= dcerpc_netr_ServerAuthenticate2_recv(subreq
, state
,
1233 TALLOC_FREE(subreq
);
1234 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1235 state
->try_auth2
= false;
1236 if (state
->require_auth2
) {
1237 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1238 tevent_req_nterror(req
, status
);
1241 netlogon_creds_cli_auth_challenge_start(req
);
1244 if (tevent_req_nterror(req
, status
)) {
1248 status
= dcerpc_netr_ServerAuthenticate_recv(subreq
, state
,
1250 TALLOC_FREE(subreq
);
1251 if (tevent_req_nterror(req
, status
)) {
1256 if (!NT_STATUS_IS_OK(result
) &&
1257 !NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
))
1259 tevent_req_nterror(req
, result
);
1263 tmp_flags
= state
->creds
->negotiate_flags
;
1264 tmp_flags
&= state
->context
->client
.required_flags
;
1265 if (tmp_flags
!= state
->context
->client
.required_flags
) {
1266 if (NT_STATUS_IS_OK(result
)) {
1267 tevent_req_nterror(req
, NT_STATUS_DOWNGRADE_DETECTED
);
1270 tevent_req_nterror(req
, result
);
1274 if (NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
)) {
1276 tmp_flags
= state
->context
->client
.proposed_flags
;
1277 if ((state
->current_flags
== tmp_flags
) &&
1278 (state
->creds
->negotiate_flags
!= tmp_flags
))
1281 * lets retry with the negotiated flags
1283 state
->current_flags
= state
->creds
->negotiate_flags
;
1284 netlogon_creds_cli_auth_challenge_start(req
);
1288 if (!state
->try_previous_nt_hash
) {
1290 * we already retried, giving up...
1292 tevent_req_nterror(req
, result
);
1297 * lets retry with the old nt hash.
1299 state
->try_previous_nt_hash
= false;
1300 state
->used_nt_hash
= state
->previous_nt_hash
;
1301 state
->current_flags
= state
->context
->client
.proposed_flags
;
1302 netlogon_creds_cli_auth_challenge_start(req
);
1306 ok
= netlogon_creds_client_check(state
->creds
,
1307 &state
->server_credential
);
1309 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1313 ndr_err
= ndr_push_struct_blob(&blob
, state
, state
->creds
,
1314 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
1315 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1316 status
= ndr_map_error2ntstatus(ndr_err
);
1317 tevent_req_nterror(req
, status
);
1321 data
.dptr
= blob
.data
;
1322 data
.dsize
= blob
.length
;
1324 status
= dbwrap_store(state
->context
->db
.ctx
,
1325 state
->context
->db
.key_data
,
1327 TALLOC_FREE(state
->locked_state
);
1328 if (tevent_req_nterror(req
, status
)) {
1332 tevent_req_done(req
);
1335 NTSTATUS
netlogon_creds_cli_auth_recv(struct tevent_req
*req
)
1339 if (tevent_req_is_nterror(req
, &status
)) {
1340 tevent_req_received(req
);
1344 tevent_req_received(req
);
1345 return NT_STATUS_OK
;
1348 NTSTATUS
netlogon_creds_cli_auth(struct netlogon_creds_cli_context
*context
,
1349 struct dcerpc_binding_handle
*b
,
1350 struct samr_Password current_nt_hash
,
1351 const struct samr_Password
*previous_nt_hash
)
1353 TALLOC_CTX
*frame
= talloc_stackframe();
1354 struct tevent_context
*ev
;
1355 struct tevent_req
*req
;
1356 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1358 ev
= samba_tevent_context_init(frame
);
1362 req
= netlogon_creds_cli_auth_send(frame
, ev
, context
, b
,
1368 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1371 status
= netlogon_creds_cli_auth_recv(req
);
1377 struct netlogon_creds_cli_check_state
{
1378 struct tevent_context
*ev
;
1379 struct netlogon_creds_cli_context
*context
;
1380 struct dcerpc_binding_handle
*binding_handle
;
1382 char *srv_name_slash
;
1384 union netr_Capabilities caps
;
1386 struct netlogon_creds_CredentialState
*creds
;
1387 struct netlogon_creds_CredentialState tmp_creds
;
1388 struct netr_Authenticator req_auth
;
1389 struct netr_Authenticator rep_auth
;
1392 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1394 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
);
1396 struct tevent_req
*netlogon_creds_cli_check_send(TALLOC_CTX
*mem_ctx
,
1397 struct tevent_context
*ev
,
1398 struct netlogon_creds_cli_context
*context
,
1399 struct dcerpc_binding_handle
*b
)
1401 struct tevent_req
*req
;
1402 struct netlogon_creds_cli_check_state
*state
;
1403 struct tevent_req
*subreq
;
1404 enum dcerpc_AuthType auth_type
;
1405 enum dcerpc_AuthLevel auth_level
;
1407 req
= tevent_req_create(mem_ctx
, &state
,
1408 struct netlogon_creds_cli_check_state
);
1414 state
->context
= context
;
1415 state
->binding_handle
= b
;
1417 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1418 context
->server
.computer
);
1419 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1420 return tevent_req_post(req
, ev
);
1423 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1424 &auth_type
, &auth_level
);
1426 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
1427 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1428 return tevent_req_post(req
, ev
);
1431 switch (auth_level
) {
1432 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1433 case DCERPC_AUTH_LEVEL_PRIVACY
:
1436 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1437 return tevent_req_post(req
, ev
);
1440 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1442 if (tevent_req_nomem(subreq
, req
)) {
1443 return tevent_req_post(req
, ev
);
1446 tevent_req_set_callback(subreq
,
1447 netlogon_creds_cli_check_locked
,
1453 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1456 struct netlogon_creds_cli_check_state
*state
=
1457 tevent_req_data(req
,
1458 struct netlogon_creds_cli_check_state
);
1460 if (state
->creds
== NULL
) {
1464 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1465 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1466 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1467 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1468 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1469 TALLOC_FREE(state
->creds
);
1473 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
1476 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
);
1478 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
)
1480 struct tevent_req
*req
=
1481 tevent_req_callback_data(subreq
,
1483 struct netlogon_creds_cli_check_state
*state
=
1484 tevent_req_data(req
,
1485 struct netlogon_creds_cli_check_state
);
1488 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1490 TALLOC_FREE(subreq
);
1491 if (tevent_req_nterror(req
, status
)) {
1496 * we defer all callbacks in order to cleanup
1497 * the database record.
1499 tevent_req_defer_callback(req
, state
->ev
);
1501 state
->tmp_creds
= *state
->creds
;
1502 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1504 ZERO_STRUCT(state
->rep_auth
);
1506 subreq
= dcerpc_netr_LogonGetCapabilities_send(state
, state
->ev
,
1507 state
->binding_handle
,
1508 state
->srv_name_slash
,
1509 state
->context
->client
.computer
,
1514 if (tevent_req_nomem(subreq
, req
)) {
1515 status
= NT_STATUS_NO_MEMORY
;
1516 netlogon_creds_cli_check_cleanup(req
, status
);
1519 tevent_req_set_callback(subreq
,
1520 netlogon_creds_cli_check_caps
,
1524 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
)
1526 struct tevent_req
*req
=
1527 tevent_req_callback_data(subreq
,
1529 struct netlogon_creds_cli_check_state
*state
=
1530 tevent_req_data(req
,
1531 struct netlogon_creds_cli_check_state
);
1536 status
= dcerpc_netr_LogonGetCapabilities_recv(subreq
, state
,
1538 TALLOC_FREE(subreq
);
1539 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1541 * Note that the negotiated flags are already checked
1542 * for our required flags after the ServerAuthenticate3/2 call.
1544 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1546 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1548 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1549 * already, we expect this to work!
1551 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1552 tevent_req_nterror(req
, status
);
1553 netlogon_creds_cli_check_cleanup(req
, status
);
1557 if (negotiated
& NETLOGON_NEG_STRONG_KEYS
) {
1559 * If we have negotiated NETLOGON_NEG_STRONG_KEYS
1560 * we expect this to work at least as far as the
1561 * NOT_SUPPORTED error handled below!
1563 * NT 4.0 and Old Samba servers are not
1564 * allowed without "require strong key = no"
1566 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1567 tevent_req_nterror(req
, status
);
1568 netlogon_creds_cli_check_cleanup(req
, status
);
1573 * If we not require NETLOGON_NEG_SUPPORTS_AES or
1574 * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore
1575 * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
1577 * This is needed against NT 4.0 and old Samba servers.
1579 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
1580 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
1581 * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
1582 * with the next request as the sequence number processing
1585 netlogon_creds_cli_check_cleanup(req
, result
);
1586 tevent_req_done(req
);
1589 if (tevent_req_nterror(req
, status
)) {
1590 netlogon_creds_cli_check_cleanup(req
, status
);
1594 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOT_IMPLEMENTED
)) {
1596 * Note that the negotiated flags are already checked
1597 * for our required flags after the ServerAuthenticate3/2 call.
1599 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1601 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1603 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1604 * already, we expect this to work!
1606 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1607 tevent_req_nterror(req
, status
);
1608 netlogon_creds_cli_check_cleanup(req
, status
);
1613 * This is ok, the server does not support
1614 * NETLOGON_NEG_SUPPORTS_AES.
1616 * netr_LogonGetCapabilities() was
1617 * netr_LogonDummyRoutine1() before
1618 * NETLOGON_NEG_SUPPORTS_AES was invented.
1620 netlogon_creds_cli_check_cleanup(req
, result
);
1621 tevent_req_done(req
);
1625 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1626 &state
->rep_auth
.cred
);
1628 status
= NT_STATUS_ACCESS_DENIED
;
1629 tevent_req_nterror(req
, status
);
1630 netlogon_creds_cli_check_cleanup(req
, status
);
1634 if (tevent_req_nterror(req
, result
)) {
1635 netlogon_creds_cli_check_cleanup(req
, result
);
1639 if (state
->caps
.server_capabilities
!= state
->tmp_creds
.negotiate_flags
) {
1640 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1641 tevent_req_nterror(req
, status
);
1642 netlogon_creds_cli_check_cleanup(req
, status
);
1647 * This is the key check that makes this check secure. If we
1648 * get OK here (rather than NOT_SUPPORTED), then the server
1649 * did support AES. If the server only proposed STRONG_KEYS
1650 * and not AES, then it should have failed with
1651 * NOT_IMPLEMENTED. We always send AES as a client, so the
1652 * server should always have returned it.
1654 if (!(state
->caps
.server_capabilities
& NETLOGON_NEG_SUPPORTS_AES
)) {
1655 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1656 tevent_req_nterror(req
, status
);
1657 netlogon_creds_cli_check_cleanup(req
, status
);
1661 *state
->creds
= state
->tmp_creds
;
1662 status
= netlogon_creds_cli_store(state
->context
,
1664 netlogon_creds_cli_check_cleanup(req
, status
);
1665 if (tevent_req_nterror(req
, status
)) {
1669 tevent_req_done(req
);
1672 NTSTATUS
netlogon_creds_cli_check_recv(struct tevent_req
*req
)
1676 if (tevent_req_is_nterror(req
, &status
)) {
1677 netlogon_creds_cli_check_cleanup(req
, status
);
1678 tevent_req_received(req
);
1682 tevent_req_received(req
);
1683 return NT_STATUS_OK
;
1686 NTSTATUS
netlogon_creds_cli_check(struct netlogon_creds_cli_context
*context
,
1687 struct dcerpc_binding_handle
*b
)
1689 TALLOC_CTX
*frame
= talloc_stackframe();
1690 struct tevent_context
*ev
;
1691 struct tevent_req
*req
;
1692 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1694 ev
= samba_tevent_context_init(frame
);
1698 req
= netlogon_creds_cli_check_send(frame
, ev
, context
, b
);
1702 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1705 status
= netlogon_creds_cli_check_recv(req
);
1711 struct netlogon_creds_cli_ServerPasswordSet_state
{
1712 struct tevent_context
*ev
;
1713 struct netlogon_creds_cli_context
*context
;
1714 struct dcerpc_binding_handle
*binding_handle
;
1715 uint32_t old_timeout
;
1717 char *srv_name_slash
;
1718 enum dcerpc_AuthType auth_type
;
1719 enum dcerpc_AuthLevel auth_level
;
1721 struct samr_CryptPassword samr_crypt_password
;
1722 struct netr_CryptPassword netr_crypt_password
;
1723 struct samr_Password samr_password
;
1725 struct netlogon_creds_CredentialState
*creds
;
1726 struct netlogon_creds_CredentialState tmp_creds
;
1727 struct netr_Authenticator req_auth
;
1728 struct netr_Authenticator rep_auth
;
1731 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1733 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
);
1735 struct tevent_req
*netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX
*mem_ctx
,
1736 struct tevent_context
*ev
,
1737 struct netlogon_creds_cli_context
*context
,
1738 struct dcerpc_binding_handle
*b
,
1739 const char *new_password
,
1740 const uint32_t *new_version
)
1742 struct tevent_req
*req
;
1743 struct netlogon_creds_cli_ServerPasswordSet_state
*state
;
1744 struct tevent_req
*subreq
;
1747 req
= tevent_req_create(mem_ctx
, &state
,
1748 struct netlogon_creds_cli_ServerPasswordSet_state
);
1754 state
->context
= context
;
1755 state
->binding_handle
= b
;
1758 * netr_ServerPasswordSet
1760 E_md4hash(new_password
, state
->samr_password
.hash
);
1763 * netr_ServerPasswordSet2
1765 ok
= encode_pw_buffer(state
->samr_crypt_password
.data
,
1766 new_password
, STR_UNICODE
);
1768 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1769 return tevent_req_post(req
, ev
);
1772 if (new_version
!= NULL
) {
1773 struct NL_PASSWORD_VERSION version
;
1774 uint32_t len
= IVAL(state
->samr_crypt_password
.data
, 512);
1775 uint32_t ofs
= 512 - len
;
1779 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1780 return tevent_req_post(req
, ev
);
1784 version
.ReservedField
= 0;
1785 version
.PasswordVersionNumber
= *new_version
;
1786 version
.PasswordVersionPresent
=
1787 NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT
;
1789 p
= state
->samr_crypt_password
.data
+ ofs
;
1790 SIVAL(p
, 0, version
.ReservedField
);
1791 SIVAL(p
, 4, version
.PasswordVersionNumber
);
1792 SIVAL(p
, 8, version
.PasswordVersionPresent
);
1795 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1796 context
->server
.computer
);
1797 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1798 return tevent_req_post(req
, ev
);
1801 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1803 &state
->auth_level
);
1805 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1807 if (tevent_req_nomem(subreq
, req
)) {
1808 return tevent_req_post(req
, ev
);
1811 tevent_req_set_callback(subreq
,
1812 netlogon_creds_cli_ServerPasswordSet_locked
,
1818 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1821 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1822 tevent_req_data(req
,
1823 struct netlogon_creds_cli_ServerPasswordSet_state
);
1825 if (state
->creds
== NULL
) {
1829 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
1830 state
->old_timeout
);
1832 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1833 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1834 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1835 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1836 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1837 TALLOC_FREE(state
->creds
);
1841 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
1844 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
);
1846 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
)
1848 struct tevent_req
*req
=
1849 tevent_req_callback_data(subreq
,
1851 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1852 tevent_req_data(req
,
1853 struct netlogon_creds_cli_ServerPasswordSet_state
);
1856 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1858 TALLOC_FREE(subreq
);
1859 if (tevent_req_nterror(req
, status
)) {
1863 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
1864 switch (state
->auth_level
) {
1865 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1866 case DCERPC_AUTH_LEVEL_PRIVACY
:
1869 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1873 uint32_t tmp
= state
->creds
->negotiate_flags
;
1875 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
1877 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
1878 * it should be used, which means
1879 * we had a chance to verify no downgrade
1882 * This relies on netlogon_creds_cli_check*
1883 * being called before, as first request after
1886 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1891 state
->old_timeout
= dcerpc_binding_handle_set_timeout(
1892 state
->binding_handle
, 600000);
1895 * we defer all callbacks in order to cleanup
1896 * the database record.
1898 tevent_req_defer_callback(req
, state
->ev
);
1900 state
->tmp_creds
= *state
->creds
;
1901 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1903 ZERO_STRUCT(state
->rep_auth
);
1905 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1907 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1908 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
1909 state
->samr_crypt_password
.data
,
1912 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
1913 state
->samr_crypt_password
.data
,
1917 memcpy(state
->netr_crypt_password
.data
,
1918 state
->samr_crypt_password
.data
, 512);
1919 state
->netr_crypt_password
.length
=
1920 IVAL(state
->samr_crypt_password
.data
, 512);
1922 subreq
= dcerpc_netr_ServerPasswordSet2_send(state
, state
->ev
,
1923 state
->binding_handle
,
1924 state
->srv_name_slash
,
1925 state
->tmp_creds
.account_name
,
1926 state
->tmp_creds
.secure_channel_type
,
1927 state
->tmp_creds
.computer_name
,
1930 &state
->netr_crypt_password
);
1931 if (tevent_req_nomem(subreq
, req
)) {
1932 status
= NT_STATUS_NO_MEMORY
;
1933 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1937 netlogon_creds_des_encrypt(&state
->tmp_creds
,
1938 &state
->samr_password
);
1940 subreq
= dcerpc_netr_ServerPasswordSet_send(state
, state
->ev
,
1941 state
->binding_handle
,
1942 state
->srv_name_slash
,
1943 state
->tmp_creds
.account_name
,
1944 state
->tmp_creds
.secure_channel_type
,
1945 state
->tmp_creds
.computer_name
,
1948 &state
->samr_password
);
1949 if (tevent_req_nomem(subreq
, req
)) {
1950 status
= NT_STATUS_NO_MEMORY
;
1951 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1956 tevent_req_set_callback(subreq
,
1957 netlogon_creds_cli_ServerPasswordSet_done
,
1961 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
)
1963 struct tevent_req
*req
=
1964 tevent_req_callback_data(subreq
,
1966 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1967 tevent_req_data(req
,
1968 struct netlogon_creds_cli_ServerPasswordSet_state
);
1973 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1974 status
= dcerpc_netr_ServerPasswordSet2_recv(subreq
, state
,
1976 TALLOC_FREE(subreq
);
1977 if (tevent_req_nterror(req
, status
)) {
1978 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1982 status
= dcerpc_netr_ServerPasswordSet_recv(subreq
, state
,
1984 TALLOC_FREE(subreq
);
1985 if (tevent_req_nterror(req
, status
)) {
1986 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1991 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1992 &state
->rep_auth
.cred
);
1994 status
= NT_STATUS_ACCESS_DENIED
;
1995 tevent_req_nterror(req
, status
);
1996 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2000 if (tevent_req_nterror(req
, result
)) {
2001 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, result
);
2005 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
2006 state
->old_timeout
);
2008 *state
->creds
= state
->tmp_creds
;
2009 status
= netlogon_creds_cli_store(state
->context
,
2011 if (tevent_req_nterror(req
, status
)) {
2012 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2016 tevent_req_done(req
);
2019 NTSTATUS
netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req
*req
)
2023 if (tevent_req_is_nterror(req
, &status
)) {
2024 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2025 tevent_req_received(req
);
2029 tevent_req_received(req
);
2030 return NT_STATUS_OK
;
2033 NTSTATUS
netlogon_creds_cli_ServerPasswordSet(
2034 struct netlogon_creds_cli_context
*context
,
2035 struct dcerpc_binding_handle
*b
,
2036 const char *new_password
,
2037 const uint32_t *new_version
)
2039 TALLOC_CTX
*frame
= talloc_stackframe();
2040 struct tevent_context
*ev
;
2041 struct tevent_req
*req
;
2042 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2044 ev
= samba_tevent_context_init(frame
);
2048 req
= netlogon_creds_cli_ServerPasswordSet_send(frame
, ev
, context
, b
,
2054 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2057 status
= netlogon_creds_cli_ServerPasswordSet_recv(req
);
2063 struct netlogon_creds_cli_LogonSamLogon_state
{
2064 struct tevent_context
*ev
;
2065 struct netlogon_creds_cli_context
*context
;
2066 struct dcerpc_binding_handle
*binding_handle
;
2068 char *srv_name_slash
;
2070 enum netr_LogonInfoClass logon_level
;
2071 const union netr_LogonLevel
*const_logon
;
2072 union netr_LogonLevel
*logon
;
2075 uint16_t validation_level
;
2076 union netr_Validation
*validation
;
2077 uint8_t authoritative
;
2080 * do we need encryption at the application layer?
2084 bool try_validation6
;
2087 * the read only credentials before we started the operation
2089 struct netlogon_creds_CredentialState
*ro_creds
;
2091 struct netlogon_creds_CredentialState
*lk_creds
;
2093 struct netlogon_creds_CredentialState tmp_creds
;
2094 struct netr_Authenticator req_auth
;
2095 struct netr_Authenticator rep_auth
;
2098 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
);
2099 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2102 struct tevent_req
*netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX
*mem_ctx
,
2103 struct tevent_context
*ev
,
2104 struct netlogon_creds_cli_context
*context
,
2105 struct dcerpc_binding_handle
*b
,
2106 enum netr_LogonInfoClass logon_level
,
2107 const union netr_LogonLevel
*logon
,
2110 struct tevent_req
*req
;
2111 struct netlogon_creds_cli_LogonSamLogon_state
*state
;
2113 req
= tevent_req_create(mem_ctx
, &state
,
2114 struct netlogon_creds_cli_LogonSamLogon_state
);
2120 state
->context
= context
;
2121 state
->binding_handle
= b
;
2123 state
->logon_level
= logon_level
;
2124 state
->const_logon
= logon
;
2125 state
->flags
= flags
;
2127 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2128 context
->server
.computer
);
2129 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2130 return tevent_req_post(req
, ev
);
2133 switch (logon_level
) {
2134 case NetlogonInteractiveInformation
:
2135 case NetlogonInteractiveTransitiveInformation
:
2136 case NetlogonServiceInformation
:
2137 case NetlogonServiceTransitiveInformation
:
2138 case NetlogonGenericInformation
:
2139 state
->user_encrypt
= true;
2142 case NetlogonNetworkInformation
:
2143 case NetlogonNetworkTransitiveInformation
:
2147 state
->validation
= talloc_zero(state
, union netr_Validation
);
2148 if (tevent_req_nomem(state
->validation
, req
)) {
2149 return tevent_req_post(req
, ev
);
2152 netlogon_creds_cli_LogonSamLogon_start(req
);
2153 if (!tevent_req_is_in_progress(req
)) {
2154 return tevent_req_post(req
, ev
);
2158 * we defer all callbacks in order to cleanup
2159 * the database record.
2161 tevent_req_defer_callback(req
, state
->ev
);
2165 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2168 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2169 tevent_req_data(req
,
2170 struct netlogon_creds_cli_LogonSamLogon_state
);
2172 if (state
->lk_creds
== NULL
) {
2176 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2178 * This is a hack to recover from a bug in old
2179 * Samba servers, when LogonSamLogonEx() fails:
2181 * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
2183 * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2185 * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE,
2186 * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR
2187 * If the sign/seal check fails.
2189 * In that case we need to cleanup the netlogon session.
2191 * It's the job of the caller to disconnect the current
2192 * connection, if netlogon_creds_cli_LogonSamLogon()
2193 * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2195 if (!state
->context
->server
.try_logon_with
) {
2196 status
= NT_STATUS_NETWORK_ACCESS_DENIED
;
2200 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2201 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2202 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2203 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2204 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2205 TALLOC_FREE(state
->lk_creds
);
2209 netlogon_creds_cli_delete(state
->context
, &state
->lk_creds
);
2212 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
);
2214 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
)
2216 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2217 tevent_req_data(req
,
2218 struct netlogon_creds_cli_LogonSamLogon_state
);
2219 struct tevent_req
*subreq
;
2221 enum dcerpc_AuthType auth_type
;
2222 enum dcerpc_AuthLevel auth_level
;
2224 TALLOC_FREE(state
->ro_creds
);
2225 TALLOC_FREE(state
->logon
);
2226 ZERO_STRUCTP(state
->validation
);
2228 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2229 &auth_type
, &auth_level
);
2231 state
->try_logon_ex
= state
->context
->server
.try_logon_ex
;
2232 state
->try_validation6
= state
->context
->server
.try_validation6
;
2234 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
2235 state
->try_logon_ex
= false;
2238 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
2239 state
->try_validation6
= false;
2242 if (state
->try_logon_ex
) {
2243 if (state
->try_validation6
) {
2244 state
->validation_level
= 6;
2246 state
->validation_level
= 3;
2247 state
->user_encrypt
= true;
2250 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2252 state
->const_logon
);
2253 if (tevent_req_nomem(state
->logon
, req
)) {
2254 status
= NT_STATUS_NO_MEMORY
;
2255 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2259 if (state
->user_encrypt
) {
2260 status
= netlogon_creds_cli_get(state
->context
,
2263 if (!NT_STATUS_IS_OK(status
)) {
2264 status
= NT_STATUS_ACCESS_DENIED
;
2265 tevent_req_nterror(req
, status
);
2266 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2270 netlogon_creds_encrypt_samlogon_logon(state
->ro_creds
,
2275 subreq
= dcerpc_netr_LogonSamLogonEx_send(state
, state
->ev
,
2276 state
->binding_handle
,
2277 state
->srv_name_slash
,
2278 state
->context
->client
.computer
,
2281 state
->validation_level
,
2283 &state
->authoritative
,
2285 if (tevent_req_nomem(subreq
, req
)) {
2286 status
= NT_STATUS_NO_MEMORY
;
2287 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2290 tevent_req_set_callback(subreq
,
2291 netlogon_creds_cli_LogonSamLogon_done
,
2296 if (state
->lk_creds
== NULL
) {
2297 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2299 if (tevent_req_nomem(subreq
, req
)) {
2300 status
= NT_STATUS_NO_MEMORY
;
2301 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2304 tevent_req_set_callback(subreq
,
2305 netlogon_creds_cli_LogonSamLogon_done
,
2310 state
->tmp_creds
= *state
->lk_creds
;
2311 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2313 ZERO_STRUCT(state
->rep_auth
);
2315 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2317 state
->const_logon
);
2318 if (tevent_req_nomem(state
->logon
, req
)) {
2319 status
= NT_STATUS_NO_MEMORY
;
2320 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2324 netlogon_creds_encrypt_samlogon_logon(state
->ro_creds
,
2328 state
->validation_level
= 3;
2330 if (state
->context
->server
.try_logon_with
) {
2331 subreq
= dcerpc_netr_LogonSamLogonWithFlags_send(state
, state
->ev
,
2332 state
->binding_handle
,
2333 state
->srv_name_slash
,
2334 state
->context
->client
.computer
,
2339 state
->validation_level
,
2341 &state
->authoritative
,
2343 if (tevent_req_nomem(subreq
, req
)) {
2344 status
= NT_STATUS_NO_MEMORY
;
2345 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2351 subreq
= dcerpc_netr_LogonSamLogon_send(state
, state
->ev
,
2352 state
->binding_handle
,
2353 state
->srv_name_slash
,
2354 state
->context
->client
.computer
,
2359 state
->validation_level
,
2361 &state
->authoritative
);
2362 if (tevent_req_nomem(subreq
, req
)) {
2363 status
= NT_STATUS_NO_MEMORY
;
2364 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2369 tevent_req_set_callback(subreq
,
2370 netlogon_creds_cli_LogonSamLogon_done
,
2374 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
)
2376 struct tevent_req
*req
=
2377 tevent_req_callback_data(subreq
,
2379 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2380 tevent_req_data(req
,
2381 struct netlogon_creds_cli_LogonSamLogon_state
);
2386 if (state
->try_logon_ex
) {
2387 status
= dcerpc_netr_LogonSamLogonEx_recv(subreq
,
2390 TALLOC_FREE(subreq
);
2391 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2392 state
->context
->server
.try_validation6
= false;
2393 state
->context
->server
.try_logon_ex
= false;
2394 netlogon_creds_cli_LogonSamLogon_start(req
);
2397 if (tevent_req_nterror(req
, status
)) {
2398 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2402 if ((state
->validation_level
== 6) &&
2403 (NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_INFO_CLASS
) ||
2404 NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_PARAMETER
) ||
2405 NT_STATUS_EQUAL(result
, NT_STATUS_BUFFER_TOO_SMALL
)))
2407 state
->context
->server
.try_validation6
= false;
2408 netlogon_creds_cli_LogonSamLogon_start(req
);
2412 if (tevent_req_nterror(req
, result
)) {
2413 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2417 if (state
->ro_creds
== NULL
) {
2418 tevent_req_done(req
);
2422 ok
= netlogon_creds_cli_validate(state
->context
, state
->ro_creds
);
2425 * We got a race, lets retry with on authenticator
2428 TALLOC_FREE(state
->ro_creds
);
2429 state
->try_logon_ex
= false;
2430 netlogon_creds_cli_LogonSamLogon_start(req
);
2434 netlogon_creds_decrypt_samlogon_validation(state
->ro_creds
,
2435 state
->validation_level
,
2438 tevent_req_done(req
);
2442 if (state
->lk_creds
== NULL
) {
2443 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2445 TALLOC_FREE(subreq
);
2446 if (tevent_req_nterror(req
, status
)) {
2447 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2451 netlogon_creds_cli_LogonSamLogon_start(req
);
2455 if (state
->context
->server
.try_logon_with
) {
2456 status
= dcerpc_netr_LogonSamLogonWithFlags_recv(subreq
,
2459 TALLOC_FREE(subreq
);
2460 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2461 state
->context
->server
.try_logon_with
= false;
2462 netlogon_creds_cli_LogonSamLogon_start(req
);
2465 if (tevent_req_nterror(req
, status
)) {
2466 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2470 status
= dcerpc_netr_LogonSamLogon_recv(subreq
,
2473 TALLOC_FREE(subreq
);
2474 if (tevent_req_nterror(req
, status
)) {
2475 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2480 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2481 &state
->rep_auth
.cred
);
2483 status
= NT_STATUS_ACCESS_DENIED
;
2484 tevent_req_nterror(req
, status
);
2485 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2489 *state
->lk_creds
= state
->tmp_creds
;
2490 status
= netlogon_creds_cli_store(state
->context
,
2492 if (tevent_req_nterror(req
, status
)) {
2493 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2497 if (tevent_req_nterror(req
, result
)) {
2498 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2502 netlogon_creds_decrypt_samlogon_validation(&state
->tmp_creds
,
2503 state
->validation_level
,
2506 tevent_req_done(req
);
2509 NTSTATUS
netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req
*req
,
2510 TALLOC_CTX
*mem_ctx
,
2511 uint16_t *validation_level
,
2512 union netr_Validation
**validation
,
2513 uint8_t *authoritative
,
2516 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2517 tevent_req_data(req
,
2518 struct netlogon_creds_cli_LogonSamLogon_state
);
2521 /* authoritative is also returned on error */
2522 *authoritative
= state
->authoritative
;
2524 if (tevent_req_is_nterror(req
, &status
)) {
2525 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2526 tevent_req_received(req
);
2530 *validation_level
= state
->validation_level
;
2531 *validation
= talloc_move(mem_ctx
, &state
->validation
);
2532 *flags
= state
->flags
;
2534 tevent_req_received(req
);
2535 return NT_STATUS_OK
;
2538 NTSTATUS
netlogon_creds_cli_LogonSamLogon(
2539 struct netlogon_creds_cli_context
*context
,
2540 struct dcerpc_binding_handle
*b
,
2541 enum netr_LogonInfoClass logon_level
,
2542 const union netr_LogonLevel
*logon
,
2543 TALLOC_CTX
*mem_ctx
,
2544 uint16_t *validation_level
,
2545 union netr_Validation
**validation
,
2546 uint8_t *authoritative
,
2549 TALLOC_CTX
*frame
= talloc_stackframe();
2550 struct tevent_context
*ev
;
2551 struct tevent_req
*req
;
2552 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2554 ev
= samba_tevent_context_init(frame
);
2558 req
= netlogon_creds_cli_LogonSamLogon_send(frame
, ev
, context
, b
,
2564 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2567 status
= netlogon_creds_cli_LogonSamLogon_recv(req
, mem_ctx
,