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 if (DEBUGLEVEL
>= 10) {
499 NDR_PRINT_DEBUG(netlogon_creds_CredentialState
, state
->creds
);
502 tmp_flags
= state
->creds
->negotiate_flags
;
503 tmp_flags
&= state
->required_flags
;
504 if (tmp_flags
!= state
->required_flags
) {
505 TALLOC_FREE(state
->creds
);
506 state
->status
= NT_STATUS_DOWNGRADE_DETECTED
;
510 state
->status
= NT_STATUS_OK
;
513 static NTSTATUS
netlogon_creds_cli_get_internal(
514 struct netlogon_creds_cli_context
*context
,
515 TALLOC_CTX
*mem_ctx
, struct netlogon_creds_CredentialState
**pcreds
);
517 NTSTATUS
netlogon_creds_cli_get(struct netlogon_creds_cli_context
*context
,
519 struct netlogon_creds_CredentialState
**_creds
)
522 struct netlogon_creds_CredentialState
*creds
;
526 status
= netlogon_creds_cli_get_internal(context
, mem_ctx
, &creds
);
527 if (!NT_STATUS_IS_OK(status
)) {
532 * mark it as invalid for step operations.
535 creds
->seed
= (struct netr_Credential
) {{0}};
536 creds
->client
= (struct netr_Credential
) {{0}};
537 creds
->server
= (struct netr_Credential
) {{0}};
543 bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context
*context
,
544 const struct netlogon_creds_CredentialState
*creds1
)
546 TALLOC_CTX
*frame
= talloc_stackframe();
547 struct netlogon_creds_CredentialState
*creds2
;
551 enum ndr_err_code ndr_err
;
554 status
= netlogon_creds_cli_get(context
, frame
, &creds2
);
555 if (!NT_STATUS_IS_OK(status
)) {
560 ndr_err
= ndr_push_struct_blob(&blob1
, frame
, creds1
,
561 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
562 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
567 ndr_err
= ndr_push_struct_blob(&blob2
, frame
, creds2
,
568 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
569 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
574 cmp
= data_blob_cmp(&blob1
, &blob2
);
581 NTSTATUS
netlogon_creds_cli_store(struct netlogon_creds_cli_context
*context
,
582 struct netlogon_creds_CredentialState
*creds
)
585 enum ndr_err_code ndr_err
;
589 if (context
->db
.locked_state
== NULL
) {
591 * this was not the result of netlogon_creds_cli_lock*()
593 return NT_STATUS_INVALID_PAGE_PROTECTION
;
596 if (context
->db
.locked_state
->creds
!= creds
) {
598 * this was not the result of netlogon_creds_cli_lock*()
600 return NT_STATUS_INVALID_PAGE_PROTECTION
;
603 if (DEBUGLEVEL
>= 10) {
604 NDR_PRINT_DEBUG(netlogon_creds_CredentialState
, creds
);
607 ndr_err
= ndr_push_struct_blob(&blob
, creds
, creds
,
608 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
609 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
610 status
= ndr_map_error2ntstatus(ndr_err
);
614 data
.dptr
= blob
.data
;
615 data
.dsize
= blob
.length
;
617 status
= dbwrap_store(context
->db
.ctx
,
618 context
->db
.key_data
,
620 TALLOC_FREE(data
.dptr
);
621 if (!NT_STATUS_IS_OK(status
)) {
628 NTSTATUS
netlogon_creds_cli_delete(struct netlogon_creds_cli_context
*context
,
629 struct netlogon_creds_CredentialState
*creds
)
633 if (context
->db
.locked_state
== NULL
) {
635 * this was not the result of netlogon_creds_cli_lock*()
637 return NT_STATUS_INVALID_PAGE_PROTECTION
;
640 if (context
->db
.locked_state
->creds
!= creds
) {
642 * this was not the result of netlogon_creds_cli_lock*()
644 return NT_STATUS_INVALID_PAGE_PROTECTION
;
647 status
= dbwrap_delete(context
->db
.ctx
,
648 context
->db
.key_data
);
649 if (!NT_STATUS_IS_OK(status
)) {
656 struct netlogon_creds_cli_lock_state
{
657 struct netlogon_creds_cli_locked_state
*locked_state
;
658 struct netlogon_creds_CredentialState
*creds
;
661 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
);
663 struct tevent_req
*netlogon_creds_cli_lock_send(TALLOC_CTX
*mem_ctx
,
664 struct tevent_context
*ev
,
665 struct netlogon_creds_cli_context
*context
)
667 struct tevent_req
*req
;
668 struct netlogon_creds_cli_lock_state
*state
;
669 struct netlogon_creds_cli_locked_state
*locked_state
;
670 struct tevent_req
*subreq
;
672 req
= tevent_req_create(mem_ctx
, &state
,
673 struct netlogon_creds_cli_lock_state
);
678 if (context
->db
.locked_state
!= NULL
) {
679 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
680 return tevent_req_post(req
, ev
);
683 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
684 if (tevent_req_nomem(locked_state
, req
)) {
685 return tevent_req_post(req
, ev
);
687 talloc_set_destructor(locked_state
,
688 netlogon_creds_cli_locked_state_destructor
);
689 locked_state
->context
= context
;
691 context
->db
.locked_state
= locked_state
;
692 state
->locked_state
= locked_state
;
694 if (context
->db
.g_ctx
== NULL
) {
697 status
= netlogon_creds_cli_get_internal(
698 context
, state
, &state
->creds
);
699 if (tevent_req_nterror(req
, status
)) {
700 return tevent_req_post(req
, ev
);
706 subreq
= g_lock_lock_send(state
, ev
,
708 context
->db
.key_name
,
710 if (tevent_req_nomem(subreq
, req
)) {
711 return tevent_req_post(req
, ev
);
713 tevent_req_set_callback(subreq
, netlogon_creds_cli_lock_done
, req
);
718 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
)
720 struct tevent_req
*req
=
721 tevent_req_callback_data(subreq
,
723 struct netlogon_creds_cli_lock_state
*state
=
725 struct netlogon_creds_cli_lock_state
);
728 status
= g_lock_lock_recv(subreq
);
730 if (tevent_req_nterror(req
, status
)) {
733 state
->locked_state
->is_glocked
= true;
735 status
= netlogon_creds_cli_get_internal(state
->locked_state
->context
,
736 state
, &state
->creds
);
737 if (tevent_req_nterror(req
, status
)) {
740 tevent_req_done(req
);
743 static NTSTATUS
netlogon_creds_cli_get_internal(
744 struct netlogon_creds_cli_context
*context
,
745 TALLOC_CTX
*mem_ctx
, struct netlogon_creds_CredentialState
**pcreds
)
747 struct netlogon_creds_cli_fetch_state fstate
= {
748 .status
= NT_STATUS_INTERNAL_ERROR
,
749 .required_flags
= context
->client
.required_flags
,
753 fstate
.mem_ctx
= mem_ctx
;
754 status
= dbwrap_parse_record(context
->db
.ctx
,
755 context
->db
.key_data
,
756 netlogon_creds_cli_fetch_parser
,
758 if (!NT_STATUS_IS_OK(status
)) {
761 if (!NT_STATUS_IS_OK(fstate
.status
)) {
762 return fstate
.status
;
765 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
766 *pcreds
= fstate
.creds
;
771 * It is really important to try SamLogonEx here,
772 * because multiple processes can talk to the same
773 * domain controller, without using the credential
776 * With a normal SamLogon call, we must keep the
777 * credentials chain updated and intact between all
778 * users of the machine account (which would imply
779 * cross-node communication for every NTLM logon).
781 * The credentials chain is not per NETLOGON pipe
782 * connection, but globally on the server/client pair
785 * It's also important to use NetlogonValidationSamInfo4 (6),
786 * because it relies on the rpc transport encryption
787 * and avoids using the global netlogon schannel
788 * session key to en/decrypt secret information
789 * like the user_session_key for network logons.
791 * [MS-APDS] 3.1.5.2 NTLM Network Logon
792 * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and
793 * NETLOGON_NEG_AUTHENTICATED_RPC set together
794 * are the indication that the server supports
795 * NetlogonValidationSamInfo4 (6). And it must only
796 * be used if "SealSecureChannel" is used.
798 * The "SealSecureChannel" AUTH_TYPE_SCHANNEL/AUTH_LEVEL_PRIVACY
799 * check is done in netlogon_creds_cli_LogonSamLogon*().
802 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
803 context
->server
.try_validation6
= true;
804 context
->server
.try_logon_ex
= true;
805 context
->server
.try_logon_with
= true;
807 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
808 context
->server
.try_validation6
= false;
809 context
->server
.try_logon_ex
= false;
811 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
812 context
->server
.try_validation6
= false;
815 *pcreds
= fstate
.creds
;
819 NTSTATUS
netlogon_creds_cli_lock_recv(struct tevent_req
*req
,
821 struct netlogon_creds_CredentialState
**creds
)
823 struct netlogon_creds_cli_lock_state
*state
=
825 struct netlogon_creds_cli_lock_state
);
828 if (tevent_req_is_nterror(req
, &status
)) {
829 tevent_req_received(req
);
833 talloc_steal(state
->creds
, state
->locked_state
);
834 state
->locked_state
->creds
= state
->creds
;
835 *creds
= talloc_move(mem_ctx
, &state
->creds
);
836 tevent_req_received(req
);
840 NTSTATUS
netlogon_creds_cli_lock(struct netlogon_creds_cli_context
*context
,
842 struct netlogon_creds_CredentialState
**creds
)
844 TALLOC_CTX
*frame
= talloc_stackframe();
845 struct tevent_context
*ev
;
846 struct tevent_req
*req
;
847 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
849 ev
= samba_tevent_context_init(frame
);
853 req
= netlogon_creds_cli_lock_send(frame
, ev
, context
);
857 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
860 status
= netlogon_creds_cli_lock_recv(req
, mem_ctx
, creds
);
866 struct netlogon_creds_cli_auth_state
{
867 struct tevent_context
*ev
;
868 struct netlogon_creds_cli_context
*context
;
869 struct dcerpc_binding_handle
*binding_handle
;
870 uint8_t num_nt_hashes
;
871 uint8_t idx_nt_hashes
;
872 const struct samr_Password
* const *nt_hashes
;
873 const struct samr_Password
*used_nt_hash
;
874 char *srv_name_slash
;
875 uint32_t current_flags
;
876 struct netr_Credential client_challenge
;
877 struct netr_Credential server_challenge
;
878 struct netlogon_creds_CredentialState
*creds
;
879 struct netr_Credential client_credential
;
880 struct netr_Credential server_credential
;
885 struct netlogon_creds_cli_locked_state
*locked_state
;
888 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
);
889 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
);
891 struct tevent_req
*netlogon_creds_cli_auth_send(TALLOC_CTX
*mem_ctx
,
892 struct tevent_context
*ev
,
893 struct netlogon_creds_cli_context
*context
,
894 struct dcerpc_binding_handle
*b
,
895 uint8_t num_nt_hashes
,
896 const struct samr_Password
* const *nt_hashes
)
898 struct tevent_req
*req
;
899 struct netlogon_creds_cli_auth_state
*state
;
900 struct netlogon_creds_cli_locked_state
*locked_state
;
903 req
= tevent_req_create(mem_ctx
, &state
,
904 struct netlogon_creds_cli_auth_state
);
910 state
->context
= context
;
911 state
->binding_handle
= b
;
912 if (num_nt_hashes
< 1) {
913 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
914 return tevent_req_post(req
, ev
);
916 if (num_nt_hashes
> 4) {
917 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
918 return tevent_req_post(req
, ev
);
921 state
->num_nt_hashes
= num_nt_hashes
;
922 state
->idx_nt_hashes
= 0;
923 state
->nt_hashes
= nt_hashes
;
925 if (context
->db
.locked_state
!= NULL
) {
926 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
927 return tevent_req_post(req
, ev
);
930 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
931 if (tevent_req_nomem(locked_state
, req
)) {
932 return tevent_req_post(req
, ev
);
934 talloc_set_destructor(locked_state
,
935 netlogon_creds_cli_locked_state_destructor
);
936 locked_state
->context
= context
;
938 context
->db
.locked_state
= locked_state
;
939 state
->locked_state
= locked_state
;
941 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
942 context
->server
.computer
);
943 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
944 return tevent_req_post(req
, ev
);
947 state
->try_auth3
= true;
948 state
->try_auth2
= true;
950 if (context
->client
.required_flags
!= 0) {
951 state
->require_auth2
= true;
954 state
->used_nt_hash
= state
->nt_hashes
[state
->idx_nt_hashes
];
955 state
->current_flags
= context
->client
.proposed_flags
;
957 if (context
->db
.g_ctx
!= NULL
) {
958 struct tevent_req
*subreq
;
960 subreq
= g_lock_lock_send(state
, ev
,
962 context
->db
.key_name
,
964 if (tevent_req_nomem(subreq
, req
)) {
965 return tevent_req_post(req
, ev
);
967 tevent_req_set_callback(subreq
,
968 netlogon_creds_cli_auth_locked
,
974 status
= dbwrap_purge(state
->context
->db
.ctx
,
975 state
->context
->db
.key_data
);
976 if (tevent_req_nterror(req
, status
)) {
977 return tevent_req_post(req
, ev
);
980 netlogon_creds_cli_auth_challenge_start(req
);
981 if (!tevent_req_is_in_progress(req
)) {
982 return tevent_req_post(req
, ev
);
988 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
)
990 struct tevent_req
*req
=
991 tevent_req_callback_data(subreq
,
993 struct netlogon_creds_cli_auth_state
*state
=
995 struct netlogon_creds_cli_auth_state
);
998 status
= g_lock_lock_recv(subreq
);
1000 if (tevent_req_nterror(req
, status
)) {
1003 state
->locked_state
->is_glocked
= true;
1005 status
= dbwrap_purge(state
->context
->db
.ctx
,
1006 state
->context
->db
.key_data
);
1007 if (tevent_req_nterror(req
, status
)) {
1011 netlogon_creds_cli_auth_challenge_start(req
);
1014 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
);
1016 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
)
1018 struct netlogon_creds_cli_auth_state
*state
=
1019 tevent_req_data(req
,
1020 struct netlogon_creds_cli_auth_state
);
1021 struct tevent_req
*subreq
;
1023 TALLOC_FREE(state
->creds
);
1025 generate_random_buffer(state
->client_challenge
.data
,
1026 sizeof(state
->client_challenge
.data
));
1028 subreq
= dcerpc_netr_ServerReqChallenge_send(state
, state
->ev
,
1029 state
->binding_handle
,
1030 state
->srv_name_slash
,
1031 state
->context
->client
.computer
,
1032 &state
->client_challenge
,
1033 &state
->server_challenge
);
1034 if (tevent_req_nomem(subreq
, req
)) {
1037 tevent_req_set_callback(subreq
,
1038 netlogon_creds_cli_auth_challenge_done
,
1042 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
);
1044 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
)
1046 struct tevent_req
*req
=
1047 tevent_req_callback_data(subreq
,
1049 struct netlogon_creds_cli_auth_state
*state
=
1050 tevent_req_data(req
,
1051 struct netlogon_creds_cli_auth_state
);
1055 status
= dcerpc_netr_ServerReqChallenge_recv(subreq
, state
, &result
);
1056 TALLOC_FREE(subreq
);
1057 if (tevent_req_nterror(req
, status
)) {
1060 if (tevent_req_nterror(req
, result
)) {
1064 if (!state
->try_auth3
&& !state
->try_auth2
) {
1065 state
->current_flags
= 0;
1068 /* Calculate the session key and client credentials */
1070 state
->creds
= netlogon_creds_client_init(state
,
1071 state
->context
->client
.account
,
1072 state
->context
->client
.computer
,
1073 state
->context
->client
.type
,
1074 &state
->client_challenge
,
1075 &state
->server_challenge
,
1076 state
->used_nt_hash
,
1077 &state
->client_credential
,
1078 state
->current_flags
);
1079 if (tevent_req_nomem(state
->creds
, req
)) {
1083 if (state
->try_auth3
) {
1084 subreq
= dcerpc_netr_ServerAuthenticate3_send(state
, state
->ev
,
1085 state
->binding_handle
,
1086 state
->srv_name_slash
,
1087 state
->context
->client
.account
,
1088 state
->context
->client
.type
,
1089 state
->context
->client
.computer
,
1090 &state
->client_credential
,
1091 &state
->server_credential
,
1092 &state
->creds
->negotiate_flags
,
1094 if (tevent_req_nomem(subreq
, req
)) {
1097 } else if (state
->try_auth2
) {
1100 subreq
= dcerpc_netr_ServerAuthenticate2_send(state
, state
->ev
,
1101 state
->binding_handle
,
1102 state
->srv_name_slash
,
1103 state
->context
->client
.account
,
1104 state
->context
->client
.type
,
1105 state
->context
->client
.computer
,
1106 &state
->client_credential
,
1107 &state
->server_credential
,
1108 &state
->creds
->negotiate_flags
);
1109 if (tevent_req_nomem(subreq
, req
)) {
1115 subreq
= dcerpc_netr_ServerAuthenticate_send(state
, state
->ev
,
1116 state
->binding_handle
,
1117 state
->srv_name_slash
,
1118 state
->context
->client
.account
,
1119 state
->context
->client
.type
,
1120 state
->context
->client
.computer
,
1121 &state
->client_credential
,
1122 &state
->server_credential
);
1123 if (tevent_req_nomem(subreq
, req
)) {
1127 tevent_req_set_callback(subreq
,
1128 netlogon_creds_cli_auth_srvauth_done
,
1132 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
)
1134 struct tevent_req
*req
=
1135 tevent_req_callback_data(subreq
,
1137 struct netlogon_creds_cli_auth_state
*state
=
1138 tevent_req_data(req
,
1139 struct netlogon_creds_cli_auth_state
);
1143 enum ndr_err_code ndr_err
;
1148 if (state
->try_auth3
) {
1149 status
= dcerpc_netr_ServerAuthenticate3_recv(subreq
, state
,
1151 TALLOC_FREE(subreq
);
1152 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1153 state
->try_auth3
= false;
1154 netlogon_creds_cli_auth_challenge_start(req
);
1157 if (tevent_req_nterror(req
, status
)) {
1160 } else if (state
->try_auth2
) {
1161 status
= dcerpc_netr_ServerAuthenticate2_recv(subreq
, state
,
1163 TALLOC_FREE(subreq
);
1164 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1165 state
->try_auth2
= false;
1166 if (state
->require_auth2
) {
1167 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1168 tevent_req_nterror(req
, status
);
1171 netlogon_creds_cli_auth_challenge_start(req
);
1174 if (tevent_req_nterror(req
, status
)) {
1178 status
= dcerpc_netr_ServerAuthenticate_recv(subreq
, state
,
1180 TALLOC_FREE(subreq
);
1181 if (tevent_req_nterror(req
, status
)) {
1186 if (!NT_STATUS_IS_OK(result
) &&
1187 !NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
))
1189 tevent_req_nterror(req
, result
);
1193 tmp_flags
= state
->creds
->negotiate_flags
;
1194 tmp_flags
&= state
->context
->client
.required_flags
;
1195 if (tmp_flags
!= state
->context
->client
.required_flags
) {
1196 if (NT_STATUS_IS_OK(result
)) {
1197 tevent_req_nterror(req
, NT_STATUS_DOWNGRADE_DETECTED
);
1200 tevent_req_nterror(req
, result
);
1204 if (NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
)) {
1206 tmp_flags
= state
->context
->client
.proposed_flags
;
1207 if ((state
->current_flags
== tmp_flags
) &&
1208 (state
->creds
->negotiate_flags
!= tmp_flags
))
1211 * lets retry with the negotiated flags
1213 state
->current_flags
= state
->creds
->negotiate_flags
;
1214 netlogon_creds_cli_auth_challenge_start(req
);
1218 state
->idx_nt_hashes
+= 1;
1219 if (state
->idx_nt_hashes
>= state
->num_nt_hashes
) {
1221 * we already retried, giving up...
1223 tevent_req_nterror(req
, result
);
1228 * lets retry with the old nt hash.
1230 state
->used_nt_hash
= state
->nt_hashes
[state
->idx_nt_hashes
];
1231 state
->current_flags
= state
->context
->client
.proposed_flags
;
1232 netlogon_creds_cli_auth_challenge_start(req
);
1236 ok
= netlogon_creds_client_check(state
->creds
,
1237 &state
->server_credential
);
1239 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1243 ndr_err
= ndr_push_struct_blob(&blob
, state
, state
->creds
,
1244 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
1245 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1246 status
= ndr_map_error2ntstatus(ndr_err
);
1247 tevent_req_nterror(req
, status
);
1251 data
.dptr
= blob
.data
;
1252 data
.dsize
= blob
.length
;
1254 status
= dbwrap_store(state
->context
->db
.ctx
,
1255 state
->context
->db
.key_data
,
1257 TALLOC_FREE(state
->locked_state
);
1258 if (tevent_req_nterror(req
, status
)) {
1262 tevent_req_done(req
);
1265 NTSTATUS
netlogon_creds_cli_auth_recv(struct tevent_req
*req
,
1266 uint8_t *idx_nt_hashes
)
1268 struct netlogon_creds_cli_auth_state
*state
=
1269 tevent_req_data(req
,
1270 struct netlogon_creds_cli_auth_state
);
1275 if (tevent_req_is_nterror(req
, &status
)) {
1276 tevent_req_received(req
);
1280 *idx_nt_hashes
= state
->idx_nt_hashes
;
1281 tevent_req_received(req
);
1282 return NT_STATUS_OK
;
1285 NTSTATUS
netlogon_creds_cli_auth(struct netlogon_creds_cli_context
*context
,
1286 struct dcerpc_binding_handle
*b
,
1287 uint8_t num_nt_hashes
,
1288 const struct samr_Password
* const *nt_hashes
,
1289 uint8_t *idx_nt_hashes
)
1291 TALLOC_CTX
*frame
= talloc_stackframe();
1292 struct tevent_context
*ev
;
1293 struct tevent_req
*req
;
1294 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1298 ev
= samba_tevent_context_init(frame
);
1302 req
= netlogon_creds_cli_auth_send(frame
, ev
, context
, b
,
1303 num_nt_hashes
, nt_hashes
);
1307 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1310 status
= netlogon_creds_cli_auth_recv(req
, idx_nt_hashes
);
1316 struct netlogon_creds_cli_check_state
{
1317 struct tevent_context
*ev
;
1318 struct netlogon_creds_cli_context
*context
;
1319 struct dcerpc_binding_handle
*binding_handle
;
1321 char *srv_name_slash
;
1323 union netr_Capabilities caps
;
1325 struct netlogon_creds_CredentialState
*creds
;
1326 struct netlogon_creds_CredentialState tmp_creds
;
1327 struct netr_Authenticator req_auth
;
1328 struct netr_Authenticator rep_auth
;
1331 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1333 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
);
1335 struct tevent_req
*netlogon_creds_cli_check_send(TALLOC_CTX
*mem_ctx
,
1336 struct tevent_context
*ev
,
1337 struct netlogon_creds_cli_context
*context
,
1338 struct dcerpc_binding_handle
*b
)
1340 struct tevent_req
*req
;
1341 struct netlogon_creds_cli_check_state
*state
;
1342 struct tevent_req
*subreq
;
1343 enum dcerpc_AuthType auth_type
;
1344 enum dcerpc_AuthLevel auth_level
;
1346 req
= tevent_req_create(mem_ctx
, &state
,
1347 struct netlogon_creds_cli_check_state
);
1353 state
->context
= context
;
1354 state
->binding_handle
= b
;
1356 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1357 context
->server
.computer
);
1358 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1359 return tevent_req_post(req
, ev
);
1362 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1363 &auth_type
, &auth_level
);
1365 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
1366 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1367 return tevent_req_post(req
, ev
);
1370 switch (auth_level
) {
1371 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1372 case DCERPC_AUTH_LEVEL_PRIVACY
:
1375 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1376 return tevent_req_post(req
, ev
);
1379 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1381 if (tevent_req_nomem(subreq
, req
)) {
1382 return tevent_req_post(req
, ev
);
1385 tevent_req_set_callback(subreq
,
1386 netlogon_creds_cli_check_locked
,
1392 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1395 struct netlogon_creds_cli_check_state
*state
=
1396 tevent_req_data(req
,
1397 struct netlogon_creds_cli_check_state
);
1399 if (state
->creds
== NULL
) {
1403 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1404 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1405 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1406 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1407 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1408 TALLOC_FREE(state
->creds
);
1412 netlogon_creds_cli_delete(state
->context
, state
->creds
);
1413 TALLOC_FREE(state
->creds
);
1416 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
);
1418 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
)
1420 struct tevent_req
*req
=
1421 tevent_req_callback_data(subreq
,
1423 struct netlogon_creds_cli_check_state
*state
=
1424 tevent_req_data(req
,
1425 struct netlogon_creds_cli_check_state
);
1428 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1430 TALLOC_FREE(subreq
);
1431 if (tevent_req_nterror(req
, status
)) {
1436 * we defer all callbacks in order to cleanup
1437 * the database record.
1439 tevent_req_defer_callback(req
, state
->ev
);
1441 state
->tmp_creds
= *state
->creds
;
1442 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1444 ZERO_STRUCT(state
->rep_auth
);
1446 subreq
= dcerpc_netr_LogonGetCapabilities_send(state
, state
->ev
,
1447 state
->binding_handle
,
1448 state
->srv_name_slash
,
1449 state
->context
->client
.computer
,
1454 if (tevent_req_nomem(subreq
, req
)) {
1455 status
= NT_STATUS_NO_MEMORY
;
1456 netlogon_creds_cli_check_cleanup(req
, status
);
1459 tevent_req_set_callback(subreq
,
1460 netlogon_creds_cli_check_caps
,
1464 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
)
1466 struct tevent_req
*req
=
1467 tevent_req_callback_data(subreq
,
1469 struct netlogon_creds_cli_check_state
*state
=
1470 tevent_req_data(req
,
1471 struct netlogon_creds_cli_check_state
);
1476 status
= dcerpc_netr_LogonGetCapabilities_recv(subreq
, state
,
1478 TALLOC_FREE(subreq
);
1479 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1481 * Note that the negotiated flags are already checked
1482 * for our required flags after the ServerAuthenticate3/2 call.
1484 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1486 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1488 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1489 * already, we expect this to work!
1491 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1492 tevent_req_nterror(req
, status
);
1493 netlogon_creds_cli_check_cleanup(req
, status
);
1497 if (negotiated
& NETLOGON_NEG_STRONG_KEYS
) {
1499 * If we have negotiated NETLOGON_NEG_STRONG_KEYS
1500 * we expect this to work at least as far as the
1501 * NOT_SUPPORTED error handled below!
1503 * NT 4.0 and Old Samba servers are not
1504 * allowed without "require strong key = no"
1506 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1507 tevent_req_nterror(req
, status
);
1508 netlogon_creds_cli_check_cleanup(req
, status
);
1513 * If we not require NETLOGON_NEG_SUPPORTS_AES or
1514 * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore
1515 * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
1517 * This is needed against NT 4.0 and old Samba servers.
1519 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
1520 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
1521 * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
1522 * with the next request as the sequence number processing
1525 netlogon_creds_cli_check_cleanup(req
, status
);
1526 tevent_req_done(req
);
1529 if (tevent_req_nterror(req
, status
)) {
1530 netlogon_creds_cli_check_cleanup(req
, status
);
1534 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOT_IMPLEMENTED
)) {
1536 * Note that the negotiated flags are already checked
1537 * for our required flags after the ServerAuthenticate3/2 call.
1539 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1541 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1543 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1544 * already, we expect this to work!
1546 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1547 tevent_req_nterror(req
, status
);
1548 netlogon_creds_cli_check_cleanup(req
, status
);
1553 * This is ok, the server does not support
1554 * NETLOGON_NEG_SUPPORTS_AES.
1556 * netr_LogonGetCapabilities() was
1557 * netr_LogonDummyRoutine1() before
1558 * NETLOGON_NEG_SUPPORTS_AES was invented.
1560 netlogon_creds_cli_check_cleanup(req
, result
);
1561 tevent_req_done(req
);
1565 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1566 &state
->rep_auth
.cred
);
1568 status
= NT_STATUS_ACCESS_DENIED
;
1569 tevent_req_nterror(req
, status
);
1570 netlogon_creds_cli_check_cleanup(req
, status
);
1574 if (tevent_req_nterror(req
, result
)) {
1575 netlogon_creds_cli_check_cleanup(req
, result
);
1579 if (state
->caps
.server_capabilities
!= state
->tmp_creds
.negotiate_flags
) {
1580 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1581 tevent_req_nterror(req
, status
);
1582 netlogon_creds_cli_check_cleanup(req
, status
);
1587 * This is the key check that makes this check secure. If we
1588 * get OK here (rather than NOT_SUPPORTED), then the server
1589 * did support AES. If the server only proposed STRONG_KEYS
1590 * and not AES, then it should have failed with
1591 * NOT_IMPLEMENTED. We always send AES as a client, so the
1592 * server should always have returned it.
1594 if (!(state
->caps
.server_capabilities
& NETLOGON_NEG_SUPPORTS_AES
)) {
1595 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1596 tevent_req_nterror(req
, status
);
1597 netlogon_creds_cli_check_cleanup(req
, status
);
1601 *state
->creds
= state
->tmp_creds
;
1602 status
= netlogon_creds_cli_store(state
->context
,
1604 TALLOC_FREE(state
->creds
);
1605 if (tevent_req_nterror(req
, status
)) {
1609 tevent_req_done(req
);
1612 NTSTATUS
netlogon_creds_cli_check_recv(struct tevent_req
*req
)
1616 if (tevent_req_is_nterror(req
, &status
)) {
1617 netlogon_creds_cli_check_cleanup(req
, status
);
1618 tevent_req_received(req
);
1622 tevent_req_received(req
);
1623 return NT_STATUS_OK
;
1626 NTSTATUS
netlogon_creds_cli_check(struct netlogon_creds_cli_context
*context
,
1627 struct dcerpc_binding_handle
*b
)
1629 TALLOC_CTX
*frame
= talloc_stackframe();
1630 struct tevent_context
*ev
;
1631 struct tevent_req
*req
;
1632 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1634 ev
= samba_tevent_context_init(frame
);
1638 req
= netlogon_creds_cli_check_send(frame
, ev
, context
, b
);
1642 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1645 status
= netlogon_creds_cli_check_recv(req
);
1651 struct netlogon_creds_cli_ServerPasswordSet_state
{
1652 struct tevent_context
*ev
;
1653 struct netlogon_creds_cli_context
*context
;
1654 struct dcerpc_binding_handle
*binding_handle
;
1655 uint32_t old_timeout
;
1657 char *srv_name_slash
;
1658 enum dcerpc_AuthType auth_type
;
1659 enum dcerpc_AuthLevel auth_level
;
1661 struct samr_CryptPassword samr_crypt_password
;
1662 struct netr_CryptPassword netr_crypt_password
;
1663 struct samr_Password samr_password
;
1665 struct netlogon_creds_CredentialState
*creds
;
1666 struct netlogon_creds_CredentialState tmp_creds
;
1667 struct netr_Authenticator req_auth
;
1668 struct netr_Authenticator rep_auth
;
1671 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1673 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
);
1675 struct tevent_req
*netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX
*mem_ctx
,
1676 struct tevent_context
*ev
,
1677 struct netlogon_creds_cli_context
*context
,
1678 struct dcerpc_binding_handle
*b
,
1679 const DATA_BLOB
*new_password
,
1680 const uint32_t *new_version
)
1682 struct tevent_req
*req
;
1683 struct netlogon_creds_cli_ServerPasswordSet_state
*state
;
1684 struct tevent_req
*subreq
;
1687 req
= tevent_req_create(mem_ctx
, &state
,
1688 struct netlogon_creds_cli_ServerPasswordSet_state
);
1694 state
->context
= context
;
1695 state
->binding_handle
= b
;
1697 if (new_password
->length
< 14) {
1698 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1699 return tevent_req_post(req
, ev
);
1703 * netr_ServerPasswordSet
1705 mdfour(state
->samr_password
.hash
, new_password
->data
, new_password
->length
);
1708 * netr_ServerPasswordSet2
1710 ok
= set_pw_in_buffer(state
->samr_crypt_password
.data
,
1713 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1714 return tevent_req_post(req
, ev
);
1717 if (new_version
!= NULL
) {
1718 struct NL_PASSWORD_VERSION version
;
1719 uint32_t len
= IVAL(state
->samr_crypt_password
.data
, 512);
1720 uint32_t ofs
= 512 - len
;
1724 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1725 return tevent_req_post(req
, ev
);
1729 version
.ReservedField
= 0;
1730 version
.PasswordVersionNumber
= *new_version
;
1731 version
.PasswordVersionPresent
=
1732 NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT
;
1734 p
= state
->samr_crypt_password
.data
+ ofs
;
1735 SIVAL(p
, 0, version
.ReservedField
);
1736 SIVAL(p
, 4, version
.PasswordVersionNumber
);
1737 SIVAL(p
, 8, version
.PasswordVersionPresent
);
1740 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1741 context
->server
.computer
);
1742 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1743 return tevent_req_post(req
, ev
);
1746 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1748 &state
->auth_level
);
1750 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1752 if (tevent_req_nomem(subreq
, req
)) {
1753 return tevent_req_post(req
, ev
);
1756 tevent_req_set_callback(subreq
,
1757 netlogon_creds_cli_ServerPasswordSet_locked
,
1763 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1766 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1767 tevent_req_data(req
,
1768 struct netlogon_creds_cli_ServerPasswordSet_state
);
1770 if (state
->creds
== NULL
) {
1774 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
1775 state
->old_timeout
);
1777 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1778 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1779 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1780 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1781 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1782 TALLOC_FREE(state
->creds
);
1786 netlogon_creds_cli_delete(state
->context
, state
->creds
);
1787 TALLOC_FREE(state
->creds
);
1790 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
);
1792 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
)
1794 struct tevent_req
*req
=
1795 tevent_req_callback_data(subreq
,
1797 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1798 tevent_req_data(req
,
1799 struct netlogon_creds_cli_ServerPasswordSet_state
);
1802 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1804 TALLOC_FREE(subreq
);
1805 if (tevent_req_nterror(req
, status
)) {
1809 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
1810 switch (state
->auth_level
) {
1811 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1812 case DCERPC_AUTH_LEVEL_PRIVACY
:
1815 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1819 uint32_t tmp
= state
->creds
->negotiate_flags
;
1821 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
1823 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
1824 * it should be used, which means
1825 * we had a chance to verify no downgrade
1828 * This relies on netlogon_creds_cli_check*
1829 * being called before, as first request after
1832 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1837 state
->old_timeout
= dcerpc_binding_handle_set_timeout(
1838 state
->binding_handle
, 600000);
1841 * we defer all callbacks in order to cleanup
1842 * the database record.
1844 tevent_req_defer_callback(req
, state
->ev
);
1846 state
->tmp_creds
= *state
->creds
;
1847 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1849 ZERO_STRUCT(state
->rep_auth
);
1851 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1853 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1854 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
1855 state
->samr_crypt_password
.data
,
1858 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
1859 state
->samr_crypt_password
.data
,
1863 memcpy(state
->netr_crypt_password
.data
,
1864 state
->samr_crypt_password
.data
, 512);
1865 state
->netr_crypt_password
.length
=
1866 IVAL(state
->samr_crypt_password
.data
, 512);
1868 subreq
= dcerpc_netr_ServerPasswordSet2_send(state
, state
->ev
,
1869 state
->binding_handle
,
1870 state
->srv_name_slash
,
1871 state
->tmp_creds
.account_name
,
1872 state
->tmp_creds
.secure_channel_type
,
1873 state
->tmp_creds
.computer_name
,
1876 &state
->netr_crypt_password
);
1877 if (tevent_req_nomem(subreq
, req
)) {
1878 status
= NT_STATUS_NO_MEMORY
;
1879 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1883 netlogon_creds_des_encrypt(&state
->tmp_creds
,
1884 &state
->samr_password
);
1886 subreq
= dcerpc_netr_ServerPasswordSet_send(state
, state
->ev
,
1887 state
->binding_handle
,
1888 state
->srv_name_slash
,
1889 state
->tmp_creds
.account_name
,
1890 state
->tmp_creds
.secure_channel_type
,
1891 state
->tmp_creds
.computer_name
,
1894 &state
->samr_password
);
1895 if (tevent_req_nomem(subreq
, req
)) {
1896 status
= NT_STATUS_NO_MEMORY
;
1897 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1902 tevent_req_set_callback(subreq
,
1903 netlogon_creds_cli_ServerPasswordSet_done
,
1907 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
)
1909 struct tevent_req
*req
=
1910 tevent_req_callback_data(subreq
,
1912 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1913 tevent_req_data(req
,
1914 struct netlogon_creds_cli_ServerPasswordSet_state
);
1919 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1920 status
= dcerpc_netr_ServerPasswordSet2_recv(subreq
, state
,
1922 TALLOC_FREE(subreq
);
1923 if (tevent_req_nterror(req
, status
)) {
1924 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1928 status
= dcerpc_netr_ServerPasswordSet_recv(subreq
, state
,
1930 TALLOC_FREE(subreq
);
1931 if (tevent_req_nterror(req
, status
)) {
1932 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1937 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1938 &state
->rep_auth
.cred
);
1940 status
= NT_STATUS_ACCESS_DENIED
;
1941 tevent_req_nterror(req
, status
);
1942 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1946 if (tevent_req_nterror(req
, result
)) {
1947 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, result
);
1951 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
1952 state
->old_timeout
);
1954 *state
->creds
= state
->tmp_creds
;
1955 status
= netlogon_creds_cli_store(state
->context
,
1957 TALLOC_FREE(state
->creds
);
1958 if (tevent_req_nterror(req
, status
)) {
1959 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1963 tevent_req_done(req
);
1966 NTSTATUS
netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req
*req
)
1970 if (tevent_req_is_nterror(req
, &status
)) {
1971 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1972 tevent_req_received(req
);
1976 tevent_req_received(req
);
1977 return NT_STATUS_OK
;
1980 NTSTATUS
netlogon_creds_cli_ServerPasswordSet(
1981 struct netlogon_creds_cli_context
*context
,
1982 struct dcerpc_binding_handle
*b
,
1983 const DATA_BLOB
*new_password
,
1984 const uint32_t *new_version
)
1986 TALLOC_CTX
*frame
= talloc_stackframe();
1987 struct tevent_context
*ev
;
1988 struct tevent_req
*req
;
1989 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1991 ev
= samba_tevent_context_init(frame
);
1995 req
= netlogon_creds_cli_ServerPasswordSet_send(frame
, ev
, context
, b
,
2001 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2004 status
= netlogon_creds_cli_ServerPasswordSet_recv(req
);
2010 struct netlogon_creds_cli_LogonSamLogon_state
{
2011 struct tevent_context
*ev
;
2012 struct netlogon_creds_cli_context
*context
;
2013 struct dcerpc_binding_handle
*binding_handle
;
2015 char *srv_name_slash
;
2017 enum netr_LogonInfoClass logon_level
;
2018 const union netr_LogonLevel
*const_logon
;
2019 union netr_LogonLevel
*logon
;
2022 uint16_t validation_level
;
2023 union netr_Validation
*validation
;
2024 uint8_t authoritative
;
2027 * do we need encryption at the application layer?
2031 bool try_validation6
;
2034 * the read only credentials before we started the operation
2035 * used for netr_LogonSamLogonEx() if required (validation_level = 3).
2037 struct netlogon_creds_CredentialState
*ro_creds
;
2040 * The (locked) credentials used for the credential chain
2041 * used for netr_LogonSamLogonWithFlags() or
2042 * netr_LogonSamLogonWith().
2044 struct netlogon_creds_CredentialState
*lk_creds
;
2047 * While we have locked the global credentials (lk_creds above)
2048 * we operate an a temporary copy, because a server
2049 * may not support netr_LogonSamLogonWithFlags() and
2050 * didn't process our netr_Authenticator, so we need to
2051 * restart from lk_creds.
2053 struct netlogon_creds_CredentialState tmp_creds
;
2054 struct netr_Authenticator req_auth
;
2055 struct netr_Authenticator rep_auth
;
2058 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
);
2059 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2062 struct tevent_req
*netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX
*mem_ctx
,
2063 struct tevent_context
*ev
,
2064 struct netlogon_creds_cli_context
*context
,
2065 struct dcerpc_binding_handle
*b
,
2066 enum netr_LogonInfoClass logon_level
,
2067 const union netr_LogonLevel
*logon
,
2070 struct tevent_req
*req
;
2071 struct netlogon_creds_cli_LogonSamLogon_state
*state
;
2073 req
= tevent_req_create(mem_ctx
, &state
,
2074 struct netlogon_creds_cli_LogonSamLogon_state
);
2080 state
->context
= context
;
2081 state
->binding_handle
= b
;
2083 state
->logon_level
= logon_level
;
2084 state
->const_logon
= logon
;
2085 state
->flags
= flags
;
2087 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2088 context
->server
.computer
);
2089 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2090 return tevent_req_post(req
, ev
);
2093 switch (logon_level
) {
2094 case NetlogonInteractiveInformation
:
2095 case NetlogonInteractiveTransitiveInformation
:
2096 case NetlogonServiceInformation
:
2097 case NetlogonServiceTransitiveInformation
:
2098 case NetlogonGenericInformation
:
2099 state
->user_encrypt
= true;
2102 case NetlogonNetworkInformation
:
2103 case NetlogonNetworkTransitiveInformation
:
2107 state
->validation
= talloc_zero(state
, union netr_Validation
);
2108 if (tevent_req_nomem(state
->validation
, req
)) {
2109 return tevent_req_post(req
, ev
);
2112 netlogon_creds_cli_LogonSamLogon_start(req
);
2113 if (!tevent_req_is_in_progress(req
)) {
2114 return tevent_req_post(req
, ev
);
2118 * we defer all callbacks in order to cleanup
2119 * the database record.
2121 tevent_req_defer_callback(req
, state
->ev
);
2125 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2128 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2129 tevent_req_data(req
,
2130 struct netlogon_creds_cli_LogonSamLogon_state
);
2132 if (state
->lk_creds
== NULL
) {
2136 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2138 * This is a hack to recover from a bug in old
2139 * Samba servers, when LogonSamLogonEx() fails:
2141 * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
2143 * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2145 * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE,
2146 * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR
2147 * If the sign/seal check fails.
2149 * In that case we need to cleanup the netlogon session.
2151 * It's the job of the caller to disconnect the current
2152 * connection, if netlogon_creds_cli_LogonSamLogon()
2153 * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2155 if (!state
->context
->server
.try_logon_with
) {
2156 status
= NT_STATUS_NETWORK_ACCESS_DENIED
;
2160 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2161 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2162 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2163 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2164 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2165 TALLOC_FREE(state
->lk_creds
);
2169 netlogon_creds_cli_delete(state
->context
, state
->lk_creds
);
2170 TALLOC_FREE(state
->lk_creds
);
2173 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
);
2175 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
)
2177 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2178 tevent_req_data(req
,
2179 struct netlogon_creds_cli_LogonSamLogon_state
);
2180 struct tevent_req
*subreq
;
2182 enum dcerpc_AuthType auth_type
;
2183 enum dcerpc_AuthLevel auth_level
;
2185 TALLOC_FREE(state
->ro_creds
);
2186 TALLOC_FREE(state
->logon
);
2187 ZERO_STRUCTP(state
->validation
);
2189 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2190 &auth_type
, &auth_level
);
2192 state
->try_logon_ex
= state
->context
->server
.try_logon_ex
;
2193 state
->try_validation6
= state
->context
->server
.try_validation6
;
2195 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
2196 state
->try_logon_ex
= false;
2199 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
2200 state
->try_validation6
= false;
2203 if (state
->try_logon_ex
) {
2204 if (state
->try_validation6
) {
2205 state
->validation_level
= 6;
2207 state
->validation_level
= 3;
2208 state
->user_encrypt
= true;
2211 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2213 state
->const_logon
);
2214 if (tevent_req_nomem(state
->logon
, req
)) {
2215 status
= NT_STATUS_NO_MEMORY
;
2216 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2220 if (state
->user_encrypt
) {
2221 status
= netlogon_creds_cli_get(state
->context
,
2224 if (!NT_STATUS_IS_OK(status
)) {
2225 status
= NT_STATUS_ACCESS_DENIED
;
2226 tevent_req_nterror(req
, status
);
2227 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2231 netlogon_creds_encrypt_samlogon_logon(state
->ro_creds
,
2236 subreq
= dcerpc_netr_LogonSamLogonEx_send(state
, state
->ev
,
2237 state
->binding_handle
,
2238 state
->srv_name_slash
,
2239 state
->context
->client
.computer
,
2242 state
->validation_level
,
2244 &state
->authoritative
,
2246 if (tevent_req_nomem(subreq
, req
)) {
2247 status
= NT_STATUS_NO_MEMORY
;
2248 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2251 tevent_req_set_callback(subreq
,
2252 netlogon_creds_cli_LogonSamLogon_done
,
2257 if (state
->lk_creds
== NULL
) {
2258 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2260 if (tevent_req_nomem(subreq
, req
)) {
2261 status
= NT_STATUS_NO_MEMORY
;
2262 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2265 tevent_req_set_callback(subreq
,
2266 netlogon_creds_cli_LogonSamLogon_done
,
2271 state
->tmp_creds
= *state
->lk_creds
;
2272 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2274 ZERO_STRUCT(state
->rep_auth
);
2276 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2278 state
->const_logon
);
2279 if (tevent_req_nomem(state
->logon
, req
)) {
2280 status
= NT_STATUS_NO_MEMORY
;
2281 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2285 netlogon_creds_encrypt_samlogon_logon(&state
->tmp_creds
,
2289 state
->validation_level
= 3;
2291 if (state
->context
->server
.try_logon_with
) {
2292 subreq
= dcerpc_netr_LogonSamLogonWithFlags_send(state
, state
->ev
,
2293 state
->binding_handle
,
2294 state
->srv_name_slash
,
2295 state
->context
->client
.computer
,
2300 state
->validation_level
,
2302 &state
->authoritative
,
2304 if (tevent_req_nomem(subreq
, req
)) {
2305 status
= NT_STATUS_NO_MEMORY
;
2306 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2312 subreq
= dcerpc_netr_LogonSamLogon_send(state
, state
->ev
,
2313 state
->binding_handle
,
2314 state
->srv_name_slash
,
2315 state
->context
->client
.computer
,
2320 state
->validation_level
,
2322 &state
->authoritative
);
2323 if (tevent_req_nomem(subreq
, req
)) {
2324 status
= NT_STATUS_NO_MEMORY
;
2325 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2330 tevent_req_set_callback(subreq
,
2331 netlogon_creds_cli_LogonSamLogon_done
,
2335 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
)
2337 struct tevent_req
*req
=
2338 tevent_req_callback_data(subreq
,
2340 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2341 tevent_req_data(req
,
2342 struct netlogon_creds_cli_LogonSamLogon_state
);
2347 if (state
->try_logon_ex
) {
2348 status
= dcerpc_netr_LogonSamLogonEx_recv(subreq
,
2351 TALLOC_FREE(subreq
);
2352 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2353 state
->context
->server
.try_validation6
= false;
2354 state
->context
->server
.try_logon_ex
= false;
2355 netlogon_creds_cli_LogonSamLogon_start(req
);
2358 if (tevent_req_nterror(req
, status
)) {
2359 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2363 if ((state
->validation_level
== 6) &&
2364 (NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_INFO_CLASS
) ||
2365 NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_PARAMETER
) ||
2366 NT_STATUS_EQUAL(result
, NT_STATUS_BUFFER_TOO_SMALL
)))
2368 state
->context
->server
.try_validation6
= false;
2369 netlogon_creds_cli_LogonSamLogon_start(req
);
2373 if (tevent_req_nterror(req
, result
)) {
2374 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2378 if (state
->ro_creds
== NULL
) {
2379 tevent_req_done(req
);
2383 ok
= netlogon_creds_cli_validate(state
->context
, state
->ro_creds
);
2386 * We got a race, lets retry with on authenticator
2389 * netlogon_creds_cli_LogonSamLogon_start()
2390 * will TALLOC_FREE(state->ro_creds);
2392 state
->try_logon_ex
= false;
2393 netlogon_creds_cli_LogonSamLogon_start(req
);
2397 netlogon_creds_decrypt_samlogon_validation(state
->ro_creds
,
2398 state
->validation_level
,
2401 tevent_req_done(req
);
2405 if (state
->lk_creds
== NULL
) {
2406 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2408 TALLOC_FREE(subreq
);
2409 if (tevent_req_nterror(req
, status
)) {
2410 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2414 netlogon_creds_cli_LogonSamLogon_start(req
);
2418 if (state
->context
->server
.try_logon_with
) {
2419 status
= dcerpc_netr_LogonSamLogonWithFlags_recv(subreq
,
2422 TALLOC_FREE(subreq
);
2423 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2424 state
->context
->server
.try_logon_with
= false;
2425 netlogon_creds_cli_LogonSamLogon_start(req
);
2428 if (tevent_req_nterror(req
, status
)) {
2429 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2433 status
= dcerpc_netr_LogonSamLogon_recv(subreq
,
2436 TALLOC_FREE(subreq
);
2437 if (tevent_req_nterror(req
, status
)) {
2438 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2443 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2444 &state
->rep_auth
.cred
);
2446 status
= NT_STATUS_ACCESS_DENIED
;
2447 tevent_req_nterror(req
, status
);
2448 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2452 *state
->lk_creds
= state
->tmp_creds
;
2453 status
= netlogon_creds_cli_store(state
->context
,
2455 TALLOC_FREE(state
->lk_creds
);
2457 if (tevent_req_nterror(req
, status
)) {
2458 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2462 if (tevent_req_nterror(req
, result
)) {
2463 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2467 netlogon_creds_decrypt_samlogon_validation(&state
->tmp_creds
,
2468 state
->validation_level
,
2471 tevent_req_done(req
);
2474 NTSTATUS
netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req
*req
,
2475 TALLOC_CTX
*mem_ctx
,
2476 uint16_t *validation_level
,
2477 union netr_Validation
**validation
,
2478 uint8_t *authoritative
,
2481 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2482 tevent_req_data(req
,
2483 struct netlogon_creds_cli_LogonSamLogon_state
);
2486 /* authoritative is also returned on error */
2487 *authoritative
= state
->authoritative
;
2489 if (tevent_req_is_nterror(req
, &status
)) {
2490 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2491 tevent_req_received(req
);
2495 *validation_level
= state
->validation_level
;
2496 *validation
= talloc_move(mem_ctx
, &state
->validation
);
2497 *flags
= state
->flags
;
2499 tevent_req_received(req
);
2500 return NT_STATUS_OK
;
2503 NTSTATUS
netlogon_creds_cli_LogonSamLogon(
2504 struct netlogon_creds_cli_context
*context
,
2505 struct dcerpc_binding_handle
*b
,
2506 enum netr_LogonInfoClass logon_level
,
2507 const union netr_LogonLevel
*logon
,
2508 TALLOC_CTX
*mem_ctx
,
2509 uint16_t *validation_level
,
2510 union netr_Validation
**validation
,
2511 uint8_t *authoritative
,
2514 TALLOC_CTX
*frame
= talloc_stackframe();
2515 struct tevent_context
*ev
;
2516 struct tevent_req
*req
;
2517 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2519 ev
= samba_tevent_context_init(frame
);
2523 req
= netlogon_creds_cli_LogonSamLogon_send(frame
, ev
, context
, b
,
2529 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2532 status
= netlogon_creds_cli_LogonSamLogon_recv(req
, mem_ctx
,
2542 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
{
2543 struct tevent_context
*ev
;
2544 struct netlogon_creds_cli_context
*context
;
2545 struct dcerpc_binding_handle
*binding_handle
;
2547 char *srv_name_slash
;
2548 enum dcerpc_AuthType auth_type
;
2549 enum dcerpc_AuthLevel auth_level
;
2551 const char *site_name
;
2553 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
;
2555 struct netlogon_creds_CredentialState
*creds
;
2556 struct netlogon_creds_CredentialState tmp_creds
;
2557 struct netr_Authenticator req_auth
;
2558 struct netr_Authenticator rep_auth
;
2561 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2563 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
);
2565 struct tevent_req
*netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(TALLOC_CTX
*mem_ctx
,
2566 struct tevent_context
*ev
,
2567 struct netlogon_creds_cli_context
*context
,
2568 struct dcerpc_binding_handle
*b
,
2569 const char *site_name
,
2571 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2573 struct tevent_req
*req
;
2574 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
;
2575 struct tevent_req
*subreq
;
2577 req
= tevent_req_create(mem_ctx
, &state
,
2578 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2584 state
->context
= context
;
2585 state
->binding_handle
= b
;
2587 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2588 context
->server
.computer
);
2589 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2590 return tevent_req_post(req
, ev
);
2593 state
->site_name
= site_name
;
2594 state
->dns_ttl
= dns_ttl
;
2595 state
->dns_names
= dns_names
;
2597 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2599 &state
->auth_level
);
2601 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2603 if (tevent_req_nomem(subreq
, req
)) {
2604 return tevent_req_post(req
, ev
);
2607 tevent_req_set_callback(subreq
,
2608 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked
,
2614 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2617 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2618 tevent_req_data(req
,
2619 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2621 if (state
->creds
== NULL
) {
2625 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2626 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2627 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2628 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2629 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2630 TALLOC_FREE(state
->creds
);
2634 netlogon_creds_cli_delete(state
->context
, state
->creds
);
2635 TALLOC_FREE(state
->creds
);
2638 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
);
2640 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
)
2642 struct tevent_req
*req
=
2643 tevent_req_callback_data(subreq
,
2645 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2646 tevent_req_data(req
,
2647 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2650 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2652 TALLOC_FREE(subreq
);
2653 if (tevent_req_nterror(req
, status
)) {
2657 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
2658 switch (state
->auth_level
) {
2659 case DCERPC_AUTH_LEVEL_INTEGRITY
:
2660 case DCERPC_AUTH_LEVEL_PRIVACY
:
2663 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2667 uint32_t tmp
= state
->creds
->negotiate_flags
;
2669 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
2671 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
2672 * it should be used, which means
2673 * we had a chance to verify no downgrade
2676 * This relies on netlogon_creds_cli_check*
2677 * being called before, as first request after
2680 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2686 * we defer all callbacks in order to cleanup
2687 * the database record.
2689 tevent_req_defer_callback(req
, state
->ev
);
2691 state
->tmp_creds
= *state
->creds
;
2692 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2694 ZERO_STRUCT(state
->rep_auth
);
2696 subreq
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_send(state
, state
->ev
,
2697 state
->binding_handle
,
2698 state
->srv_name_slash
,
2699 state
->tmp_creds
.computer_name
,
2705 if (tevent_req_nomem(subreq
, req
)) {
2706 status
= NT_STATUS_NO_MEMORY
;
2707 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2711 tevent_req_set_callback(subreq
,
2712 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done
,
2716 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
)
2718 struct tevent_req
*req
=
2719 tevent_req_callback_data(subreq
,
2721 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2722 tevent_req_data(req
,
2723 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2729 * We use state->dns_names as the memory context, as this is
2730 * the only in/out variable and it has been overwritten by the
2731 * out parameter from the server.
2733 * We need to preserve the return value until the caller can use it.
2735 status
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_recv(subreq
, state
->dns_names
,
2737 TALLOC_FREE(subreq
);
2738 if (tevent_req_nterror(req
, status
)) {
2739 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2743 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2744 &state
->rep_auth
.cred
);
2746 status
= NT_STATUS_ACCESS_DENIED
;
2747 tevent_req_nterror(req
, status
);
2748 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2752 *state
->creds
= state
->tmp_creds
;
2753 status
= netlogon_creds_cli_store(state
->context
,
2755 TALLOC_FREE(state
->creds
);
2757 if (tevent_req_nterror(req
, status
)) {
2758 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2762 if (tevent_req_nterror(req
, result
)) {
2763 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, result
);
2767 tevent_req_done(req
);
2770 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(struct tevent_req
*req
)
2774 if (tevent_req_is_nterror(req
, &status
)) {
2775 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2776 tevent_req_received(req
);
2780 tevent_req_received(req
);
2781 return NT_STATUS_OK
;
2784 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(
2785 struct netlogon_creds_cli_context
*context
,
2786 struct dcerpc_binding_handle
*b
,
2787 const char *site_name
,
2789 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2791 TALLOC_CTX
*frame
= talloc_stackframe();
2792 struct tevent_context
*ev
;
2793 struct tevent_req
*req
;
2794 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2796 ev
= samba_tevent_context_init(frame
);
2800 req
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(frame
, ev
, context
, b
,
2807 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2810 status
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(req
);
2816 struct netlogon_creds_cli_ServerGetTrustInfo_state
{
2817 struct tevent_context
*ev
;
2818 struct netlogon_creds_cli_context
*context
;
2819 struct dcerpc_binding_handle
*binding_handle
;
2821 char *srv_name_slash
;
2822 enum dcerpc_AuthType auth_type
;
2823 enum dcerpc_AuthLevel auth_level
;
2825 struct samr_Password new_owf_password
;
2826 struct samr_Password old_owf_password
;
2827 struct netr_TrustInfo
*trust_info
;
2829 struct netlogon_creds_CredentialState
*creds
;
2830 struct netlogon_creds_CredentialState tmp_creds
;
2831 struct netr_Authenticator req_auth
;
2832 struct netr_Authenticator rep_auth
;
2835 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
2837 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
);
2839 struct tevent_req
*netlogon_creds_cli_ServerGetTrustInfo_send(TALLOC_CTX
*mem_ctx
,
2840 struct tevent_context
*ev
,
2841 struct netlogon_creds_cli_context
*context
,
2842 struct dcerpc_binding_handle
*b
)
2844 struct tevent_req
*req
;
2845 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
;
2846 struct tevent_req
*subreq
;
2848 req
= tevent_req_create(mem_ctx
, &state
,
2849 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2855 state
->context
= context
;
2856 state
->binding_handle
= b
;
2858 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2859 context
->server
.computer
);
2860 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2861 return tevent_req_post(req
, ev
);
2864 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2866 &state
->auth_level
);
2868 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2870 if (tevent_req_nomem(subreq
, req
)) {
2871 return tevent_req_post(req
, ev
);
2874 tevent_req_set_callback(subreq
,
2875 netlogon_creds_cli_ServerGetTrustInfo_locked
,
2881 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
2884 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2885 tevent_req_data(req
,
2886 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2888 if (state
->creds
== NULL
) {
2892 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2893 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2894 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2895 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2896 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2897 TALLOC_FREE(state
->creds
);
2901 netlogon_creds_cli_delete(state
->context
, state
->creds
);
2902 TALLOC_FREE(state
->creds
);
2905 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
);
2907 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
)
2909 struct tevent_req
*req
=
2910 tevent_req_callback_data(subreq
,
2912 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2913 tevent_req_data(req
,
2914 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2917 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2919 TALLOC_FREE(subreq
);
2920 if (tevent_req_nterror(req
, status
)) {
2924 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
2925 switch (state
->auth_level
) {
2926 case DCERPC_AUTH_LEVEL_PRIVACY
:
2929 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2933 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2938 * we defer all callbacks in order to cleanup
2939 * the database record.
2941 tevent_req_defer_callback(req
, state
->ev
);
2943 state
->tmp_creds
= *state
->creds
;
2944 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2946 ZERO_STRUCT(state
->rep_auth
);
2948 subreq
= dcerpc_netr_ServerGetTrustInfo_send(state
, state
->ev
,
2949 state
->binding_handle
,
2950 state
->srv_name_slash
,
2951 state
->tmp_creds
.account_name
,
2952 state
->tmp_creds
.secure_channel_type
,
2953 state
->tmp_creds
.computer_name
,
2956 &state
->new_owf_password
,
2957 &state
->old_owf_password
,
2958 &state
->trust_info
);
2959 if (tevent_req_nomem(subreq
, req
)) {
2960 status
= NT_STATUS_NO_MEMORY
;
2961 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
2965 tevent_req_set_callback(subreq
,
2966 netlogon_creds_cli_ServerGetTrustInfo_done
,
2970 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
)
2972 struct tevent_req
*req
=
2973 tevent_req_callback_data(subreq
,
2975 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2976 tevent_req_data(req
,
2977 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2980 const struct samr_Password zero
= {};
2985 * We use state->dns_names as the memory context, as this is
2986 * the only in/out variable and it has been overwritten by the
2987 * out parameter from the server.
2989 * We need to preserve the return value until the caller can use it.
2991 status
= dcerpc_netr_ServerGetTrustInfo_recv(subreq
, state
, &result
);
2992 TALLOC_FREE(subreq
);
2993 if (tevent_req_nterror(req
, status
)) {
2994 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
2998 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2999 &state
->rep_auth
.cred
);
3001 status
= NT_STATUS_ACCESS_DENIED
;
3002 tevent_req_nterror(req
, status
);
3003 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3007 cmp
= memcmp(state
->new_owf_password
.hash
,
3008 zero
.hash
, sizeof(zero
.hash
));
3010 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3011 &state
->new_owf_password
);
3013 cmp
= memcmp(state
->old_owf_password
.hash
,
3014 zero
.hash
, sizeof(zero
.hash
));
3016 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3017 &state
->old_owf_password
);
3020 *state
->creds
= state
->tmp_creds
;
3021 status
= netlogon_creds_cli_store(state
->context
,
3023 TALLOC_FREE(state
->creds
);
3024 if (tevent_req_nterror(req
, status
)) {
3025 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3029 if (tevent_req_nterror(req
, result
)) {
3030 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, result
);
3034 tevent_req_done(req
);
3037 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo_recv(struct tevent_req
*req
,
3038 TALLOC_CTX
*mem_ctx
,
3039 struct samr_Password
*new_owf_password
,
3040 struct samr_Password
*old_owf_password
,
3041 struct netr_TrustInfo
**trust_info
)
3043 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3044 tevent_req_data(req
,
3045 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3048 if (tevent_req_is_nterror(req
, &status
)) {
3049 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3050 tevent_req_received(req
);
3054 if (new_owf_password
!= NULL
) {
3055 *new_owf_password
= state
->new_owf_password
;
3057 if (old_owf_password
!= NULL
) {
3058 *old_owf_password
= state
->old_owf_password
;
3060 if (trust_info
!= NULL
) {
3061 *trust_info
= talloc_move(mem_ctx
, &state
->trust_info
);
3064 tevent_req_received(req
);
3065 return NT_STATUS_OK
;
3068 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo(
3069 struct netlogon_creds_cli_context
*context
,
3070 struct dcerpc_binding_handle
*b
,
3071 TALLOC_CTX
*mem_ctx
,
3072 struct samr_Password
*new_owf_password
,
3073 struct samr_Password
*old_owf_password
,
3074 struct netr_TrustInfo
**trust_info
)
3076 TALLOC_CTX
*frame
= talloc_stackframe();
3077 struct tevent_context
*ev
;
3078 struct tevent_req
*req
;
3079 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3081 ev
= samba_tevent_context_init(frame
);
3085 req
= netlogon_creds_cli_ServerGetTrustInfo_send(frame
, ev
, context
, b
);
3089 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3092 status
= netlogon_creds_cli_ServerGetTrustInfo_recv(req
,
3102 struct netlogon_creds_cli_GetForestTrustInformation_state
{
3103 struct tevent_context
*ev
;
3104 struct netlogon_creds_cli_context
*context
;
3105 struct dcerpc_binding_handle
*binding_handle
;
3107 char *srv_name_slash
;
3108 enum dcerpc_AuthType auth_type
;
3109 enum dcerpc_AuthLevel auth_level
;
3112 struct lsa_ForestTrustInformation
*forest_trust_info
;
3114 struct netlogon_creds_CredentialState
*creds
;
3115 struct netlogon_creds_CredentialState tmp_creds
;
3116 struct netr_Authenticator req_auth
;
3117 struct netr_Authenticator rep_auth
;
3120 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3122 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
);
3124 struct tevent_req
*netlogon_creds_cli_GetForestTrustInformation_send(TALLOC_CTX
*mem_ctx
,
3125 struct tevent_context
*ev
,
3126 struct netlogon_creds_cli_context
*context
,
3127 struct dcerpc_binding_handle
*b
)
3129 struct tevent_req
*req
;
3130 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
;
3131 struct tevent_req
*subreq
;
3133 req
= tevent_req_create(mem_ctx
, &state
,
3134 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3140 state
->context
= context
;
3141 state
->binding_handle
= b
;
3143 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3144 context
->server
.computer
);
3145 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3146 return tevent_req_post(req
, ev
);
3151 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3153 &state
->auth_level
);
3155 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3157 if (tevent_req_nomem(subreq
, req
)) {
3158 return tevent_req_post(req
, ev
);
3161 tevent_req_set_callback(subreq
,
3162 netlogon_creds_cli_GetForestTrustInformation_locked
,
3168 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3171 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3172 tevent_req_data(req
,
3173 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3175 if (state
->creds
== NULL
) {
3179 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3180 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3181 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3182 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3183 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3184 TALLOC_FREE(state
->creds
);
3188 netlogon_creds_cli_delete(state
->context
, state
->creds
);
3189 TALLOC_FREE(state
->creds
);
3192 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
);
3194 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
)
3196 struct tevent_req
*req
=
3197 tevent_req_callback_data(subreq
,
3199 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3200 tevent_req_data(req
,
3201 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3204 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3206 TALLOC_FREE(subreq
);
3207 if (tevent_req_nterror(req
, status
)) {
3211 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3212 switch (state
->auth_level
) {
3213 case DCERPC_AUTH_LEVEL_INTEGRITY
:
3214 case DCERPC_AUTH_LEVEL_PRIVACY
:
3217 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3221 uint32_t tmp
= state
->creds
->negotiate_flags
;
3223 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
3225 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3226 * it should be used, which means
3227 * we had a chance to verify no downgrade
3230 * This relies on netlogon_creds_cli_check*
3231 * being called before, as first request after
3234 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3240 * we defer all callbacks in order to cleanup
3241 * the database record.
3243 tevent_req_defer_callback(req
, state
->ev
);
3245 state
->tmp_creds
= *state
->creds
;
3246 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3248 ZERO_STRUCT(state
->rep_auth
);
3250 subreq
= dcerpc_netr_GetForestTrustInformation_send(state
, state
->ev
,
3251 state
->binding_handle
,
3252 state
->srv_name_slash
,
3253 state
->tmp_creds
.computer_name
,
3257 &state
->forest_trust_info
);
3258 if (tevent_req_nomem(subreq
, req
)) {
3259 status
= NT_STATUS_NO_MEMORY
;
3260 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3264 tevent_req_set_callback(subreq
,
3265 netlogon_creds_cli_GetForestTrustInformation_done
,
3269 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
)
3271 struct tevent_req
*req
=
3272 tevent_req_callback_data(subreq
,
3274 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3275 tevent_req_data(req
,
3276 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3282 * We use state->dns_names as the memory context, as this is
3283 * the only in/out variable and it has been overwritten by the
3284 * out parameter from the server.
3286 * We need to preserve the return value until the caller can use it.
3288 status
= dcerpc_netr_GetForestTrustInformation_recv(subreq
, state
, &result
);
3289 TALLOC_FREE(subreq
);
3290 if (tevent_req_nterror(req
, status
)) {
3291 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3295 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3296 &state
->rep_auth
.cred
);
3298 status
= NT_STATUS_ACCESS_DENIED
;
3299 tevent_req_nterror(req
, status
);
3300 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3304 *state
->creds
= state
->tmp_creds
;
3305 status
= netlogon_creds_cli_store(state
->context
,
3307 TALLOC_FREE(state
->creds
);
3309 if (tevent_req_nterror(req
, status
)) {
3310 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3314 if (tevent_req_nterror(req
, result
)) {
3315 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, result
);
3319 tevent_req_done(req
);
3322 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation_recv(struct tevent_req
*req
,
3323 TALLOC_CTX
*mem_ctx
,
3324 struct lsa_ForestTrustInformation
**forest_trust_info
)
3326 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3327 tevent_req_data(req
,
3328 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3331 if (tevent_req_is_nterror(req
, &status
)) {
3332 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3333 tevent_req_received(req
);
3337 *forest_trust_info
= talloc_move(mem_ctx
, &state
->forest_trust_info
);
3339 tevent_req_received(req
);
3340 return NT_STATUS_OK
;
3343 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation(
3344 struct netlogon_creds_cli_context
*context
,
3345 struct dcerpc_binding_handle
*b
,
3346 TALLOC_CTX
*mem_ctx
,
3347 struct lsa_ForestTrustInformation
**forest_trust_info
)
3349 TALLOC_CTX
*frame
= talloc_stackframe();
3350 struct tevent_context
*ev
;
3351 struct tevent_req
*req
;
3352 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3354 ev
= samba_tevent_context_init(frame
);
3358 req
= netlogon_creds_cli_GetForestTrustInformation_send(frame
, ev
, context
, b
);
3362 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3365 status
= netlogon_creds_cli_GetForestTrustInformation_recv(req
,
3373 struct netlogon_creds_cli_SendToSam_state
{
3374 struct tevent_context
*ev
;
3375 struct netlogon_creds_cli_context
*context
;
3376 struct dcerpc_binding_handle
*binding_handle
;
3378 char *srv_name_slash
;
3379 enum dcerpc_AuthType auth_type
;
3380 enum dcerpc_AuthLevel auth_level
;
3384 struct netlogon_creds_CredentialState
*creds
;
3385 struct netlogon_creds_CredentialState tmp_creds
;
3386 struct netr_Authenticator req_auth
;
3387 struct netr_Authenticator rep_auth
;
3390 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req
*req
,
3392 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req
*subreq
);
3394 struct tevent_req
*netlogon_creds_cli_SendToSam_send(TALLOC_CTX
*mem_ctx
,
3395 struct tevent_context
*ev
,
3396 struct netlogon_creds_cli_context
*context
,
3397 struct dcerpc_binding_handle
*b
,
3398 struct netr_SendToSamBase
*message
)
3400 struct tevent_req
*req
;
3401 struct netlogon_creds_cli_SendToSam_state
*state
;
3402 struct tevent_req
*subreq
;
3403 enum ndr_err_code ndr_err
;
3405 req
= tevent_req_create(mem_ctx
, &state
,
3406 struct netlogon_creds_cli_SendToSam_state
);
3412 state
->context
= context
;
3413 state
->binding_handle
= b
;
3415 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3416 context
->server
.computer
);
3417 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3418 return tevent_req_post(req
, ev
);
3421 ndr_err
= ndr_push_struct_blob(&state
->opaque
, mem_ctx
, message
,
3422 (ndr_push_flags_fn_t
)ndr_push_netr_SendToSamBase
);
3423 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
3424 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
3425 tevent_req_nterror(req
, status
);
3426 return tevent_req_post(req
, ev
);
3429 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3431 &state
->auth_level
);
3433 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3435 if (tevent_req_nomem(subreq
, req
)) {
3436 return tevent_req_post(req
, ev
);
3439 tevent_req_set_callback(subreq
,
3440 netlogon_creds_cli_SendToSam_locked
,
3446 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req
*req
,
3449 struct netlogon_creds_cli_SendToSam_state
*state
=
3450 tevent_req_data(req
,
3451 struct netlogon_creds_cli_SendToSam_state
);
3453 if (state
->creds
== NULL
) {
3457 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3458 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3459 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3460 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3461 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3462 TALLOC_FREE(state
->creds
);
3466 netlogon_creds_cli_delete(state
->context
, state
->creds
);
3467 TALLOC_FREE(state
->creds
);
3470 static void netlogon_creds_cli_SendToSam_done(struct tevent_req
*subreq
);
3472 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req
*subreq
)
3474 struct tevent_req
*req
=
3475 tevent_req_callback_data(subreq
,
3477 struct netlogon_creds_cli_SendToSam_state
*state
=
3478 tevent_req_data(req
,
3479 struct netlogon_creds_cli_SendToSam_state
);
3482 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3484 TALLOC_FREE(subreq
);
3485 if (tevent_req_nterror(req
, status
)) {
3489 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3490 switch (state
->auth_level
) {
3491 case DCERPC_AUTH_LEVEL_INTEGRITY
:
3492 case DCERPC_AUTH_LEVEL_PRIVACY
:
3495 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3499 uint32_t tmp
= state
->creds
->negotiate_flags
;
3501 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
3503 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3504 * it should be used, which means
3505 * we had a chance to verify no downgrade
3508 * This relies on netlogon_creds_cli_check*
3509 * being called before, as first request after
3512 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3518 * we defer all callbacks in order to cleanup
3519 * the database record.
3521 tevent_req_defer_callback(req
, state
->ev
);
3523 state
->tmp_creds
= *state
->creds
;
3524 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3526 ZERO_STRUCT(state
->rep_auth
);
3528 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
3529 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
3531 state
->opaque
.length
);
3533 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
3535 state
->opaque
.length
);
3538 subreq
= dcerpc_netr_NetrLogonSendToSam_send(state
, state
->ev
,
3539 state
->binding_handle
,
3540 state
->srv_name_slash
,
3541 state
->tmp_creds
.computer_name
,
3545 state
->opaque
.length
);
3546 if (tevent_req_nomem(subreq
, req
)) {
3547 status
= NT_STATUS_NO_MEMORY
;
3548 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3552 tevent_req_set_callback(subreq
,
3553 netlogon_creds_cli_SendToSam_done
,
3557 static void netlogon_creds_cli_SendToSam_done(struct tevent_req
*subreq
)
3559 struct tevent_req
*req
=
3560 tevent_req_callback_data(subreq
,
3562 struct netlogon_creds_cli_SendToSam_state
*state
=
3563 tevent_req_data(req
,
3564 struct netlogon_creds_cli_SendToSam_state
);
3569 status
= dcerpc_netr_NetrLogonSendToSam_recv(subreq
, state
, &result
);
3570 TALLOC_FREE(subreq
);
3571 if (tevent_req_nterror(req
, status
)) {
3572 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3576 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3577 &state
->rep_auth
.cred
);
3579 status
= NT_STATUS_ACCESS_DENIED
;
3580 tevent_req_nterror(req
, status
);
3581 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3585 *state
->creds
= state
->tmp_creds
;
3586 status
= netlogon_creds_cli_store(state
->context
,
3588 TALLOC_FREE(state
->creds
);
3590 if (tevent_req_nterror(req
, status
)) {
3591 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3596 * Creds must be stored before we send back application errors
3597 * e.g. NT_STATUS_NOT_IMPLEMENTED
3599 if (tevent_req_nterror(req
, result
)) {
3600 netlogon_creds_cli_SendToSam_cleanup(req
, result
);
3604 tevent_req_done(req
);
3607 NTSTATUS
netlogon_creds_cli_SendToSam(struct netlogon_creds_cli_context
*context
,
3608 struct dcerpc_binding_handle
*b
,
3609 struct netr_SendToSamBase
*message
)
3611 TALLOC_CTX
*frame
= talloc_stackframe();
3612 struct tevent_context
*ev
;
3613 struct tevent_req
*req
;
3614 NTSTATUS status
= NT_STATUS_OK
;
3616 ev
= samba_tevent_context_init(frame
);
3620 req
= netlogon_creds_cli_SendToSam_send(frame
, ev
, context
, b
, message
);
3624 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3628 /* Ignore the result */