2 Unix SMB/CIFS implementation.
4 module to store/fetch session keys for the schannel client
6 Copyright (C) Stefan Metzmacher 2013
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "system/filesys.h"
25 #include "lib/util/tevent_ntstatus.h"
26 #include "lib/dbwrap/dbwrap.h"
27 #include "lib/dbwrap/dbwrap_rbt.h"
28 #include "lib/util/util_tdb.h"
29 #include "libcli/security/security.h"
30 #include "../lib/param/param.h"
31 #include "../libcli/auth/schannel.h"
32 #include "../librpc/gen_ndr/ndr_schannel.h"
33 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
34 #include "../librpc/gen_ndr/ndr_netlogon.h"
35 #include "../librpc/gen_ndr/server_id.h"
36 #include "netlogon_creds_cli.h"
37 #include "source3/include/messages.h"
38 #include "source3/include/g_lock.h"
39 #include "libds/common/roles.h"
40 #include "lib/crypto/crypto.h"
42 struct netlogon_creds_cli_locked_state;
44 struct netlogon_creds_cli_context {
48 uint32_t proposed_flags;
49 uint32_t required_flags;
50 enum netr_SchannelType type;
51 enum dcerpc_AuthLevel auth_level;
56 const char *netbios_domain;
57 uint32_t cached_flags;
66 struct db_context *ctx;
67 struct g_lock_ctx *g_ctx;
68 struct netlogon_creds_cli_locked_state *locked_state;
72 struct netlogon_creds_cli_locked_state {
73 struct netlogon_creds_cli_context *context;
75 struct netlogon_creds_CredentialState *creds;
78 static int netlogon_creds_cli_locked_state_destructor(
79 struct netlogon_creds_cli_locked_state *state)
81 struct netlogon_creds_cli_context *context = state->context;
83 if (context == NULL) {
87 if (context->db.locked_state == state) {
88 context->db.locked_state = NULL;
91 if (state->is_glocked) {
92 g_lock_unlock(context->db.g_ctx,
93 context->db.key_name);
99 static NTSTATUS netlogon_creds_cli_context_common(
100 const char *client_computer,
101 const char *client_account,
102 enum netr_SchannelType type,
103 enum dcerpc_AuthLevel auth_level,
104 uint32_t proposed_flags,
105 uint32_t required_flags,
106 const char *server_computer,
107 const char *server_netbios_domain,
109 struct netlogon_creds_cli_context **_context)
111 struct netlogon_creds_cli_context *context = NULL;
112 TALLOC_CTX *frame = talloc_stackframe();
113 char *_key_name = NULL;
114 char *server_netbios_name = NULL;
119 context = talloc_zero(mem_ctx, struct netlogon_creds_cli_context);
120 if (context == NULL) {
122 return NT_STATUS_NO_MEMORY;
125 context->client.computer = talloc_strdup(context, client_computer);
126 if (context->client.computer == NULL) {
127 TALLOC_FREE(context);
129 return NT_STATUS_NO_MEMORY;
132 context->client.account = talloc_strdup(context, client_account);
133 if (context->client.account == NULL) {
134 TALLOC_FREE(context);
136 return NT_STATUS_NO_MEMORY;
139 context->client.proposed_flags = proposed_flags;
140 context->client.required_flags = required_flags;
141 context->client.type = type;
142 context->client.auth_level = auth_level;
144 context->server.computer = talloc_strdup(context, server_computer);
145 if (context->server.computer == NULL) {
146 TALLOC_FREE(context);
148 return NT_STATUS_NO_MEMORY;
151 context->server.netbios_domain = talloc_strdup(context, server_netbios_domain);
152 if (context->server.netbios_domain == NULL) {
153 TALLOC_FREE(context);
155 return NT_STATUS_NO_MEMORY;
160 * Force the callers to provide a unique
161 * value for server_computer and use this directly.
163 * For now we have to deal with
164 * "HOSTNAME" vs. "hostname.example.com".
166 server_netbios_name = talloc_strdup(frame, server_computer);
167 if (server_netbios_name == NULL) {
168 TALLOC_FREE(context);
170 return NT_STATUS_NO_MEMORY;
173 p = strchr(server_netbios_name, '.');
178 _key_name = talloc_asprintf(frame, "CLI[%s/%s]/SRV[%s/%s]",
182 server_netbios_domain);
183 if (_key_name == NULL) {
184 TALLOC_FREE(context);
186 return NT_STATUS_NO_MEMORY;
189 context->db.key_name = talloc_strdup_upper(context, _key_name);
190 if (context->db.key_name == NULL) {
191 TALLOC_FREE(context);
193 return NT_STATUS_NO_MEMORY;
196 context->db.key_data = string_term_tdb_data(context->db.key_name);
203 static struct db_context *netlogon_creds_cli_global_db;
205 NTSTATUS netlogon_creds_cli_set_global_db(struct db_context **db)
207 if (netlogon_creds_cli_global_db != NULL) {
208 return NT_STATUS_INVALID_PARAMETER_MIX;
211 netlogon_creds_cli_global_db = talloc_move(talloc_autofree_context(), db);
215 NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx)
218 struct db_context *global_db;
220 if (netlogon_creds_cli_global_db != NULL) {
224 fname = lpcfg_private_db_path(NULL, lp_ctx, "netlogon_creds_cli");
226 return NT_STATUS_NO_MEMORY;
229 global_db = dbwrap_local_open(talloc_autofree_context(), lp_ctx,
231 TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
233 0600, DBWRAP_LOCK_ORDER_2,
235 if (global_db == NULL) {
236 DEBUG(0,("netlogon_creds_cli_open_global_db: Failed to open %s - %s\n",
237 fname, strerror(errno)));
239 return NT_STATUS_NO_MEMORY;
243 netlogon_creds_cli_global_db = global_db;
247 NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx,
248 struct messaging_context *msg_ctx,
249 const char *client_account,
250 enum netr_SchannelType type,
251 const char *server_computer,
252 const char *server_netbios_domain,
254 struct netlogon_creds_cli_context **_context)
256 TALLOC_CTX *frame = talloc_stackframe();
258 struct netlogon_creds_cli_context *context = NULL;
259 const char *client_computer;
260 uint32_t proposed_flags;
261 uint32_t required_flags = 0;
262 bool reject_md5_servers = false;
263 bool require_strong_key = false;
264 int require_sign_or_seal = true;
265 bool seal_secure_channel = true;
266 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
267 bool neutralize_nt4_emulation = false;
271 client_computer = lpcfg_netbios_name(lp_ctx);
272 if (strlen(client_computer) > 15) {
273 return NT_STATUS_INVALID_PARAMETER_MIX;
277 * allow overwrite per domain
278 * reject md5 servers:<netbios_domain>
280 reject_md5_servers = lpcfg_reject_md5_servers(lp_ctx);
281 reject_md5_servers = lpcfg_parm_bool(lp_ctx, NULL,
282 "reject md5 servers",
283 server_netbios_domain,
287 * allow overwrite per domain
288 * require strong key:<netbios_domain>
290 require_strong_key = lpcfg_require_strong_key(lp_ctx);
291 require_strong_key = lpcfg_parm_bool(lp_ctx, NULL,
292 "require strong key",
293 server_netbios_domain,
297 * allow overwrite per domain
298 * client schannel:<netbios_domain>
300 require_sign_or_seal = lpcfg_client_schannel(lp_ctx);
301 require_sign_or_seal = lpcfg_parm_int(lp_ctx, NULL,
303 server_netbios_domain,
304 require_sign_or_seal);
307 * allow overwrite per domain
308 * winbind sealed pipes:<netbios_domain>
310 seal_secure_channel = lpcfg_winbind_sealed_pipes(lp_ctx);
311 seal_secure_channel = lpcfg_parm_bool(lp_ctx, NULL,
312 "winbind sealed pipes",
313 server_netbios_domain,
314 seal_secure_channel);
317 * allow overwrite per domain
318 * neutralize nt4 emulation:<netbios_domain>
320 neutralize_nt4_emulation = lpcfg_neutralize_nt4_emulation(lp_ctx);
321 neutralize_nt4_emulation = lpcfg_parm_bool(lp_ctx, NULL,
322 "neutralize nt4 emulation",
323 server_netbios_domain,
324 neutralize_nt4_emulation);
326 proposed_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
327 proposed_flags |= NETLOGON_NEG_SUPPORTS_AES;
331 if (lpcfg_security(lp_ctx) == SEC_ADS) {
333 * AD domains should be secure
335 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
336 require_sign_or_seal = true;
337 require_strong_key = true;
341 case SEC_CHAN_DOMAIN:
344 case SEC_CHAN_DNS_DOMAIN:
346 * AD domains should be secure
348 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
349 require_sign_or_seal = true;
350 require_strong_key = true;
351 neutralize_nt4_emulation = true;
355 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
356 require_sign_or_seal = true;
357 require_strong_key = true;
361 required_flags |= NETLOGON_NEG_RODC_PASSTHROUGH;
362 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
363 require_sign_or_seal = true;
364 require_strong_key = true;
365 neutralize_nt4_emulation = true;
370 return NT_STATUS_INVALID_PARAMETER;
373 if (neutralize_nt4_emulation) {
374 proposed_flags |= NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION;
377 if (require_sign_or_seal == false) {
378 proposed_flags &= ~NETLOGON_NEG_AUTHENTICATED_RPC;
380 required_flags |= NETLOGON_NEG_ARCFOUR;
381 required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC;
384 if (reject_md5_servers) {
385 required_flags |= NETLOGON_NEG_ARCFOUR;
386 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
387 required_flags |= NETLOGON_NEG_SUPPORTS_AES;
388 required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC;
391 if (require_strong_key) {
392 required_flags |= NETLOGON_NEG_ARCFOUR;
393 required_flags |= NETLOGON_NEG_STRONG_KEYS;
394 required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC;
397 proposed_flags |= required_flags;
399 if (seal_secure_channel) {
400 auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
402 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
405 status = netlogon_creds_cli_context_common(client_computer,
412 server_netbios_domain,
415 if (!NT_STATUS_IS_OK(status)) {
420 if (msg_ctx != NULL) {
421 context->db.g_ctx = g_lock_ctx_init(context, msg_ctx);
422 if (context->db.g_ctx == NULL) {
423 TALLOC_FREE(context);
425 return NT_STATUS_NO_MEMORY;
429 if (netlogon_creds_cli_global_db != NULL) {
430 context->db.ctx = netlogon_creds_cli_global_db;
436 status = netlogon_creds_cli_open_global_db(lp_ctx);
437 if (!NT_STATUS_IS_OK(status)) {
438 TALLOC_FREE(context);
440 return NT_STATUS_NO_MEMORY;
443 context->db.ctx = netlogon_creds_cli_global_db;
449 NTSTATUS netlogon_creds_cli_context_tmp(const char *client_computer,
450 const char *client_account,
451 enum netr_SchannelType type,
452 uint32_t proposed_flags,
453 uint32_t required_flags,
454 enum dcerpc_AuthLevel auth_level,
455 const char *server_computer,
456 const char *server_netbios_domain,
458 struct netlogon_creds_cli_context **_context)
461 struct netlogon_creds_cli_context *context = NULL;
465 status = netlogon_creds_cli_context_common(client_computer,
472 server_netbios_domain,
475 if (!NT_STATUS_IS_OK(status)) {
479 context->db.ctx = db_open_rbt(context);
480 if (context->db.ctx == NULL) {
481 talloc_free(context);
482 return NT_STATUS_NO_MEMORY;
489 char *netlogon_creds_cli_debug_string(
490 const struct netlogon_creds_cli_context *context,
493 return talloc_asprintf(mem_ctx, "netlogon_creds_cli:%s",
494 context->db.key_name);
497 enum dcerpc_AuthLevel netlogon_creds_cli_auth_level(
498 struct netlogon_creds_cli_context *context)
500 return context->client.auth_level;
503 struct netlogon_creds_cli_fetch_state {
505 struct netlogon_creds_CredentialState *creds;
506 uint32_t required_flags;
510 static void netlogon_creds_cli_fetch_parser(TDB_DATA key, TDB_DATA data,
513 struct netlogon_creds_cli_fetch_state *state =
514 (struct netlogon_creds_cli_fetch_state *)private_data;
515 enum ndr_err_code ndr_err;
519 state->creds = talloc_zero(state->mem_ctx,
520 struct netlogon_creds_CredentialState);
521 if (state->creds == NULL) {
522 state->status = NT_STATUS_NO_MEMORY;
526 blob.data = data.dptr;
527 blob.length = data.dsize;
529 ndr_err = ndr_pull_struct_blob(&blob, state->creds, state->creds,
530 (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState);
531 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
532 TALLOC_FREE(state->creds);
533 state->status = ndr_map_error2ntstatus(ndr_err);
537 tmp_flags = state->creds->negotiate_flags;
538 tmp_flags &= state->required_flags;
539 if (tmp_flags != state->required_flags) {
540 TALLOC_FREE(state->creds);
541 state->status = NT_STATUS_DOWNGRADE_DETECTED;
545 state->status = NT_STATUS_OK;
548 NTSTATUS netlogon_creds_cli_get(struct netlogon_creds_cli_context *context,
550 struct netlogon_creds_CredentialState **_creds)
553 struct netlogon_creds_cli_fetch_state fstate = {
555 .status = NT_STATUS_INTERNAL_ERROR,
556 .required_flags = context->client.required_flags,
558 static const struct netr_Credential zero_creds;
562 status = dbwrap_parse_record(context->db.ctx,
563 context->db.key_data,
564 netlogon_creds_cli_fetch_parser,
566 if (!NT_STATUS_IS_OK(status)) {
569 status = fstate.status;
570 if (!NT_STATUS_IS_OK(status)) {
575 * mark it as invalid for step operations.
577 fstate.creds->sequence = 0;
578 fstate.creds->seed = zero_creds;
579 fstate.creds->client = zero_creds;
580 fstate.creds->server = zero_creds;
582 if (context->server.cached_flags == fstate.creds->negotiate_flags) {
583 *_creds = fstate.creds;
588 * It is really important to try SamLogonEx here,
589 * because multiple processes can talk to the same
590 * domain controller, without using the credential
593 * With a normal SamLogon call, we must keep the
594 * credentials chain updated and intact between all
595 * users of the machine account (which would imply
596 * cross-node communication for every NTLM logon).
598 * The credentials chain is not per NETLOGON pipe
599 * connection, but globally on the server/client pair
600 * by computer name, while the client is free to use
601 * any computer name. We include the cluster node number
602 * in our computer name in order to avoid cross node
603 * coordination of the credential chain.
605 * It's also important to use NetlogonValidationSamInfo4 (6),
606 * because it relies on the rpc transport encryption
607 * and avoids using the global netlogon schannel
608 * session key to en/decrypt secret information
609 * like the user_session_key for network logons.
611 * [MS-APDS] 3.1.5.2 NTLM Network Logon
612 * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and
613 * NETLOGON_NEG_AUTHENTICATED_RPC set together
614 * are the indication that the server supports
615 * NetlogonValidationSamInfo4 (6). And it must only
616 * be used if "SealSecureChannel" is used.
618 * The "SealSecureChannel" AUTH_TYPE_SCHANNEL/AUTH_LEVEL_PRIVACY
619 * check is done in netlogon_creds_cli_LogonSamLogon*().
621 context->server.cached_flags = fstate.creds->negotiate_flags;
622 context->server.try_validation6 = true;
623 context->server.try_logon_ex = true;
624 context->server.try_logon_with = true;
626 if (!(context->server.cached_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
627 context->server.try_validation6 = false;
628 context->server.try_logon_ex = false;
630 if (!(context->server.cached_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) {
631 context->server.try_validation6 = false;
634 *_creds = fstate.creds;
638 bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context *context,
639 const struct netlogon_creds_CredentialState *creds1)
641 TALLOC_CTX *frame = talloc_stackframe();
642 struct netlogon_creds_CredentialState *creds2;
646 enum ndr_err_code ndr_err;
649 status = netlogon_creds_cli_get(context, frame, &creds2);
650 if (!NT_STATUS_IS_OK(status)) {
655 ndr_err = ndr_push_struct_blob(&blob1, frame, creds1,
656 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
657 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
662 ndr_err = ndr_push_struct_blob(&blob2, frame, creds2,
663 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
664 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
669 if (blob1.length != blob2.length) {
674 cmp = memcmp(blob1.data, blob2.data, blob1.length);
684 NTSTATUS netlogon_creds_cli_store(struct netlogon_creds_cli_context *context,
685 struct netlogon_creds_CredentialState **_creds)
687 struct netlogon_creds_CredentialState *creds = *_creds;
689 enum ndr_err_code ndr_err;
695 if (context->db.locked_state == NULL) {
697 * this was not the result of netlogon_creds_cli_lock*()
700 return NT_STATUS_INVALID_PAGE_PROTECTION;
703 if (context->db.locked_state->creds != creds) {
705 * this was not the result of netlogon_creds_cli_lock*()
708 return NT_STATUS_INVALID_PAGE_PROTECTION;
711 ndr_err = ndr_push_struct_blob(&blob, creds, creds,
712 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
713 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
715 status = ndr_map_error2ntstatus(ndr_err);
719 data.dptr = blob.data;
720 data.dsize = blob.length;
722 status = dbwrap_store(context->db.ctx,
723 context->db.key_data,
726 if (!NT_STATUS_IS_OK(status)) {
733 NTSTATUS netlogon_creds_cli_delete(struct netlogon_creds_cli_context *context,
734 struct netlogon_creds_CredentialState **_creds)
736 struct netlogon_creds_CredentialState *creds = *_creds;
741 if (context->db.locked_state == NULL) {
743 * this was not the result of netlogon_creds_cli_lock*()
746 return NT_STATUS_INVALID_PAGE_PROTECTION;
749 if (context->db.locked_state->creds != creds) {
751 * this was not the result of netlogon_creds_cli_lock*()
754 return NT_STATUS_INVALID_PAGE_PROTECTION;
757 status = dbwrap_delete(context->db.ctx,
758 context->db.key_data);
760 if (!NT_STATUS_IS_OK(status)) {
767 struct netlogon_creds_cli_lock_state {
768 struct netlogon_creds_cli_locked_state *locked_state;
769 struct netlogon_creds_CredentialState *creds;
772 static void netlogon_creds_cli_lock_done(struct tevent_req *subreq);
773 static void netlogon_creds_cli_lock_fetch(struct tevent_req *req);
775 struct tevent_req *netlogon_creds_cli_lock_send(TALLOC_CTX *mem_ctx,
776 struct tevent_context *ev,
777 struct netlogon_creds_cli_context *context)
779 struct tevent_req *req;
780 struct netlogon_creds_cli_lock_state *state;
781 struct netlogon_creds_cli_locked_state *locked_state;
782 struct tevent_req *subreq;
784 req = tevent_req_create(mem_ctx, &state,
785 struct netlogon_creds_cli_lock_state);
790 if (context->db.locked_state != NULL) {
791 tevent_req_nterror(req, NT_STATUS_LOCK_NOT_GRANTED);
792 return tevent_req_post(req, ev);
795 locked_state = talloc_zero(state, struct netlogon_creds_cli_locked_state);
796 if (tevent_req_nomem(locked_state, req)) {
797 return tevent_req_post(req, ev);
799 talloc_set_destructor(locked_state,
800 netlogon_creds_cli_locked_state_destructor);
801 locked_state->context = context;
803 context->db.locked_state = locked_state;
804 state->locked_state = locked_state;
806 if (context->db.g_ctx == NULL) {
807 netlogon_creds_cli_lock_fetch(req);
808 if (!tevent_req_is_in_progress(req)) {
809 return tevent_req_post(req, ev);
815 subreq = g_lock_lock_send(state, ev,
817 context->db.key_name,
819 if (tevent_req_nomem(subreq, req)) {
820 return tevent_req_post(req, ev);
822 tevent_req_set_callback(subreq, netlogon_creds_cli_lock_done, req);
827 static void netlogon_creds_cli_lock_done(struct tevent_req *subreq)
829 struct tevent_req *req =
830 tevent_req_callback_data(subreq,
832 struct netlogon_creds_cli_lock_state *state =
834 struct netlogon_creds_cli_lock_state);
837 status = g_lock_lock_recv(subreq);
839 if (tevent_req_nterror(req, status)) {
842 state->locked_state->is_glocked = true;
844 netlogon_creds_cli_lock_fetch(req);
847 static void netlogon_creds_cli_lock_fetch(struct tevent_req *req)
849 struct netlogon_creds_cli_lock_state *state =
851 struct netlogon_creds_cli_lock_state);
852 struct netlogon_creds_cli_context *context = state->locked_state->context;
853 struct netlogon_creds_cli_fetch_state fstate = {
854 .status = NT_STATUS_INTERNAL_ERROR,
855 .required_flags = context->client.required_flags,
859 fstate.mem_ctx = state;
860 status = dbwrap_parse_record(context->db.ctx,
861 context->db.key_data,
862 netlogon_creds_cli_fetch_parser,
864 if (tevent_req_nterror(req, status)) {
867 status = fstate.status;
868 if (tevent_req_nterror(req, status)) {
872 if (context->server.cached_flags == fstate.creds->negotiate_flags) {
873 state->creds = fstate.creds;
874 tevent_req_done(req);
878 context->server.cached_flags = fstate.creds->negotiate_flags;
879 context->server.try_validation6 = true;
880 context->server.try_logon_ex = true;
881 context->server.try_logon_with = true;
883 if (!(context->server.cached_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
884 context->server.try_validation6 = false;
885 context->server.try_logon_ex = false;
887 if (!(context->server.cached_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) {
888 context->server.try_validation6 = false;
891 state->creds = fstate.creds;
892 tevent_req_done(req);
896 NTSTATUS netlogon_creds_cli_lock_recv(struct tevent_req *req,
898 struct netlogon_creds_CredentialState **creds)
900 struct netlogon_creds_cli_lock_state *state =
902 struct netlogon_creds_cli_lock_state);
905 if (tevent_req_is_nterror(req, &status)) {
906 tevent_req_received(req);
910 talloc_steal(state->creds, state->locked_state);
911 state->locked_state->creds = state->creds;
912 *creds = talloc_move(mem_ctx, &state->creds);
913 tevent_req_received(req);
917 NTSTATUS netlogon_creds_cli_lock(struct netlogon_creds_cli_context *context,
919 struct netlogon_creds_CredentialState **creds)
921 TALLOC_CTX *frame = talloc_stackframe();
922 struct tevent_context *ev;
923 struct tevent_req *req;
924 NTSTATUS status = NT_STATUS_NO_MEMORY;
926 ev = samba_tevent_context_init(frame);
930 req = netlogon_creds_cli_lock_send(frame, ev, context);
934 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
937 status = netlogon_creds_cli_lock_recv(req, mem_ctx, creds);
943 struct netlogon_creds_cli_auth_state {
944 struct tevent_context *ev;
945 struct netlogon_creds_cli_context *context;
946 struct dcerpc_binding_handle *binding_handle;
947 uint8_t num_nt_hashes;
948 uint8_t idx_nt_hashes;
949 const struct samr_Password * const *nt_hashes;
950 const struct samr_Password *used_nt_hash;
951 char *srv_name_slash;
952 uint32_t current_flags;
953 struct netr_Credential client_challenge;
954 struct netr_Credential server_challenge;
955 struct netlogon_creds_CredentialState *creds;
956 struct netr_Credential client_credential;
957 struct netr_Credential server_credential;
962 struct netlogon_creds_cli_locked_state *locked_state;
965 static void netlogon_creds_cli_auth_locked(struct tevent_req *subreq);
966 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req *req);
968 struct tevent_req *netlogon_creds_cli_auth_send(TALLOC_CTX *mem_ctx,
969 struct tevent_context *ev,
970 struct netlogon_creds_cli_context *context,
971 struct dcerpc_binding_handle *b,
972 uint8_t num_nt_hashes,
973 const struct samr_Password * const *nt_hashes)
975 struct tevent_req *req;
976 struct netlogon_creds_cli_auth_state *state;
977 struct netlogon_creds_cli_locked_state *locked_state;
980 req = tevent_req_create(mem_ctx, &state,
981 struct netlogon_creds_cli_auth_state);
987 state->context = context;
988 state->binding_handle = b;
989 if (num_nt_hashes < 1) {
990 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
991 return tevent_req_post(req, ev);
993 if (num_nt_hashes > 4) {
994 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
995 return tevent_req_post(req, ev);
998 state->num_nt_hashes = num_nt_hashes;
999 state->idx_nt_hashes = 0;
1000 state->nt_hashes = nt_hashes;
1002 if (context->db.locked_state != NULL) {
1003 tevent_req_nterror(req, NT_STATUS_LOCK_NOT_GRANTED);
1004 return tevent_req_post(req, ev);
1007 locked_state = talloc_zero(state, struct netlogon_creds_cli_locked_state);
1008 if (tevent_req_nomem(locked_state, req)) {
1009 return tevent_req_post(req, ev);
1011 talloc_set_destructor(locked_state,
1012 netlogon_creds_cli_locked_state_destructor);
1013 locked_state->context = context;
1015 context->db.locked_state = locked_state;
1016 state->locked_state = locked_state;
1018 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
1019 context->server.computer);
1020 if (tevent_req_nomem(state->srv_name_slash, req)) {
1021 return tevent_req_post(req, ev);
1024 state->try_auth3 = true;
1025 state->try_auth2 = true;
1027 if (context->client.required_flags != 0) {
1028 state->require_auth2 = true;
1031 state->used_nt_hash = state->nt_hashes[state->idx_nt_hashes];
1032 state->current_flags = context->client.proposed_flags;
1034 if (context->db.g_ctx != NULL) {
1035 struct tevent_req *subreq;
1037 subreq = g_lock_lock_send(state, ev,
1039 context->db.key_name,
1041 if (tevent_req_nomem(subreq, req)) {
1042 return tevent_req_post(req, ev);
1044 tevent_req_set_callback(subreq,
1045 netlogon_creds_cli_auth_locked,
1051 status = dbwrap_purge(state->context->db.ctx,
1052 state->context->db.key_data);
1053 if (tevent_req_nterror(req, status)) {
1054 return tevent_req_post(req, ev);
1057 netlogon_creds_cli_auth_challenge_start(req);
1058 if (!tevent_req_is_in_progress(req)) {
1059 return tevent_req_post(req, ev);
1065 static void netlogon_creds_cli_auth_locked(struct tevent_req *subreq)
1067 struct tevent_req *req =
1068 tevent_req_callback_data(subreq,
1070 struct netlogon_creds_cli_auth_state *state =
1071 tevent_req_data(req,
1072 struct netlogon_creds_cli_auth_state);
1075 status = g_lock_lock_recv(subreq);
1076 TALLOC_FREE(subreq);
1077 if (tevent_req_nterror(req, status)) {
1080 state->locked_state->is_glocked = true;
1082 status = dbwrap_purge(state->context->db.ctx,
1083 state->context->db.key_data);
1084 if (tevent_req_nterror(req, status)) {
1088 netlogon_creds_cli_auth_challenge_start(req);
1091 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq);
1093 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req *req)
1095 struct netlogon_creds_cli_auth_state *state =
1096 tevent_req_data(req,
1097 struct netlogon_creds_cli_auth_state);
1098 struct tevent_req *subreq;
1100 TALLOC_FREE(state->creds);
1102 generate_random_buffer(state->client_challenge.data,
1103 sizeof(state->client_challenge.data));
1105 subreq = dcerpc_netr_ServerReqChallenge_send(state, state->ev,
1106 state->binding_handle,
1107 state->srv_name_slash,
1108 state->context->client.computer,
1109 &state->client_challenge,
1110 &state->server_challenge);
1111 if (tevent_req_nomem(subreq, req)) {
1114 tevent_req_set_callback(subreq,
1115 netlogon_creds_cli_auth_challenge_done,
1119 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq);
1121 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq)
1123 struct tevent_req *req =
1124 tevent_req_callback_data(subreq,
1126 struct netlogon_creds_cli_auth_state *state =
1127 tevent_req_data(req,
1128 struct netlogon_creds_cli_auth_state);
1132 status = dcerpc_netr_ServerReqChallenge_recv(subreq, state, &result);
1133 TALLOC_FREE(subreq);
1134 if (tevent_req_nterror(req, status)) {
1137 if (tevent_req_nterror(req, result)) {
1141 if (!state->try_auth3 && !state->try_auth2) {
1142 state->current_flags = 0;
1145 /* Calculate the session key and client credentials */
1147 state->creds = netlogon_creds_client_init(state,
1148 state->context->client.account,
1149 state->context->client.computer,
1150 state->context->client.type,
1151 &state->client_challenge,
1152 &state->server_challenge,
1153 state->used_nt_hash,
1154 &state->client_credential,
1155 state->current_flags);
1156 if (tevent_req_nomem(state->creds, req)) {
1160 if (state->try_auth3) {
1161 subreq = dcerpc_netr_ServerAuthenticate3_send(state, state->ev,
1162 state->binding_handle,
1163 state->srv_name_slash,
1164 state->context->client.account,
1165 state->context->client.type,
1166 state->context->client.computer,
1167 &state->client_credential,
1168 &state->server_credential,
1169 &state->creds->negotiate_flags,
1171 if (tevent_req_nomem(subreq, req)) {
1174 } else if (state->try_auth2) {
1177 subreq = dcerpc_netr_ServerAuthenticate2_send(state, state->ev,
1178 state->binding_handle,
1179 state->srv_name_slash,
1180 state->context->client.account,
1181 state->context->client.type,
1182 state->context->client.computer,
1183 &state->client_credential,
1184 &state->server_credential,
1185 &state->creds->negotiate_flags);
1186 if (tevent_req_nomem(subreq, req)) {
1192 subreq = dcerpc_netr_ServerAuthenticate_send(state, state->ev,
1193 state->binding_handle,
1194 state->srv_name_slash,
1195 state->context->client.account,
1196 state->context->client.type,
1197 state->context->client.computer,
1198 &state->client_credential,
1199 &state->server_credential);
1200 if (tevent_req_nomem(subreq, req)) {
1204 tevent_req_set_callback(subreq,
1205 netlogon_creds_cli_auth_srvauth_done,
1209 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq)
1211 struct tevent_req *req =
1212 tevent_req_callback_data(subreq,
1214 struct netlogon_creds_cli_auth_state *state =
1215 tevent_req_data(req,
1216 struct netlogon_creds_cli_auth_state);
1220 enum ndr_err_code ndr_err;
1225 if (state->try_auth3) {
1226 status = dcerpc_netr_ServerAuthenticate3_recv(subreq, state,
1228 TALLOC_FREE(subreq);
1229 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1230 state->try_auth3 = false;
1231 netlogon_creds_cli_auth_challenge_start(req);
1234 if (tevent_req_nterror(req, status)) {
1237 } else if (state->try_auth2) {
1238 status = dcerpc_netr_ServerAuthenticate2_recv(subreq, state,
1240 TALLOC_FREE(subreq);
1241 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1242 state->try_auth2 = false;
1243 if (state->require_auth2) {
1244 status = NT_STATUS_DOWNGRADE_DETECTED;
1245 tevent_req_nterror(req, status);
1248 netlogon_creds_cli_auth_challenge_start(req);
1251 if (tevent_req_nterror(req, status)) {
1255 status = dcerpc_netr_ServerAuthenticate_recv(subreq, state,
1257 TALLOC_FREE(subreq);
1258 if (tevent_req_nterror(req, status)) {
1263 if (!NT_STATUS_IS_OK(result) &&
1264 !NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED))
1266 tevent_req_nterror(req, result);
1270 tmp_flags = state->creds->negotiate_flags;
1271 tmp_flags &= state->context->client.required_flags;
1272 if (tmp_flags != state->context->client.required_flags) {
1273 if (NT_STATUS_IS_OK(result)) {
1274 tevent_req_nterror(req, NT_STATUS_DOWNGRADE_DETECTED);
1277 tevent_req_nterror(req, result);
1281 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
1283 tmp_flags = state->context->client.proposed_flags;
1284 if ((state->current_flags == tmp_flags) &&
1285 (state->creds->negotiate_flags != tmp_flags))
1288 * lets retry with the negotiated flags
1290 state->current_flags = state->creds->negotiate_flags;
1291 netlogon_creds_cli_auth_challenge_start(req);
1295 state->idx_nt_hashes += 1;
1296 if (state->idx_nt_hashes >= state->num_nt_hashes) {
1298 * we already retried, giving up...
1300 tevent_req_nterror(req, result);
1305 * lets retry with the old nt hash.
1307 state->used_nt_hash = state->nt_hashes[state->idx_nt_hashes];
1308 state->current_flags = state->context->client.proposed_flags;
1309 netlogon_creds_cli_auth_challenge_start(req);
1313 ok = netlogon_creds_client_check(state->creds,
1314 &state->server_credential);
1316 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1320 ndr_err = ndr_push_struct_blob(&blob, state, state->creds,
1321 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
1322 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1323 status = ndr_map_error2ntstatus(ndr_err);
1324 tevent_req_nterror(req, status);
1328 data.dptr = blob.data;
1329 data.dsize = blob.length;
1331 status = dbwrap_store(state->context->db.ctx,
1332 state->context->db.key_data,
1334 TALLOC_FREE(state->locked_state);
1335 if (tevent_req_nterror(req, status)) {
1339 tevent_req_done(req);
1342 NTSTATUS netlogon_creds_cli_auth_recv(struct tevent_req *req,
1343 uint8_t *idx_nt_hashes)
1345 struct netlogon_creds_cli_auth_state *state =
1346 tevent_req_data(req,
1347 struct netlogon_creds_cli_auth_state);
1352 if (tevent_req_is_nterror(req, &status)) {
1353 tevent_req_received(req);
1357 *idx_nt_hashes = state->idx_nt_hashes;
1358 tevent_req_received(req);
1359 return NT_STATUS_OK;
1362 NTSTATUS netlogon_creds_cli_auth(struct netlogon_creds_cli_context *context,
1363 struct dcerpc_binding_handle *b,
1364 uint8_t num_nt_hashes,
1365 const struct samr_Password * const *nt_hashes,
1366 uint8_t *idx_nt_hashes)
1368 TALLOC_CTX *frame = talloc_stackframe();
1369 struct tevent_context *ev;
1370 struct tevent_req *req;
1371 NTSTATUS status = NT_STATUS_NO_MEMORY;
1375 ev = samba_tevent_context_init(frame);
1379 req = netlogon_creds_cli_auth_send(frame, ev, context, b,
1380 num_nt_hashes, nt_hashes);
1384 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1387 status = netlogon_creds_cli_auth_recv(req, idx_nt_hashes);
1393 struct netlogon_creds_cli_check_state {
1394 struct tevent_context *ev;
1395 struct netlogon_creds_cli_context *context;
1396 struct dcerpc_binding_handle *binding_handle;
1398 char *srv_name_slash;
1400 union netr_Capabilities caps;
1402 struct netlogon_creds_CredentialState *creds;
1403 struct netlogon_creds_CredentialState tmp_creds;
1404 struct netr_Authenticator req_auth;
1405 struct netr_Authenticator rep_auth;
1408 static void netlogon_creds_cli_check_cleanup(struct tevent_req *req,
1410 static void netlogon_creds_cli_check_locked(struct tevent_req *subreq);
1412 struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx,
1413 struct tevent_context *ev,
1414 struct netlogon_creds_cli_context *context,
1415 struct dcerpc_binding_handle *b)
1417 struct tevent_req *req;
1418 struct netlogon_creds_cli_check_state *state;
1419 struct tevent_req *subreq;
1420 enum dcerpc_AuthType auth_type;
1421 enum dcerpc_AuthLevel auth_level;
1423 req = tevent_req_create(mem_ctx, &state,
1424 struct netlogon_creds_cli_check_state);
1430 state->context = context;
1431 state->binding_handle = b;
1433 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
1434 context->server.computer);
1435 if (tevent_req_nomem(state->srv_name_slash, req)) {
1436 return tevent_req_post(req, ev);
1439 dcerpc_binding_handle_auth_info(state->binding_handle,
1440 &auth_type, &auth_level);
1442 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1443 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1444 return tevent_req_post(req, ev);
1447 switch (auth_level) {
1448 case DCERPC_AUTH_LEVEL_INTEGRITY:
1449 case DCERPC_AUTH_LEVEL_PRIVACY:
1452 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1453 return tevent_req_post(req, ev);
1456 subreq = netlogon_creds_cli_lock_send(state, state->ev,
1458 if (tevent_req_nomem(subreq, req)) {
1459 return tevent_req_post(req, ev);
1462 tevent_req_set_callback(subreq,
1463 netlogon_creds_cli_check_locked,
1469 static void netlogon_creds_cli_check_cleanup(struct tevent_req *req,
1472 struct netlogon_creds_cli_check_state *state =
1473 tevent_req_data(req,
1474 struct netlogon_creds_cli_check_state);
1476 if (state->creds == NULL) {
1480 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
1481 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
1482 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
1483 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
1484 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1485 TALLOC_FREE(state->creds);
1489 netlogon_creds_cli_delete(state->context, &state->creds);
1492 static void netlogon_creds_cli_check_caps(struct tevent_req *subreq);
1494 static void netlogon_creds_cli_check_locked(struct tevent_req *subreq)
1496 struct tevent_req *req =
1497 tevent_req_callback_data(subreq,
1499 struct netlogon_creds_cli_check_state *state =
1500 tevent_req_data(req,
1501 struct netlogon_creds_cli_check_state);
1504 status = netlogon_creds_cli_lock_recv(subreq, state,
1506 TALLOC_FREE(subreq);
1507 if (tevent_req_nterror(req, status)) {
1512 * we defer all callbacks in order to cleanup
1513 * the database record.
1515 tevent_req_defer_callback(req, state->ev);
1517 state->tmp_creds = *state->creds;
1518 netlogon_creds_client_authenticator(&state->tmp_creds,
1520 ZERO_STRUCT(state->rep_auth);
1522 subreq = dcerpc_netr_LogonGetCapabilities_send(state, state->ev,
1523 state->binding_handle,
1524 state->srv_name_slash,
1525 state->context->client.computer,
1530 if (tevent_req_nomem(subreq, req)) {
1531 status = NT_STATUS_NO_MEMORY;
1532 netlogon_creds_cli_check_cleanup(req, status);
1535 tevent_req_set_callback(subreq,
1536 netlogon_creds_cli_check_caps,
1540 static void netlogon_creds_cli_check_caps(struct tevent_req *subreq)
1542 struct tevent_req *req =
1543 tevent_req_callback_data(subreq,
1545 struct netlogon_creds_cli_check_state *state =
1546 tevent_req_data(req,
1547 struct netlogon_creds_cli_check_state);
1552 status = dcerpc_netr_LogonGetCapabilities_recv(subreq, state,
1554 TALLOC_FREE(subreq);
1555 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1557 * Note that the negotiated flags are already checked
1558 * for our required flags after the ServerAuthenticate3/2 call.
1560 uint32_t negotiated = state->tmp_creds.negotiate_flags;
1562 if (negotiated & NETLOGON_NEG_SUPPORTS_AES) {
1564 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1565 * already, we expect this to work!
1567 status = NT_STATUS_DOWNGRADE_DETECTED;
1568 tevent_req_nterror(req, status);
1569 netlogon_creds_cli_check_cleanup(req, status);
1573 if (negotiated & NETLOGON_NEG_STRONG_KEYS) {
1575 * If we have negotiated NETLOGON_NEG_STRONG_KEYS
1576 * we expect this to work at least as far as the
1577 * NOT_SUPPORTED error handled below!
1579 * NT 4.0 and Old Samba servers are not
1580 * allowed without "require strong key = no"
1582 status = NT_STATUS_DOWNGRADE_DETECTED;
1583 tevent_req_nterror(req, status);
1584 netlogon_creds_cli_check_cleanup(req, status);
1589 * If we not require NETLOGON_NEG_SUPPORTS_AES or
1590 * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore
1591 * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
1593 * This is needed against NT 4.0 and old Samba servers.
1595 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
1596 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
1597 * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
1598 * with the next request as the sequence number processing
1601 netlogon_creds_cli_check_cleanup(req, status);
1602 tevent_req_done(req);
1605 if (tevent_req_nterror(req, status)) {
1606 netlogon_creds_cli_check_cleanup(req, status);
1610 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
1612 * Note that the negotiated flags are already checked
1613 * for our required flags after the ServerAuthenticate3/2 call.
1615 uint32_t negotiated = state->tmp_creds.negotiate_flags;
1617 if (negotiated & NETLOGON_NEG_SUPPORTS_AES) {
1619 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1620 * already, we expect this to work!
1622 status = NT_STATUS_DOWNGRADE_DETECTED;
1623 tevent_req_nterror(req, status);
1624 netlogon_creds_cli_check_cleanup(req, status);
1629 * This is ok, the server does not support
1630 * NETLOGON_NEG_SUPPORTS_AES.
1632 * netr_LogonGetCapabilities() was
1633 * netr_LogonDummyRoutine1() before
1634 * NETLOGON_NEG_SUPPORTS_AES was invented.
1636 netlogon_creds_cli_check_cleanup(req, result);
1637 tevent_req_done(req);
1641 ok = netlogon_creds_client_check(&state->tmp_creds,
1642 &state->rep_auth.cred);
1644 status = NT_STATUS_ACCESS_DENIED;
1645 tevent_req_nterror(req, status);
1646 netlogon_creds_cli_check_cleanup(req, status);
1650 if (tevent_req_nterror(req, result)) {
1651 netlogon_creds_cli_check_cleanup(req, result);
1655 if (state->caps.server_capabilities != state->tmp_creds.negotiate_flags) {
1656 status = NT_STATUS_DOWNGRADE_DETECTED;
1657 tevent_req_nterror(req, status);
1658 netlogon_creds_cli_check_cleanup(req, status);
1663 * This is the key check that makes this check secure. If we
1664 * get OK here (rather than NOT_SUPPORTED), then the server
1665 * did support AES. If the server only proposed STRONG_KEYS
1666 * and not AES, then it should have failed with
1667 * NOT_IMPLEMENTED. We always send AES as a client, so the
1668 * server should always have returned it.
1670 if (!(state->caps.server_capabilities & NETLOGON_NEG_SUPPORTS_AES)) {
1671 status = NT_STATUS_DOWNGRADE_DETECTED;
1672 tevent_req_nterror(req, status);
1673 netlogon_creds_cli_check_cleanup(req, status);
1677 *state->creds = state->tmp_creds;
1678 status = netlogon_creds_cli_store(state->context,
1680 netlogon_creds_cli_check_cleanup(req, status);
1681 if (tevent_req_nterror(req, status)) {
1685 tevent_req_done(req);
1688 NTSTATUS netlogon_creds_cli_check_recv(struct tevent_req *req)
1692 if (tevent_req_is_nterror(req, &status)) {
1693 netlogon_creds_cli_check_cleanup(req, status);
1694 tevent_req_received(req);
1698 tevent_req_received(req);
1699 return NT_STATUS_OK;
1702 NTSTATUS netlogon_creds_cli_check(struct netlogon_creds_cli_context *context,
1703 struct dcerpc_binding_handle *b)
1705 TALLOC_CTX *frame = talloc_stackframe();
1706 struct tevent_context *ev;
1707 struct tevent_req *req;
1708 NTSTATUS status = NT_STATUS_NO_MEMORY;
1710 ev = samba_tevent_context_init(frame);
1714 req = netlogon_creds_cli_check_send(frame, ev, context, b);
1718 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1721 status = netlogon_creds_cli_check_recv(req);
1727 struct netlogon_creds_cli_ServerPasswordSet_state {
1728 struct tevent_context *ev;
1729 struct netlogon_creds_cli_context *context;
1730 struct dcerpc_binding_handle *binding_handle;
1731 uint32_t old_timeout;
1733 char *srv_name_slash;
1734 enum dcerpc_AuthType auth_type;
1735 enum dcerpc_AuthLevel auth_level;
1737 struct samr_CryptPassword samr_crypt_password;
1738 struct netr_CryptPassword netr_crypt_password;
1739 struct samr_Password samr_password;
1741 struct netlogon_creds_CredentialState *creds;
1742 struct netlogon_creds_CredentialState tmp_creds;
1743 struct netr_Authenticator req_auth;
1744 struct netr_Authenticator rep_auth;
1747 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req *req,
1749 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subreq);
1751 struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx,
1752 struct tevent_context *ev,
1753 struct netlogon_creds_cli_context *context,
1754 struct dcerpc_binding_handle *b,
1755 const DATA_BLOB *new_password,
1756 const uint32_t *new_version)
1758 struct tevent_req *req;
1759 struct netlogon_creds_cli_ServerPasswordSet_state *state;
1760 struct tevent_req *subreq;
1763 req = tevent_req_create(mem_ctx, &state,
1764 struct netlogon_creds_cli_ServerPasswordSet_state);
1770 state->context = context;
1771 state->binding_handle = b;
1773 if (new_password->length < 14) {
1774 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1775 return tevent_req_post(req, ev);
1779 * netr_ServerPasswordSet
1781 mdfour(state->samr_password.hash, new_password->data, new_password->length);
1784 * netr_ServerPasswordSet2
1786 ok = set_pw_in_buffer(state->samr_crypt_password.data,
1789 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1790 return tevent_req_post(req, ev);
1793 if (new_version != NULL) {
1794 struct NL_PASSWORD_VERSION version;
1795 uint32_t len = IVAL(state->samr_crypt_password.data, 512);
1796 uint32_t ofs = 512 - len;
1800 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1801 return tevent_req_post(req, ev);
1805 version.ReservedField = 0;
1806 version.PasswordVersionNumber = *new_version;
1807 version.PasswordVersionPresent =
1808 NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT;
1810 p = state->samr_crypt_password.data + ofs;
1811 SIVAL(p, 0, version.ReservedField);
1812 SIVAL(p, 4, version.PasswordVersionNumber);
1813 SIVAL(p, 8, version.PasswordVersionPresent);
1816 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
1817 context->server.computer);
1818 if (tevent_req_nomem(state->srv_name_slash, req)) {
1819 return tevent_req_post(req, ev);
1822 dcerpc_binding_handle_auth_info(state->binding_handle,
1824 &state->auth_level);
1826 subreq = netlogon_creds_cli_lock_send(state, state->ev,
1828 if (tevent_req_nomem(subreq, req)) {
1829 return tevent_req_post(req, ev);
1832 tevent_req_set_callback(subreq,
1833 netlogon_creds_cli_ServerPasswordSet_locked,
1839 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req *req,
1842 struct netlogon_creds_cli_ServerPasswordSet_state *state =
1843 tevent_req_data(req,
1844 struct netlogon_creds_cli_ServerPasswordSet_state);
1846 if (state->creds == NULL) {
1850 dcerpc_binding_handle_set_timeout(state->binding_handle,
1851 state->old_timeout);
1853 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
1854 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
1855 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
1856 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
1857 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1858 TALLOC_FREE(state->creds);
1862 netlogon_creds_cli_delete(state->context, &state->creds);
1865 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq);
1867 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subreq)
1869 struct tevent_req *req =
1870 tevent_req_callback_data(subreq,
1872 struct netlogon_creds_cli_ServerPasswordSet_state *state =
1873 tevent_req_data(req,
1874 struct netlogon_creds_cli_ServerPasswordSet_state);
1877 status = netlogon_creds_cli_lock_recv(subreq, state,
1879 TALLOC_FREE(subreq);
1880 if (tevent_req_nterror(req, status)) {
1884 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
1885 switch (state->auth_level) {
1886 case DCERPC_AUTH_LEVEL_INTEGRITY:
1887 case DCERPC_AUTH_LEVEL_PRIVACY:
1890 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1894 uint32_t tmp = state->creds->negotiate_flags;
1896 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
1898 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
1899 * it should be used, which means
1900 * we had a chance to verify no downgrade
1903 * This relies on netlogon_creds_cli_check*
1904 * being called before, as first request after
1907 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1912 state->old_timeout = dcerpc_binding_handle_set_timeout(
1913 state->binding_handle, 600000);
1916 * we defer all callbacks in order to cleanup
1917 * the database record.
1919 tevent_req_defer_callback(req, state->ev);
1921 state->tmp_creds = *state->creds;
1922 netlogon_creds_client_authenticator(&state->tmp_creds,
1924 ZERO_STRUCT(state->rep_auth);
1926 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) {
1928 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1929 netlogon_creds_aes_encrypt(&state->tmp_creds,
1930 state->samr_crypt_password.data,
1933 netlogon_creds_arcfour_crypt(&state->tmp_creds,
1934 state->samr_crypt_password.data,
1938 memcpy(state->netr_crypt_password.data,
1939 state->samr_crypt_password.data, 512);
1940 state->netr_crypt_password.length =
1941 IVAL(state->samr_crypt_password.data, 512);
1943 subreq = dcerpc_netr_ServerPasswordSet2_send(state, state->ev,
1944 state->binding_handle,
1945 state->srv_name_slash,
1946 state->tmp_creds.account_name,
1947 state->tmp_creds.secure_channel_type,
1948 state->tmp_creds.computer_name,
1951 &state->netr_crypt_password);
1952 if (tevent_req_nomem(subreq, req)) {
1953 status = NT_STATUS_NO_MEMORY;
1954 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1958 netlogon_creds_des_encrypt(&state->tmp_creds,
1959 &state->samr_password);
1961 subreq = dcerpc_netr_ServerPasswordSet_send(state, state->ev,
1962 state->binding_handle,
1963 state->srv_name_slash,
1964 state->tmp_creds.account_name,
1965 state->tmp_creds.secure_channel_type,
1966 state->tmp_creds.computer_name,
1969 &state->samr_password);
1970 if (tevent_req_nomem(subreq, req)) {
1971 status = NT_STATUS_NO_MEMORY;
1972 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1977 tevent_req_set_callback(subreq,
1978 netlogon_creds_cli_ServerPasswordSet_done,
1982 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq)
1984 struct tevent_req *req =
1985 tevent_req_callback_data(subreq,
1987 struct netlogon_creds_cli_ServerPasswordSet_state *state =
1988 tevent_req_data(req,
1989 struct netlogon_creds_cli_ServerPasswordSet_state);
1994 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) {
1995 status = dcerpc_netr_ServerPasswordSet2_recv(subreq, state,
1997 TALLOC_FREE(subreq);
1998 if (tevent_req_nterror(req, status)) {
1999 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2003 status = dcerpc_netr_ServerPasswordSet_recv(subreq, state,
2005 TALLOC_FREE(subreq);
2006 if (tevent_req_nterror(req, status)) {
2007 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2012 ok = netlogon_creds_client_check(&state->tmp_creds,
2013 &state->rep_auth.cred);
2015 status = NT_STATUS_ACCESS_DENIED;
2016 tevent_req_nterror(req, status);
2017 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2021 if (tevent_req_nterror(req, result)) {
2022 netlogon_creds_cli_ServerPasswordSet_cleanup(req, result);
2026 dcerpc_binding_handle_set_timeout(state->binding_handle,
2027 state->old_timeout);
2029 *state->creds = state->tmp_creds;
2030 status = netlogon_creds_cli_store(state->context,
2032 if (tevent_req_nterror(req, status)) {
2033 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2037 tevent_req_done(req);
2040 NTSTATUS netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req *req)
2044 if (tevent_req_is_nterror(req, &status)) {
2045 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2046 tevent_req_received(req);
2050 tevent_req_received(req);
2051 return NT_STATUS_OK;
2054 NTSTATUS netlogon_creds_cli_ServerPasswordSet(
2055 struct netlogon_creds_cli_context *context,
2056 struct dcerpc_binding_handle *b,
2057 const DATA_BLOB *new_password,
2058 const uint32_t *new_version)
2060 TALLOC_CTX *frame = talloc_stackframe();
2061 struct tevent_context *ev;
2062 struct tevent_req *req;
2063 NTSTATUS status = NT_STATUS_NO_MEMORY;
2065 ev = samba_tevent_context_init(frame);
2069 req = netlogon_creds_cli_ServerPasswordSet_send(frame, ev, context, b,
2075 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2078 status = netlogon_creds_cli_ServerPasswordSet_recv(req);
2084 struct netlogon_creds_cli_LogonSamLogon_state {
2085 struct tevent_context *ev;
2086 struct netlogon_creds_cli_context *context;
2087 struct dcerpc_binding_handle *binding_handle;
2089 char *srv_name_slash;
2091 enum netr_LogonInfoClass logon_level;
2092 const union netr_LogonLevel *const_logon;
2093 union netr_LogonLevel *logon;
2096 uint16_t validation_level;
2097 union netr_Validation *validation;
2098 uint8_t authoritative;
2101 * do we need encryption at the application layer?
2105 bool try_validation6;
2108 * the read only credentials before we started the operation
2109 * used for netr_LogonSamLogonEx() if required (validation_level = 3).
2111 struct netlogon_creds_CredentialState *ro_creds;
2114 * The (locked) credentials used for the credential chain
2115 * used for netr_LogonSamLogonWithFlags() or
2116 * netr_LogonSamLogonWith().
2118 struct netlogon_creds_CredentialState *lk_creds;
2121 * While we have locked the global credentials (lk_creds above)
2122 * we operate an a temporary copy, because a server
2123 * may not support netr_LogonSamLogonWithFlags() and
2124 * didn't process our netr_Authenticator, so we need to
2125 * restart from lk_creds.
2127 struct netlogon_creds_CredentialState tmp_creds;
2128 struct netr_Authenticator req_auth;
2129 struct netr_Authenticator rep_auth;
2132 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req);
2133 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req *req,
2136 struct tevent_req *netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX *mem_ctx,
2137 struct tevent_context *ev,
2138 struct netlogon_creds_cli_context *context,
2139 struct dcerpc_binding_handle *b,
2140 enum netr_LogonInfoClass logon_level,
2141 const union netr_LogonLevel *logon,
2144 struct tevent_req *req;
2145 struct netlogon_creds_cli_LogonSamLogon_state *state;
2147 req = tevent_req_create(mem_ctx, &state,
2148 struct netlogon_creds_cli_LogonSamLogon_state);
2154 state->context = context;
2155 state->binding_handle = b;
2157 state->logon_level = logon_level;
2158 state->const_logon = logon;
2159 state->flags = flags;
2161 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
2162 context->server.computer);
2163 if (tevent_req_nomem(state->srv_name_slash, req)) {
2164 return tevent_req_post(req, ev);
2167 switch (logon_level) {
2168 case NetlogonInteractiveInformation:
2169 case NetlogonInteractiveTransitiveInformation:
2170 case NetlogonServiceInformation:
2171 case NetlogonServiceTransitiveInformation:
2172 case NetlogonGenericInformation:
2173 state->user_encrypt = true;
2176 case NetlogonNetworkInformation:
2177 case NetlogonNetworkTransitiveInformation:
2181 state->validation = talloc_zero(state, union netr_Validation);
2182 if (tevent_req_nomem(state->validation, req)) {
2183 return tevent_req_post(req, ev);
2186 netlogon_creds_cli_LogonSamLogon_start(req);
2187 if (!tevent_req_is_in_progress(req)) {
2188 return tevent_req_post(req, ev);
2192 * we defer all callbacks in order to cleanup
2193 * the database record.
2195 tevent_req_defer_callback(req, state->ev);
2199 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req *req,
2202 struct netlogon_creds_cli_LogonSamLogon_state *state =
2203 tevent_req_data(req,
2204 struct netlogon_creds_cli_LogonSamLogon_state);
2206 if (state->lk_creds == NULL) {
2210 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2212 * This is a hack to recover from a bug in old
2213 * Samba servers, when LogonSamLogonEx() fails:
2215 * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
2217 * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2219 * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE,
2220 * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR
2221 * If the sign/seal check fails.
2223 * In that case we need to cleanup the netlogon session.
2225 * It's the job of the caller to disconnect the current
2226 * connection, if netlogon_creds_cli_LogonSamLogon()
2227 * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2229 if (!state->context->server.try_logon_with) {
2230 status = NT_STATUS_NETWORK_ACCESS_DENIED;
2234 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
2235 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
2236 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
2237 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
2238 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
2239 TALLOC_FREE(state->lk_creds);
2243 netlogon_creds_cli_delete(state->context, &state->lk_creds);
2246 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq);
2248 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req)
2250 struct netlogon_creds_cli_LogonSamLogon_state *state =
2251 tevent_req_data(req,
2252 struct netlogon_creds_cli_LogonSamLogon_state);
2253 struct tevent_req *subreq;
2255 enum dcerpc_AuthType auth_type;
2256 enum dcerpc_AuthLevel auth_level;
2258 TALLOC_FREE(state->ro_creds);
2259 TALLOC_FREE(state->logon);
2260 ZERO_STRUCTP(state->validation);
2262 dcerpc_binding_handle_auth_info(state->binding_handle,
2263 &auth_type, &auth_level);
2265 state->try_logon_ex = state->context->server.try_logon_ex;
2266 state->try_validation6 = state->context->server.try_validation6;
2268 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
2269 state->try_logon_ex = false;
2272 if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
2273 state->try_validation6 = false;
2276 if (state->try_logon_ex) {
2277 if (state->try_validation6) {
2278 state->validation_level = 6;
2280 state->validation_level = 3;
2281 state->user_encrypt = true;
2284 state->logon = netlogon_creds_shallow_copy_logon(state,
2286 state->const_logon);
2287 if (tevent_req_nomem(state->logon, req)) {
2288 status = NT_STATUS_NO_MEMORY;
2289 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2293 if (state->user_encrypt) {
2294 status = netlogon_creds_cli_get(state->context,
2297 if (!NT_STATUS_IS_OK(status)) {
2298 status = NT_STATUS_ACCESS_DENIED;
2299 tevent_req_nterror(req, status);
2300 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2304 netlogon_creds_encrypt_samlogon_logon(state->ro_creds,
2309 subreq = dcerpc_netr_LogonSamLogonEx_send(state, state->ev,
2310 state->binding_handle,
2311 state->srv_name_slash,
2312 state->context->client.computer,
2315 state->validation_level,
2317 &state->authoritative,
2319 if (tevent_req_nomem(subreq, req)) {
2320 status = NT_STATUS_NO_MEMORY;
2321 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2324 tevent_req_set_callback(subreq,
2325 netlogon_creds_cli_LogonSamLogon_done,
2330 if (state->lk_creds == NULL) {
2331 subreq = netlogon_creds_cli_lock_send(state, state->ev,
2333 if (tevent_req_nomem(subreq, req)) {
2334 status = NT_STATUS_NO_MEMORY;
2335 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2338 tevent_req_set_callback(subreq,
2339 netlogon_creds_cli_LogonSamLogon_done,
2344 state->tmp_creds = *state->lk_creds;
2345 netlogon_creds_client_authenticator(&state->tmp_creds,
2347 ZERO_STRUCT(state->rep_auth);
2349 state->logon = netlogon_creds_shallow_copy_logon(state,
2351 state->const_logon);
2352 if (tevent_req_nomem(state->logon, req)) {
2353 status = NT_STATUS_NO_MEMORY;
2354 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2358 netlogon_creds_encrypt_samlogon_logon(&state->tmp_creds,
2362 state->validation_level = 3;
2364 if (state->context->server.try_logon_with) {
2365 subreq = dcerpc_netr_LogonSamLogonWithFlags_send(state, state->ev,
2366 state->binding_handle,
2367 state->srv_name_slash,
2368 state->context->client.computer,
2373 state->validation_level,
2375 &state->authoritative,
2377 if (tevent_req_nomem(subreq, req)) {
2378 status = NT_STATUS_NO_MEMORY;
2379 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2385 subreq = dcerpc_netr_LogonSamLogon_send(state, state->ev,
2386 state->binding_handle,
2387 state->srv_name_slash,
2388 state->context->client.computer,
2393 state->validation_level,
2395 &state->authoritative);
2396 if (tevent_req_nomem(subreq, req)) {
2397 status = NT_STATUS_NO_MEMORY;
2398 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2403 tevent_req_set_callback(subreq,
2404 netlogon_creds_cli_LogonSamLogon_done,
2408 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq)
2410 struct tevent_req *req =
2411 tevent_req_callback_data(subreq,
2413 struct netlogon_creds_cli_LogonSamLogon_state *state =
2414 tevent_req_data(req,
2415 struct netlogon_creds_cli_LogonSamLogon_state);
2420 if (state->try_logon_ex) {
2421 status = dcerpc_netr_LogonSamLogonEx_recv(subreq,
2424 TALLOC_FREE(subreq);
2425 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2426 state->context->server.try_validation6 = false;
2427 state->context->server.try_logon_ex = false;
2428 netlogon_creds_cli_LogonSamLogon_start(req);
2431 if (tevent_req_nterror(req, status)) {
2432 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2436 if ((state->validation_level == 6) &&
2437 (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS) ||
2438 NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PARAMETER) ||
2439 NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL)))
2441 state->context->server.try_validation6 = false;
2442 netlogon_creds_cli_LogonSamLogon_start(req);
2446 if (tevent_req_nterror(req, result)) {
2447 netlogon_creds_cli_LogonSamLogon_cleanup(req, result);
2451 if (state->ro_creds == NULL) {
2452 tevent_req_done(req);
2456 ok = netlogon_creds_cli_validate(state->context, state->ro_creds);
2459 * We got a race, lets retry with on authenticator
2462 * netlogon_creds_cli_LogonSamLogon_start()
2463 * will TALLOC_FREE(state->ro_creds);
2465 state->try_logon_ex = false;
2466 netlogon_creds_cli_LogonSamLogon_start(req);
2470 netlogon_creds_decrypt_samlogon_validation(state->ro_creds,
2471 state->validation_level,
2474 tevent_req_done(req);
2478 if (state->lk_creds == NULL) {
2479 status = netlogon_creds_cli_lock_recv(subreq, state,
2481 TALLOC_FREE(subreq);
2482 if (tevent_req_nterror(req, status)) {
2483 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2487 netlogon_creds_cli_LogonSamLogon_start(req);
2491 if (state->context->server.try_logon_with) {
2492 status = dcerpc_netr_LogonSamLogonWithFlags_recv(subreq,
2495 TALLOC_FREE(subreq);
2496 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2497 state->context->server.try_logon_with = false;
2498 netlogon_creds_cli_LogonSamLogon_start(req);
2501 if (tevent_req_nterror(req, status)) {
2502 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2506 status = dcerpc_netr_LogonSamLogon_recv(subreq,
2509 TALLOC_FREE(subreq);
2510 if (tevent_req_nterror(req, status)) {
2511 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2516 ok = netlogon_creds_client_check(&state->tmp_creds,
2517 &state->rep_auth.cred);
2519 status = NT_STATUS_ACCESS_DENIED;
2520 tevent_req_nterror(req, status);
2521 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2525 *state->lk_creds = state->tmp_creds;
2526 status = netlogon_creds_cli_store(state->context,
2528 if (tevent_req_nterror(req, status)) {
2529 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2533 if (tevent_req_nterror(req, result)) {
2534 netlogon_creds_cli_LogonSamLogon_cleanup(req, result);
2538 netlogon_creds_decrypt_samlogon_validation(&state->tmp_creds,
2539 state->validation_level,
2542 tevent_req_done(req);
2545 NTSTATUS netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req *req,
2546 TALLOC_CTX *mem_ctx,
2547 uint16_t *validation_level,
2548 union netr_Validation **validation,
2549 uint8_t *authoritative,
2552 struct netlogon_creds_cli_LogonSamLogon_state *state =
2553 tevent_req_data(req,
2554 struct netlogon_creds_cli_LogonSamLogon_state);
2557 /* authoritative is also returned on error */
2558 *authoritative = state->authoritative;
2560 if (tevent_req_is_nterror(req, &status)) {
2561 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2562 tevent_req_received(req);
2566 *validation_level = state->validation_level;
2567 *validation = talloc_move(mem_ctx, &state->validation);
2568 *flags = state->flags;
2570 tevent_req_received(req);
2571 return NT_STATUS_OK;
2574 NTSTATUS netlogon_creds_cli_LogonSamLogon(
2575 struct netlogon_creds_cli_context *context,
2576 struct dcerpc_binding_handle *b,
2577 enum netr_LogonInfoClass logon_level,
2578 const union netr_LogonLevel *logon,
2579 TALLOC_CTX *mem_ctx,
2580 uint16_t *validation_level,
2581 union netr_Validation **validation,
2582 uint8_t *authoritative,
2585 TALLOC_CTX *frame = talloc_stackframe();
2586 struct tevent_context *ev;
2587 struct tevent_req *req;
2588 NTSTATUS status = NT_STATUS_NO_MEMORY;
2590 ev = samba_tevent_context_init(frame);
2594 req = netlogon_creds_cli_LogonSamLogon_send(frame, ev, context, b,
2600 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2603 status = netlogon_creds_cli_LogonSamLogon_recv(req, mem_ctx,
2613 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state {
2614 struct tevent_context *ev;
2615 struct netlogon_creds_cli_context *context;
2616 struct dcerpc_binding_handle *binding_handle;
2618 char *srv_name_slash;
2619 enum dcerpc_AuthType auth_type;
2620 enum dcerpc_AuthLevel auth_level;
2622 const char *site_name;
2624 struct NL_DNS_NAME_INFO_ARRAY *dns_names;
2626 struct netlogon_creds_CredentialState *creds;
2627 struct netlogon_creds_CredentialState tmp_creds;
2628 struct netr_Authenticator req_auth;
2629 struct netr_Authenticator rep_auth;
2632 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req *req,
2634 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req *subreq);
2636 struct tevent_req *netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(TALLOC_CTX *mem_ctx,
2637 struct tevent_context *ev,
2638 struct netlogon_creds_cli_context *context,
2639 struct dcerpc_binding_handle *b,
2640 const char *site_name,
2642 struct NL_DNS_NAME_INFO_ARRAY *dns_names)
2644 struct tevent_req *req;
2645 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state;
2646 struct tevent_req *subreq;
2648 req = tevent_req_create(mem_ctx, &state,
2649 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2655 state->context = context;
2656 state->binding_handle = b;
2658 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
2659 context->server.computer);
2660 if (tevent_req_nomem(state->srv_name_slash, req)) {
2661 return tevent_req_post(req, ev);
2664 state->site_name = site_name;
2665 state->dns_ttl = dns_ttl;
2666 state->dns_names = dns_names;
2668 dcerpc_binding_handle_auth_info(state->binding_handle,
2670 &state->auth_level);
2672 subreq = netlogon_creds_cli_lock_send(state, state->ev,
2674 if (tevent_req_nomem(subreq, req)) {
2675 return tevent_req_post(req, ev);
2678 tevent_req_set_callback(subreq,
2679 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked,
2685 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req *req,
2688 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
2689 tevent_req_data(req,
2690 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2692 if (state->creds == NULL) {
2696 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
2697 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
2698 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
2699 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
2700 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
2701 TALLOC_FREE(state->creds);
2705 netlogon_creds_cli_delete(state->context, &state->creds);
2708 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req *subreq);
2710 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req *subreq)
2712 struct tevent_req *req =
2713 tevent_req_callback_data(subreq,
2715 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
2716 tevent_req_data(req,
2717 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2720 status = netlogon_creds_cli_lock_recv(subreq, state,
2722 TALLOC_FREE(subreq);
2723 if (tevent_req_nterror(req, status)) {
2727 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
2728 switch (state->auth_level) {
2729 case DCERPC_AUTH_LEVEL_INTEGRITY:
2730 case DCERPC_AUTH_LEVEL_PRIVACY:
2733 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2737 uint32_t tmp = state->creds->negotiate_flags;
2739 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
2741 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
2742 * it should be used, which means
2743 * we had a chance to verify no downgrade
2746 * This relies on netlogon_creds_cli_check*
2747 * being called before, as first request after
2750 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2756 * we defer all callbacks in order to cleanup
2757 * the database record.
2759 tevent_req_defer_callback(req, state->ev);
2761 state->tmp_creds = *state->creds;
2762 netlogon_creds_client_authenticator(&state->tmp_creds,
2764 ZERO_STRUCT(state->rep_auth);
2766 subreq = dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_send(state, state->ev,
2767 state->binding_handle,
2768 state->srv_name_slash,
2769 state->tmp_creds.computer_name,
2775 if (tevent_req_nomem(subreq, req)) {
2776 status = NT_STATUS_NO_MEMORY;
2777 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2781 tevent_req_set_callback(subreq,
2782 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done,
2786 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req *subreq)
2788 struct tevent_req *req =
2789 tevent_req_callback_data(subreq,
2791 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
2792 tevent_req_data(req,
2793 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2799 * We use state->dns_names as the memory context, as this is
2800 * the only in/out variable and it has been overwritten by the
2801 * out parameter from the server.
2803 * We need to preserve the return value until the caller can use it.
2805 status = dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_recv(subreq, state->dns_names,
2807 TALLOC_FREE(subreq);
2808 if (tevent_req_nterror(req, status)) {
2809 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2813 ok = netlogon_creds_client_check(&state->tmp_creds,
2814 &state->rep_auth.cred);
2816 status = NT_STATUS_ACCESS_DENIED;
2817 tevent_req_nterror(req, status);
2818 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2822 *state->creds = state->tmp_creds;
2823 status = netlogon_creds_cli_store(state->context,
2826 if (tevent_req_nterror(req, status)) {
2827 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2831 if (tevent_req_nterror(req, result)) {
2832 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, result);
2836 tevent_req_done(req);
2839 NTSTATUS netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(struct tevent_req *req)
2843 if (tevent_req_is_nterror(req, &status)) {
2844 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2845 tevent_req_received(req);
2849 tevent_req_received(req);
2850 return NT_STATUS_OK;
2853 NTSTATUS netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(
2854 struct netlogon_creds_cli_context *context,
2855 struct dcerpc_binding_handle *b,
2856 const char *site_name,
2858 struct NL_DNS_NAME_INFO_ARRAY *dns_names)
2860 TALLOC_CTX *frame = talloc_stackframe();
2861 struct tevent_context *ev;
2862 struct tevent_req *req;
2863 NTSTATUS status = NT_STATUS_NO_MEMORY;
2865 ev = samba_tevent_context_init(frame);
2869 req = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(frame, ev, context, b,
2876 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2879 status = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(req);
2885 struct netlogon_creds_cli_ServerGetTrustInfo_state {
2886 struct tevent_context *ev;
2887 struct netlogon_creds_cli_context *context;
2888 struct dcerpc_binding_handle *binding_handle;
2890 char *srv_name_slash;
2891 enum dcerpc_AuthType auth_type;
2892 enum dcerpc_AuthLevel auth_level;
2894 struct samr_Password new_owf_password;
2895 struct samr_Password old_owf_password;
2896 struct netr_TrustInfo *trust_info;
2898 struct netlogon_creds_CredentialState *creds;
2899 struct netlogon_creds_CredentialState tmp_creds;
2900 struct netr_Authenticator req_auth;
2901 struct netr_Authenticator rep_auth;
2904 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req *req,
2906 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req *subreq);
2908 struct tevent_req *netlogon_creds_cli_ServerGetTrustInfo_send(TALLOC_CTX *mem_ctx,
2909 struct tevent_context *ev,
2910 struct netlogon_creds_cli_context *context,
2911 struct dcerpc_binding_handle *b)
2913 struct tevent_req *req;
2914 struct netlogon_creds_cli_ServerGetTrustInfo_state *state;
2915 struct tevent_req *subreq;
2917 req = tevent_req_create(mem_ctx, &state,
2918 struct netlogon_creds_cli_ServerGetTrustInfo_state);
2924 state->context = context;
2925 state->binding_handle = b;
2927 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
2928 context->server.computer);
2929 if (tevent_req_nomem(state->srv_name_slash, req)) {
2930 return tevent_req_post(req, ev);
2933 dcerpc_binding_handle_auth_info(state->binding_handle,
2935 &state->auth_level);
2937 subreq = netlogon_creds_cli_lock_send(state, state->ev,
2939 if (tevent_req_nomem(subreq, req)) {
2940 return tevent_req_post(req, ev);
2943 tevent_req_set_callback(subreq,
2944 netlogon_creds_cli_ServerGetTrustInfo_locked,
2950 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req *req,
2953 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
2954 tevent_req_data(req,
2955 struct netlogon_creds_cli_ServerGetTrustInfo_state);
2957 if (state->creds == NULL) {
2961 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
2962 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
2963 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
2964 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
2965 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
2966 TALLOC_FREE(state->creds);
2970 netlogon_creds_cli_delete(state->context, &state->creds);
2973 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req *subreq);
2975 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req *subreq)
2977 struct tevent_req *req =
2978 tevent_req_callback_data(subreq,
2980 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
2981 tevent_req_data(req,
2982 struct netlogon_creds_cli_ServerGetTrustInfo_state);
2985 status = netlogon_creds_cli_lock_recv(subreq, state,
2987 TALLOC_FREE(subreq);
2988 if (tevent_req_nterror(req, status)) {
2992 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
2993 switch (state->auth_level) {
2994 case DCERPC_AUTH_LEVEL_PRIVACY:
2997 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3001 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3006 * we defer all callbacks in order to cleanup
3007 * the database record.
3009 tevent_req_defer_callback(req, state->ev);
3011 state->tmp_creds = *state->creds;
3012 netlogon_creds_client_authenticator(&state->tmp_creds,
3014 ZERO_STRUCT(state->rep_auth);
3016 subreq = dcerpc_netr_ServerGetTrustInfo_send(state, state->ev,
3017 state->binding_handle,
3018 state->srv_name_slash,
3019 state->tmp_creds.account_name,
3020 state->tmp_creds.secure_channel_type,
3021 state->tmp_creds.computer_name,
3024 &state->new_owf_password,
3025 &state->old_owf_password,
3026 &state->trust_info);
3027 if (tevent_req_nomem(subreq, req)) {
3028 status = NT_STATUS_NO_MEMORY;
3029 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3033 tevent_req_set_callback(subreq,
3034 netlogon_creds_cli_ServerGetTrustInfo_done,
3038 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req *subreq)
3040 struct tevent_req *req =
3041 tevent_req_callback_data(subreq,
3043 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
3044 tevent_req_data(req,
3045 struct netlogon_creds_cli_ServerGetTrustInfo_state);
3048 const struct samr_Password zero = {};
3053 * We use state->dns_names as the memory context, as this is
3054 * the only in/out variable and it has been overwritten by the
3055 * out parameter from the server.
3057 * We need to preserve the return value until the caller can use it.
3059 status = dcerpc_netr_ServerGetTrustInfo_recv(subreq, state, &result);
3060 TALLOC_FREE(subreq);
3061 if (tevent_req_nterror(req, status)) {
3062 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3066 ok = netlogon_creds_client_check(&state->tmp_creds,
3067 &state->rep_auth.cred);
3069 status = NT_STATUS_ACCESS_DENIED;
3070 tevent_req_nterror(req, status);
3071 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3075 cmp = memcmp(state->new_owf_password.hash,
3076 zero.hash, sizeof(zero.hash));
3078 netlogon_creds_des_decrypt(&state->tmp_creds,
3079 &state->new_owf_password);
3081 cmp = memcmp(state->old_owf_password.hash,
3082 zero.hash, sizeof(zero.hash));
3084 netlogon_creds_des_decrypt(&state->tmp_creds,
3085 &state->old_owf_password);
3088 *state->creds = state->tmp_creds;
3089 status = netlogon_creds_cli_store(state->context,
3091 if (tevent_req_nterror(req, status)) {
3092 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3096 if (tevent_req_nterror(req, result)) {
3097 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, result);
3101 tevent_req_done(req);
3104 NTSTATUS netlogon_creds_cli_ServerGetTrustInfo_recv(struct tevent_req *req,
3105 TALLOC_CTX *mem_ctx,
3106 struct samr_Password *new_owf_password,
3107 struct samr_Password *old_owf_password,
3108 struct netr_TrustInfo **trust_info)
3110 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
3111 tevent_req_data(req,
3112 struct netlogon_creds_cli_ServerGetTrustInfo_state);
3115 if (tevent_req_is_nterror(req, &status)) {
3116 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3117 tevent_req_received(req);
3121 if (new_owf_password != NULL) {
3122 *new_owf_password = state->new_owf_password;
3124 if (old_owf_password != NULL) {
3125 *old_owf_password = state->old_owf_password;
3127 if (trust_info != NULL) {
3128 *trust_info = talloc_move(mem_ctx, &state->trust_info);
3131 tevent_req_received(req);
3132 return NT_STATUS_OK;
3135 NTSTATUS netlogon_creds_cli_ServerGetTrustInfo(
3136 struct netlogon_creds_cli_context *context,
3137 struct dcerpc_binding_handle *b,
3138 TALLOC_CTX *mem_ctx,
3139 struct samr_Password *new_owf_password,
3140 struct samr_Password *old_owf_password,
3141 struct netr_TrustInfo **trust_info)
3143 TALLOC_CTX *frame = talloc_stackframe();
3144 struct tevent_context *ev;
3145 struct tevent_req *req;
3146 NTSTATUS status = NT_STATUS_NO_MEMORY;
3148 ev = samba_tevent_context_init(frame);
3152 req = netlogon_creds_cli_ServerGetTrustInfo_send(frame, ev, context, b);
3156 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3159 status = netlogon_creds_cli_ServerGetTrustInfo_recv(req,
3169 struct netlogon_creds_cli_GetForestTrustInformation_state {
3170 struct tevent_context *ev;
3171 struct netlogon_creds_cli_context *context;
3172 struct dcerpc_binding_handle *binding_handle;
3174 char *srv_name_slash;
3175 enum dcerpc_AuthType auth_type;
3176 enum dcerpc_AuthLevel auth_level;
3179 struct lsa_ForestTrustInformation *forest_trust_info;
3181 struct netlogon_creds_CredentialState *creds;
3182 struct netlogon_creds_CredentialState tmp_creds;
3183 struct netr_Authenticator req_auth;
3184 struct netr_Authenticator rep_auth;
3187 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req *req,
3189 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req *subreq);
3191 struct tevent_req *netlogon_creds_cli_GetForestTrustInformation_send(TALLOC_CTX *mem_ctx,
3192 struct tevent_context *ev,
3193 struct netlogon_creds_cli_context *context,
3194 struct dcerpc_binding_handle *b)
3196 struct tevent_req *req;
3197 struct netlogon_creds_cli_GetForestTrustInformation_state *state;
3198 struct tevent_req *subreq;
3200 req = tevent_req_create(mem_ctx, &state,
3201 struct netlogon_creds_cli_GetForestTrustInformation_state);
3207 state->context = context;
3208 state->binding_handle = b;
3210 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
3211 context->server.computer);
3212 if (tevent_req_nomem(state->srv_name_slash, req)) {
3213 return tevent_req_post(req, ev);
3218 dcerpc_binding_handle_auth_info(state->binding_handle,
3220 &state->auth_level);
3222 subreq = netlogon_creds_cli_lock_send(state, state->ev,
3224 if (tevent_req_nomem(subreq, req)) {
3225 return tevent_req_post(req, ev);
3228 tevent_req_set_callback(subreq,
3229 netlogon_creds_cli_GetForestTrustInformation_locked,
3235 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req *req,
3238 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3239 tevent_req_data(req,
3240 struct netlogon_creds_cli_GetForestTrustInformation_state);
3242 if (state->creds == NULL) {
3246 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
3247 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
3248 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
3249 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
3250 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
3251 TALLOC_FREE(state->creds);
3255 netlogon_creds_cli_delete(state->context, &state->creds);
3258 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req *subreq);
3260 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req *subreq)
3262 struct tevent_req *req =
3263 tevent_req_callback_data(subreq,
3265 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3266 tevent_req_data(req,
3267 struct netlogon_creds_cli_GetForestTrustInformation_state);
3270 status = netlogon_creds_cli_lock_recv(subreq, state,
3272 TALLOC_FREE(subreq);
3273 if (tevent_req_nterror(req, status)) {
3277 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
3278 switch (state->auth_level) {
3279 case DCERPC_AUTH_LEVEL_INTEGRITY:
3280 case DCERPC_AUTH_LEVEL_PRIVACY:
3283 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3287 uint32_t tmp = state->creds->negotiate_flags;
3289 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
3291 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3292 * it should be used, which means
3293 * we had a chance to verify no downgrade
3296 * This relies on netlogon_creds_cli_check*
3297 * being called before, as first request after
3300 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3306 * we defer all callbacks in order to cleanup
3307 * the database record.
3309 tevent_req_defer_callback(req, state->ev);
3311 state->tmp_creds = *state->creds;
3312 netlogon_creds_client_authenticator(&state->tmp_creds,
3314 ZERO_STRUCT(state->rep_auth);
3316 subreq = dcerpc_netr_GetForestTrustInformation_send(state, state->ev,
3317 state->binding_handle,
3318 state->srv_name_slash,
3319 state->tmp_creds.computer_name,
3323 &state->forest_trust_info);
3324 if (tevent_req_nomem(subreq, req)) {
3325 status = NT_STATUS_NO_MEMORY;
3326 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3330 tevent_req_set_callback(subreq,
3331 netlogon_creds_cli_GetForestTrustInformation_done,
3335 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req *subreq)
3337 struct tevent_req *req =
3338 tevent_req_callback_data(subreq,
3340 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3341 tevent_req_data(req,
3342 struct netlogon_creds_cli_GetForestTrustInformation_state);
3348 * We use state->dns_names as the memory context, as this is
3349 * the only in/out variable and it has been overwritten by the
3350 * out parameter from the server.
3352 * We need to preserve the return value until the caller can use it.
3354 status = dcerpc_netr_GetForestTrustInformation_recv(subreq, state, &result);
3355 TALLOC_FREE(subreq);
3356 if (tevent_req_nterror(req, status)) {
3357 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3361 ok = netlogon_creds_client_check(&state->tmp_creds,
3362 &state->rep_auth.cred);
3364 status = NT_STATUS_ACCESS_DENIED;
3365 tevent_req_nterror(req, status);
3366 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3370 *state->creds = state->tmp_creds;
3371 status = netlogon_creds_cli_store(state->context,
3374 if (tevent_req_nterror(req, status)) {
3375 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3379 if (tevent_req_nterror(req, result)) {
3380 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, result);
3384 tevent_req_done(req);
3387 NTSTATUS netlogon_creds_cli_GetForestTrustInformation_recv(struct tevent_req *req,
3388 TALLOC_CTX *mem_ctx,
3389 struct lsa_ForestTrustInformation **forest_trust_info)
3391 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3392 tevent_req_data(req,
3393 struct netlogon_creds_cli_GetForestTrustInformation_state);
3396 if (tevent_req_is_nterror(req, &status)) {
3397 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3398 tevent_req_received(req);
3402 *forest_trust_info = talloc_move(mem_ctx, &state->forest_trust_info);
3404 tevent_req_received(req);
3405 return NT_STATUS_OK;
3408 NTSTATUS netlogon_creds_cli_GetForestTrustInformation(
3409 struct netlogon_creds_cli_context *context,
3410 struct dcerpc_binding_handle *b,
3411 TALLOC_CTX *mem_ctx,
3412 struct lsa_ForestTrustInformation **forest_trust_info)
3414 TALLOC_CTX *frame = talloc_stackframe();
3415 struct tevent_context *ev;
3416 struct tevent_req *req;
3417 NTSTATUS status = NT_STATUS_NO_MEMORY;
3419 ev = samba_tevent_context_init(frame);
3423 req = netlogon_creds_cli_GetForestTrustInformation_send(frame, ev, context, b);
3427 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3430 status = netlogon_creds_cli_GetForestTrustInformation_recv(req,
3438 struct netlogon_creds_cli_SendToSam_state {
3439 struct tevent_context *ev;
3440 struct netlogon_creds_cli_context *context;
3441 struct dcerpc_binding_handle *binding_handle;
3443 char *srv_name_slash;
3444 enum dcerpc_AuthType auth_type;
3445 enum dcerpc_AuthLevel auth_level;
3449 struct netlogon_creds_CredentialState *creds;
3450 struct netlogon_creds_CredentialState tmp_creds;
3451 struct netr_Authenticator req_auth;
3452 struct netr_Authenticator rep_auth;
3455 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req *req,
3457 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req *subreq);
3459 struct tevent_req *netlogon_creds_cli_SendToSam_send(TALLOC_CTX *mem_ctx,
3460 struct tevent_context *ev,
3461 struct netlogon_creds_cli_context *context,
3462 struct dcerpc_binding_handle *b,
3463 struct netr_SendToSamBase *message)
3465 struct tevent_req *req;
3466 struct netlogon_creds_cli_SendToSam_state *state;
3467 struct tevent_req *subreq;
3468 enum ndr_err_code ndr_err;
3470 req = tevent_req_create(mem_ctx, &state,
3471 struct netlogon_creds_cli_SendToSam_state);
3477 state->context = context;
3478 state->binding_handle = b;
3480 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
3481 context->server.computer);
3482 if (tevent_req_nomem(state->srv_name_slash, req)) {
3483 return tevent_req_post(req, ev);
3486 ndr_err = ndr_push_struct_blob(&state->opaque, mem_ctx, message,
3487 (ndr_push_flags_fn_t)ndr_push_netr_SendToSamBase);
3488 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3489 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
3490 tevent_req_nterror(req, status);
3491 return tevent_req_post(req, ev);
3494 dcerpc_binding_handle_auth_info(state->binding_handle,
3496 &state->auth_level);
3498 subreq = netlogon_creds_cli_lock_send(state, state->ev,
3500 if (tevent_req_nomem(subreq, req)) {
3501 return tevent_req_post(req, ev);
3504 tevent_req_set_callback(subreq,
3505 netlogon_creds_cli_SendToSam_locked,
3511 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req *req,
3514 struct netlogon_creds_cli_SendToSam_state *state =
3515 tevent_req_data(req,
3516 struct netlogon_creds_cli_SendToSam_state);
3518 if (state->creds == NULL) {
3522 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
3523 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
3524 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
3525 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
3526 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
3527 TALLOC_FREE(state->creds);
3531 netlogon_creds_cli_delete(state->context, &state->creds);
3534 static void netlogon_creds_cli_SendToSam_done(struct tevent_req *subreq);
3536 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req *subreq)
3538 struct tevent_req *req =
3539 tevent_req_callback_data(subreq,
3541 struct netlogon_creds_cli_SendToSam_state *state =
3542 tevent_req_data(req,
3543 struct netlogon_creds_cli_SendToSam_state);
3546 status = netlogon_creds_cli_lock_recv(subreq, state,
3548 TALLOC_FREE(subreq);
3549 if (tevent_req_nterror(req, status)) {
3553 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
3554 switch (state->auth_level) {
3555 case DCERPC_AUTH_LEVEL_INTEGRITY:
3556 case DCERPC_AUTH_LEVEL_PRIVACY:
3559 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3563 uint32_t tmp = state->creds->negotiate_flags;
3565 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
3567 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3568 * it should be used, which means
3569 * we had a chance to verify no downgrade
3572 * This relies on netlogon_creds_cli_check*
3573 * being called before, as first request after
3576 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3582 * we defer all callbacks in order to cleanup
3583 * the database record.
3585 tevent_req_defer_callback(req, state->ev);
3587 state->tmp_creds = *state->creds;
3588 netlogon_creds_client_authenticator(&state->tmp_creds,
3590 ZERO_STRUCT(state->rep_auth);
3592 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
3593 netlogon_creds_aes_encrypt(&state->tmp_creds,
3595 state->opaque.length);
3597 netlogon_creds_arcfour_crypt(&state->tmp_creds,
3599 state->opaque.length);
3602 subreq = dcerpc_netr_NetrLogonSendToSam_send(state, state->ev,
3603 state->binding_handle,
3604 state->srv_name_slash,
3605 state->tmp_creds.computer_name,
3609 state->opaque.length);
3610 if (tevent_req_nomem(subreq, req)) {
3611 status = NT_STATUS_NO_MEMORY;
3612 netlogon_creds_cli_SendToSam_cleanup(req, status);
3616 tevent_req_set_callback(subreq,
3617 netlogon_creds_cli_SendToSam_done,
3621 static void netlogon_creds_cli_SendToSam_done(struct tevent_req *subreq)
3623 struct tevent_req *req =
3624 tevent_req_callback_data(subreq,
3626 struct netlogon_creds_cli_SendToSam_state *state =
3627 tevent_req_data(req,
3628 struct netlogon_creds_cli_SendToSam_state);
3633 status = dcerpc_netr_NetrLogonSendToSam_recv(subreq, state, &result);
3634 TALLOC_FREE(subreq);
3635 if (tevent_req_nterror(req, status)) {
3636 netlogon_creds_cli_SendToSam_cleanup(req, status);
3640 ok = netlogon_creds_client_check(&state->tmp_creds,
3641 &state->rep_auth.cred);
3643 status = NT_STATUS_ACCESS_DENIED;
3644 tevent_req_nterror(req, status);
3645 netlogon_creds_cli_SendToSam_cleanup(req, status);
3649 *state->creds = state->tmp_creds;
3650 status = netlogon_creds_cli_store(state->context,
3653 if (tevent_req_nterror(req, status)) {
3654 netlogon_creds_cli_SendToSam_cleanup(req, status);
3659 * Creds must be stored before we send back application errors
3660 * e.g. NT_STATUS_NOT_IMPLEMENTED
3662 if (tevent_req_nterror(req, result)) {
3663 netlogon_creds_cli_SendToSam_cleanup(req, result);
3667 tevent_req_done(req);
3670 NTSTATUS netlogon_creds_cli_SendToSam(struct netlogon_creds_cli_context *context,
3671 struct dcerpc_binding_handle *b,
3672 struct netr_SendToSamBase *message)
3674 TALLOC_CTX *frame = talloc_stackframe();
3675 struct tevent_context *ev;
3676 struct tevent_req *req;
3677 NTSTATUS status = NT_STATUS_OK;
3679 ev = samba_tevent_context_init(frame);
3683 req = netlogon_creds_cli_SendToSam_send(frame, ev, context, b, message);
3687 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3691 /* Ignore the result */