2 Unix SMB/CIFS implementation.
4 module to store/fetch session keys for the schannel client
6 Copyright (C) Stefan Metzmacher 2013
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "system/filesys.h"
25 #include "lib/util/tevent_ntstatus.h"
26 #include "lib/dbwrap/dbwrap.h"
27 #include "lib/dbwrap/dbwrap_rbt.h"
28 #include "lib/util/util_tdb.h"
29 #include "libcli/security/security.h"
30 #include "../lib/param/param.h"
31 #include "../libcli/auth/schannel.h"
32 #include "../librpc/gen_ndr/ndr_schannel.h"
33 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
34 #include "../librpc/gen_ndr/server_id.h"
35 #include "netlogon_creds_cli.h"
36 #include "source3/include/messages.h"
37 #include "source3/include/g_lock.h"
38 #include "libds/common/roles.h"
40 struct netlogon_creds_cli_locked_state;
42 struct netlogon_creds_cli_context {
46 uint32_t proposed_flags;
47 uint32_t required_flags;
48 enum netr_SchannelType type;
49 enum dcerpc_AuthLevel auth_level;
54 const char *netbios_domain;
55 uint32_t cached_flags;
64 struct db_context *ctx;
65 struct g_lock_ctx *g_ctx;
66 struct netlogon_creds_cli_locked_state *locked_state;
70 struct netlogon_creds_cli_locked_state {
71 struct netlogon_creds_cli_context *context;
73 struct netlogon_creds_CredentialState *creds;
76 static int netlogon_creds_cli_locked_state_destructor(
77 struct netlogon_creds_cli_locked_state *state)
79 struct netlogon_creds_cli_context *context = state->context;
81 if (context == NULL) {
85 if (context->db.locked_state == state) {
86 context->db.locked_state = NULL;
89 if (state->is_glocked) {
90 g_lock_unlock(context->db.g_ctx,
91 context->db.key_name);
97 static NTSTATUS netlogon_creds_cli_context_common(
98 const char *client_computer,
99 const char *client_account,
100 enum netr_SchannelType type,
101 enum dcerpc_AuthLevel auth_level,
102 uint32_t proposed_flags,
103 uint32_t required_flags,
104 const char *server_computer,
105 const char *server_netbios_domain,
107 struct netlogon_creds_cli_context **_context)
109 struct netlogon_creds_cli_context *context = NULL;
110 TALLOC_CTX *frame = talloc_stackframe();
111 char *_key_name = NULL;
112 char *server_netbios_name = NULL;
117 context = talloc_zero(mem_ctx, struct netlogon_creds_cli_context);
118 if (context == NULL) {
120 return NT_STATUS_NO_MEMORY;
123 context->client.computer = talloc_strdup(context, client_computer);
124 if (context->client.computer == NULL) {
125 TALLOC_FREE(context);
127 return NT_STATUS_NO_MEMORY;
130 context->client.account = talloc_strdup(context, client_account);
131 if (context->client.account == NULL) {
132 TALLOC_FREE(context);
134 return NT_STATUS_NO_MEMORY;
137 context->client.proposed_flags = proposed_flags;
138 context->client.required_flags = required_flags;
139 context->client.type = type;
140 context->client.auth_level = auth_level;
142 context->server.computer = talloc_strdup(context, server_computer);
143 if (context->server.computer == NULL) {
144 TALLOC_FREE(context);
146 return NT_STATUS_NO_MEMORY;
149 context->server.netbios_domain = talloc_strdup(context, server_netbios_domain);
150 if (context->server.netbios_domain == NULL) {
151 TALLOC_FREE(context);
153 return NT_STATUS_NO_MEMORY;
158 * Force the callers to provide a unique
159 * value for server_computer and use this directly.
161 * For now we have to deal with
162 * "HOSTNAME" vs. "hostname.example.com".
164 server_netbios_name = talloc_strdup(frame, server_computer);
165 if (server_netbios_name == NULL) {
166 TALLOC_FREE(context);
168 return NT_STATUS_NO_MEMORY;
171 p = strchr(server_netbios_name, '.');
176 _key_name = talloc_asprintf(frame, "CLI[%s/%s]/SRV[%s/%s]",
180 server_netbios_domain);
181 if (_key_name == NULL) {
182 TALLOC_FREE(context);
184 return NT_STATUS_NO_MEMORY;
187 context->db.key_name = talloc_strdup_upper(context, _key_name);
188 if (context->db.key_name == NULL) {
189 TALLOC_FREE(context);
191 return NT_STATUS_NO_MEMORY;
194 context->db.key_data = string_term_tdb_data(context->db.key_name);
201 static struct db_context *netlogon_creds_cli_global_db;
203 NTSTATUS netlogon_creds_cli_set_global_db(struct db_context **db)
205 if (netlogon_creds_cli_global_db != NULL) {
206 return NT_STATUS_INVALID_PARAMETER_MIX;
209 netlogon_creds_cli_global_db = talloc_move(talloc_autofree_context(), db);
213 NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx)
216 struct db_context *global_db;
218 if (netlogon_creds_cli_global_db != NULL) {
222 fname = lpcfg_private_db_path(talloc_autofree_context(), lp_ctx, "netlogon_creds_cli");
224 return NT_STATUS_NO_MEMORY;
227 global_db = dbwrap_local_open(talloc_autofree_context(), lp_ctx,
229 TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
231 0600, DBWRAP_LOCK_ORDER_2,
233 if (global_db == NULL) {
234 DEBUG(0,("netlogon_creds_cli_open_global_db: Failed to open %s - %s\n",
235 fname, strerror(errno)));
237 return NT_STATUS_NO_MEMORY;
241 netlogon_creds_cli_global_db = global_db;
245 NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx,
246 struct messaging_context *msg_ctx,
247 const char *client_account,
248 enum netr_SchannelType type,
249 const char *server_computer,
250 const char *server_netbios_domain,
252 struct netlogon_creds_cli_context **_context)
254 TALLOC_CTX *frame = talloc_stackframe();
256 struct netlogon_creds_cli_context *context = NULL;
257 const char *client_computer;
258 uint32_t proposed_flags;
259 uint32_t required_flags = 0;
260 bool reject_md5_servers = false;
261 bool require_strong_key = false;
262 int require_sign_or_seal = true;
263 bool seal_secure_channel = true;
264 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
265 bool neutralize_nt4_emulation = false;
269 client_computer = lpcfg_netbios_name(lp_ctx);
270 if (strlen(client_computer) > 15) {
271 return NT_STATUS_INVALID_PARAMETER_MIX;
275 * allow overwrite per domain
276 * reject md5 servers:<netbios_domain>
278 reject_md5_servers = lpcfg_reject_md5_servers(lp_ctx);
279 reject_md5_servers = lpcfg_parm_bool(lp_ctx, NULL,
280 "reject md5 servers",
281 server_netbios_domain,
285 * allow overwrite per domain
286 * require strong key:<netbios_domain>
288 require_strong_key = lpcfg_require_strong_key(lp_ctx);
289 require_strong_key = lpcfg_parm_bool(lp_ctx, NULL,
290 "require strong key",
291 server_netbios_domain,
295 * allow overwrite per domain
296 * client schannel:<netbios_domain>
298 require_sign_or_seal = lpcfg_client_schannel(lp_ctx);
299 require_sign_or_seal = lpcfg_parm_int(lp_ctx, NULL,
301 server_netbios_domain,
302 require_sign_or_seal);
305 * allow overwrite per domain
306 * winbind sealed pipes:<netbios_domain>
308 seal_secure_channel = lpcfg_winbind_sealed_pipes(lp_ctx);
309 seal_secure_channel = lpcfg_parm_bool(lp_ctx, NULL,
310 "winbind sealed pipes",
311 server_netbios_domain,
312 seal_secure_channel);
315 * allow overwrite per domain
316 * neutralize nt4 emulation:<netbios_domain>
318 neutralize_nt4_emulation = lpcfg_neutralize_nt4_emulation(lp_ctx);
319 neutralize_nt4_emulation = lpcfg_parm_bool(lp_ctx, NULL,
320 "neutralize nt4 emulation",
321 server_netbios_domain,
322 neutralize_nt4_emulation);
324 proposed_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
325 proposed_flags |= NETLOGON_NEG_SUPPORTS_AES;
329 if (lpcfg_security(lp_ctx) == SEC_ADS) {
331 * AD domains should be secure
333 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
334 require_sign_or_seal = true;
335 require_strong_key = true;
339 case SEC_CHAN_DOMAIN:
342 case SEC_CHAN_DNS_DOMAIN:
344 * AD domains should be secure
346 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
347 require_sign_or_seal = true;
348 require_strong_key = true;
349 neutralize_nt4_emulation = true;
353 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
354 require_sign_or_seal = true;
355 require_strong_key = true;
359 required_flags |= NETLOGON_NEG_RODC_PASSTHROUGH;
360 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
361 require_sign_or_seal = true;
362 require_strong_key = true;
363 neutralize_nt4_emulation = true;
368 return NT_STATUS_INVALID_PARAMETER;
371 if (neutralize_nt4_emulation) {
372 proposed_flags |= NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION;
375 if (require_sign_or_seal == false) {
376 proposed_flags &= ~NETLOGON_NEG_AUTHENTICATED_RPC;
378 required_flags |= NETLOGON_NEG_ARCFOUR;
379 required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC;
382 if (reject_md5_servers) {
383 required_flags |= NETLOGON_NEG_ARCFOUR;
384 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
385 required_flags |= NETLOGON_NEG_SUPPORTS_AES;
386 required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC;
389 if (require_strong_key) {
390 required_flags |= NETLOGON_NEG_ARCFOUR;
391 required_flags |= NETLOGON_NEG_STRONG_KEYS;
392 required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC;
395 proposed_flags |= required_flags;
397 if (seal_secure_channel) {
398 auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
400 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
403 status = netlogon_creds_cli_context_common(client_computer,
410 server_netbios_domain,
413 if (!NT_STATUS_IS_OK(status)) {
418 if (msg_ctx != NULL) {
419 context->db.g_ctx = g_lock_ctx_init(context, msg_ctx);
420 if (context->db.g_ctx == NULL) {
421 TALLOC_FREE(context);
423 return NT_STATUS_NO_MEMORY;
427 if (netlogon_creds_cli_global_db != NULL) {
428 context->db.ctx = netlogon_creds_cli_global_db;
434 status = netlogon_creds_cli_open_global_db(lp_ctx);
435 if (!NT_STATUS_IS_OK(status)) {
436 TALLOC_FREE(context);
438 return NT_STATUS_NO_MEMORY;
441 context->db.ctx = netlogon_creds_cli_global_db;
447 NTSTATUS netlogon_creds_cli_context_tmp(const char *client_computer,
448 const char *client_account,
449 enum netr_SchannelType type,
450 uint32_t proposed_flags,
451 uint32_t required_flags,
452 enum dcerpc_AuthLevel auth_level,
453 const char *server_computer,
454 const char *server_netbios_domain,
456 struct netlogon_creds_cli_context **_context)
459 struct netlogon_creds_cli_context *context = NULL;
463 status = netlogon_creds_cli_context_common(client_computer,
470 server_netbios_domain,
473 if (!NT_STATUS_IS_OK(status)) {
477 context->db.ctx = db_open_rbt(context);
478 if (context->db.ctx == NULL) {
479 talloc_free(context);
480 return NT_STATUS_NO_MEMORY;
487 enum dcerpc_AuthLevel netlogon_creds_cli_auth_level(
488 struct netlogon_creds_cli_context *context)
490 return context->client.auth_level;
493 struct netlogon_creds_cli_fetch_state {
495 struct netlogon_creds_CredentialState *creds;
496 uint32_t required_flags;
500 static void netlogon_creds_cli_fetch_parser(TDB_DATA key, TDB_DATA data,
503 struct netlogon_creds_cli_fetch_state *state =
504 (struct netlogon_creds_cli_fetch_state *)private_data;
505 enum ndr_err_code ndr_err;
509 state->creds = talloc_zero(state->mem_ctx,
510 struct netlogon_creds_CredentialState);
511 if (state->creds == NULL) {
512 state->status = NT_STATUS_NO_MEMORY;
516 blob.data = data.dptr;
517 blob.length = data.dsize;
519 ndr_err = ndr_pull_struct_blob(&blob, state->creds, state->creds,
520 (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState);
521 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
522 TALLOC_FREE(state->creds);
523 state->status = ndr_map_error2ntstatus(ndr_err);
527 tmp_flags = state->creds->negotiate_flags;
528 tmp_flags &= state->required_flags;
529 if (tmp_flags != state->required_flags) {
530 TALLOC_FREE(state->creds);
531 state->status = NT_STATUS_DOWNGRADE_DETECTED;
535 state->status = NT_STATUS_OK;
538 NTSTATUS netlogon_creds_cli_get(struct netlogon_creds_cli_context *context,
540 struct netlogon_creds_CredentialState **_creds)
543 struct netlogon_creds_cli_fetch_state fstate = {
545 .status = NT_STATUS_INTERNAL_ERROR,
546 .required_flags = context->client.required_flags,
548 static const struct netr_Credential zero_creds;
552 status = dbwrap_parse_record(context->db.ctx,
553 context->db.key_data,
554 netlogon_creds_cli_fetch_parser,
556 if (!NT_STATUS_IS_OK(status)) {
559 status = fstate.status;
560 if (!NT_STATUS_IS_OK(status)) {
565 * mark it as invalid for step operations.
567 fstate.creds->sequence = 0;
568 fstate.creds->seed = zero_creds;
569 fstate.creds->client = zero_creds;
570 fstate.creds->server = zero_creds;
572 if (context->server.cached_flags == fstate.creds->negotiate_flags) {
573 *_creds = fstate.creds;
578 * It is really important to try SamLogonEx here,
579 * because multiple processes can talk to the same
580 * domain controller, without using the credential
583 * With a normal SamLogon call, we must keep the
584 * credentials chain updated and intact between all
585 * users of the machine account (which would imply
586 * cross-node communication for every NTLM logon).
588 * The credentials chain is not per NETLOGON pipe
589 * connection, but globally on the server/client pair
590 * by computer name, while the client is free to use
591 * any computer name. We include the cluster node number
592 * in our computer name in order to avoid cross node
593 * coordination of the credential chain.
595 * It's also important to use NetlogonValidationSamInfo4 (6),
596 * because it relies on the rpc transport encryption
597 * and avoids using the global netlogon schannel
598 * session key to en/decrypt secret information
599 * like the user_session_key for network logons.
601 * [MS-APDS] 3.1.5.2 NTLM Network Logon
602 * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and
603 * NETLOGON_NEG_AUTHENTICATED_RPC set together
604 * are the indication that the server supports
605 * NetlogonValidationSamInfo4 (6). And it must only
606 * be used if "SealSecureChannel" is used.
608 * The "SealSecureChannel" AUTH_TYPE_SCHANNEL/AUTH_LEVEL_PRIVACY
609 * check is done in netlogon_creds_cli_LogonSamLogon*().
611 context->server.cached_flags = fstate.creds->negotiate_flags;
612 context->server.try_validation6 = true;
613 context->server.try_logon_ex = true;
614 context->server.try_logon_with = true;
616 if (!(context->server.cached_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
617 context->server.try_validation6 = false;
618 context->server.try_logon_ex = false;
620 if (!(context->server.cached_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) {
621 context->server.try_validation6 = false;
624 *_creds = fstate.creds;
628 bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context *context,
629 const struct netlogon_creds_CredentialState *creds1)
631 TALLOC_CTX *frame = talloc_stackframe();
632 struct netlogon_creds_CredentialState *creds2;
636 enum ndr_err_code ndr_err;
639 status = netlogon_creds_cli_get(context, frame, &creds2);
640 if (!NT_STATUS_IS_OK(status)) {
645 ndr_err = ndr_push_struct_blob(&blob1, frame, creds1,
646 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
647 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
652 ndr_err = ndr_push_struct_blob(&blob2, frame, creds2,
653 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
654 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
659 if (blob1.length != blob2.length) {
664 cmp = memcmp(blob1.data, blob2.data, blob1.length);
674 NTSTATUS netlogon_creds_cli_store(struct netlogon_creds_cli_context *context,
675 struct netlogon_creds_CredentialState **_creds)
677 struct netlogon_creds_CredentialState *creds = *_creds;
679 enum ndr_err_code ndr_err;
685 if (context->db.locked_state == NULL) {
687 * this was not the result of netlogon_creds_cli_lock*()
690 return NT_STATUS_INVALID_PAGE_PROTECTION;
693 if (context->db.locked_state->creds != creds) {
695 * this was not the result of netlogon_creds_cli_lock*()
698 return NT_STATUS_INVALID_PAGE_PROTECTION;
701 ndr_err = ndr_push_struct_blob(&blob, creds, creds,
702 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
703 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
705 status = ndr_map_error2ntstatus(ndr_err);
709 data.dptr = blob.data;
710 data.dsize = blob.length;
712 status = dbwrap_store(context->db.ctx,
713 context->db.key_data,
716 if (!NT_STATUS_IS_OK(status)) {
723 NTSTATUS netlogon_creds_cli_delete(struct netlogon_creds_cli_context *context,
724 struct netlogon_creds_CredentialState **_creds)
726 struct netlogon_creds_CredentialState *creds = *_creds;
731 if (context->db.locked_state == NULL) {
733 * this was not the result of netlogon_creds_cli_lock*()
736 return NT_STATUS_INVALID_PAGE_PROTECTION;
739 if (context->db.locked_state->creds != creds) {
741 * this was not the result of netlogon_creds_cli_lock*()
744 return NT_STATUS_INVALID_PAGE_PROTECTION;
747 status = dbwrap_delete(context->db.ctx,
748 context->db.key_data);
750 if (!NT_STATUS_IS_OK(status)) {
757 struct netlogon_creds_cli_lock_state {
758 struct netlogon_creds_cli_locked_state *locked_state;
759 struct netlogon_creds_CredentialState *creds;
762 static void netlogon_creds_cli_lock_done(struct tevent_req *subreq);
763 static void netlogon_creds_cli_lock_fetch(struct tevent_req *req);
765 struct tevent_req *netlogon_creds_cli_lock_send(TALLOC_CTX *mem_ctx,
766 struct tevent_context *ev,
767 struct netlogon_creds_cli_context *context)
769 struct tevent_req *req;
770 struct netlogon_creds_cli_lock_state *state;
771 struct netlogon_creds_cli_locked_state *locked_state;
772 struct tevent_req *subreq;
774 req = tevent_req_create(mem_ctx, &state,
775 struct netlogon_creds_cli_lock_state);
780 if (context->db.locked_state != NULL) {
781 tevent_req_nterror(req, NT_STATUS_LOCK_NOT_GRANTED);
782 return tevent_req_post(req, ev);
785 locked_state = talloc_zero(state, struct netlogon_creds_cli_locked_state);
786 if (tevent_req_nomem(locked_state, req)) {
787 return tevent_req_post(req, ev);
789 talloc_set_destructor(locked_state,
790 netlogon_creds_cli_locked_state_destructor);
791 locked_state->context = context;
793 context->db.locked_state = locked_state;
794 state->locked_state = locked_state;
796 if (context->db.g_ctx == NULL) {
797 netlogon_creds_cli_lock_fetch(req);
798 if (!tevent_req_is_in_progress(req)) {
799 return tevent_req_post(req, ev);
805 subreq = g_lock_lock_send(state, ev,
807 context->db.key_name,
809 if (tevent_req_nomem(subreq, req)) {
810 return tevent_req_post(req, ev);
812 tevent_req_set_callback(subreq, netlogon_creds_cli_lock_done, req);
817 static void netlogon_creds_cli_lock_done(struct tevent_req *subreq)
819 struct tevent_req *req =
820 tevent_req_callback_data(subreq,
822 struct netlogon_creds_cli_lock_state *state =
824 struct netlogon_creds_cli_lock_state);
827 status = g_lock_lock_recv(subreq);
829 if (tevent_req_nterror(req, status)) {
832 state->locked_state->is_glocked = true;
834 netlogon_creds_cli_lock_fetch(req);
837 static void netlogon_creds_cli_lock_fetch(struct tevent_req *req)
839 struct netlogon_creds_cli_lock_state *state =
841 struct netlogon_creds_cli_lock_state);
842 struct netlogon_creds_cli_context *context = state->locked_state->context;
843 struct netlogon_creds_cli_fetch_state fstate = {
844 .status = NT_STATUS_INTERNAL_ERROR,
845 .required_flags = context->client.required_flags,
849 fstate.mem_ctx = state;
850 status = dbwrap_parse_record(context->db.ctx,
851 context->db.key_data,
852 netlogon_creds_cli_fetch_parser,
854 if (tevent_req_nterror(req, status)) {
857 status = fstate.status;
858 if (tevent_req_nterror(req, status)) {
862 if (context->server.cached_flags == fstate.creds->negotiate_flags) {
863 state->creds = fstate.creds;
864 tevent_req_done(req);
868 context->server.cached_flags = fstate.creds->negotiate_flags;
869 context->server.try_validation6 = true;
870 context->server.try_logon_ex = true;
871 context->server.try_logon_with = true;
873 if (!(context->server.cached_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
874 context->server.try_validation6 = false;
875 context->server.try_logon_ex = false;
877 if (!(context->server.cached_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) {
878 context->server.try_validation6 = false;
881 state->creds = fstate.creds;
882 tevent_req_done(req);
886 NTSTATUS netlogon_creds_cli_lock_recv(struct tevent_req *req,
888 struct netlogon_creds_CredentialState **creds)
890 struct netlogon_creds_cli_lock_state *state =
892 struct netlogon_creds_cli_lock_state);
895 if (tevent_req_is_nterror(req, &status)) {
896 tevent_req_received(req);
900 talloc_steal(state->creds, state->locked_state);
901 state->locked_state->creds = state->creds;
902 *creds = talloc_move(mem_ctx, &state->creds);
903 tevent_req_received(req);
907 NTSTATUS netlogon_creds_cli_lock(struct netlogon_creds_cli_context *context,
909 struct netlogon_creds_CredentialState **creds)
911 TALLOC_CTX *frame = talloc_stackframe();
912 struct tevent_context *ev;
913 struct tevent_req *req;
914 NTSTATUS status = NT_STATUS_NO_MEMORY;
916 ev = samba_tevent_context_init(frame);
920 req = netlogon_creds_cli_lock_send(frame, ev, context);
924 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
927 status = netlogon_creds_cli_lock_recv(req, mem_ctx, creds);
933 struct netlogon_creds_cli_auth_state {
934 struct tevent_context *ev;
935 struct netlogon_creds_cli_context *context;
936 struct dcerpc_binding_handle *binding_handle;
937 struct samr_Password current_nt_hash;
938 struct samr_Password previous_nt_hash;
939 struct samr_Password used_nt_hash;
940 char *srv_name_slash;
941 uint32_t current_flags;
942 struct netr_Credential client_challenge;
943 struct netr_Credential server_challenge;
944 struct netlogon_creds_CredentialState *creds;
945 struct netr_Credential client_credential;
946 struct netr_Credential server_credential;
951 bool try_previous_nt_hash;
952 struct netlogon_creds_cli_locked_state *locked_state;
955 static void netlogon_creds_cli_auth_locked(struct tevent_req *subreq);
956 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req *req);
958 struct tevent_req *netlogon_creds_cli_auth_send(TALLOC_CTX *mem_ctx,
959 struct tevent_context *ev,
960 struct netlogon_creds_cli_context *context,
961 struct dcerpc_binding_handle *b,
962 struct samr_Password current_nt_hash,
963 const struct samr_Password *previous_nt_hash)
965 struct tevent_req *req;
966 struct netlogon_creds_cli_auth_state *state;
967 struct netlogon_creds_cli_locked_state *locked_state;
970 req = tevent_req_create(mem_ctx, &state,
971 struct netlogon_creds_cli_auth_state);
977 state->context = context;
978 state->binding_handle = b;
979 state->current_nt_hash = current_nt_hash;
980 if (previous_nt_hash != NULL) {
981 state->previous_nt_hash = *previous_nt_hash;
982 state->try_previous_nt_hash = true;
985 if (context->db.locked_state != NULL) {
986 tevent_req_nterror(req, NT_STATUS_LOCK_NOT_GRANTED);
987 return tevent_req_post(req, ev);
990 locked_state = talloc_zero(state, struct netlogon_creds_cli_locked_state);
991 if (tevent_req_nomem(locked_state, req)) {
992 return tevent_req_post(req, ev);
994 talloc_set_destructor(locked_state,
995 netlogon_creds_cli_locked_state_destructor);
996 locked_state->context = context;
998 context->db.locked_state = locked_state;
999 state->locked_state = locked_state;
1001 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
1002 context->server.computer);
1003 if (tevent_req_nomem(state->srv_name_slash, req)) {
1004 return tevent_req_post(req, ev);
1007 state->try_auth3 = true;
1008 state->try_auth2 = true;
1010 if (context->client.required_flags != 0) {
1011 state->require_auth2 = true;
1014 state->used_nt_hash = state->current_nt_hash;
1015 state->current_flags = context->client.proposed_flags;
1017 if (context->db.g_ctx != NULL) {
1018 struct tevent_req *subreq;
1020 subreq = g_lock_lock_send(state, ev,
1022 context->db.key_name,
1024 if (tevent_req_nomem(subreq, req)) {
1025 return tevent_req_post(req, ev);
1027 tevent_req_set_callback(subreq,
1028 netlogon_creds_cli_auth_locked,
1034 status = dbwrap_delete(state->context->db.ctx,
1035 state->context->db.key_data);
1036 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
1037 status = NT_STATUS_OK;
1039 if (tevent_req_nterror(req, status)) {
1040 return tevent_req_post(req, ev);
1043 netlogon_creds_cli_auth_challenge_start(req);
1044 if (!tevent_req_is_in_progress(req)) {
1045 return tevent_req_post(req, ev);
1051 static void netlogon_creds_cli_auth_locked(struct tevent_req *subreq)
1053 struct tevent_req *req =
1054 tevent_req_callback_data(subreq,
1056 struct netlogon_creds_cli_auth_state *state =
1057 tevent_req_data(req,
1058 struct netlogon_creds_cli_auth_state);
1061 status = g_lock_lock_recv(subreq);
1062 TALLOC_FREE(subreq);
1063 if (tevent_req_nterror(req, status)) {
1066 state->locked_state->is_glocked = true;
1068 status = dbwrap_delete(state->context->db.ctx,
1069 state->context->db.key_data);
1070 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
1071 status = NT_STATUS_OK;
1073 if (tevent_req_nterror(req, status)) {
1077 netlogon_creds_cli_auth_challenge_start(req);
1080 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq);
1082 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req *req)
1084 struct netlogon_creds_cli_auth_state *state =
1085 tevent_req_data(req,
1086 struct netlogon_creds_cli_auth_state);
1087 struct tevent_req *subreq;
1089 TALLOC_FREE(state->creds);
1091 generate_random_buffer(state->client_challenge.data,
1092 sizeof(state->client_challenge.data));
1094 subreq = dcerpc_netr_ServerReqChallenge_send(state, state->ev,
1095 state->binding_handle,
1096 state->srv_name_slash,
1097 state->context->client.computer,
1098 &state->client_challenge,
1099 &state->server_challenge);
1100 if (tevent_req_nomem(subreq, req)) {
1103 tevent_req_set_callback(subreq,
1104 netlogon_creds_cli_auth_challenge_done,
1108 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq);
1110 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq)
1112 struct tevent_req *req =
1113 tevent_req_callback_data(subreq,
1115 struct netlogon_creds_cli_auth_state *state =
1116 tevent_req_data(req,
1117 struct netlogon_creds_cli_auth_state);
1121 status = dcerpc_netr_ServerReqChallenge_recv(subreq, state, &result);
1122 TALLOC_FREE(subreq);
1123 if (tevent_req_nterror(req, status)) {
1126 if (tevent_req_nterror(req, result)) {
1130 if (!state->try_auth3 && !state->try_auth2) {
1131 state->current_flags = 0;
1134 /* Calculate the session key and client credentials */
1136 state->creds = netlogon_creds_client_init(state,
1137 state->context->client.account,
1138 state->context->client.computer,
1139 state->context->client.type,
1140 &state->client_challenge,
1141 &state->server_challenge,
1142 &state->used_nt_hash,
1143 &state->client_credential,
1144 state->current_flags);
1145 if (tevent_req_nomem(state->creds, req)) {
1149 if (state->try_auth3) {
1150 subreq = dcerpc_netr_ServerAuthenticate3_send(state, state->ev,
1151 state->binding_handle,
1152 state->srv_name_slash,
1153 state->context->client.account,
1154 state->context->client.type,
1155 state->context->client.computer,
1156 &state->client_credential,
1157 &state->server_credential,
1158 &state->creds->negotiate_flags,
1160 if (tevent_req_nomem(subreq, req)) {
1163 } else if (state->try_auth2) {
1166 subreq = dcerpc_netr_ServerAuthenticate2_send(state, state->ev,
1167 state->binding_handle,
1168 state->srv_name_slash,
1169 state->context->client.account,
1170 state->context->client.type,
1171 state->context->client.computer,
1172 &state->client_credential,
1173 &state->server_credential,
1174 &state->creds->negotiate_flags);
1175 if (tevent_req_nomem(subreq, req)) {
1181 subreq = dcerpc_netr_ServerAuthenticate_send(state, state->ev,
1182 state->binding_handle,
1183 state->srv_name_slash,
1184 state->context->client.account,
1185 state->context->client.type,
1186 state->context->client.computer,
1187 &state->client_credential,
1188 &state->server_credential);
1189 if (tevent_req_nomem(subreq, req)) {
1193 tevent_req_set_callback(subreq,
1194 netlogon_creds_cli_auth_srvauth_done,
1198 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq)
1200 struct tevent_req *req =
1201 tevent_req_callback_data(subreq,
1203 struct netlogon_creds_cli_auth_state *state =
1204 tevent_req_data(req,
1205 struct netlogon_creds_cli_auth_state);
1209 enum ndr_err_code ndr_err;
1214 if (state->try_auth3) {
1215 status = dcerpc_netr_ServerAuthenticate3_recv(subreq, state,
1217 TALLOC_FREE(subreq);
1218 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1219 state->try_auth3 = false;
1220 netlogon_creds_cli_auth_challenge_start(req);
1223 if (tevent_req_nterror(req, status)) {
1226 } else if (state->try_auth2) {
1227 status = dcerpc_netr_ServerAuthenticate2_recv(subreq, state,
1229 TALLOC_FREE(subreq);
1230 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1231 state->try_auth2 = false;
1232 if (state->require_auth2) {
1233 status = NT_STATUS_DOWNGRADE_DETECTED;
1234 tevent_req_nterror(req, status);
1237 netlogon_creds_cli_auth_challenge_start(req);
1240 if (tevent_req_nterror(req, status)) {
1244 status = dcerpc_netr_ServerAuthenticate_recv(subreq, state,
1246 TALLOC_FREE(subreq);
1247 if (tevent_req_nterror(req, status)) {
1252 if (!NT_STATUS_IS_OK(result) &&
1253 !NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED))
1255 tevent_req_nterror(req, result);
1259 tmp_flags = state->creds->negotiate_flags;
1260 tmp_flags &= state->context->client.required_flags;
1261 if (tmp_flags != state->context->client.required_flags) {
1262 if (NT_STATUS_IS_OK(result)) {
1263 tevent_req_nterror(req, NT_STATUS_DOWNGRADE_DETECTED);
1266 tevent_req_nterror(req, result);
1270 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
1272 tmp_flags = state->context->client.proposed_flags;
1273 if ((state->current_flags == tmp_flags) &&
1274 (state->creds->negotiate_flags != tmp_flags))
1277 * lets retry with the negotiated flags
1279 state->current_flags = state->creds->negotiate_flags;
1280 netlogon_creds_cli_auth_challenge_start(req);
1284 if (!state->try_previous_nt_hash) {
1286 * we already retried, giving up...
1288 tevent_req_nterror(req, result);
1293 * lets retry with the old nt hash.
1295 state->try_previous_nt_hash = false;
1296 state->used_nt_hash = state->previous_nt_hash;
1297 state->current_flags = state->context->client.proposed_flags;
1298 netlogon_creds_cli_auth_challenge_start(req);
1302 ok = netlogon_creds_client_check(state->creds,
1303 &state->server_credential);
1305 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1309 ndr_err = ndr_push_struct_blob(&blob, state, state->creds,
1310 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
1311 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1312 status = ndr_map_error2ntstatus(ndr_err);
1313 tevent_req_nterror(req, status);
1317 data.dptr = blob.data;
1318 data.dsize = blob.length;
1320 status = dbwrap_store(state->context->db.ctx,
1321 state->context->db.key_data,
1323 TALLOC_FREE(state->locked_state);
1324 if (tevent_req_nterror(req, status)) {
1328 tevent_req_done(req);
1331 NTSTATUS netlogon_creds_cli_auth_recv(struct tevent_req *req)
1335 if (tevent_req_is_nterror(req, &status)) {
1336 tevent_req_received(req);
1340 tevent_req_received(req);
1341 return NT_STATUS_OK;
1344 NTSTATUS netlogon_creds_cli_auth(struct netlogon_creds_cli_context *context,
1345 struct dcerpc_binding_handle *b,
1346 struct samr_Password current_nt_hash,
1347 const struct samr_Password *previous_nt_hash)
1349 TALLOC_CTX *frame = talloc_stackframe();
1350 struct tevent_context *ev;
1351 struct tevent_req *req;
1352 NTSTATUS status = NT_STATUS_NO_MEMORY;
1354 ev = samba_tevent_context_init(frame);
1358 req = netlogon_creds_cli_auth_send(frame, ev, context, b,
1364 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1367 status = netlogon_creds_cli_auth_recv(req);
1373 struct netlogon_creds_cli_check_state {
1374 struct tevent_context *ev;
1375 struct netlogon_creds_cli_context *context;
1376 struct dcerpc_binding_handle *binding_handle;
1378 char *srv_name_slash;
1380 union netr_Capabilities caps;
1382 struct netlogon_creds_CredentialState *creds;
1383 struct netlogon_creds_CredentialState tmp_creds;
1384 struct netr_Authenticator req_auth;
1385 struct netr_Authenticator rep_auth;
1388 static void netlogon_creds_cli_check_cleanup(struct tevent_req *req,
1390 static void netlogon_creds_cli_check_locked(struct tevent_req *subreq);
1392 struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx,
1393 struct tevent_context *ev,
1394 struct netlogon_creds_cli_context *context,
1395 struct dcerpc_binding_handle *b)
1397 struct tevent_req *req;
1398 struct netlogon_creds_cli_check_state *state;
1399 struct tevent_req *subreq;
1400 enum dcerpc_AuthType auth_type;
1401 enum dcerpc_AuthLevel auth_level;
1403 req = tevent_req_create(mem_ctx, &state,
1404 struct netlogon_creds_cli_check_state);
1410 state->context = context;
1411 state->binding_handle = b;
1413 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
1414 context->server.computer);
1415 if (tevent_req_nomem(state->srv_name_slash, req)) {
1416 return tevent_req_post(req, ev);
1419 dcerpc_binding_handle_auth_info(state->binding_handle,
1420 &auth_type, &auth_level);
1422 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1423 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1424 return tevent_req_post(req, ev);
1427 switch (auth_level) {
1428 case DCERPC_AUTH_LEVEL_INTEGRITY:
1429 case DCERPC_AUTH_LEVEL_PRIVACY:
1432 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1433 return tevent_req_post(req, ev);
1436 subreq = netlogon_creds_cli_lock_send(state, state->ev,
1438 if (tevent_req_nomem(subreq, req)) {
1439 return tevent_req_post(req, ev);
1442 tevent_req_set_callback(subreq,
1443 netlogon_creds_cli_check_locked,
1449 static void netlogon_creds_cli_check_cleanup(struct tevent_req *req,
1452 struct netlogon_creds_cli_check_state *state =
1453 tevent_req_data(req,
1454 struct netlogon_creds_cli_check_state);
1456 if (state->creds == NULL) {
1460 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
1461 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
1462 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
1463 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
1464 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1465 TALLOC_FREE(state->creds);
1469 netlogon_creds_cli_delete(state->context, &state->creds);
1472 static void netlogon_creds_cli_check_caps(struct tevent_req *subreq);
1474 static void netlogon_creds_cli_check_locked(struct tevent_req *subreq)
1476 struct tevent_req *req =
1477 tevent_req_callback_data(subreq,
1479 struct netlogon_creds_cli_check_state *state =
1480 tevent_req_data(req,
1481 struct netlogon_creds_cli_check_state);
1484 status = netlogon_creds_cli_lock_recv(subreq, state,
1486 TALLOC_FREE(subreq);
1487 if (tevent_req_nterror(req, status)) {
1492 * we defer all callbacks in order to cleanup
1493 * the database record.
1495 tevent_req_defer_callback(req, state->ev);
1497 state->tmp_creds = *state->creds;
1498 netlogon_creds_client_authenticator(&state->tmp_creds,
1500 ZERO_STRUCT(state->rep_auth);
1502 subreq = dcerpc_netr_LogonGetCapabilities_send(state, state->ev,
1503 state->binding_handle,
1504 state->srv_name_slash,
1505 state->context->client.computer,
1510 if (tevent_req_nomem(subreq, req)) {
1511 status = NT_STATUS_NO_MEMORY;
1512 netlogon_creds_cli_check_cleanup(req, status);
1515 tevent_req_set_callback(subreq,
1516 netlogon_creds_cli_check_caps,
1520 static void netlogon_creds_cli_check_caps(struct tevent_req *subreq)
1522 struct tevent_req *req =
1523 tevent_req_callback_data(subreq,
1525 struct netlogon_creds_cli_check_state *state =
1526 tevent_req_data(req,
1527 struct netlogon_creds_cli_check_state);
1532 status = dcerpc_netr_LogonGetCapabilities_recv(subreq, state,
1534 TALLOC_FREE(subreq);
1535 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1537 * Note that the negotiated flags are already checked
1538 * for our required flags after the ServerAuthenticate3/2 call.
1540 uint32_t negotiated = state->tmp_creds.negotiate_flags;
1542 if (negotiated & NETLOGON_NEG_SUPPORTS_AES) {
1544 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1545 * already, we expect this to work!
1547 status = NT_STATUS_DOWNGRADE_DETECTED;
1548 tevent_req_nterror(req, status);
1549 netlogon_creds_cli_check_cleanup(req, status);
1553 if (negotiated & NETLOGON_NEG_STRONG_KEYS) {
1555 * If we have negotiated NETLOGON_NEG_STRONG_KEYS
1556 * we expect this to work at least as far as the
1557 * NOT_SUPPORTED error handled below!
1559 * NT 4.0 and Old Samba servers are not
1560 * allowed without "require strong key = no"
1562 status = NT_STATUS_DOWNGRADE_DETECTED;
1563 tevent_req_nterror(req, status);
1564 netlogon_creds_cli_check_cleanup(req, status);
1569 * If we not require NETLOGON_NEG_SUPPORTS_AES or
1570 * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore
1571 * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
1573 * This is needed against NT 4.0 and old Samba servers.
1575 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
1576 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
1577 * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
1578 * with the next request as the sequence number processing
1581 netlogon_creds_cli_check_cleanup(req, status);
1582 tevent_req_done(req);
1585 if (tevent_req_nterror(req, status)) {
1586 netlogon_creds_cli_check_cleanup(req, status);
1590 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
1592 * Note that the negotiated flags are already checked
1593 * for our required flags after the ServerAuthenticate3/2 call.
1595 uint32_t negotiated = state->tmp_creds.negotiate_flags;
1597 if (negotiated & NETLOGON_NEG_SUPPORTS_AES) {
1599 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1600 * already, we expect this to work!
1602 status = NT_STATUS_DOWNGRADE_DETECTED;
1603 tevent_req_nterror(req, status);
1604 netlogon_creds_cli_check_cleanup(req, status);
1609 * This is ok, the server does not support
1610 * NETLOGON_NEG_SUPPORTS_AES.
1612 * netr_LogonGetCapabilities() was
1613 * netr_LogonDummyRoutine1() before
1614 * NETLOGON_NEG_SUPPORTS_AES was invented.
1616 netlogon_creds_cli_check_cleanup(req, result);
1617 tevent_req_done(req);
1621 ok = netlogon_creds_client_check(&state->tmp_creds,
1622 &state->rep_auth.cred);
1624 status = NT_STATUS_ACCESS_DENIED;
1625 tevent_req_nterror(req, status);
1626 netlogon_creds_cli_check_cleanup(req, status);
1630 if (tevent_req_nterror(req, result)) {
1631 netlogon_creds_cli_check_cleanup(req, result);
1635 if (state->caps.server_capabilities != state->tmp_creds.negotiate_flags) {
1636 status = NT_STATUS_DOWNGRADE_DETECTED;
1637 tevent_req_nterror(req, status);
1638 netlogon_creds_cli_check_cleanup(req, status);
1643 * This is the key check that makes this check secure. If we
1644 * get OK here (rather than NOT_SUPPORTED), then the server
1645 * did support AES. If the server only proposed STRONG_KEYS
1646 * and not AES, then it should have failed with
1647 * NOT_IMPLEMENTED. We always send AES as a client, so the
1648 * server should always have returned it.
1650 if (!(state->caps.server_capabilities & NETLOGON_NEG_SUPPORTS_AES)) {
1651 status = NT_STATUS_DOWNGRADE_DETECTED;
1652 tevent_req_nterror(req, status);
1653 netlogon_creds_cli_check_cleanup(req, status);
1657 *state->creds = state->tmp_creds;
1658 status = netlogon_creds_cli_store(state->context,
1660 netlogon_creds_cli_check_cleanup(req, status);
1661 if (tevent_req_nterror(req, status)) {
1665 tevent_req_done(req);
1668 NTSTATUS netlogon_creds_cli_check_recv(struct tevent_req *req)
1672 if (tevent_req_is_nterror(req, &status)) {
1673 netlogon_creds_cli_check_cleanup(req, status);
1674 tevent_req_received(req);
1678 tevent_req_received(req);
1679 return NT_STATUS_OK;
1682 NTSTATUS netlogon_creds_cli_check(struct netlogon_creds_cli_context *context,
1683 struct dcerpc_binding_handle *b)
1685 TALLOC_CTX *frame = talloc_stackframe();
1686 struct tevent_context *ev;
1687 struct tevent_req *req;
1688 NTSTATUS status = NT_STATUS_NO_MEMORY;
1690 ev = samba_tevent_context_init(frame);
1694 req = netlogon_creds_cli_check_send(frame, ev, context, b);
1698 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1701 status = netlogon_creds_cli_check_recv(req);
1707 struct netlogon_creds_cli_ServerPasswordSet_state {
1708 struct tevent_context *ev;
1709 struct netlogon_creds_cli_context *context;
1710 struct dcerpc_binding_handle *binding_handle;
1711 uint32_t old_timeout;
1713 char *srv_name_slash;
1714 enum dcerpc_AuthType auth_type;
1715 enum dcerpc_AuthLevel auth_level;
1717 struct samr_CryptPassword samr_crypt_password;
1718 struct netr_CryptPassword netr_crypt_password;
1719 struct samr_Password samr_password;
1721 struct netlogon_creds_CredentialState *creds;
1722 struct netlogon_creds_CredentialState tmp_creds;
1723 struct netr_Authenticator req_auth;
1724 struct netr_Authenticator rep_auth;
1727 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req *req,
1729 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subreq);
1731 struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx,
1732 struct tevent_context *ev,
1733 struct netlogon_creds_cli_context *context,
1734 struct dcerpc_binding_handle *b,
1735 const char *new_password,
1736 const uint32_t *new_version)
1738 struct tevent_req *req;
1739 struct netlogon_creds_cli_ServerPasswordSet_state *state;
1740 struct tevent_req *subreq;
1743 req = tevent_req_create(mem_ctx, &state,
1744 struct netlogon_creds_cli_ServerPasswordSet_state);
1750 state->context = context;
1751 state->binding_handle = b;
1754 * netr_ServerPasswordSet
1756 E_md4hash(new_password, state->samr_password.hash);
1759 * netr_ServerPasswordSet2
1761 ok = encode_pw_buffer(state->samr_crypt_password.data,
1762 new_password, STR_UNICODE);
1764 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1765 return tevent_req_post(req, ev);
1768 if (new_version != NULL) {
1769 struct NL_PASSWORD_VERSION version;
1770 uint32_t len = IVAL(state->samr_crypt_password.data, 512);
1771 uint32_t ofs = 512 - len;
1775 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1776 return tevent_req_post(req, ev);
1780 version.ReservedField = 0;
1781 version.PasswordVersionNumber = *new_version;
1782 version.PasswordVersionPresent =
1783 NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT;
1785 p = state->samr_crypt_password.data + ofs;
1786 SIVAL(p, 0, version.ReservedField);
1787 SIVAL(p, 4, version.PasswordVersionNumber);
1788 SIVAL(p, 8, version.PasswordVersionPresent);
1791 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
1792 context->server.computer);
1793 if (tevent_req_nomem(state->srv_name_slash, req)) {
1794 return tevent_req_post(req, ev);
1797 dcerpc_binding_handle_auth_info(state->binding_handle,
1799 &state->auth_level);
1801 subreq = netlogon_creds_cli_lock_send(state, state->ev,
1803 if (tevent_req_nomem(subreq, req)) {
1804 return tevent_req_post(req, ev);
1807 tevent_req_set_callback(subreq,
1808 netlogon_creds_cli_ServerPasswordSet_locked,
1814 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req *req,
1817 struct netlogon_creds_cli_ServerPasswordSet_state *state =
1818 tevent_req_data(req,
1819 struct netlogon_creds_cli_ServerPasswordSet_state);
1821 if (state->creds == NULL) {
1825 dcerpc_binding_handle_set_timeout(state->binding_handle,
1826 state->old_timeout);
1828 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
1829 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
1830 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
1831 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
1832 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1833 TALLOC_FREE(state->creds);
1837 netlogon_creds_cli_delete(state->context, &state->creds);
1840 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq);
1842 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subreq)
1844 struct tevent_req *req =
1845 tevent_req_callback_data(subreq,
1847 struct netlogon_creds_cli_ServerPasswordSet_state *state =
1848 tevent_req_data(req,
1849 struct netlogon_creds_cli_ServerPasswordSet_state);
1852 status = netlogon_creds_cli_lock_recv(subreq, state,
1854 TALLOC_FREE(subreq);
1855 if (tevent_req_nterror(req, status)) {
1859 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
1860 switch (state->auth_level) {
1861 case DCERPC_AUTH_LEVEL_INTEGRITY:
1862 case DCERPC_AUTH_LEVEL_PRIVACY:
1865 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1869 uint32_t tmp = state->creds->negotiate_flags;
1871 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
1873 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
1874 * it should be used, which means
1875 * we had a chance to verify no downgrade
1878 * This relies on netlogon_creds_cli_check*
1879 * being called before, as first request after
1882 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1887 state->old_timeout = dcerpc_binding_handle_set_timeout(
1888 state->binding_handle, 600000);
1891 * we defer all callbacks in order to cleanup
1892 * the database record.
1894 tevent_req_defer_callback(req, state->ev);
1896 state->tmp_creds = *state->creds;
1897 netlogon_creds_client_authenticator(&state->tmp_creds,
1899 ZERO_STRUCT(state->rep_auth);
1901 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) {
1903 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1904 netlogon_creds_aes_encrypt(&state->tmp_creds,
1905 state->samr_crypt_password.data,
1908 netlogon_creds_arcfour_crypt(&state->tmp_creds,
1909 state->samr_crypt_password.data,
1913 memcpy(state->netr_crypt_password.data,
1914 state->samr_crypt_password.data, 512);
1915 state->netr_crypt_password.length =
1916 IVAL(state->samr_crypt_password.data, 512);
1918 subreq = dcerpc_netr_ServerPasswordSet2_send(state, state->ev,
1919 state->binding_handle,
1920 state->srv_name_slash,
1921 state->tmp_creds.account_name,
1922 state->tmp_creds.secure_channel_type,
1923 state->tmp_creds.computer_name,
1926 &state->netr_crypt_password);
1927 if (tevent_req_nomem(subreq, req)) {
1928 status = NT_STATUS_NO_MEMORY;
1929 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1933 netlogon_creds_des_encrypt(&state->tmp_creds,
1934 &state->samr_password);
1936 subreq = dcerpc_netr_ServerPasswordSet_send(state, state->ev,
1937 state->binding_handle,
1938 state->srv_name_slash,
1939 state->tmp_creds.account_name,
1940 state->tmp_creds.secure_channel_type,
1941 state->tmp_creds.computer_name,
1944 &state->samr_password);
1945 if (tevent_req_nomem(subreq, req)) {
1946 status = NT_STATUS_NO_MEMORY;
1947 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1952 tevent_req_set_callback(subreq,
1953 netlogon_creds_cli_ServerPasswordSet_done,
1957 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq)
1959 struct tevent_req *req =
1960 tevent_req_callback_data(subreq,
1962 struct netlogon_creds_cli_ServerPasswordSet_state *state =
1963 tevent_req_data(req,
1964 struct netlogon_creds_cli_ServerPasswordSet_state);
1969 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) {
1970 status = dcerpc_netr_ServerPasswordSet2_recv(subreq, state,
1972 TALLOC_FREE(subreq);
1973 if (tevent_req_nterror(req, status)) {
1974 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1978 status = dcerpc_netr_ServerPasswordSet_recv(subreq, state,
1980 TALLOC_FREE(subreq);
1981 if (tevent_req_nterror(req, status)) {
1982 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1987 ok = netlogon_creds_client_check(&state->tmp_creds,
1988 &state->rep_auth.cred);
1990 status = NT_STATUS_ACCESS_DENIED;
1991 tevent_req_nterror(req, status);
1992 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1996 if (tevent_req_nterror(req, result)) {
1997 netlogon_creds_cli_ServerPasswordSet_cleanup(req, result);
2001 dcerpc_binding_handle_set_timeout(state->binding_handle,
2002 state->old_timeout);
2004 *state->creds = state->tmp_creds;
2005 status = netlogon_creds_cli_store(state->context,
2007 if (tevent_req_nterror(req, status)) {
2008 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2012 tevent_req_done(req);
2015 NTSTATUS netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req *req)
2019 if (tevent_req_is_nterror(req, &status)) {
2020 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2021 tevent_req_received(req);
2025 tevent_req_received(req);
2026 return NT_STATUS_OK;
2029 NTSTATUS netlogon_creds_cli_ServerPasswordSet(
2030 struct netlogon_creds_cli_context *context,
2031 struct dcerpc_binding_handle *b,
2032 const char *new_password,
2033 const uint32_t *new_version)
2035 TALLOC_CTX *frame = talloc_stackframe();
2036 struct tevent_context *ev;
2037 struct tevent_req *req;
2038 NTSTATUS status = NT_STATUS_NO_MEMORY;
2040 ev = samba_tevent_context_init(frame);
2044 req = netlogon_creds_cli_ServerPasswordSet_send(frame, ev, context, b,
2050 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2053 status = netlogon_creds_cli_ServerPasswordSet_recv(req);
2059 struct netlogon_creds_cli_LogonSamLogon_state {
2060 struct tevent_context *ev;
2061 struct netlogon_creds_cli_context *context;
2062 struct dcerpc_binding_handle *binding_handle;
2064 char *srv_name_slash;
2066 enum netr_LogonInfoClass logon_level;
2067 const union netr_LogonLevel *const_logon;
2068 union netr_LogonLevel *logon;
2071 uint16_t validation_level;
2072 union netr_Validation *validation;
2073 uint8_t authoritative;
2076 * do we need encryption at the application layer?
2080 bool try_validation6;
2083 * the read only credentials before we started the operation
2085 struct netlogon_creds_CredentialState *ro_creds;
2087 struct netlogon_creds_CredentialState *lk_creds;
2089 struct netlogon_creds_CredentialState tmp_creds;
2090 struct netr_Authenticator req_auth;
2091 struct netr_Authenticator rep_auth;
2094 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req);
2095 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req *req,
2098 struct tevent_req *netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX *mem_ctx,
2099 struct tevent_context *ev,
2100 struct netlogon_creds_cli_context *context,
2101 struct dcerpc_binding_handle *b,
2102 enum netr_LogonInfoClass logon_level,
2103 const union netr_LogonLevel *logon,
2106 struct tevent_req *req;
2107 struct netlogon_creds_cli_LogonSamLogon_state *state;
2109 req = tevent_req_create(mem_ctx, &state,
2110 struct netlogon_creds_cli_LogonSamLogon_state);
2116 state->context = context;
2117 state->binding_handle = b;
2119 state->logon_level = logon_level;
2120 state->const_logon = logon;
2121 state->flags = flags;
2123 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
2124 context->server.computer);
2125 if (tevent_req_nomem(state->srv_name_slash, req)) {
2126 return tevent_req_post(req, ev);
2129 switch (logon_level) {
2130 case NetlogonInteractiveInformation:
2131 case NetlogonInteractiveTransitiveInformation:
2132 case NetlogonServiceInformation:
2133 case NetlogonServiceTransitiveInformation:
2134 case NetlogonGenericInformation:
2135 state->user_encrypt = true;
2138 case NetlogonNetworkInformation:
2139 case NetlogonNetworkTransitiveInformation:
2143 state->validation = talloc_zero(state, union netr_Validation);
2144 if (tevent_req_nomem(state->validation, req)) {
2145 return tevent_req_post(req, ev);
2148 netlogon_creds_cli_LogonSamLogon_start(req);
2149 if (!tevent_req_is_in_progress(req)) {
2150 return tevent_req_post(req, ev);
2154 * we defer all callbacks in order to cleanup
2155 * the database record.
2157 tevent_req_defer_callback(req, state->ev);
2161 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req *req,
2164 struct netlogon_creds_cli_LogonSamLogon_state *state =
2165 tevent_req_data(req,
2166 struct netlogon_creds_cli_LogonSamLogon_state);
2168 if (state->lk_creds == NULL) {
2172 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2174 * This is a hack to recover from a bug in old
2175 * Samba servers, when LogonSamLogonEx() fails:
2177 * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
2179 * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2181 * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE,
2182 * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR
2183 * If the sign/seal check fails.
2185 * In that case we need to cleanup the netlogon session.
2187 * It's the job of the caller to disconnect the current
2188 * connection, if netlogon_creds_cli_LogonSamLogon()
2189 * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2191 if (!state->context->server.try_logon_with) {
2192 status = NT_STATUS_NETWORK_ACCESS_DENIED;
2196 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
2197 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
2198 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
2199 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
2200 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
2201 TALLOC_FREE(state->lk_creds);
2205 netlogon_creds_cli_delete(state->context, &state->lk_creds);
2208 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq);
2210 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req)
2212 struct netlogon_creds_cli_LogonSamLogon_state *state =
2213 tevent_req_data(req,
2214 struct netlogon_creds_cli_LogonSamLogon_state);
2215 struct tevent_req *subreq;
2217 enum dcerpc_AuthType auth_type;
2218 enum dcerpc_AuthLevel auth_level;
2220 TALLOC_FREE(state->ro_creds);
2221 TALLOC_FREE(state->logon);
2222 ZERO_STRUCTP(state->validation);
2224 dcerpc_binding_handle_auth_info(state->binding_handle,
2225 &auth_type, &auth_level);
2227 state->try_logon_ex = state->context->server.try_logon_ex;
2228 state->try_validation6 = state->context->server.try_validation6;
2230 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
2231 state->try_logon_ex = false;
2234 if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
2235 state->try_validation6 = false;
2238 if (state->try_logon_ex) {
2239 if (state->try_validation6) {
2240 state->validation_level = 6;
2242 state->validation_level = 3;
2243 state->user_encrypt = true;
2246 state->logon = netlogon_creds_shallow_copy_logon(state,
2248 state->const_logon);
2249 if (tevent_req_nomem(state->logon, req)) {
2250 status = NT_STATUS_NO_MEMORY;
2251 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2255 if (state->user_encrypt) {
2256 status = netlogon_creds_cli_get(state->context,
2259 if (!NT_STATUS_IS_OK(status)) {
2260 status = NT_STATUS_ACCESS_DENIED;
2261 tevent_req_nterror(req, status);
2262 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2266 netlogon_creds_encrypt_samlogon_logon(state->ro_creds,
2271 subreq = dcerpc_netr_LogonSamLogonEx_send(state, state->ev,
2272 state->binding_handle,
2273 state->srv_name_slash,
2274 state->context->client.computer,
2277 state->validation_level,
2279 &state->authoritative,
2281 if (tevent_req_nomem(subreq, req)) {
2282 status = NT_STATUS_NO_MEMORY;
2283 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2286 tevent_req_set_callback(subreq,
2287 netlogon_creds_cli_LogonSamLogon_done,
2292 if (state->lk_creds == NULL) {
2293 subreq = netlogon_creds_cli_lock_send(state, state->ev,
2295 if (tevent_req_nomem(subreq, req)) {
2296 status = NT_STATUS_NO_MEMORY;
2297 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2300 tevent_req_set_callback(subreq,
2301 netlogon_creds_cli_LogonSamLogon_done,
2306 state->tmp_creds = *state->lk_creds;
2307 netlogon_creds_client_authenticator(&state->tmp_creds,
2309 ZERO_STRUCT(state->rep_auth);
2311 state->logon = netlogon_creds_shallow_copy_logon(state,
2313 state->const_logon);
2314 if (tevent_req_nomem(state->logon, req)) {
2315 status = NT_STATUS_NO_MEMORY;
2316 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2320 netlogon_creds_encrypt_samlogon_logon(state->ro_creds,
2324 state->validation_level = 3;
2326 if (state->context->server.try_logon_with) {
2327 subreq = dcerpc_netr_LogonSamLogonWithFlags_send(state, state->ev,
2328 state->binding_handle,
2329 state->srv_name_slash,
2330 state->context->client.computer,
2335 state->validation_level,
2337 &state->authoritative,
2339 if (tevent_req_nomem(subreq, req)) {
2340 status = NT_STATUS_NO_MEMORY;
2341 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2347 subreq = dcerpc_netr_LogonSamLogon_send(state, state->ev,
2348 state->binding_handle,
2349 state->srv_name_slash,
2350 state->context->client.computer,
2355 state->validation_level,
2357 &state->authoritative);
2358 if (tevent_req_nomem(subreq, req)) {
2359 status = NT_STATUS_NO_MEMORY;
2360 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2365 tevent_req_set_callback(subreq,
2366 netlogon_creds_cli_LogonSamLogon_done,
2370 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq)
2372 struct tevent_req *req =
2373 tevent_req_callback_data(subreq,
2375 struct netlogon_creds_cli_LogonSamLogon_state *state =
2376 tevent_req_data(req,
2377 struct netlogon_creds_cli_LogonSamLogon_state);
2382 if (state->try_logon_ex) {
2383 status = dcerpc_netr_LogonSamLogonEx_recv(subreq,
2386 TALLOC_FREE(subreq);
2387 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2388 state->context->server.try_validation6 = false;
2389 state->context->server.try_logon_ex = false;
2390 netlogon_creds_cli_LogonSamLogon_start(req);
2393 if (tevent_req_nterror(req, status)) {
2394 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2398 if ((state->validation_level == 6) &&
2399 (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS) ||
2400 NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PARAMETER) ||
2401 NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL)))
2403 state->context->server.try_validation6 = false;
2404 netlogon_creds_cli_LogonSamLogon_start(req);
2408 if (tevent_req_nterror(req, result)) {
2409 netlogon_creds_cli_LogonSamLogon_cleanup(req, result);
2413 if (state->ro_creds == NULL) {
2414 tevent_req_done(req);
2418 ok = netlogon_creds_cli_validate(state->context, state->ro_creds);
2421 * We got a race, lets retry with on authenticator
2424 TALLOC_FREE(state->ro_creds);
2425 state->try_logon_ex = false;
2426 netlogon_creds_cli_LogonSamLogon_start(req);
2430 netlogon_creds_decrypt_samlogon_validation(state->ro_creds,
2431 state->validation_level,
2434 tevent_req_done(req);
2438 if (state->lk_creds == NULL) {
2439 status = netlogon_creds_cli_lock_recv(subreq, state,
2441 TALLOC_FREE(subreq);
2442 if (tevent_req_nterror(req, status)) {
2443 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2447 netlogon_creds_cli_LogonSamLogon_start(req);
2451 if (state->context->server.try_logon_with) {
2452 status = dcerpc_netr_LogonSamLogonWithFlags_recv(subreq,
2455 TALLOC_FREE(subreq);
2456 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2457 state->context->server.try_logon_with = false;
2458 netlogon_creds_cli_LogonSamLogon_start(req);
2461 if (tevent_req_nterror(req, status)) {
2462 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2466 status = dcerpc_netr_LogonSamLogon_recv(subreq,
2469 TALLOC_FREE(subreq);
2470 if (tevent_req_nterror(req, status)) {
2471 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2476 ok = netlogon_creds_client_check(&state->tmp_creds,
2477 &state->rep_auth.cred);
2479 status = NT_STATUS_ACCESS_DENIED;
2480 tevent_req_nterror(req, status);
2481 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2485 *state->lk_creds = state->tmp_creds;
2486 status = netlogon_creds_cli_store(state->context,
2488 if (tevent_req_nterror(req, status)) {
2489 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2493 if (tevent_req_nterror(req, result)) {
2494 netlogon_creds_cli_LogonSamLogon_cleanup(req, result);
2498 netlogon_creds_decrypt_samlogon_validation(&state->tmp_creds,
2499 state->validation_level,
2502 tevent_req_done(req);
2505 NTSTATUS netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req *req,
2506 TALLOC_CTX *mem_ctx,
2507 uint16_t *validation_level,
2508 union netr_Validation **validation,
2509 uint8_t *authoritative,
2512 struct netlogon_creds_cli_LogonSamLogon_state *state =
2513 tevent_req_data(req,
2514 struct netlogon_creds_cli_LogonSamLogon_state);
2517 /* authoritative is also returned on error */
2518 *authoritative = state->authoritative;
2520 if (tevent_req_is_nterror(req, &status)) {
2521 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2522 tevent_req_received(req);
2526 *validation_level = state->validation_level;
2527 *validation = talloc_move(mem_ctx, &state->validation);
2528 *flags = state->flags;
2530 tevent_req_received(req);
2531 return NT_STATUS_OK;
2534 NTSTATUS netlogon_creds_cli_LogonSamLogon(
2535 struct netlogon_creds_cli_context *context,
2536 struct dcerpc_binding_handle *b,
2537 enum netr_LogonInfoClass logon_level,
2538 const union netr_LogonLevel *logon,
2539 TALLOC_CTX *mem_ctx,
2540 uint16_t *validation_level,
2541 union netr_Validation **validation,
2542 uint8_t *authoritative,
2545 TALLOC_CTX *frame = talloc_stackframe();
2546 struct tevent_context *ev;
2547 struct tevent_req *req;
2548 NTSTATUS status = NT_STATUS_NO_MEMORY;
2550 ev = samba_tevent_context_init(frame);
2554 req = netlogon_creds_cli_LogonSamLogon_send(frame, ev, context, b,
2560 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2563 status = netlogon_creds_cli_LogonSamLogon_recv(req, mem_ctx,
2573 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state {
2574 struct tevent_context *ev;
2575 struct netlogon_creds_cli_context *context;
2576 struct dcerpc_binding_handle *binding_handle;
2578 char *srv_name_slash;
2579 enum dcerpc_AuthType auth_type;
2580 enum dcerpc_AuthLevel auth_level;
2582 const char *site_name;
2584 struct NL_DNS_NAME_INFO_ARRAY *dns_names;
2586 struct netlogon_creds_CredentialState *creds;
2587 struct netlogon_creds_CredentialState tmp_creds;
2588 struct netr_Authenticator req_auth;
2589 struct netr_Authenticator rep_auth;
2592 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req *req,
2594 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req *subreq);
2596 struct tevent_req *netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(TALLOC_CTX *mem_ctx,
2597 struct tevent_context *ev,
2598 struct netlogon_creds_cli_context *context,
2599 struct dcerpc_binding_handle *b,
2600 const char *site_name,
2602 struct NL_DNS_NAME_INFO_ARRAY *dns_names)
2604 struct tevent_req *req;
2605 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state;
2606 struct tevent_req *subreq;
2608 req = tevent_req_create(mem_ctx, &state,
2609 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2615 state->context = context;
2616 state->binding_handle = b;
2618 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
2619 context->server.computer);
2620 if (tevent_req_nomem(state->srv_name_slash, req)) {
2621 return tevent_req_post(req, ev);
2624 state->site_name = site_name;
2625 state->dns_ttl = dns_ttl;
2626 state->dns_names = dns_names;
2628 dcerpc_binding_handle_auth_info(state->binding_handle,
2630 &state->auth_level);
2632 subreq = netlogon_creds_cli_lock_send(state, state->ev,
2634 if (tevent_req_nomem(subreq, req)) {
2635 return tevent_req_post(req, ev);
2638 tevent_req_set_callback(subreq,
2639 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked,
2645 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req *req,
2648 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
2649 tevent_req_data(req,
2650 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2652 if (state->creds == NULL) {
2656 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
2657 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
2658 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
2659 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
2660 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
2661 TALLOC_FREE(state->creds);
2665 netlogon_creds_cli_delete(state->context, &state->creds);
2668 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req *subreq);
2670 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req *subreq)
2672 struct tevent_req *req =
2673 tevent_req_callback_data(subreq,
2675 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
2676 tevent_req_data(req,
2677 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2680 status = netlogon_creds_cli_lock_recv(subreq, state,
2682 TALLOC_FREE(subreq);
2683 if (tevent_req_nterror(req, status)) {
2687 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
2688 switch (state->auth_level) {
2689 case DCERPC_AUTH_LEVEL_INTEGRITY:
2690 case DCERPC_AUTH_LEVEL_PRIVACY:
2693 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2697 uint32_t tmp = state->creds->negotiate_flags;
2699 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
2701 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
2702 * it should be used, which means
2703 * we had a chance to verify no downgrade
2706 * This relies on netlogon_creds_cli_check*
2707 * being called before, as first request after
2710 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2716 * we defer all callbacks in order to cleanup
2717 * the database record.
2719 tevent_req_defer_callback(req, state->ev);
2721 state->tmp_creds = *state->creds;
2722 netlogon_creds_client_authenticator(&state->tmp_creds,
2724 ZERO_STRUCT(state->rep_auth);
2726 subreq = dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_send(state, state->ev,
2727 state->binding_handle,
2728 state->srv_name_slash,
2729 state->tmp_creds.computer_name,
2735 if (tevent_req_nomem(subreq, req)) {
2736 status = NT_STATUS_NO_MEMORY;
2737 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2741 tevent_req_set_callback(subreq,
2742 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done,
2746 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req *subreq)
2748 struct tevent_req *req =
2749 tevent_req_callback_data(subreq,
2751 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
2752 tevent_req_data(req,
2753 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2759 * We use state->dns_names as the memory context, as this is
2760 * the only in/out variable and it has been overwritten by the
2761 * out parameter from the server.
2763 * We need to preserve the return value until the caller can use it.
2765 status = dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_recv(subreq, state->dns_names,
2767 TALLOC_FREE(subreq);
2768 if (tevent_req_nterror(req, status)) {
2769 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2773 ok = netlogon_creds_client_check(&state->tmp_creds,
2774 &state->rep_auth.cred);
2776 status = NT_STATUS_ACCESS_DENIED;
2777 tevent_req_nterror(req, status);
2778 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2782 if (tevent_req_nterror(req, result)) {
2783 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, result);
2787 *state->creds = state->tmp_creds;
2788 status = netlogon_creds_cli_store(state->context,
2790 if (tevent_req_nterror(req, status)) {
2791 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2795 tevent_req_done(req);
2798 NTSTATUS netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(struct tevent_req *req)
2802 if (tevent_req_is_nterror(req, &status)) {
2803 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2804 tevent_req_received(req);
2808 tevent_req_received(req);
2809 return NT_STATUS_OK;
2812 NTSTATUS netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(
2813 struct netlogon_creds_cli_context *context,
2814 struct dcerpc_binding_handle *b,
2815 const char *site_name,
2817 struct NL_DNS_NAME_INFO_ARRAY *dns_names)
2819 TALLOC_CTX *frame = talloc_stackframe();
2820 struct tevent_context *ev;
2821 struct tevent_req *req;
2822 NTSTATUS status = NT_STATUS_NO_MEMORY;
2824 ev = samba_tevent_context_init(frame);
2828 req = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(frame, ev, context, b,
2835 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2838 status = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(req);
2844 struct netlogon_creds_cli_ServerGetTrustInfo_state {
2845 struct tevent_context *ev;
2846 struct netlogon_creds_cli_context *context;
2847 struct dcerpc_binding_handle *binding_handle;
2849 char *srv_name_slash;
2850 enum dcerpc_AuthType auth_type;
2851 enum dcerpc_AuthLevel auth_level;
2853 struct samr_Password new_owf_password;
2854 struct samr_Password old_owf_password;
2855 struct netr_TrustInfo *trust_info;
2857 struct netlogon_creds_CredentialState *creds;
2858 struct netlogon_creds_CredentialState tmp_creds;
2859 struct netr_Authenticator req_auth;
2860 struct netr_Authenticator rep_auth;
2863 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req *req,
2865 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req *subreq);
2867 struct tevent_req *netlogon_creds_cli_ServerGetTrustInfo_send(TALLOC_CTX *mem_ctx,
2868 struct tevent_context *ev,
2869 struct netlogon_creds_cli_context *context,
2870 struct dcerpc_binding_handle *b)
2872 struct tevent_req *req;
2873 struct netlogon_creds_cli_ServerGetTrustInfo_state *state;
2874 struct tevent_req *subreq;
2876 req = tevent_req_create(mem_ctx, &state,
2877 struct netlogon_creds_cli_ServerGetTrustInfo_state);
2883 state->context = context;
2884 state->binding_handle = b;
2886 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
2887 context->server.computer);
2888 if (tevent_req_nomem(state->srv_name_slash, req)) {
2889 return tevent_req_post(req, ev);
2892 dcerpc_binding_handle_auth_info(state->binding_handle,
2894 &state->auth_level);
2896 subreq = netlogon_creds_cli_lock_send(state, state->ev,
2898 if (tevent_req_nomem(subreq, req)) {
2899 return tevent_req_post(req, ev);
2902 tevent_req_set_callback(subreq,
2903 netlogon_creds_cli_ServerGetTrustInfo_locked,
2909 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req *req,
2912 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
2913 tevent_req_data(req,
2914 struct netlogon_creds_cli_ServerGetTrustInfo_state);
2916 if (state->creds == NULL) {
2920 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
2921 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
2922 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
2923 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
2924 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
2925 TALLOC_FREE(state->creds);
2929 netlogon_creds_cli_delete(state->context, &state->creds);
2932 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req *subreq);
2934 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req *subreq)
2936 struct tevent_req *req =
2937 tevent_req_callback_data(subreq,
2939 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
2940 tevent_req_data(req,
2941 struct netlogon_creds_cli_ServerGetTrustInfo_state);
2944 status = netlogon_creds_cli_lock_recv(subreq, state,
2946 TALLOC_FREE(subreq);
2947 if (tevent_req_nterror(req, status)) {
2951 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
2952 switch (state->auth_level) {
2953 case DCERPC_AUTH_LEVEL_PRIVACY:
2956 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2960 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2965 * we defer all callbacks in order to cleanup
2966 * the database record.
2968 tevent_req_defer_callback(req, state->ev);
2970 state->tmp_creds = *state->creds;
2971 netlogon_creds_client_authenticator(&state->tmp_creds,
2973 ZERO_STRUCT(state->rep_auth);
2975 subreq = dcerpc_netr_ServerGetTrustInfo_send(state, state->ev,
2976 state->binding_handle,
2977 state->srv_name_slash,
2978 state->tmp_creds.account_name,
2979 state->tmp_creds.secure_channel_type,
2980 state->tmp_creds.computer_name,
2983 &state->new_owf_password,
2984 &state->old_owf_password,
2985 &state->trust_info);
2986 if (tevent_req_nomem(subreq, req)) {
2987 status = NT_STATUS_NO_MEMORY;
2988 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
2992 tevent_req_set_callback(subreq,
2993 netlogon_creds_cli_ServerGetTrustInfo_done,
2997 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req *subreq)
2999 struct tevent_req *req =
3000 tevent_req_callback_data(subreq,
3002 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
3003 tevent_req_data(req,
3004 struct netlogon_creds_cli_ServerGetTrustInfo_state);
3007 const struct samr_Password zero = {};
3012 * We use state->dns_names as the memory context, as this is
3013 * the only in/out variable and it has been overwritten by the
3014 * out parameter from the server.
3016 * We need to preserve the return value until the caller can use it.
3018 status = dcerpc_netr_ServerGetTrustInfo_recv(subreq, state, &result);
3019 TALLOC_FREE(subreq);
3020 if (tevent_req_nterror(req, status)) {
3021 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3025 ok = netlogon_creds_client_check(&state->tmp_creds,
3026 &state->rep_auth.cred);
3028 status = NT_STATUS_ACCESS_DENIED;
3029 tevent_req_nterror(req, status);
3030 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3034 if (tevent_req_nterror(req, result)) {
3035 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, result);
3039 cmp = memcmp(state->new_owf_password.hash,
3040 zero.hash, sizeof(zero.hash));
3042 netlogon_creds_des_decrypt(&state->tmp_creds,
3043 &state->new_owf_password);
3045 cmp = memcmp(state->old_owf_password.hash,
3046 zero.hash, sizeof(zero.hash));
3048 netlogon_creds_des_decrypt(&state->tmp_creds,
3049 &state->old_owf_password);
3052 *state->creds = state->tmp_creds;
3053 status = netlogon_creds_cli_store(state->context,
3055 if (tevent_req_nterror(req, status)) {
3056 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3060 tevent_req_done(req);
3063 NTSTATUS netlogon_creds_cli_ServerGetTrustInfo_recv(struct tevent_req *req,
3064 TALLOC_CTX *mem_ctx,
3065 struct samr_Password *new_owf_password,
3066 struct samr_Password *old_owf_password,
3067 struct netr_TrustInfo **trust_info)
3069 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
3070 tevent_req_data(req,
3071 struct netlogon_creds_cli_ServerGetTrustInfo_state);
3074 if (tevent_req_is_nterror(req, &status)) {
3075 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3076 tevent_req_received(req);
3080 if (new_owf_password != NULL) {
3081 *new_owf_password = state->new_owf_password;
3083 if (old_owf_password != NULL) {
3084 *old_owf_password = state->old_owf_password;
3086 if (trust_info != NULL) {
3087 *trust_info = talloc_move(mem_ctx, &state->trust_info);
3090 tevent_req_received(req);
3091 return NT_STATUS_OK;
3094 NTSTATUS netlogon_creds_cli_ServerGetTrustInfo(
3095 struct netlogon_creds_cli_context *context,
3096 struct dcerpc_binding_handle *b,
3097 TALLOC_CTX *mem_ctx,
3098 struct samr_Password *new_owf_password,
3099 struct samr_Password *old_owf_password,
3100 struct netr_TrustInfo **trust_info)
3102 TALLOC_CTX *frame = talloc_stackframe();
3103 struct tevent_context *ev;
3104 struct tevent_req *req;
3105 NTSTATUS status = NT_STATUS_NO_MEMORY;
3107 ev = samba_tevent_context_init(frame);
3111 req = netlogon_creds_cli_ServerGetTrustInfo_send(frame, ev, context, b);
3115 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3118 status = netlogon_creds_cli_ServerGetTrustInfo_recv(req,
3128 struct netlogon_creds_cli_GetForestTrustInformation_state {
3129 struct tevent_context *ev;
3130 struct netlogon_creds_cli_context *context;
3131 struct dcerpc_binding_handle *binding_handle;
3133 char *srv_name_slash;
3134 enum dcerpc_AuthType auth_type;
3135 enum dcerpc_AuthLevel auth_level;
3138 struct lsa_ForestTrustInformation *forest_trust_info;
3140 struct netlogon_creds_CredentialState *creds;
3141 struct netlogon_creds_CredentialState tmp_creds;
3142 struct netr_Authenticator req_auth;
3143 struct netr_Authenticator rep_auth;
3146 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req *req,
3148 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req *subreq);
3150 struct tevent_req *netlogon_creds_cli_GetForestTrustInformation_send(TALLOC_CTX *mem_ctx,
3151 struct tevent_context *ev,
3152 struct netlogon_creds_cli_context *context,
3153 struct dcerpc_binding_handle *b)
3155 struct tevent_req *req;
3156 struct netlogon_creds_cli_GetForestTrustInformation_state *state;
3157 struct tevent_req *subreq;
3159 req = tevent_req_create(mem_ctx, &state,
3160 struct netlogon_creds_cli_GetForestTrustInformation_state);
3166 state->context = context;
3167 state->binding_handle = b;
3169 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
3170 context->server.computer);
3171 if (tevent_req_nomem(state->srv_name_slash, req)) {
3172 return tevent_req_post(req, ev);
3177 dcerpc_binding_handle_auth_info(state->binding_handle,
3179 &state->auth_level);
3181 subreq = netlogon_creds_cli_lock_send(state, state->ev,
3183 if (tevent_req_nomem(subreq, req)) {
3184 return tevent_req_post(req, ev);
3187 tevent_req_set_callback(subreq,
3188 netlogon_creds_cli_GetForestTrustInformation_locked,
3194 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req *req,
3197 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3198 tevent_req_data(req,
3199 struct netlogon_creds_cli_GetForestTrustInformation_state);
3201 if (state->creds == NULL) {
3205 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
3206 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
3207 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
3208 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
3209 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
3210 TALLOC_FREE(state->creds);
3214 netlogon_creds_cli_delete(state->context, &state->creds);
3217 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req *subreq);
3219 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req *subreq)
3221 struct tevent_req *req =
3222 tevent_req_callback_data(subreq,
3224 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3225 tevent_req_data(req,
3226 struct netlogon_creds_cli_GetForestTrustInformation_state);
3229 status = netlogon_creds_cli_lock_recv(subreq, state,
3231 TALLOC_FREE(subreq);
3232 if (tevent_req_nterror(req, status)) {
3236 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
3237 switch (state->auth_level) {
3238 case DCERPC_AUTH_LEVEL_INTEGRITY:
3239 case DCERPC_AUTH_LEVEL_PRIVACY:
3242 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3246 uint32_t tmp = state->creds->negotiate_flags;
3248 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
3250 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3251 * it should be used, which means
3252 * we had a chance to verify no downgrade
3255 * This relies on netlogon_creds_cli_check*
3256 * being called before, as first request after
3259 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3265 * we defer all callbacks in order to cleanup
3266 * the database record.
3268 tevent_req_defer_callback(req, state->ev);
3270 state->tmp_creds = *state->creds;
3271 netlogon_creds_client_authenticator(&state->tmp_creds,
3273 ZERO_STRUCT(state->rep_auth);
3275 subreq = dcerpc_netr_GetForestTrustInformation_send(state, state->ev,
3276 state->binding_handle,
3277 state->srv_name_slash,
3278 state->tmp_creds.computer_name,
3282 &state->forest_trust_info);
3283 if (tevent_req_nomem(subreq, req)) {
3284 status = NT_STATUS_NO_MEMORY;
3285 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3289 tevent_req_set_callback(subreq,
3290 netlogon_creds_cli_GetForestTrustInformation_done,
3294 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req *subreq)
3296 struct tevent_req *req =
3297 tevent_req_callback_data(subreq,
3299 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3300 tevent_req_data(req,
3301 struct netlogon_creds_cli_GetForestTrustInformation_state);
3307 * We use state->dns_names as the memory context, as this is
3308 * the only in/out variable and it has been overwritten by the
3309 * out parameter from the server.
3311 * We need to preserve the return value until the caller can use it.
3313 status = dcerpc_netr_GetForestTrustInformation_recv(subreq, state, &result);
3314 TALLOC_FREE(subreq);
3315 if (tevent_req_nterror(req, status)) {
3316 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3320 ok = netlogon_creds_client_check(&state->tmp_creds,
3321 &state->rep_auth.cred);
3323 status = NT_STATUS_ACCESS_DENIED;
3324 tevent_req_nterror(req, status);
3325 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3329 if (tevent_req_nterror(req, result)) {
3330 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, result);
3334 *state->creds = state->tmp_creds;
3335 status = netlogon_creds_cli_store(state->context,
3337 if (tevent_req_nterror(req, status)) {
3338 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3342 tevent_req_done(req);
3345 NTSTATUS netlogon_creds_cli_GetForestTrustInformation_recv(struct tevent_req *req,
3346 TALLOC_CTX *mem_ctx,
3347 struct lsa_ForestTrustInformation **forest_trust_info)
3349 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3350 tevent_req_data(req,
3351 struct netlogon_creds_cli_GetForestTrustInformation_state);
3354 if (tevent_req_is_nterror(req, &status)) {
3355 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3356 tevent_req_received(req);
3360 *forest_trust_info = talloc_move(mem_ctx, &state->forest_trust_info);
3362 tevent_req_received(req);
3363 return NT_STATUS_OK;
3366 NTSTATUS netlogon_creds_cli_GetForestTrustInformation(
3367 struct netlogon_creds_cli_context *context,
3368 struct dcerpc_binding_handle *b,
3369 TALLOC_CTX *mem_ctx,
3370 struct lsa_ForestTrustInformation **forest_trust_info)
3372 TALLOC_CTX *frame = talloc_stackframe();
3373 struct tevent_context *ev;
3374 struct tevent_req *req;
3375 NTSTATUS status = NT_STATUS_NO_MEMORY;
3377 ev = samba_tevent_context_init(frame);
3381 req = netlogon_creds_cli_GetForestTrustInformation_send(frame, ev, context, b);
3385 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3388 status = netlogon_creds_cli_GetForestTrustInformation_recv(req,