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 "netlogon_creds_cli.h"
36 struct netlogon_creds_cli_context {
40 uint32_t proposed_flags;
41 uint32_t required_flags;
42 enum netr_SchannelType type;
47 const char *netbios_domain;
48 uint32_t cached_flags;
57 struct db_context *ctx;
58 struct g_lock_ctx *g_ctx;
62 static NTSTATUS netlogon_creds_cli_context_common(
63 const char *client_computer,
64 const char *client_account,
65 enum netr_SchannelType type,
66 uint32_t proposed_flags,
67 uint32_t required_flags,
68 const char *server_computer,
69 const char *server_netbios_domain,
71 struct netlogon_creds_cli_context **_context)
73 struct netlogon_creds_cli_context *context = NULL;
77 context = talloc_zero(mem_ctx, struct netlogon_creds_cli_context);
78 if (context == NULL) {
79 return NT_STATUS_NO_MEMORY;
82 context->client.computer = talloc_strdup(context, client_computer);
83 if (context->client.computer == NULL) {
85 return NT_STATUS_NO_MEMORY;
88 context->client.account = talloc_strdup(context, client_account);
89 if (context->client.account == NULL) {
91 return NT_STATUS_NO_MEMORY;
94 context->client.proposed_flags = proposed_flags;
95 context->client.required_flags = required_flags;
96 context->client.type = type;
98 context->server.computer = talloc_strdup(context, server_computer);
99 if (context->server.computer == NULL) {
100 talloc_free(context);
101 return NT_STATUS_NO_MEMORY;
104 context->server.netbios_domain = talloc_strdup(context, server_netbios_domain);
105 if (context->server.netbios_domain == NULL) {
106 talloc_free(context);
107 return NT_STATUS_NO_MEMORY;
110 context->db.key_name = talloc_asprintf(context, "CLI[%s/%s]/SRV[%s/%s]",
114 server_netbios_domain);
115 if (context->db.key_name == NULL) {
116 talloc_free(context);
117 return NT_STATUS_NO_MEMORY;
120 context->db.key_data = string_term_tdb_data(context->db.key_name);
126 NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx,
127 const char *client_account,
128 enum netr_SchannelType type,
129 const char *server_computer,
130 const char *server_netbios_domain,
132 struct netlogon_creds_cli_context **_context)
134 static struct db_context *global_db = NULL;
137 struct netlogon_creds_cli_context *context = NULL;
138 const char *client_computer;
139 uint32_t proposed_flags;
140 uint32_t required_flags = 0;
141 bool reject_md5_servers = false;
142 bool require_strong_key = false;
143 int require_sign_or_seal = lpcfg_client_schannel(lp_ctx);
147 client_computer = lpcfg_netbios_name(lp_ctx);
149 //TODO: add lpcfp_reject_md5_servers()
150 reject_md5_servers = lpcfg_parm_bool(lp_ctx, NULL,
152 "reject md5 servers",
155 * allow overwrite per domain
156 * reject md5 servers:<netbios_domain>
158 reject_md5_servers = lpcfg_parm_bool(lp_ctx, NULL,
159 "reject md5 servers",
160 server_netbios_domain,
163 //TODO: add lpcfp_require_strong_key()
164 require_strong_key = lpcfg_parm_bool(lp_ctx, NULL,
166 "require strong key",
169 * allow overwrite per domain
170 * require strong key:<netbios_domain>
172 require_strong_key = lpcfg_parm_bool(lp_ctx, NULL,
173 "require strong key",
174 server_netbios_domain,
177 proposed_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
178 proposed_flags |= NETLOGON_NEG_SUPPORTS_AES;
180 if (reject_md5_servers) {
181 required_flags |= NETLOGON_NEG_SUPPORTS_AES;
182 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
183 required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC;
186 if (require_strong_key) {
187 required_flags |= NETLOGON_NEG_STRONG_KEYS;
188 required_flags |= NETLOGON_NEG_ARCFOUR;
189 required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC;
192 if (require_sign_or_seal == true) {
193 required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC;
196 status = netlogon_creds_cli_context_common(client_account,
202 server_netbios_domain,
205 if (!NT_STATUS_IS_OK(status)) {
209 if (global_db != NULL) {
210 context->db.ctx = global_db;
215 fname = lpcfg_private_db_path(context, lp_ctx, "netlogon_creds_cli");
217 talloc_free(context);
218 return NT_STATUS_NO_MEMORY;
221 global_db = dbwrap_local_open(talloc_autofree_context(), lp_ctx,
223 TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
225 0600, DBWRAP_LOCK_ORDER_2);
226 if (global_db == NULL) {
227 DEBUG(0,("netlogon_creds_cli_context_global: Failed to open %s - %s\n",
228 fname, strerror(errno)));
229 talloc_free(context);
230 return NT_STATUS_NO_MEMORY;
234 context->db.ctx = global_db;
239 NTSTATUS netlogon_creds_cli_context_tmp(const char *client_account,
240 const char *client_computer,
241 enum netr_SchannelType type,
242 uint32_t proposed_flags,
243 uint32_t required_flags,
244 const char *server_computer,
245 const char *server_netbios_domain,
247 struct netlogon_creds_cli_context **_context)
250 struct netlogon_creds_cli_context *context = NULL;
254 status = netlogon_creds_cli_context_common(client_account,
260 server_netbios_domain,
263 if (!NT_STATUS_IS_OK(status)) {
267 context->db.ctx = db_open_rbt(context);
268 if (context->db.ctx == NULL) {
269 talloc_free(context);
270 return NT_STATUS_NO_MEMORY;
277 struct netlogon_creds_cli_fetch_state {
279 struct netlogon_creds_CredentialState *creds;
283 static void netlogon_creds_cli_fetch_parser(TDB_DATA key, TDB_DATA data,
286 struct netlogon_creds_cli_fetch_state *state =
287 (struct netlogon_creds_cli_fetch_state *)private_data;
288 enum ndr_err_code ndr_err;
291 state->creds = talloc_zero(state->mem_ctx,
292 struct netlogon_creds_CredentialState);
293 if (state->creds == NULL) {
294 state->status = NT_STATUS_NO_MEMORY;
298 blob.data = data.dptr;
299 blob.length = data.dsize;
301 ndr_err = ndr_pull_struct_blob(&blob, state->creds, state->creds,
302 (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState);
303 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
304 TALLOC_FREE(state->creds);
305 state->status = ndr_map_error2ntstatus(ndr_err);
309 state->status = NT_STATUS_OK;
312 NTSTATUS netlogon_creds_cli_get(struct netlogon_creds_cli_context *context,
314 struct netlogon_creds_CredentialState **_creds)
317 struct netlogon_creds_cli_fetch_state fstate = {
319 .status = NT_STATUS_INTERNAL_ERROR,
321 static const struct netr_Credential zero_creds;
325 status = dbwrap_parse_record(context->db.ctx,
326 context->db.key_data,
327 netlogon_creds_cli_fetch_parser,
329 if (!NT_STATUS_IS_OK(status)) {
332 status = fstate.status;
333 if (!NT_STATUS_IS_OK(status)) {
338 * mark it as invalid for step operations.
340 fstate.creds->sequence = 0;
341 fstate.creds->seed = zero_creds;
342 fstate.creds->client = zero_creds;
343 fstate.creds->server = zero_creds;
345 if (context->server.cached_flags == fstate.creds->negotiate_flags) {
346 *_creds = fstate.creds;
350 context->server.cached_flags = fstate.creds->negotiate_flags;
351 context->server.try_validation6 = true;
352 context->server.try_logon_ex = true;
353 context->server.try_logon_with = true;
355 if (!(context->server.cached_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
356 context->server.try_validation6 = false;
357 context->server.try_logon_ex = false;
359 if (!(context->server.cached_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) {
360 context->server.try_validation6 = false;
363 *_creds = fstate.creds;
367 bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context *context,
368 const struct netlogon_creds_CredentialState *creds1)
370 TALLOC_CTX *frame = talloc_stackframe();
371 struct netlogon_creds_CredentialState *creds2;
374 status = netlogon_creds_cli_get(context, frame, &creds2);
375 if (!NT_STATUS_IS_OK(status)) {
380 if (creds1->negotiate_flags != creds2->negotiate_flags) {
384 if (memcmp(creds1->session_key, creds2->session_key, 16) != 0) {
389 if (creds1->sequence != creds2->sequence) {
394 if (memcmp(&creds1->seed, &creds2->seed, sizeof(creds2->seed)) != 0) {
399 if (memcmp(&creds1->client, &creds2->client, sizeof(creds2->client)) != 0) {
404 if (memcmp(&creds1->server, &creds2->server, sizeof(creds2->server)) != 0) {
409 if (creds1->secure_channel_type != creds2->secure_channel_type) {
414 if (!strequal(creds1->computer_name, creds2->computer_name)) {
419 if (!strequal(creds1->account_name, creds2->account_name)) {
424 if (dom_sid_compare(creds1->sid, creds2->sid) != 0) {
433 NTSTATUS netlogon_creds_cli_store(struct netlogon_creds_cli_context *context,
434 struct netlogon_creds_CredentialState **_creds)
436 struct netlogon_creds_CredentialState *creds = *_creds;
438 enum ndr_err_code ndr_err;
441 static const struct netr_Credential zero_creds;
446 if (creds->sequence != 0) {
448 } else if (memcmp(&creds->seed, &zero_creds, sizeof(zero_creds)) != 0) {
450 } else if (memcmp(&creds->client, &zero_creds, sizeof(zero_creds)) != 0) {
452 } else if (memcmp(&creds->server, &zero_creds, sizeof(zero_creds)) != 0) {
458 * this was the result of netlogon_creds_cli_get()
459 * which only gives a valid read only session key.
462 return NT_STATUS_INVALID_PAGE_PROTECTION;
465 ndr_err = ndr_push_struct_blob(&blob, creds, creds,
466 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
467 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
469 status = ndr_map_error2ntstatus(ndr_err);
473 data.dptr = blob.data;
474 data.dsize = blob.length;
476 status = dbwrap_store(context->db.ctx,
477 context->db.key_data,
480 if (!NT_STATUS_IS_OK(status)) {
487 NTSTATUS netlogon_creds_cli_delete(struct netlogon_creds_cli_context *context,
488 struct netlogon_creds_CredentialState **_creds)
490 struct netlogon_creds_CredentialState *creds = *_creds;
492 static const struct netr_Credential zero_creds;
497 if (creds->sequence != 0) {
499 } else if (memcmp(&creds->seed, &zero_creds, sizeof(zero_creds)) != 0) {
501 } else if (memcmp(&creds->client, &zero_creds, sizeof(zero_creds)) != 0) {
503 } else if (memcmp(&creds->server, &zero_creds, sizeof(zero_creds)) != 0) {
509 * this was the result of netlogon_creds_cli_get()
510 * which only gives a valid read only session key.
513 return NT_STATUS_INVALID_PAGE_PROTECTION;
516 status = dbwrap_delete(context->db.ctx,
517 context->db.key_data);
519 if (!NT_STATUS_IS_OK(status)) {
526 struct netlogon_creds_cli_lock_state {
527 struct netlogon_creds_CredentialState *creds;
530 struct tevent_req *netlogon_creds_cli_lock_send(TALLOC_CTX *mem_ctx,
531 struct tevent_context *ev,
532 struct netlogon_creds_cli_context *context)
534 struct tevent_req *req;
535 struct netlogon_creds_cli_lock_state *state;
536 struct netlogon_creds_cli_fetch_state fstate = {
537 .status = NT_STATUS_INTERNAL_ERROR,
541 req = tevent_req_create(mem_ctx, &state,
542 struct netlogon_creds_cli_lock_state);
547 fstate.mem_ctx = state;
548 status = dbwrap_parse_record(context->db.ctx,
549 context->db.key_data,
550 netlogon_creds_cli_fetch_parser,
552 if (tevent_req_nterror(req, status)) {
553 return tevent_req_post(req, ev);
555 status = fstate.status;
556 if (tevent_req_nterror(req, status)) {
557 return tevent_req_post(req, ev);
560 if (context->server.cached_flags == fstate.creds->negotiate_flags) {
561 state->creds = fstate.creds;
562 tevent_req_done(req);
563 return tevent_req_post(req, ev);
566 context->server.cached_flags = fstate.creds->negotiate_flags;
567 context->server.try_validation6 = true;
568 context->server.try_logon_ex = true;
569 context->server.try_logon_with = true;
571 if (!(context->server.cached_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
572 context->server.try_validation6 = false;
573 context->server.try_logon_ex = false;
575 if (!(context->server.cached_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) {
576 context->server.try_validation6 = false;
579 state->creds = fstate.creds;
580 tevent_req_done(req);
581 return tevent_req_post(req, ev);
584 NTSTATUS netlogon_creds_cli_lock_recv(struct tevent_req *req,
586 struct netlogon_creds_CredentialState **creds)
588 struct netlogon_creds_cli_lock_state *state =
590 struct netlogon_creds_cli_lock_state);
593 if (tevent_req_is_nterror(req, &status)) {
594 tevent_req_received(req);
598 *creds = talloc_move(mem_ctx, &state->creds);
599 tevent_req_received(req);
603 NTSTATUS netlogon_creds_cli_lock(struct netlogon_creds_cli_context *context,
605 struct netlogon_creds_CredentialState **creds)
607 TALLOC_CTX *frame = talloc_stackframe();
608 struct tevent_context *ev;
609 struct tevent_req *req;
610 NTSTATUS status = NT_STATUS_NO_MEMORY;
612 ev = samba_tevent_context_init(frame);
616 req = netlogon_creds_cli_lock_send(frame, ev, context);
620 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
623 status = netlogon_creds_cli_lock_recv(req, mem_ctx, creds);
629 struct netlogon_creds_cli_auth_state {
630 struct tevent_context *ev;
631 struct netlogon_creds_cli_context *context;
632 struct dcerpc_binding_handle *binding_handle;
633 struct samr_Password current_nt_hash;
634 struct samr_Password previous_nt_hash;
635 struct samr_Password used_nt_hash;
636 char *srv_name_slash;
637 uint32_t current_flags;
638 struct netr_Credential client_challenge;
639 struct netr_Credential server_challenge;
640 struct netlogon_creds_CredentialState *creds;
641 struct netr_Credential client_credential;
642 struct netr_Credential server_credential;
647 bool try_previous_nt_hash;
650 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req *req);
652 struct tevent_req *netlogon_creds_cli_auth_send(TALLOC_CTX *mem_ctx,
653 struct tevent_context *ev,
654 struct netlogon_creds_cli_context *context,
655 struct dcerpc_binding_handle *b,
656 struct samr_Password current_nt_hash,
657 const struct samr_Password *previous_nt_hash)
659 struct tevent_req *req;
660 struct netlogon_creds_cli_auth_state *state;
663 req = tevent_req_create(mem_ctx, &state,
664 struct netlogon_creds_cli_auth_state);
670 state->context = context;
671 state->binding_handle = b;
672 state->current_nt_hash = current_nt_hash;
673 if (previous_nt_hash != NULL) {
674 state->previous_nt_hash = *previous_nt_hash;
675 state->try_previous_nt_hash = true;
678 state->used_nt_hash = state->current_nt_hash;
680 if (context->client.required_flags & NETLOGON_NEG_SUPPORTS_AES) {
681 state->try_auth2 = true;
682 state->require_auth2 = true;
685 if (context->client.required_flags & NETLOGON_NEG_STRONG_KEYS) {
686 state->try_auth2 = true;
687 state->require_auth2 = true;
690 state->current_flags = context->client.proposed_flags;
692 if (state->current_flags & NETLOGON_NEG_AUTHENTICATED_RPC) {
693 state->try_auth3 = true;
694 state->try_auth2 = true;
697 state->srv_name_slash = talloc_asprintf(state, "\\%s",
698 context->server.computer);
699 if (tevent_req_nomem(state->srv_name_slash, req)) {
700 return tevent_req_post(req, ev);
703 status = dbwrap_delete(state->context->db.ctx,
704 state->context->db.key_data);
705 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
706 status = NT_STATUS_OK;
708 if (tevent_req_nterror(req, status)) {
709 return tevent_req_post(req, ev);
712 netlogon_creds_cli_auth_challenge_start(req);
714 if (!tevent_req_is_in_progress(req)) {
715 return tevent_req_post(req, ev);
721 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq);
723 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req *req)
725 struct netlogon_creds_cli_auth_state *state =
727 struct netlogon_creds_cli_auth_state);
728 struct tevent_req *subreq;
730 generate_random_buffer(state->client_challenge.data,
731 sizeof(state->client_challenge.data));
733 subreq = dcerpc_netr_ServerReqChallenge_send(state, state->ev,
734 state->binding_handle,
735 state->srv_name_slash,
736 state->context->client.computer,
737 &state->client_challenge,
738 &state->server_challenge);
739 if (tevent_req_nomem(subreq, req)) {
742 tevent_req_set_callback(subreq,
743 netlogon_creds_cli_auth_challenge_done,
747 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq);
749 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq)
751 struct tevent_req *req =
752 tevent_req_callback_data(subreq,
754 struct netlogon_creds_cli_auth_state *state =
756 struct netlogon_creds_cli_auth_state);
760 status = dcerpc_netr_ServerReqChallenge_recv(subreq, state, &result);
762 if (tevent_req_nterror(req, status)) {
765 if (tevent_req_nterror(req, result)) {
769 /* Calculate the session key and client credentials */
771 state->creds = netlogon_creds_client_init(state,
772 state->context->client.account,
773 state->context->client.computer,
774 &state->client_challenge,
775 &state->server_challenge,
776 &state->used_nt_hash,
777 &state->client_credential,
778 state->current_flags);
779 if (tevent_req_nomem(state->creds, req)) {
783 if (state->try_auth3) {
784 subreq = dcerpc_netr_ServerAuthenticate3_send(state, state->ev,
785 state->binding_handle,
786 state->srv_name_slash,
787 state->context->client.account,
788 state->context->client.type,
789 state->context->client.computer,
790 &state->client_credential,
791 &state->server_credential,
792 &state->creds->negotiate_flags,
794 if (tevent_req_nomem(subreq, req)) {
797 } else if (state->try_auth2) {
800 subreq = dcerpc_netr_ServerAuthenticate2_send(state, state->ev,
801 state->binding_handle,
802 state->srv_name_slash,
803 state->context->client.account,
804 state->context->client.type,
805 state->context->client.computer,
806 &state->client_credential,
807 &state->server_credential,
808 &state->creds->negotiate_flags);
809 if (tevent_req_nomem(subreq, req)) {
815 * keep old samba versions happy.
817 state->creds->negotiate_flags = NETLOGON_NEG_AUTHENTICATED_RPC;
819 subreq = dcerpc_netr_ServerAuthenticate_send(state, state->ev,
820 state->binding_handle,
821 state->srv_name_slash,
822 state->context->client.account,
823 state->context->client.type,
824 state->context->client.computer,
825 &state->client_credential,
826 &state->server_credential);
827 if (tevent_req_nomem(subreq, req)) {
831 tevent_req_set_callback(subreq,
832 netlogon_creds_cli_auth_srvauth_done,
836 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq)
838 struct tevent_req *req =
839 tevent_req_callback_data(subreq,
841 struct netlogon_creds_cli_auth_state *state =
843 struct netlogon_creds_cli_auth_state);
847 enum ndr_err_code ndr_err;
852 if (state->try_auth3) {
853 status = dcerpc_netr_ServerAuthenticate3_recv(subreq, state,
856 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
857 state->try_auth3 = false;
858 TALLOC_FREE(state->creds);
859 netlogon_creds_cli_auth_challenge_start(req);
862 if (tevent_req_nterror(req, status)) {
865 } else if (state->try_auth2) {
866 status = dcerpc_netr_ServerAuthenticate2_recv(subreq, state,
869 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
870 state->try_auth2 = false;
871 if (state->require_auth2) {
872 status = NT_STATUS_DOWNGRADE_DETECTED;
873 tevent_req_nterror(req, status);
876 TALLOC_FREE(state->creds);
877 netlogon_creds_cli_auth_challenge_start(req);
880 if (tevent_req_nterror(req, status)) {
884 status = dcerpc_netr_ServerAuthenticate_recv(subreq, state,
887 if (tevent_req_nterror(req, status)) {
892 tmp_flags = state->creds->negotiate_flags;
893 tmp_flags &= state->context->client.required_flags;
894 if (tmp_flags != state->context->client.required_flags) {
895 if (NT_STATUS_IS_OK(result)) {
896 tevent_req_nterror(req, NT_STATUS_DOWNGRADE_DETECTED);
899 tevent_req_nterror(req, result);
903 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
904 tmp_flags = state->context->client.proposed_flags;
905 if (state->current_flags != tmp_flags) {
906 if (!state->try_previous_nt_hash) {
908 * we already retried, giving up...
910 tevent_req_nterror(req, result);
915 * lets retry with the old nt hash.
917 state->used_nt_hash = state->previous_nt_hash;
918 state->try_previous_nt_hash = false;
919 state->current_flags = tmp_flags;
920 TALLOC_FREE(state->creds);
921 netlogon_creds_cli_auth_challenge_start(req);
926 * lets retry with the negotiated flags
928 state->current_flags = state->creds->negotiate_flags;
929 TALLOC_FREE(state->creds);
930 netlogon_creds_cli_auth_challenge_start(req);
934 ok = netlogon_creds_client_check(state->creds,
935 &state->server_credential);
937 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
941 ndr_err = ndr_push_struct_blob(&blob, state, state->creds,
942 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
943 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
944 status = ndr_map_error2ntstatus(ndr_err);
945 tevent_req_nterror(req, status);
949 data.dptr = blob.data;
950 data.dsize = blob.length;
952 status = dbwrap_store(state->context->db.ctx,
953 state->context->db.key_data,
955 if (tevent_req_nterror(req, status)) {
959 tevent_req_done(req);
962 NTSTATUS netlogon_creds_cli_auth_recv(struct tevent_req *req)
966 if (tevent_req_is_nterror(req, &status)) {
967 tevent_req_received(req);
971 tevent_req_received(req);
975 NTSTATUS netlogon_creds_cli_auth(struct netlogon_creds_cli_context *context,
976 struct dcerpc_binding_handle *b,
977 struct samr_Password current_nt_hash,
978 const struct samr_Password *previous_nt_hash)
980 TALLOC_CTX *frame = talloc_stackframe();
981 struct tevent_context *ev;
982 struct tevent_req *req;
983 NTSTATUS status = NT_STATUS_NO_MEMORY;
985 ev = samba_tevent_context_init(frame);
989 req = netlogon_creds_cli_auth_send(frame, ev, context, b,
995 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
998 status = netlogon_creds_cli_auth_recv(req);
1004 struct netlogon_creds_cli_check_state {
1005 struct tevent_context *ev;
1006 struct netlogon_creds_cli_context *context;
1007 struct dcerpc_binding_handle *binding_handle;
1009 char *srv_name_slash;
1010 char *cli_name_slash;
1012 union netr_Capabilities caps;
1014 struct netlogon_creds_CredentialState *creds;
1015 struct netlogon_creds_CredentialState tmp_creds;
1016 struct netr_Authenticator req_auth;
1017 struct netr_Authenticator rep_auth;
1020 static void netlogon_creds_cli_check_cleanup(struct tevent_req *req,
1022 static void netlogon_creds_cli_check_locked(struct tevent_req *subreq);
1024 struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx,
1025 struct tevent_context *ev,
1026 struct netlogon_creds_cli_context *context,
1027 struct dcerpc_binding_handle *b)
1029 struct tevent_req *req;
1030 struct netlogon_creds_cli_check_state *state;
1031 struct tevent_req *subreq;
1033 req = tevent_req_create(mem_ctx, &state,
1034 struct netlogon_creds_cli_check_state);
1040 state->context = context;
1041 state->binding_handle = b;
1043 state->srv_name_slash = talloc_asprintf(state, "\\%s",
1044 context->server.computer);
1045 if (tevent_req_nomem(state->srv_name_slash, req)) {
1046 return tevent_req_post(req, ev);
1049 state->cli_name_slash = talloc_asprintf(state, "\\%s",
1050 context->client.computer);
1051 if (tevent_req_nomem(state->cli_name_slash, req)) {
1052 return tevent_req_post(req, ev);
1057 * verify DCERPC_AUTH_TYPE_SCHANNEL
1060 subreq = netlogon_creds_cli_lock_send(state, state->ev,
1062 if (tevent_req_nomem(subreq, req)) {
1063 return tevent_req_post(req, ev);
1066 tevent_req_set_callback(subreq,
1067 netlogon_creds_cli_check_locked,
1073 static void netlogon_creds_cli_check_cleanup(struct tevent_req *req,
1076 struct netlogon_creds_cli_check_state *state =
1077 tevent_req_data(req,
1078 struct netlogon_creds_cli_check_state);
1080 if (state->creds == NULL) {
1084 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
1085 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED)) {
1086 TALLOC_FREE(state->creds);
1090 netlogon_creds_cli_delete(state->context, &state->creds);
1093 static void netlogon_creds_cli_check_caps(struct tevent_req *subreq);
1095 static void netlogon_creds_cli_check_locked(struct tevent_req *subreq)
1097 struct tevent_req *req =
1098 tevent_req_callback_data(subreq,
1100 struct netlogon_creds_cli_check_state *state =
1101 tevent_req_data(req,
1102 struct netlogon_creds_cli_check_state);
1105 status = netlogon_creds_cli_lock_recv(subreq, state,
1107 TALLOC_FREE(subreq);
1108 if (tevent_req_nterror(req, status)) {
1113 * we defer all callbacks in order to cleanup
1114 * the database record.
1116 tevent_req_defer_callback(req, state->ev);
1118 state->tmp_creds = *state->creds;
1119 netlogon_creds_client_authenticator(&state->tmp_creds,
1121 ZERO_STRUCT(state->rep_auth);
1123 subreq = dcerpc_netr_LogonGetCapabilities_send(state, state->ev,
1124 state->binding_handle,
1125 state->srv_name_slash,
1126 state->cli_name_slash,
1131 if (tevent_req_nomem(subreq, req)) {
1132 status = NT_STATUS_NO_MEMORY;
1133 netlogon_creds_cli_check_cleanup(req, status);
1136 tevent_req_set_callback(subreq,
1137 netlogon_creds_cli_check_caps,
1141 static void netlogon_creds_cli_check_caps(struct tevent_req *subreq)
1143 struct tevent_req *req =
1144 tevent_req_callback_data(subreq,
1146 struct netlogon_creds_cli_check_state *state =
1147 tevent_req_data(req,
1148 struct netlogon_creds_cli_check_state);
1153 status = dcerpc_netr_LogonGetCapabilities_recv(subreq, state,
1155 TALLOC_FREE(subreq);
1156 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1157 status = NT_STATUS_OK;
1158 result = NT_STATUS_NOT_IMPLEMENTED;
1160 if (tevent_req_nterror(req, status)) {
1161 netlogon_creds_cli_check_cleanup(req, status);
1165 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
1166 if (tevent_req_nterror(req, result)) {
1167 netlogon_creds_cli_check_cleanup(req, result);
1172 ok = netlogon_creds_client_check(&state->tmp_creds,
1173 &state->rep_auth.cred);
1175 status = NT_STATUS_ACCESS_DENIED;
1176 tevent_req_nterror(req, status);
1177 netlogon_creds_cli_check_cleanup(req, status);
1181 if (tevent_req_nterror(req, result)) {
1182 netlogon_creds_cli_check_cleanup(req, result);
1186 if (state->caps.server_capabilities != state->tmp_creds.negotiate_flags) {
1187 status = NT_STATUS_DOWNGRADE_DETECTED;
1188 tevent_req_nterror(req, status);
1189 netlogon_creds_cli_check_cleanup(req, status);
1193 if (!(state->caps.server_capabilities & NETLOGON_NEG_SUPPORTS_AES)) {
1194 status = NT_STATUS_DOWNGRADE_DETECTED;
1195 tevent_req_nterror(req, status);
1196 netlogon_creds_cli_check_cleanup(req, status);
1200 *state->creds = state->tmp_creds;
1201 status = netlogon_creds_cli_store(state->context,
1203 if (tevent_req_nterror(req, status)) {
1204 netlogon_creds_cli_check_cleanup(req, status);
1208 tevent_req_done(req);
1211 NTSTATUS netlogon_creds_cli_check_recv(struct tevent_req *req)
1215 if (tevent_req_is_nterror(req, &status)) {
1216 netlogon_creds_cli_check_cleanup(req, status);
1217 tevent_req_received(req);
1221 tevent_req_received(req);
1222 return NT_STATUS_OK;
1225 NTSTATUS netlogon_creds_cli_check(struct netlogon_creds_cli_context *context,
1226 struct dcerpc_binding_handle *b)
1228 TALLOC_CTX *frame = talloc_stackframe();
1229 struct tevent_context *ev;
1230 struct tevent_req *req;
1231 NTSTATUS status = NT_STATUS_NO_MEMORY;
1233 ev = samba_tevent_context_init(frame);
1237 req = netlogon_creds_cli_check_send(frame, ev, context, b);
1241 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1244 status = netlogon_creds_cli_check_recv(req);
1250 struct netlogon_creds_cli_ServerPasswordSet_state {
1251 struct tevent_context *ev;
1252 struct netlogon_creds_cli_context *context;
1253 struct dcerpc_binding_handle *binding_handle;
1254 uint32_t old_timeout;
1256 const char *new_password;
1258 char *srv_name_slash;
1260 struct netr_CryptPassword crypt_password;
1261 struct samr_Password samr_password;
1263 struct netlogon_creds_CredentialState *creds;
1264 struct netlogon_creds_CredentialState tmp_creds;
1265 struct netr_Authenticator req_auth;
1266 struct netr_Authenticator rep_auth;
1269 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req *req,
1271 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subreq);
1273 struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx,
1274 struct tevent_context *ev,
1275 struct netlogon_creds_cli_context *context,
1276 struct dcerpc_binding_handle *b,
1277 const char *new_password)
1279 struct tevent_req *req;
1280 struct netlogon_creds_cli_ServerPasswordSet_state *state;
1281 struct tevent_req *subreq;
1283 req = tevent_req_create(mem_ctx, &state,
1284 struct netlogon_creds_cli_ServerPasswordSet_state);
1290 state->context = context;
1291 state->binding_handle = b;
1293 state->new_password = talloc_strdup(state, new_password);
1294 if (tevent_req_nomem(state->new_password, req)) {
1295 return tevent_req_post(req, ev);
1297 talloc_set_name_const(state->new_password, "<new_password>");
1299 state->srv_name_slash = talloc_asprintf(state, "\\%s",
1300 context->server.computer);
1301 if (tevent_req_nomem(state->srv_name_slash, req)) {
1302 return tevent_req_post(req, ev);
1307 * verify DCERPC_AUTH_TYPE_SCHANNEL
1310 subreq = netlogon_creds_cli_lock_send(state, state->ev,
1312 if (tevent_req_nomem(subreq, req)) {
1313 return tevent_req_post(req, ev);
1316 tevent_req_set_callback(subreq,
1317 netlogon_creds_cli_ServerPasswordSet_locked,
1323 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req *req,
1326 struct netlogon_creds_cli_ServerPasswordSet_state *state =
1327 tevent_req_data(req,
1328 struct netlogon_creds_cli_ServerPasswordSet_state);
1330 if (state->creds == NULL) {
1334 dcerpc_binding_handle_set_timeout(state->binding_handle,
1335 state->old_timeout);
1337 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1338 TALLOC_FREE(state->creds);
1342 netlogon_creds_cli_delete(state->context, &state->creds);
1345 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq);
1347 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subreq)
1349 struct tevent_req *req =
1350 tevent_req_callback_data(subreq,
1352 struct netlogon_creds_cli_ServerPasswordSet_state *state =
1353 tevent_req_data(req,
1354 struct netlogon_creds_cli_ServerPasswordSet_state);
1357 status = netlogon_creds_cli_lock_recv(subreq, state,
1359 TALLOC_FREE(subreq);
1360 if (tevent_req_nterror(req, status)) {
1364 state->old_timeout = dcerpc_binding_handle_set_timeout(
1365 state->binding_handle, 600000);
1368 * we defer all callbacks in order to cleanup
1369 * the database record.
1371 tevent_req_defer_callback(req, state->ev);
1373 state->tmp_creds = *state->creds;
1374 netlogon_creds_client_authenticator(&state->tmp_creds,
1376 ZERO_STRUCT(state->rep_auth);
1378 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) {
1379 struct samr_CryptPassword password_buf;
1381 encode_pw_buffer(password_buf.data,
1382 state->new_password, STR_UNICODE);
1384 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1385 netlogon_creds_aes_encrypt(&state->tmp_creds,
1386 password_buf.data, 516);
1388 netlogon_creds_arcfour_crypt(&state->tmp_creds,
1389 password_buf.data, 516);
1392 memcpy(state->crypt_password.data, password_buf.data, 512);
1393 state->crypt_password.length = IVAL(password_buf.data, 512);
1394 ZERO_STRUCT(password_buf);
1396 subreq = dcerpc_netr_ServerPasswordSet2_send(state, state->ev,
1397 state->binding_handle,
1398 state->srv_name_slash,
1399 state->tmp_creds.account_name,
1400 /* TODO: state->tmp_creds.secure_channel_type, */
1401 state->context->client.type,
1402 state->tmp_creds.computer_name,
1405 &state->crypt_password);
1406 if (tevent_req_nomem(subreq, req)) {
1407 status = NT_STATUS_NO_MEMORY;
1408 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1412 E_md4hash(state->new_password, state->samr_password.hash);
1413 netlogon_creds_des_encrypt(&state->tmp_creds,
1414 &state->samr_password);
1416 subreq = dcerpc_netr_ServerPasswordSet_send(state, state->ev,
1417 state->binding_handle,
1418 state->srv_name_slash,
1419 state->tmp_creds.account_name,
1420 state->tmp_creds.secure_channel_type,
1421 state->tmp_creds.computer_name,
1424 &state->samr_password);
1425 if (tevent_req_nomem(subreq, req)) {
1426 status = NT_STATUS_NO_MEMORY;
1427 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1432 tevent_req_set_callback(subreq,
1433 netlogon_creds_cli_ServerPasswordSet_done,
1437 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq)
1439 struct tevent_req *req =
1440 tevent_req_callback_data(subreq,
1442 struct netlogon_creds_cli_ServerPasswordSet_state *state =
1443 tevent_req_data(req,
1444 struct netlogon_creds_cli_ServerPasswordSet_state);
1449 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) {
1450 status = dcerpc_netr_ServerPasswordSet2_recv(subreq, state,
1452 TALLOC_FREE(subreq);
1453 if (tevent_req_nterror(req, status)) {
1454 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1458 status = dcerpc_netr_ServerPasswordSet_recv(subreq, state,
1460 TALLOC_FREE(subreq);
1461 if (tevent_req_nterror(req, status)) {
1462 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1467 ok = netlogon_creds_client_check(&state->tmp_creds,
1468 &state->rep_auth.cred);
1470 status = NT_STATUS_ACCESS_DENIED;
1471 tevent_req_nterror(req, status);
1472 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1476 if (tevent_req_nterror(req, result)) {
1477 netlogon_creds_cli_ServerPasswordSet_cleanup(req, result);
1481 dcerpc_binding_handle_set_timeout(state->binding_handle,
1482 state->old_timeout);
1484 *state->creds = state->tmp_creds;
1485 status = netlogon_creds_cli_store(state->context,
1487 if (tevent_req_nterror(req, status)) {
1488 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1492 tevent_req_done(req);
1495 NTSTATUS netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req *req)
1499 if (tevent_req_is_nterror(req, &status)) {
1500 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1501 tevent_req_received(req);
1505 tevent_req_received(req);
1506 return NT_STATUS_OK;
1509 NTSTATUS netlogon_creds_cli_ServerPasswordSet(
1510 struct netlogon_creds_cli_context *context,
1511 struct dcerpc_binding_handle *b,
1512 const char *new_password)
1514 TALLOC_CTX *frame = talloc_stackframe();
1515 struct tevent_context *ev;
1516 struct tevent_req *req;
1517 NTSTATUS status = NT_STATUS_NO_MEMORY;
1519 ev = samba_tevent_context_init(frame);
1523 req = netlogon_creds_cli_ServerPasswordSet_send(frame, ev, context, b,
1528 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1531 status = netlogon_creds_cli_ServerPasswordSet_recv(req);
1537 struct netlogon_creds_cli_LogonSamLogon_state {
1538 struct tevent_context *ev;
1539 struct netlogon_creds_cli_context *context;
1540 struct dcerpc_binding_handle *binding_handle;
1542 char *srv_name_slash;
1543 char *cli_name_slash;
1545 enum netr_LogonInfoClass logon_level;
1546 const union netr_LogonLevel *const_logon;
1547 union netr_LogonLevel *logon;
1550 uint16_t validation_level;
1551 union netr_Validation *validation;
1552 uint8_t authoritative;
1555 * do we need encryption at the application layer?
1560 * the read only credentials before we started the operation
1562 struct netlogon_creds_CredentialState *ro_creds;
1564 struct netlogon_creds_CredentialState *lk_creds;
1566 struct netlogon_creds_CredentialState tmp_creds;
1567 struct netr_Authenticator req_auth;
1568 struct netr_Authenticator rep_auth;
1571 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req);
1572 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req *req,
1575 struct tevent_req *netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX *mem_ctx,
1576 struct tevent_context *ev,
1577 struct netlogon_creds_cli_context *context,
1578 struct dcerpc_binding_handle *b,
1579 enum netr_LogonInfoClass logon_level,
1580 const union netr_LogonLevel *logon,
1583 struct tevent_req *req;
1584 struct netlogon_creds_cli_LogonSamLogon_state *state;
1586 req = tevent_req_create(mem_ctx, &state,
1587 struct netlogon_creds_cli_LogonSamLogon_state);
1593 state->context = context;
1594 state->binding_handle = b;
1596 state->logon_level = logon_level;
1597 state->const_logon = logon;
1598 state->flags = flags;
1600 state->srv_name_slash = talloc_asprintf(state, "\\%s",
1601 context->server.computer);
1602 if (tevent_req_nomem(state->srv_name_slash, req)) {
1603 return tevent_req_post(req, ev);
1606 state->cli_name_slash = talloc_asprintf(state, "\\%s",
1607 context->client.computer);
1608 if (tevent_req_nomem(state->cli_name_slash, req)) {
1609 return tevent_req_post(req, ev);
1612 switch (logon_level) {
1613 case NetlogonInteractiveInformation:
1614 case NetlogonInteractiveTransitiveInformation:
1615 case NetlogonServiceInformation:
1616 case NetlogonServiceTransitiveInformation:
1617 case NetlogonGenericInformation:
1618 state->user_encrypt = true;
1621 case NetlogonNetworkInformation:
1622 case NetlogonNetworkTransitiveInformation:
1626 state->validation = talloc_zero(state, union netr_Validation);
1627 if (tevent_req_nomem(state->validation, req)) {
1628 return tevent_req_post(req, ev);
1633 * verify DCERPC_AUTH_TYPE_SCHANNEL
1636 * and DCERPC_AUTH_LEVEL_PRIVACY for
1640 netlogon_creds_cli_LogonSamLogon_start(req);
1642 if (!tevent_req_is_in_progress(req)) {
1643 return tevent_req_post(req, ev);
1647 * we defer all callbacks in order to cleanup
1648 * the database record.
1650 tevent_req_defer_callback(req, state->ev);
1654 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req *req,
1657 struct netlogon_creds_cli_LogonSamLogon_state *state =
1658 tevent_req_data(req,
1659 struct netlogon_creds_cli_LogonSamLogon_state);
1661 if (state->lk_creds == NULL) {
1665 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1666 TALLOC_FREE(state->lk_creds);
1670 netlogon_creds_cli_delete(state->context, &state->lk_creds);
1673 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq);
1675 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req)
1677 struct netlogon_creds_cli_LogonSamLogon_state *state =
1678 tevent_req_data(req,
1679 struct netlogon_creds_cli_LogonSamLogon_state);
1680 struct tevent_req *subreq;
1683 TALLOC_FREE(state->ro_creds);
1684 TALLOC_FREE(state->logon);
1686 if (state->context->server.try_logon_ex) {
1687 if (state->context->server.try_validation6) {
1688 state->validation_level = 6;
1690 state->validation_level = 3;
1691 state->user_encrypt = true;
1694 state->logon = netlogon_creds_shallow_copy_logon(state,
1696 state->const_logon);
1697 if (tevent_req_nomem(state->logon, req)) {
1698 status = NT_STATUS_NO_MEMORY;
1699 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
1703 if (state->user_encrypt) {
1704 status = netlogon_creds_cli_get(state->context,
1707 if (!NT_STATUS_IS_OK(status)) {
1708 status = NT_STATUS_ACCESS_DENIED;
1709 tevent_req_nterror(req, status);
1710 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
1714 netlogon_creds_encrypt_samlogon_logon(state->ro_creds,
1719 subreq = dcerpc_netr_LogonSamLogonEx_send(state, state->ev,
1720 state->binding_handle,
1721 state->srv_name_slash,
1722 state->cli_name_slash,
1725 state->validation_level,
1727 &state->authoritative,
1729 if (tevent_req_nomem(subreq, req)) {
1730 status = NT_STATUS_NO_MEMORY;
1731 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
1734 tevent_req_set_callback(subreq,
1735 netlogon_creds_cli_LogonSamLogon_done,
1740 if (state->lk_creds == NULL) {
1741 subreq = netlogon_creds_cli_lock_send(state, state->ev,
1743 if (tevent_req_nomem(subreq, req)) {
1744 status = NT_STATUS_NO_MEMORY;
1745 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
1748 tevent_req_set_callback(subreq,
1749 netlogon_creds_cli_LogonSamLogon_done,
1754 state->tmp_creds = *state->lk_creds;
1755 netlogon_creds_client_authenticator(&state->tmp_creds,
1757 ZERO_STRUCT(state->rep_auth);
1759 state->logon = netlogon_creds_shallow_copy_logon(state,
1761 state->const_logon);
1762 if (tevent_req_nomem(state->logon, req)) {
1763 status = NT_STATUS_NO_MEMORY;
1764 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
1768 netlogon_creds_encrypt_samlogon_logon(state->ro_creds,
1772 state->validation_level = 3;
1774 if (state->context->server.try_logon_with) {
1775 subreq = dcerpc_netr_LogonSamLogonWithFlags_send(state, state->ev,
1776 state->binding_handle,
1777 state->srv_name_slash,
1778 state->cli_name_slash,
1783 state->validation_level,
1785 &state->authoritative,
1787 if (tevent_req_nomem(subreq, req)) {
1788 status = NT_STATUS_NO_MEMORY;
1789 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
1795 subreq = dcerpc_netr_LogonSamLogon_send(state, state->ev,
1796 state->binding_handle,
1797 state->srv_name_slash,
1798 state->cli_name_slash,
1803 state->validation_level,
1805 &state->authoritative);
1806 if (tevent_req_nomem(subreq, req)) {
1807 status = NT_STATUS_NO_MEMORY;
1808 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
1813 tevent_req_set_callback(subreq,
1814 netlogon_creds_cli_LogonSamLogon_done,
1818 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq)
1820 struct tevent_req *req =
1821 tevent_req_callback_data(subreq,
1823 struct netlogon_creds_cli_LogonSamLogon_state *state =
1824 tevent_req_data(req,
1825 struct netlogon_creds_cli_LogonSamLogon_state);
1830 if (state->context->server.try_logon_ex) {
1831 status = dcerpc_netr_LogonSamLogonEx_recv(subreq, state,
1833 TALLOC_FREE(subreq);
1834 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1835 state->context->server.try_validation6 = false;
1836 state->context->server.try_logon_ex = false;
1837 netlogon_creds_cli_LogonSamLogon_start(req);
1840 if (tevent_req_nterror(req, status)) {
1841 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
1845 if ((state->validation_level == 6) &&
1846 (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS) ||
1847 NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PARAMETER) ||
1848 NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL)))
1850 state->context->server.try_validation6 = false;
1851 netlogon_creds_cli_LogonSamLogon_start(req);
1855 if (tevent_req_nterror(req, result)) {
1856 netlogon_creds_cli_LogonSamLogon_cleanup(req, result);
1860 if (state->ro_creds == NULL) {
1861 tevent_req_done(req);
1865 ok = netlogon_creds_cli_validate(state->context, state->ro_creds);
1867 status = NT_STATUS_ACCESS_DENIED;
1868 tevent_req_nterror(req, status);
1869 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
1873 netlogon_creds_decrypt_samlogon_validation(state->ro_creds,
1874 state->validation_level,
1877 tevent_req_done(req);
1881 if (state->lk_creds == NULL) {
1882 status = netlogon_creds_cli_lock_recv(subreq, state,
1884 TALLOC_FREE(subreq);
1885 if (tevent_req_nterror(req, status)) {
1886 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
1890 netlogon_creds_cli_LogonSamLogon_start(req);
1894 if (state->context->server.try_logon_with) {
1895 status = dcerpc_netr_LogonSamLogonWithFlags_recv(subreq, state,
1897 TALLOC_FREE(subreq);
1898 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1899 state->context->server.try_logon_with = false;
1900 netlogon_creds_cli_LogonSamLogon_start(req);
1903 if (tevent_req_nterror(req, status)) {
1904 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
1908 status = dcerpc_netr_LogonSamLogon_recv(subreq, state,
1910 TALLOC_FREE(subreq);
1911 if (tevent_req_nterror(req, status)) {
1912 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
1917 ok = netlogon_creds_client_check(&state->tmp_creds,
1918 &state->rep_auth.cred);
1920 status = NT_STATUS_ACCESS_DENIED;
1921 tevent_req_nterror(req, status);
1922 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
1926 *state->lk_creds = state->tmp_creds;
1927 status = netlogon_creds_cli_store(state->context,
1929 if (tevent_req_nterror(req, status)) {
1930 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
1934 if (tevent_req_nterror(req, result)) {
1935 netlogon_creds_cli_LogonSamLogon_cleanup(req, result);
1939 netlogon_creds_decrypt_samlogon_validation(&state->tmp_creds,
1940 state->validation_level,
1943 tevent_req_done(req);
1946 NTSTATUS netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req *req,
1947 TALLOC_CTX *mem_ctx,
1948 uint16_t *validation_level,
1949 union netr_Validation **validation,
1950 uint8_t *authoritative,
1953 struct netlogon_creds_cli_LogonSamLogon_state *state =
1954 tevent_req_data(req,
1955 struct netlogon_creds_cli_LogonSamLogon_state);
1958 if (tevent_req_is_nterror(req, &status)) {
1959 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
1960 tevent_req_received(req);
1964 *validation_level = state->validation_level;
1965 *validation = talloc_move(mem_ctx, &state->validation);
1966 *authoritative = state->authoritative;
1967 *flags = state->flags;
1969 tevent_req_received(req);
1970 return NT_STATUS_OK;
1973 NTSTATUS netlogon_creds_cli_LogonSamLogon(
1974 struct netlogon_creds_cli_context *context,
1975 struct dcerpc_binding_handle *b,
1976 enum netr_LogonInfoClass logon_level,
1977 const union netr_LogonLevel *logon,
1978 TALLOC_CTX *mem_ctx,
1979 uint16_t *validation_level,
1980 union netr_Validation **validation,
1981 uint8_t *authoritative,
1984 TALLOC_CTX *frame = talloc_stackframe();
1985 struct tevent_context *ev;
1986 struct tevent_req *req;
1987 NTSTATUS status = NT_STATUS_NO_MEMORY;
1989 ev = samba_tevent_context_init(frame);
1993 req = netlogon_creds_cli_LogonSamLogon_send(frame, ev, context, b,
1999 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2002 status = netlogon_creds_cli_LogonSamLogon_recv(req, mem_ctx,