2 Unix SMB/CIFS implementation.
4 module to store/fetch session keys for the schannel client
6 Copyright (C) Stefan Metzmacher 2013
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "system/filesys.h"
25 #include "lib/util/tevent_ntstatus.h"
26 #include "lib/dbwrap/dbwrap.h"
27 #include "lib/dbwrap/dbwrap_rbt.h"
28 #include "lib/util/util_tdb.h"
29 #include "libcli/security/security.h"
30 #include "../lib/param/param.h"
31 #include "../libcli/auth/schannel.h"
32 #include "../librpc/gen_ndr/ndr_schannel.h"
33 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
34 #include "../librpc/gen_ndr/ndr_netlogon.h"
35 #include "../librpc/gen_ndr/server_id.h"
36 #include "netlogon_creds_cli.h"
37 #include "source3/include/messages.h"
38 #include "source3/include/g_lock.h"
39 #include "libds/common/roles.h"
40 #include "lib/crypto/crypto.h"
42 struct netlogon_creds_cli_locked_state
;
44 struct netlogon_creds_cli_context
{
48 uint32_t proposed_flags
;
49 uint32_t required_flags
;
50 enum netr_SchannelType type
;
51 enum dcerpc_AuthLevel auth_level
;
56 const char *netbios_domain
;
57 const char *dns_domain
;
58 uint32_t cached_flags
;
67 struct db_context
*ctx
;
68 struct g_lock_ctx
*g_ctx
;
69 struct netlogon_creds_cli_locked_state
*locked_state
;
73 struct netlogon_creds_cli_locked_state
{
74 struct netlogon_creds_cli_context
*context
;
76 struct netlogon_creds_CredentialState
*creds
;
79 static int netlogon_creds_cli_locked_state_destructor(
80 struct netlogon_creds_cli_locked_state
*state
)
82 struct netlogon_creds_cli_context
*context
= state
->context
;
84 if (context
== NULL
) {
88 if (context
->db
.locked_state
== state
) {
89 context
->db
.locked_state
= NULL
;
92 if (state
->is_glocked
) {
93 g_lock_unlock(context
->db
.g_ctx
,
94 context
->db
.key_name
);
100 static NTSTATUS
netlogon_creds_cli_context_common(
101 const char *client_computer
,
102 const char *client_account
,
103 enum netr_SchannelType type
,
104 enum dcerpc_AuthLevel auth_level
,
105 uint32_t proposed_flags
,
106 uint32_t required_flags
,
107 const char *server_computer
,
108 const char *server_netbios_domain
,
109 const char *server_dns_domain
,
111 struct netlogon_creds_cli_context
**_context
)
113 struct netlogon_creds_cli_context
*context
= NULL
;
114 char *_key_name
= NULL
;
115 size_t server_netbios_name_len
;
120 context
= talloc_zero(mem_ctx
, struct netlogon_creds_cli_context
);
121 if (context
== NULL
) {
122 return NT_STATUS_NO_MEMORY
;
125 context
->client
.computer
= talloc_strdup(context
, client_computer
);
126 if (context
->client
.computer
== NULL
) {
127 TALLOC_FREE(context
);
128 return NT_STATUS_NO_MEMORY
;
131 context
->client
.account
= talloc_strdup(context
, client_account
);
132 if (context
->client
.account
== NULL
) {
133 TALLOC_FREE(context
);
134 return NT_STATUS_NO_MEMORY
;
137 context
->client
.proposed_flags
= proposed_flags
;
138 context
->client
.required_flags
= required_flags
;
139 context
->client
.type
= type
;
140 context
->client
.auth_level
= auth_level
;
142 context
->server
.computer
= talloc_strdup(context
, server_computer
);
143 if (context
->server
.computer
== NULL
) {
144 TALLOC_FREE(context
);
145 return NT_STATUS_NO_MEMORY
;
148 context
->server
.netbios_domain
= talloc_strdup(context
, server_netbios_domain
);
149 if (context
->server
.netbios_domain
== NULL
) {
150 TALLOC_FREE(context
);
151 return NT_STATUS_NO_MEMORY
;
154 context
->server
.dns_domain
= talloc_strdup(context
, server_dns_domain
);
155 if (context
->server
.dns_domain
== NULL
) {
156 TALLOC_FREE(context
);
157 return NT_STATUS_NO_MEMORY
;
162 * Force the callers to provide a unique
163 * value for server_computer and use this directly.
165 * For now we have to deal with
166 * "HOSTNAME" vs. "hostname.example.com".
169 p
= strchr(server_computer
, '.');
171 server_netbios_name_len
= p
-server_computer
;
173 server_netbios_name_len
= strlen(server_computer
);
176 _key_name
= talloc_asprintf(context
, "CLI[%s/%s]/SRV[%.*s/%s]",
179 (int)server_netbios_name_len
,
181 server_netbios_domain
);
182 if (_key_name
== NULL
) {
183 TALLOC_FREE(context
);
184 return NT_STATUS_NO_MEMORY
;
187 context
->db
.key_name
= talloc_strdup_upper(context
, _key_name
);
188 TALLOC_FREE(_key_name
);
189 if (context
->db
.key_name
== NULL
) {
190 TALLOC_FREE(context
);
191 return NT_STATUS_NO_MEMORY
;
194 context
->db
.key_data
= string_term_tdb_data(context
->db
.key_name
);
200 static struct db_context
*netlogon_creds_cli_global_db
;
202 NTSTATUS
netlogon_creds_cli_set_global_db(struct db_context
**db
)
204 if (netlogon_creds_cli_global_db
!= NULL
) {
205 return NT_STATUS_INVALID_PARAMETER_MIX
;
208 netlogon_creds_cli_global_db
= talloc_move(NULL
, db
);
212 NTSTATUS
netlogon_creds_cli_open_global_db(struct loadparm_context
*lp_ctx
)
215 struct db_context
*global_db
;
217 if (netlogon_creds_cli_global_db
!= NULL
) {
221 fname
= lpcfg_private_db_path(NULL
, lp_ctx
, "netlogon_creds_cli");
223 return NT_STATUS_NO_MEMORY
;
226 global_db
= dbwrap_local_open(NULL
, lp_ctx
,
228 TDB_CLEAR_IF_FIRST
|TDB_INCOMPATIBLE_HASH
,
230 0600, DBWRAP_LOCK_ORDER_2
,
232 if (global_db
== NULL
) {
233 DEBUG(0,("netlogon_creds_cli_open_global_db: Failed to open %s - %s\n",
234 fname
, strerror(errno
)));
236 return NT_STATUS_NO_MEMORY
;
240 netlogon_creds_cli_global_db
= global_db
;
244 void netlogon_creds_cli_close_global_db(void)
246 TALLOC_FREE(netlogon_creds_cli_global_db
);
249 NTSTATUS
netlogon_creds_cli_context_global(struct loadparm_context
*lp_ctx
,
250 struct messaging_context
*msg_ctx
,
251 const char *client_account
,
252 enum netr_SchannelType type
,
253 const char *server_computer
,
254 const char *server_netbios_domain
,
255 const char *server_dns_domain
,
257 struct netlogon_creds_cli_context
**_context
)
259 TALLOC_CTX
*frame
= talloc_stackframe();
261 struct netlogon_creds_cli_context
*context
= NULL
;
262 const char *client_computer
;
263 uint32_t proposed_flags
;
264 uint32_t required_flags
= 0;
265 bool reject_md5_servers
= false;
266 bool require_strong_key
= false;
267 int require_sign_or_seal
= true;
268 bool seal_secure_channel
= true;
269 enum dcerpc_AuthLevel auth_level
= DCERPC_AUTH_LEVEL_NONE
;
270 bool neutralize_nt4_emulation
= false;
274 if (msg_ctx
== NULL
) {
276 return NT_STATUS_INVALID_PARAMETER_MIX
;
279 client_computer
= lpcfg_netbios_name(lp_ctx
);
280 if (strlen(client_computer
) > 15) {
282 return NT_STATUS_INVALID_PARAMETER_MIX
;
286 * allow overwrite per domain
287 * reject md5 servers:<netbios_domain>
289 reject_md5_servers
= lpcfg_reject_md5_servers(lp_ctx
);
290 reject_md5_servers
= lpcfg_parm_bool(lp_ctx
, NULL
,
291 "reject md5 servers",
292 server_netbios_domain
,
296 * allow overwrite per domain
297 * require strong key:<netbios_domain>
299 require_strong_key
= lpcfg_require_strong_key(lp_ctx
);
300 require_strong_key
= lpcfg_parm_bool(lp_ctx
, NULL
,
301 "require strong key",
302 server_netbios_domain
,
306 * allow overwrite per domain
307 * client schannel:<netbios_domain>
309 require_sign_or_seal
= lpcfg_client_schannel(lp_ctx
);
310 require_sign_or_seal
= lpcfg_parm_int(lp_ctx
, NULL
,
312 server_netbios_domain
,
313 require_sign_or_seal
);
316 * allow overwrite per domain
317 * winbind sealed pipes:<netbios_domain>
319 seal_secure_channel
= lpcfg_winbind_sealed_pipes(lp_ctx
);
320 seal_secure_channel
= lpcfg_parm_bool(lp_ctx
, NULL
,
321 "winbind sealed pipes",
322 server_netbios_domain
,
323 seal_secure_channel
);
326 * allow overwrite per domain
327 * neutralize nt4 emulation:<netbios_domain>
329 neutralize_nt4_emulation
= lpcfg_neutralize_nt4_emulation(lp_ctx
);
330 neutralize_nt4_emulation
= lpcfg_parm_bool(lp_ctx
, NULL
,
331 "neutralize nt4 emulation",
332 server_netbios_domain
,
333 neutralize_nt4_emulation
);
335 proposed_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
336 proposed_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
340 if (lpcfg_security(lp_ctx
) == SEC_ADS
) {
342 * AD domains should be secure
344 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
345 require_sign_or_seal
= true;
346 require_strong_key
= true;
350 case SEC_CHAN_DOMAIN
:
353 case SEC_CHAN_DNS_DOMAIN
:
355 * AD domains should be secure
357 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
358 require_sign_or_seal
= true;
359 require_strong_key
= true;
360 neutralize_nt4_emulation
= true;
364 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
365 require_sign_or_seal
= true;
366 require_strong_key
= true;
370 required_flags
|= NETLOGON_NEG_RODC_PASSTHROUGH
;
371 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
372 require_sign_or_seal
= true;
373 require_strong_key
= true;
374 neutralize_nt4_emulation
= true;
379 return NT_STATUS_INVALID_PARAMETER
;
382 if (neutralize_nt4_emulation
) {
383 proposed_flags
|= NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION
;
386 if (require_sign_or_seal
) {
387 required_flags
|= NETLOGON_NEG_ARCFOUR
;
388 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
390 proposed_flags
&= ~NETLOGON_NEG_AUTHENTICATED_RPC
;
393 if (reject_md5_servers
) {
394 required_flags
|= NETLOGON_NEG_ARCFOUR
;
395 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
396 required_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
397 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
400 if (require_strong_key
) {
401 required_flags
|= NETLOGON_NEG_ARCFOUR
;
402 required_flags
|= NETLOGON_NEG_STRONG_KEYS
;
403 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
406 proposed_flags
|= required_flags
;
408 if (seal_secure_channel
) {
409 auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
411 auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
414 status
= netlogon_creds_cli_context_common(client_computer
,
421 server_netbios_domain
,
425 if (!NT_STATUS_IS_OK(status
)) {
430 context
->db
.g_ctx
= g_lock_ctx_init(context
, msg_ctx
);
431 if (context
->db
.g_ctx
== NULL
) {
432 TALLOC_FREE(context
);
434 return NT_STATUS_NO_MEMORY
;
437 status
= netlogon_creds_cli_open_global_db(lp_ctx
);
438 if (!NT_STATUS_IS_OK(status
)) {
439 TALLOC_FREE(context
);
441 return NT_STATUS_NO_MEMORY
;
444 context
->db
.ctx
= netlogon_creds_cli_global_db
;
450 char *netlogon_creds_cli_debug_string(
451 const struct netlogon_creds_cli_context
*context
,
454 return talloc_asprintf(mem_ctx
, "netlogon_creds_cli:%s",
455 context
->db
.key_name
);
458 enum dcerpc_AuthLevel
netlogon_creds_cli_auth_level(
459 struct netlogon_creds_cli_context
*context
)
461 return context
->client
.auth_level
;
464 struct netlogon_creds_cli_fetch_state
{
466 struct netlogon_creds_CredentialState
*creds
;
467 uint32_t required_flags
;
471 static void netlogon_creds_cli_fetch_parser(TDB_DATA key
, TDB_DATA data
,
474 struct netlogon_creds_cli_fetch_state
*state
=
475 (struct netlogon_creds_cli_fetch_state
*)private_data
;
476 enum ndr_err_code ndr_err
;
480 state
->creds
= talloc_zero(state
->mem_ctx
,
481 struct netlogon_creds_CredentialState
);
482 if (state
->creds
== NULL
) {
483 state
->status
= NT_STATUS_NO_MEMORY
;
487 blob
.data
= data
.dptr
;
488 blob
.length
= data
.dsize
;
490 ndr_err
= ndr_pull_struct_blob(&blob
, state
->creds
, state
->creds
,
491 (ndr_pull_flags_fn_t
)ndr_pull_netlogon_creds_CredentialState
);
492 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
493 TALLOC_FREE(state
->creds
);
494 state
->status
= ndr_map_error2ntstatus(ndr_err
);
498 tmp_flags
= state
->creds
->negotiate_flags
;
499 tmp_flags
&= state
->required_flags
;
500 if (tmp_flags
!= state
->required_flags
) {
501 TALLOC_FREE(state
->creds
);
502 state
->status
= NT_STATUS_DOWNGRADE_DETECTED
;
506 state
->status
= NT_STATUS_OK
;
509 NTSTATUS
netlogon_creds_cli_get(struct netlogon_creds_cli_context
*context
,
511 struct netlogon_creds_CredentialState
**_creds
)
514 struct netlogon_creds_cli_fetch_state fstate
= {
516 .status
= NT_STATUS_INTERNAL_ERROR
,
517 .required_flags
= context
->client
.required_flags
,
522 status
= dbwrap_parse_record(context
->db
.ctx
,
523 context
->db
.key_data
,
524 netlogon_creds_cli_fetch_parser
,
526 if (!NT_STATUS_IS_OK(status
)) {
529 status
= fstate
.status
;
530 if (!NT_STATUS_IS_OK(status
)) {
535 * mark it as invalid for step operations.
537 fstate
.creds
->sequence
= 0;
538 fstate
.creds
->seed
= (struct netr_Credential
) {{0}};
539 fstate
.creds
->client
= (struct netr_Credential
) {{0}};
540 fstate
.creds
->server
= (struct netr_Credential
) {{0}};
542 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
543 *_creds
= fstate
.creds
;
548 * It is really important to try SamLogonEx here,
549 * because multiple processes can talk to the same
550 * domain controller, without using the credential
553 * With a normal SamLogon call, we must keep the
554 * credentials chain updated and intact between all
555 * users of the machine account (which would imply
556 * cross-node communication for every NTLM logon).
558 * The credentials chain is not per NETLOGON pipe
559 * connection, but globally on the server/client pair
562 * It's also important to use NetlogonValidationSamInfo4 (6),
563 * because it relies on the rpc transport encryption
564 * and avoids using the global netlogon schannel
565 * session key to en/decrypt secret information
566 * like the user_session_key for network logons.
568 * [MS-APDS] 3.1.5.2 NTLM Network Logon
569 * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and
570 * NETLOGON_NEG_AUTHENTICATED_RPC set together
571 * are the indication that the server supports
572 * NetlogonValidationSamInfo4 (6). And it must only
573 * be used if "SealSecureChannel" is used.
575 * The "SealSecureChannel" AUTH_TYPE_SCHANNEL/AUTH_LEVEL_PRIVACY
576 * check is done in netlogon_creds_cli_LogonSamLogon*().
578 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
579 context
->server
.try_validation6
= true;
580 context
->server
.try_logon_ex
= true;
581 context
->server
.try_logon_with
= true;
583 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
584 context
->server
.try_validation6
= false;
585 context
->server
.try_logon_ex
= false;
587 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
588 context
->server
.try_validation6
= false;
591 *_creds
= fstate
.creds
;
595 bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context
*context
,
596 const struct netlogon_creds_CredentialState
*creds1
)
598 TALLOC_CTX
*frame
= talloc_stackframe();
599 struct netlogon_creds_CredentialState
*creds2
;
603 enum ndr_err_code ndr_err
;
606 status
= netlogon_creds_cli_get(context
, frame
, &creds2
);
607 if (!NT_STATUS_IS_OK(status
)) {
612 ndr_err
= ndr_push_struct_blob(&blob1
, frame
, creds1
,
613 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
614 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
619 ndr_err
= ndr_push_struct_blob(&blob2
, frame
, creds2
,
620 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
621 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
626 cmp
= data_blob_cmp(&blob1
, &blob2
);
633 NTSTATUS
netlogon_creds_cli_store(struct netlogon_creds_cli_context
*context
,
634 struct netlogon_creds_CredentialState
*creds
)
637 enum ndr_err_code ndr_err
;
641 if (context
->db
.locked_state
== NULL
) {
643 * this was not the result of netlogon_creds_cli_lock*()
645 return NT_STATUS_INVALID_PAGE_PROTECTION
;
648 if (context
->db
.locked_state
->creds
!= creds
) {
650 * this was not the result of netlogon_creds_cli_lock*()
652 return NT_STATUS_INVALID_PAGE_PROTECTION
;
655 ndr_err
= ndr_push_struct_blob(&blob
, creds
, creds
,
656 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
657 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
658 status
= ndr_map_error2ntstatus(ndr_err
);
662 data
.dptr
= blob
.data
;
663 data
.dsize
= blob
.length
;
665 status
= dbwrap_store(context
->db
.ctx
,
666 context
->db
.key_data
,
668 TALLOC_FREE(data
.dptr
);
669 if (!NT_STATUS_IS_OK(status
)) {
676 NTSTATUS
netlogon_creds_cli_delete(struct netlogon_creds_cli_context
*context
,
677 struct netlogon_creds_CredentialState
*creds
)
681 if (context
->db
.locked_state
== NULL
) {
683 * this was not the result of netlogon_creds_cli_lock*()
685 return NT_STATUS_INVALID_PAGE_PROTECTION
;
688 if (context
->db
.locked_state
->creds
!= creds
) {
690 * this was not the result of netlogon_creds_cli_lock*()
692 return NT_STATUS_INVALID_PAGE_PROTECTION
;
695 status
= dbwrap_delete(context
->db
.ctx
,
696 context
->db
.key_data
);
697 if (!NT_STATUS_IS_OK(status
)) {
704 struct netlogon_creds_cli_lock_state
{
705 struct netlogon_creds_cli_locked_state
*locked_state
;
706 struct netlogon_creds_CredentialState
*creds
;
709 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
);
710 static NTSTATUS
netlogon_creds_cli_lock_fetch(
711 struct netlogon_creds_cli_context
*context
,
712 TALLOC_CTX
*mem_ctx
, struct netlogon_creds_CredentialState
**pcreds
);
714 struct tevent_req
*netlogon_creds_cli_lock_send(TALLOC_CTX
*mem_ctx
,
715 struct tevent_context
*ev
,
716 struct netlogon_creds_cli_context
*context
)
718 struct tevent_req
*req
;
719 struct netlogon_creds_cli_lock_state
*state
;
720 struct netlogon_creds_cli_locked_state
*locked_state
;
721 struct tevent_req
*subreq
;
723 req
= tevent_req_create(mem_ctx
, &state
,
724 struct netlogon_creds_cli_lock_state
);
729 if (context
->db
.locked_state
!= NULL
) {
730 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
731 return tevent_req_post(req
, ev
);
734 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
735 if (tevent_req_nomem(locked_state
, req
)) {
736 return tevent_req_post(req
, ev
);
738 talloc_set_destructor(locked_state
,
739 netlogon_creds_cli_locked_state_destructor
);
740 locked_state
->context
= context
;
742 context
->db
.locked_state
= locked_state
;
743 state
->locked_state
= locked_state
;
745 if (context
->db
.g_ctx
== NULL
) {
748 status
= netlogon_creds_cli_lock_fetch(
749 context
, state
, &state
->creds
);
750 if (tevent_req_nterror(req
, status
)) {
751 return tevent_req_post(req
, ev
);
757 subreq
= g_lock_lock_send(state
, ev
,
759 context
->db
.key_name
,
761 if (tevent_req_nomem(subreq
, req
)) {
762 return tevent_req_post(req
, ev
);
764 tevent_req_set_callback(subreq
, netlogon_creds_cli_lock_done
, req
);
769 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
)
771 struct tevent_req
*req
=
772 tevent_req_callback_data(subreq
,
774 struct netlogon_creds_cli_lock_state
*state
=
776 struct netlogon_creds_cli_lock_state
);
779 status
= g_lock_lock_recv(subreq
);
781 if (tevent_req_nterror(req
, status
)) {
784 state
->locked_state
->is_glocked
= true;
786 status
= netlogon_creds_cli_lock_fetch(state
->locked_state
->context
,
787 state
, &state
->creds
);
788 if (tevent_req_nterror(req
, status
)) {
791 tevent_req_done(req
);
794 static NTSTATUS
netlogon_creds_cli_lock_fetch(
795 struct netlogon_creds_cli_context
*context
,
796 TALLOC_CTX
*mem_ctx
, struct netlogon_creds_CredentialState
**pcreds
)
798 struct netlogon_creds_cli_fetch_state fstate
= {
799 .status
= NT_STATUS_INTERNAL_ERROR
,
800 .required_flags
= context
->client
.required_flags
,
804 fstate
.mem_ctx
= mem_ctx
;
805 status
= dbwrap_parse_record(context
->db
.ctx
,
806 context
->db
.key_data
,
807 netlogon_creds_cli_fetch_parser
,
809 if (!NT_STATUS_IS_OK(status
)) {
812 if (!NT_STATUS_IS_OK(fstate
.status
)) {
813 return fstate
.status
;
816 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
817 *pcreds
= fstate
.creds
;
821 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
822 context
->server
.try_validation6
= true;
823 context
->server
.try_logon_ex
= true;
824 context
->server
.try_logon_with
= true;
826 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
827 context
->server
.try_validation6
= false;
828 context
->server
.try_logon_ex
= false;
830 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
831 context
->server
.try_validation6
= false;
834 *pcreds
= fstate
.creds
;
838 NTSTATUS
netlogon_creds_cli_lock_recv(struct tevent_req
*req
,
840 struct netlogon_creds_CredentialState
**creds
)
842 struct netlogon_creds_cli_lock_state
*state
=
844 struct netlogon_creds_cli_lock_state
);
847 if (tevent_req_is_nterror(req
, &status
)) {
848 tevent_req_received(req
);
852 talloc_steal(state
->creds
, state
->locked_state
);
853 state
->locked_state
->creds
= state
->creds
;
854 *creds
= talloc_move(mem_ctx
, &state
->creds
);
855 tevent_req_received(req
);
859 NTSTATUS
netlogon_creds_cli_lock(struct netlogon_creds_cli_context
*context
,
861 struct netlogon_creds_CredentialState
**creds
)
863 TALLOC_CTX
*frame
= talloc_stackframe();
864 struct tevent_context
*ev
;
865 struct tevent_req
*req
;
866 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
868 ev
= samba_tevent_context_init(frame
);
872 req
= netlogon_creds_cli_lock_send(frame
, ev
, context
);
876 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
879 status
= netlogon_creds_cli_lock_recv(req
, mem_ctx
, creds
);
885 struct netlogon_creds_cli_auth_state
{
886 struct tevent_context
*ev
;
887 struct netlogon_creds_cli_context
*context
;
888 struct dcerpc_binding_handle
*binding_handle
;
889 uint8_t num_nt_hashes
;
890 uint8_t idx_nt_hashes
;
891 const struct samr_Password
* const *nt_hashes
;
892 const struct samr_Password
*used_nt_hash
;
893 char *srv_name_slash
;
894 uint32_t current_flags
;
895 struct netr_Credential client_challenge
;
896 struct netr_Credential server_challenge
;
897 struct netlogon_creds_CredentialState
*creds
;
898 struct netr_Credential client_credential
;
899 struct netr_Credential server_credential
;
904 struct netlogon_creds_cli_locked_state
*locked_state
;
907 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
);
908 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
);
910 struct tevent_req
*netlogon_creds_cli_auth_send(TALLOC_CTX
*mem_ctx
,
911 struct tevent_context
*ev
,
912 struct netlogon_creds_cli_context
*context
,
913 struct dcerpc_binding_handle
*b
,
914 uint8_t num_nt_hashes
,
915 const struct samr_Password
* const *nt_hashes
)
917 struct tevent_req
*req
;
918 struct netlogon_creds_cli_auth_state
*state
;
919 struct netlogon_creds_cli_locked_state
*locked_state
;
922 req
= tevent_req_create(mem_ctx
, &state
,
923 struct netlogon_creds_cli_auth_state
);
929 state
->context
= context
;
930 state
->binding_handle
= b
;
931 if (num_nt_hashes
< 1) {
932 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
933 return tevent_req_post(req
, ev
);
935 if (num_nt_hashes
> 4) {
936 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
937 return tevent_req_post(req
, ev
);
940 state
->num_nt_hashes
= num_nt_hashes
;
941 state
->idx_nt_hashes
= 0;
942 state
->nt_hashes
= nt_hashes
;
944 if (context
->db
.locked_state
!= NULL
) {
945 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
946 return tevent_req_post(req
, ev
);
949 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
950 if (tevent_req_nomem(locked_state
, req
)) {
951 return tevent_req_post(req
, ev
);
953 talloc_set_destructor(locked_state
,
954 netlogon_creds_cli_locked_state_destructor
);
955 locked_state
->context
= context
;
957 context
->db
.locked_state
= locked_state
;
958 state
->locked_state
= locked_state
;
960 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
961 context
->server
.computer
);
962 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
963 return tevent_req_post(req
, ev
);
966 state
->try_auth3
= true;
967 state
->try_auth2
= true;
969 if (context
->client
.required_flags
!= 0) {
970 state
->require_auth2
= true;
973 state
->used_nt_hash
= state
->nt_hashes
[state
->idx_nt_hashes
];
974 state
->current_flags
= context
->client
.proposed_flags
;
976 if (context
->db
.g_ctx
!= NULL
) {
977 struct tevent_req
*subreq
;
979 subreq
= g_lock_lock_send(state
, ev
,
981 context
->db
.key_name
,
983 if (tevent_req_nomem(subreq
, req
)) {
984 return tevent_req_post(req
, ev
);
986 tevent_req_set_callback(subreq
,
987 netlogon_creds_cli_auth_locked
,
993 status
= dbwrap_purge(state
->context
->db
.ctx
,
994 state
->context
->db
.key_data
);
995 if (tevent_req_nterror(req
, status
)) {
996 return tevent_req_post(req
, ev
);
999 netlogon_creds_cli_auth_challenge_start(req
);
1000 if (!tevent_req_is_in_progress(req
)) {
1001 return tevent_req_post(req
, ev
);
1007 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
)
1009 struct tevent_req
*req
=
1010 tevent_req_callback_data(subreq
,
1012 struct netlogon_creds_cli_auth_state
*state
=
1013 tevent_req_data(req
,
1014 struct netlogon_creds_cli_auth_state
);
1017 status
= g_lock_lock_recv(subreq
);
1018 TALLOC_FREE(subreq
);
1019 if (tevent_req_nterror(req
, status
)) {
1022 state
->locked_state
->is_glocked
= true;
1024 status
= dbwrap_purge(state
->context
->db
.ctx
,
1025 state
->context
->db
.key_data
);
1026 if (tevent_req_nterror(req
, status
)) {
1030 netlogon_creds_cli_auth_challenge_start(req
);
1033 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
);
1035 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
)
1037 struct netlogon_creds_cli_auth_state
*state
=
1038 tevent_req_data(req
,
1039 struct netlogon_creds_cli_auth_state
);
1040 struct tevent_req
*subreq
;
1042 TALLOC_FREE(state
->creds
);
1044 generate_random_buffer(state
->client_challenge
.data
,
1045 sizeof(state
->client_challenge
.data
));
1047 subreq
= dcerpc_netr_ServerReqChallenge_send(state
, state
->ev
,
1048 state
->binding_handle
,
1049 state
->srv_name_slash
,
1050 state
->context
->client
.computer
,
1051 &state
->client_challenge
,
1052 &state
->server_challenge
);
1053 if (tevent_req_nomem(subreq
, req
)) {
1056 tevent_req_set_callback(subreq
,
1057 netlogon_creds_cli_auth_challenge_done
,
1061 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
);
1063 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
)
1065 struct tevent_req
*req
=
1066 tevent_req_callback_data(subreq
,
1068 struct netlogon_creds_cli_auth_state
*state
=
1069 tevent_req_data(req
,
1070 struct netlogon_creds_cli_auth_state
);
1074 status
= dcerpc_netr_ServerReqChallenge_recv(subreq
, state
, &result
);
1075 TALLOC_FREE(subreq
);
1076 if (tevent_req_nterror(req
, status
)) {
1079 if (tevent_req_nterror(req
, result
)) {
1083 if (!state
->try_auth3
&& !state
->try_auth2
) {
1084 state
->current_flags
= 0;
1087 /* Calculate the session key and client credentials */
1089 state
->creds
= netlogon_creds_client_init(state
,
1090 state
->context
->client
.account
,
1091 state
->context
->client
.computer
,
1092 state
->context
->client
.type
,
1093 &state
->client_challenge
,
1094 &state
->server_challenge
,
1095 state
->used_nt_hash
,
1096 &state
->client_credential
,
1097 state
->current_flags
);
1098 if (tevent_req_nomem(state
->creds
, req
)) {
1102 if (state
->try_auth3
) {
1103 subreq
= dcerpc_netr_ServerAuthenticate3_send(state
, state
->ev
,
1104 state
->binding_handle
,
1105 state
->srv_name_slash
,
1106 state
->context
->client
.account
,
1107 state
->context
->client
.type
,
1108 state
->context
->client
.computer
,
1109 &state
->client_credential
,
1110 &state
->server_credential
,
1111 &state
->creds
->negotiate_flags
,
1113 if (tevent_req_nomem(subreq
, req
)) {
1116 } else if (state
->try_auth2
) {
1119 subreq
= dcerpc_netr_ServerAuthenticate2_send(state
, state
->ev
,
1120 state
->binding_handle
,
1121 state
->srv_name_slash
,
1122 state
->context
->client
.account
,
1123 state
->context
->client
.type
,
1124 state
->context
->client
.computer
,
1125 &state
->client_credential
,
1126 &state
->server_credential
,
1127 &state
->creds
->negotiate_flags
);
1128 if (tevent_req_nomem(subreq
, req
)) {
1134 subreq
= dcerpc_netr_ServerAuthenticate_send(state
, state
->ev
,
1135 state
->binding_handle
,
1136 state
->srv_name_slash
,
1137 state
->context
->client
.account
,
1138 state
->context
->client
.type
,
1139 state
->context
->client
.computer
,
1140 &state
->client_credential
,
1141 &state
->server_credential
);
1142 if (tevent_req_nomem(subreq
, req
)) {
1146 tevent_req_set_callback(subreq
,
1147 netlogon_creds_cli_auth_srvauth_done
,
1151 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
)
1153 struct tevent_req
*req
=
1154 tevent_req_callback_data(subreq
,
1156 struct netlogon_creds_cli_auth_state
*state
=
1157 tevent_req_data(req
,
1158 struct netlogon_creds_cli_auth_state
);
1162 enum ndr_err_code ndr_err
;
1167 if (state
->try_auth3
) {
1168 status
= dcerpc_netr_ServerAuthenticate3_recv(subreq
, state
,
1170 TALLOC_FREE(subreq
);
1171 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1172 state
->try_auth3
= false;
1173 netlogon_creds_cli_auth_challenge_start(req
);
1176 if (tevent_req_nterror(req
, status
)) {
1179 } else if (state
->try_auth2
) {
1180 status
= dcerpc_netr_ServerAuthenticate2_recv(subreq
, state
,
1182 TALLOC_FREE(subreq
);
1183 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1184 state
->try_auth2
= false;
1185 if (state
->require_auth2
) {
1186 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1187 tevent_req_nterror(req
, status
);
1190 netlogon_creds_cli_auth_challenge_start(req
);
1193 if (tevent_req_nterror(req
, status
)) {
1197 status
= dcerpc_netr_ServerAuthenticate_recv(subreq
, state
,
1199 TALLOC_FREE(subreq
);
1200 if (tevent_req_nterror(req
, status
)) {
1205 if (!NT_STATUS_IS_OK(result
) &&
1206 !NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
))
1208 tevent_req_nterror(req
, result
);
1212 tmp_flags
= state
->creds
->negotiate_flags
;
1213 tmp_flags
&= state
->context
->client
.required_flags
;
1214 if (tmp_flags
!= state
->context
->client
.required_flags
) {
1215 if (NT_STATUS_IS_OK(result
)) {
1216 tevent_req_nterror(req
, NT_STATUS_DOWNGRADE_DETECTED
);
1219 tevent_req_nterror(req
, result
);
1223 if (NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
)) {
1225 tmp_flags
= state
->context
->client
.proposed_flags
;
1226 if ((state
->current_flags
== tmp_flags
) &&
1227 (state
->creds
->negotiate_flags
!= tmp_flags
))
1230 * lets retry with the negotiated flags
1232 state
->current_flags
= state
->creds
->negotiate_flags
;
1233 netlogon_creds_cli_auth_challenge_start(req
);
1237 state
->idx_nt_hashes
+= 1;
1238 if (state
->idx_nt_hashes
>= state
->num_nt_hashes
) {
1240 * we already retried, giving up...
1242 tevent_req_nterror(req
, result
);
1247 * lets retry with the old nt hash.
1249 state
->used_nt_hash
= state
->nt_hashes
[state
->idx_nt_hashes
];
1250 state
->current_flags
= state
->context
->client
.proposed_flags
;
1251 netlogon_creds_cli_auth_challenge_start(req
);
1255 ok
= netlogon_creds_client_check(state
->creds
,
1256 &state
->server_credential
);
1258 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1262 ndr_err
= ndr_push_struct_blob(&blob
, state
, state
->creds
,
1263 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
1264 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1265 status
= ndr_map_error2ntstatus(ndr_err
);
1266 tevent_req_nterror(req
, status
);
1270 data
.dptr
= blob
.data
;
1271 data
.dsize
= blob
.length
;
1273 status
= dbwrap_store(state
->context
->db
.ctx
,
1274 state
->context
->db
.key_data
,
1276 TALLOC_FREE(state
->locked_state
);
1277 if (tevent_req_nterror(req
, status
)) {
1281 tevent_req_done(req
);
1284 NTSTATUS
netlogon_creds_cli_auth_recv(struct tevent_req
*req
,
1285 uint8_t *idx_nt_hashes
)
1287 struct netlogon_creds_cli_auth_state
*state
=
1288 tevent_req_data(req
,
1289 struct netlogon_creds_cli_auth_state
);
1294 if (tevent_req_is_nterror(req
, &status
)) {
1295 tevent_req_received(req
);
1299 *idx_nt_hashes
= state
->idx_nt_hashes
;
1300 tevent_req_received(req
);
1301 return NT_STATUS_OK
;
1304 NTSTATUS
netlogon_creds_cli_auth(struct netlogon_creds_cli_context
*context
,
1305 struct dcerpc_binding_handle
*b
,
1306 uint8_t num_nt_hashes
,
1307 const struct samr_Password
* const *nt_hashes
,
1308 uint8_t *idx_nt_hashes
)
1310 TALLOC_CTX
*frame
= talloc_stackframe();
1311 struct tevent_context
*ev
;
1312 struct tevent_req
*req
;
1313 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1317 ev
= samba_tevent_context_init(frame
);
1321 req
= netlogon_creds_cli_auth_send(frame
, ev
, context
, b
,
1322 num_nt_hashes
, nt_hashes
);
1326 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1329 status
= netlogon_creds_cli_auth_recv(req
, idx_nt_hashes
);
1335 struct netlogon_creds_cli_check_state
{
1336 struct tevent_context
*ev
;
1337 struct netlogon_creds_cli_context
*context
;
1338 struct dcerpc_binding_handle
*binding_handle
;
1340 char *srv_name_slash
;
1342 union netr_Capabilities caps
;
1344 struct netlogon_creds_CredentialState
*creds
;
1345 struct netlogon_creds_CredentialState tmp_creds
;
1346 struct netr_Authenticator req_auth
;
1347 struct netr_Authenticator rep_auth
;
1350 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1352 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
);
1354 struct tevent_req
*netlogon_creds_cli_check_send(TALLOC_CTX
*mem_ctx
,
1355 struct tevent_context
*ev
,
1356 struct netlogon_creds_cli_context
*context
,
1357 struct dcerpc_binding_handle
*b
)
1359 struct tevent_req
*req
;
1360 struct netlogon_creds_cli_check_state
*state
;
1361 struct tevent_req
*subreq
;
1362 enum dcerpc_AuthType auth_type
;
1363 enum dcerpc_AuthLevel auth_level
;
1365 req
= tevent_req_create(mem_ctx
, &state
,
1366 struct netlogon_creds_cli_check_state
);
1372 state
->context
= context
;
1373 state
->binding_handle
= b
;
1375 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1376 context
->server
.computer
);
1377 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1378 return tevent_req_post(req
, ev
);
1381 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1382 &auth_type
, &auth_level
);
1384 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
1385 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1386 return tevent_req_post(req
, ev
);
1389 switch (auth_level
) {
1390 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1391 case DCERPC_AUTH_LEVEL_PRIVACY
:
1394 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1395 return tevent_req_post(req
, ev
);
1398 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1400 if (tevent_req_nomem(subreq
, req
)) {
1401 return tevent_req_post(req
, ev
);
1404 tevent_req_set_callback(subreq
,
1405 netlogon_creds_cli_check_locked
,
1411 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1414 struct netlogon_creds_cli_check_state
*state
=
1415 tevent_req_data(req
,
1416 struct netlogon_creds_cli_check_state
);
1418 if (state
->creds
== NULL
) {
1422 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1423 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1424 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1425 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1426 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1427 TALLOC_FREE(state
->creds
);
1431 netlogon_creds_cli_delete(state
->context
, state
->creds
);
1432 TALLOC_FREE(state
->creds
);
1435 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
);
1437 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
)
1439 struct tevent_req
*req
=
1440 tevent_req_callback_data(subreq
,
1442 struct netlogon_creds_cli_check_state
*state
=
1443 tevent_req_data(req
,
1444 struct netlogon_creds_cli_check_state
);
1447 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1449 TALLOC_FREE(subreq
);
1450 if (tevent_req_nterror(req
, status
)) {
1455 * we defer all callbacks in order to cleanup
1456 * the database record.
1458 tevent_req_defer_callback(req
, state
->ev
);
1460 state
->tmp_creds
= *state
->creds
;
1461 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1463 ZERO_STRUCT(state
->rep_auth
);
1465 subreq
= dcerpc_netr_LogonGetCapabilities_send(state
, state
->ev
,
1466 state
->binding_handle
,
1467 state
->srv_name_slash
,
1468 state
->context
->client
.computer
,
1473 if (tevent_req_nomem(subreq
, req
)) {
1474 status
= NT_STATUS_NO_MEMORY
;
1475 netlogon_creds_cli_check_cleanup(req
, status
);
1478 tevent_req_set_callback(subreq
,
1479 netlogon_creds_cli_check_caps
,
1483 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
)
1485 struct tevent_req
*req
=
1486 tevent_req_callback_data(subreq
,
1488 struct netlogon_creds_cli_check_state
*state
=
1489 tevent_req_data(req
,
1490 struct netlogon_creds_cli_check_state
);
1495 status
= dcerpc_netr_LogonGetCapabilities_recv(subreq
, state
,
1497 TALLOC_FREE(subreq
);
1498 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1500 * Note that the negotiated flags are already checked
1501 * for our required flags after the ServerAuthenticate3/2 call.
1503 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1505 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1507 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1508 * already, we expect this to work!
1510 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1511 tevent_req_nterror(req
, status
);
1512 netlogon_creds_cli_check_cleanup(req
, status
);
1516 if (negotiated
& NETLOGON_NEG_STRONG_KEYS
) {
1518 * If we have negotiated NETLOGON_NEG_STRONG_KEYS
1519 * we expect this to work at least as far as the
1520 * NOT_SUPPORTED error handled below!
1522 * NT 4.0 and Old Samba servers are not
1523 * allowed without "require strong key = no"
1525 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1526 tevent_req_nterror(req
, status
);
1527 netlogon_creds_cli_check_cleanup(req
, status
);
1532 * If we not require NETLOGON_NEG_SUPPORTS_AES or
1533 * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore
1534 * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
1536 * This is needed against NT 4.0 and old Samba servers.
1538 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
1539 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
1540 * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
1541 * with the next request as the sequence number processing
1544 netlogon_creds_cli_check_cleanup(req
, status
);
1545 tevent_req_done(req
);
1548 if (tevent_req_nterror(req
, status
)) {
1549 netlogon_creds_cli_check_cleanup(req
, status
);
1553 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOT_IMPLEMENTED
)) {
1555 * Note that the negotiated flags are already checked
1556 * for our required flags after the ServerAuthenticate3/2 call.
1558 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1560 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1562 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1563 * already, we expect this to work!
1565 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1566 tevent_req_nterror(req
, status
);
1567 netlogon_creds_cli_check_cleanup(req
, status
);
1572 * This is ok, the server does not support
1573 * NETLOGON_NEG_SUPPORTS_AES.
1575 * netr_LogonGetCapabilities() was
1576 * netr_LogonDummyRoutine1() before
1577 * NETLOGON_NEG_SUPPORTS_AES was invented.
1579 netlogon_creds_cli_check_cleanup(req
, result
);
1580 tevent_req_done(req
);
1584 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1585 &state
->rep_auth
.cred
);
1587 status
= NT_STATUS_ACCESS_DENIED
;
1588 tevent_req_nterror(req
, status
);
1589 netlogon_creds_cli_check_cleanup(req
, status
);
1593 if (tevent_req_nterror(req
, result
)) {
1594 netlogon_creds_cli_check_cleanup(req
, result
);
1598 if (state
->caps
.server_capabilities
!= state
->tmp_creds
.negotiate_flags
) {
1599 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1600 tevent_req_nterror(req
, status
);
1601 netlogon_creds_cli_check_cleanup(req
, status
);
1606 * This is the key check that makes this check secure. If we
1607 * get OK here (rather than NOT_SUPPORTED), then the server
1608 * did support AES. If the server only proposed STRONG_KEYS
1609 * and not AES, then it should have failed with
1610 * NOT_IMPLEMENTED. We always send AES as a client, so the
1611 * server should always have returned it.
1613 if (!(state
->caps
.server_capabilities
& NETLOGON_NEG_SUPPORTS_AES
)) {
1614 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1615 tevent_req_nterror(req
, status
);
1616 netlogon_creds_cli_check_cleanup(req
, status
);
1620 *state
->creds
= state
->tmp_creds
;
1621 status
= netlogon_creds_cli_store(state
->context
,
1623 TALLOC_FREE(state
->creds
);
1624 if (tevent_req_nterror(req
, status
)) {
1628 tevent_req_done(req
);
1631 NTSTATUS
netlogon_creds_cli_check_recv(struct tevent_req
*req
)
1635 if (tevent_req_is_nterror(req
, &status
)) {
1636 netlogon_creds_cli_check_cleanup(req
, status
);
1637 tevent_req_received(req
);
1641 tevent_req_received(req
);
1642 return NT_STATUS_OK
;
1645 NTSTATUS
netlogon_creds_cli_check(struct netlogon_creds_cli_context
*context
,
1646 struct dcerpc_binding_handle
*b
)
1648 TALLOC_CTX
*frame
= talloc_stackframe();
1649 struct tevent_context
*ev
;
1650 struct tevent_req
*req
;
1651 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1653 ev
= samba_tevent_context_init(frame
);
1657 req
= netlogon_creds_cli_check_send(frame
, ev
, context
, b
);
1661 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1664 status
= netlogon_creds_cli_check_recv(req
);
1670 struct netlogon_creds_cli_ServerPasswordSet_state
{
1671 struct tevent_context
*ev
;
1672 struct netlogon_creds_cli_context
*context
;
1673 struct dcerpc_binding_handle
*binding_handle
;
1674 uint32_t old_timeout
;
1676 char *srv_name_slash
;
1677 enum dcerpc_AuthType auth_type
;
1678 enum dcerpc_AuthLevel auth_level
;
1680 struct samr_CryptPassword samr_crypt_password
;
1681 struct netr_CryptPassword netr_crypt_password
;
1682 struct samr_Password samr_password
;
1684 struct netlogon_creds_CredentialState
*creds
;
1685 struct netlogon_creds_CredentialState tmp_creds
;
1686 struct netr_Authenticator req_auth
;
1687 struct netr_Authenticator rep_auth
;
1690 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1692 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
);
1694 struct tevent_req
*netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX
*mem_ctx
,
1695 struct tevent_context
*ev
,
1696 struct netlogon_creds_cli_context
*context
,
1697 struct dcerpc_binding_handle
*b
,
1698 const DATA_BLOB
*new_password
,
1699 const uint32_t *new_version
)
1701 struct tevent_req
*req
;
1702 struct netlogon_creds_cli_ServerPasswordSet_state
*state
;
1703 struct tevent_req
*subreq
;
1706 req
= tevent_req_create(mem_ctx
, &state
,
1707 struct netlogon_creds_cli_ServerPasswordSet_state
);
1713 state
->context
= context
;
1714 state
->binding_handle
= b
;
1716 if (new_password
->length
< 14) {
1717 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1718 return tevent_req_post(req
, ev
);
1722 * netr_ServerPasswordSet
1724 mdfour(state
->samr_password
.hash
, new_password
->data
, new_password
->length
);
1727 * netr_ServerPasswordSet2
1729 ok
= set_pw_in_buffer(state
->samr_crypt_password
.data
,
1732 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1733 return tevent_req_post(req
, ev
);
1736 if (new_version
!= NULL
) {
1737 struct NL_PASSWORD_VERSION version
;
1738 uint32_t len
= IVAL(state
->samr_crypt_password
.data
, 512);
1739 uint32_t ofs
= 512 - len
;
1743 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1744 return tevent_req_post(req
, ev
);
1748 version
.ReservedField
= 0;
1749 version
.PasswordVersionNumber
= *new_version
;
1750 version
.PasswordVersionPresent
=
1751 NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT
;
1753 p
= state
->samr_crypt_password
.data
+ ofs
;
1754 SIVAL(p
, 0, version
.ReservedField
);
1755 SIVAL(p
, 4, version
.PasswordVersionNumber
);
1756 SIVAL(p
, 8, version
.PasswordVersionPresent
);
1759 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1760 context
->server
.computer
);
1761 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1762 return tevent_req_post(req
, ev
);
1765 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1767 &state
->auth_level
);
1769 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1771 if (tevent_req_nomem(subreq
, req
)) {
1772 return tevent_req_post(req
, ev
);
1775 tevent_req_set_callback(subreq
,
1776 netlogon_creds_cli_ServerPasswordSet_locked
,
1782 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1785 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1786 tevent_req_data(req
,
1787 struct netlogon_creds_cli_ServerPasswordSet_state
);
1789 if (state
->creds
== NULL
) {
1793 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
1794 state
->old_timeout
);
1796 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1797 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1798 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1799 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1800 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1801 TALLOC_FREE(state
->creds
);
1805 netlogon_creds_cli_delete(state
->context
, state
->creds
);
1806 TALLOC_FREE(state
->creds
);
1809 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
);
1811 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
)
1813 struct tevent_req
*req
=
1814 tevent_req_callback_data(subreq
,
1816 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1817 tevent_req_data(req
,
1818 struct netlogon_creds_cli_ServerPasswordSet_state
);
1821 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1823 TALLOC_FREE(subreq
);
1824 if (tevent_req_nterror(req
, status
)) {
1828 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
1829 switch (state
->auth_level
) {
1830 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1831 case DCERPC_AUTH_LEVEL_PRIVACY
:
1834 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1838 uint32_t tmp
= state
->creds
->negotiate_flags
;
1840 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
1842 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
1843 * it should be used, which means
1844 * we had a chance to verify no downgrade
1847 * This relies on netlogon_creds_cli_check*
1848 * being called before, as first request after
1851 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1856 state
->old_timeout
= dcerpc_binding_handle_set_timeout(
1857 state
->binding_handle
, 600000);
1860 * we defer all callbacks in order to cleanup
1861 * the database record.
1863 tevent_req_defer_callback(req
, state
->ev
);
1865 state
->tmp_creds
= *state
->creds
;
1866 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1868 ZERO_STRUCT(state
->rep_auth
);
1870 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1872 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1873 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
1874 state
->samr_crypt_password
.data
,
1877 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
1878 state
->samr_crypt_password
.data
,
1882 memcpy(state
->netr_crypt_password
.data
,
1883 state
->samr_crypt_password
.data
, 512);
1884 state
->netr_crypt_password
.length
=
1885 IVAL(state
->samr_crypt_password
.data
, 512);
1887 subreq
= dcerpc_netr_ServerPasswordSet2_send(state
, state
->ev
,
1888 state
->binding_handle
,
1889 state
->srv_name_slash
,
1890 state
->tmp_creds
.account_name
,
1891 state
->tmp_creds
.secure_channel_type
,
1892 state
->tmp_creds
.computer_name
,
1895 &state
->netr_crypt_password
);
1896 if (tevent_req_nomem(subreq
, req
)) {
1897 status
= NT_STATUS_NO_MEMORY
;
1898 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1902 netlogon_creds_des_encrypt(&state
->tmp_creds
,
1903 &state
->samr_password
);
1905 subreq
= dcerpc_netr_ServerPasswordSet_send(state
, state
->ev
,
1906 state
->binding_handle
,
1907 state
->srv_name_slash
,
1908 state
->tmp_creds
.account_name
,
1909 state
->tmp_creds
.secure_channel_type
,
1910 state
->tmp_creds
.computer_name
,
1913 &state
->samr_password
);
1914 if (tevent_req_nomem(subreq
, req
)) {
1915 status
= NT_STATUS_NO_MEMORY
;
1916 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1921 tevent_req_set_callback(subreq
,
1922 netlogon_creds_cli_ServerPasswordSet_done
,
1926 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
)
1928 struct tevent_req
*req
=
1929 tevent_req_callback_data(subreq
,
1931 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1932 tevent_req_data(req
,
1933 struct netlogon_creds_cli_ServerPasswordSet_state
);
1938 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1939 status
= dcerpc_netr_ServerPasswordSet2_recv(subreq
, state
,
1941 TALLOC_FREE(subreq
);
1942 if (tevent_req_nterror(req
, status
)) {
1943 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1947 status
= dcerpc_netr_ServerPasswordSet_recv(subreq
, state
,
1949 TALLOC_FREE(subreq
);
1950 if (tevent_req_nterror(req
, status
)) {
1951 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1956 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1957 &state
->rep_auth
.cred
);
1959 status
= NT_STATUS_ACCESS_DENIED
;
1960 tevent_req_nterror(req
, status
);
1961 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1965 if (tevent_req_nterror(req
, result
)) {
1966 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, result
);
1970 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
1971 state
->old_timeout
);
1973 *state
->creds
= state
->tmp_creds
;
1974 status
= netlogon_creds_cli_store(state
->context
,
1976 TALLOC_FREE(state
->creds
);
1977 if (tevent_req_nterror(req
, status
)) {
1978 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1982 tevent_req_done(req
);
1985 NTSTATUS
netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req
*req
)
1989 if (tevent_req_is_nterror(req
, &status
)) {
1990 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1991 tevent_req_received(req
);
1995 tevent_req_received(req
);
1996 return NT_STATUS_OK
;
1999 NTSTATUS
netlogon_creds_cli_ServerPasswordSet(
2000 struct netlogon_creds_cli_context
*context
,
2001 struct dcerpc_binding_handle
*b
,
2002 const DATA_BLOB
*new_password
,
2003 const uint32_t *new_version
)
2005 TALLOC_CTX
*frame
= talloc_stackframe();
2006 struct tevent_context
*ev
;
2007 struct tevent_req
*req
;
2008 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2010 ev
= samba_tevent_context_init(frame
);
2014 req
= netlogon_creds_cli_ServerPasswordSet_send(frame
, ev
, context
, b
,
2020 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2023 status
= netlogon_creds_cli_ServerPasswordSet_recv(req
);
2029 struct netlogon_creds_cli_LogonSamLogon_state
{
2030 struct tevent_context
*ev
;
2031 struct netlogon_creds_cli_context
*context
;
2032 struct dcerpc_binding_handle
*binding_handle
;
2034 char *srv_name_slash
;
2036 enum netr_LogonInfoClass logon_level
;
2037 const union netr_LogonLevel
*const_logon
;
2038 union netr_LogonLevel
*logon
;
2041 uint16_t validation_level
;
2042 union netr_Validation
*validation
;
2043 uint8_t authoritative
;
2046 * do we need encryption at the application layer?
2050 bool try_validation6
;
2053 * the read only credentials before we started the operation
2054 * used for netr_LogonSamLogonEx() if required (validation_level = 3).
2056 struct netlogon_creds_CredentialState
*ro_creds
;
2059 * The (locked) credentials used for the credential chain
2060 * used for netr_LogonSamLogonWithFlags() or
2061 * netr_LogonSamLogonWith().
2063 struct netlogon_creds_CredentialState
*lk_creds
;
2066 * While we have locked the global credentials (lk_creds above)
2067 * we operate an a temporary copy, because a server
2068 * may not support netr_LogonSamLogonWithFlags() and
2069 * didn't process our netr_Authenticator, so we need to
2070 * restart from lk_creds.
2072 struct netlogon_creds_CredentialState tmp_creds
;
2073 struct netr_Authenticator req_auth
;
2074 struct netr_Authenticator rep_auth
;
2077 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
);
2078 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2081 struct tevent_req
*netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX
*mem_ctx
,
2082 struct tevent_context
*ev
,
2083 struct netlogon_creds_cli_context
*context
,
2084 struct dcerpc_binding_handle
*b
,
2085 enum netr_LogonInfoClass logon_level
,
2086 const union netr_LogonLevel
*logon
,
2089 struct tevent_req
*req
;
2090 struct netlogon_creds_cli_LogonSamLogon_state
*state
;
2092 req
= tevent_req_create(mem_ctx
, &state
,
2093 struct netlogon_creds_cli_LogonSamLogon_state
);
2099 state
->context
= context
;
2100 state
->binding_handle
= b
;
2102 state
->logon_level
= logon_level
;
2103 state
->const_logon
= logon
;
2104 state
->flags
= flags
;
2106 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2107 context
->server
.computer
);
2108 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2109 return tevent_req_post(req
, ev
);
2112 switch (logon_level
) {
2113 case NetlogonInteractiveInformation
:
2114 case NetlogonInteractiveTransitiveInformation
:
2115 case NetlogonServiceInformation
:
2116 case NetlogonServiceTransitiveInformation
:
2117 case NetlogonGenericInformation
:
2118 state
->user_encrypt
= true;
2121 case NetlogonNetworkInformation
:
2122 case NetlogonNetworkTransitiveInformation
:
2126 state
->validation
= talloc_zero(state
, union netr_Validation
);
2127 if (tevent_req_nomem(state
->validation
, req
)) {
2128 return tevent_req_post(req
, ev
);
2131 netlogon_creds_cli_LogonSamLogon_start(req
);
2132 if (!tevent_req_is_in_progress(req
)) {
2133 return tevent_req_post(req
, ev
);
2137 * we defer all callbacks in order to cleanup
2138 * the database record.
2140 tevent_req_defer_callback(req
, state
->ev
);
2144 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2147 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2148 tevent_req_data(req
,
2149 struct netlogon_creds_cli_LogonSamLogon_state
);
2151 if (state
->lk_creds
== NULL
) {
2155 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2157 * This is a hack to recover from a bug in old
2158 * Samba servers, when LogonSamLogonEx() fails:
2160 * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
2162 * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2164 * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE,
2165 * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR
2166 * If the sign/seal check fails.
2168 * In that case we need to cleanup the netlogon session.
2170 * It's the job of the caller to disconnect the current
2171 * connection, if netlogon_creds_cli_LogonSamLogon()
2172 * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2174 if (!state
->context
->server
.try_logon_with
) {
2175 status
= NT_STATUS_NETWORK_ACCESS_DENIED
;
2179 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2180 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2181 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2182 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2183 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2184 TALLOC_FREE(state
->lk_creds
);
2188 netlogon_creds_cli_delete(state
->context
, state
->lk_creds
);
2189 TALLOC_FREE(state
->lk_creds
);
2192 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
);
2194 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
)
2196 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2197 tevent_req_data(req
,
2198 struct netlogon_creds_cli_LogonSamLogon_state
);
2199 struct tevent_req
*subreq
;
2201 enum dcerpc_AuthType auth_type
;
2202 enum dcerpc_AuthLevel auth_level
;
2204 TALLOC_FREE(state
->ro_creds
);
2205 TALLOC_FREE(state
->logon
);
2206 ZERO_STRUCTP(state
->validation
);
2208 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2209 &auth_type
, &auth_level
);
2211 state
->try_logon_ex
= state
->context
->server
.try_logon_ex
;
2212 state
->try_validation6
= state
->context
->server
.try_validation6
;
2214 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
2215 state
->try_logon_ex
= false;
2218 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
2219 state
->try_validation6
= false;
2222 if (state
->try_logon_ex
) {
2223 if (state
->try_validation6
) {
2224 state
->validation_level
= 6;
2226 state
->validation_level
= 3;
2227 state
->user_encrypt
= true;
2230 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2232 state
->const_logon
);
2233 if (tevent_req_nomem(state
->logon
, req
)) {
2234 status
= NT_STATUS_NO_MEMORY
;
2235 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2239 if (state
->user_encrypt
) {
2240 status
= netlogon_creds_cli_get(state
->context
,
2243 if (!NT_STATUS_IS_OK(status
)) {
2244 status
= NT_STATUS_ACCESS_DENIED
;
2245 tevent_req_nterror(req
, status
);
2246 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2250 netlogon_creds_encrypt_samlogon_logon(state
->ro_creds
,
2255 subreq
= dcerpc_netr_LogonSamLogonEx_send(state
, state
->ev
,
2256 state
->binding_handle
,
2257 state
->srv_name_slash
,
2258 state
->context
->client
.computer
,
2261 state
->validation_level
,
2263 &state
->authoritative
,
2265 if (tevent_req_nomem(subreq
, req
)) {
2266 status
= NT_STATUS_NO_MEMORY
;
2267 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2270 tevent_req_set_callback(subreq
,
2271 netlogon_creds_cli_LogonSamLogon_done
,
2276 if (state
->lk_creds
== NULL
) {
2277 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
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 state
->tmp_creds
= *state
->lk_creds
;
2291 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2293 ZERO_STRUCT(state
->rep_auth
);
2295 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2297 state
->const_logon
);
2298 if (tevent_req_nomem(state
->logon
, req
)) {
2299 status
= NT_STATUS_NO_MEMORY
;
2300 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2304 netlogon_creds_encrypt_samlogon_logon(&state
->tmp_creds
,
2308 state
->validation_level
= 3;
2310 if (state
->context
->server
.try_logon_with
) {
2311 subreq
= dcerpc_netr_LogonSamLogonWithFlags_send(state
, state
->ev
,
2312 state
->binding_handle
,
2313 state
->srv_name_slash
,
2314 state
->context
->client
.computer
,
2319 state
->validation_level
,
2321 &state
->authoritative
,
2323 if (tevent_req_nomem(subreq
, req
)) {
2324 status
= NT_STATUS_NO_MEMORY
;
2325 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2331 subreq
= dcerpc_netr_LogonSamLogon_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
);
2342 if (tevent_req_nomem(subreq
, req
)) {
2343 status
= NT_STATUS_NO_MEMORY
;
2344 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2349 tevent_req_set_callback(subreq
,
2350 netlogon_creds_cli_LogonSamLogon_done
,
2354 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
)
2356 struct tevent_req
*req
=
2357 tevent_req_callback_data(subreq
,
2359 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2360 tevent_req_data(req
,
2361 struct netlogon_creds_cli_LogonSamLogon_state
);
2366 if (state
->try_logon_ex
) {
2367 status
= dcerpc_netr_LogonSamLogonEx_recv(subreq
,
2370 TALLOC_FREE(subreq
);
2371 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2372 state
->context
->server
.try_validation6
= false;
2373 state
->context
->server
.try_logon_ex
= false;
2374 netlogon_creds_cli_LogonSamLogon_start(req
);
2377 if (tevent_req_nterror(req
, status
)) {
2378 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2382 if ((state
->validation_level
== 6) &&
2383 (NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_INFO_CLASS
) ||
2384 NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_PARAMETER
) ||
2385 NT_STATUS_EQUAL(result
, NT_STATUS_BUFFER_TOO_SMALL
)))
2387 state
->context
->server
.try_validation6
= false;
2388 netlogon_creds_cli_LogonSamLogon_start(req
);
2392 if (tevent_req_nterror(req
, result
)) {
2393 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2397 if (state
->ro_creds
== NULL
) {
2398 tevent_req_done(req
);
2402 ok
= netlogon_creds_cli_validate(state
->context
, state
->ro_creds
);
2405 * We got a race, lets retry with on authenticator
2408 * netlogon_creds_cli_LogonSamLogon_start()
2409 * will TALLOC_FREE(state->ro_creds);
2411 state
->try_logon_ex
= false;
2412 netlogon_creds_cli_LogonSamLogon_start(req
);
2416 netlogon_creds_decrypt_samlogon_validation(state
->ro_creds
,
2417 state
->validation_level
,
2420 tevent_req_done(req
);
2424 if (state
->lk_creds
== NULL
) {
2425 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2427 TALLOC_FREE(subreq
);
2428 if (tevent_req_nterror(req
, status
)) {
2429 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2433 netlogon_creds_cli_LogonSamLogon_start(req
);
2437 if (state
->context
->server
.try_logon_with
) {
2438 status
= dcerpc_netr_LogonSamLogonWithFlags_recv(subreq
,
2441 TALLOC_FREE(subreq
);
2442 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2443 state
->context
->server
.try_logon_with
= false;
2444 netlogon_creds_cli_LogonSamLogon_start(req
);
2447 if (tevent_req_nterror(req
, status
)) {
2448 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2452 status
= dcerpc_netr_LogonSamLogon_recv(subreq
,
2455 TALLOC_FREE(subreq
);
2456 if (tevent_req_nterror(req
, status
)) {
2457 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2462 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2463 &state
->rep_auth
.cred
);
2465 status
= NT_STATUS_ACCESS_DENIED
;
2466 tevent_req_nterror(req
, status
);
2467 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2471 *state
->lk_creds
= state
->tmp_creds
;
2472 status
= netlogon_creds_cli_store(state
->context
,
2474 TALLOC_FREE(state
->lk_creds
);
2476 if (tevent_req_nterror(req
, status
)) {
2477 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2481 if (tevent_req_nterror(req
, result
)) {
2482 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2486 netlogon_creds_decrypt_samlogon_validation(&state
->tmp_creds
,
2487 state
->validation_level
,
2490 tevent_req_done(req
);
2493 NTSTATUS
netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req
*req
,
2494 TALLOC_CTX
*mem_ctx
,
2495 uint16_t *validation_level
,
2496 union netr_Validation
**validation
,
2497 uint8_t *authoritative
,
2500 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2501 tevent_req_data(req
,
2502 struct netlogon_creds_cli_LogonSamLogon_state
);
2505 /* authoritative is also returned on error */
2506 *authoritative
= state
->authoritative
;
2508 if (tevent_req_is_nterror(req
, &status
)) {
2509 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2510 tevent_req_received(req
);
2514 *validation_level
= state
->validation_level
;
2515 *validation
= talloc_move(mem_ctx
, &state
->validation
);
2516 *flags
= state
->flags
;
2518 tevent_req_received(req
);
2519 return NT_STATUS_OK
;
2522 NTSTATUS
netlogon_creds_cli_LogonSamLogon(
2523 struct netlogon_creds_cli_context
*context
,
2524 struct dcerpc_binding_handle
*b
,
2525 enum netr_LogonInfoClass logon_level
,
2526 const union netr_LogonLevel
*logon
,
2527 TALLOC_CTX
*mem_ctx
,
2528 uint16_t *validation_level
,
2529 union netr_Validation
**validation
,
2530 uint8_t *authoritative
,
2533 TALLOC_CTX
*frame
= talloc_stackframe();
2534 struct tevent_context
*ev
;
2535 struct tevent_req
*req
;
2536 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2538 ev
= samba_tevent_context_init(frame
);
2542 req
= netlogon_creds_cli_LogonSamLogon_send(frame
, ev
, context
, b
,
2548 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2551 status
= netlogon_creds_cli_LogonSamLogon_recv(req
, mem_ctx
,
2561 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
{
2562 struct tevent_context
*ev
;
2563 struct netlogon_creds_cli_context
*context
;
2564 struct dcerpc_binding_handle
*binding_handle
;
2566 char *srv_name_slash
;
2567 enum dcerpc_AuthType auth_type
;
2568 enum dcerpc_AuthLevel auth_level
;
2570 const char *site_name
;
2572 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
;
2574 struct netlogon_creds_CredentialState
*creds
;
2575 struct netlogon_creds_CredentialState tmp_creds
;
2576 struct netr_Authenticator req_auth
;
2577 struct netr_Authenticator rep_auth
;
2580 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2582 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
);
2584 struct tevent_req
*netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(TALLOC_CTX
*mem_ctx
,
2585 struct tevent_context
*ev
,
2586 struct netlogon_creds_cli_context
*context
,
2587 struct dcerpc_binding_handle
*b
,
2588 const char *site_name
,
2590 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2592 struct tevent_req
*req
;
2593 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
;
2594 struct tevent_req
*subreq
;
2596 req
= tevent_req_create(mem_ctx
, &state
,
2597 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2603 state
->context
= context
;
2604 state
->binding_handle
= b
;
2606 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2607 context
->server
.computer
);
2608 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2609 return tevent_req_post(req
, ev
);
2612 state
->site_name
= site_name
;
2613 state
->dns_ttl
= dns_ttl
;
2614 state
->dns_names
= dns_names
;
2616 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2618 &state
->auth_level
);
2620 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2622 if (tevent_req_nomem(subreq
, req
)) {
2623 return tevent_req_post(req
, ev
);
2626 tevent_req_set_callback(subreq
,
2627 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked
,
2633 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2636 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2637 tevent_req_data(req
,
2638 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2640 if (state
->creds
== NULL
) {
2644 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2645 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2646 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2647 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2648 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2649 TALLOC_FREE(state
->creds
);
2653 netlogon_creds_cli_delete(state
->context
, state
->creds
);
2654 TALLOC_FREE(state
->creds
);
2657 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
);
2659 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
)
2661 struct tevent_req
*req
=
2662 tevent_req_callback_data(subreq
,
2664 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2665 tevent_req_data(req
,
2666 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2669 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2671 TALLOC_FREE(subreq
);
2672 if (tevent_req_nterror(req
, status
)) {
2676 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
2677 switch (state
->auth_level
) {
2678 case DCERPC_AUTH_LEVEL_INTEGRITY
:
2679 case DCERPC_AUTH_LEVEL_PRIVACY
:
2682 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2686 uint32_t tmp
= state
->creds
->negotiate_flags
;
2688 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
2690 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
2691 * it should be used, which means
2692 * we had a chance to verify no downgrade
2695 * This relies on netlogon_creds_cli_check*
2696 * being called before, as first request after
2699 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2705 * we defer all callbacks in order to cleanup
2706 * the database record.
2708 tevent_req_defer_callback(req
, state
->ev
);
2710 state
->tmp_creds
= *state
->creds
;
2711 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2713 ZERO_STRUCT(state
->rep_auth
);
2715 subreq
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_send(state
, state
->ev
,
2716 state
->binding_handle
,
2717 state
->srv_name_slash
,
2718 state
->tmp_creds
.computer_name
,
2724 if (tevent_req_nomem(subreq
, req
)) {
2725 status
= NT_STATUS_NO_MEMORY
;
2726 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2730 tevent_req_set_callback(subreq
,
2731 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done
,
2735 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
)
2737 struct tevent_req
*req
=
2738 tevent_req_callback_data(subreq
,
2740 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2741 tevent_req_data(req
,
2742 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2748 * We use state->dns_names as the memory context, as this is
2749 * the only in/out variable and it has been overwritten by the
2750 * out parameter from the server.
2752 * We need to preserve the return value until the caller can use it.
2754 status
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_recv(subreq
, state
->dns_names
,
2756 TALLOC_FREE(subreq
);
2757 if (tevent_req_nterror(req
, status
)) {
2758 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2762 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2763 &state
->rep_auth
.cred
);
2765 status
= NT_STATUS_ACCESS_DENIED
;
2766 tevent_req_nterror(req
, status
);
2767 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2771 *state
->creds
= state
->tmp_creds
;
2772 status
= netlogon_creds_cli_store(state
->context
,
2774 TALLOC_FREE(state
->creds
);
2776 if (tevent_req_nterror(req
, status
)) {
2777 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2781 if (tevent_req_nterror(req
, result
)) {
2782 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, result
);
2786 tevent_req_done(req
);
2789 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(struct tevent_req
*req
)
2793 if (tevent_req_is_nterror(req
, &status
)) {
2794 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2795 tevent_req_received(req
);
2799 tevent_req_received(req
);
2800 return NT_STATUS_OK
;
2803 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(
2804 struct netlogon_creds_cli_context
*context
,
2805 struct dcerpc_binding_handle
*b
,
2806 const char *site_name
,
2808 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2810 TALLOC_CTX
*frame
= talloc_stackframe();
2811 struct tevent_context
*ev
;
2812 struct tevent_req
*req
;
2813 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2815 ev
= samba_tevent_context_init(frame
);
2819 req
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(frame
, ev
, context
, b
,
2826 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2829 status
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(req
);
2835 struct netlogon_creds_cli_ServerGetTrustInfo_state
{
2836 struct tevent_context
*ev
;
2837 struct netlogon_creds_cli_context
*context
;
2838 struct dcerpc_binding_handle
*binding_handle
;
2840 char *srv_name_slash
;
2841 enum dcerpc_AuthType auth_type
;
2842 enum dcerpc_AuthLevel auth_level
;
2844 struct samr_Password new_owf_password
;
2845 struct samr_Password old_owf_password
;
2846 struct netr_TrustInfo
*trust_info
;
2848 struct netlogon_creds_CredentialState
*creds
;
2849 struct netlogon_creds_CredentialState tmp_creds
;
2850 struct netr_Authenticator req_auth
;
2851 struct netr_Authenticator rep_auth
;
2854 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
2856 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
);
2858 struct tevent_req
*netlogon_creds_cli_ServerGetTrustInfo_send(TALLOC_CTX
*mem_ctx
,
2859 struct tevent_context
*ev
,
2860 struct netlogon_creds_cli_context
*context
,
2861 struct dcerpc_binding_handle
*b
)
2863 struct tevent_req
*req
;
2864 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
;
2865 struct tevent_req
*subreq
;
2867 req
= tevent_req_create(mem_ctx
, &state
,
2868 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2874 state
->context
= context
;
2875 state
->binding_handle
= b
;
2877 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2878 context
->server
.computer
);
2879 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2880 return tevent_req_post(req
, ev
);
2883 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2885 &state
->auth_level
);
2887 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2889 if (tevent_req_nomem(subreq
, req
)) {
2890 return tevent_req_post(req
, ev
);
2893 tevent_req_set_callback(subreq
,
2894 netlogon_creds_cli_ServerGetTrustInfo_locked
,
2900 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
2903 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2904 tevent_req_data(req
,
2905 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2907 if (state
->creds
== NULL
) {
2911 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2912 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2913 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2914 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2915 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2916 TALLOC_FREE(state
->creds
);
2920 netlogon_creds_cli_delete(state
->context
, state
->creds
);
2921 TALLOC_FREE(state
->creds
);
2924 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
);
2926 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
)
2928 struct tevent_req
*req
=
2929 tevent_req_callback_data(subreq
,
2931 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2932 tevent_req_data(req
,
2933 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2936 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2938 TALLOC_FREE(subreq
);
2939 if (tevent_req_nterror(req
, status
)) {
2943 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
2944 switch (state
->auth_level
) {
2945 case DCERPC_AUTH_LEVEL_PRIVACY
:
2948 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2952 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2957 * we defer all callbacks in order to cleanup
2958 * the database record.
2960 tevent_req_defer_callback(req
, state
->ev
);
2962 state
->tmp_creds
= *state
->creds
;
2963 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2965 ZERO_STRUCT(state
->rep_auth
);
2967 subreq
= dcerpc_netr_ServerGetTrustInfo_send(state
, state
->ev
,
2968 state
->binding_handle
,
2969 state
->srv_name_slash
,
2970 state
->tmp_creds
.account_name
,
2971 state
->tmp_creds
.secure_channel_type
,
2972 state
->tmp_creds
.computer_name
,
2975 &state
->new_owf_password
,
2976 &state
->old_owf_password
,
2977 &state
->trust_info
);
2978 if (tevent_req_nomem(subreq
, req
)) {
2979 status
= NT_STATUS_NO_MEMORY
;
2980 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
2984 tevent_req_set_callback(subreq
,
2985 netlogon_creds_cli_ServerGetTrustInfo_done
,
2989 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
)
2991 struct tevent_req
*req
=
2992 tevent_req_callback_data(subreq
,
2994 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2995 tevent_req_data(req
,
2996 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2999 const struct samr_Password zero
= {};
3004 * We use state->dns_names as the memory context, as this is
3005 * the only in/out variable and it has been overwritten by the
3006 * out parameter from the server.
3008 * We need to preserve the return value until the caller can use it.
3010 status
= dcerpc_netr_ServerGetTrustInfo_recv(subreq
, state
, &result
);
3011 TALLOC_FREE(subreq
);
3012 if (tevent_req_nterror(req
, status
)) {
3013 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3017 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3018 &state
->rep_auth
.cred
);
3020 status
= NT_STATUS_ACCESS_DENIED
;
3021 tevent_req_nterror(req
, status
);
3022 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3026 cmp
= memcmp(state
->new_owf_password
.hash
,
3027 zero
.hash
, sizeof(zero
.hash
));
3029 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3030 &state
->new_owf_password
);
3032 cmp
= memcmp(state
->old_owf_password
.hash
,
3033 zero
.hash
, sizeof(zero
.hash
));
3035 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3036 &state
->old_owf_password
);
3039 *state
->creds
= state
->tmp_creds
;
3040 status
= netlogon_creds_cli_store(state
->context
,
3042 TALLOC_FREE(state
->creds
);
3043 if (tevent_req_nterror(req
, status
)) {
3044 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3048 if (tevent_req_nterror(req
, result
)) {
3049 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, result
);
3053 tevent_req_done(req
);
3056 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo_recv(struct tevent_req
*req
,
3057 TALLOC_CTX
*mem_ctx
,
3058 struct samr_Password
*new_owf_password
,
3059 struct samr_Password
*old_owf_password
,
3060 struct netr_TrustInfo
**trust_info
)
3062 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3063 tevent_req_data(req
,
3064 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3067 if (tevent_req_is_nterror(req
, &status
)) {
3068 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3069 tevent_req_received(req
);
3073 if (new_owf_password
!= NULL
) {
3074 *new_owf_password
= state
->new_owf_password
;
3076 if (old_owf_password
!= NULL
) {
3077 *old_owf_password
= state
->old_owf_password
;
3079 if (trust_info
!= NULL
) {
3080 *trust_info
= talloc_move(mem_ctx
, &state
->trust_info
);
3083 tevent_req_received(req
);
3084 return NT_STATUS_OK
;
3087 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo(
3088 struct netlogon_creds_cli_context
*context
,
3089 struct dcerpc_binding_handle
*b
,
3090 TALLOC_CTX
*mem_ctx
,
3091 struct samr_Password
*new_owf_password
,
3092 struct samr_Password
*old_owf_password
,
3093 struct netr_TrustInfo
**trust_info
)
3095 TALLOC_CTX
*frame
= talloc_stackframe();
3096 struct tevent_context
*ev
;
3097 struct tevent_req
*req
;
3098 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3100 ev
= samba_tevent_context_init(frame
);
3104 req
= netlogon_creds_cli_ServerGetTrustInfo_send(frame
, ev
, context
, b
);
3108 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3111 status
= netlogon_creds_cli_ServerGetTrustInfo_recv(req
,
3121 struct netlogon_creds_cli_GetForestTrustInformation_state
{
3122 struct tevent_context
*ev
;
3123 struct netlogon_creds_cli_context
*context
;
3124 struct dcerpc_binding_handle
*binding_handle
;
3126 char *srv_name_slash
;
3127 enum dcerpc_AuthType auth_type
;
3128 enum dcerpc_AuthLevel auth_level
;
3131 struct lsa_ForestTrustInformation
*forest_trust_info
;
3133 struct netlogon_creds_CredentialState
*creds
;
3134 struct netlogon_creds_CredentialState tmp_creds
;
3135 struct netr_Authenticator req_auth
;
3136 struct netr_Authenticator rep_auth
;
3139 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3141 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
);
3143 struct tevent_req
*netlogon_creds_cli_GetForestTrustInformation_send(TALLOC_CTX
*mem_ctx
,
3144 struct tevent_context
*ev
,
3145 struct netlogon_creds_cli_context
*context
,
3146 struct dcerpc_binding_handle
*b
)
3148 struct tevent_req
*req
;
3149 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
;
3150 struct tevent_req
*subreq
;
3152 req
= tevent_req_create(mem_ctx
, &state
,
3153 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3159 state
->context
= context
;
3160 state
->binding_handle
= b
;
3162 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3163 context
->server
.computer
);
3164 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3165 return tevent_req_post(req
, ev
);
3170 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3172 &state
->auth_level
);
3174 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3176 if (tevent_req_nomem(subreq
, req
)) {
3177 return tevent_req_post(req
, ev
);
3180 tevent_req_set_callback(subreq
,
3181 netlogon_creds_cli_GetForestTrustInformation_locked
,
3187 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3190 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3191 tevent_req_data(req
,
3192 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3194 if (state
->creds
== NULL
) {
3198 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3199 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3200 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3201 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3202 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3203 TALLOC_FREE(state
->creds
);
3207 netlogon_creds_cli_delete(state
->context
, state
->creds
);
3208 TALLOC_FREE(state
->creds
);
3211 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
);
3213 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
)
3215 struct tevent_req
*req
=
3216 tevent_req_callback_data(subreq
,
3218 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3219 tevent_req_data(req
,
3220 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3223 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3225 TALLOC_FREE(subreq
);
3226 if (tevent_req_nterror(req
, status
)) {
3230 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3231 switch (state
->auth_level
) {
3232 case DCERPC_AUTH_LEVEL_INTEGRITY
:
3233 case DCERPC_AUTH_LEVEL_PRIVACY
:
3236 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3240 uint32_t tmp
= state
->creds
->negotiate_flags
;
3242 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
3244 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3245 * it should be used, which means
3246 * we had a chance to verify no downgrade
3249 * This relies on netlogon_creds_cli_check*
3250 * being called before, as first request after
3253 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3259 * we defer all callbacks in order to cleanup
3260 * the database record.
3262 tevent_req_defer_callback(req
, state
->ev
);
3264 state
->tmp_creds
= *state
->creds
;
3265 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3267 ZERO_STRUCT(state
->rep_auth
);
3269 subreq
= dcerpc_netr_GetForestTrustInformation_send(state
, state
->ev
,
3270 state
->binding_handle
,
3271 state
->srv_name_slash
,
3272 state
->tmp_creds
.computer_name
,
3276 &state
->forest_trust_info
);
3277 if (tevent_req_nomem(subreq
, req
)) {
3278 status
= NT_STATUS_NO_MEMORY
;
3279 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3283 tevent_req_set_callback(subreq
,
3284 netlogon_creds_cli_GetForestTrustInformation_done
,
3288 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
)
3290 struct tevent_req
*req
=
3291 tevent_req_callback_data(subreq
,
3293 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3294 tevent_req_data(req
,
3295 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3301 * We use state->dns_names as the memory context, as this is
3302 * the only in/out variable and it has been overwritten by the
3303 * out parameter from the server.
3305 * We need to preserve the return value until the caller can use it.
3307 status
= dcerpc_netr_GetForestTrustInformation_recv(subreq
, state
, &result
);
3308 TALLOC_FREE(subreq
);
3309 if (tevent_req_nterror(req
, status
)) {
3310 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3314 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3315 &state
->rep_auth
.cred
);
3317 status
= NT_STATUS_ACCESS_DENIED
;
3318 tevent_req_nterror(req
, status
);
3319 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3323 *state
->creds
= state
->tmp_creds
;
3324 status
= netlogon_creds_cli_store(state
->context
,
3326 TALLOC_FREE(state
->creds
);
3328 if (tevent_req_nterror(req
, status
)) {
3329 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3333 if (tevent_req_nterror(req
, result
)) {
3334 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, result
);
3338 tevent_req_done(req
);
3341 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation_recv(struct tevent_req
*req
,
3342 TALLOC_CTX
*mem_ctx
,
3343 struct lsa_ForestTrustInformation
**forest_trust_info
)
3345 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3346 tevent_req_data(req
,
3347 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3350 if (tevent_req_is_nterror(req
, &status
)) {
3351 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3352 tevent_req_received(req
);
3356 *forest_trust_info
= talloc_move(mem_ctx
, &state
->forest_trust_info
);
3358 tevent_req_received(req
);
3359 return NT_STATUS_OK
;
3362 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation(
3363 struct netlogon_creds_cli_context
*context
,
3364 struct dcerpc_binding_handle
*b
,
3365 TALLOC_CTX
*mem_ctx
,
3366 struct lsa_ForestTrustInformation
**forest_trust_info
)
3368 TALLOC_CTX
*frame
= talloc_stackframe();
3369 struct tevent_context
*ev
;
3370 struct tevent_req
*req
;
3371 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3373 ev
= samba_tevent_context_init(frame
);
3377 req
= netlogon_creds_cli_GetForestTrustInformation_send(frame
, ev
, context
, b
);
3381 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3384 status
= netlogon_creds_cli_GetForestTrustInformation_recv(req
,
3392 struct netlogon_creds_cli_SendToSam_state
{
3393 struct tevent_context
*ev
;
3394 struct netlogon_creds_cli_context
*context
;
3395 struct dcerpc_binding_handle
*binding_handle
;
3397 char *srv_name_slash
;
3398 enum dcerpc_AuthType auth_type
;
3399 enum dcerpc_AuthLevel auth_level
;
3403 struct netlogon_creds_CredentialState
*creds
;
3404 struct netlogon_creds_CredentialState tmp_creds
;
3405 struct netr_Authenticator req_auth
;
3406 struct netr_Authenticator rep_auth
;
3409 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req
*req
,
3411 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req
*subreq
);
3413 struct tevent_req
*netlogon_creds_cli_SendToSam_send(TALLOC_CTX
*mem_ctx
,
3414 struct tevent_context
*ev
,
3415 struct netlogon_creds_cli_context
*context
,
3416 struct dcerpc_binding_handle
*b
,
3417 struct netr_SendToSamBase
*message
)
3419 struct tevent_req
*req
;
3420 struct netlogon_creds_cli_SendToSam_state
*state
;
3421 struct tevent_req
*subreq
;
3422 enum ndr_err_code ndr_err
;
3424 req
= tevent_req_create(mem_ctx
, &state
,
3425 struct netlogon_creds_cli_SendToSam_state
);
3431 state
->context
= context
;
3432 state
->binding_handle
= b
;
3434 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3435 context
->server
.computer
);
3436 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3437 return tevent_req_post(req
, ev
);
3440 ndr_err
= ndr_push_struct_blob(&state
->opaque
, mem_ctx
, message
,
3441 (ndr_push_flags_fn_t
)ndr_push_netr_SendToSamBase
);
3442 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
3443 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
3444 tevent_req_nterror(req
, status
);
3445 return tevent_req_post(req
, ev
);
3448 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3450 &state
->auth_level
);
3452 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3454 if (tevent_req_nomem(subreq
, req
)) {
3455 return tevent_req_post(req
, ev
);
3458 tevent_req_set_callback(subreq
,
3459 netlogon_creds_cli_SendToSam_locked
,
3465 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req
*req
,
3468 struct netlogon_creds_cli_SendToSam_state
*state
=
3469 tevent_req_data(req
,
3470 struct netlogon_creds_cli_SendToSam_state
);
3472 if (state
->creds
== NULL
) {
3476 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3477 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3478 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3479 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3480 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3481 TALLOC_FREE(state
->creds
);
3485 netlogon_creds_cli_delete(state
->context
, state
->creds
);
3486 TALLOC_FREE(state
->creds
);
3489 static void netlogon_creds_cli_SendToSam_done(struct tevent_req
*subreq
);
3491 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req
*subreq
)
3493 struct tevent_req
*req
=
3494 tevent_req_callback_data(subreq
,
3496 struct netlogon_creds_cli_SendToSam_state
*state
=
3497 tevent_req_data(req
,
3498 struct netlogon_creds_cli_SendToSam_state
);
3501 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3503 TALLOC_FREE(subreq
);
3504 if (tevent_req_nterror(req
, status
)) {
3508 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3509 switch (state
->auth_level
) {
3510 case DCERPC_AUTH_LEVEL_INTEGRITY
:
3511 case DCERPC_AUTH_LEVEL_PRIVACY
:
3514 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3518 uint32_t tmp
= state
->creds
->negotiate_flags
;
3520 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
3522 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3523 * it should be used, which means
3524 * we had a chance to verify no downgrade
3527 * This relies on netlogon_creds_cli_check*
3528 * being called before, as first request after
3531 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3537 * we defer all callbacks in order to cleanup
3538 * the database record.
3540 tevent_req_defer_callback(req
, state
->ev
);
3542 state
->tmp_creds
= *state
->creds
;
3543 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3545 ZERO_STRUCT(state
->rep_auth
);
3547 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
3548 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
3550 state
->opaque
.length
);
3552 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
3554 state
->opaque
.length
);
3557 subreq
= dcerpc_netr_NetrLogonSendToSam_send(state
, state
->ev
,
3558 state
->binding_handle
,
3559 state
->srv_name_slash
,
3560 state
->tmp_creds
.computer_name
,
3564 state
->opaque
.length
);
3565 if (tevent_req_nomem(subreq
, req
)) {
3566 status
= NT_STATUS_NO_MEMORY
;
3567 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3571 tevent_req_set_callback(subreq
,
3572 netlogon_creds_cli_SendToSam_done
,
3576 static void netlogon_creds_cli_SendToSam_done(struct tevent_req
*subreq
)
3578 struct tevent_req
*req
=
3579 tevent_req_callback_data(subreq
,
3581 struct netlogon_creds_cli_SendToSam_state
*state
=
3582 tevent_req_data(req
,
3583 struct netlogon_creds_cli_SendToSam_state
);
3588 status
= dcerpc_netr_NetrLogonSendToSam_recv(subreq
, state
, &result
);
3589 TALLOC_FREE(subreq
);
3590 if (tevent_req_nterror(req
, status
)) {
3591 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3595 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3596 &state
->rep_auth
.cred
);
3598 status
= NT_STATUS_ACCESS_DENIED
;
3599 tevent_req_nterror(req
, status
);
3600 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3604 *state
->creds
= state
->tmp_creds
;
3605 status
= netlogon_creds_cli_store(state
->context
,
3607 TALLOC_FREE(state
->creds
);
3609 if (tevent_req_nterror(req
, status
)) {
3610 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3615 * Creds must be stored before we send back application errors
3616 * e.g. NT_STATUS_NOT_IMPLEMENTED
3618 if (tevent_req_nterror(req
, result
)) {
3619 netlogon_creds_cli_SendToSam_cleanup(req
, result
);
3623 tevent_req_done(req
);
3626 NTSTATUS
netlogon_creds_cli_SendToSam(struct netlogon_creds_cli_context
*context
,
3627 struct dcerpc_binding_handle
*b
,
3628 struct netr_SendToSamBase
*message
)
3630 TALLOC_CTX
*frame
= talloc_stackframe();
3631 struct tevent_context
*ev
;
3632 struct tevent_req
*req
;
3633 NTSTATUS status
= NT_STATUS_OK
;
3635 ev
= samba_tevent_context_init(frame
);
3639 req
= netlogon_creds_cli_SendToSam_send(frame
, ev
, context
, b
, message
);
3643 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3647 /* Ignore the result */