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_purge(state->context->db.ctx,
1035 state->context->db.key_data);
1036 if (tevent_req_nterror(req, status)) {
1037 return tevent_req_post(req, ev);
1040 netlogon_creds_cli_auth_challenge_start(req);
1041 if (!tevent_req_is_in_progress(req)) {
1042 return tevent_req_post(req, ev);
1048 static void netlogon_creds_cli_auth_locked(struct tevent_req *subreq)
1050 struct tevent_req *req =
1051 tevent_req_callback_data(subreq,
1053 struct netlogon_creds_cli_auth_state *state =
1054 tevent_req_data(req,
1055 struct netlogon_creds_cli_auth_state);
1058 status = g_lock_lock_recv(subreq);
1059 TALLOC_FREE(subreq);
1060 if (tevent_req_nterror(req, status)) {
1063 state->locked_state->is_glocked = true;
1065 status = dbwrap_purge(state->context->db.ctx,
1066 state->context->db.key_data);
1067 if (tevent_req_nterror(req, status)) {
1071 netlogon_creds_cli_auth_challenge_start(req);
1074 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq);
1076 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req *req)
1078 struct netlogon_creds_cli_auth_state *state =
1079 tevent_req_data(req,
1080 struct netlogon_creds_cli_auth_state);
1081 struct tevent_req *subreq;
1083 TALLOC_FREE(state->creds);
1085 generate_random_buffer(state->client_challenge.data,
1086 sizeof(state->client_challenge.data));
1088 subreq = dcerpc_netr_ServerReqChallenge_send(state, state->ev,
1089 state->binding_handle,
1090 state->srv_name_slash,
1091 state->context->client.computer,
1092 &state->client_challenge,
1093 &state->server_challenge);
1094 if (tevent_req_nomem(subreq, req)) {
1097 tevent_req_set_callback(subreq,
1098 netlogon_creds_cli_auth_challenge_done,
1102 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq);
1104 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq)
1106 struct tevent_req *req =
1107 tevent_req_callback_data(subreq,
1109 struct netlogon_creds_cli_auth_state *state =
1110 tevent_req_data(req,
1111 struct netlogon_creds_cli_auth_state);
1115 status = dcerpc_netr_ServerReqChallenge_recv(subreq, state, &result);
1116 TALLOC_FREE(subreq);
1117 if (tevent_req_nterror(req, status)) {
1120 if (tevent_req_nterror(req, result)) {
1124 if (!state->try_auth3 && !state->try_auth2) {
1125 state->current_flags = 0;
1128 /* Calculate the session key and client credentials */
1130 state->creds = netlogon_creds_client_init(state,
1131 state->context->client.account,
1132 state->context->client.computer,
1133 state->context->client.type,
1134 &state->client_challenge,
1135 &state->server_challenge,
1136 &state->used_nt_hash,
1137 &state->client_credential,
1138 state->current_flags);
1139 if (tevent_req_nomem(state->creds, req)) {
1143 if (state->try_auth3) {
1144 subreq = dcerpc_netr_ServerAuthenticate3_send(state, state->ev,
1145 state->binding_handle,
1146 state->srv_name_slash,
1147 state->context->client.account,
1148 state->context->client.type,
1149 state->context->client.computer,
1150 &state->client_credential,
1151 &state->server_credential,
1152 &state->creds->negotiate_flags,
1154 if (tevent_req_nomem(subreq, req)) {
1157 } else if (state->try_auth2) {
1160 subreq = dcerpc_netr_ServerAuthenticate2_send(state, state->ev,
1161 state->binding_handle,
1162 state->srv_name_slash,
1163 state->context->client.account,
1164 state->context->client.type,
1165 state->context->client.computer,
1166 &state->client_credential,
1167 &state->server_credential,
1168 &state->creds->negotiate_flags);
1169 if (tevent_req_nomem(subreq, req)) {
1175 subreq = dcerpc_netr_ServerAuthenticate_send(state, state->ev,
1176 state->binding_handle,
1177 state->srv_name_slash,
1178 state->context->client.account,
1179 state->context->client.type,
1180 state->context->client.computer,
1181 &state->client_credential,
1182 &state->server_credential);
1183 if (tevent_req_nomem(subreq, req)) {
1187 tevent_req_set_callback(subreq,
1188 netlogon_creds_cli_auth_srvauth_done,
1192 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq)
1194 struct tevent_req *req =
1195 tevent_req_callback_data(subreq,
1197 struct netlogon_creds_cli_auth_state *state =
1198 tevent_req_data(req,
1199 struct netlogon_creds_cli_auth_state);
1203 enum ndr_err_code ndr_err;
1208 if (state->try_auth3) {
1209 status = dcerpc_netr_ServerAuthenticate3_recv(subreq, state,
1211 TALLOC_FREE(subreq);
1212 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1213 state->try_auth3 = false;
1214 netlogon_creds_cli_auth_challenge_start(req);
1217 if (tevent_req_nterror(req, status)) {
1220 } else if (state->try_auth2) {
1221 status = dcerpc_netr_ServerAuthenticate2_recv(subreq, state,
1223 TALLOC_FREE(subreq);
1224 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1225 state->try_auth2 = false;
1226 if (state->require_auth2) {
1227 status = NT_STATUS_DOWNGRADE_DETECTED;
1228 tevent_req_nterror(req, status);
1231 netlogon_creds_cli_auth_challenge_start(req);
1234 if (tevent_req_nterror(req, status)) {
1238 status = dcerpc_netr_ServerAuthenticate_recv(subreq, state,
1240 TALLOC_FREE(subreq);
1241 if (tevent_req_nterror(req, status)) {
1246 if (!NT_STATUS_IS_OK(result) &&
1247 !NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED))
1249 tevent_req_nterror(req, result);
1253 tmp_flags = state->creds->negotiate_flags;
1254 tmp_flags &= state->context->client.required_flags;
1255 if (tmp_flags != state->context->client.required_flags) {
1256 if (NT_STATUS_IS_OK(result)) {
1257 tevent_req_nterror(req, NT_STATUS_DOWNGRADE_DETECTED);
1260 tevent_req_nterror(req, result);
1264 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
1266 tmp_flags = state->context->client.proposed_flags;
1267 if ((state->current_flags == tmp_flags) &&
1268 (state->creds->negotiate_flags != tmp_flags))
1271 * lets retry with the negotiated flags
1273 state->current_flags = state->creds->negotiate_flags;
1274 netlogon_creds_cli_auth_challenge_start(req);
1278 if (!state->try_previous_nt_hash) {
1280 * we already retried, giving up...
1282 tevent_req_nterror(req, result);
1287 * lets retry with the old nt hash.
1289 state->try_previous_nt_hash = false;
1290 state->used_nt_hash = state->previous_nt_hash;
1291 state->current_flags = state->context->client.proposed_flags;
1292 netlogon_creds_cli_auth_challenge_start(req);
1296 ok = netlogon_creds_client_check(state->creds,
1297 &state->server_credential);
1299 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1303 ndr_err = ndr_push_struct_blob(&blob, state, state->creds,
1304 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
1305 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1306 status = ndr_map_error2ntstatus(ndr_err);
1307 tevent_req_nterror(req, status);
1311 data.dptr = blob.data;
1312 data.dsize = blob.length;
1314 status = dbwrap_store(state->context->db.ctx,
1315 state->context->db.key_data,
1317 TALLOC_FREE(state->locked_state);
1318 if (tevent_req_nterror(req, status)) {
1322 tevent_req_done(req);
1325 NTSTATUS netlogon_creds_cli_auth_recv(struct tevent_req *req)
1329 if (tevent_req_is_nterror(req, &status)) {
1330 tevent_req_received(req);
1334 tevent_req_received(req);
1335 return NT_STATUS_OK;
1338 NTSTATUS netlogon_creds_cli_auth(struct netlogon_creds_cli_context *context,
1339 struct dcerpc_binding_handle *b,
1340 struct samr_Password current_nt_hash,
1341 const struct samr_Password *previous_nt_hash)
1343 TALLOC_CTX *frame = talloc_stackframe();
1344 struct tevent_context *ev;
1345 struct tevent_req *req;
1346 NTSTATUS status = NT_STATUS_NO_MEMORY;
1348 ev = samba_tevent_context_init(frame);
1352 req = netlogon_creds_cli_auth_send(frame, ev, context, b,
1358 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1361 status = netlogon_creds_cli_auth_recv(req);
1367 struct netlogon_creds_cli_check_state {
1368 struct tevent_context *ev;
1369 struct netlogon_creds_cli_context *context;
1370 struct dcerpc_binding_handle *binding_handle;
1372 char *srv_name_slash;
1374 union netr_Capabilities caps;
1376 struct netlogon_creds_CredentialState *creds;
1377 struct netlogon_creds_CredentialState tmp_creds;
1378 struct netr_Authenticator req_auth;
1379 struct netr_Authenticator rep_auth;
1382 static void netlogon_creds_cli_check_cleanup(struct tevent_req *req,
1384 static void netlogon_creds_cli_check_locked(struct tevent_req *subreq);
1386 struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx,
1387 struct tevent_context *ev,
1388 struct netlogon_creds_cli_context *context,
1389 struct dcerpc_binding_handle *b)
1391 struct tevent_req *req;
1392 struct netlogon_creds_cli_check_state *state;
1393 struct tevent_req *subreq;
1394 enum dcerpc_AuthType auth_type;
1395 enum dcerpc_AuthLevel auth_level;
1397 req = tevent_req_create(mem_ctx, &state,
1398 struct netlogon_creds_cli_check_state);
1404 state->context = context;
1405 state->binding_handle = b;
1407 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
1408 context->server.computer);
1409 if (tevent_req_nomem(state->srv_name_slash, req)) {
1410 return tevent_req_post(req, ev);
1413 dcerpc_binding_handle_auth_info(state->binding_handle,
1414 &auth_type, &auth_level);
1416 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1417 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1418 return tevent_req_post(req, ev);
1421 switch (auth_level) {
1422 case DCERPC_AUTH_LEVEL_INTEGRITY:
1423 case DCERPC_AUTH_LEVEL_PRIVACY:
1426 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1427 return tevent_req_post(req, ev);
1430 subreq = netlogon_creds_cli_lock_send(state, state->ev,
1432 if (tevent_req_nomem(subreq, req)) {
1433 return tevent_req_post(req, ev);
1436 tevent_req_set_callback(subreq,
1437 netlogon_creds_cli_check_locked,
1443 static void netlogon_creds_cli_check_cleanup(struct tevent_req *req,
1446 struct netlogon_creds_cli_check_state *state =
1447 tevent_req_data(req,
1448 struct netlogon_creds_cli_check_state);
1450 if (state->creds == NULL) {
1454 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
1455 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
1456 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
1457 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
1458 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1459 TALLOC_FREE(state->creds);
1463 netlogon_creds_cli_delete(state->context, &state->creds);
1466 static void netlogon_creds_cli_check_caps(struct tevent_req *subreq);
1468 static void netlogon_creds_cli_check_locked(struct tevent_req *subreq)
1470 struct tevent_req *req =
1471 tevent_req_callback_data(subreq,
1473 struct netlogon_creds_cli_check_state *state =
1474 tevent_req_data(req,
1475 struct netlogon_creds_cli_check_state);
1478 status = netlogon_creds_cli_lock_recv(subreq, state,
1480 TALLOC_FREE(subreq);
1481 if (tevent_req_nterror(req, status)) {
1486 * we defer all callbacks in order to cleanup
1487 * the database record.
1489 tevent_req_defer_callback(req, state->ev);
1491 state->tmp_creds = *state->creds;
1492 netlogon_creds_client_authenticator(&state->tmp_creds,
1494 ZERO_STRUCT(state->rep_auth);
1496 subreq = dcerpc_netr_LogonGetCapabilities_send(state, state->ev,
1497 state->binding_handle,
1498 state->srv_name_slash,
1499 state->context->client.computer,
1504 if (tevent_req_nomem(subreq, req)) {
1505 status = NT_STATUS_NO_MEMORY;
1506 netlogon_creds_cli_check_cleanup(req, status);
1509 tevent_req_set_callback(subreq,
1510 netlogon_creds_cli_check_caps,
1514 static void netlogon_creds_cli_check_caps(struct tevent_req *subreq)
1516 struct tevent_req *req =
1517 tevent_req_callback_data(subreq,
1519 struct netlogon_creds_cli_check_state *state =
1520 tevent_req_data(req,
1521 struct netlogon_creds_cli_check_state);
1526 status = dcerpc_netr_LogonGetCapabilities_recv(subreq, state,
1528 TALLOC_FREE(subreq);
1529 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1531 * Note that the negotiated flags are already checked
1532 * for our required flags after the ServerAuthenticate3/2 call.
1534 uint32_t negotiated = state->tmp_creds.negotiate_flags;
1536 if (negotiated & NETLOGON_NEG_SUPPORTS_AES) {
1538 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1539 * already, we expect this to work!
1541 status = NT_STATUS_DOWNGRADE_DETECTED;
1542 tevent_req_nterror(req, status);
1543 netlogon_creds_cli_check_cleanup(req, status);
1547 if (negotiated & NETLOGON_NEG_STRONG_KEYS) {
1549 * If we have negotiated NETLOGON_NEG_STRONG_KEYS
1550 * we expect this to work at least as far as the
1551 * NOT_SUPPORTED error handled below!
1553 * NT 4.0 and Old Samba servers are not
1554 * allowed without "require strong key = no"
1556 status = NT_STATUS_DOWNGRADE_DETECTED;
1557 tevent_req_nterror(req, status);
1558 netlogon_creds_cli_check_cleanup(req, status);
1563 * If we not require NETLOGON_NEG_SUPPORTS_AES or
1564 * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore
1565 * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
1567 * This is needed against NT 4.0 and old Samba servers.
1569 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
1570 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
1571 * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
1572 * with the next request as the sequence number processing
1575 netlogon_creds_cli_check_cleanup(req, status);
1576 tevent_req_done(req);
1579 if (tevent_req_nterror(req, status)) {
1580 netlogon_creds_cli_check_cleanup(req, status);
1584 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
1586 * Note that the negotiated flags are already checked
1587 * for our required flags after the ServerAuthenticate3/2 call.
1589 uint32_t negotiated = state->tmp_creds.negotiate_flags;
1591 if (negotiated & NETLOGON_NEG_SUPPORTS_AES) {
1593 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1594 * already, we expect this to work!
1596 status = NT_STATUS_DOWNGRADE_DETECTED;
1597 tevent_req_nterror(req, status);
1598 netlogon_creds_cli_check_cleanup(req, status);
1603 * This is ok, the server does not support
1604 * NETLOGON_NEG_SUPPORTS_AES.
1606 * netr_LogonGetCapabilities() was
1607 * netr_LogonDummyRoutine1() before
1608 * NETLOGON_NEG_SUPPORTS_AES was invented.
1610 netlogon_creds_cli_check_cleanup(req, result);
1611 tevent_req_done(req);
1615 ok = netlogon_creds_client_check(&state->tmp_creds,
1616 &state->rep_auth.cred);
1618 status = NT_STATUS_ACCESS_DENIED;
1619 tevent_req_nterror(req, status);
1620 netlogon_creds_cli_check_cleanup(req, status);
1624 if (tevent_req_nterror(req, result)) {
1625 netlogon_creds_cli_check_cleanup(req, result);
1629 if (state->caps.server_capabilities != state->tmp_creds.negotiate_flags) {
1630 status = NT_STATUS_DOWNGRADE_DETECTED;
1631 tevent_req_nterror(req, status);
1632 netlogon_creds_cli_check_cleanup(req, status);
1637 * This is the key check that makes this check secure. If we
1638 * get OK here (rather than NOT_SUPPORTED), then the server
1639 * did support AES. If the server only proposed STRONG_KEYS
1640 * and not AES, then it should have failed with
1641 * NOT_IMPLEMENTED. We always send AES as a client, so the
1642 * server should always have returned it.
1644 if (!(state->caps.server_capabilities & NETLOGON_NEG_SUPPORTS_AES)) {
1645 status = NT_STATUS_DOWNGRADE_DETECTED;
1646 tevent_req_nterror(req, status);
1647 netlogon_creds_cli_check_cleanup(req, status);
1651 *state->creds = state->tmp_creds;
1652 status = netlogon_creds_cli_store(state->context,
1654 netlogon_creds_cli_check_cleanup(req, status);
1655 if (tevent_req_nterror(req, status)) {
1659 tevent_req_done(req);
1662 NTSTATUS netlogon_creds_cli_check_recv(struct tevent_req *req)
1666 if (tevent_req_is_nterror(req, &status)) {
1667 netlogon_creds_cli_check_cleanup(req, status);
1668 tevent_req_received(req);
1672 tevent_req_received(req);
1673 return NT_STATUS_OK;
1676 NTSTATUS netlogon_creds_cli_check(struct netlogon_creds_cli_context *context,
1677 struct dcerpc_binding_handle *b)
1679 TALLOC_CTX *frame = talloc_stackframe();
1680 struct tevent_context *ev;
1681 struct tevent_req *req;
1682 NTSTATUS status = NT_STATUS_NO_MEMORY;
1684 ev = samba_tevent_context_init(frame);
1688 req = netlogon_creds_cli_check_send(frame, ev, context, b);
1692 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1695 status = netlogon_creds_cli_check_recv(req);
1701 struct netlogon_creds_cli_ServerPasswordSet_state {
1702 struct tevent_context *ev;
1703 struct netlogon_creds_cli_context *context;
1704 struct dcerpc_binding_handle *binding_handle;
1705 uint32_t old_timeout;
1707 char *srv_name_slash;
1708 enum dcerpc_AuthType auth_type;
1709 enum dcerpc_AuthLevel auth_level;
1711 struct samr_CryptPassword samr_crypt_password;
1712 struct netr_CryptPassword netr_crypt_password;
1713 struct samr_Password samr_password;
1715 struct netlogon_creds_CredentialState *creds;
1716 struct netlogon_creds_CredentialState tmp_creds;
1717 struct netr_Authenticator req_auth;
1718 struct netr_Authenticator rep_auth;
1721 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req *req,
1723 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subreq);
1725 struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx,
1726 struct tevent_context *ev,
1727 struct netlogon_creds_cli_context *context,
1728 struct dcerpc_binding_handle *b,
1729 const char *new_password,
1730 const uint32_t *new_version)
1732 struct tevent_req *req;
1733 struct netlogon_creds_cli_ServerPasswordSet_state *state;
1734 struct tevent_req *subreq;
1737 req = tevent_req_create(mem_ctx, &state,
1738 struct netlogon_creds_cli_ServerPasswordSet_state);
1744 state->context = context;
1745 state->binding_handle = b;
1748 * netr_ServerPasswordSet
1750 E_md4hash(new_password, state->samr_password.hash);
1753 * netr_ServerPasswordSet2
1755 ok = encode_pw_buffer(state->samr_crypt_password.data,
1756 new_password, STR_UNICODE);
1758 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1759 return tevent_req_post(req, ev);
1762 if (new_version != NULL) {
1763 struct NL_PASSWORD_VERSION version;
1764 uint32_t len = IVAL(state->samr_crypt_password.data, 512);
1765 uint32_t ofs = 512 - len;
1769 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1770 return tevent_req_post(req, ev);
1774 version.ReservedField = 0;
1775 version.PasswordVersionNumber = *new_version;
1776 version.PasswordVersionPresent =
1777 NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT;
1779 p = state->samr_crypt_password.data + ofs;
1780 SIVAL(p, 0, version.ReservedField);
1781 SIVAL(p, 4, version.PasswordVersionNumber);
1782 SIVAL(p, 8, version.PasswordVersionPresent);
1785 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
1786 context->server.computer);
1787 if (tevent_req_nomem(state->srv_name_slash, req)) {
1788 return tevent_req_post(req, ev);
1791 dcerpc_binding_handle_auth_info(state->binding_handle,
1793 &state->auth_level);
1795 subreq = netlogon_creds_cli_lock_send(state, state->ev,
1797 if (tevent_req_nomem(subreq, req)) {
1798 return tevent_req_post(req, ev);
1801 tevent_req_set_callback(subreq,
1802 netlogon_creds_cli_ServerPasswordSet_locked,
1808 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req *req,
1811 struct netlogon_creds_cli_ServerPasswordSet_state *state =
1812 tevent_req_data(req,
1813 struct netlogon_creds_cli_ServerPasswordSet_state);
1815 if (state->creds == NULL) {
1819 dcerpc_binding_handle_set_timeout(state->binding_handle,
1820 state->old_timeout);
1822 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
1823 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
1824 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
1825 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
1826 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1827 TALLOC_FREE(state->creds);
1831 netlogon_creds_cli_delete(state->context, &state->creds);
1834 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq);
1836 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subreq)
1838 struct tevent_req *req =
1839 tevent_req_callback_data(subreq,
1841 struct netlogon_creds_cli_ServerPasswordSet_state *state =
1842 tevent_req_data(req,
1843 struct netlogon_creds_cli_ServerPasswordSet_state);
1846 status = netlogon_creds_cli_lock_recv(subreq, state,
1848 TALLOC_FREE(subreq);
1849 if (tevent_req_nterror(req, status)) {
1853 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
1854 switch (state->auth_level) {
1855 case DCERPC_AUTH_LEVEL_INTEGRITY:
1856 case DCERPC_AUTH_LEVEL_PRIVACY:
1859 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1863 uint32_t tmp = state->creds->negotiate_flags;
1865 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
1867 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
1868 * it should be used, which means
1869 * we had a chance to verify no downgrade
1872 * This relies on netlogon_creds_cli_check*
1873 * being called before, as first request after
1876 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1881 state->old_timeout = dcerpc_binding_handle_set_timeout(
1882 state->binding_handle, 600000);
1885 * we defer all callbacks in order to cleanup
1886 * the database record.
1888 tevent_req_defer_callback(req, state->ev);
1890 state->tmp_creds = *state->creds;
1891 netlogon_creds_client_authenticator(&state->tmp_creds,
1893 ZERO_STRUCT(state->rep_auth);
1895 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) {
1897 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1898 netlogon_creds_aes_encrypt(&state->tmp_creds,
1899 state->samr_crypt_password.data,
1902 netlogon_creds_arcfour_crypt(&state->tmp_creds,
1903 state->samr_crypt_password.data,
1907 memcpy(state->netr_crypt_password.data,
1908 state->samr_crypt_password.data, 512);
1909 state->netr_crypt_password.length =
1910 IVAL(state->samr_crypt_password.data, 512);
1912 subreq = dcerpc_netr_ServerPasswordSet2_send(state, state->ev,
1913 state->binding_handle,
1914 state->srv_name_slash,
1915 state->tmp_creds.account_name,
1916 state->tmp_creds.secure_channel_type,
1917 state->tmp_creds.computer_name,
1920 &state->netr_crypt_password);
1921 if (tevent_req_nomem(subreq, req)) {
1922 status = NT_STATUS_NO_MEMORY;
1923 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1927 netlogon_creds_des_encrypt(&state->tmp_creds,
1928 &state->samr_password);
1930 subreq = dcerpc_netr_ServerPasswordSet_send(state, state->ev,
1931 state->binding_handle,
1932 state->srv_name_slash,
1933 state->tmp_creds.account_name,
1934 state->tmp_creds.secure_channel_type,
1935 state->tmp_creds.computer_name,
1938 &state->samr_password);
1939 if (tevent_req_nomem(subreq, req)) {
1940 status = NT_STATUS_NO_MEMORY;
1941 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1946 tevent_req_set_callback(subreq,
1947 netlogon_creds_cli_ServerPasswordSet_done,
1951 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq)
1953 struct tevent_req *req =
1954 tevent_req_callback_data(subreq,
1956 struct netlogon_creds_cli_ServerPasswordSet_state *state =
1957 tevent_req_data(req,
1958 struct netlogon_creds_cli_ServerPasswordSet_state);
1963 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) {
1964 status = dcerpc_netr_ServerPasswordSet2_recv(subreq, state,
1966 TALLOC_FREE(subreq);
1967 if (tevent_req_nterror(req, status)) {
1968 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1972 status = dcerpc_netr_ServerPasswordSet_recv(subreq, state,
1974 TALLOC_FREE(subreq);
1975 if (tevent_req_nterror(req, status)) {
1976 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1981 ok = netlogon_creds_client_check(&state->tmp_creds,
1982 &state->rep_auth.cred);
1984 status = NT_STATUS_ACCESS_DENIED;
1985 tevent_req_nterror(req, status);
1986 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1990 if (tevent_req_nterror(req, result)) {
1991 netlogon_creds_cli_ServerPasswordSet_cleanup(req, result);
1995 dcerpc_binding_handle_set_timeout(state->binding_handle,
1996 state->old_timeout);
1998 *state->creds = state->tmp_creds;
1999 status = netlogon_creds_cli_store(state->context,
2001 if (tevent_req_nterror(req, status)) {
2002 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2006 tevent_req_done(req);
2009 NTSTATUS netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req *req)
2013 if (tevent_req_is_nterror(req, &status)) {
2014 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2015 tevent_req_received(req);
2019 tevent_req_received(req);
2020 return NT_STATUS_OK;
2023 NTSTATUS netlogon_creds_cli_ServerPasswordSet(
2024 struct netlogon_creds_cli_context *context,
2025 struct dcerpc_binding_handle *b,
2026 const char *new_password,
2027 const uint32_t *new_version)
2029 TALLOC_CTX *frame = talloc_stackframe();
2030 struct tevent_context *ev;
2031 struct tevent_req *req;
2032 NTSTATUS status = NT_STATUS_NO_MEMORY;
2034 ev = samba_tevent_context_init(frame);
2038 req = netlogon_creds_cli_ServerPasswordSet_send(frame, ev, context, b,
2044 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2047 status = netlogon_creds_cli_ServerPasswordSet_recv(req);
2053 struct netlogon_creds_cli_LogonSamLogon_state {
2054 struct tevent_context *ev;
2055 struct netlogon_creds_cli_context *context;
2056 struct dcerpc_binding_handle *binding_handle;
2058 char *srv_name_slash;
2060 enum netr_LogonInfoClass logon_level;
2061 const union netr_LogonLevel *const_logon;
2062 union netr_LogonLevel *logon;
2065 uint16_t validation_level;
2066 union netr_Validation *validation;
2067 uint8_t authoritative;
2070 * do we need encryption at the application layer?
2074 bool try_validation6;
2077 * the read only credentials before we started the operation
2078 * used for netr_LogonSamLogonEx() if required (validation_level = 3).
2080 struct netlogon_creds_CredentialState *ro_creds;
2083 * The (locked) credentials used for the credential chain
2084 * used for netr_LogonSamLogonWithFlags() or
2085 * netr_LogonSamLogonWith().
2087 struct netlogon_creds_CredentialState *lk_creds;
2090 * While we have locked the global credentials (lk_creds above)
2091 * we operate an a temporary copy, because a server
2092 * may not support netr_LogonSamLogonWithFlags() and
2093 * didn't process our netr_Authenticator, so we need to
2094 * restart from lk_creds.
2096 struct netlogon_creds_CredentialState tmp_creds;
2097 struct netr_Authenticator req_auth;
2098 struct netr_Authenticator rep_auth;
2101 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req);
2102 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req *req,
2105 struct tevent_req *netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX *mem_ctx,
2106 struct tevent_context *ev,
2107 struct netlogon_creds_cli_context *context,
2108 struct dcerpc_binding_handle *b,
2109 enum netr_LogonInfoClass logon_level,
2110 const union netr_LogonLevel *logon,
2113 struct tevent_req *req;
2114 struct netlogon_creds_cli_LogonSamLogon_state *state;
2116 req = tevent_req_create(mem_ctx, &state,
2117 struct netlogon_creds_cli_LogonSamLogon_state);
2123 state->context = context;
2124 state->binding_handle = b;
2126 state->logon_level = logon_level;
2127 state->const_logon = logon;
2128 state->flags = flags;
2130 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
2131 context->server.computer);
2132 if (tevent_req_nomem(state->srv_name_slash, req)) {
2133 return tevent_req_post(req, ev);
2136 switch (logon_level) {
2137 case NetlogonInteractiveInformation:
2138 case NetlogonInteractiveTransitiveInformation:
2139 case NetlogonServiceInformation:
2140 case NetlogonServiceTransitiveInformation:
2141 case NetlogonGenericInformation:
2142 state->user_encrypt = true;
2145 case NetlogonNetworkInformation:
2146 case NetlogonNetworkTransitiveInformation:
2150 state->validation = talloc_zero(state, union netr_Validation);
2151 if (tevent_req_nomem(state->validation, req)) {
2152 return tevent_req_post(req, ev);
2155 netlogon_creds_cli_LogonSamLogon_start(req);
2156 if (!tevent_req_is_in_progress(req)) {
2157 return tevent_req_post(req, ev);
2161 * we defer all callbacks in order to cleanup
2162 * the database record.
2164 tevent_req_defer_callback(req, state->ev);
2168 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req *req,
2171 struct netlogon_creds_cli_LogonSamLogon_state *state =
2172 tevent_req_data(req,
2173 struct netlogon_creds_cli_LogonSamLogon_state);
2175 if (state->lk_creds == NULL) {
2179 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2181 * This is a hack to recover from a bug in old
2182 * Samba servers, when LogonSamLogonEx() fails:
2184 * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
2186 * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2188 * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE,
2189 * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR
2190 * If the sign/seal check fails.
2192 * In that case we need to cleanup the netlogon session.
2194 * It's the job of the caller to disconnect the current
2195 * connection, if netlogon_creds_cli_LogonSamLogon()
2196 * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2198 if (!state->context->server.try_logon_with) {
2199 status = NT_STATUS_NETWORK_ACCESS_DENIED;
2203 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
2204 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
2205 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
2206 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
2207 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
2208 TALLOC_FREE(state->lk_creds);
2212 netlogon_creds_cli_delete(state->context, &state->lk_creds);
2215 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq);
2217 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req)
2219 struct netlogon_creds_cli_LogonSamLogon_state *state =
2220 tevent_req_data(req,
2221 struct netlogon_creds_cli_LogonSamLogon_state);
2222 struct tevent_req *subreq;
2224 enum dcerpc_AuthType auth_type;
2225 enum dcerpc_AuthLevel auth_level;
2227 TALLOC_FREE(state->ro_creds);
2228 TALLOC_FREE(state->logon);
2229 ZERO_STRUCTP(state->validation);
2231 dcerpc_binding_handle_auth_info(state->binding_handle,
2232 &auth_type, &auth_level);
2234 state->try_logon_ex = state->context->server.try_logon_ex;
2235 state->try_validation6 = state->context->server.try_validation6;
2237 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
2238 state->try_logon_ex = false;
2241 if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
2242 state->try_validation6 = false;
2245 if (state->try_logon_ex) {
2246 if (state->try_validation6) {
2247 state->validation_level = 6;
2249 state->validation_level = 3;
2250 state->user_encrypt = true;
2253 state->logon = netlogon_creds_shallow_copy_logon(state,
2255 state->const_logon);
2256 if (tevent_req_nomem(state->logon, req)) {
2257 status = NT_STATUS_NO_MEMORY;
2258 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2262 if (state->user_encrypt) {
2263 status = netlogon_creds_cli_get(state->context,
2266 if (!NT_STATUS_IS_OK(status)) {
2267 status = NT_STATUS_ACCESS_DENIED;
2268 tevent_req_nterror(req, status);
2269 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2273 netlogon_creds_encrypt_samlogon_logon(state->ro_creds,
2278 subreq = dcerpc_netr_LogonSamLogonEx_send(state, state->ev,
2279 state->binding_handle,
2280 state->srv_name_slash,
2281 state->context->client.computer,
2284 state->validation_level,
2286 &state->authoritative,
2288 if (tevent_req_nomem(subreq, req)) {
2289 status = NT_STATUS_NO_MEMORY;
2290 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2293 tevent_req_set_callback(subreq,
2294 netlogon_creds_cli_LogonSamLogon_done,
2299 if (state->lk_creds == NULL) {
2300 subreq = netlogon_creds_cli_lock_send(state, state->ev,
2302 if (tevent_req_nomem(subreq, req)) {
2303 status = NT_STATUS_NO_MEMORY;
2304 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2307 tevent_req_set_callback(subreq,
2308 netlogon_creds_cli_LogonSamLogon_done,
2313 state->tmp_creds = *state->lk_creds;
2314 netlogon_creds_client_authenticator(&state->tmp_creds,
2316 ZERO_STRUCT(state->rep_auth);
2318 state->logon = netlogon_creds_shallow_copy_logon(state,
2320 state->const_logon);
2321 if (tevent_req_nomem(state->logon, req)) {
2322 status = NT_STATUS_NO_MEMORY;
2323 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2327 netlogon_creds_encrypt_samlogon_logon(&state->tmp_creds,
2331 state->validation_level = 3;
2333 if (state->context->server.try_logon_with) {
2334 subreq = dcerpc_netr_LogonSamLogonWithFlags_send(state, state->ev,
2335 state->binding_handle,
2336 state->srv_name_slash,
2337 state->context->client.computer,
2342 state->validation_level,
2344 &state->authoritative,
2346 if (tevent_req_nomem(subreq, req)) {
2347 status = NT_STATUS_NO_MEMORY;
2348 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2354 subreq = dcerpc_netr_LogonSamLogon_send(state, state->ev,
2355 state->binding_handle,
2356 state->srv_name_slash,
2357 state->context->client.computer,
2362 state->validation_level,
2364 &state->authoritative);
2365 if (tevent_req_nomem(subreq, req)) {
2366 status = NT_STATUS_NO_MEMORY;
2367 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2372 tevent_req_set_callback(subreq,
2373 netlogon_creds_cli_LogonSamLogon_done,
2377 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq)
2379 struct tevent_req *req =
2380 tevent_req_callback_data(subreq,
2382 struct netlogon_creds_cli_LogonSamLogon_state *state =
2383 tevent_req_data(req,
2384 struct netlogon_creds_cli_LogonSamLogon_state);
2389 if (state->try_logon_ex) {
2390 status = dcerpc_netr_LogonSamLogonEx_recv(subreq,
2393 TALLOC_FREE(subreq);
2394 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2395 state->context->server.try_validation6 = false;
2396 state->context->server.try_logon_ex = false;
2397 netlogon_creds_cli_LogonSamLogon_start(req);
2400 if (tevent_req_nterror(req, status)) {
2401 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2405 if ((state->validation_level == 6) &&
2406 (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS) ||
2407 NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PARAMETER) ||
2408 NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL)))
2410 state->context->server.try_validation6 = false;
2411 netlogon_creds_cli_LogonSamLogon_start(req);
2415 if (tevent_req_nterror(req, result)) {
2416 netlogon_creds_cli_LogonSamLogon_cleanup(req, result);
2420 if (state->ro_creds == NULL) {
2421 tevent_req_done(req);
2425 ok = netlogon_creds_cli_validate(state->context, state->ro_creds);
2428 * We got a race, lets retry with on authenticator
2431 * netlogon_creds_cli_LogonSamLogon_start()
2432 * will TALLOC_FREE(state->ro_creds);
2434 state->try_logon_ex = false;
2435 netlogon_creds_cli_LogonSamLogon_start(req);
2439 netlogon_creds_decrypt_samlogon_validation(state->ro_creds,
2440 state->validation_level,
2443 tevent_req_done(req);
2447 if (state->lk_creds == NULL) {
2448 status = netlogon_creds_cli_lock_recv(subreq, state,
2450 TALLOC_FREE(subreq);
2451 if (tevent_req_nterror(req, status)) {
2452 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2456 netlogon_creds_cli_LogonSamLogon_start(req);
2460 if (state->context->server.try_logon_with) {
2461 status = dcerpc_netr_LogonSamLogonWithFlags_recv(subreq,
2464 TALLOC_FREE(subreq);
2465 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2466 state->context->server.try_logon_with = false;
2467 netlogon_creds_cli_LogonSamLogon_start(req);
2470 if (tevent_req_nterror(req, status)) {
2471 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2475 status = dcerpc_netr_LogonSamLogon_recv(subreq,
2478 TALLOC_FREE(subreq);
2479 if (tevent_req_nterror(req, status)) {
2480 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2485 ok = netlogon_creds_client_check(&state->tmp_creds,
2486 &state->rep_auth.cred);
2488 status = NT_STATUS_ACCESS_DENIED;
2489 tevent_req_nterror(req, status);
2490 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2494 *state->lk_creds = state->tmp_creds;
2495 status = netlogon_creds_cli_store(state->context,
2497 if (tevent_req_nterror(req, status)) {
2498 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2502 if (tevent_req_nterror(req, result)) {
2503 netlogon_creds_cli_LogonSamLogon_cleanup(req, result);
2507 netlogon_creds_decrypt_samlogon_validation(&state->tmp_creds,
2508 state->validation_level,
2511 tevent_req_done(req);
2514 NTSTATUS netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req *req,
2515 TALLOC_CTX *mem_ctx,
2516 uint16_t *validation_level,
2517 union netr_Validation **validation,
2518 uint8_t *authoritative,
2521 struct netlogon_creds_cli_LogonSamLogon_state *state =
2522 tevent_req_data(req,
2523 struct netlogon_creds_cli_LogonSamLogon_state);
2526 /* authoritative is also returned on error */
2527 *authoritative = state->authoritative;
2529 if (tevent_req_is_nterror(req, &status)) {
2530 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2531 tevent_req_received(req);
2535 *validation_level = state->validation_level;
2536 *validation = talloc_move(mem_ctx, &state->validation);
2537 *flags = state->flags;
2539 tevent_req_received(req);
2540 return NT_STATUS_OK;
2543 NTSTATUS netlogon_creds_cli_LogonSamLogon(
2544 struct netlogon_creds_cli_context *context,
2545 struct dcerpc_binding_handle *b,
2546 enum netr_LogonInfoClass logon_level,
2547 const union netr_LogonLevel *logon,
2548 TALLOC_CTX *mem_ctx,
2549 uint16_t *validation_level,
2550 union netr_Validation **validation,
2551 uint8_t *authoritative,
2554 TALLOC_CTX *frame = talloc_stackframe();
2555 struct tevent_context *ev;
2556 struct tevent_req *req;
2557 NTSTATUS status = NT_STATUS_NO_MEMORY;
2559 ev = samba_tevent_context_init(frame);
2563 req = netlogon_creds_cli_LogonSamLogon_send(frame, ev, context, b,
2569 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2572 status = netlogon_creds_cli_LogonSamLogon_recv(req, mem_ctx,
2582 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state {
2583 struct tevent_context *ev;
2584 struct netlogon_creds_cli_context *context;
2585 struct dcerpc_binding_handle *binding_handle;
2587 char *srv_name_slash;
2588 enum dcerpc_AuthType auth_type;
2589 enum dcerpc_AuthLevel auth_level;
2591 const char *site_name;
2593 struct NL_DNS_NAME_INFO_ARRAY *dns_names;
2595 struct netlogon_creds_CredentialState *creds;
2596 struct netlogon_creds_CredentialState tmp_creds;
2597 struct netr_Authenticator req_auth;
2598 struct netr_Authenticator rep_auth;
2601 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req *req,
2603 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req *subreq);
2605 struct tevent_req *netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(TALLOC_CTX *mem_ctx,
2606 struct tevent_context *ev,
2607 struct netlogon_creds_cli_context *context,
2608 struct dcerpc_binding_handle *b,
2609 const char *site_name,
2611 struct NL_DNS_NAME_INFO_ARRAY *dns_names)
2613 struct tevent_req *req;
2614 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state;
2615 struct tevent_req *subreq;
2617 req = tevent_req_create(mem_ctx, &state,
2618 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2624 state->context = context;
2625 state->binding_handle = b;
2627 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
2628 context->server.computer);
2629 if (tevent_req_nomem(state->srv_name_slash, req)) {
2630 return tevent_req_post(req, ev);
2633 state->site_name = site_name;
2634 state->dns_ttl = dns_ttl;
2635 state->dns_names = dns_names;
2637 dcerpc_binding_handle_auth_info(state->binding_handle,
2639 &state->auth_level);
2641 subreq = netlogon_creds_cli_lock_send(state, state->ev,
2643 if (tevent_req_nomem(subreq, req)) {
2644 return tevent_req_post(req, ev);
2647 tevent_req_set_callback(subreq,
2648 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked,
2654 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req *req,
2657 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
2658 tevent_req_data(req,
2659 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2661 if (state->creds == NULL) {
2665 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
2666 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
2667 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
2668 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
2669 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
2670 TALLOC_FREE(state->creds);
2674 netlogon_creds_cli_delete(state->context, &state->creds);
2677 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req *subreq);
2679 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req *subreq)
2681 struct tevent_req *req =
2682 tevent_req_callback_data(subreq,
2684 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
2685 tevent_req_data(req,
2686 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2689 status = netlogon_creds_cli_lock_recv(subreq, state,
2691 TALLOC_FREE(subreq);
2692 if (tevent_req_nterror(req, status)) {
2696 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
2697 switch (state->auth_level) {
2698 case DCERPC_AUTH_LEVEL_INTEGRITY:
2699 case DCERPC_AUTH_LEVEL_PRIVACY:
2702 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2706 uint32_t tmp = state->creds->negotiate_flags;
2708 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
2710 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
2711 * it should be used, which means
2712 * we had a chance to verify no downgrade
2715 * This relies on netlogon_creds_cli_check*
2716 * being called before, as first request after
2719 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2725 * we defer all callbacks in order to cleanup
2726 * the database record.
2728 tevent_req_defer_callback(req, state->ev);
2730 state->tmp_creds = *state->creds;
2731 netlogon_creds_client_authenticator(&state->tmp_creds,
2733 ZERO_STRUCT(state->rep_auth);
2735 subreq = dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_send(state, state->ev,
2736 state->binding_handle,
2737 state->srv_name_slash,
2738 state->tmp_creds.computer_name,
2744 if (tevent_req_nomem(subreq, req)) {
2745 status = NT_STATUS_NO_MEMORY;
2746 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2750 tevent_req_set_callback(subreq,
2751 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done,
2755 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req *subreq)
2757 struct tevent_req *req =
2758 tevent_req_callback_data(subreq,
2760 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
2761 tevent_req_data(req,
2762 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2768 * We use state->dns_names as the memory context, as this is
2769 * the only in/out variable and it has been overwritten by the
2770 * out parameter from the server.
2772 * We need to preserve the return value until the caller can use it.
2774 status = dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_recv(subreq, state->dns_names,
2776 TALLOC_FREE(subreq);
2777 if (tevent_req_nterror(req, status)) {
2778 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2782 ok = netlogon_creds_client_check(&state->tmp_creds,
2783 &state->rep_auth.cred);
2785 status = NT_STATUS_ACCESS_DENIED;
2786 tevent_req_nterror(req, status);
2787 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2791 if (tevent_req_nterror(req, result)) {
2792 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, result);
2796 *state->creds = state->tmp_creds;
2797 status = netlogon_creds_cli_store(state->context,
2799 if (tevent_req_nterror(req, status)) {
2800 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2804 tevent_req_done(req);
2807 NTSTATUS netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(struct tevent_req *req)
2811 if (tevent_req_is_nterror(req, &status)) {
2812 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2813 tevent_req_received(req);
2817 tevent_req_received(req);
2818 return NT_STATUS_OK;
2821 NTSTATUS netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(
2822 struct netlogon_creds_cli_context *context,
2823 struct dcerpc_binding_handle *b,
2824 const char *site_name,
2826 struct NL_DNS_NAME_INFO_ARRAY *dns_names)
2828 TALLOC_CTX *frame = talloc_stackframe();
2829 struct tevent_context *ev;
2830 struct tevent_req *req;
2831 NTSTATUS status = NT_STATUS_NO_MEMORY;
2833 ev = samba_tevent_context_init(frame);
2837 req = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(frame, ev, context, b,
2844 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2847 status = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(req);
2853 struct netlogon_creds_cli_ServerGetTrustInfo_state {
2854 struct tevent_context *ev;
2855 struct netlogon_creds_cli_context *context;
2856 struct dcerpc_binding_handle *binding_handle;
2858 char *srv_name_slash;
2859 enum dcerpc_AuthType auth_type;
2860 enum dcerpc_AuthLevel auth_level;
2862 struct samr_Password new_owf_password;
2863 struct samr_Password old_owf_password;
2864 struct netr_TrustInfo *trust_info;
2866 struct netlogon_creds_CredentialState *creds;
2867 struct netlogon_creds_CredentialState tmp_creds;
2868 struct netr_Authenticator req_auth;
2869 struct netr_Authenticator rep_auth;
2872 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req *req,
2874 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req *subreq);
2876 struct tevent_req *netlogon_creds_cli_ServerGetTrustInfo_send(TALLOC_CTX *mem_ctx,
2877 struct tevent_context *ev,
2878 struct netlogon_creds_cli_context *context,
2879 struct dcerpc_binding_handle *b)
2881 struct tevent_req *req;
2882 struct netlogon_creds_cli_ServerGetTrustInfo_state *state;
2883 struct tevent_req *subreq;
2885 req = tevent_req_create(mem_ctx, &state,
2886 struct netlogon_creds_cli_ServerGetTrustInfo_state);
2892 state->context = context;
2893 state->binding_handle = b;
2895 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
2896 context->server.computer);
2897 if (tevent_req_nomem(state->srv_name_slash, req)) {
2898 return tevent_req_post(req, ev);
2901 dcerpc_binding_handle_auth_info(state->binding_handle,
2903 &state->auth_level);
2905 subreq = netlogon_creds_cli_lock_send(state, state->ev,
2907 if (tevent_req_nomem(subreq, req)) {
2908 return tevent_req_post(req, ev);
2911 tevent_req_set_callback(subreq,
2912 netlogon_creds_cli_ServerGetTrustInfo_locked,
2918 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req *req,
2921 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
2922 tevent_req_data(req,
2923 struct netlogon_creds_cli_ServerGetTrustInfo_state);
2925 if (state->creds == NULL) {
2929 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
2930 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
2931 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
2932 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
2933 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
2934 TALLOC_FREE(state->creds);
2938 netlogon_creds_cli_delete(state->context, &state->creds);
2941 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req *subreq);
2943 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req *subreq)
2945 struct tevent_req *req =
2946 tevent_req_callback_data(subreq,
2948 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
2949 tevent_req_data(req,
2950 struct netlogon_creds_cli_ServerGetTrustInfo_state);
2953 status = netlogon_creds_cli_lock_recv(subreq, state,
2955 TALLOC_FREE(subreq);
2956 if (tevent_req_nterror(req, status)) {
2960 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
2961 switch (state->auth_level) {
2962 case DCERPC_AUTH_LEVEL_PRIVACY:
2965 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2969 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2974 * we defer all callbacks in order to cleanup
2975 * the database record.
2977 tevent_req_defer_callback(req, state->ev);
2979 state->tmp_creds = *state->creds;
2980 netlogon_creds_client_authenticator(&state->tmp_creds,
2982 ZERO_STRUCT(state->rep_auth);
2984 subreq = dcerpc_netr_ServerGetTrustInfo_send(state, state->ev,
2985 state->binding_handle,
2986 state->srv_name_slash,
2987 state->tmp_creds.account_name,
2988 state->tmp_creds.secure_channel_type,
2989 state->tmp_creds.computer_name,
2992 &state->new_owf_password,
2993 &state->old_owf_password,
2994 &state->trust_info);
2995 if (tevent_req_nomem(subreq, req)) {
2996 status = NT_STATUS_NO_MEMORY;
2997 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3001 tevent_req_set_callback(subreq,
3002 netlogon_creds_cli_ServerGetTrustInfo_done,
3006 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req *subreq)
3008 struct tevent_req *req =
3009 tevent_req_callback_data(subreq,
3011 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
3012 tevent_req_data(req,
3013 struct netlogon_creds_cli_ServerGetTrustInfo_state);
3016 const struct samr_Password zero = {};
3021 * We use state->dns_names as the memory context, as this is
3022 * the only in/out variable and it has been overwritten by the
3023 * out parameter from the server.
3025 * We need to preserve the return value until the caller can use it.
3027 status = dcerpc_netr_ServerGetTrustInfo_recv(subreq, state, &result);
3028 TALLOC_FREE(subreq);
3029 if (tevent_req_nterror(req, status)) {
3030 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3034 ok = netlogon_creds_client_check(&state->tmp_creds,
3035 &state->rep_auth.cred);
3037 status = NT_STATUS_ACCESS_DENIED;
3038 tevent_req_nterror(req, status);
3039 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3043 if (tevent_req_nterror(req, result)) {
3044 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, result);
3048 cmp = memcmp(state->new_owf_password.hash,
3049 zero.hash, sizeof(zero.hash));
3051 netlogon_creds_des_decrypt(&state->tmp_creds,
3052 &state->new_owf_password);
3054 cmp = memcmp(state->old_owf_password.hash,
3055 zero.hash, sizeof(zero.hash));
3057 netlogon_creds_des_decrypt(&state->tmp_creds,
3058 &state->old_owf_password);
3061 *state->creds = state->tmp_creds;
3062 status = netlogon_creds_cli_store(state->context,
3064 if (tevent_req_nterror(req, status)) {
3065 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3069 tevent_req_done(req);
3072 NTSTATUS netlogon_creds_cli_ServerGetTrustInfo_recv(struct tevent_req *req,
3073 TALLOC_CTX *mem_ctx,
3074 struct samr_Password *new_owf_password,
3075 struct samr_Password *old_owf_password,
3076 struct netr_TrustInfo **trust_info)
3078 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
3079 tevent_req_data(req,
3080 struct netlogon_creds_cli_ServerGetTrustInfo_state);
3083 if (tevent_req_is_nterror(req, &status)) {
3084 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3085 tevent_req_received(req);
3089 if (new_owf_password != NULL) {
3090 *new_owf_password = state->new_owf_password;
3092 if (old_owf_password != NULL) {
3093 *old_owf_password = state->old_owf_password;
3095 if (trust_info != NULL) {
3096 *trust_info = talloc_move(mem_ctx, &state->trust_info);
3099 tevent_req_received(req);
3100 return NT_STATUS_OK;
3103 NTSTATUS netlogon_creds_cli_ServerGetTrustInfo(
3104 struct netlogon_creds_cli_context *context,
3105 struct dcerpc_binding_handle *b,
3106 TALLOC_CTX *mem_ctx,
3107 struct samr_Password *new_owf_password,
3108 struct samr_Password *old_owf_password,
3109 struct netr_TrustInfo **trust_info)
3111 TALLOC_CTX *frame = talloc_stackframe();
3112 struct tevent_context *ev;
3113 struct tevent_req *req;
3114 NTSTATUS status = NT_STATUS_NO_MEMORY;
3116 ev = samba_tevent_context_init(frame);
3120 req = netlogon_creds_cli_ServerGetTrustInfo_send(frame, ev, context, b);
3124 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3127 status = netlogon_creds_cli_ServerGetTrustInfo_recv(req,
3137 struct netlogon_creds_cli_GetForestTrustInformation_state {
3138 struct tevent_context *ev;
3139 struct netlogon_creds_cli_context *context;
3140 struct dcerpc_binding_handle *binding_handle;
3142 char *srv_name_slash;
3143 enum dcerpc_AuthType auth_type;
3144 enum dcerpc_AuthLevel auth_level;
3147 struct lsa_ForestTrustInformation *forest_trust_info;
3149 struct netlogon_creds_CredentialState *creds;
3150 struct netlogon_creds_CredentialState tmp_creds;
3151 struct netr_Authenticator req_auth;
3152 struct netr_Authenticator rep_auth;
3155 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req *req,
3157 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req *subreq);
3159 struct tevent_req *netlogon_creds_cli_GetForestTrustInformation_send(TALLOC_CTX *mem_ctx,
3160 struct tevent_context *ev,
3161 struct netlogon_creds_cli_context *context,
3162 struct dcerpc_binding_handle *b)
3164 struct tevent_req *req;
3165 struct netlogon_creds_cli_GetForestTrustInformation_state *state;
3166 struct tevent_req *subreq;
3168 req = tevent_req_create(mem_ctx, &state,
3169 struct netlogon_creds_cli_GetForestTrustInformation_state);
3175 state->context = context;
3176 state->binding_handle = b;
3178 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
3179 context->server.computer);
3180 if (tevent_req_nomem(state->srv_name_slash, req)) {
3181 return tevent_req_post(req, ev);
3186 dcerpc_binding_handle_auth_info(state->binding_handle,
3188 &state->auth_level);
3190 subreq = netlogon_creds_cli_lock_send(state, state->ev,
3192 if (tevent_req_nomem(subreq, req)) {
3193 return tevent_req_post(req, ev);
3196 tevent_req_set_callback(subreq,
3197 netlogon_creds_cli_GetForestTrustInformation_locked,
3203 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req *req,
3206 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3207 tevent_req_data(req,
3208 struct netlogon_creds_cli_GetForestTrustInformation_state);
3210 if (state->creds == NULL) {
3214 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
3215 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
3216 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
3217 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
3218 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
3219 TALLOC_FREE(state->creds);
3223 netlogon_creds_cli_delete(state->context, &state->creds);
3226 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req *subreq);
3228 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req *subreq)
3230 struct tevent_req *req =
3231 tevent_req_callback_data(subreq,
3233 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3234 tevent_req_data(req,
3235 struct netlogon_creds_cli_GetForestTrustInformation_state);
3238 status = netlogon_creds_cli_lock_recv(subreq, state,
3240 TALLOC_FREE(subreq);
3241 if (tevent_req_nterror(req, status)) {
3245 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
3246 switch (state->auth_level) {
3247 case DCERPC_AUTH_LEVEL_INTEGRITY:
3248 case DCERPC_AUTH_LEVEL_PRIVACY:
3251 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3255 uint32_t tmp = state->creds->negotiate_flags;
3257 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
3259 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3260 * it should be used, which means
3261 * we had a chance to verify no downgrade
3264 * This relies on netlogon_creds_cli_check*
3265 * being called before, as first request after
3268 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3274 * we defer all callbacks in order to cleanup
3275 * the database record.
3277 tevent_req_defer_callback(req, state->ev);
3279 state->tmp_creds = *state->creds;
3280 netlogon_creds_client_authenticator(&state->tmp_creds,
3282 ZERO_STRUCT(state->rep_auth);
3284 subreq = dcerpc_netr_GetForestTrustInformation_send(state, state->ev,
3285 state->binding_handle,
3286 state->srv_name_slash,
3287 state->tmp_creds.computer_name,
3291 &state->forest_trust_info);
3292 if (tevent_req_nomem(subreq, req)) {
3293 status = NT_STATUS_NO_MEMORY;
3294 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3298 tevent_req_set_callback(subreq,
3299 netlogon_creds_cli_GetForestTrustInformation_done,
3303 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req *subreq)
3305 struct tevent_req *req =
3306 tevent_req_callback_data(subreq,
3308 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3309 tevent_req_data(req,
3310 struct netlogon_creds_cli_GetForestTrustInformation_state);
3316 * We use state->dns_names as the memory context, as this is
3317 * the only in/out variable and it has been overwritten by the
3318 * out parameter from the server.
3320 * We need to preserve the return value until the caller can use it.
3322 status = dcerpc_netr_GetForestTrustInformation_recv(subreq, state, &result);
3323 TALLOC_FREE(subreq);
3324 if (tevent_req_nterror(req, status)) {
3325 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3329 ok = netlogon_creds_client_check(&state->tmp_creds,
3330 &state->rep_auth.cred);
3332 status = NT_STATUS_ACCESS_DENIED;
3333 tevent_req_nterror(req, status);
3334 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3338 if (tevent_req_nterror(req, result)) {
3339 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, result);
3343 *state->creds = state->tmp_creds;
3344 status = netlogon_creds_cli_store(state->context,
3346 if (tevent_req_nterror(req, status)) {
3347 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3351 tevent_req_done(req);
3354 NTSTATUS netlogon_creds_cli_GetForestTrustInformation_recv(struct tevent_req *req,
3355 TALLOC_CTX *mem_ctx,
3356 struct lsa_ForestTrustInformation **forest_trust_info)
3358 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3359 tevent_req_data(req,
3360 struct netlogon_creds_cli_GetForestTrustInformation_state);
3363 if (tevent_req_is_nterror(req, &status)) {
3364 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3365 tevent_req_received(req);
3369 *forest_trust_info = talloc_move(mem_ctx, &state->forest_trust_info);
3371 tevent_req_received(req);
3372 return NT_STATUS_OK;
3375 NTSTATUS netlogon_creds_cli_GetForestTrustInformation(
3376 struct netlogon_creds_cli_context *context,
3377 struct dcerpc_binding_handle *b,
3378 TALLOC_CTX *mem_ctx,
3379 struct lsa_ForestTrustInformation **forest_trust_info)
3381 TALLOC_CTX *frame = talloc_stackframe();
3382 struct tevent_context *ev;
3383 struct tevent_req *req;
3384 NTSTATUS status = NT_STATUS_NO_MEMORY;
3386 ev = samba_tevent_context_init(frame);
3390 req = netlogon_creds_cli_GetForestTrustInformation_send(frame, ev, context, b);
3394 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3397 status = netlogon_creds_cli_GetForestTrustInformation_recv(req,