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/md4.h"
41 #include "auth/credentials/credentials.h"
42 #include "lib/param/loadparm.h"
44 struct netlogon_creds_cli_locked_state
;
46 struct netlogon_creds_cli_context
{
50 uint32_t proposed_flags
;
51 uint32_t required_flags
;
52 enum netr_SchannelType type
;
53 enum dcerpc_AuthLevel auth_level
;
58 const char *netbios_domain
;
59 const char *dns_domain
;
60 uint32_t cached_flags
;
69 struct db_context
*ctx
;
70 struct g_lock_ctx
*g_ctx
;
71 struct netlogon_creds_cli_locked_state
*locked_state
;
72 enum netlogon_creds_cli_lck_type lock
;
76 struct netlogon_creds_cli_locked_state
{
77 struct netlogon_creds_cli_context
*context
;
79 struct netlogon_creds_CredentialState
*creds
;
82 static int netlogon_creds_cli_locked_state_destructor(
83 struct netlogon_creds_cli_locked_state
*state
)
85 struct netlogon_creds_cli_context
*context
= state
->context
;
87 if (context
== NULL
) {
91 if (context
->db
.locked_state
== state
) {
92 context
->db
.locked_state
= NULL
;
95 if (state
->is_glocked
) {
96 g_lock_unlock(context
->db
.g_ctx
,
97 string_term_tdb_data(context
->db
.key_name
));
103 static NTSTATUS
netlogon_creds_cli_context_common(
104 const char *client_computer
,
105 const char *client_account
,
106 enum netr_SchannelType type
,
107 enum dcerpc_AuthLevel auth_level
,
108 uint32_t proposed_flags
,
109 uint32_t required_flags
,
110 const char *server_computer
,
111 const char *server_netbios_domain
,
112 const char *server_dns_domain
,
114 struct netlogon_creds_cli_context
**_context
)
116 struct netlogon_creds_cli_context
*context
= NULL
;
117 char *_key_name
= NULL
;
118 size_t server_netbios_name_len
;
123 context
= talloc_zero(mem_ctx
, struct netlogon_creds_cli_context
);
124 if (context
== NULL
) {
125 return NT_STATUS_NO_MEMORY
;
128 context
->client
.computer
= talloc_strdup(context
, client_computer
);
129 if (context
->client
.computer
== NULL
) {
130 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
);
137 return NT_STATUS_NO_MEMORY
;
140 context
->client
.proposed_flags
= proposed_flags
;
141 context
->client
.required_flags
= required_flags
;
142 context
->client
.type
= type
;
143 context
->client
.auth_level
= auth_level
;
145 context
->server
.computer
= talloc_strdup(context
, server_computer
);
146 if (context
->server
.computer
== NULL
) {
147 TALLOC_FREE(context
);
148 return NT_STATUS_NO_MEMORY
;
151 context
->server
.netbios_domain
= talloc_strdup(context
, server_netbios_domain
);
152 if (context
->server
.netbios_domain
== NULL
) {
153 TALLOC_FREE(context
);
154 return NT_STATUS_NO_MEMORY
;
157 context
->server
.dns_domain
= talloc_strdup(context
, server_dns_domain
);
158 if (context
->server
.dns_domain
== NULL
) {
159 TALLOC_FREE(context
);
160 return NT_STATUS_NO_MEMORY
;
165 * Force the callers to provide a unique
166 * value for server_computer and use this directly.
168 * For now we have to deal with
169 * "HOSTNAME" vs. "hostname.example.com".
172 p
= strchr(server_computer
, '.');
174 server_netbios_name_len
= p
-server_computer
;
176 server_netbios_name_len
= strlen(server_computer
);
179 _key_name
= talloc_asprintf(context
, "CLI[%s/%s]/SRV[%.*s/%s]",
182 (int)server_netbios_name_len
,
184 server_netbios_domain
);
185 if (_key_name
== NULL
) {
186 TALLOC_FREE(context
);
187 return NT_STATUS_NO_MEMORY
;
190 context
->db
.key_name
= talloc_strdup_upper(context
, _key_name
);
191 TALLOC_FREE(_key_name
);
192 if (context
->db
.key_name
== NULL
) {
193 TALLOC_FREE(context
);
194 return NT_STATUS_NO_MEMORY
;
197 context
->db
.key_data
= string_term_tdb_data(context
->db
.key_name
);
203 static struct db_context
*netlogon_creds_cli_global_db
;
205 NTSTATUS
netlogon_creds_cli_set_global_db(struct loadparm_context
*lp_ctx
,
206 struct db_context
**db
)
208 netlogon_creds_cli_warn_options(lp_ctx
);
210 if (netlogon_creds_cli_global_db
!= NULL
) {
211 return NT_STATUS_INVALID_PARAMETER_MIX
;
214 netlogon_creds_cli_global_db
= talloc_move(NULL
, db
);
218 NTSTATUS
netlogon_creds_cli_open_global_db(struct loadparm_context
*lp_ctx
)
221 struct db_context
*global_db
;
222 int hash_size
, tdb_flags
;
224 netlogon_creds_cli_warn_options(lp_ctx
);
226 if (netlogon_creds_cli_global_db
!= NULL
) {
230 fname
= lpcfg_private_db_path(NULL
, lp_ctx
, "netlogon_creds_cli");
232 return NT_STATUS_NO_MEMORY
;
235 hash_size
= lpcfg_tdb_hash_size(lp_ctx
, fname
);
236 tdb_flags
= lpcfg_tdb_flags(
238 TDB_CLEAR_IF_FIRST
|TDB_INCOMPATIBLE_HASH
);
240 global_db
= dbwrap_local_open(
249 if (global_db
== NULL
) {
250 DEBUG(0,("netlogon_creds_cli_open_global_db: Failed to open %s - %s\n",
251 fname
, strerror(errno
)));
253 return NT_STATUS_NO_MEMORY
;
257 netlogon_creds_cli_global_db
= global_db
;
261 void netlogon_creds_cli_close_global_db(void)
263 TALLOC_FREE(netlogon_creds_cli_global_db
);
266 void netlogon_creds_cli_warn_options(struct loadparm_context
*lp_ctx
)
268 bool global_reject_md5_servers
= lpcfg_reject_md5_servers(lp_ctx
);
269 bool global_require_strong_key
= lpcfg_require_strong_key(lp_ctx
);
270 int global_client_schannel
= lpcfg_client_schannel(lp_ctx
);
271 bool global_seal_secure_channel
= lpcfg_winbind_sealed_pipes(lp_ctx
);
272 int global_kerberos_enctypes
= lpcfg_kerberos_encryption_types(lp_ctx
);
273 static bool warned_global_reject_md5_servers
= false;
274 static bool warned_global_require_strong_key
= false;
275 static bool warned_global_client_schannel
= false;
276 static bool warned_global_seal_secure_channel
= false;
277 static bool warned_global_kerberos_encryption_types
= false;
278 static int warned_global_pid
= 0;
279 int current_pid
= tevent_cached_getpid();
281 if (warned_global_pid
!= current_pid
) {
282 warned_global_reject_md5_servers
= false;
283 warned_global_require_strong_key
= false;
284 warned_global_client_schannel
= false;
285 warned_global_seal_secure_channel
= false;
286 warned_global_kerberos_encryption_types
= false;
287 warned_global_pid
= current_pid
;
290 if (!global_reject_md5_servers
&& !warned_global_reject_md5_servers
) {
292 * We want admins to notice their misconfiguration!
294 DBG_ERR("CVE-2022-38023 (and others): "
295 "Please configure 'reject md5 servers = yes' (the default), "
296 "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
297 warned_global_reject_md5_servers
= true;
300 if (!global_require_strong_key
&& !warned_global_require_strong_key
) {
302 * We want admins to notice their misconfiguration!
304 DBG_ERR("CVE-2022-38023 (and others): "
305 "Please configure 'require strong key = yes' (the default), "
306 "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
307 warned_global_require_strong_key
= true;
310 if (global_client_schannel
!= true && !warned_global_client_schannel
) {
312 * We want admins to notice their misconfiguration!
314 DBG_ERR("CVE-2022-38023 (and others): "
315 "Please configure 'client schannel = yes' (the default), "
316 "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
317 warned_global_client_schannel
= true;
320 if (!global_seal_secure_channel
&& !warned_global_seal_secure_channel
) {
322 * We want admins to notice their misconfiguration!
324 DBG_ERR("CVE-2022-38023 (and others): "
325 "Please configure 'winbind sealed pipes = yes' (the default), "
326 "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
327 warned_global_seal_secure_channel
= true;
330 if (global_kerberos_enctypes
== KERBEROS_ETYPES_LEGACY
&&
331 !warned_global_kerberos_encryption_types
)
334 * We want admins to notice their misconfiguration!
336 DBG_ERR("CVE-2022-37966: "
337 "Please void 'kerberos encryption types = legacy', "
338 "See https://bugzilla.samba.org/show_bug.cgi?id=15237\n");
339 warned_global_kerberos_encryption_types
= true;
343 NTSTATUS
netlogon_creds_cli_context_global(struct loadparm_context
*lp_ctx
,
344 struct messaging_context
*msg_ctx
,
345 const char *client_account
,
346 enum netr_SchannelType type
,
347 const char *server_computer
,
348 const char *server_netbios_domain
,
349 const char *server_dns_domain
,
351 struct netlogon_creds_cli_context
**_context
)
353 TALLOC_CTX
*frame
= talloc_stackframe();
355 struct netlogon_creds_cli_context
*context
= NULL
;
356 const char *client_computer
;
357 uint32_t proposed_flags
;
358 uint32_t required_flags
= 0;
359 bool reject_md5_servers
= true;
360 bool require_strong_key
= true;
361 bool reject_aes_servers
= true;
362 int require_sign_or_seal
= true;
363 bool seal_secure_channel
= true;
364 bool trust_support_kerberos
= false;
365 #if defined(HAVE_ADS) && defined(HAVE_KRB5_INIT_CREDS_STEP)
366 const bool support_krb5_netlogon
= true;
368 const bool support_krb5_netlogon
= false;
370 int global_client_use_krb5_netlogon
= true;
371 bool client_use_krb5_netlogon
= true;
372 enum dcerpc_AuthLevel auth_level
= DCERPC_AUTH_LEVEL_NONE
;
373 bool neutralize_nt4_emulation
= false;
377 if (msg_ctx
== NULL
) {
379 return NT_STATUS_INVALID_PARAMETER_MIX
;
382 client_computer
= lpcfg_netbios_name(lp_ctx
);
383 if (strlen(client_computer
) > 15) {
385 return NT_STATUS_INVALID_PARAMETER_MIX
;
389 * allow overwrite per domain
390 * reject md5 servers:<netbios_domain>
392 reject_md5_servers
= lpcfg_reject_md5_servers(lp_ctx
);
393 reject_md5_servers
= lpcfg_parm_bool(lp_ctx
, NULL
,
394 "reject md5 servers",
395 server_netbios_domain
,
399 * allow overwrite per domain
400 * require strong key:<netbios_domain>
402 require_strong_key
= lpcfg_require_strong_key(lp_ctx
);
403 require_strong_key
= lpcfg_parm_bool(lp_ctx
, NULL
,
404 "require strong key",
405 server_netbios_domain
,
409 * allow overwrite per domain
410 * client schannel:<netbios_domain>
412 require_sign_or_seal
= lpcfg_client_schannel(lp_ctx
);
413 require_sign_or_seal
= lpcfg_parm_int(lp_ctx
, NULL
,
415 server_netbios_domain
,
416 require_sign_or_seal
);
419 * allow overwrite per domain
420 * winbind sealed pipes:<netbios_domain>
422 seal_secure_channel
= lpcfg_winbind_sealed_pipes(lp_ctx
);
423 seal_secure_channel
= lpcfg_parm_bool(lp_ctx
, NULL
,
424 "winbind sealed pipes",
425 server_netbios_domain
,
426 seal_secure_channel
);
429 * allow overwrite per domain
430 * neutralize nt4 emulation:<netbios_domain>
432 neutralize_nt4_emulation
= lpcfg_neutralize_nt4_emulation(lp_ctx
);
433 neutralize_nt4_emulation
= lpcfg_parm_bool(lp_ctx
, NULL
,
434 "neutralize nt4 emulation",
435 server_netbios_domain
,
436 neutralize_nt4_emulation
);
439 * allow overwrite per domain
440 * reject aes netlogon servers:<netbios_domain>
442 reject_aes_servers
= lpcfg_reject_aes_netlogon_servers(lp_ctx
);
443 reject_aes_servers
= lpcfg_parm_bool(lp_ctx
, NULL
,
444 "reject aes netlogon servers",
445 server_netbios_domain
,
449 * allow overwrite per domain
450 * client use krb5 netlogon:<netbios_domain>
454 global_client_use_krb5_netlogon
= lpcfg_client_use_krb5_netlogon(lp_ctx
);
456 proposed_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
457 proposed_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
461 if (lpcfg_security(lp_ctx
) == SEC_ADS
) {
463 * AD domains should be secure
465 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
466 require_sign_or_seal
= true;
467 require_strong_key
= true;
468 trust_support_kerberos
= true;
472 case SEC_CHAN_DOMAIN
:
475 case SEC_CHAN_DNS_DOMAIN
:
477 * AD domains should be secure
479 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
480 require_sign_or_seal
= true;
481 require_strong_key
= true;
482 neutralize_nt4_emulation
= true;
483 trust_support_kerberos
= true;
487 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
488 require_sign_or_seal
= true;
489 require_strong_key
= true;
490 if (lpcfg_server_role(lp_ctx
) == ROLE_ACTIVE_DIRECTORY_DC
) {
491 trust_support_kerberos
= true;
496 required_flags
|= NETLOGON_NEG_RODC_PASSTHROUGH
;
497 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
498 require_sign_or_seal
= true;
499 require_strong_key
= true;
500 neutralize_nt4_emulation
= true;
501 trust_support_kerberos
= true;
506 return NT_STATUS_INVALID_PARAMETER
;
509 if (global_client_use_krb5_netlogon
== Auto
) {
510 if (support_krb5_netlogon
) {
511 global_client_use_krb5_netlogon
= trust_support_kerberos
;
513 global_client_use_krb5_netlogon
= false;
516 client_use_krb5_netlogon
= global_client_use_krb5_netlogon
;
517 client_use_krb5_netlogon
= lpcfg_parm_bool(lp_ctx
, NULL
,
518 "client use krb5 netlogon",
519 server_netbios_domain
,
520 client_use_krb5_netlogon
);
522 if (reject_aes_servers
) {
523 client_use_krb5_netlogon
= true;
526 if (client_use_krb5_netlogon
) {
527 if (!support_krb5_netlogon
) {
528 DBG_ERR("No support for ServerAuthenticateKerberos!\n");
530 return NT_STATUS_DEVICE_FEATURE_NOT_SUPPORTED
;
532 proposed_flags
|= NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
;
535 if (neutralize_nt4_emulation
) {
536 proposed_flags
|= NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION
;
539 if (require_sign_or_seal
) {
540 required_flags
|= NETLOGON_NEG_ARCFOUR
;
541 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
543 proposed_flags
&= ~NETLOGON_NEG_AUTHENTICATED_RPC
;
546 if (reject_md5_servers
) {
547 required_flags
|= NETLOGON_NEG_ARCFOUR
;
548 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
549 required_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
550 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
553 if (require_strong_key
) {
554 required_flags
|= NETLOGON_NEG_ARCFOUR
;
555 required_flags
|= NETLOGON_NEG_STRONG_KEYS
;
556 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
559 if (reject_aes_servers
) {
560 required_flags
|= NETLOGON_NEG_ARCFOUR
;
561 required_flags
|= NETLOGON_NEG_STRONG_KEYS
;
562 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
563 required_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
564 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
565 required_flags
|= NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
;
569 * If weak crypto is disabled, do not announce that we support RC4 and
572 if (lpcfg_weak_crypto(lp_ctx
) == SAMBA_WEAK_CRYPTO_DISALLOWED
) {
573 required_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
576 proposed_flags
|= required_flags
;
578 if (required_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
579 required_flags
&= ~NETLOGON_NEG_ARCFOUR
;
580 required_flags
&= ~NETLOGON_NEG_STRONG_KEYS
;
583 if (required_flags
& NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
) {
584 required_flags
&= ~NETLOGON_NEG_SUPPORTS_AES
;
587 if (proposed_flags
& NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
) {
588 seal_secure_channel
= true;
591 if (seal_secure_channel
) {
592 auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
594 auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
597 if (server_dns_domain
== NULL
) {
598 server_dns_domain
= "";
601 status
= netlogon_creds_cli_context_common(client_computer
,
608 server_netbios_domain
,
612 if (!NT_STATUS_IS_OK(status
)) {
617 context
->db
.g_ctx
= g_lock_ctx_init(context
, msg_ctx
);
618 if (context
->db
.g_ctx
== NULL
) {
619 TALLOC_FREE(context
);
621 return NT_STATUS_NO_MEMORY
;
624 status
= netlogon_creds_cli_open_global_db(lp_ctx
);
625 if (!NT_STATUS_IS_OK(status
)) {
626 TALLOC_FREE(context
);
628 return NT_STATUS_NO_MEMORY
;
631 context
->db
.ctx
= netlogon_creds_cli_global_db
;
637 NTSTATUS
netlogon_creds_bind_cli_credentials(
638 struct netlogon_creds_cli_context
*context
, TALLOC_CTX
*mem_ctx
,
639 struct cli_credentials
**pcli_creds
)
641 struct cli_credentials
*cli_creds
;
642 struct netlogon_creds_CredentialState
*ncreds
;
645 cli_creds
= cli_credentials_init(mem_ctx
);
646 if (cli_creds
== NULL
) {
647 return NT_STATUS_NO_MEMORY
;
649 cli_credentials_set_secure_channel_type(cli_creds
,
650 context
->client
.type
);
651 cli_credentials_set_username(cli_creds
, context
->client
.account
,
653 cli_credentials_set_domain(cli_creds
, context
->server
.netbios_domain
,
655 cli_credentials_set_realm(cli_creds
, context
->server
.dns_domain
,
658 status
= netlogon_creds_cli_get(context
, cli_creds
, &ncreds
);
659 if (!NT_STATUS_IS_OK(status
)) {
660 TALLOC_FREE(cli_creds
);
663 cli_credentials_set_netlogon_creds(cli_creds
, ncreds
);
665 *pcli_creds
= cli_creds
;
669 char *netlogon_creds_cli_debug_string(
670 const struct netlogon_creds_cli_context
*context
,
673 return talloc_asprintf(mem_ctx
, "netlogon_creds_cli:%s",
674 context
->db
.key_name
);
677 void netlogon_creds_cli_use_kerberos(
678 struct netlogon_creds_cli_context
*context
,
679 bool *client_use_krb5_netlogon
,
680 bool *reject_aes_servers
)
682 *client_use_krb5_netlogon
= false;
683 *reject_aes_servers
= false;
685 if (context
->client
.required_flags
& NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
) {
686 *client_use_krb5_netlogon
= true;
687 *reject_aes_servers
= true;
690 if (context
->client
.proposed_flags
& NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
) {
691 *client_use_krb5_netlogon
= true;
695 enum dcerpc_AuthLevel
netlogon_creds_cli_auth_level(
696 struct netlogon_creds_cli_context
*context
)
698 return context
->client
.auth_level
;
701 static bool netlogon_creds_cli_downgraded(uint32_t negotiated_flags
,
702 bool authenticate_kerberos
,
703 uint32_t proposed_flags
,
704 uint32_t required_flags
)
706 uint32_t req_flags
= required_flags
;
709 req_flags
= required_flags
;
710 if (authenticate_kerberos
) {
711 if ((negotiated_flags
& NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
) &&
712 (proposed_flags
& NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
))
714 req_flags
&= ~NETLOGON_NEG_ARCFOUR
;
715 req_flags
&= ~NETLOGON_NEG_STRONG_KEYS
;
716 req_flags
&= ~NETLOGON_NEG_SUPPORTS_AES
;
721 if (req_flags
& NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
) {
724 if (negotiated_flags
& NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
) {
728 if ((negotiated_flags
& NETLOGON_NEG_SUPPORTS_AES
) &&
729 (proposed_flags
& NETLOGON_NEG_SUPPORTS_AES
))
731 req_flags
&= ~NETLOGON_NEG_ARCFOUR
|NETLOGON_NEG_STRONG_KEYS
;
734 tmp_flags
= negotiated_flags
;
735 tmp_flags
&= req_flags
;
736 if (tmp_flags
!= req_flags
) {
743 struct netlogon_creds_cli_fetch_state
{
745 struct netlogon_creds_CredentialState
*creds
;
746 uint32_t proposed_flags
;
747 uint32_t required_flags
;
751 static void netlogon_creds_cli_fetch_parser(TDB_DATA key
, TDB_DATA data
,
754 struct netlogon_creds_cli_fetch_state
*state
=
755 (struct netlogon_creds_cli_fetch_state
*)private_data
;
756 enum ndr_err_code ndr_err
;
760 state
->creds
= talloc_zero(state
->mem_ctx
,
761 struct netlogon_creds_CredentialState
);
762 if (state
->creds
== NULL
) {
763 state
->status
= NT_STATUS_NO_MEMORY
;
767 blob
.data
= data
.dptr
;
768 blob
.length
= data
.dsize
;
770 ndr_err
= ndr_pull_struct_blob(&blob
, state
->creds
, state
->creds
,
771 (ndr_pull_flags_fn_t
)ndr_pull_netlogon_creds_CredentialState
);
772 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
773 TALLOC_FREE(state
->creds
);
774 state
->status
= ndr_map_error2ntstatus(ndr_err
);
778 if (DEBUGLEVEL
>= 10) {
779 NDR_PRINT_DEBUG(netlogon_creds_CredentialState
, state
->creds
);
782 if (state
->proposed_flags
!= state
->creds
->client_requested_flags
) {
783 TALLOC_FREE(state
->creds
);
784 state
->status
= NT_STATUS_RESOURCE_REQUIREMENTS_CHANGED
;
788 downgraded
= netlogon_creds_cli_downgraded(
789 state
->creds
->negotiate_flags
,
790 state
->creds
->authenticate_kerberos
,
791 state
->proposed_flags
,
792 state
->required_flags
);
794 TALLOC_FREE(state
->creds
);
795 state
->status
= NT_STATUS_DOWNGRADE_DETECTED
;
799 state
->status
= NT_STATUS_OK
;
802 static NTSTATUS
netlogon_creds_cli_get_internal(
803 struct netlogon_creds_cli_context
*context
,
804 TALLOC_CTX
*mem_ctx
, struct netlogon_creds_CredentialState
**pcreds
);
806 NTSTATUS
netlogon_creds_cli_get(struct netlogon_creds_cli_context
*context
,
808 struct netlogon_creds_CredentialState
**_creds
)
811 struct netlogon_creds_CredentialState
*creds
;
815 status
= netlogon_creds_cli_get_internal(context
, mem_ctx
, &creds
);
816 if (!NT_STATUS_IS_OK(status
)) {
821 * mark it as invalid for step operations.
824 creds
->seed
= (struct netr_Credential
) {{0}};
825 creds
->client
= (struct netr_Credential
) {{0}};
826 creds
->server
= (struct netr_Credential
) {{0}};
832 bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context
*context
,
833 const struct netlogon_creds_CredentialState
*creds1
)
835 TALLOC_CTX
*frame
= talloc_stackframe();
836 struct netlogon_creds_CredentialState
*creds2
;
840 enum ndr_err_code ndr_err
;
843 status
= netlogon_creds_cli_get(context
, frame
, &creds2
);
844 if (!NT_STATUS_IS_OK(status
)) {
849 ndr_err
= ndr_push_struct_blob(&blob1
, frame
, creds1
,
850 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
851 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
856 ndr_err
= ndr_push_struct_blob(&blob2
, frame
, creds2
,
857 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
858 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
863 equal
= data_blob_equal_const_time(&blob1
, &blob2
);
870 static NTSTATUS
netlogon_creds_cli_store_internal(
871 struct netlogon_creds_cli_context
*context
,
872 struct netlogon_creds_CredentialState
*creds
)
874 TALLOC_CTX
*frame
= talloc_stackframe();
876 enum ndr_err_code ndr_err
;
880 if (DEBUGLEVEL
>= 10) {
881 NDR_PRINT_DEBUG(netlogon_creds_CredentialState
, creds
);
884 ndr_err
= ndr_push_struct_blob(&blob
, frame
, creds
,
885 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
886 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
887 status
= ndr_map_error2ntstatus(ndr_err
);
892 data
.dptr
= blob
.data
;
893 data
.dsize
= blob
.length
;
895 status
= dbwrap_store(context
->db
.ctx
,
896 context
->db
.key_data
,
898 if (!NT_STATUS_IS_OK(status
)) {
907 NTSTATUS
netlogon_creds_cli_store(struct netlogon_creds_cli_context
*context
,
908 struct netlogon_creds_CredentialState
*creds
)
912 if (context
->db
.locked_state
== NULL
) {
914 * this was not the result of netlogon_creds_cli_lock*()
916 return NT_STATUS_INVALID_PAGE_PROTECTION
;
919 if (context
->db
.locked_state
->creds
!= creds
) {
921 * this was not the result of netlogon_creds_cli_lock*()
923 return NT_STATUS_INVALID_PAGE_PROTECTION
;
926 status
= netlogon_creds_cli_store_internal(context
, creds
);
930 static NTSTATUS
netlogon_creds_cli_delete_internal(
931 struct netlogon_creds_cli_context
*context
)
934 status
= dbwrap_delete(context
->db
.ctx
, context
->db
.key_data
);
938 NTSTATUS
netlogon_creds_cli_delete_lck(
939 struct netlogon_creds_cli_context
*context
)
943 if (context
->db
.lock
!= NETLOGON_CREDS_CLI_LCK_EXCLUSIVE
) {
944 return NT_STATUS_NOT_LOCKED
;
947 status
= netlogon_creds_cli_delete_internal(context
);
951 NTSTATUS
netlogon_creds_cli_delete(struct netlogon_creds_cli_context
*context
,
952 struct netlogon_creds_CredentialState
*creds
)
956 if (context
->db
.locked_state
== NULL
) {
958 * this was not the result of netlogon_creds_cli_lock*()
960 return NT_STATUS_INVALID_PAGE_PROTECTION
;
963 if (context
->db
.locked_state
->creds
!= creds
) {
965 * this was not the result of netlogon_creds_cli_lock*()
967 return NT_STATUS_INVALID_PAGE_PROTECTION
;
970 status
= netlogon_creds_cli_delete_internal(context
);
974 struct netlogon_creds_cli_lock_state
{
975 struct netlogon_creds_cli_locked_state
*locked_state
;
976 struct netlogon_creds_CredentialState
*creds
;
979 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
);
981 struct tevent_req
*netlogon_creds_cli_lock_send(TALLOC_CTX
*mem_ctx
,
982 struct tevent_context
*ev
,
983 struct netlogon_creds_cli_context
*context
)
985 struct tevent_req
*req
;
986 struct netlogon_creds_cli_lock_state
*state
;
987 struct netlogon_creds_cli_locked_state
*locked_state
;
988 struct tevent_req
*subreq
;
990 req
= tevent_req_create(mem_ctx
, &state
,
991 struct netlogon_creds_cli_lock_state
);
996 if (context
->db
.locked_state
!= NULL
) {
997 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
998 return tevent_req_post(req
, ev
);
1001 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
1002 if (tevent_req_nomem(locked_state
, req
)) {
1003 return tevent_req_post(req
, ev
);
1005 talloc_set_destructor(locked_state
,
1006 netlogon_creds_cli_locked_state_destructor
);
1007 locked_state
->context
= context
;
1009 context
->db
.locked_state
= locked_state
;
1010 state
->locked_state
= locked_state
;
1012 if (context
->db
.g_ctx
== NULL
) {
1015 status
= netlogon_creds_cli_get_internal(
1016 context
, state
, &state
->creds
);
1017 if (tevent_req_nterror(req
, status
)) {
1018 return tevent_req_post(req
, ev
);
1024 subreq
= g_lock_lock_send(state
, ev
,
1026 string_term_tdb_data(context
->db
.key_name
),
1029 if (tevent_req_nomem(subreq
, req
)) {
1030 return tevent_req_post(req
, ev
);
1032 tevent_req_set_callback(subreq
, netlogon_creds_cli_lock_done
, req
);
1037 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
)
1039 struct tevent_req
*req
=
1040 tevent_req_callback_data(subreq
,
1042 struct netlogon_creds_cli_lock_state
*state
=
1043 tevent_req_data(req
,
1044 struct netlogon_creds_cli_lock_state
);
1047 status
= g_lock_lock_recv(subreq
);
1048 TALLOC_FREE(subreq
);
1049 if (tevent_req_nterror(req
, status
)) {
1052 state
->locked_state
->is_glocked
= true;
1054 status
= netlogon_creds_cli_get_internal(state
->locked_state
->context
,
1055 state
, &state
->creds
);
1056 if (tevent_req_nterror(req
, status
)) {
1059 tevent_req_done(req
);
1062 static NTSTATUS
netlogon_creds_cli_get_internal(
1063 struct netlogon_creds_cli_context
*context
,
1064 TALLOC_CTX
*mem_ctx
, struct netlogon_creds_CredentialState
**pcreds
)
1066 struct netlogon_creds_cli_fetch_state fstate
= {
1067 .status
= NT_STATUS_INTERNAL_ERROR
,
1068 .proposed_flags
= context
->client
.proposed_flags
,
1069 .required_flags
= context
->client
.required_flags
,
1073 fstate
.mem_ctx
= mem_ctx
;
1074 status
= dbwrap_parse_record(context
->db
.ctx
,
1075 context
->db
.key_data
,
1076 netlogon_creds_cli_fetch_parser
,
1078 if (!NT_STATUS_IS_OK(status
)) {
1081 if (!NT_STATUS_IS_OK(fstate
.status
)) {
1082 return fstate
.status
;
1085 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
1086 *pcreds
= fstate
.creds
;
1087 return NT_STATUS_OK
;
1091 * It is really important to try SamLogonEx here,
1092 * because multiple processes can talk to the same
1093 * domain controller, without using the credential
1096 * With a normal SamLogon call, we must keep the
1097 * credentials chain updated and intact between all
1098 * users of the machine account (which would imply
1099 * cross-node communication for every NTLM logon).
1101 * The credentials chain is not per NETLOGON pipe
1102 * connection, but globally on the server/client pair
1105 * It's also important to use NetlogonValidationSamInfo4 (6),
1106 * because it relies on the rpc transport encryption
1107 * and avoids using the global netlogon schannel
1108 * session key to en/decrypt secret information
1109 * like the user_session_key for network logons.
1111 * [MS-APDS] 3.1.5.2 NTLM Network Logon
1112 * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and
1113 * NETLOGON_NEG_AUTHENTICATED_RPC set together
1114 * are the indication that the server supports
1115 * NetlogonValidationSamInfo4 (6). And it must only
1116 * be used if "SealSecureChannel" is used.
1118 * The "SealSecureChannel" AUTH_TYPE_SCHANNEL/AUTH_LEVEL_PRIVACY
1119 * check is done in netlogon_creds_cli_LogonSamLogon*().
1122 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
1123 context
->server
.try_validation6
= true;
1124 context
->server
.try_logon_ex
= true;
1125 context
->server
.try_logon_with
= true;
1127 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
1128 context
->server
.try_validation6
= false;
1129 context
->server
.try_logon_ex
= false;
1131 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
1132 context
->server
.try_validation6
= false;
1135 *pcreds
= fstate
.creds
;
1136 return NT_STATUS_OK
;
1139 NTSTATUS
netlogon_creds_cli_lock_recv(struct tevent_req
*req
,
1140 TALLOC_CTX
*mem_ctx
,
1141 struct netlogon_creds_CredentialState
**creds
)
1143 struct netlogon_creds_cli_lock_state
*state
=
1144 tevent_req_data(req
,
1145 struct netlogon_creds_cli_lock_state
);
1148 if (tevent_req_is_nterror(req
, &status
)) {
1149 tevent_req_received(req
);
1153 talloc_steal(state
->creds
, state
->locked_state
);
1154 state
->locked_state
->creds
= state
->creds
;
1155 *creds
= talloc_move(mem_ctx
, &state
->creds
);
1156 tevent_req_received(req
);
1157 return NT_STATUS_OK
;
1160 NTSTATUS
netlogon_creds_cli_lock(struct netlogon_creds_cli_context
*context
,
1161 TALLOC_CTX
*mem_ctx
,
1162 struct netlogon_creds_CredentialState
**creds
)
1164 TALLOC_CTX
*frame
= talloc_stackframe();
1165 struct tevent_context
*ev
;
1166 struct tevent_req
*req
;
1167 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1169 ev
= samba_tevent_context_init(frame
);
1173 req
= netlogon_creds_cli_lock_send(frame
, ev
, context
);
1177 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1180 status
= netlogon_creds_cli_lock_recv(req
, mem_ctx
, creds
);
1186 struct netlogon_creds_cli_lck
{
1187 struct netlogon_creds_cli_context
*context
;
1190 struct netlogon_creds_cli_lck_state
{
1191 struct netlogon_creds_cli_lck
*lck
;
1192 enum netlogon_creds_cli_lck_type type
;
1195 static void netlogon_creds_cli_lck_locked(struct tevent_req
*subreq
);
1196 static int netlogon_creds_cli_lck_destructor(
1197 struct netlogon_creds_cli_lck
*lck
);
1199 struct tevent_req
*netlogon_creds_cli_lck_send(
1200 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
1201 struct netlogon_creds_cli_context
*context
,
1202 enum netlogon_creds_cli_lck_type type
)
1204 struct tevent_req
*req
, *subreq
;
1205 struct netlogon_creds_cli_lck_state
*state
;
1206 enum g_lock_type gtype
;
1208 req
= tevent_req_create(mem_ctx
, &state
,
1209 struct netlogon_creds_cli_lck_state
);
1214 if (context
->db
.lock
!= NETLOGON_CREDS_CLI_LCK_NONE
) {
1215 DBG_DEBUG("context already locked\n");
1216 tevent_req_nterror(req
, NT_STATUS_INVALID_LOCK_SEQUENCE
);
1217 return tevent_req_post(req
, ev
);
1221 case NETLOGON_CREDS_CLI_LCK_SHARED
:
1222 gtype
= G_LOCK_READ
;
1224 case NETLOGON_CREDS_CLI_LCK_EXCLUSIVE
:
1225 gtype
= G_LOCK_WRITE
;
1228 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1229 return tevent_req_post(req
, ev
);
1232 state
->lck
= talloc(state
, struct netlogon_creds_cli_lck
);
1233 if (tevent_req_nomem(state
->lck
, req
)) {
1234 return tevent_req_post(req
, ev
);
1236 state
->lck
->context
= context
;
1239 subreq
= g_lock_lock_send(state
, ev
,
1241 string_term_tdb_data(context
->db
.key_name
),
1244 if (tevent_req_nomem(subreq
, req
)) {
1245 return tevent_req_post(req
, ev
);
1247 tevent_req_set_callback(subreq
, netlogon_creds_cli_lck_locked
, req
);
1252 static void netlogon_creds_cli_lck_locked(struct tevent_req
*subreq
)
1254 struct tevent_req
*req
= tevent_req_callback_data(
1255 subreq
, struct tevent_req
);
1256 struct netlogon_creds_cli_lck_state
*state
= tevent_req_data(
1257 req
, struct netlogon_creds_cli_lck_state
);
1260 status
= g_lock_lock_recv(subreq
);
1261 TALLOC_FREE(subreq
);
1262 if (tevent_req_nterror(req
, status
)) {
1266 state
->lck
->context
->db
.lock
= state
->type
;
1267 talloc_set_destructor(state
->lck
, netlogon_creds_cli_lck_destructor
);
1269 tevent_req_done(req
);
1272 static int netlogon_creds_cli_lck_destructor(
1273 struct netlogon_creds_cli_lck
*lck
)
1275 struct netlogon_creds_cli_context
*ctx
= lck
->context
;
1278 status
= g_lock_unlock(ctx
->db
.g_ctx
,
1279 string_term_tdb_data(ctx
->db
.key_name
));
1280 if (!NT_STATUS_IS_OK(status
)) {
1281 DBG_WARNING("g_lock_unlock failed: %s\n", nt_errstr(status
));
1282 smb_panic("g_lock_unlock failed");
1284 ctx
->db
.lock
= NETLOGON_CREDS_CLI_LCK_NONE
;
1288 NTSTATUS
netlogon_creds_cli_lck_recv(
1289 struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
1290 struct netlogon_creds_cli_lck
**lck
)
1292 struct netlogon_creds_cli_lck_state
*state
= tevent_req_data(
1293 req
, struct netlogon_creds_cli_lck_state
);
1296 if (tevent_req_is_nterror(req
, &status
)) {
1299 *lck
= talloc_move(mem_ctx
, &state
->lck
);
1300 return NT_STATUS_OK
;
1303 NTSTATUS
netlogon_creds_cli_lck(
1304 struct netlogon_creds_cli_context
*context
,
1305 enum netlogon_creds_cli_lck_type type
,
1306 TALLOC_CTX
*mem_ctx
, struct netlogon_creds_cli_lck
**lck
)
1308 TALLOC_CTX
*frame
= talloc_stackframe();
1309 struct tevent_context
*ev
;
1310 struct tevent_req
*req
;
1311 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1313 ev
= samba_tevent_context_init(frame
);
1317 req
= netlogon_creds_cli_lck_send(frame
, ev
, context
, type
);
1321 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1324 status
= netlogon_creds_cli_lck_recv(req
, mem_ctx
, lck
);
1330 static NTSTATUS
netlogon_creds_cli_check_transport(
1331 enum dcerpc_AuthType auth_type
,
1332 enum dcerpc_AuthLevel auth_level
,
1333 const struct netlogon_creds_CredentialState
*creds
,
1334 enum dcerpc_AuthLevel min_auth_level
)
1336 if (auth_level
< min_auth_level
) {
1337 return NT_STATUS_INVALID_PARAMETER_MIX
;
1340 if (creds
== NULL
) {
1341 return NT_STATUS_INVALID_PARAMETER_MIX
;
1344 if (creds
->authenticate_kerberos
) {
1345 if (auth_type
== DCERPC_AUTH_TYPE_KRB5
) {
1346 switch (auth_level
) {
1347 case DCERPC_AUTH_LEVEL_PRIVACY
:
1348 return NT_STATUS_OK
;
1354 return NT_STATUS_INVALID_PARAMETER_MIX
;
1357 if (auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
1358 switch (auth_level
) {
1359 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1360 case DCERPC_AUTH_LEVEL_PRIVACY
:
1361 return NT_STATUS_OK
;
1366 return NT_STATUS_INVALID_PARAMETER_MIX
;
1369 if (creds
->negotiate_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
1371 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
1372 * it should be used, which means
1373 * we had a chance to verify no downgrade
1376 * This relies on netlogon_creds_cli_check*
1377 * being called before, as first request after
1380 return NT_STATUS_INVALID_PARAMETER_MIX
;
1383 return NT_STATUS_OK
;
1386 struct netlogon_creds_cli_auth_state
{
1387 struct tevent_context
*ev
;
1388 struct netlogon_creds_cli_context
*context
;
1389 struct dcerpc_binding_handle
*binding_handle
;
1390 enum dcerpc_AuthType auth_type
;
1391 enum dcerpc_AuthLevel auth_level
;
1392 uint8_t num_nt_hashes
;
1393 uint8_t idx_nt_hashes
;
1394 const struct samr_Password
* const *nt_hashes
;
1395 const struct samr_Password
*used_nt_hash
;
1396 char *srv_name_slash
;
1397 uint32_t current_flags
;
1398 struct netr_Credential client_challenge
;
1399 struct netr_Credential server_challenge
;
1400 struct netlogon_creds_CredentialState
*creds
;
1401 struct netr_Credential client_credential
;
1402 struct netr_Credential server_credential
;
1403 uint32_t negotiate_flags
;
1412 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
);
1414 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
);
1416 struct tevent_req
*netlogon_creds_cli_auth_send(TALLOC_CTX
*mem_ctx
,
1417 struct tevent_context
*ev
,
1418 struct netlogon_creds_cli_context
*context
,
1419 struct dcerpc_binding_handle
*b
,
1420 uint8_t num_nt_hashes
,
1421 const struct samr_Password
* const *nt_hashes
)
1423 struct tevent_req
*req
;
1424 struct netlogon_creds_cli_auth_state
*state
;
1426 bool client_use_krb5_netlogon
= false;
1427 bool reject_aes_servers
= false;
1429 req
= tevent_req_create(mem_ctx
, &state
,
1430 struct netlogon_creds_cli_auth_state
);
1436 state
->context
= context
;
1437 state
->binding_handle
= b
;
1438 if (num_nt_hashes
< 1) {
1439 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1440 return tevent_req_post(req
, ev
);
1442 if (num_nt_hashes
> 4) {
1443 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1444 return tevent_req_post(req
, ev
);
1447 state
->num_nt_hashes
= num_nt_hashes
;
1448 state
->idx_nt_hashes
= 0;
1449 state
->nt_hashes
= nt_hashes
;
1451 if (context
->db
.lock
!= NETLOGON_CREDS_CLI_LCK_EXCLUSIVE
) {
1452 tevent_req_nterror(req
, NT_STATUS_NOT_LOCKED
);
1453 return tevent_req_post(req
, ev
);
1456 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1457 context
->server
.computer
);
1458 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1459 return tevent_req_post(req
, ev
);
1462 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1464 &state
->auth_level
);
1466 state
->try_auth3
= true;
1467 state
->try_auth2
= true;
1469 if (context
->client
.required_flags
!= 0) {
1470 state
->require_auth2
= true;
1473 netlogon_creds_cli_use_kerberos(context
,
1474 &client_use_krb5_netlogon
,
1475 &reject_aes_servers
);
1476 if (client_use_krb5_netlogon
) {
1477 if (state
->auth_type
== DCERPC_AUTH_TYPE_KRB5
&&
1478 state
->auth_level
== DCERPC_AUTH_LEVEL_PRIVACY
)
1480 state
->try_krb5
= true;
1484 if (reject_aes_servers
) {
1485 if (!state
->try_krb5
) {
1486 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1487 return tevent_req_post(req
, ev
);
1489 state
->require_krb5
= true;
1492 state
->used_nt_hash
= state
->nt_hashes
[state
->idx_nt_hashes
];
1493 state
->current_flags
= context
->client
.proposed_flags
;
1495 status
= dbwrap_purge(state
->context
->db
.ctx
,
1496 state
->context
->db
.key_data
);
1497 if (tevent_req_nterror(req
, status
)) {
1498 return tevent_req_post(req
, ev
);
1501 if (state
->try_krb5
) {
1502 struct tevent_req
*subreq
= NULL
;
1504 state
->creds
= netlogon_creds_kerberos_init(state
,
1505 state
->context
->client
.account
,
1506 state
->context
->client
.computer
,
1507 state
->context
->client
.type
,
1508 state
->context
->client
.proposed_flags
,
1509 NULL
, /* client_sid */
1510 state
->current_flags
);
1511 if (tevent_req_nomem(state
->creds
, req
)) {
1512 return tevent_req_post(req
, ev
);
1515 state
->negotiate_flags
= state
->context
->client
.proposed_flags
;
1517 subreq
= dcerpc_netr_ServerAuthenticateKerberos_send(state
,
1519 state
->binding_handle
,
1520 state
->srv_name_slash
,
1521 state
->context
->client
.account
,
1522 state
->context
->client
.type
,
1523 state
->context
->client
.computer
,
1524 &state
->negotiate_flags
,
1526 if (tevent_req_nomem(subreq
, req
)) {
1527 return tevent_req_post(req
, ev
);
1529 tevent_req_set_callback(subreq
,
1530 netlogon_creds_cli_auth_srvauth_done
,
1535 netlogon_creds_cli_auth_challenge_start(req
);
1536 if (!tevent_req_is_in_progress(req
)) {
1537 return tevent_req_post(req
, ev
);
1543 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
);
1545 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
)
1547 struct netlogon_creds_cli_auth_state
*state
=
1548 tevent_req_data(req
,
1549 struct netlogon_creds_cli_auth_state
);
1550 struct tevent_req
*subreq
;
1552 TALLOC_FREE(state
->creds
);
1554 netlogon_creds_random_challenge(&state
->client_challenge
);
1556 subreq
= dcerpc_netr_ServerReqChallenge_send(state
, state
->ev
,
1557 state
->binding_handle
,
1558 state
->srv_name_slash
,
1559 state
->context
->client
.computer
,
1560 &state
->client_challenge
,
1561 &state
->server_challenge
);
1562 if (tevent_req_nomem(subreq
, req
)) {
1565 tevent_req_set_callback(subreq
,
1566 netlogon_creds_cli_auth_challenge_done
,
1570 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
);
1572 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
)
1574 struct tevent_req
*req
=
1575 tevent_req_callback_data(subreq
,
1577 struct netlogon_creds_cli_auth_state
*state
=
1578 tevent_req_data(req
,
1579 struct netlogon_creds_cli_auth_state
);
1583 status
= dcerpc_netr_ServerReqChallenge_recv(subreq
, state
, &result
);
1584 TALLOC_FREE(subreq
);
1585 if (tevent_req_nterror(req
, status
)) {
1588 if (tevent_req_nterror(req
, result
)) {
1592 if (!state
->try_krb5
&& !state
->try_auth3
&& !state
->try_auth2
) {
1593 state
->current_flags
= 0;
1596 /* Calculate the session key and client credentials */
1598 state
->creds
= netlogon_creds_client_init(state
,
1599 state
->context
->client
.account
,
1600 state
->context
->client
.computer
,
1601 state
->context
->client
.type
,
1602 &state
->client_challenge
,
1603 &state
->server_challenge
,
1604 state
->used_nt_hash
,
1605 &state
->client_credential
,
1606 state
->context
->client
.proposed_flags
,
1607 state
->current_flags
);
1608 if (tevent_req_nomem(state
->creds
, req
)) {
1612 if (state
->try_auth3
) {
1614 * We always need to send our proposed flags,
1615 * even if state->current_flags we passed to
1616 * netlogon_creds_client_init() is already downgraded,
1618 * An old server will just ignore the bits it doesn't
1619 * know about, but LogonGetCapabilities(level=2) will
1620 * report what we proposed.
1622 state
->negotiate_flags
= state
->context
->client
.proposed_flags
;
1624 subreq
= dcerpc_netr_ServerAuthenticate3_send(state
, state
->ev
,
1625 state
->binding_handle
,
1626 state
->srv_name_slash
,
1627 state
->context
->client
.account
,
1628 state
->context
->client
.type
,
1629 state
->context
->client
.computer
,
1630 &state
->client_credential
,
1631 &state
->server_credential
,
1632 &state
->negotiate_flags
,
1634 if (tevent_req_nomem(subreq
, req
)) {
1637 } else if (state
->try_auth2
) {
1639 * We always need to send our proposed flags,
1640 * even if state->current_flags we passed to
1641 * netlogon_creds_client_init() is already downgraded,
1643 * An old server will just ignore the bits it doesn't
1644 * know about, but LogonGetCapabilities(level=2) will
1645 * report what we proposed.
1647 state
->negotiate_flags
= state
->context
->client
.proposed_flags
;
1650 subreq
= dcerpc_netr_ServerAuthenticate2_send(state
, state
->ev
,
1651 state
->binding_handle
,
1652 state
->srv_name_slash
,
1653 state
->context
->client
.account
,
1654 state
->context
->client
.type
,
1655 state
->context
->client
.computer
,
1656 &state
->client_credential
,
1657 &state
->server_credential
,
1658 &state
->negotiate_flags
);
1659 if (tevent_req_nomem(subreq
, req
)) {
1663 state
->negotiate_flags
= 0;
1666 subreq
= dcerpc_netr_ServerAuthenticate_send(state
, state
->ev
,
1667 state
->binding_handle
,
1668 state
->srv_name_slash
,
1669 state
->context
->client
.account
,
1670 state
->context
->client
.type
,
1671 state
->context
->client
.computer
,
1672 &state
->client_credential
,
1673 &state
->server_credential
);
1674 if (tevent_req_nomem(subreq
, req
)) {
1678 tevent_req_set_callback(subreq
,
1679 netlogon_creds_cli_auth_srvauth_done
,
1683 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
)
1685 struct tevent_req
*req
=
1686 tevent_req_callback_data(subreq
,
1688 struct netlogon_creds_cli_auth_state
*state
=
1689 tevent_req_data(req
,
1690 struct netlogon_creds_cli_auth_state
);
1695 if (state
->try_krb5
) {
1696 status
= dcerpc_netr_ServerAuthenticateKerberos_recv(subreq
, state
,
1698 TALLOC_FREE(subreq
);
1699 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1700 if (state
->require_krb5
) {
1701 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1702 tevent_req_nterror(req
, status
);
1705 state
->try_krb5
= false;
1706 netlogon_creds_cli_auth_challenge_start(req
);
1709 if (tevent_req_nterror(req
, status
)) {
1713 * We don't downgrade if this fails
1714 * without PROCNUM_OUT_OF_RANGE.
1716 if (tevent_req_nterror(req
, result
)) {
1719 } else if (state
->try_auth3
) {
1720 status
= dcerpc_netr_ServerAuthenticate3_recv(subreq
, state
,
1722 TALLOC_FREE(subreq
);
1723 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1724 state
->try_auth3
= false;
1725 netlogon_creds_cli_auth_challenge_start(req
);
1728 if (tevent_req_nterror(req
, status
)) {
1731 } else if (state
->try_auth2
) {
1732 status
= dcerpc_netr_ServerAuthenticate2_recv(subreq
, state
,
1734 TALLOC_FREE(subreq
);
1735 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1736 state
->try_auth2
= false;
1737 if (state
->require_auth2
) {
1738 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1739 tevent_req_nterror(req
, status
);
1742 netlogon_creds_cli_auth_challenge_start(req
);
1745 if (tevent_req_nterror(req
, status
)) {
1749 status
= dcerpc_netr_ServerAuthenticate_recv(subreq
, state
,
1751 TALLOC_FREE(subreq
);
1752 if (tevent_req_nterror(req
, status
)) {
1757 if (!NT_STATUS_IS_OK(result
) &&
1758 !NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
))
1760 tevent_req_nterror(req
, result
);
1764 downgraded
= netlogon_creds_cli_downgraded(
1765 state
->negotiate_flags
,
1766 state
->creds
->authenticate_kerberos
,
1767 state
->context
->client
.proposed_flags
,
1768 state
->context
->client
.required_flags
);
1770 if (NT_STATUS_IS_OK(result
)) {
1771 tevent_req_nterror(req
, NT_STATUS_DOWNGRADE_DETECTED
);
1774 tevent_req_nterror(req
, result
);
1778 if (NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
)) {
1779 uint32_t prop_f
= state
->context
->client
.proposed_flags
;
1780 uint32_t cli_f
= state
->current_flags
;
1781 uint32_t srv_f
= state
->negotiate_flags
;
1782 uint32_t nego_f
= cli_f
& srv_f
;
1784 if (cli_f
== prop_f
&& nego_f
!= prop_f
) {
1786 * lets retry with the negotiated flags
1788 state
->current_flags
= nego_f
;
1789 netlogon_creds_cli_auth_challenge_start(req
);
1793 state
->idx_nt_hashes
+= 1;
1794 if (state
->idx_nt_hashes
>= state
->num_nt_hashes
) {
1796 * we already retried, giving up...
1798 tevent_req_nterror(req
, result
);
1803 * lets retry with the old nt hash.
1805 state
->used_nt_hash
= state
->nt_hashes
[state
->idx_nt_hashes
];
1806 state
->current_flags
= state
->context
->client
.proposed_flags
;
1807 netlogon_creds_cli_auth_challenge_start(req
);
1811 status
= netlogon_creds_client_verify(state
->creds
,
1812 &state
->server_credential
,
1815 if (tevent_req_nterror(req
, status
)) {
1819 if (state
->current_flags
== state
->context
->client
.proposed_flags
) {
1821 * Without a downgrade in the crypto we proposed
1822 * we can adjust the otherwise downgraded flags
1825 state
->creds
->negotiate_flags
&= state
->negotiate_flags
;
1826 } else if (state
->current_flags
!= state
->negotiate_flags
) {
1828 * We downgraded our crypto once, we should not
1829 * allow any additional downgrade!
1831 tevent_req_nterror(req
, NT_STATUS_DOWNGRADE_DETECTED
);
1835 state
->creds
->client_sid
.sub_auths
[0] = state
->rid
;
1836 status
= netlogon_creds_cli_store_internal(state
->context
,
1838 if (tevent_req_nterror(req
, status
)) {
1842 tevent_req_done(req
);
1845 NTSTATUS
netlogon_creds_cli_auth_recv(struct tevent_req
*req
,
1846 uint8_t *idx_nt_hashes
)
1848 struct netlogon_creds_cli_auth_state
*state
=
1849 tevent_req_data(req
,
1850 struct netlogon_creds_cli_auth_state
);
1855 if (tevent_req_is_nterror(req
, &status
)) {
1856 tevent_req_received(req
);
1860 *idx_nt_hashes
= state
->idx_nt_hashes
;
1861 tevent_req_received(req
);
1862 return NT_STATUS_OK
;
1865 NTSTATUS
netlogon_creds_cli_auth(struct netlogon_creds_cli_context
*context
,
1866 struct dcerpc_binding_handle
*b
,
1867 uint8_t num_nt_hashes
,
1868 const struct samr_Password
* const *nt_hashes
,
1869 uint8_t *idx_nt_hashes
)
1871 TALLOC_CTX
*frame
= talloc_stackframe();
1872 struct tevent_context
*ev
;
1873 struct tevent_req
*req
;
1874 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1878 ev
= samba_tevent_context_init(frame
);
1882 req
= netlogon_creds_cli_auth_send(frame
, ev
, context
, b
,
1883 num_nt_hashes
, nt_hashes
);
1887 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1890 status
= netlogon_creds_cli_auth_recv(req
, idx_nt_hashes
);
1896 struct netlogon_creds_cli_check_state
{
1897 struct tevent_context
*ev
;
1898 struct netlogon_creds_cli_context
*context
;
1899 struct dcerpc_binding_handle
*binding_handle
;
1900 enum dcerpc_AuthType auth_type
;
1901 enum dcerpc_AuthLevel auth_level
;
1903 char *srv_name_slash
;
1905 union netr_Capabilities caps
;
1906 union netr_Capabilities client_caps
;
1908 struct netlogon_creds_CredentialState
*creds
;
1909 struct netr_Authenticator req_auth
;
1910 struct netr_Authenticator rep_auth
;
1912 union netr_CONTROL_QUERY_INFORMATION ctrl_info
;
1915 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1917 static void netlogon_creds_cli_check_negotiate_caps(struct tevent_req
*subreq
);
1918 static void netlogon_creds_cli_check_client_caps(struct tevent_req
*subreq
);
1920 struct tevent_req
*netlogon_creds_cli_check_send(TALLOC_CTX
*mem_ctx
,
1921 struct tevent_context
*ev
,
1922 struct netlogon_creds_cli_context
*context
,
1923 struct dcerpc_binding_handle
*b
)
1925 struct tevent_req
*req
;
1926 struct netlogon_creds_cli_check_state
*state
;
1927 struct tevent_req
*subreq
;
1930 req
= tevent_req_create(mem_ctx
, &state
,
1931 struct netlogon_creds_cli_check_state
);
1937 state
->context
= context
;
1938 state
->binding_handle
= b
;
1940 if (context
->db
.lock
!= NETLOGON_CREDS_CLI_LCK_EXCLUSIVE
) {
1941 tevent_req_nterror(req
, NT_STATUS_NOT_LOCKED
);
1942 return tevent_req_post(req
, ev
);
1945 status
= netlogon_creds_cli_get_internal(context
, state
,
1947 if (tevent_req_nterror(req
, status
)) {
1948 return tevent_req_post(req
, ev
);
1951 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1952 context
->server
.computer
);
1953 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1954 return tevent_req_post(req
, ev
);
1957 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1959 &state
->auth_level
);
1961 status
= netlogon_creds_cli_check_transport(state
->auth_type
,
1964 DCERPC_AUTH_LEVEL_INTEGRITY
);
1965 if (tevent_req_nterror(req
, status
)) {
1966 return tevent_req_post(req
, ev
);
1970 * we defer all callbacks in order to cleanup
1971 * the database record.
1973 tevent_req_defer_callback(req
, state
->ev
);
1975 status
= netlogon_creds_client_authenticator(state
->creds
,
1977 if (tevent_req_nterror(req
, status
)) {
1978 return tevent_req_post(req
, ev
);
1980 ZERO_STRUCT(state
->rep_auth
);
1982 subreq
= dcerpc_netr_LogonGetCapabilities_send(state
, state
->ev
,
1983 state
->binding_handle
,
1984 state
->srv_name_slash
,
1985 state
->context
->client
.computer
,
1990 if (tevent_req_nomem(subreq
, req
)) {
1991 return tevent_req_post(req
, ev
);
1994 tevent_req_set_callback(subreq
,
1995 netlogon_creds_cli_check_negotiate_caps
,
2001 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
2004 struct netlogon_creds_cli_check_state
*state
=
2005 tevent_req_data(req
,
2006 struct netlogon_creds_cli_check_state
);
2008 if (state
->creds
== NULL
) {
2012 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2013 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2014 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2015 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2016 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2017 TALLOC_FREE(state
->creds
);
2021 netlogon_creds_cli_delete_lck(state
->context
);
2022 TALLOC_FREE(state
->creds
);
2025 static void netlogon_creds_cli_check_control_do(struct tevent_req
*req
);
2027 static void netlogon_creds_cli_check_negotiate_caps(struct tevent_req
*subreq
)
2029 struct tevent_req
*req
=
2030 tevent_req_callback_data(subreq
,
2032 struct netlogon_creds_cli_check_state
*state
=
2033 tevent_req_data(req
,
2034 struct netlogon_creds_cli_check_state
);
2038 status
= dcerpc_netr_LogonGetCapabilities_recv(subreq
, state
,
2040 TALLOC_FREE(subreq
);
2041 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2043 * Note that the negotiated flags are already checked
2044 * for our required flags after the ServerAuthenticate3/2 call.
2046 uint32_t negotiated
= state
->creds
->negotiate_flags
;
2048 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
2050 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
2051 * already, we expect this to work!
2053 status
= NT_STATUS_DOWNGRADE_DETECTED
;
2054 tevent_req_nterror(req
, status
);
2055 netlogon_creds_cli_check_cleanup(req
, status
);
2059 if (negotiated
& NETLOGON_NEG_STRONG_KEYS
) {
2061 * If we have negotiated NETLOGON_NEG_STRONG_KEYS
2062 * we expect this to work at least as far as the
2063 * NOT_SUPPORTED error handled below!
2065 * NT 4.0 and Old Samba servers are not
2066 * allowed without "require strong key = no"
2068 status
= NT_STATUS_DOWNGRADE_DETECTED
;
2069 tevent_req_nterror(req
, status
);
2070 netlogon_creds_cli_check_cleanup(req
, status
);
2075 * If we not require NETLOGON_NEG_SUPPORTS_AES or
2076 * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore
2077 * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2079 * This is needed against NT 4.0 and old Samba servers.
2081 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
2082 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
2083 * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
2084 * with the next request as the sequence number processing
2087 * So we'll do a LogonControl message to check that...
2089 netlogon_creds_cli_check_control_do(req
);
2092 if (tevent_req_nterror(req
, status
)) {
2093 netlogon_creds_cli_check_cleanup(req
, status
);
2097 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOT_IMPLEMENTED
)) {
2099 * Note that the negotiated flags are already checked
2100 * for our required flags after the ServerAuthenticate3/2 call.
2102 uint32_t negotiated
= state
->creds
->negotiate_flags
;
2104 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
2106 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
2107 * already, we expect this to work!
2109 status
= NT_STATUS_DOWNGRADE_DETECTED
;
2110 tevent_req_nterror(req
, status
);
2111 netlogon_creds_cli_check_cleanup(req
, status
);
2116 * This is ok, the server does not support
2117 * NETLOGON_NEG_SUPPORTS_AES.
2119 * netr_LogonGetCapabilities() was
2120 * netr_LogonDummyRoutine1() before
2121 * NETLOGON_NEG_SUPPORTS_AES was invented.
2123 netlogon_creds_cli_check_cleanup(req
, result
);
2124 tevent_req_done(req
);
2128 status
= netlogon_creds_client_verify(state
->creds
,
2129 &state
->rep_auth
.cred
,
2132 if (tevent_req_nterror(req
, status
)) {
2133 netlogon_creds_cli_check_cleanup(req
, status
);
2137 if (tevent_req_nterror(req
, result
)) {
2138 netlogon_creds_cli_check_cleanup(req
, result
);
2142 if (state
->caps
.server_capabilities
!= state
->creds
->negotiate_flags
) {
2143 status
= NT_STATUS_DOWNGRADE_DETECTED
;
2144 tevent_req_nterror(req
, status
);
2145 netlogon_creds_cli_check_cleanup(req
, status
);
2150 * This is the key check that makes this check secure. If we
2151 * get OK here (rather than NOT_SUPPORTED), then the server
2152 * did support AES. If the server only proposed STRONG_KEYS
2153 * and not AES, then it should have failed with
2154 * NOT_IMPLEMENTED. We always send AES as a client, so the
2155 * server should always have returned it.
2157 if (!(state
->caps
.server_capabilities
& NETLOGON_NEG_SUPPORTS_AES
)) {
2158 status
= NT_STATUS_DOWNGRADE_DETECTED
;
2159 tevent_req_nterror(req
, status
);
2160 netlogon_creds_cli_check_cleanup(req
, status
);
2164 status
= netlogon_creds_cli_store_internal(state
->context
,
2166 if (tevent_req_nterror(req
, status
)) {
2171 * Now try to verify our client proposed flags
2172 * arrived at the server, using query_level = 2
2175 status
= netlogon_creds_client_authenticator(state
->creds
,
2177 if (tevent_req_nterror(req
, status
)) {
2180 ZERO_STRUCT(state
->rep_auth
);
2182 subreq
= dcerpc_netr_LogonGetCapabilities_send(state
, state
->ev
,
2183 state
->binding_handle
,
2184 state
->srv_name_slash
,
2185 state
->context
->client
.computer
,
2189 &state
->client_caps
);
2190 if (tevent_req_nomem(subreq
, req
)) {
2194 tevent_req_set_callback(subreq
,
2195 netlogon_creds_cli_check_client_caps
,
2200 static void netlogon_creds_cli_check_client_caps(struct tevent_req
*subreq
)
2202 struct tevent_req
*req
=
2203 tevent_req_callback_data(subreq
,
2205 struct netlogon_creds_cli_check_state
*state
=
2206 tevent_req_data(req
,
2207 struct netlogon_creds_cli_check_state
);
2208 uint32_t requested_flags
;
2212 status
= dcerpc_netr_LogonGetCapabilities_recv(subreq
, state
,
2214 TALLOC_FREE(subreq
);
2215 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_BAD_STUB_DATA
)) {
2217 * unpatched Samba server, see
2218 * https://bugzilla.samba.org/show_bug.cgi?id=15418
2220 status
= NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE
;
2222 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE
)) {
2224 * Here we know the negotiated flags were already
2225 * verified with query_level=1, which means
2226 * the server supported NETLOGON_NEG_SUPPORTS_AES
2227 * and also NETLOGON_NEG_AUTHENTICATED_RPC
2229 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
2230 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
2231 * we should detect a faked
2232 * NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE
2233 * with the next request as the sequence number processing
2236 * So we'll do a LogonControl message to check that...
2238 netlogon_creds_cli_check_control_do(req
);
2241 if (tevent_req_nterror(req
, status
)) {
2242 netlogon_creds_cli_check_cleanup(req
, status
);
2246 status
= netlogon_creds_client_verify(state
->creds
,
2247 &state
->rep_auth
.cred
,
2250 if (tevent_req_nterror(req
, status
)) {
2251 netlogon_creds_cli_check_cleanup(req
, status
);
2254 if (tevent_req_nterror(req
, result
)) {
2255 netlogon_creds_cli_check_cleanup(req
, result
);
2259 requested_flags
= state
->creds
->client_requested_flags
;
2261 if (state
->client_caps
.requested_flags
!= requested_flags
) {
2262 status
= NT_STATUS_DOWNGRADE_DETECTED
;
2263 tevent_req_nterror(req
, status
);
2264 netlogon_creds_cli_check_cleanup(req
, status
);
2268 status
= netlogon_creds_cli_store_internal(state
->context
,
2270 if (tevent_req_nterror(req
, status
)) {
2274 tevent_req_done(req
);
2277 static void netlogon_creds_cli_check_control_done(struct tevent_req
*subreq
);
2279 static void netlogon_creds_cli_check_control_do(struct tevent_req
*req
)
2281 struct netlogon_creds_cli_check_state
*state
=
2282 tevent_req_data(req
,
2283 struct netlogon_creds_cli_check_state
);
2284 struct tevent_req
*subreq
= NULL
;
2287 * In case we got a downgrade based on a FAULT
2288 * we use a LogonControl that is supposed to
2289 * return WERR_NOT_SUPPORTED (without a DCERPC FAULT)
2290 * to verify that the connection is still ok and didn't
2293 subreq
= dcerpc_netr_LogonControl_send(state
,
2295 state
->binding_handle
,
2296 state
->srv_name_slash
,
2297 NETLOGON_CONTROL_QUERY
,
2300 if (tevent_req_nomem(subreq
, req
)) {
2304 tevent_req_set_callback(subreq
,
2305 netlogon_creds_cli_check_control_done
,
2310 static void netlogon_creds_cli_check_control_done(struct tevent_req
*subreq
)
2312 struct tevent_req
*req
=
2313 tevent_req_callback_data(subreq
,
2315 struct netlogon_creds_cli_check_state
*state
=
2316 tevent_req_data(req
,
2317 struct netlogon_creds_cli_check_state
);
2321 status
= dcerpc_netr_LogonControl_recv(subreq
, state
, &result
);
2322 TALLOC_FREE(subreq
);
2323 if (tevent_req_nterror(req
, status
)) {
2325 * We want to delete the creds,
2326 * so we pass NT_STATUS_DOWNGRADE_DETECTED
2327 * to netlogon_creds_cli_check_cleanup()
2329 status
= NT_STATUS_DOWNGRADE_DETECTED
;
2330 netlogon_creds_cli_check_cleanup(req
, status
);
2334 if (!W_ERROR_EQUAL(result
, WERR_NOT_SUPPORTED
)) {
2335 status
= NT_STATUS_DOWNGRADE_DETECTED
;
2336 tevent_req_nterror(req
, status
);
2337 netlogon_creds_cli_check_cleanup(req
, status
);
2341 tevent_req_done(req
);
2344 NTSTATUS
netlogon_creds_cli_check_recv(struct tevent_req
*req
,
2345 union netr_Capabilities
*capabilities
)
2347 struct netlogon_creds_cli_check_state
*state
= tevent_req_data(
2348 req
, struct netlogon_creds_cli_check_state
);
2351 if (tevent_req_is_nterror(req
, &status
)) {
2352 netlogon_creds_cli_check_cleanup(req
, status
);
2353 tevent_req_received(req
);
2357 if (capabilities
!= NULL
) {
2358 *capabilities
= state
->caps
;
2361 tevent_req_received(req
);
2362 return NT_STATUS_OK
;
2365 NTSTATUS
netlogon_creds_cli_check(struct netlogon_creds_cli_context
*context
,
2366 struct dcerpc_binding_handle
*b
,
2367 union netr_Capabilities
*capabilities
)
2369 TALLOC_CTX
*frame
= talloc_stackframe();
2370 struct tevent_context
*ev
;
2371 struct tevent_req
*req
;
2372 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2374 ev
= samba_tevent_context_init(frame
);
2378 req
= netlogon_creds_cli_check_send(frame
, ev
, context
, b
);
2382 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2385 status
= netlogon_creds_cli_check_recv(req
, capabilities
);
2391 struct netlogon_creds_cli_ServerPasswordSet_state
{
2392 struct tevent_context
*ev
;
2393 struct netlogon_creds_cli_context
*context
;
2394 struct dcerpc_binding_handle
*binding_handle
;
2395 uint32_t old_timeout
;
2397 char *srv_name_slash
;
2398 enum dcerpc_AuthType auth_type
;
2399 enum dcerpc_AuthLevel auth_level
;
2401 struct samr_CryptPassword samr_crypt_password
;
2402 struct netr_CryptPassword netr_crypt_password
;
2403 struct samr_Password samr_password
;
2405 struct netlogon_creds_CredentialState
*creds
;
2406 struct netlogon_creds_CredentialState tmp_creds
;
2407 struct netr_Authenticator req_auth
;
2408 struct netr_Authenticator rep_auth
;
2411 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
2413 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
);
2415 struct tevent_req
*netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX
*mem_ctx
,
2416 struct tevent_context
*ev
,
2417 struct netlogon_creds_cli_context
*context
,
2418 struct dcerpc_binding_handle
*b
,
2419 const DATA_BLOB
*new_password
,
2420 const uint32_t *new_version
)
2422 struct tevent_req
*req
;
2423 struct netlogon_creds_cli_ServerPasswordSet_state
*state
;
2424 struct tevent_req
*subreq
;
2427 req
= tevent_req_create(mem_ctx
, &state
,
2428 struct netlogon_creds_cli_ServerPasswordSet_state
);
2434 state
->context
= context
;
2435 state
->binding_handle
= b
;
2437 if (new_password
->length
< 14) {
2438 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2439 return tevent_req_post(req
, ev
);
2443 * netr_ServerPasswordSet
2445 mdfour(state
->samr_password
.hash
, new_password
->data
, new_password
->length
);
2448 * netr_ServerPasswordSet2
2450 ok
= set_pw_in_buffer(state
->samr_crypt_password
.data
,
2453 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2454 return tevent_req_post(req
, ev
);
2457 if (new_version
!= NULL
) {
2458 struct NL_PASSWORD_VERSION version
;
2459 uint32_t len
= IVAL(state
->samr_crypt_password
.data
, 512);
2460 uint32_t ofs
= 512 - len
;
2464 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2465 return tevent_req_post(req
, ev
);
2469 version
.ReservedField
= 0;
2470 version
.PasswordVersionNumber
= *new_version
;
2471 version
.PasswordVersionPresent
=
2472 NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT
;
2474 p
= state
->samr_crypt_password
.data
+ ofs
;
2475 SIVAL(p
, 0, version
.ReservedField
);
2476 SIVAL(p
, 4, version
.PasswordVersionNumber
);
2477 SIVAL(p
, 8, version
.PasswordVersionPresent
);
2480 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2481 context
->server
.computer
);
2482 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2483 return tevent_req_post(req
, ev
);
2486 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2488 &state
->auth_level
);
2490 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2492 if (tevent_req_nomem(subreq
, req
)) {
2493 return tevent_req_post(req
, ev
);
2496 tevent_req_set_callback(subreq
,
2497 netlogon_creds_cli_ServerPasswordSet_locked
,
2503 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
2506 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
2507 tevent_req_data(req
,
2508 struct netlogon_creds_cli_ServerPasswordSet_state
);
2510 if (state
->creds
== NULL
) {
2514 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
2515 state
->old_timeout
);
2517 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2518 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2519 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2520 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2521 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2522 TALLOC_FREE(state
->creds
);
2526 netlogon_creds_cli_delete(state
->context
, state
->creds
);
2527 TALLOC_FREE(state
->creds
);
2530 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
);
2532 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
)
2534 struct tevent_req
*req
=
2535 tevent_req_callback_data(subreq
,
2537 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
2538 tevent_req_data(req
,
2539 struct netlogon_creds_cli_ServerPasswordSet_state
);
2542 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2544 TALLOC_FREE(subreq
);
2545 if (tevent_req_nterror(req
, status
)) {
2549 status
= netlogon_creds_cli_check_transport(state
->auth_type
,
2552 DCERPC_AUTH_LEVEL_NONE
);
2553 if (tevent_req_nterror(req
, status
)) {
2557 state
->old_timeout
= dcerpc_binding_handle_set_timeout(
2558 state
->binding_handle
, 600000);
2561 * we defer all callbacks in order to cleanup
2562 * the database record.
2564 tevent_req_defer_callback(req
, state
->ev
);
2566 state
->tmp_creds
= *state
->creds
;
2567 status
= netlogon_creds_client_authenticator(&state
->tmp_creds
,
2569 if (tevent_req_nterror(req
, status
)) {
2572 ZERO_STRUCT(state
->rep_auth
);
2574 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
2576 status
= netlogon_creds_encrypt_samr_CryptPassword(&state
->tmp_creds
,
2577 &state
->samr_crypt_password
,
2580 if (tevent_req_nterror(req
, status
)) {
2581 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2585 memcpy(state
->netr_crypt_password
.data
,
2586 state
->samr_crypt_password
.data
, 512);
2587 state
->netr_crypt_password
.length
=
2588 IVAL(state
->samr_crypt_password
.data
, 512);
2590 subreq
= dcerpc_netr_ServerPasswordSet2_send(state
, state
->ev
,
2591 state
->binding_handle
,
2592 state
->srv_name_slash
,
2593 state
->tmp_creds
.account_name
,
2594 state
->tmp_creds
.secure_channel_type
,
2595 state
->tmp_creds
.computer_name
,
2598 &state
->netr_crypt_password
);
2599 if (tevent_req_nomem(subreq
, req
)) {
2600 status
= NT_STATUS_NO_MEMORY
;
2601 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2605 status
= netlogon_creds_encrypt_samr_Password(&state
->tmp_creds
,
2606 &state
->samr_password
,
2609 if (tevent_req_nterror(req
, status
)) {
2610 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2614 subreq
= dcerpc_netr_ServerPasswordSet_send(state
, state
->ev
,
2615 state
->binding_handle
,
2616 state
->srv_name_slash
,
2617 state
->tmp_creds
.account_name
,
2618 state
->tmp_creds
.secure_channel_type
,
2619 state
->tmp_creds
.computer_name
,
2622 &state
->samr_password
);
2623 if (tevent_req_nomem(subreq
, req
)) {
2624 status
= NT_STATUS_NO_MEMORY
;
2625 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2630 tevent_req_set_callback(subreq
,
2631 netlogon_creds_cli_ServerPasswordSet_done
,
2635 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
)
2637 struct tevent_req
*req
=
2638 tevent_req_callback_data(subreq
,
2640 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
2641 tevent_req_data(req
,
2642 struct netlogon_creds_cli_ServerPasswordSet_state
);
2646 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
2647 status
= dcerpc_netr_ServerPasswordSet2_recv(subreq
, state
,
2649 TALLOC_FREE(subreq
);
2650 if (tevent_req_nterror(req
, status
)) {
2651 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2655 status
= dcerpc_netr_ServerPasswordSet_recv(subreq
, state
,
2657 TALLOC_FREE(subreq
);
2658 if (tevent_req_nterror(req
, status
)) {
2659 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2664 status
= netlogon_creds_client_verify(&state
->tmp_creds
,
2665 &state
->rep_auth
.cred
,
2668 if (tevent_req_nterror(req
, status
)) {
2669 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2673 if (tevent_req_nterror(req
, result
)) {
2674 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, result
);
2678 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
2679 state
->old_timeout
);
2681 *state
->creds
= state
->tmp_creds
;
2682 status
= netlogon_creds_cli_store(state
->context
,
2684 TALLOC_FREE(state
->creds
);
2685 if (tevent_req_nterror(req
, status
)) {
2686 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2690 tevent_req_done(req
);
2693 NTSTATUS
netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req
*req
)
2697 if (tevent_req_is_nterror(req
, &status
)) {
2698 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2699 tevent_req_received(req
);
2703 tevent_req_received(req
);
2704 return NT_STATUS_OK
;
2707 NTSTATUS
netlogon_creds_cli_ServerPasswordSet(
2708 struct netlogon_creds_cli_context
*context
,
2709 struct dcerpc_binding_handle
*b
,
2710 const DATA_BLOB
*new_password
,
2711 const uint32_t *new_version
)
2713 TALLOC_CTX
*frame
= talloc_stackframe();
2714 struct tevent_context
*ev
;
2715 struct tevent_req
*req
;
2716 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2718 ev
= samba_tevent_context_init(frame
);
2722 req
= netlogon_creds_cli_ServerPasswordSet_send(frame
, ev
, context
, b
,
2728 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2731 status
= netlogon_creds_cli_ServerPasswordSet_recv(req
);
2737 struct netlogon_creds_cli_LogonSamLogon_state
{
2738 struct tevent_context
*ev
;
2739 struct netlogon_creds_cli_context
*context
;
2740 struct dcerpc_binding_handle
*binding_handle
;
2742 char *srv_name_slash
;
2744 enum netr_LogonInfoClass logon_level
;
2745 const union netr_LogonLevel
*const_logon
;
2746 union netr_LogonLevel
*logon
;
2749 uint16_t validation_level
;
2750 union netr_Validation
*validation
;
2751 uint8_t authoritative
;
2754 * do we need encryption at the application layer?
2758 bool try_validation6
;
2761 * the read only credentials before we started the operation
2762 * used for netr_LogonSamLogonEx() if required (validation_level = 3).
2764 struct netlogon_creds_CredentialState
*ro_creds
;
2767 * The (locked) credentials used for the credential chain
2768 * used for netr_LogonSamLogonWithFlags() or
2769 * netr_LogonSamLogonWith().
2771 struct netlogon_creds_CredentialState
*lk_creds
;
2774 * While we have locked the global credentials (lk_creds above)
2775 * we operate an a temporary copy, because a server
2776 * may not support netr_LogonSamLogonWithFlags() and
2777 * didn't process our netr_Authenticator, so we need to
2778 * restart from lk_creds.
2780 struct netlogon_creds_CredentialState tmp_creds
;
2781 struct netr_Authenticator req_auth
;
2782 struct netr_Authenticator rep_auth
;
2785 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
);
2786 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2789 struct tevent_req
*netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX
*mem_ctx
,
2790 struct tevent_context
*ev
,
2791 struct netlogon_creds_cli_context
*context
,
2792 struct dcerpc_binding_handle
*b
,
2793 enum netr_LogonInfoClass logon_level
,
2794 const union netr_LogonLevel
*logon
,
2797 struct tevent_req
*req
;
2798 struct netlogon_creds_cli_LogonSamLogon_state
*state
;
2800 req
= tevent_req_create(mem_ctx
, &state
,
2801 struct netlogon_creds_cli_LogonSamLogon_state
);
2807 state
->context
= context
;
2808 state
->binding_handle
= b
;
2810 state
->logon_level
= logon_level
;
2811 state
->const_logon
= logon
;
2812 state
->flags
= flags
;
2814 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2815 context
->server
.computer
);
2816 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2817 return tevent_req_post(req
, ev
);
2820 switch (logon_level
) {
2821 case NetlogonInteractiveInformation
:
2822 case NetlogonInteractiveTransitiveInformation
:
2823 case NetlogonServiceInformation
:
2824 case NetlogonServiceTransitiveInformation
:
2825 case NetlogonGenericInformation
:
2826 state
->user_encrypt
= true;
2829 case NetlogonNetworkInformation
:
2830 case NetlogonNetworkTransitiveInformation
:
2831 case NetlogonTicketLogonInformation
:
2835 state
->validation
= talloc_zero(state
, union netr_Validation
);
2836 if (tevent_req_nomem(state
->validation
, req
)) {
2837 return tevent_req_post(req
, ev
);
2840 netlogon_creds_cli_LogonSamLogon_start(req
);
2841 if (!tevent_req_is_in_progress(req
)) {
2842 return tevent_req_post(req
, ev
);
2846 * we defer all callbacks in order to cleanup
2847 * the database record.
2849 tevent_req_defer_callback(req
, state
->ev
);
2853 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2856 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2857 tevent_req_data(req
,
2858 struct netlogon_creds_cli_LogonSamLogon_state
);
2860 if (state
->lk_creds
== NULL
) {
2864 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2866 * This is a hack to recover from a bug in old
2867 * Samba servers, when LogonSamLogonEx() fails:
2869 * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
2871 * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2873 * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE,
2874 * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR
2875 * If the sign/seal check fails.
2877 * In that case we need to cleanup the netlogon session.
2879 * It's the job of the caller to disconnect the current
2880 * connection, if netlogon_creds_cli_LogonSamLogon()
2881 * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2883 if (!state
->context
->server
.try_logon_with
) {
2884 status
= NT_STATUS_NETWORK_ACCESS_DENIED
;
2888 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2889 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2890 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2891 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2892 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2893 TALLOC_FREE(state
->lk_creds
);
2897 netlogon_creds_cli_delete(state
->context
, state
->lk_creds
);
2898 TALLOC_FREE(state
->lk_creds
);
2901 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
);
2903 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
)
2905 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2906 tevent_req_data(req
,
2907 struct netlogon_creds_cli_LogonSamLogon_state
);
2908 struct tevent_req
*subreq
;
2910 enum dcerpc_AuthType auth_type
;
2911 enum dcerpc_AuthLevel auth_level
;
2913 TALLOC_FREE(state
->ro_creds
);
2914 TALLOC_FREE(state
->logon
);
2915 ZERO_STRUCTP(state
->validation
);
2917 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2918 &auth_type
, &auth_level
);
2920 state
->try_logon_ex
= state
->context
->server
.try_logon_ex
;
2921 state
->try_validation6
= state
->context
->server
.try_validation6
;
2923 if (auth_type
!= DCERPC_AUTH_TYPE_KRB5
&&
2924 auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
)
2926 state
->try_logon_ex
= false;
2929 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
2930 state
->try_validation6
= false;
2933 if (state
->try_logon_ex
) {
2934 if (state
->try_validation6
) {
2935 state
->validation_level
= 6;
2937 state
->validation_level
= 3;
2938 state
->user_encrypt
= true;
2941 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2943 state
->const_logon
);
2944 if (tevent_req_nomem(state
->logon
, req
)) {
2945 status
= NT_STATUS_NO_MEMORY
;
2946 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2950 if (state
->user_encrypt
) {
2951 status
= netlogon_creds_cli_get(state
->context
,
2954 if (!NT_STATUS_IS_OK(status
)) {
2955 status
= NT_STATUS_ACCESS_DENIED
;
2956 tevent_req_nterror(req
, status
);
2957 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2961 status
= netlogon_creds_encrypt_samlogon_logon(state
->ro_creds
,
2966 if (!NT_STATUS_IS_OK(status
)) {
2967 status
= NT_STATUS_ACCESS_DENIED
;
2968 tevent_req_nterror(req
, status
);
2969 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2974 subreq
= dcerpc_netr_LogonSamLogonEx_send(state
, state
->ev
,
2975 state
->binding_handle
,
2976 state
->srv_name_slash
,
2977 state
->context
->client
.computer
,
2980 state
->validation_level
,
2982 &state
->authoritative
,
2984 if (tevent_req_nomem(subreq
, req
)) {
2985 status
= NT_STATUS_NO_MEMORY
;
2986 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2989 tevent_req_set_callback(subreq
,
2990 netlogon_creds_cli_LogonSamLogon_done
,
2995 if (state
->lk_creds
== NULL
) {
2996 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2998 if (tevent_req_nomem(subreq
, req
)) {
2999 status
= NT_STATUS_NO_MEMORY
;
3000 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
3003 tevent_req_set_callback(subreq
,
3004 netlogon_creds_cli_LogonSamLogon_done
,
3009 state
->tmp_creds
= *state
->lk_creds
;
3010 status
= netlogon_creds_client_authenticator(&state
->tmp_creds
,
3012 if (tevent_req_nterror(req
, status
)) {
3013 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
3016 ZERO_STRUCT(state
->rep_auth
);
3018 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
3020 state
->const_logon
);
3021 if (tevent_req_nomem(state
->logon
, req
)) {
3022 status
= NT_STATUS_NO_MEMORY
;
3023 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
3027 status
= netlogon_creds_encrypt_samlogon_logon(&state
->tmp_creds
,
3032 if (tevent_req_nterror(req
, status
)) {
3033 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
3037 state
->validation_level
= 3;
3039 if (state
->context
->server
.try_logon_with
) {
3040 subreq
= dcerpc_netr_LogonSamLogonWithFlags_send(state
, state
->ev
,
3041 state
->binding_handle
,
3042 state
->srv_name_slash
,
3043 state
->context
->client
.computer
,
3048 state
->validation_level
,
3050 &state
->authoritative
,
3052 if (tevent_req_nomem(subreq
, req
)) {
3053 status
= NT_STATUS_NO_MEMORY
;
3054 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
3060 subreq
= dcerpc_netr_LogonSamLogon_send(state
, state
->ev
,
3061 state
->binding_handle
,
3062 state
->srv_name_slash
,
3063 state
->context
->client
.computer
,
3068 state
->validation_level
,
3070 &state
->authoritative
);
3071 if (tevent_req_nomem(subreq
, req
)) {
3072 status
= NT_STATUS_NO_MEMORY
;
3073 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
3078 tevent_req_set_callback(subreq
,
3079 netlogon_creds_cli_LogonSamLogon_done
,
3083 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
)
3085 struct tevent_req
*req
=
3086 tevent_req_callback_data(subreq
,
3088 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
3089 tevent_req_data(req
,
3090 struct netlogon_creds_cli_LogonSamLogon_state
);
3091 enum dcerpc_AuthType auth_type
;
3092 enum dcerpc_AuthLevel auth_level
;
3097 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3101 if (state
->try_logon_ex
) {
3102 status
= dcerpc_netr_LogonSamLogonEx_recv(subreq
,
3105 TALLOC_FREE(subreq
);
3106 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
3107 state
->context
->server
.try_validation6
= false;
3108 state
->context
->server
.try_logon_ex
= false;
3109 netlogon_creds_cli_LogonSamLogon_start(req
);
3112 if (tevent_req_nterror(req
, status
)) {
3113 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
3117 if ((state
->validation_level
== 6) &&
3118 (NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_INFO_CLASS
) ||
3119 NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_PARAMETER
) ||
3120 NT_STATUS_EQUAL(result
, NT_STATUS_BUFFER_TOO_SMALL
)))
3122 state
->context
->server
.try_validation6
= false;
3123 netlogon_creds_cli_LogonSamLogon_start(req
);
3127 if (tevent_req_nterror(req
, result
)) {
3128 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
3132 if (state
->ro_creds
== NULL
) {
3133 tevent_req_done(req
);
3137 ok
= netlogon_creds_cli_validate(state
->context
, state
->ro_creds
);
3140 * We got a race, lets retry with on authenticator
3143 * netlogon_creds_cli_LogonSamLogon_start()
3144 * will TALLOC_FREE(state->ro_creds);
3146 state
->try_logon_ex
= false;
3147 netlogon_creds_cli_LogonSamLogon_start(req
);
3151 status
= netlogon_creds_decrypt_samlogon_validation(state
->ro_creds
,
3152 state
->validation_level
,
3156 if (tevent_req_nterror(req
, status
)) {
3157 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
3161 tevent_req_done(req
);
3165 if (state
->lk_creds
== NULL
) {
3166 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3168 TALLOC_FREE(subreq
);
3169 if (tevent_req_nterror(req
, status
)) {
3170 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
3174 netlogon_creds_cli_LogonSamLogon_start(req
);
3178 if (state
->context
->server
.try_logon_with
) {
3179 status
= dcerpc_netr_LogonSamLogonWithFlags_recv(subreq
,
3182 TALLOC_FREE(subreq
);
3183 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
3184 state
->context
->server
.try_logon_with
= false;
3185 netlogon_creds_cli_LogonSamLogon_start(req
);
3188 if (tevent_req_nterror(req
, status
)) {
3189 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
3193 status
= dcerpc_netr_LogonSamLogon_recv(subreq
,
3196 TALLOC_FREE(subreq
);
3197 if (tevent_req_nterror(req
, status
)) {
3198 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
3203 status
= netlogon_creds_client_verify(&state
->tmp_creds
,
3204 &state
->rep_auth
.cred
,
3207 if (tevent_req_nterror(req
, status
)) {
3208 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
3212 *state
->lk_creds
= state
->tmp_creds
;
3213 status
= netlogon_creds_cli_store(state
->context
,
3215 TALLOC_FREE(state
->lk_creds
);
3217 if (tevent_req_nterror(req
, status
)) {
3218 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
3222 if (tevent_req_nterror(req
, result
)) {
3223 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
3227 status
= netlogon_creds_decrypt_samlogon_validation(&state
->tmp_creds
,
3228 state
->validation_level
,
3232 if (tevent_req_nterror(req
, status
)) {
3233 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
3237 tevent_req_done(req
);
3240 NTSTATUS
netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req
*req
,
3241 TALLOC_CTX
*mem_ctx
,
3242 uint16_t *validation_level
,
3243 union netr_Validation
**validation
,
3244 uint8_t *authoritative
,
3247 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
3248 tevent_req_data(req
,
3249 struct netlogon_creds_cli_LogonSamLogon_state
);
3252 /* authoritative is also returned on error */
3253 *authoritative
= state
->authoritative
;
3255 if (tevent_req_is_nterror(req
, &status
)) {
3256 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
3257 tevent_req_received(req
);
3261 *validation_level
= state
->validation_level
;
3262 *validation
= talloc_move(mem_ctx
, &state
->validation
);
3263 *flags
= state
->flags
;
3265 tevent_req_received(req
);
3266 return NT_STATUS_OK
;
3269 NTSTATUS
netlogon_creds_cli_LogonSamLogon(
3270 struct netlogon_creds_cli_context
*context
,
3271 struct dcerpc_binding_handle
*b
,
3272 enum netr_LogonInfoClass logon_level
,
3273 const union netr_LogonLevel
*logon
,
3274 TALLOC_CTX
*mem_ctx
,
3275 uint16_t *validation_level
,
3276 union netr_Validation
**validation
,
3277 uint8_t *authoritative
,
3280 TALLOC_CTX
*frame
= talloc_stackframe();
3281 struct tevent_context
*ev
;
3282 struct tevent_req
*req
;
3283 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3285 ev
= samba_tevent_context_init(frame
);
3289 req
= netlogon_creds_cli_LogonSamLogon_send(frame
, ev
, context
, b
,
3295 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3298 status
= netlogon_creds_cli_LogonSamLogon_recv(req
, mem_ctx
,
3308 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
{
3309 struct tevent_context
*ev
;
3310 struct netlogon_creds_cli_context
*context
;
3311 struct dcerpc_binding_handle
*binding_handle
;
3313 char *srv_name_slash
;
3314 enum dcerpc_AuthType auth_type
;
3315 enum dcerpc_AuthLevel auth_level
;
3317 const char *site_name
;
3319 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
;
3321 struct netlogon_creds_CredentialState
*creds
;
3322 struct netlogon_creds_CredentialState tmp_creds
;
3323 struct netr_Authenticator req_auth
;
3324 struct netr_Authenticator rep_auth
;
3327 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
3329 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
);
3331 struct tevent_req
*netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(TALLOC_CTX
*mem_ctx
,
3332 struct tevent_context
*ev
,
3333 struct netlogon_creds_cli_context
*context
,
3334 struct dcerpc_binding_handle
*b
,
3335 const char *site_name
,
3337 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
3339 struct tevent_req
*req
;
3340 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
;
3341 struct tevent_req
*subreq
;
3343 req
= tevent_req_create(mem_ctx
, &state
,
3344 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
3350 state
->context
= context
;
3351 state
->binding_handle
= b
;
3353 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3354 context
->server
.computer
);
3355 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3356 return tevent_req_post(req
, ev
);
3359 state
->site_name
= site_name
;
3360 state
->dns_ttl
= dns_ttl
;
3361 state
->dns_names
= dns_names
;
3363 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3365 &state
->auth_level
);
3367 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3369 if (tevent_req_nomem(subreq
, req
)) {
3370 return tevent_req_post(req
, ev
);
3373 tevent_req_set_callback(subreq
,
3374 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked
,
3380 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
3383 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
3384 tevent_req_data(req
,
3385 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
3387 if (state
->creds
== NULL
) {
3391 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3392 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3393 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3394 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3395 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3396 TALLOC_FREE(state
->creds
);
3400 netlogon_creds_cli_delete(state
->context
, state
->creds
);
3401 TALLOC_FREE(state
->creds
);
3404 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
);
3406 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
)
3408 struct tevent_req
*req
=
3409 tevent_req_callback_data(subreq
,
3411 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
3412 tevent_req_data(req
,
3413 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
3416 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3418 TALLOC_FREE(subreq
);
3419 if (tevent_req_nterror(req
, status
)) {
3423 status
= netlogon_creds_cli_check_transport(state
->auth_type
,
3426 DCERPC_AUTH_LEVEL_NONE
);
3427 if (tevent_req_nterror(req
, status
)) {
3432 * we defer all callbacks in order to cleanup
3433 * the database record.
3435 tevent_req_defer_callback(req
, state
->ev
);
3437 state
->tmp_creds
= *state
->creds
;
3438 status
= netlogon_creds_client_authenticator(&state
->tmp_creds
,
3440 if (tevent_req_nterror(req
, status
)) {
3443 ZERO_STRUCT(state
->rep_auth
);
3445 subreq
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_send(state
, state
->ev
,
3446 state
->binding_handle
,
3447 state
->srv_name_slash
,
3448 state
->tmp_creds
.computer_name
,
3454 if (tevent_req_nomem(subreq
, req
)) {
3455 status
= NT_STATUS_NO_MEMORY
;
3456 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
3460 tevent_req_set_callback(subreq
,
3461 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done
,
3465 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
)
3467 struct tevent_req
*req
=
3468 tevent_req_callback_data(subreq
,
3470 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
3471 tevent_req_data(req
,
3472 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
3477 * We use state->dns_names as the memory context, as this is
3478 * the only in/out variable and it has been overwritten by the
3479 * out parameter from the server.
3481 * We need to preserve the return value until the caller can use it.
3483 status
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_recv(subreq
, state
->dns_names
,
3485 TALLOC_FREE(subreq
);
3486 if (tevent_req_nterror(req
, status
)) {
3487 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
3491 status
= netlogon_creds_client_verify(&state
->tmp_creds
,
3492 &state
->rep_auth
.cred
,
3495 if (tevent_req_nterror(req
, status
)) {
3496 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
3500 *state
->creds
= state
->tmp_creds
;
3501 status
= netlogon_creds_cli_store(state
->context
,
3503 TALLOC_FREE(state
->creds
);
3505 if (tevent_req_nterror(req
, status
)) {
3506 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
3510 if (tevent_req_nterror(req
, result
)) {
3511 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, result
);
3515 tevent_req_done(req
);
3518 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(struct tevent_req
*req
)
3522 if (tevent_req_is_nterror(req
, &status
)) {
3523 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
3524 tevent_req_received(req
);
3528 tevent_req_received(req
);
3529 return NT_STATUS_OK
;
3532 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(
3533 struct netlogon_creds_cli_context
*context
,
3534 struct dcerpc_binding_handle
*b
,
3535 const char *site_name
,
3537 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
3539 TALLOC_CTX
*frame
= talloc_stackframe();
3540 struct tevent_context
*ev
;
3541 struct tevent_req
*req
;
3542 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3544 ev
= samba_tevent_context_init(frame
);
3548 req
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(frame
, ev
, context
, b
,
3555 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3558 status
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(req
);
3564 struct netlogon_creds_cli_ServerGetTrustInfo_state
{
3565 struct tevent_context
*ev
;
3566 struct netlogon_creds_cli_context
*context
;
3567 struct dcerpc_binding_handle
*binding_handle
;
3569 char *srv_name_slash
;
3570 enum dcerpc_AuthType auth_type
;
3571 enum dcerpc_AuthLevel auth_level
;
3573 struct samr_Password new_owf_password
;
3574 struct samr_Password old_owf_password
;
3575 struct netr_TrustInfo
*trust_info
;
3577 struct netlogon_creds_CredentialState
*creds
;
3578 struct netlogon_creds_CredentialState tmp_creds
;
3579 struct netr_Authenticator req_auth
;
3580 struct netr_Authenticator rep_auth
;
3583 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
3585 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
);
3587 struct tevent_req
*netlogon_creds_cli_ServerGetTrustInfo_send(TALLOC_CTX
*mem_ctx
,
3588 struct tevent_context
*ev
,
3589 struct netlogon_creds_cli_context
*context
,
3590 struct dcerpc_binding_handle
*b
)
3592 struct tevent_req
*req
;
3593 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
;
3594 struct tevent_req
*subreq
;
3596 req
= tevent_req_create(mem_ctx
, &state
,
3597 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3603 state
->context
= context
;
3604 state
->binding_handle
= b
;
3606 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3607 context
->server
.computer
);
3608 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3609 return tevent_req_post(req
, ev
);
3612 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3614 &state
->auth_level
);
3616 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3618 if (tevent_req_nomem(subreq
, req
)) {
3619 return tevent_req_post(req
, ev
);
3622 tevent_req_set_callback(subreq
,
3623 netlogon_creds_cli_ServerGetTrustInfo_locked
,
3629 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
3632 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3633 tevent_req_data(req
,
3634 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3636 if (state
->creds
== NULL
) {
3640 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3641 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3642 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3643 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3644 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3645 TALLOC_FREE(state
->creds
);
3649 netlogon_creds_cli_delete(state
->context
, state
->creds
);
3650 TALLOC_FREE(state
->creds
);
3653 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
);
3655 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
)
3657 struct tevent_req
*req
=
3658 tevent_req_callback_data(subreq
,
3660 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3661 tevent_req_data(req
,
3662 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3665 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3667 TALLOC_FREE(subreq
);
3668 if (tevent_req_nterror(req
, status
)) {
3672 status
= netlogon_creds_cli_check_transport(state
->auth_type
,
3675 DCERPC_AUTH_LEVEL_PRIVACY
);
3676 if (tevent_req_nterror(req
, status
)) {
3681 * we defer all callbacks in order to cleanup
3682 * the database record.
3684 tevent_req_defer_callback(req
, state
->ev
);
3686 state
->tmp_creds
= *state
->creds
;
3687 status
= netlogon_creds_client_authenticator(&state
->tmp_creds
,
3689 if (tevent_req_nterror(req
, status
)) {
3692 ZERO_STRUCT(state
->rep_auth
);
3694 subreq
= dcerpc_netr_ServerGetTrustInfo_send(state
, state
->ev
,
3695 state
->binding_handle
,
3696 state
->srv_name_slash
,
3697 state
->tmp_creds
.account_name
,
3698 state
->tmp_creds
.secure_channel_type
,
3699 state
->tmp_creds
.computer_name
,
3702 &state
->new_owf_password
,
3703 &state
->old_owf_password
,
3704 &state
->trust_info
);
3705 if (tevent_req_nomem(subreq
, req
)) {
3706 status
= NT_STATUS_NO_MEMORY
;
3707 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3711 tevent_req_set_callback(subreq
,
3712 netlogon_creds_cli_ServerGetTrustInfo_done
,
3716 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
)
3718 struct tevent_req
*req
=
3719 tevent_req_callback_data(subreq
,
3721 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3722 tevent_req_data(req
,
3723 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3728 * We use state->dns_names as the memory context, as this is
3729 * the only in/out variable and it has been overwritten by the
3730 * out parameter from the server.
3732 * We need to preserve the return value until the caller can use it.
3734 status
= dcerpc_netr_ServerGetTrustInfo_recv(subreq
, state
, &result
);
3735 TALLOC_FREE(subreq
);
3736 if (tevent_req_nterror(req
, status
)) {
3737 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3741 status
= netlogon_creds_client_verify(&state
->tmp_creds
,
3742 &state
->rep_auth
.cred
,
3745 if (tevent_req_nterror(req
, status
)) {
3746 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3750 status
= netlogon_creds_decrypt_samr_Password(&state
->tmp_creds
,
3751 &state
->new_owf_password
,
3754 if (tevent_req_nterror(req
, status
)) {
3755 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3758 status
= netlogon_creds_decrypt_samr_Password(&state
->tmp_creds
,
3759 &state
->old_owf_password
,
3762 if (tevent_req_nterror(req
, status
)) {
3763 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3767 *state
->creds
= state
->tmp_creds
;
3768 status
= netlogon_creds_cli_store(state
->context
,
3770 TALLOC_FREE(state
->creds
);
3771 if (tevent_req_nterror(req
, status
)) {
3772 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3776 if (tevent_req_nterror(req
, result
)) {
3777 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, result
);
3781 tevent_req_done(req
);
3784 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo_recv(struct tevent_req
*req
,
3785 TALLOC_CTX
*mem_ctx
,
3786 struct samr_Password
*new_owf_password
,
3787 struct samr_Password
*old_owf_password
,
3788 struct netr_TrustInfo
**trust_info
)
3790 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3791 tevent_req_data(req
,
3792 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3795 if (tevent_req_is_nterror(req
, &status
)) {
3796 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3797 tevent_req_received(req
);
3801 if (new_owf_password
!= NULL
) {
3802 *new_owf_password
= state
->new_owf_password
;
3804 if (old_owf_password
!= NULL
) {
3805 *old_owf_password
= state
->old_owf_password
;
3807 if (trust_info
!= NULL
) {
3808 *trust_info
= talloc_move(mem_ctx
, &state
->trust_info
);
3811 tevent_req_received(req
);
3812 return NT_STATUS_OK
;
3815 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo(
3816 struct netlogon_creds_cli_context
*context
,
3817 struct dcerpc_binding_handle
*b
,
3818 TALLOC_CTX
*mem_ctx
,
3819 struct samr_Password
*new_owf_password
,
3820 struct samr_Password
*old_owf_password
,
3821 struct netr_TrustInfo
**trust_info
)
3823 TALLOC_CTX
*frame
= talloc_stackframe();
3824 struct tevent_context
*ev
;
3825 struct tevent_req
*req
;
3826 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3828 ev
= samba_tevent_context_init(frame
);
3832 req
= netlogon_creds_cli_ServerGetTrustInfo_send(frame
, ev
, context
, b
);
3836 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3839 status
= netlogon_creds_cli_ServerGetTrustInfo_recv(req
,
3849 struct netlogon_creds_cli_GetForestTrustInformation_state
{
3850 struct tevent_context
*ev
;
3851 struct netlogon_creds_cli_context
*context
;
3852 struct dcerpc_binding_handle
*binding_handle
;
3854 char *srv_name_slash
;
3855 enum dcerpc_AuthType auth_type
;
3856 enum dcerpc_AuthLevel auth_level
;
3859 struct lsa_ForestTrustInformation
*forest_trust_info
;
3861 struct netlogon_creds_CredentialState
*creds
;
3862 struct netlogon_creds_CredentialState tmp_creds
;
3863 struct netr_Authenticator req_auth
;
3864 struct netr_Authenticator rep_auth
;
3867 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3869 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
);
3871 struct tevent_req
*netlogon_creds_cli_GetForestTrustInformation_send(TALLOC_CTX
*mem_ctx
,
3872 struct tevent_context
*ev
,
3873 struct netlogon_creds_cli_context
*context
,
3874 struct dcerpc_binding_handle
*b
)
3876 struct tevent_req
*req
;
3877 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
;
3878 struct tevent_req
*subreq
;
3880 req
= tevent_req_create(mem_ctx
, &state
,
3881 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3887 state
->context
= context
;
3888 state
->binding_handle
= b
;
3890 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3891 context
->server
.computer
);
3892 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3893 return tevent_req_post(req
, ev
);
3898 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3900 &state
->auth_level
);
3902 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3904 if (tevent_req_nomem(subreq
, req
)) {
3905 return tevent_req_post(req
, ev
);
3908 tevent_req_set_callback(subreq
,
3909 netlogon_creds_cli_GetForestTrustInformation_locked
,
3915 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3918 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3919 tevent_req_data(req
,
3920 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3922 if (state
->creds
== NULL
) {
3926 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3927 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3928 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3929 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3930 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3931 TALLOC_FREE(state
->creds
);
3935 netlogon_creds_cli_delete(state
->context
, state
->creds
);
3936 TALLOC_FREE(state
->creds
);
3939 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
);
3941 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
)
3943 struct tevent_req
*req
=
3944 tevent_req_callback_data(subreq
,
3946 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3947 tevent_req_data(req
,
3948 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3951 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3953 TALLOC_FREE(subreq
);
3954 if (tevent_req_nterror(req
, status
)) {
3958 status
= netlogon_creds_cli_check_transport(state
->auth_type
,
3961 DCERPC_AUTH_LEVEL_NONE
);
3962 if (tevent_req_nterror(req
, status
)) {
3967 * we defer all callbacks in order to cleanup
3968 * the database record.
3970 tevent_req_defer_callback(req
, state
->ev
);
3972 state
->tmp_creds
= *state
->creds
;
3973 status
= netlogon_creds_client_authenticator(&state
->tmp_creds
,
3975 if (tevent_req_nterror(req
, status
)) {
3978 ZERO_STRUCT(state
->rep_auth
);
3980 subreq
= dcerpc_netr_GetForestTrustInformation_send(state
, state
->ev
,
3981 state
->binding_handle
,
3982 state
->srv_name_slash
,
3983 state
->tmp_creds
.computer_name
,
3987 &state
->forest_trust_info
);
3988 if (tevent_req_nomem(subreq
, req
)) {
3989 status
= NT_STATUS_NO_MEMORY
;
3990 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3994 tevent_req_set_callback(subreq
,
3995 netlogon_creds_cli_GetForestTrustInformation_done
,
3999 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
)
4001 struct tevent_req
*req
=
4002 tevent_req_callback_data(subreq
,
4004 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
4005 tevent_req_data(req
,
4006 struct netlogon_creds_cli_GetForestTrustInformation_state
);
4011 * We use state->dns_names as the memory context, as this is
4012 * the only in/out variable and it has been overwritten by the
4013 * out parameter from the server.
4015 * We need to preserve the return value until the caller can use it.
4017 status
= dcerpc_netr_GetForestTrustInformation_recv(subreq
, state
, &result
);
4018 TALLOC_FREE(subreq
);
4019 if (tevent_req_nterror(req
, status
)) {
4020 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
4024 status
= netlogon_creds_client_verify(&state
->tmp_creds
,
4025 &state
->rep_auth
.cred
,
4028 if (tevent_req_nterror(req
, status
)) {
4029 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
4033 *state
->creds
= state
->tmp_creds
;
4034 status
= netlogon_creds_cli_store(state
->context
,
4036 TALLOC_FREE(state
->creds
);
4038 if (tevent_req_nterror(req
, status
)) {
4039 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
4043 if (tevent_req_nterror(req
, result
)) {
4044 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, result
);
4048 tevent_req_done(req
);
4051 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation_recv(struct tevent_req
*req
,
4052 TALLOC_CTX
*mem_ctx
,
4053 struct lsa_ForestTrustInformation
**forest_trust_info
)
4055 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
4056 tevent_req_data(req
,
4057 struct netlogon_creds_cli_GetForestTrustInformation_state
);
4060 if (tevent_req_is_nterror(req
, &status
)) {
4061 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
4062 tevent_req_received(req
);
4066 *forest_trust_info
= talloc_move(mem_ctx
, &state
->forest_trust_info
);
4068 tevent_req_received(req
);
4069 return NT_STATUS_OK
;
4072 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation(
4073 struct netlogon_creds_cli_context
*context
,
4074 struct dcerpc_binding_handle
*b
,
4075 TALLOC_CTX
*mem_ctx
,
4076 struct lsa_ForestTrustInformation
**forest_trust_info
)
4078 TALLOC_CTX
*frame
= talloc_stackframe();
4079 struct tevent_context
*ev
;
4080 struct tevent_req
*req
;
4081 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
4083 ev
= samba_tevent_context_init(frame
);
4087 req
= netlogon_creds_cli_GetForestTrustInformation_send(frame
, ev
, context
, b
);
4091 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4094 status
= netlogon_creds_cli_GetForestTrustInformation_recv(req
,
4101 struct netlogon_creds_cli_SendToSam_state
{
4102 struct tevent_context
*ev
;
4103 struct netlogon_creds_cli_context
*context
;
4104 struct dcerpc_binding_handle
*binding_handle
;
4106 char *srv_name_slash
;
4107 enum dcerpc_AuthType auth_type
;
4108 enum dcerpc_AuthLevel auth_level
;
4112 struct netlogon_creds_CredentialState
*creds
;
4113 struct netlogon_creds_CredentialState tmp_creds
;
4114 struct netr_Authenticator req_auth
;
4115 struct netr_Authenticator rep_auth
;
4118 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req
*req
,
4120 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req
*subreq
);
4122 struct tevent_req
*netlogon_creds_cli_SendToSam_send(TALLOC_CTX
*mem_ctx
,
4123 struct tevent_context
*ev
,
4124 struct netlogon_creds_cli_context
*context
,
4125 struct dcerpc_binding_handle
*b
,
4126 struct netr_SendToSamBase
*message
)
4128 struct tevent_req
*req
;
4129 struct netlogon_creds_cli_SendToSam_state
*state
;
4130 struct tevent_req
*subreq
;
4131 enum ndr_err_code ndr_err
;
4133 req
= tevent_req_create(mem_ctx
, &state
,
4134 struct netlogon_creds_cli_SendToSam_state
);
4140 state
->context
= context
;
4141 state
->binding_handle
= b
;
4143 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
4144 context
->server
.computer
);
4145 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
4146 return tevent_req_post(req
, ev
);
4149 ndr_err
= ndr_push_struct_blob(&state
->opaque
, mem_ctx
, message
,
4150 (ndr_push_flags_fn_t
)ndr_push_netr_SendToSamBase
);
4151 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
4152 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
4153 tevent_req_nterror(req
, status
);
4154 return tevent_req_post(req
, ev
);
4157 dcerpc_binding_handle_auth_info(state
->binding_handle
,
4159 &state
->auth_level
);
4161 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
4163 if (tevent_req_nomem(subreq
, req
)) {
4164 return tevent_req_post(req
, ev
);
4167 tevent_req_set_callback(subreq
,
4168 netlogon_creds_cli_SendToSam_locked
,
4174 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req
*req
,
4177 struct netlogon_creds_cli_SendToSam_state
*state
=
4178 tevent_req_data(req
,
4179 struct netlogon_creds_cli_SendToSam_state
);
4181 if (state
->creds
== NULL
) {
4185 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
4186 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
4187 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
4188 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
4189 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
4190 TALLOC_FREE(state
->creds
);
4194 netlogon_creds_cli_delete(state
->context
, state
->creds
);
4195 TALLOC_FREE(state
->creds
);
4198 static void netlogon_creds_cli_SendToSam_done(struct tevent_req
*subreq
);
4200 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req
*subreq
)
4202 struct tevent_req
*req
=
4203 tevent_req_callback_data(subreq
,
4205 struct netlogon_creds_cli_SendToSam_state
*state
=
4206 tevent_req_data(req
,
4207 struct netlogon_creds_cli_SendToSam_state
);
4210 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
4212 TALLOC_FREE(subreq
);
4213 if (tevent_req_nterror(req
, status
)) {
4217 status
= netlogon_creds_cli_check_transport(state
->auth_type
,
4220 DCERPC_AUTH_LEVEL_NONE
);
4221 if (tevent_req_nterror(req
, status
)) {
4226 * we defer all callbacks in order to cleanup
4227 * the database record.
4229 tevent_req_defer_callback(req
, state
->ev
);
4231 state
->tmp_creds
= *state
->creds
;
4232 status
= netlogon_creds_client_authenticator(&state
->tmp_creds
,
4234 if (tevent_req_nterror(req
, status
)) {
4237 ZERO_STRUCT(state
->rep_auth
);
4239 status
= netlogon_creds_encrypt_SendToSam(&state
->tmp_creds
,
4241 state
->opaque
.length
,
4244 if (tevent_req_nterror(req
, status
)) {
4245 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
4249 subreq
= dcerpc_netr_NetrLogonSendToSam_send(state
, state
->ev
,
4250 state
->binding_handle
,
4251 state
->srv_name_slash
,
4252 state
->tmp_creds
.computer_name
,
4256 state
->opaque
.length
);
4257 if (tevent_req_nomem(subreq
, req
)) {
4258 status
= NT_STATUS_NO_MEMORY
;
4259 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
4263 tevent_req_set_callback(subreq
,
4264 netlogon_creds_cli_SendToSam_done
,
4268 static void netlogon_creds_cli_SendToSam_done(struct tevent_req
*subreq
)
4270 struct tevent_req
*req
=
4271 tevent_req_callback_data(subreq
,
4273 struct netlogon_creds_cli_SendToSam_state
*state
=
4274 tevent_req_data(req
,
4275 struct netlogon_creds_cli_SendToSam_state
);
4279 status
= dcerpc_netr_NetrLogonSendToSam_recv(subreq
, state
, &result
);
4280 TALLOC_FREE(subreq
);
4281 if (tevent_req_nterror(req
, status
)) {
4282 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
4286 status
= netlogon_creds_client_verify(&state
->tmp_creds
,
4287 &state
->rep_auth
.cred
,
4290 if (tevent_req_nterror(req
, status
)) {
4291 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
4295 *state
->creds
= state
->tmp_creds
;
4296 status
= netlogon_creds_cli_store(state
->context
,
4298 TALLOC_FREE(state
->creds
);
4300 if (tevent_req_nterror(req
, status
)) {
4301 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
4306 * Creds must be stored before we send back application errors
4307 * e.g. NT_STATUS_NOT_IMPLEMENTED
4309 if (tevent_req_nterror(req
, result
)) {
4310 netlogon_creds_cli_SendToSam_cleanup(req
, result
);
4314 tevent_req_done(req
);
4317 NTSTATUS
netlogon_creds_cli_SendToSam_recv(struct tevent_req
*req
)
4321 if (tevent_req_is_nterror(req
, &status
)) {
4322 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
4323 tevent_req_received(req
);
4327 tevent_req_received(req
);
4328 return NT_STATUS_OK
;
4331 NTSTATUS
netlogon_creds_cli_SendToSam(struct netlogon_creds_cli_context
*context
,
4332 struct dcerpc_binding_handle
*b
,
4333 struct netr_SendToSamBase
*message
)
4335 TALLOC_CTX
*frame
= talloc_stackframe();
4336 struct tevent_context
*ev
;
4337 struct tevent_req
*req
;
4338 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
4340 ev
= samba_tevent_context_init(frame
);
4344 req
= netlogon_creds_cli_SendToSam_send(frame
, ev
, context
, b
, message
);
4348 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4351 status
= netlogon_creds_cli_SendToSam_recv(req
);
4357 struct netlogon_creds_cli_LogonGetDomainInfo_state
{
4358 struct tevent_context
*ev
;
4359 struct netlogon_creds_cli_context
*context
;
4360 struct dcerpc_binding_handle
*binding_handle
;
4362 char *srv_name_slash
;
4363 enum dcerpc_AuthType auth_type
;
4364 enum dcerpc_AuthLevel auth_level
;
4367 union netr_WorkstationInfo
*query
;
4368 union netr_DomainInfo
*info
;
4370 struct netlogon_creds_CredentialState
*creds
;
4371 struct netlogon_creds_CredentialState tmp_creds
;
4372 struct netr_Authenticator req_auth
;
4373 struct netr_Authenticator rep_auth
;
4376 static void netlogon_creds_cli_LogonGetDomainInfo_cleanup(struct tevent_req
*req
,
4378 static void netlogon_creds_cli_LogonGetDomainInfo_locked(struct tevent_req
*subreq
);
4380 struct tevent_req
*netlogon_creds_cli_LogonGetDomainInfo_send(TALLOC_CTX
*mem_ctx
,
4381 struct tevent_context
*ev
,
4382 struct netlogon_creds_cli_context
*context
,
4383 struct dcerpc_binding_handle
*b
,
4385 union netr_WorkstationInfo
*query
)
4387 struct tevent_req
*req
;
4388 struct netlogon_creds_cli_LogonGetDomainInfo_state
*state
;
4389 struct tevent_req
*subreq
;
4391 req
= tevent_req_create(mem_ctx
, &state
,
4392 struct netlogon_creds_cli_LogonGetDomainInfo_state
);
4398 state
->context
= context
;
4399 state
->binding_handle
= b
;
4401 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
4402 context
->server
.computer
);
4403 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
4404 return tevent_req_post(req
, ev
);
4407 state
->level
= level
;
4408 state
->query
= query
;
4409 state
->info
= talloc_zero(state
, union netr_DomainInfo
);
4410 if (tevent_req_nomem(state
->info
, req
)) {
4411 return tevent_req_post(req
, ev
);
4414 dcerpc_binding_handle_auth_info(state
->binding_handle
,
4416 &state
->auth_level
);
4418 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
4420 if (tevent_req_nomem(subreq
, req
)) {
4421 return tevent_req_post(req
, ev
);
4424 tevent_req_set_callback(subreq
,
4425 netlogon_creds_cli_LogonGetDomainInfo_locked
,
4431 static void netlogon_creds_cli_LogonGetDomainInfo_cleanup(struct tevent_req
*req
,
4434 struct netlogon_creds_cli_LogonGetDomainInfo_state
*state
=
4435 tevent_req_data(req
,
4436 struct netlogon_creds_cli_LogonGetDomainInfo_state
);
4438 if (state
->creds
== NULL
) {
4442 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
4443 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
4444 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
4445 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
4446 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
4447 TALLOC_FREE(state
->creds
);
4451 netlogon_creds_cli_delete(state
->context
, state
->creds
);
4454 static void netlogon_creds_cli_LogonGetDomainInfo_done(struct tevent_req
*subreq
);
4456 static void netlogon_creds_cli_LogonGetDomainInfo_locked(struct tevent_req
*subreq
)
4458 struct tevent_req
*req
=
4459 tevent_req_callback_data(subreq
,
4461 struct netlogon_creds_cli_LogonGetDomainInfo_state
*state
=
4462 tevent_req_data(req
,
4463 struct netlogon_creds_cli_LogonGetDomainInfo_state
);
4466 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
4468 TALLOC_FREE(subreq
);
4469 if (tevent_req_nterror(req
, status
)) {
4473 status
= netlogon_creds_cli_check_transport(state
->auth_type
,
4476 DCERPC_AUTH_LEVEL_NONE
);
4477 if (tevent_req_nterror(req
, status
)) {
4482 * we defer all callbacks in order to cleanup
4483 * the database record.
4485 tevent_req_defer_callback(req
, state
->ev
);
4487 state
->tmp_creds
= *state
->creds
;
4488 status
= netlogon_creds_client_authenticator(&state
->tmp_creds
,
4490 if (tevent_req_nterror(req
, status
)) {
4493 ZERO_STRUCT(state
->rep_auth
);
4495 subreq
= dcerpc_netr_LogonGetDomainInfo_send(state
, state
->ev
,
4496 state
->binding_handle
,
4497 state
->srv_name_slash
,
4498 state
->tmp_creds
.computer_name
,
4504 if (tevent_req_nomem(subreq
, req
)) {
4505 status
= NT_STATUS_NO_MEMORY
;
4506 netlogon_creds_cli_LogonGetDomainInfo_cleanup(req
, status
);
4510 tevent_req_set_callback(subreq
,
4511 netlogon_creds_cli_LogonGetDomainInfo_done
,
4515 static void netlogon_creds_cli_LogonGetDomainInfo_done(struct tevent_req
*subreq
)
4517 struct tevent_req
*req
=
4518 tevent_req_callback_data(subreq
,
4520 struct netlogon_creds_cli_LogonGetDomainInfo_state
*state
=
4521 tevent_req_data(req
,
4522 struct netlogon_creds_cli_LogonGetDomainInfo_state
);
4527 * We use state->dns_names as the memory context, as this is
4528 * the only in/out variable and it has been overwritten by the
4529 * out parameter from the server.
4531 * We need to preserve the return value until the caller can use it.
4533 status
= dcerpc_netr_LogonGetDomainInfo_recv(subreq
, state
->info
, &result
);
4534 TALLOC_FREE(subreq
);
4535 if (tevent_req_nterror(req
, status
)) {
4536 netlogon_creds_cli_LogonGetDomainInfo_cleanup(req
, status
);
4540 status
= netlogon_creds_client_verify(&state
->tmp_creds
,
4541 &state
->rep_auth
.cred
,
4544 if (tevent_req_nterror(req
, status
)) {
4545 netlogon_creds_cli_LogonGetDomainInfo_cleanup(req
, status
);
4549 if (tevent_req_nterror(req
, result
)) {
4550 netlogon_creds_cli_LogonGetDomainInfo_cleanup(req
, result
);
4554 *state
->creds
= state
->tmp_creds
;
4555 status
= netlogon_creds_cli_store(state
->context
,
4557 if (tevent_req_nterror(req
, status
)) {
4558 netlogon_creds_cli_LogonGetDomainInfo_cleanup(req
, status
);
4562 tevent_req_done(req
);
4565 NTSTATUS
netlogon_creds_cli_LogonGetDomainInfo_recv(struct tevent_req
*req
,
4566 TALLOC_CTX
*mem_ctx
,
4567 union netr_DomainInfo
**info
)
4569 struct netlogon_creds_cli_LogonGetDomainInfo_state
*state
=
4570 tevent_req_data(req
,
4571 struct netlogon_creds_cli_LogonGetDomainInfo_state
);
4574 if (tevent_req_is_nterror(req
, &status
)) {
4575 netlogon_creds_cli_LogonGetDomainInfo_cleanup(req
, status
);
4576 tevent_req_received(req
);
4580 *info
= talloc_move(mem_ctx
, &state
->info
);
4582 tevent_req_received(req
);
4583 return NT_STATUS_OK
;
4586 NTSTATUS
netlogon_creds_cli_LogonGetDomainInfo(
4587 struct netlogon_creds_cli_context
*context
,
4588 struct dcerpc_binding_handle
*b
,
4589 TALLOC_CTX
*mem_ctx
,
4591 union netr_WorkstationInfo
*query
,
4592 union netr_DomainInfo
**info
)
4594 TALLOC_CTX
*frame
= talloc_stackframe();
4595 struct tevent_context
*ev
;
4596 struct tevent_req
*req
;
4597 NTSTATUS status
= NT_STATUS_OK
;
4599 ev
= samba_tevent_context_init(frame
);
4603 req
= netlogon_creds_cli_LogonGetDomainInfo_send(frame
, ev
, context
, b
,
4608 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4611 status
= netlogon_creds_cli_LogonGetDomainInfo_recv(req
,