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 TALLOC_CTX
*frame
= talloc_stackframe();
115 char *_key_name
= NULL
;
116 char *server_netbios_name
= NULL
;
121 context
= talloc_zero(mem_ctx
, struct netlogon_creds_cli_context
);
122 if (context
== NULL
) {
124 return NT_STATUS_NO_MEMORY
;
127 context
->client
.computer
= talloc_strdup(context
, client_computer
);
128 if (context
->client
.computer
== NULL
) {
129 TALLOC_FREE(context
);
131 return NT_STATUS_NO_MEMORY
;
134 context
->client
.account
= talloc_strdup(context
, client_account
);
135 if (context
->client
.account
== NULL
) {
136 TALLOC_FREE(context
);
138 return NT_STATUS_NO_MEMORY
;
141 context
->client
.proposed_flags
= proposed_flags
;
142 context
->client
.required_flags
= required_flags
;
143 context
->client
.type
= type
;
144 context
->client
.auth_level
= auth_level
;
146 context
->server
.computer
= talloc_strdup(context
, server_computer
);
147 if (context
->server
.computer
== NULL
) {
148 TALLOC_FREE(context
);
150 return NT_STATUS_NO_MEMORY
;
153 context
->server
.netbios_domain
= talloc_strdup(context
, server_netbios_domain
);
154 if (context
->server
.netbios_domain
== NULL
) {
155 TALLOC_FREE(context
);
157 return NT_STATUS_NO_MEMORY
;
160 context
->server
.dns_domain
= talloc_strdup(context
, server_dns_domain
);
161 if (context
->server
.dns_domain
== NULL
) {
162 TALLOC_FREE(context
);
164 return NT_STATUS_NO_MEMORY
;
169 * Force the callers to provide a unique
170 * value for server_computer and use this directly.
172 * For now we have to deal with
173 * "HOSTNAME" vs. "hostname.example.com".
175 server_netbios_name
= talloc_strdup(frame
, server_computer
);
176 if (server_netbios_name
== NULL
) {
177 TALLOC_FREE(context
);
179 return NT_STATUS_NO_MEMORY
;
182 p
= strchr(server_netbios_name
, '.');
187 _key_name
= talloc_asprintf(frame
, "CLI[%s/%s]/SRV[%s/%s]",
191 server_netbios_domain
);
192 if (_key_name
== NULL
) {
193 TALLOC_FREE(context
);
195 return NT_STATUS_NO_MEMORY
;
198 context
->db
.key_name
= talloc_strdup_upper(context
, _key_name
);
199 if (context
->db
.key_name
== NULL
) {
200 TALLOC_FREE(context
);
202 return NT_STATUS_NO_MEMORY
;
205 context
->db
.key_data
= string_term_tdb_data(context
->db
.key_name
);
212 static struct db_context
*netlogon_creds_cli_global_db
;
214 NTSTATUS
netlogon_creds_cli_set_global_db(struct db_context
**db
)
216 if (netlogon_creds_cli_global_db
!= NULL
) {
217 return NT_STATUS_INVALID_PARAMETER_MIX
;
220 netlogon_creds_cli_global_db
= talloc_move(NULL
, db
);
224 NTSTATUS
netlogon_creds_cli_open_global_db(struct loadparm_context
*lp_ctx
)
227 struct db_context
*global_db
;
229 if (netlogon_creds_cli_global_db
!= NULL
) {
233 fname
= lpcfg_private_db_path(NULL
, lp_ctx
, "netlogon_creds_cli");
235 return NT_STATUS_NO_MEMORY
;
238 global_db
= dbwrap_local_open(NULL
, lp_ctx
,
240 TDB_CLEAR_IF_FIRST
|TDB_INCOMPATIBLE_HASH
,
242 0600, DBWRAP_LOCK_ORDER_2
,
244 if (global_db
== NULL
) {
245 DEBUG(0,("netlogon_creds_cli_open_global_db: Failed to open %s - %s\n",
246 fname
, strerror(errno
)));
248 return NT_STATUS_NO_MEMORY
;
252 netlogon_creds_cli_global_db
= global_db
;
256 void netlogon_creds_cli_close_global_db(void)
258 TALLOC_FREE(netlogon_creds_cli_global_db
);
261 NTSTATUS
netlogon_creds_cli_context_global(struct loadparm_context
*lp_ctx
,
262 struct messaging_context
*msg_ctx
,
263 const char *client_account
,
264 enum netr_SchannelType type
,
265 const char *server_computer
,
266 const char *server_netbios_domain
,
267 const char *server_dns_domain
,
269 struct netlogon_creds_cli_context
**_context
)
271 TALLOC_CTX
*frame
= talloc_stackframe();
273 struct netlogon_creds_cli_context
*context
= NULL
;
274 const char *client_computer
;
275 uint32_t proposed_flags
;
276 uint32_t required_flags
= 0;
277 bool reject_md5_servers
= false;
278 bool require_strong_key
= false;
279 int require_sign_or_seal
= true;
280 bool seal_secure_channel
= true;
281 enum dcerpc_AuthLevel auth_level
= DCERPC_AUTH_LEVEL_NONE
;
282 bool neutralize_nt4_emulation
= false;
286 client_computer
= lpcfg_netbios_name(lp_ctx
);
287 if (strlen(client_computer
) > 15) {
288 return NT_STATUS_INVALID_PARAMETER_MIX
;
292 * allow overwrite per domain
293 * reject md5 servers:<netbios_domain>
295 reject_md5_servers
= lpcfg_reject_md5_servers(lp_ctx
);
296 reject_md5_servers
= lpcfg_parm_bool(lp_ctx
, NULL
,
297 "reject md5 servers",
298 server_netbios_domain
,
302 * allow overwrite per domain
303 * require strong key:<netbios_domain>
305 require_strong_key
= lpcfg_require_strong_key(lp_ctx
);
306 require_strong_key
= lpcfg_parm_bool(lp_ctx
, NULL
,
307 "require strong key",
308 server_netbios_domain
,
312 * allow overwrite per domain
313 * client schannel:<netbios_domain>
315 require_sign_or_seal
= lpcfg_client_schannel(lp_ctx
);
316 require_sign_or_seal
= lpcfg_parm_int(lp_ctx
, NULL
,
318 server_netbios_domain
,
319 require_sign_or_seal
);
322 * allow overwrite per domain
323 * winbind sealed pipes:<netbios_domain>
325 seal_secure_channel
= lpcfg_winbind_sealed_pipes(lp_ctx
);
326 seal_secure_channel
= lpcfg_parm_bool(lp_ctx
, NULL
,
327 "winbind sealed pipes",
328 server_netbios_domain
,
329 seal_secure_channel
);
332 * allow overwrite per domain
333 * neutralize nt4 emulation:<netbios_domain>
335 neutralize_nt4_emulation
= lpcfg_neutralize_nt4_emulation(lp_ctx
);
336 neutralize_nt4_emulation
= lpcfg_parm_bool(lp_ctx
, NULL
,
337 "neutralize nt4 emulation",
338 server_netbios_domain
,
339 neutralize_nt4_emulation
);
341 proposed_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
342 proposed_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
346 if (lpcfg_security(lp_ctx
) == SEC_ADS
) {
348 * AD domains should be secure
350 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
351 require_sign_or_seal
= true;
352 require_strong_key
= true;
356 case SEC_CHAN_DOMAIN
:
359 case SEC_CHAN_DNS_DOMAIN
:
361 * AD domains should be secure
363 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
364 require_sign_or_seal
= true;
365 require_strong_key
= true;
366 neutralize_nt4_emulation
= true;
370 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
371 require_sign_or_seal
= true;
372 require_strong_key
= true;
376 required_flags
|= NETLOGON_NEG_RODC_PASSTHROUGH
;
377 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
378 require_sign_or_seal
= true;
379 require_strong_key
= true;
380 neutralize_nt4_emulation
= true;
385 return NT_STATUS_INVALID_PARAMETER
;
388 if (neutralize_nt4_emulation
) {
389 proposed_flags
|= NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION
;
392 if (require_sign_or_seal
== false) {
393 proposed_flags
&= ~NETLOGON_NEG_AUTHENTICATED_RPC
;
395 required_flags
|= NETLOGON_NEG_ARCFOUR
;
396 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
399 if (reject_md5_servers
) {
400 required_flags
|= NETLOGON_NEG_ARCFOUR
;
401 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
402 required_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
403 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
406 if (require_strong_key
) {
407 required_flags
|= NETLOGON_NEG_ARCFOUR
;
408 required_flags
|= NETLOGON_NEG_STRONG_KEYS
;
409 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
412 proposed_flags
|= required_flags
;
414 if (seal_secure_channel
) {
415 auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
417 auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
420 status
= netlogon_creds_cli_context_common(client_computer
,
427 server_netbios_domain
,
431 if (!NT_STATUS_IS_OK(status
)) {
436 if (msg_ctx
!= NULL
) {
437 context
->db
.g_ctx
= g_lock_ctx_init(context
, msg_ctx
);
438 if (context
->db
.g_ctx
== NULL
) {
439 TALLOC_FREE(context
);
441 return NT_STATUS_NO_MEMORY
;
445 if (netlogon_creds_cli_global_db
!= NULL
) {
446 context
->db
.ctx
= netlogon_creds_cli_global_db
;
452 status
= netlogon_creds_cli_open_global_db(lp_ctx
);
453 if (!NT_STATUS_IS_OK(status
)) {
454 TALLOC_FREE(context
);
456 return NT_STATUS_NO_MEMORY
;
459 context
->db
.ctx
= netlogon_creds_cli_global_db
;
465 NTSTATUS
netlogon_creds_cli_context_tmp(const char *client_computer
,
466 const char *client_account
,
467 enum netr_SchannelType type
,
468 uint32_t proposed_flags
,
469 uint32_t required_flags
,
470 enum dcerpc_AuthLevel auth_level
,
471 const char *server_computer
,
472 const char *server_netbios_domain
,
474 struct netlogon_creds_cli_context
**_context
)
477 struct netlogon_creds_cli_context
*context
= NULL
;
481 status
= netlogon_creds_cli_context_common(client_computer
,
488 server_netbios_domain
,
492 if (!NT_STATUS_IS_OK(status
)) {
496 context
->db
.ctx
= db_open_rbt(context
);
497 if (context
->db
.ctx
== NULL
) {
498 talloc_free(context
);
499 return NT_STATUS_NO_MEMORY
;
506 char *netlogon_creds_cli_debug_string(
507 const struct netlogon_creds_cli_context
*context
,
510 return talloc_asprintf(mem_ctx
, "netlogon_creds_cli:%s",
511 context
->db
.key_name
);
514 enum dcerpc_AuthLevel
netlogon_creds_cli_auth_level(
515 struct netlogon_creds_cli_context
*context
)
517 return context
->client
.auth_level
;
520 struct netlogon_creds_cli_fetch_state
{
522 struct netlogon_creds_CredentialState
*creds
;
523 uint32_t required_flags
;
527 static void netlogon_creds_cli_fetch_parser(TDB_DATA key
, TDB_DATA data
,
530 struct netlogon_creds_cli_fetch_state
*state
=
531 (struct netlogon_creds_cli_fetch_state
*)private_data
;
532 enum ndr_err_code ndr_err
;
536 state
->creds
= talloc_zero(state
->mem_ctx
,
537 struct netlogon_creds_CredentialState
);
538 if (state
->creds
== NULL
) {
539 state
->status
= NT_STATUS_NO_MEMORY
;
543 blob
.data
= data
.dptr
;
544 blob
.length
= data
.dsize
;
546 ndr_err
= ndr_pull_struct_blob(&blob
, state
->creds
, state
->creds
,
547 (ndr_pull_flags_fn_t
)ndr_pull_netlogon_creds_CredentialState
);
548 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
549 TALLOC_FREE(state
->creds
);
550 state
->status
= ndr_map_error2ntstatus(ndr_err
);
554 tmp_flags
= state
->creds
->negotiate_flags
;
555 tmp_flags
&= state
->required_flags
;
556 if (tmp_flags
!= state
->required_flags
) {
557 TALLOC_FREE(state
->creds
);
558 state
->status
= NT_STATUS_DOWNGRADE_DETECTED
;
562 state
->status
= NT_STATUS_OK
;
565 NTSTATUS
netlogon_creds_cli_get(struct netlogon_creds_cli_context
*context
,
567 struct netlogon_creds_CredentialState
**_creds
)
570 struct netlogon_creds_cli_fetch_state fstate
= {
572 .status
= NT_STATUS_INTERNAL_ERROR
,
573 .required_flags
= context
->client
.required_flags
,
578 status
= dbwrap_parse_record(context
->db
.ctx
,
579 context
->db
.key_data
,
580 netlogon_creds_cli_fetch_parser
,
582 if (!NT_STATUS_IS_OK(status
)) {
585 status
= fstate
.status
;
586 if (!NT_STATUS_IS_OK(status
)) {
591 * mark it as invalid for step operations.
593 fstate
.creds
->sequence
= 0;
594 fstate
.creds
->seed
= (struct netr_Credential
) {{0}};
595 fstate
.creds
->client
= (struct netr_Credential
) {{0}};
596 fstate
.creds
->server
= (struct netr_Credential
) {{0}};
598 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
599 *_creds
= fstate
.creds
;
604 * It is really important to try SamLogonEx here,
605 * because multiple processes can talk to the same
606 * domain controller, without using the credential
609 * With a normal SamLogon call, we must keep the
610 * credentials chain updated and intact between all
611 * users of the machine account (which would imply
612 * cross-node communication for every NTLM logon).
614 * The credentials chain is not per NETLOGON pipe
615 * connection, but globally on the server/client pair
616 * by computer name, while the client is free to use
617 * any computer name. We include the cluster node number
618 * in our computer name in order to avoid cross node
619 * coordination of the credential chain.
621 * It's also important to use NetlogonValidationSamInfo4 (6),
622 * because it relies on the rpc transport encryption
623 * and avoids using the global netlogon schannel
624 * session key to en/decrypt secret information
625 * like the user_session_key for network logons.
627 * [MS-APDS] 3.1.5.2 NTLM Network Logon
628 * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and
629 * NETLOGON_NEG_AUTHENTICATED_RPC set together
630 * are the indication that the server supports
631 * NetlogonValidationSamInfo4 (6). And it must only
632 * be used if "SealSecureChannel" is used.
634 * The "SealSecureChannel" AUTH_TYPE_SCHANNEL/AUTH_LEVEL_PRIVACY
635 * check is done in netlogon_creds_cli_LogonSamLogon*().
637 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
638 context
->server
.try_validation6
= true;
639 context
->server
.try_logon_ex
= true;
640 context
->server
.try_logon_with
= true;
642 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
643 context
->server
.try_validation6
= false;
644 context
->server
.try_logon_ex
= false;
646 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
647 context
->server
.try_validation6
= false;
650 *_creds
= fstate
.creds
;
654 bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context
*context
,
655 const struct netlogon_creds_CredentialState
*creds1
)
657 TALLOC_CTX
*frame
= talloc_stackframe();
658 struct netlogon_creds_CredentialState
*creds2
;
662 enum ndr_err_code ndr_err
;
665 status
= netlogon_creds_cli_get(context
, frame
, &creds2
);
666 if (!NT_STATUS_IS_OK(status
)) {
671 ndr_err
= ndr_push_struct_blob(&blob1
, frame
, creds1
,
672 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
673 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
678 ndr_err
= ndr_push_struct_blob(&blob2
, frame
, creds2
,
679 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
680 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
685 if (blob1
.length
!= blob2
.length
) {
690 cmp
= memcmp(blob1
.data
, blob2
.data
, blob1
.length
);
700 NTSTATUS
netlogon_creds_cli_store(struct netlogon_creds_cli_context
*context
,
701 struct netlogon_creds_CredentialState
**_creds
)
703 struct netlogon_creds_CredentialState
*creds
= *_creds
;
705 enum ndr_err_code ndr_err
;
711 if (context
->db
.locked_state
== NULL
) {
713 * this was not the result of netlogon_creds_cli_lock*()
716 return NT_STATUS_INVALID_PAGE_PROTECTION
;
719 if (context
->db
.locked_state
->creds
!= creds
) {
721 * this was not the result of netlogon_creds_cli_lock*()
724 return NT_STATUS_INVALID_PAGE_PROTECTION
;
727 ndr_err
= ndr_push_struct_blob(&blob
, creds
, creds
,
728 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
729 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
731 status
= ndr_map_error2ntstatus(ndr_err
);
735 data
.dptr
= blob
.data
;
736 data
.dsize
= blob
.length
;
738 status
= dbwrap_store(context
->db
.ctx
,
739 context
->db
.key_data
,
742 if (!NT_STATUS_IS_OK(status
)) {
749 NTSTATUS
netlogon_creds_cli_delete(struct netlogon_creds_cli_context
*context
,
750 struct netlogon_creds_CredentialState
**_creds
)
752 struct netlogon_creds_CredentialState
*creds
= *_creds
;
757 if (context
->db
.locked_state
== NULL
) {
759 * this was not the result of netlogon_creds_cli_lock*()
762 return NT_STATUS_INVALID_PAGE_PROTECTION
;
765 if (context
->db
.locked_state
->creds
!= creds
) {
767 * this was not the result of netlogon_creds_cli_lock*()
770 return NT_STATUS_INVALID_PAGE_PROTECTION
;
773 status
= dbwrap_delete(context
->db
.ctx
,
774 context
->db
.key_data
);
776 if (!NT_STATUS_IS_OK(status
)) {
783 struct netlogon_creds_cli_lock_state
{
784 struct netlogon_creds_cli_locked_state
*locked_state
;
785 struct netlogon_creds_CredentialState
*creds
;
788 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
);
789 static void netlogon_creds_cli_lock_fetch(struct tevent_req
*req
);
791 struct tevent_req
*netlogon_creds_cli_lock_send(TALLOC_CTX
*mem_ctx
,
792 struct tevent_context
*ev
,
793 struct netlogon_creds_cli_context
*context
)
795 struct tevent_req
*req
;
796 struct netlogon_creds_cli_lock_state
*state
;
797 struct netlogon_creds_cli_locked_state
*locked_state
;
798 struct tevent_req
*subreq
;
800 req
= tevent_req_create(mem_ctx
, &state
,
801 struct netlogon_creds_cli_lock_state
);
806 if (context
->db
.locked_state
!= NULL
) {
807 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
808 return tevent_req_post(req
, ev
);
811 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
812 if (tevent_req_nomem(locked_state
, req
)) {
813 return tevent_req_post(req
, ev
);
815 talloc_set_destructor(locked_state
,
816 netlogon_creds_cli_locked_state_destructor
);
817 locked_state
->context
= context
;
819 context
->db
.locked_state
= locked_state
;
820 state
->locked_state
= locked_state
;
822 if (context
->db
.g_ctx
== NULL
) {
823 netlogon_creds_cli_lock_fetch(req
);
824 if (!tevent_req_is_in_progress(req
)) {
825 return tevent_req_post(req
, ev
);
831 subreq
= g_lock_lock_send(state
, ev
,
833 context
->db
.key_name
,
835 if (tevent_req_nomem(subreq
, req
)) {
836 return tevent_req_post(req
, ev
);
838 tevent_req_set_callback(subreq
, netlogon_creds_cli_lock_done
, req
);
843 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
)
845 struct tevent_req
*req
=
846 tevent_req_callback_data(subreq
,
848 struct netlogon_creds_cli_lock_state
*state
=
850 struct netlogon_creds_cli_lock_state
);
853 status
= g_lock_lock_recv(subreq
);
855 if (tevent_req_nterror(req
, status
)) {
858 state
->locked_state
->is_glocked
= true;
860 netlogon_creds_cli_lock_fetch(req
);
863 static void netlogon_creds_cli_lock_fetch(struct tevent_req
*req
)
865 struct netlogon_creds_cli_lock_state
*state
=
867 struct netlogon_creds_cli_lock_state
);
868 struct netlogon_creds_cli_context
*context
= state
->locked_state
->context
;
869 struct netlogon_creds_cli_fetch_state fstate
= {
870 .status
= NT_STATUS_INTERNAL_ERROR
,
871 .required_flags
= context
->client
.required_flags
,
875 fstate
.mem_ctx
= state
;
876 status
= dbwrap_parse_record(context
->db
.ctx
,
877 context
->db
.key_data
,
878 netlogon_creds_cli_fetch_parser
,
880 if (tevent_req_nterror(req
, status
)) {
883 status
= fstate
.status
;
884 if (tevent_req_nterror(req
, status
)) {
888 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
889 state
->creds
= fstate
.creds
;
890 tevent_req_done(req
);
894 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
895 context
->server
.try_validation6
= true;
896 context
->server
.try_logon_ex
= true;
897 context
->server
.try_logon_with
= true;
899 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
900 context
->server
.try_validation6
= false;
901 context
->server
.try_logon_ex
= false;
903 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
904 context
->server
.try_validation6
= false;
907 state
->creds
= fstate
.creds
;
908 tevent_req_done(req
);
912 NTSTATUS
netlogon_creds_cli_lock_recv(struct tevent_req
*req
,
914 struct netlogon_creds_CredentialState
**creds
)
916 struct netlogon_creds_cli_lock_state
*state
=
918 struct netlogon_creds_cli_lock_state
);
921 if (tevent_req_is_nterror(req
, &status
)) {
922 tevent_req_received(req
);
926 talloc_steal(state
->creds
, state
->locked_state
);
927 state
->locked_state
->creds
= state
->creds
;
928 *creds
= talloc_move(mem_ctx
, &state
->creds
);
929 tevent_req_received(req
);
933 NTSTATUS
netlogon_creds_cli_lock(struct netlogon_creds_cli_context
*context
,
935 struct netlogon_creds_CredentialState
**creds
)
937 TALLOC_CTX
*frame
= talloc_stackframe();
938 struct tevent_context
*ev
;
939 struct tevent_req
*req
;
940 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
942 ev
= samba_tevent_context_init(frame
);
946 req
= netlogon_creds_cli_lock_send(frame
, ev
, context
);
950 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
953 status
= netlogon_creds_cli_lock_recv(req
, mem_ctx
, creds
);
959 struct netlogon_creds_cli_auth_state
{
960 struct tevent_context
*ev
;
961 struct netlogon_creds_cli_context
*context
;
962 struct dcerpc_binding_handle
*binding_handle
;
963 uint8_t num_nt_hashes
;
964 uint8_t idx_nt_hashes
;
965 const struct samr_Password
* const *nt_hashes
;
966 const struct samr_Password
*used_nt_hash
;
967 char *srv_name_slash
;
968 uint32_t current_flags
;
969 struct netr_Credential client_challenge
;
970 struct netr_Credential server_challenge
;
971 struct netlogon_creds_CredentialState
*creds
;
972 struct netr_Credential client_credential
;
973 struct netr_Credential server_credential
;
978 struct netlogon_creds_cli_locked_state
*locked_state
;
981 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
);
982 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
);
984 struct tevent_req
*netlogon_creds_cli_auth_send(TALLOC_CTX
*mem_ctx
,
985 struct tevent_context
*ev
,
986 struct netlogon_creds_cli_context
*context
,
987 struct dcerpc_binding_handle
*b
,
988 uint8_t num_nt_hashes
,
989 const struct samr_Password
* const *nt_hashes
)
991 struct tevent_req
*req
;
992 struct netlogon_creds_cli_auth_state
*state
;
993 struct netlogon_creds_cli_locked_state
*locked_state
;
996 req
= tevent_req_create(mem_ctx
, &state
,
997 struct netlogon_creds_cli_auth_state
);
1003 state
->context
= context
;
1004 state
->binding_handle
= b
;
1005 if (num_nt_hashes
< 1) {
1006 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1007 return tevent_req_post(req
, ev
);
1009 if (num_nt_hashes
> 4) {
1010 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1011 return tevent_req_post(req
, ev
);
1014 state
->num_nt_hashes
= num_nt_hashes
;
1015 state
->idx_nt_hashes
= 0;
1016 state
->nt_hashes
= nt_hashes
;
1018 if (context
->db
.locked_state
!= NULL
) {
1019 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
1020 return tevent_req_post(req
, ev
);
1023 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
1024 if (tevent_req_nomem(locked_state
, req
)) {
1025 return tevent_req_post(req
, ev
);
1027 talloc_set_destructor(locked_state
,
1028 netlogon_creds_cli_locked_state_destructor
);
1029 locked_state
->context
= context
;
1031 context
->db
.locked_state
= locked_state
;
1032 state
->locked_state
= locked_state
;
1034 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1035 context
->server
.computer
);
1036 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1037 return tevent_req_post(req
, ev
);
1040 state
->try_auth3
= true;
1041 state
->try_auth2
= true;
1043 if (context
->client
.required_flags
!= 0) {
1044 state
->require_auth2
= true;
1047 state
->used_nt_hash
= state
->nt_hashes
[state
->idx_nt_hashes
];
1048 state
->current_flags
= context
->client
.proposed_flags
;
1050 if (context
->db
.g_ctx
!= NULL
) {
1051 struct tevent_req
*subreq
;
1053 subreq
= g_lock_lock_send(state
, ev
,
1055 context
->db
.key_name
,
1057 if (tevent_req_nomem(subreq
, req
)) {
1058 return tevent_req_post(req
, ev
);
1060 tevent_req_set_callback(subreq
,
1061 netlogon_creds_cli_auth_locked
,
1067 status
= dbwrap_purge(state
->context
->db
.ctx
,
1068 state
->context
->db
.key_data
);
1069 if (tevent_req_nterror(req
, status
)) {
1070 return tevent_req_post(req
, ev
);
1073 netlogon_creds_cli_auth_challenge_start(req
);
1074 if (!tevent_req_is_in_progress(req
)) {
1075 return tevent_req_post(req
, ev
);
1081 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
)
1083 struct tevent_req
*req
=
1084 tevent_req_callback_data(subreq
,
1086 struct netlogon_creds_cli_auth_state
*state
=
1087 tevent_req_data(req
,
1088 struct netlogon_creds_cli_auth_state
);
1091 status
= g_lock_lock_recv(subreq
);
1092 TALLOC_FREE(subreq
);
1093 if (tevent_req_nterror(req
, status
)) {
1096 state
->locked_state
->is_glocked
= true;
1098 status
= dbwrap_purge(state
->context
->db
.ctx
,
1099 state
->context
->db
.key_data
);
1100 if (tevent_req_nterror(req
, status
)) {
1104 netlogon_creds_cli_auth_challenge_start(req
);
1107 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
);
1109 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
)
1111 struct netlogon_creds_cli_auth_state
*state
=
1112 tevent_req_data(req
,
1113 struct netlogon_creds_cli_auth_state
);
1114 struct tevent_req
*subreq
;
1116 TALLOC_FREE(state
->creds
);
1118 generate_random_buffer(state
->client_challenge
.data
,
1119 sizeof(state
->client_challenge
.data
));
1121 subreq
= dcerpc_netr_ServerReqChallenge_send(state
, state
->ev
,
1122 state
->binding_handle
,
1123 state
->srv_name_slash
,
1124 state
->context
->client
.computer
,
1125 &state
->client_challenge
,
1126 &state
->server_challenge
);
1127 if (tevent_req_nomem(subreq
, req
)) {
1130 tevent_req_set_callback(subreq
,
1131 netlogon_creds_cli_auth_challenge_done
,
1135 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
);
1137 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
)
1139 struct tevent_req
*req
=
1140 tevent_req_callback_data(subreq
,
1142 struct netlogon_creds_cli_auth_state
*state
=
1143 tevent_req_data(req
,
1144 struct netlogon_creds_cli_auth_state
);
1148 status
= dcerpc_netr_ServerReqChallenge_recv(subreq
, state
, &result
);
1149 TALLOC_FREE(subreq
);
1150 if (tevent_req_nterror(req
, status
)) {
1153 if (tevent_req_nterror(req
, result
)) {
1157 if (!state
->try_auth3
&& !state
->try_auth2
) {
1158 state
->current_flags
= 0;
1161 /* Calculate the session key and client credentials */
1163 state
->creds
= netlogon_creds_client_init(state
,
1164 state
->context
->client
.account
,
1165 state
->context
->client
.computer
,
1166 state
->context
->client
.type
,
1167 &state
->client_challenge
,
1168 &state
->server_challenge
,
1169 state
->used_nt_hash
,
1170 &state
->client_credential
,
1171 state
->current_flags
);
1172 if (tevent_req_nomem(state
->creds
, req
)) {
1176 if (state
->try_auth3
) {
1177 subreq
= dcerpc_netr_ServerAuthenticate3_send(state
, state
->ev
,
1178 state
->binding_handle
,
1179 state
->srv_name_slash
,
1180 state
->context
->client
.account
,
1181 state
->context
->client
.type
,
1182 state
->context
->client
.computer
,
1183 &state
->client_credential
,
1184 &state
->server_credential
,
1185 &state
->creds
->negotiate_flags
,
1187 if (tevent_req_nomem(subreq
, req
)) {
1190 } else if (state
->try_auth2
) {
1193 subreq
= dcerpc_netr_ServerAuthenticate2_send(state
, state
->ev
,
1194 state
->binding_handle
,
1195 state
->srv_name_slash
,
1196 state
->context
->client
.account
,
1197 state
->context
->client
.type
,
1198 state
->context
->client
.computer
,
1199 &state
->client_credential
,
1200 &state
->server_credential
,
1201 &state
->creds
->negotiate_flags
);
1202 if (tevent_req_nomem(subreq
, req
)) {
1208 subreq
= dcerpc_netr_ServerAuthenticate_send(state
, state
->ev
,
1209 state
->binding_handle
,
1210 state
->srv_name_slash
,
1211 state
->context
->client
.account
,
1212 state
->context
->client
.type
,
1213 state
->context
->client
.computer
,
1214 &state
->client_credential
,
1215 &state
->server_credential
);
1216 if (tevent_req_nomem(subreq
, req
)) {
1220 tevent_req_set_callback(subreq
,
1221 netlogon_creds_cli_auth_srvauth_done
,
1225 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
)
1227 struct tevent_req
*req
=
1228 tevent_req_callback_data(subreq
,
1230 struct netlogon_creds_cli_auth_state
*state
=
1231 tevent_req_data(req
,
1232 struct netlogon_creds_cli_auth_state
);
1236 enum ndr_err_code ndr_err
;
1241 if (state
->try_auth3
) {
1242 status
= dcerpc_netr_ServerAuthenticate3_recv(subreq
, state
,
1244 TALLOC_FREE(subreq
);
1245 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1246 state
->try_auth3
= false;
1247 netlogon_creds_cli_auth_challenge_start(req
);
1250 if (tevent_req_nterror(req
, status
)) {
1253 } else if (state
->try_auth2
) {
1254 status
= dcerpc_netr_ServerAuthenticate2_recv(subreq
, state
,
1256 TALLOC_FREE(subreq
);
1257 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1258 state
->try_auth2
= false;
1259 if (state
->require_auth2
) {
1260 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1261 tevent_req_nterror(req
, status
);
1264 netlogon_creds_cli_auth_challenge_start(req
);
1267 if (tevent_req_nterror(req
, status
)) {
1271 status
= dcerpc_netr_ServerAuthenticate_recv(subreq
, state
,
1273 TALLOC_FREE(subreq
);
1274 if (tevent_req_nterror(req
, status
)) {
1279 if (!NT_STATUS_IS_OK(result
) &&
1280 !NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
))
1282 tevent_req_nterror(req
, result
);
1286 tmp_flags
= state
->creds
->negotiate_flags
;
1287 tmp_flags
&= state
->context
->client
.required_flags
;
1288 if (tmp_flags
!= state
->context
->client
.required_flags
) {
1289 if (NT_STATUS_IS_OK(result
)) {
1290 tevent_req_nterror(req
, NT_STATUS_DOWNGRADE_DETECTED
);
1293 tevent_req_nterror(req
, result
);
1297 if (NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
)) {
1299 tmp_flags
= state
->context
->client
.proposed_flags
;
1300 if ((state
->current_flags
== tmp_flags
) &&
1301 (state
->creds
->negotiate_flags
!= tmp_flags
))
1304 * lets retry with the negotiated flags
1306 state
->current_flags
= state
->creds
->negotiate_flags
;
1307 netlogon_creds_cli_auth_challenge_start(req
);
1311 state
->idx_nt_hashes
+= 1;
1312 if (state
->idx_nt_hashes
>= state
->num_nt_hashes
) {
1314 * we already retried, giving up...
1316 tevent_req_nterror(req
, result
);
1321 * lets retry with the old nt hash.
1323 state
->used_nt_hash
= state
->nt_hashes
[state
->idx_nt_hashes
];
1324 state
->current_flags
= state
->context
->client
.proposed_flags
;
1325 netlogon_creds_cli_auth_challenge_start(req
);
1329 ok
= netlogon_creds_client_check(state
->creds
,
1330 &state
->server_credential
);
1332 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1336 ndr_err
= ndr_push_struct_blob(&blob
, state
, state
->creds
,
1337 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
1338 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1339 status
= ndr_map_error2ntstatus(ndr_err
);
1340 tevent_req_nterror(req
, status
);
1344 data
.dptr
= blob
.data
;
1345 data
.dsize
= blob
.length
;
1347 status
= dbwrap_store(state
->context
->db
.ctx
,
1348 state
->context
->db
.key_data
,
1350 TALLOC_FREE(state
->locked_state
);
1351 if (tevent_req_nterror(req
, status
)) {
1355 tevent_req_done(req
);
1358 NTSTATUS
netlogon_creds_cli_auth_recv(struct tevent_req
*req
,
1359 uint8_t *idx_nt_hashes
)
1361 struct netlogon_creds_cli_auth_state
*state
=
1362 tevent_req_data(req
,
1363 struct netlogon_creds_cli_auth_state
);
1368 if (tevent_req_is_nterror(req
, &status
)) {
1369 tevent_req_received(req
);
1373 *idx_nt_hashes
= state
->idx_nt_hashes
;
1374 tevent_req_received(req
);
1375 return NT_STATUS_OK
;
1378 NTSTATUS
netlogon_creds_cli_auth(struct netlogon_creds_cli_context
*context
,
1379 struct dcerpc_binding_handle
*b
,
1380 uint8_t num_nt_hashes
,
1381 const struct samr_Password
* const *nt_hashes
,
1382 uint8_t *idx_nt_hashes
)
1384 TALLOC_CTX
*frame
= talloc_stackframe();
1385 struct tevent_context
*ev
;
1386 struct tevent_req
*req
;
1387 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1391 ev
= samba_tevent_context_init(frame
);
1395 req
= netlogon_creds_cli_auth_send(frame
, ev
, context
, b
,
1396 num_nt_hashes
, nt_hashes
);
1400 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1403 status
= netlogon_creds_cli_auth_recv(req
, idx_nt_hashes
);
1409 struct netlogon_creds_cli_check_state
{
1410 struct tevent_context
*ev
;
1411 struct netlogon_creds_cli_context
*context
;
1412 struct dcerpc_binding_handle
*binding_handle
;
1414 char *srv_name_slash
;
1416 union netr_Capabilities caps
;
1418 struct netlogon_creds_CredentialState
*creds
;
1419 struct netlogon_creds_CredentialState tmp_creds
;
1420 struct netr_Authenticator req_auth
;
1421 struct netr_Authenticator rep_auth
;
1424 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1426 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
);
1428 struct tevent_req
*netlogon_creds_cli_check_send(TALLOC_CTX
*mem_ctx
,
1429 struct tevent_context
*ev
,
1430 struct netlogon_creds_cli_context
*context
,
1431 struct dcerpc_binding_handle
*b
)
1433 struct tevent_req
*req
;
1434 struct netlogon_creds_cli_check_state
*state
;
1435 struct tevent_req
*subreq
;
1436 enum dcerpc_AuthType auth_type
;
1437 enum dcerpc_AuthLevel auth_level
;
1439 req
= tevent_req_create(mem_ctx
, &state
,
1440 struct netlogon_creds_cli_check_state
);
1446 state
->context
= context
;
1447 state
->binding_handle
= b
;
1449 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1450 context
->server
.computer
);
1451 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1452 return tevent_req_post(req
, ev
);
1455 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1456 &auth_type
, &auth_level
);
1458 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
1459 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1460 return tevent_req_post(req
, ev
);
1463 switch (auth_level
) {
1464 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1465 case DCERPC_AUTH_LEVEL_PRIVACY
:
1468 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1469 return tevent_req_post(req
, ev
);
1472 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1474 if (tevent_req_nomem(subreq
, req
)) {
1475 return tevent_req_post(req
, ev
);
1478 tevent_req_set_callback(subreq
,
1479 netlogon_creds_cli_check_locked
,
1485 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1488 struct netlogon_creds_cli_check_state
*state
=
1489 tevent_req_data(req
,
1490 struct netlogon_creds_cli_check_state
);
1492 if (state
->creds
== NULL
) {
1496 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1497 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1498 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1499 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1500 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1501 TALLOC_FREE(state
->creds
);
1505 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
1508 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
);
1510 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
)
1512 struct tevent_req
*req
=
1513 tevent_req_callback_data(subreq
,
1515 struct netlogon_creds_cli_check_state
*state
=
1516 tevent_req_data(req
,
1517 struct netlogon_creds_cli_check_state
);
1520 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1522 TALLOC_FREE(subreq
);
1523 if (tevent_req_nterror(req
, status
)) {
1528 * we defer all callbacks in order to cleanup
1529 * the database record.
1531 tevent_req_defer_callback(req
, state
->ev
);
1533 state
->tmp_creds
= *state
->creds
;
1534 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1536 ZERO_STRUCT(state
->rep_auth
);
1538 subreq
= dcerpc_netr_LogonGetCapabilities_send(state
, state
->ev
,
1539 state
->binding_handle
,
1540 state
->srv_name_slash
,
1541 state
->context
->client
.computer
,
1546 if (tevent_req_nomem(subreq
, req
)) {
1547 status
= NT_STATUS_NO_MEMORY
;
1548 netlogon_creds_cli_check_cleanup(req
, status
);
1551 tevent_req_set_callback(subreq
,
1552 netlogon_creds_cli_check_caps
,
1556 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
)
1558 struct tevent_req
*req
=
1559 tevent_req_callback_data(subreq
,
1561 struct netlogon_creds_cli_check_state
*state
=
1562 tevent_req_data(req
,
1563 struct netlogon_creds_cli_check_state
);
1568 status
= dcerpc_netr_LogonGetCapabilities_recv(subreq
, state
,
1570 TALLOC_FREE(subreq
);
1571 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1573 * Note that the negotiated flags are already checked
1574 * for our required flags after the ServerAuthenticate3/2 call.
1576 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1578 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1580 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1581 * already, we expect this to work!
1583 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1584 tevent_req_nterror(req
, status
);
1585 netlogon_creds_cli_check_cleanup(req
, status
);
1589 if (negotiated
& NETLOGON_NEG_STRONG_KEYS
) {
1591 * If we have negotiated NETLOGON_NEG_STRONG_KEYS
1592 * we expect this to work at least as far as the
1593 * NOT_SUPPORTED error handled below!
1595 * NT 4.0 and Old Samba servers are not
1596 * allowed without "require strong key = no"
1598 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1599 tevent_req_nterror(req
, status
);
1600 netlogon_creds_cli_check_cleanup(req
, status
);
1605 * If we not require NETLOGON_NEG_SUPPORTS_AES or
1606 * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore
1607 * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
1609 * This is needed against NT 4.0 and old Samba servers.
1611 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
1612 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
1613 * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
1614 * with the next request as the sequence number processing
1617 netlogon_creds_cli_check_cleanup(req
, status
);
1618 tevent_req_done(req
);
1621 if (tevent_req_nterror(req
, status
)) {
1622 netlogon_creds_cli_check_cleanup(req
, status
);
1626 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOT_IMPLEMENTED
)) {
1628 * Note that the negotiated flags are already checked
1629 * for our required flags after the ServerAuthenticate3/2 call.
1631 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1633 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1635 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1636 * already, we expect this to work!
1638 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1639 tevent_req_nterror(req
, status
);
1640 netlogon_creds_cli_check_cleanup(req
, status
);
1645 * This is ok, the server does not support
1646 * NETLOGON_NEG_SUPPORTS_AES.
1648 * netr_LogonGetCapabilities() was
1649 * netr_LogonDummyRoutine1() before
1650 * NETLOGON_NEG_SUPPORTS_AES was invented.
1652 netlogon_creds_cli_check_cleanup(req
, result
);
1653 tevent_req_done(req
);
1657 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1658 &state
->rep_auth
.cred
);
1660 status
= NT_STATUS_ACCESS_DENIED
;
1661 tevent_req_nterror(req
, status
);
1662 netlogon_creds_cli_check_cleanup(req
, status
);
1666 if (tevent_req_nterror(req
, result
)) {
1667 netlogon_creds_cli_check_cleanup(req
, result
);
1671 if (state
->caps
.server_capabilities
!= state
->tmp_creds
.negotiate_flags
) {
1672 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1673 tevent_req_nterror(req
, status
);
1674 netlogon_creds_cli_check_cleanup(req
, status
);
1679 * This is the key check that makes this check secure. If we
1680 * get OK here (rather than NOT_SUPPORTED), then the server
1681 * did support AES. If the server only proposed STRONG_KEYS
1682 * and not AES, then it should have failed with
1683 * NOT_IMPLEMENTED. We always send AES as a client, so the
1684 * server should always have returned it.
1686 if (!(state
->caps
.server_capabilities
& NETLOGON_NEG_SUPPORTS_AES
)) {
1687 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1688 tevent_req_nterror(req
, status
);
1689 netlogon_creds_cli_check_cleanup(req
, status
);
1693 *state
->creds
= state
->tmp_creds
;
1694 status
= netlogon_creds_cli_store(state
->context
,
1696 netlogon_creds_cli_check_cleanup(req
, status
);
1697 if (tevent_req_nterror(req
, status
)) {
1701 tevent_req_done(req
);
1704 NTSTATUS
netlogon_creds_cli_check_recv(struct tevent_req
*req
)
1708 if (tevent_req_is_nterror(req
, &status
)) {
1709 netlogon_creds_cli_check_cleanup(req
, status
);
1710 tevent_req_received(req
);
1714 tevent_req_received(req
);
1715 return NT_STATUS_OK
;
1718 NTSTATUS
netlogon_creds_cli_check(struct netlogon_creds_cli_context
*context
,
1719 struct dcerpc_binding_handle
*b
)
1721 TALLOC_CTX
*frame
= talloc_stackframe();
1722 struct tevent_context
*ev
;
1723 struct tevent_req
*req
;
1724 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1726 ev
= samba_tevent_context_init(frame
);
1730 req
= netlogon_creds_cli_check_send(frame
, ev
, context
, b
);
1734 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1737 status
= netlogon_creds_cli_check_recv(req
);
1743 struct netlogon_creds_cli_ServerPasswordSet_state
{
1744 struct tevent_context
*ev
;
1745 struct netlogon_creds_cli_context
*context
;
1746 struct dcerpc_binding_handle
*binding_handle
;
1747 uint32_t old_timeout
;
1749 char *srv_name_slash
;
1750 enum dcerpc_AuthType auth_type
;
1751 enum dcerpc_AuthLevel auth_level
;
1753 struct samr_CryptPassword samr_crypt_password
;
1754 struct netr_CryptPassword netr_crypt_password
;
1755 struct samr_Password samr_password
;
1757 struct netlogon_creds_CredentialState
*creds
;
1758 struct netlogon_creds_CredentialState tmp_creds
;
1759 struct netr_Authenticator req_auth
;
1760 struct netr_Authenticator rep_auth
;
1763 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1765 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
);
1767 struct tevent_req
*netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX
*mem_ctx
,
1768 struct tevent_context
*ev
,
1769 struct netlogon_creds_cli_context
*context
,
1770 struct dcerpc_binding_handle
*b
,
1771 const DATA_BLOB
*new_password
,
1772 const uint32_t *new_version
)
1774 struct tevent_req
*req
;
1775 struct netlogon_creds_cli_ServerPasswordSet_state
*state
;
1776 struct tevent_req
*subreq
;
1779 req
= tevent_req_create(mem_ctx
, &state
,
1780 struct netlogon_creds_cli_ServerPasswordSet_state
);
1786 state
->context
= context
;
1787 state
->binding_handle
= b
;
1789 if (new_password
->length
< 14) {
1790 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1791 return tevent_req_post(req
, ev
);
1795 * netr_ServerPasswordSet
1797 mdfour(state
->samr_password
.hash
, new_password
->data
, new_password
->length
);
1800 * netr_ServerPasswordSet2
1802 ok
= set_pw_in_buffer(state
->samr_crypt_password
.data
,
1805 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1806 return tevent_req_post(req
, ev
);
1809 if (new_version
!= NULL
) {
1810 struct NL_PASSWORD_VERSION version
;
1811 uint32_t len
= IVAL(state
->samr_crypt_password
.data
, 512);
1812 uint32_t ofs
= 512 - len
;
1816 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1817 return tevent_req_post(req
, ev
);
1821 version
.ReservedField
= 0;
1822 version
.PasswordVersionNumber
= *new_version
;
1823 version
.PasswordVersionPresent
=
1824 NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT
;
1826 p
= state
->samr_crypt_password
.data
+ ofs
;
1827 SIVAL(p
, 0, version
.ReservedField
);
1828 SIVAL(p
, 4, version
.PasswordVersionNumber
);
1829 SIVAL(p
, 8, version
.PasswordVersionPresent
);
1832 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1833 context
->server
.computer
);
1834 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1835 return tevent_req_post(req
, ev
);
1838 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1840 &state
->auth_level
);
1842 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1844 if (tevent_req_nomem(subreq
, req
)) {
1845 return tevent_req_post(req
, ev
);
1848 tevent_req_set_callback(subreq
,
1849 netlogon_creds_cli_ServerPasswordSet_locked
,
1855 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1858 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1859 tevent_req_data(req
,
1860 struct netlogon_creds_cli_ServerPasswordSet_state
);
1862 if (state
->creds
== NULL
) {
1866 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
1867 state
->old_timeout
);
1869 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1870 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1871 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1872 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1873 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1874 TALLOC_FREE(state
->creds
);
1878 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
1881 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
);
1883 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
)
1885 struct tevent_req
*req
=
1886 tevent_req_callback_data(subreq
,
1888 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1889 tevent_req_data(req
,
1890 struct netlogon_creds_cli_ServerPasswordSet_state
);
1893 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1895 TALLOC_FREE(subreq
);
1896 if (tevent_req_nterror(req
, status
)) {
1900 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
1901 switch (state
->auth_level
) {
1902 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1903 case DCERPC_AUTH_LEVEL_PRIVACY
:
1906 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1910 uint32_t tmp
= state
->creds
->negotiate_flags
;
1912 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
1914 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
1915 * it should be used, which means
1916 * we had a chance to verify no downgrade
1919 * This relies on netlogon_creds_cli_check*
1920 * being called before, as first request after
1923 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1928 state
->old_timeout
= dcerpc_binding_handle_set_timeout(
1929 state
->binding_handle
, 600000);
1932 * we defer all callbacks in order to cleanup
1933 * the database record.
1935 tevent_req_defer_callback(req
, state
->ev
);
1937 state
->tmp_creds
= *state
->creds
;
1938 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1940 ZERO_STRUCT(state
->rep_auth
);
1942 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1944 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1945 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
1946 state
->samr_crypt_password
.data
,
1949 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
1950 state
->samr_crypt_password
.data
,
1954 memcpy(state
->netr_crypt_password
.data
,
1955 state
->samr_crypt_password
.data
, 512);
1956 state
->netr_crypt_password
.length
=
1957 IVAL(state
->samr_crypt_password
.data
, 512);
1959 subreq
= dcerpc_netr_ServerPasswordSet2_send(state
, state
->ev
,
1960 state
->binding_handle
,
1961 state
->srv_name_slash
,
1962 state
->tmp_creds
.account_name
,
1963 state
->tmp_creds
.secure_channel_type
,
1964 state
->tmp_creds
.computer_name
,
1967 &state
->netr_crypt_password
);
1968 if (tevent_req_nomem(subreq
, req
)) {
1969 status
= NT_STATUS_NO_MEMORY
;
1970 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1974 netlogon_creds_des_encrypt(&state
->tmp_creds
,
1975 &state
->samr_password
);
1977 subreq
= dcerpc_netr_ServerPasswordSet_send(state
, state
->ev
,
1978 state
->binding_handle
,
1979 state
->srv_name_slash
,
1980 state
->tmp_creds
.account_name
,
1981 state
->tmp_creds
.secure_channel_type
,
1982 state
->tmp_creds
.computer_name
,
1985 &state
->samr_password
);
1986 if (tevent_req_nomem(subreq
, req
)) {
1987 status
= NT_STATUS_NO_MEMORY
;
1988 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1993 tevent_req_set_callback(subreq
,
1994 netlogon_creds_cli_ServerPasswordSet_done
,
1998 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
)
2000 struct tevent_req
*req
=
2001 tevent_req_callback_data(subreq
,
2003 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
2004 tevent_req_data(req
,
2005 struct netlogon_creds_cli_ServerPasswordSet_state
);
2010 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
2011 status
= dcerpc_netr_ServerPasswordSet2_recv(subreq
, state
,
2013 TALLOC_FREE(subreq
);
2014 if (tevent_req_nterror(req
, status
)) {
2015 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2019 status
= dcerpc_netr_ServerPasswordSet_recv(subreq
, state
,
2021 TALLOC_FREE(subreq
);
2022 if (tevent_req_nterror(req
, status
)) {
2023 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2028 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2029 &state
->rep_auth
.cred
);
2031 status
= NT_STATUS_ACCESS_DENIED
;
2032 tevent_req_nterror(req
, status
);
2033 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2037 if (tevent_req_nterror(req
, result
)) {
2038 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, result
);
2042 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
2043 state
->old_timeout
);
2045 *state
->creds
= state
->tmp_creds
;
2046 status
= netlogon_creds_cli_store(state
->context
,
2048 if (tevent_req_nterror(req
, status
)) {
2049 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2053 tevent_req_done(req
);
2056 NTSTATUS
netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req
*req
)
2060 if (tevent_req_is_nterror(req
, &status
)) {
2061 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2062 tevent_req_received(req
);
2066 tevent_req_received(req
);
2067 return NT_STATUS_OK
;
2070 NTSTATUS
netlogon_creds_cli_ServerPasswordSet(
2071 struct netlogon_creds_cli_context
*context
,
2072 struct dcerpc_binding_handle
*b
,
2073 const DATA_BLOB
*new_password
,
2074 const uint32_t *new_version
)
2076 TALLOC_CTX
*frame
= talloc_stackframe();
2077 struct tevent_context
*ev
;
2078 struct tevent_req
*req
;
2079 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2081 ev
= samba_tevent_context_init(frame
);
2085 req
= netlogon_creds_cli_ServerPasswordSet_send(frame
, ev
, context
, b
,
2091 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2094 status
= netlogon_creds_cli_ServerPasswordSet_recv(req
);
2100 struct netlogon_creds_cli_LogonSamLogon_state
{
2101 struct tevent_context
*ev
;
2102 struct netlogon_creds_cli_context
*context
;
2103 struct dcerpc_binding_handle
*binding_handle
;
2105 char *srv_name_slash
;
2107 enum netr_LogonInfoClass logon_level
;
2108 const union netr_LogonLevel
*const_logon
;
2109 union netr_LogonLevel
*logon
;
2112 uint16_t validation_level
;
2113 union netr_Validation
*validation
;
2114 uint8_t authoritative
;
2117 * do we need encryption at the application layer?
2121 bool try_validation6
;
2124 * the read only credentials before we started the operation
2125 * used for netr_LogonSamLogonEx() if required (validation_level = 3).
2127 struct netlogon_creds_CredentialState
*ro_creds
;
2130 * The (locked) credentials used for the credential chain
2131 * used for netr_LogonSamLogonWithFlags() or
2132 * netr_LogonSamLogonWith().
2134 struct netlogon_creds_CredentialState
*lk_creds
;
2137 * While we have locked the global credentials (lk_creds above)
2138 * we operate an a temporary copy, because a server
2139 * may not support netr_LogonSamLogonWithFlags() and
2140 * didn't process our netr_Authenticator, so we need to
2141 * restart from lk_creds.
2143 struct netlogon_creds_CredentialState tmp_creds
;
2144 struct netr_Authenticator req_auth
;
2145 struct netr_Authenticator rep_auth
;
2148 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
);
2149 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2152 struct tevent_req
*netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX
*mem_ctx
,
2153 struct tevent_context
*ev
,
2154 struct netlogon_creds_cli_context
*context
,
2155 struct dcerpc_binding_handle
*b
,
2156 enum netr_LogonInfoClass logon_level
,
2157 const union netr_LogonLevel
*logon
,
2160 struct tevent_req
*req
;
2161 struct netlogon_creds_cli_LogonSamLogon_state
*state
;
2163 req
= tevent_req_create(mem_ctx
, &state
,
2164 struct netlogon_creds_cli_LogonSamLogon_state
);
2170 state
->context
= context
;
2171 state
->binding_handle
= b
;
2173 state
->logon_level
= logon_level
;
2174 state
->const_logon
= logon
;
2175 state
->flags
= flags
;
2177 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2178 context
->server
.computer
);
2179 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2180 return tevent_req_post(req
, ev
);
2183 switch (logon_level
) {
2184 case NetlogonInteractiveInformation
:
2185 case NetlogonInteractiveTransitiveInformation
:
2186 case NetlogonServiceInformation
:
2187 case NetlogonServiceTransitiveInformation
:
2188 case NetlogonGenericInformation
:
2189 state
->user_encrypt
= true;
2192 case NetlogonNetworkInformation
:
2193 case NetlogonNetworkTransitiveInformation
:
2197 state
->validation
= talloc_zero(state
, union netr_Validation
);
2198 if (tevent_req_nomem(state
->validation
, req
)) {
2199 return tevent_req_post(req
, ev
);
2202 netlogon_creds_cli_LogonSamLogon_start(req
);
2203 if (!tevent_req_is_in_progress(req
)) {
2204 return tevent_req_post(req
, ev
);
2208 * we defer all callbacks in order to cleanup
2209 * the database record.
2211 tevent_req_defer_callback(req
, state
->ev
);
2215 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2218 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2219 tevent_req_data(req
,
2220 struct netlogon_creds_cli_LogonSamLogon_state
);
2222 if (state
->lk_creds
== NULL
) {
2226 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2228 * This is a hack to recover from a bug in old
2229 * Samba servers, when LogonSamLogonEx() fails:
2231 * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
2233 * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2235 * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE,
2236 * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR
2237 * If the sign/seal check fails.
2239 * In that case we need to cleanup the netlogon session.
2241 * It's the job of the caller to disconnect the current
2242 * connection, if netlogon_creds_cli_LogonSamLogon()
2243 * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2245 if (!state
->context
->server
.try_logon_with
) {
2246 status
= NT_STATUS_NETWORK_ACCESS_DENIED
;
2250 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2251 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2252 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2253 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2254 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2255 TALLOC_FREE(state
->lk_creds
);
2259 netlogon_creds_cli_delete(state
->context
, &state
->lk_creds
);
2262 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
);
2264 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
)
2266 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2267 tevent_req_data(req
,
2268 struct netlogon_creds_cli_LogonSamLogon_state
);
2269 struct tevent_req
*subreq
;
2271 enum dcerpc_AuthType auth_type
;
2272 enum dcerpc_AuthLevel auth_level
;
2274 TALLOC_FREE(state
->ro_creds
);
2275 TALLOC_FREE(state
->logon
);
2276 ZERO_STRUCTP(state
->validation
);
2278 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2279 &auth_type
, &auth_level
);
2281 state
->try_logon_ex
= state
->context
->server
.try_logon_ex
;
2282 state
->try_validation6
= state
->context
->server
.try_validation6
;
2284 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
2285 state
->try_logon_ex
= false;
2288 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
2289 state
->try_validation6
= false;
2292 if (state
->try_logon_ex
) {
2293 if (state
->try_validation6
) {
2294 state
->validation_level
= 6;
2296 state
->validation_level
= 3;
2297 state
->user_encrypt
= true;
2300 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2302 state
->const_logon
);
2303 if (tevent_req_nomem(state
->logon
, req
)) {
2304 status
= NT_STATUS_NO_MEMORY
;
2305 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2309 if (state
->user_encrypt
) {
2310 status
= netlogon_creds_cli_get(state
->context
,
2313 if (!NT_STATUS_IS_OK(status
)) {
2314 status
= NT_STATUS_ACCESS_DENIED
;
2315 tevent_req_nterror(req
, status
);
2316 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2320 netlogon_creds_encrypt_samlogon_logon(state
->ro_creds
,
2325 subreq
= dcerpc_netr_LogonSamLogonEx_send(state
, state
->ev
,
2326 state
->binding_handle
,
2327 state
->srv_name_slash
,
2328 state
->context
->client
.computer
,
2331 state
->validation_level
,
2333 &state
->authoritative
,
2335 if (tevent_req_nomem(subreq
, req
)) {
2336 status
= NT_STATUS_NO_MEMORY
;
2337 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2340 tevent_req_set_callback(subreq
,
2341 netlogon_creds_cli_LogonSamLogon_done
,
2346 if (state
->lk_creds
== NULL
) {
2347 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2349 if (tevent_req_nomem(subreq
, req
)) {
2350 status
= NT_STATUS_NO_MEMORY
;
2351 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2354 tevent_req_set_callback(subreq
,
2355 netlogon_creds_cli_LogonSamLogon_done
,
2360 state
->tmp_creds
= *state
->lk_creds
;
2361 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2363 ZERO_STRUCT(state
->rep_auth
);
2365 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2367 state
->const_logon
);
2368 if (tevent_req_nomem(state
->logon
, req
)) {
2369 status
= NT_STATUS_NO_MEMORY
;
2370 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2374 netlogon_creds_encrypt_samlogon_logon(&state
->tmp_creds
,
2378 state
->validation_level
= 3;
2380 if (state
->context
->server
.try_logon_with
) {
2381 subreq
= dcerpc_netr_LogonSamLogonWithFlags_send(state
, state
->ev
,
2382 state
->binding_handle
,
2383 state
->srv_name_slash
,
2384 state
->context
->client
.computer
,
2389 state
->validation_level
,
2391 &state
->authoritative
,
2393 if (tevent_req_nomem(subreq
, req
)) {
2394 status
= NT_STATUS_NO_MEMORY
;
2395 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2401 subreq
= dcerpc_netr_LogonSamLogon_send(state
, state
->ev
,
2402 state
->binding_handle
,
2403 state
->srv_name_slash
,
2404 state
->context
->client
.computer
,
2409 state
->validation_level
,
2411 &state
->authoritative
);
2412 if (tevent_req_nomem(subreq
, req
)) {
2413 status
= NT_STATUS_NO_MEMORY
;
2414 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2419 tevent_req_set_callback(subreq
,
2420 netlogon_creds_cli_LogonSamLogon_done
,
2424 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
)
2426 struct tevent_req
*req
=
2427 tevent_req_callback_data(subreq
,
2429 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2430 tevent_req_data(req
,
2431 struct netlogon_creds_cli_LogonSamLogon_state
);
2436 if (state
->try_logon_ex
) {
2437 status
= dcerpc_netr_LogonSamLogonEx_recv(subreq
,
2440 TALLOC_FREE(subreq
);
2441 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2442 state
->context
->server
.try_validation6
= false;
2443 state
->context
->server
.try_logon_ex
= false;
2444 netlogon_creds_cli_LogonSamLogon_start(req
);
2447 if (tevent_req_nterror(req
, status
)) {
2448 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2452 if ((state
->validation_level
== 6) &&
2453 (NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_INFO_CLASS
) ||
2454 NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_PARAMETER
) ||
2455 NT_STATUS_EQUAL(result
, NT_STATUS_BUFFER_TOO_SMALL
)))
2457 state
->context
->server
.try_validation6
= false;
2458 netlogon_creds_cli_LogonSamLogon_start(req
);
2462 if (tevent_req_nterror(req
, result
)) {
2463 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2467 if (state
->ro_creds
== NULL
) {
2468 tevent_req_done(req
);
2472 ok
= netlogon_creds_cli_validate(state
->context
, state
->ro_creds
);
2475 * We got a race, lets retry with on authenticator
2478 * netlogon_creds_cli_LogonSamLogon_start()
2479 * will TALLOC_FREE(state->ro_creds);
2481 state
->try_logon_ex
= false;
2482 netlogon_creds_cli_LogonSamLogon_start(req
);
2486 netlogon_creds_decrypt_samlogon_validation(state
->ro_creds
,
2487 state
->validation_level
,
2490 tevent_req_done(req
);
2494 if (state
->lk_creds
== NULL
) {
2495 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2497 TALLOC_FREE(subreq
);
2498 if (tevent_req_nterror(req
, status
)) {
2499 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2503 netlogon_creds_cli_LogonSamLogon_start(req
);
2507 if (state
->context
->server
.try_logon_with
) {
2508 status
= dcerpc_netr_LogonSamLogonWithFlags_recv(subreq
,
2511 TALLOC_FREE(subreq
);
2512 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2513 state
->context
->server
.try_logon_with
= false;
2514 netlogon_creds_cli_LogonSamLogon_start(req
);
2517 if (tevent_req_nterror(req
, status
)) {
2518 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2522 status
= dcerpc_netr_LogonSamLogon_recv(subreq
,
2525 TALLOC_FREE(subreq
);
2526 if (tevent_req_nterror(req
, status
)) {
2527 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2532 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2533 &state
->rep_auth
.cred
);
2535 status
= NT_STATUS_ACCESS_DENIED
;
2536 tevent_req_nterror(req
, status
);
2537 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2541 *state
->lk_creds
= state
->tmp_creds
;
2542 status
= netlogon_creds_cli_store(state
->context
,
2544 if (tevent_req_nterror(req
, status
)) {
2545 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2549 if (tevent_req_nterror(req
, result
)) {
2550 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2554 netlogon_creds_decrypt_samlogon_validation(&state
->tmp_creds
,
2555 state
->validation_level
,
2558 tevent_req_done(req
);
2561 NTSTATUS
netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req
*req
,
2562 TALLOC_CTX
*mem_ctx
,
2563 uint16_t *validation_level
,
2564 union netr_Validation
**validation
,
2565 uint8_t *authoritative
,
2568 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2569 tevent_req_data(req
,
2570 struct netlogon_creds_cli_LogonSamLogon_state
);
2573 /* authoritative is also returned on error */
2574 *authoritative
= state
->authoritative
;
2576 if (tevent_req_is_nterror(req
, &status
)) {
2577 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2578 tevent_req_received(req
);
2582 *validation_level
= state
->validation_level
;
2583 *validation
= talloc_move(mem_ctx
, &state
->validation
);
2584 *flags
= state
->flags
;
2586 tevent_req_received(req
);
2587 return NT_STATUS_OK
;
2590 NTSTATUS
netlogon_creds_cli_LogonSamLogon(
2591 struct netlogon_creds_cli_context
*context
,
2592 struct dcerpc_binding_handle
*b
,
2593 enum netr_LogonInfoClass logon_level
,
2594 const union netr_LogonLevel
*logon
,
2595 TALLOC_CTX
*mem_ctx
,
2596 uint16_t *validation_level
,
2597 union netr_Validation
**validation
,
2598 uint8_t *authoritative
,
2601 TALLOC_CTX
*frame
= talloc_stackframe();
2602 struct tevent_context
*ev
;
2603 struct tevent_req
*req
;
2604 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2606 ev
= samba_tevent_context_init(frame
);
2610 req
= netlogon_creds_cli_LogonSamLogon_send(frame
, ev
, context
, b
,
2616 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2619 status
= netlogon_creds_cli_LogonSamLogon_recv(req
, mem_ctx
,
2629 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
{
2630 struct tevent_context
*ev
;
2631 struct netlogon_creds_cli_context
*context
;
2632 struct dcerpc_binding_handle
*binding_handle
;
2634 char *srv_name_slash
;
2635 enum dcerpc_AuthType auth_type
;
2636 enum dcerpc_AuthLevel auth_level
;
2638 const char *site_name
;
2640 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
;
2642 struct netlogon_creds_CredentialState
*creds
;
2643 struct netlogon_creds_CredentialState tmp_creds
;
2644 struct netr_Authenticator req_auth
;
2645 struct netr_Authenticator rep_auth
;
2648 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2650 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
);
2652 struct tevent_req
*netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(TALLOC_CTX
*mem_ctx
,
2653 struct tevent_context
*ev
,
2654 struct netlogon_creds_cli_context
*context
,
2655 struct dcerpc_binding_handle
*b
,
2656 const char *site_name
,
2658 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2660 struct tevent_req
*req
;
2661 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
;
2662 struct tevent_req
*subreq
;
2664 req
= tevent_req_create(mem_ctx
, &state
,
2665 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2671 state
->context
= context
;
2672 state
->binding_handle
= b
;
2674 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2675 context
->server
.computer
);
2676 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2677 return tevent_req_post(req
, ev
);
2680 state
->site_name
= site_name
;
2681 state
->dns_ttl
= dns_ttl
;
2682 state
->dns_names
= dns_names
;
2684 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2686 &state
->auth_level
);
2688 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2690 if (tevent_req_nomem(subreq
, req
)) {
2691 return tevent_req_post(req
, ev
);
2694 tevent_req_set_callback(subreq
,
2695 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked
,
2701 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2704 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2705 tevent_req_data(req
,
2706 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2708 if (state
->creds
== NULL
) {
2712 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2713 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2714 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2715 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2716 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2717 TALLOC_FREE(state
->creds
);
2721 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
2724 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
);
2726 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
)
2728 struct tevent_req
*req
=
2729 tevent_req_callback_data(subreq
,
2731 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2732 tevent_req_data(req
,
2733 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2736 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2738 TALLOC_FREE(subreq
);
2739 if (tevent_req_nterror(req
, status
)) {
2743 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
2744 switch (state
->auth_level
) {
2745 case DCERPC_AUTH_LEVEL_INTEGRITY
:
2746 case DCERPC_AUTH_LEVEL_PRIVACY
:
2749 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2753 uint32_t tmp
= state
->creds
->negotiate_flags
;
2755 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
2757 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
2758 * it should be used, which means
2759 * we had a chance to verify no downgrade
2762 * This relies on netlogon_creds_cli_check*
2763 * being called before, as first request after
2766 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2772 * we defer all callbacks in order to cleanup
2773 * the database record.
2775 tevent_req_defer_callback(req
, state
->ev
);
2777 state
->tmp_creds
= *state
->creds
;
2778 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2780 ZERO_STRUCT(state
->rep_auth
);
2782 subreq
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_send(state
, state
->ev
,
2783 state
->binding_handle
,
2784 state
->srv_name_slash
,
2785 state
->tmp_creds
.computer_name
,
2791 if (tevent_req_nomem(subreq
, req
)) {
2792 status
= NT_STATUS_NO_MEMORY
;
2793 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2797 tevent_req_set_callback(subreq
,
2798 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done
,
2802 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
)
2804 struct tevent_req
*req
=
2805 tevent_req_callback_data(subreq
,
2807 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2808 tevent_req_data(req
,
2809 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2815 * We use state->dns_names as the memory context, as this is
2816 * the only in/out variable and it has been overwritten by the
2817 * out parameter from the server.
2819 * We need to preserve the return value until the caller can use it.
2821 status
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_recv(subreq
, state
->dns_names
,
2823 TALLOC_FREE(subreq
);
2824 if (tevent_req_nterror(req
, status
)) {
2825 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2829 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2830 &state
->rep_auth
.cred
);
2832 status
= NT_STATUS_ACCESS_DENIED
;
2833 tevent_req_nterror(req
, status
);
2834 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2838 *state
->creds
= state
->tmp_creds
;
2839 status
= netlogon_creds_cli_store(state
->context
,
2842 if (tevent_req_nterror(req
, status
)) {
2843 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2847 if (tevent_req_nterror(req
, result
)) {
2848 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, result
);
2852 tevent_req_done(req
);
2855 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(struct tevent_req
*req
)
2859 if (tevent_req_is_nterror(req
, &status
)) {
2860 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2861 tevent_req_received(req
);
2865 tevent_req_received(req
);
2866 return NT_STATUS_OK
;
2869 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(
2870 struct netlogon_creds_cli_context
*context
,
2871 struct dcerpc_binding_handle
*b
,
2872 const char *site_name
,
2874 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2876 TALLOC_CTX
*frame
= talloc_stackframe();
2877 struct tevent_context
*ev
;
2878 struct tevent_req
*req
;
2879 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2881 ev
= samba_tevent_context_init(frame
);
2885 req
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(frame
, ev
, context
, b
,
2892 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2895 status
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(req
);
2901 struct netlogon_creds_cli_ServerGetTrustInfo_state
{
2902 struct tevent_context
*ev
;
2903 struct netlogon_creds_cli_context
*context
;
2904 struct dcerpc_binding_handle
*binding_handle
;
2906 char *srv_name_slash
;
2907 enum dcerpc_AuthType auth_type
;
2908 enum dcerpc_AuthLevel auth_level
;
2910 struct samr_Password new_owf_password
;
2911 struct samr_Password old_owf_password
;
2912 struct netr_TrustInfo
*trust_info
;
2914 struct netlogon_creds_CredentialState
*creds
;
2915 struct netlogon_creds_CredentialState tmp_creds
;
2916 struct netr_Authenticator req_auth
;
2917 struct netr_Authenticator rep_auth
;
2920 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
2922 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
);
2924 struct tevent_req
*netlogon_creds_cli_ServerGetTrustInfo_send(TALLOC_CTX
*mem_ctx
,
2925 struct tevent_context
*ev
,
2926 struct netlogon_creds_cli_context
*context
,
2927 struct dcerpc_binding_handle
*b
)
2929 struct tevent_req
*req
;
2930 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
;
2931 struct tevent_req
*subreq
;
2933 req
= tevent_req_create(mem_ctx
, &state
,
2934 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2940 state
->context
= context
;
2941 state
->binding_handle
= b
;
2943 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2944 context
->server
.computer
);
2945 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2946 return tevent_req_post(req
, ev
);
2949 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2951 &state
->auth_level
);
2953 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2955 if (tevent_req_nomem(subreq
, req
)) {
2956 return tevent_req_post(req
, ev
);
2959 tevent_req_set_callback(subreq
,
2960 netlogon_creds_cli_ServerGetTrustInfo_locked
,
2966 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
2969 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2970 tevent_req_data(req
,
2971 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2973 if (state
->creds
== NULL
) {
2977 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2978 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2979 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2980 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2981 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2982 TALLOC_FREE(state
->creds
);
2986 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
2989 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
);
2991 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
)
2993 struct tevent_req
*req
=
2994 tevent_req_callback_data(subreq
,
2996 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2997 tevent_req_data(req
,
2998 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3001 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3003 TALLOC_FREE(subreq
);
3004 if (tevent_req_nterror(req
, status
)) {
3008 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3009 switch (state
->auth_level
) {
3010 case DCERPC_AUTH_LEVEL_PRIVACY
:
3013 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3017 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3022 * we defer all callbacks in order to cleanup
3023 * the database record.
3025 tevent_req_defer_callback(req
, state
->ev
);
3027 state
->tmp_creds
= *state
->creds
;
3028 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3030 ZERO_STRUCT(state
->rep_auth
);
3032 subreq
= dcerpc_netr_ServerGetTrustInfo_send(state
, state
->ev
,
3033 state
->binding_handle
,
3034 state
->srv_name_slash
,
3035 state
->tmp_creds
.account_name
,
3036 state
->tmp_creds
.secure_channel_type
,
3037 state
->tmp_creds
.computer_name
,
3040 &state
->new_owf_password
,
3041 &state
->old_owf_password
,
3042 &state
->trust_info
);
3043 if (tevent_req_nomem(subreq
, req
)) {
3044 status
= NT_STATUS_NO_MEMORY
;
3045 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3049 tevent_req_set_callback(subreq
,
3050 netlogon_creds_cli_ServerGetTrustInfo_done
,
3054 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
)
3056 struct tevent_req
*req
=
3057 tevent_req_callback_data(subreq
,
3059 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3060 tevent_req_data(req
,
3061 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3064 const struct samr_Password zero
= {};
3069 * We use state->dns_names as the memory context, as this is
3070 * the only in/out variable and it has been overwritten by the
3071 * out parameter from the server.
3073 * We need to preserve the return value until the caller can use it.
3075 status
= dcerpc_netr_ServerGetTrustInfo_recv(subreq
, state
, &result
);
3076 TALLOC_FREE(subreq
);
3077 if (tevent_req_nterror(req
, status
)) {
3078 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3082 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3083 &state
->rep_auth
.cred
);
3085 status
= NT_STATUS_ACCESS_DENIED
;
3086 tevent_req_nterror(req
, status
);
3087 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3091 cmp
= memcmp(state
->new_owf_password
.hash
,
3092 zero
.hash
, sizeof(zero
.hash
));
3094 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3095 &state
->new_owf_password
);
3097 cmp
= memcmp(state
->old_owf_password
.hash
,
3098 zero
.hash
, sizeof(zero
.hash
));
3100 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3101 &state
->old_owf_password
);
3104 *state
->creds
= state
->tmp_creds
;
3105 status
= netlogon_creds_cli_store(state
->context
,
3107 if (tevent_req_nterror(req
, status
)) {
3108 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3112 if (tevent_req_nterror(req
, result
)) {
3113 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, result
);
3117 tevent_req_done(req
);
3120 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo_recv(struct tevent_req
*req
,
3121 TALLOC_CTX
*mem_ctx
,
3122 struct samr_Password
*new_owf_password
,
3123 struct samr_Password
*old_owf_password
,
3124 struct netr_TrustInfo
**trust_info
)
3126 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3127 tevent_req_data(req
,
3128 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3131 if (tevent_req_is_nterror(req
, &status
)) {
3132 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3133 tevent_req_received(req
);
3137 if (new_owf_password
!= NULL
) {
3138 *new_owf_password
= state
->new_owf_password
;
3140 if (old_owf_password
!= NULL
) {
3141 *old_owf_password
= state
->old_owf_password
;
3143 if (trust_info
!= NULL
) {
3144 *trust_info
= talloc_move(mem_ctx
, &state
->trust_info
);
3147 tevent_req_received(req
);
3148 return NT_STATUS_OK
;
3151 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo(
3152 struct netlogon_creds_cli_context
*context
,
3153 struct dcerpc_binding_handle
*b
,
3154 TALLOC_CTX
*mem_ctx
,
3155 struct samr_Password
*new_owf_password
,
3156 struct samr_Password
*old_owf_password
,
3157 struct netr_TrustInfo
**trust_info
)
3159 TALLOC_CTX
*frame
= talloc_stackframe();
3160 struct tevent_context
*ev
;
3161 struct tevent_req
*req
;
3162 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3164 ev
= samba_tevent_context_init(frame
);
3168 req
= netlogon_creds_cli_ServerGetTrustInfo_send(frame
, ev
, context
, b
);
3172 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3175 status
= netlogon_creds_cli_ServerGetTrustInfo_recv(req
,
3185 struct netlogon_creds_cli_GetForestTrustInformation_state
{
3186 struct tevent_context
*ev
;
3187 struct netlogon_creds_cli_context
*context
;
3188 struct dcerpc_binding_handle
*binding_handle
;
3190 char *srv_name_slash
;
3191 enum dcerpc_AuthType auth_type
;
3192 enum dcerpc_AuthLevel auth_level
;
3195 struct lsa_ForestTrustInformation
*forest_trust_info
;
3197 struct netlogon_creds_CredentialState
*creds
;
3198 struct netlogon_creds_CredentialState tmp_creds
;
3199 struct netr_Authenticator req_auth
;
3200 struct netr_Authenticator rep_auth
;
3203 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3205 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
);
3207 struct tevent_req
*netlogon_creds_cli_GetForestTrustInformation_send(TALLOC_CTX
*mem_ctx
,
3208 struct tevent_context
*ev
,
3209 struct netlogon_creds_cli_context
*context
,
3210 struct dcerpc_binding_handle
*b
)
3212 struct tevent_req
*req
;
3213 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
;
3214 struct tevent_req
*subreq
;
3216 req
= tevent_req_create(mem_ctx
, &state
,
3217 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3223 state
->context
= context
;
3224 state
->binding_handle
= b
;
3226 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3227 context
->server
.computer
);
3228 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3229 return tevent_req_post(req
, ev
);
3234 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3236 &state
->auth_level
);
3238 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3240 if (tevent_req_nomem(subreq
, req
)) {
3241 return tevent_req_post(req
, ev
);
3244 tevent_req_set_callback(subreq
,
3245 netlogon_creds_cli_GetForestTrustInformation_locked
,
3251 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3254 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3255 tevent_req_data(req
,
3256 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3258 if (state
->creds
== NULL
) {
3262 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3263 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3264 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3265 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3266 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3267 TALLOC_FREE(state
->creds
);
3271 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
3274 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
);
3276 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
)
3278 struct tevent_req
*req
=
3279 tevent_req_callback_data(subreq
,
3281 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3282 tevent_req_data(req
,
3283 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3286 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3288 TALLOC_FREE(subreq
);
3289 if (tevent_req_nterror(req
, status
)) {
3293 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3294 switch (state
->auth_level
) {
3295 case DCERPC_AUTH_LEVEL_INTEGRITY
:
3296 case DCERPC_AUTH_LEVEL_PRIVACY
:
3299 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3303 uint32_t tmp
= state
->creds
->negotiate_flags
;
3305 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
3307 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3308 * it should be used, which means
3309 * we had a chance to verify no downgrade
3312 * This relies on netlogon_creds_cli_check*
3313 * being called before, as first request after
3316 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3322 * we defer all callbacks in order to cleanup
3323 * the database record.
3325 tevent_req_defer_callback(req
, state
->ev
);
3327 state
->tmp_creds
= *state
->creds
;
3328 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3330 ZERO_STRUCT(state
->rep_auth
);
3332 subreq
= dcerpc_netr_GetForestTrustInformation_send(state
, state
->ev
,
3333 state
->binding_handle
,
3334 state
->srv_name_slash
,
3335 state
->tmp_creds
.computer_name
,
3339 &state
->forest_trust_info
);
3340 if (tevent_req_nomem(subreq
, req
)) {
3341 status
= NT_STATUS_NO_MEMORY
;
3342 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3346 tevent_req_set_callback(subreq
,
3347 netlogon_creds_cli_GetForestTrustInformation_done
,
3351 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
)
3353 struct tevent_req
*req
=
3354 tevent_req_callback_data(subreq
,
3356 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3357 tevent_req_data(req
,
3358 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3364 * We use state->dns_names as the memory context, as this is
3365 * the only in/out variable and it has been overwritten by the
3366 * out parameter from the server.
3368 * We need to preserve the return value until the caller can use it.
3370 status
= dcerpc_netr_GetForestTrustInformation_recv(subreq
, state
, &result
);
3371 TALLOC_FREE(subreq
);
3372 if (tevent_req_nterror(req
, status
)) {
3373 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3377 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3378 &state
->rep_auth
.cred
);
3380 status
= NT_STATUS_ACCESS_DENIED
;
3381 tevent_req_nterror(req
, status
);
3382 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3386 *state
->creds
= state
->tmp_creds
;
3387 status
= netlogon_creds_cli_store(state
->context
,
3390 if (tevent_req_nterror(req
, status
)) {
3391 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3395 if (tevent_req_nterror(req
, result
)) {
3396 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, result
);
3400 tevent_req_done(req
);
3403 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation_recv(struct tevent_req
*req
,
3404 TALLOC_CTX
*mem_ctx
,
3405 struct lsa_ForestTrustInformation
**forest_trust_info
)
3407 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3408 tevent_req_data(req
,
3409 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3412 if (tevent_req_is_nterror(req
, &status
)) {
3413 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3414 tevent_req_received(req
);
3418 *forest_trust_info
= talloc_move(mem_ctx
, &state
->forest_trust_info
);
3420 tevent_req_received(req
);
3421 return NT_STATUS_OK
;
3424 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation(
3425 struct netlogon_creds_cli_context
*context
,
3426 struct dcerpc_binding_handle
*b
,
3427 TALLOC_CTX
*mem_ctx
,
3428 struct lsa_ForestTrustInformation
**forest_trust_info
)
3430 TALLOC_CTX
*frame
= talloc_stackframe();
3431 struct tevent_context
*ev
;
3432 struct tevent_req
*req
;
3433 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3435 ev
= samba_tevent_context_init(frame
);
3439 req
= netlogon_creds_cli_GetForestTrustInformation_send(frame
, ev
, context
, b
);
3443 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3446 status
= netlogon_creds_cli_GetForestTrustInformation_recv(req
,
3454 struct netlogon_creds_cli_SendToSam_state
{
3455 struct tevent_context
*ev
;
3456 struct netlogon_creds_cli_context
*context
;
3457 struct dcerpc_binding_handle
*binding_handle
;
3459 char *srv_name_slash
;
3460 enum dcerpc_AuthType auth_type
;
3461 enum dcerpc_AuthLevel auth_level
;
3465 struct netlogon_creds_CredentialState
*creds
;
3466 struct netlogon_creds_CredentialState tmp_creds
;
3467 struct netr_Authenticator req_auth
;
3468 struct netr_Authenticator rep_auth
;
3471 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req
*req
,
3473 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req
*subreq
);
3475 struct tevent_req
*netlogon_creds_cli_SendToSam_send(TALLOC_CTX
*mem_ctx
,
3476 struct tevent_context
*ev
,
3477 struct netlogon_creds_cli_context
*context
,
3478 struct dcerpc_binding_handle
*b
,
3479 struct netr_SendToSamBase
*message
)
3481 struct tevent_req
*req
;
3482 struct netlogon_creds_cli_SendToSam_state
*state
;
3483 struct tevent_req
*subreq
;
3484 enum ndr_err_code ndr_err
;
3486 req
= tevent_req_create(mem_ctx
, &state
,
3487 struct netlogon_creds_cli_SendToSam_state
);
3493 state
->context
= context
;
3494 state
->binding_handle
= b
;
3496 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3497 context
->server
.computer
);
3498 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3499 return tevent_req_post(req
, ev
);
3502 ndr_err
= ndr_push_struct_blob(&state
->opaque
, mem_ctx
, message
,
3503 (ndr_push_flags_fn_t
)ndr_push_netr_SendToSamBase
);
3504 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
3505 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
3506 tevent_req_nterror(req
, status
);
3507 return tevent_req_post(req
, ev
);
3510 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3512 &state
->auth_level
);
3514 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3516 if (tevent_req_nomem(subreq
, req
)) {
3517 return tevent_req_post(req
, ev
);
3520 tevent_req_set_callback(subreq
,
3521 netlogon_creds_cli_SendToSam_locked
,
3527 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req
*req
,
3530 struct netlogon_creds_cli_SendToSam_state
*state
=
3531 tevent_req_data(req
,
3532 struct netlogon_creds_cli_SendToSam_state
);
3534 if (state
->creds
== NULL
) {
3538 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3539 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3540 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3541 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3542 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3543 TALLOC_FREE(state
->creds
);
3547 netlogon_creds_cli_delete(state
->context
, &state
->creds
);
3550 static void netlogon_creds_cli_SendToSam_done(struct tevent_req
*subreq
);
3552 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req
*subreq
)
3554 struct tevent_req
*req
=
3555 tevent_req_callback_data(subreq
,
3557 struct netlogon_creds_cli_SendToSam_state
*state
=
3558 tevent_req_data(req
,
3559 struct netlogon_creds_cli_SendToSam_state
);
3562 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3564 TALLOC_FREE(subreq
);
3565 if (tevent_req_nterror(req
, status
)) {
3569 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3570 switch (state
->auth_level
) {
3571 case DCERPC_AUTH_LEVEL_INTEGRITY
:
3572 case DCERPC_AUTH_LEVEL_PRIVACY
:
3575 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3579 uint32_t tmp
= state
->creds
->negotiate_flags
;
3581 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
3583 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3584 * it should be used, which means
3585 * we had a chance to verify no downgrade
3588 * This relies on netlogon_creds_cli_check*
3589 * being called before, as first request after
3592 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3598 * we defer all callbacks in order to cleanup
3599 * the database record.
3601 tevent_req_defer_callback(req
, state
->ev
);
3603 state
->tmp_creds
= *state
->creds
;
3604 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3606 ZERO_STRUCT(state
->rep_auth
);
3608 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
3609 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
3611 state
->opaque
.length
);
3613 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
3615 state
->opaque
.length
);
3618 subreq
= dcerpc_netr_NetrLogonSendToSam_send(state
, state
->ev
,
3619 state
->binding_handle
,
3620 state
->srv_name_slash
,
3621 state
->tmp_creds
.computer_name
,
3625 state
->opaque
.length
);
3626 if (tevent_req_nomem(subreq
, req
)) {
3627 status
= NT_STATUS_NO_MEMORY
;
3628 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3632 tevent_req_set_callback(subreq
,
3633 netlogon_creds_cli_SendToSam_done
,
3637 static void netlogon_creds_cli_SendToSam_done(struct tevent_req
*subreq
)
3639 struct tevent_req
*req
=
3640 tevent_req_callback_data(subreq
,
3642 struct netlogon_creds_cli_SendToSam_state
*state
=
3643 tevent_req_data(req
,
3644 struct netlogon_creds_cli_SendToSam_state
);
3649 status
= dcerpc_netr_NetrLogonSendToSam_recv(subreq
, state
, &result
);
3650 TALLOC_FREE(subreq
);
3651 if (tevent_req_nterror(req
, status
)) {
3652 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3656 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3657 &state
->rep_auth
.cred
);
3659 status
= NT_STATUS_ACCESS_DENIED
;
3660 tevent_req_nterror(req
, status
);
3661 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3665 *state
->creds
= state
->tmp_creds
;
3666 status
= netlogon_creds_cli_store(state
->context
,
3669 if (tevent_req_nterror(req
, status
)) {
3670 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3675 * Creds must be stored before we send back application errors
3676 * e.g. NT_STATUS_NOT_IMPLEMENTED
3678 if (tevent_req_nterror(req
, result
)) {
3679 netlogon_creds_cli_SendToSam_cleanup(req
, result
);
3683 tevent_req_done(req
);
3686 NTSTATUS
netlogon_creds_cli_SendToSam(struct netlogon_creds_cli_context
*context
,
3687 struct dcerpc_binding_handle
*b
,
3688 struct netr_SendToSamBase
*message
)
3690 TALLOC_CTX
*frame
= talloc_stackframe();
3691 struct tevent_context
*ev
;
3692 struct tevent_req
*req
;
3693 NTSTATUS status
= NT_STATUS_OK
;
3695 ev
= samba_tevent_context_init(frame
);
3699 req
= netlogon_creds_cli_SendToSam_send(frame
, ev
, context
, b
, message
);
3703 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3707 /* Ignore the result */