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 const char *dns_domain;
58 uint32_t cached_flags;
67 struct db_context *ctx;
68 struct g_lock_ctx *g_ctx;
69 struct netlogon_creds_cli_locked_state *locked_state;
73 struct netlogon_creds_cli_locked_state {
74 struct netlogon_creds_cli_context *context;
76 struct netlogon_creds_CredentialState *creds;
79 static int netlogon_creds_cli_locked_state_destructor(
80 struct netlogon_creds_cli_locked_state *state)
82 struct netlogon_creds_cli_context *context = state->context;
84 if (context == NULL) {
88 if (context->db.locked_state == state) {
89 context->db.locked_state = NULL;
92 if (state->is_glocked) {
93 g_lock_unlock(context->db.g_ctx,
94 context->db.key_name);
100 static NTSTATUS netlogon_creds_cli_context_common(
101 const char *client_computer,
102 const char *client_account,
103 enum netr_SchannelType type,
104 enum dcerpc_AuthLevel auth_level,
105 uint32_t proposed_flags,
106 uint32_t required_flags,
107 const char *server_computer,
108 const char *server_netbios_domain,
109 const char *server_dns_domain,
111 struct netlogon_creds_cli_context **_context)
113 struct netlogon_creds_cli_context *context = NULL;
114 char *_key_name = NULL;
115 size_t server_netbios_name_len;
120 context = talloc_zero(mem_ctx, struct netlogon_creds_cli_context);
121 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);
128 return NT_STATUS_NO_MEMORY;
131 context->client.account = talloc_strdup(context, client_account);
132 if (context->client.account == NULL) {
133 TALLOC_FREE(context);
134 return NT_STATUS_NO_MEMORY;
137 context->client.proposed_flags = proposed_flags;
138 context->client.required_flags = required_flags;
139 context->client.type = type;
140 context->client.auth_level = auth_level;
142 context->server.computer = talloc_strdup(context, server_computer);
143 if (context->server.computer == NULL) {
144 TALLOC_FREE(context);
145 return NT_STATUS_NO_MEMORY;
148 context->server.netbios_domain = talloc_strdup(context, server_netbios_domain);
149 if (context->server.netbios_domain == NULL) {
150 TALLOC_FREE(context);
151 return NT_STATUS_NO_MEMORY;
154 context->server.dns_domain = talloc_strdup(context, server_dns_domain);
155 if (context->server.dns_domain == NULL) {
156 TALLOC_FREE(context);
157 return NT_STATUS_NO_MEMORY;
162 * Force the callers to provide a unique
163 * value for server_computer and use this directly.
165 * For now we have to deal with
166 * "HOSTNAME" vs. "hostname.example.com".
169 p = strchr(server_computer, '.');
171 server_netbios_name_len = p-server_computer;
173 server_netbios_name_len = strlen(server_computer);
176 _key_name = talloc_asprintf(context, "CLI[%s/%s]/SRV[%.*s/%s]",
179 (int)server_netbios_name_len,
181 server_netbios_domain);
182 if (_key_name == NULL) {
183 TALLOC_FREE(context);
184 return NT_STATUS_NO_MEMORY;
187 context->db.key_name = talloc_strdup_upper(context, _key_name);
188 TALLOC_FREE(_key_name);
189 if (context->db.key_name == NULL) {
190 TALLOC_FREE(context);
191 return NT_STATUS_NO_MEMORY;
194 context->db.key_data = string_term_tdb_data(context->db.key_name);
200 static struct db_context *netlogon_creds_cli_global_db;
202 NTSTATUS netlogon_creds_cli_set_global_db(struct db_context **db)
204 if (netlogon_creds_cli_global_db != NULL) {
205 return NT_STATUS_INVALID_PARAMETER_MIX;
208 netlogon_creds_cli_global_db = talloc_move(NULL, db);
212 NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx)
215 struct db_context *global_db;
217 if (netlogon_creds_cli_global_db != NULL) {
221 fname = lpcfg_private_db_path(NULL, lp_ctx, "netlogon_creds_cli");
223 return NT_STATUS_NO_MEMORY;
226 global_db = dbwrap_local_open(NULL, lp_ctx,
228 TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
230 0600, DBWRAP_LOCK_ORDER_2,
232 if (global_db == NULL) {
233 DEBUG(0,("netlogon_creds_cli_open_global_db: Failed to open %s - %s\n",
234 fname, strerror(errno)));
236 return NT_STATUS_NO_MEMORY;
240 netlogon_creds_cli_global_db = global_db;
244 void netlogon_creds_cli_close_global_db(void)
246 TALLOC_FREE(netlogon_creds_cli_global_db);
249 NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx,
250 struct messaging_context *msg_ctx,
251 const char *client_account,
252 enum netr_SchannelType type,
253 const char *server_computer,
254 const char *server_netbios_domain,
255 const char *server_dns_domain,
257 struct netlogon_creds_cli_context **_context)
259 TALLOC_CTX *frame = talloc_stackframe();
261 struct netlogon_creds_cli_context *context = NULL;
262 const char *client_computer;
263 uint32_t proposed_flags;
264 uint32_t required_flags = 0;
265 bool reject_md5_servers = false;
266 bool require_strong_key = false;
267 int require_sign_or_seal = true;
268 bool seal_secure_channel = true;
269 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
270 bool neutralize_nt4_emulation = false;
274 if (msg_ctx == NULL) {
275 return NT_STATUS_INVALID_PARAMETER_MIX;
278 client_computer = lpcfg_netbios_name(lp_ctx);
279 if (strlen(client_computer) > 15) {
280 return NT_STATUS_INVALID_PARAMETER_MIX;
284 * allow overwrite per domain
285 * reject md5 servers:<netbios_domain>
287 reject_md5_servers = lpcfg_reject_md5_servers(lp_ctx);
288 reject_md5_servers = lpcfg_parm_bool(lp_ctx, NULL,
289 "reject md5 servers",
290 server_netbios_domain,
294 * allow overwrite per domain
295 * require strong key:<netbios_domain>
297 require_strong_key = lpcfg_require_strong_key(lp_ctx);
298 require_strong_key = lpcfg_parm_bool(lp_ctx, NULL,
299 "require strong key",
300 server_netbios_domain,
304 * allow overwrite per domain
305 * client schannel:<netbios_domain>
307 require_sign_or_seal = lpcfg_client_schannel(lp_ctx);
308 require_sign_or_seal = lpcfg_parm_int(lp_ctx, NULL,
310 server_netbios_domain,
311 require_sign_or_seal);
314 * allow overwrite per domain
315 * winbind sealed pipes:<netbios_domain>
317 seal_secure_channel = lpcfg_winbind_sealed_pipes(lp_ctx);
318 seal_secure_channel = lpcfg_parm_bool(lp_ctx, NULL,
319 "winbind sealed pipes",
320 server_netbios_domain,
321 seal_secure_channel);
324 * allow overwrite per domain
325 * neutralize nt4 emulation:<netbios_domain>
327 neutralize_nt4_emulation = lpcfg_neutralize_nt4_emulation(lp_ctx);
328 neutralize_nt4_emulation = lpcfg_parm_bool(lp_ctx, NULL,
329 "neutralize nt4 emulation",
330 server_netbios_domain,
331 neutralize_nt4_emulation);
333 proposed_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
334 proposed_flags |= NETLOGON_NEG_SUPPORTS_AES;
338 if (lpcfg_security(lp_ctx) == SEC_ADS) {
340 * AD domains should be secure
342 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
343 require_sign_or_seal = true;
344 require_strong_key = true;
348 case SEC_CHAN_DOMAIN:
351 case SEC_CHAN_DNS_DOMAIN:
353 * AD domains should be secure
355 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
356 require_sign_or_seal = true;
357 require_strong_key = true;
358 neutralize_nt4_emulation = true;
362 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
363 require_sign_or_seal = true;
364 require_strong_key = true;
368 required_flags |= NETLOGON_NEG_RODC_PASSTHROUGH;
369 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
370 require_sign_or_seal = true;
371 require_strong_key = true;
372 neutralize_nt4_emulation = true;
377 return NT_STATUS_INVALID_PARAMETER;
380 if (neutralize_nt4_emulation) {
381 proposed_flags |= NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION;
384 if (require_sign_or_seal) {
385 required_flags |= NETLOGON_NEG_ARCFOUR;
386 required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC;
388 proposed_flags &= ~NETLOGON_NEG_AUTHENTICATED_RPC;
391 if (reject_md5_servers) {
392 required_flags |= NETLOGON_NEG_ARCFOUR;
393 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
394 required_flags |= NETLOGON_NEG_SUPPORTS_AES;
395 required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC;
398 if (require_strong_key) {
399 required_flags |= NETLOGON_NEG_ARCFOUR;
400 required_flags |= NETLOGON_NEG_STRONG_KEYS;
401 required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC;
404 proposed_flags |= required_flags;
406 if (seal_secure_channel) {
407 auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
409 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
412 status = netlogon_creds_cli_context_common(client_computer,
419 server_netbios_domain,
423 if (!NT_STATUS_IS_OK(status)) {
428 context->db.g_ctx = g_lock_ctx_init(context, msg_ctx);
429 if (context->db.g_ctx == NULL) {
430 TALLOC_FREE(context);
432 return NT_STATUS_NO_MEMORY;
435 if (netlogon_creds_cli_global_db != NULL) {
436 context->db.ctx = netlogon_creds_cli_global_db;
442 status = netlogon_creds_cli_open_global_db(lp_ctx);
443 if (!NT_STATUS_IS_OK(status)) {
444 TALLOC_FREE(context);
446 return NT_STATUS_NO_MEMORY;
449 context->db.ctx = netlogon_creds_cli_global_db;
455 NTSTATUS netlogon_creds_cli_context_tmp(const char *client_computer,
456 const char *client_account,
457 enum netr_SchannelType type,
458 uint32_t proposed_flags,
459 uint32_t required_flags,
460 enum dcerpc_AuthLevel auth_level,
461 const char *server_computer,
462 const char *server_netbios_domain,
464 struct netlogon_creds_cli_context **_context)
467 struct netlogon_creds_cli_context *context = NULL;
471 status = netlogon_creds_cli_context_common(client_computer,
478 server_netbios_domain,
482 if (!NT_STATUS_IS_OK(status)) {
486 context->db.ctx = db_open_rbt(context);
487 if (context->db.ctx == NULL) {
488 talloc_free(context);
489 return NT_STATUS_NO_MEMORY;
496 char *netlogon_creds_cli_debug_string(
497 const struct netlogon_creds_cli_context *context,
500 return talloc_asprintf(mem_ctx, "netlogon_creds_cli:%s",
501 context->db.key_name);
504 enum dcerpc_AuthLevel netlogon_creds_cli_auth_level(
505 struct netlogon_creds_cli_context *context)
507 return context->client.auth_level;
510 struct netlogon_creds_cli_fetch_state {
512 struct netlogon_creds_CredentialState *creds;
513 uint32_t required_flags;
517 static void netlogon_creds_cli_fetch_parser(TDB_DATA key, TDB_DATA data,
520 struct netlogon_creds_cli_fetch_state *state =
521 (struct netlogon_creds_cli_fetch_state *)private_data;
522 enum ndr_err_code ndr_err;
526 state->creds = talloc_zero(state->mem_ctx,
527 struct netlogon_creds_CredentialState);
528 if (state->creds == NULL) {
529 state->status = NT_STATUS_NO_MEMORY;
533 blob.data = data.dptr;
534 blob.length = data.dsize;
536 ndr_err = ndr_pull_struct_blob(&blob, state->creds, state->creds,
537 (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState);
538 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
539 TALLOC_FREE(state->creds);
540 state->status = ndr_map_error2ntstatus(ndr_err);
544 tmp_flags = state->creds->negotiate_flags;
545 tmp_flags &= state->required_flags;
546 if (tmp_flags != state->required_flags) {
547 TALLOC_FREE(state->creds);
548 state->status = NT_STATUS_DOWNGRADE_DETECTED;
552 state->status = NT_STATUS_OK;
555 NTSTATUS netlogon_creds_cli_get(struct netlogon_creds_cli_context *context,
557 struct netlogon_creds_CredentialState **_creds)
560 struct netlogon_creds_cli_fetch_state fstate = {
562 .status = NT_STATUS_INTERNAL_ERROR,
563 .required_flags = context->client.required_flags,
568 status = dbwrap_parse_record(context->db.ctx,
569 context->db.key_data,
570 netlogon_creds_cli_fetch_parser,
572 if (!NT_STATUS_IS_OK(status)) {
575 status = fstate.status;
576 if (!NT_STATUS_IS_OK(status)) {
581 * mark it as invalid for step operations.
583 fstate.creds->sequence = 0;
584 fstate.creds->seed = (struct netr_Credential) {{0}};
585 fstate.creds->client = (struct netr_Credential) {{0}};
586 fstate.creds->server = (struct netr_Credential) {{0}};
588 if (context->server.cached_flags == fstate.creds->negotiate_flags) {
589 *_creds = fstate.creds;
594 * It is really important to try SamLogonEx here,
595 * because multiple processes can talk to the same
596 * domain controller, without using the credential
599 * With a normal SamLogon call, we must keep the
600 * credentials chain updated and intact between all
601 * users of the machine account (which would imply
602 * cross-node communication for every NTLM logon).
604 * The credentials chain is not per NETLOGON pipe
605 * connection, but globally on the server/client pair
608 * It's also important to use NetlogonValidationSamInfo4 (6),
609 * because it relies on the rpc transport encryption
610 * and avoids using the global netlogon schannel
611 * session key to en/decrypt secret information
612 * like the user_session_key for network logons.
614 * [MS-APDS] 3.1.5.2 NTLM Network Logon
615 * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and
616 * NETLOGON_NEG_AUTHENTICATED_RPC set together
617 * are the indication that the server supports
618 * NetlogonValidationSamInfo4 (6). And it must only
619 * be used if "SealSecureChannel" is used.
621 * The "SealSecureChannel" AUTH_TYPE_SCHANNEL/AUTH_LEVEL_PRIVACY
622 * check is done in netlogon_creds_cli_LogonSamLogon*().
624 context->server.cached_flags = fstate.creds->negotiate_flags;
625 context->server.try_validation6 = true;
626 context->server.try_logon_ex = true;
627 context->server.try_logon_with = true;
629 if (!(context->server.cached_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
630 context->server.try_validation6 = false;
631 context->server.try_logon_ex = false;
633 if (!(context->server.cached_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) {
634 context->server.try_validation6 = false;
637 *_creds = fstate.creds;
641 bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context *context,
642 const struct netlogon_creds_CredentialState *creds1)
644 TALLOC_CTX *frame = talloc_stackframe();
645 struct netlogon_creds_CredentialState *creds2;
649 enum ndr_err_code ndr_err;
652 status = netlogon_creds_cli_get(context, frame, &creds2);
653 if (!NT_STATUS_IS_OK(status)) {
658 ndr_err = ndr_push_struct_blob(&blob1, frame, creds1,
659 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
660 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
665 ndr_err = ndr_push_struct_blob(&blob2, frame, creds2,
666 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
667 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
672 if (blob1.length != blob2.length) {
677 cmp = memcmp(blob1.data, blob2.data, blob1.length);
687 NTSTATUS netlogon_creds_cli_store(struct netlogon_creds_cli_context *context,
688 struct netlogon_creds_CredentialState **_creds)
690 struct netlogon_creds_CredentialState *creds = *_creds;
692 enum ndr_err_code ndr_err;
698 if (context->db.locked_state == NULL) {
700 * this was not the result of netlogon_creds_cli_lock*()
703 return NT_STATUS_INVALID_PAGE_PROTECTION;
706 if (context->db.locked_state->creds != creds) {
708 * this was not the result of netlogon_creds_cli_lock*()
711 return NT_STATUS_INVALID_PAGE_PROTECTION;
714 ndr_err = ndr_push_struct_blob(&blob, creds, creds,
715 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
716 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
718 status = ndr_map_error2ntstatus(ndr_err);
722 data.dptr = blob.data;
723 data.dsize = blob.length;
725 status = dbwrap_store(context->db.ctx,
726 context->db.key_data,
729 if (!NT_STATUS_IS_OK(status)) {
736 NTSTATUS netlogon_creds_cli_delete(struct netlogon_creds_cli_context *context,
737 struct netlogon_creds_CredentialState **_creds)
739 struct netlogon_creds_CredentialState *creds = *_creds;
744 if (context->db.locked_state == NULL) {
746 * this was not the result of netlogon_creds_cli_lock*()
749 return NT_STATUS_INVALID_PAGE_PROTECTION;
752 if (context->db.locked_state->creds != creds) {
754 * this was not the result of netlogon_creds_cli_lock*()
757 return NT_STATUS_INVALID_PAGE_PROTECTION;
760 status = dbwrap_delete(context->db.ctx,
761 context->db.key_data);
763 if (!NT_STATUS_IS_OK(status)) {
770 struct netlogon_creds_cli_lock_state {
771 struct netlogon_creds_cli_locked_state *locked_state;
772 struct netlogon_creds_CredentialState *creds;
775 static void netlogon_creds_cli_lock_done(struct tevent_req *subreq);
776 static void netlogon_creds_cli_lock_fetch(struct tevent_req *req);
778 struct tevent_req *netlogon_creds_cli_lock_send(TALLOC_CTX *mem_ctx,
779 struct tevent_context *ev,
780 struct netlogon_creds_cli_context *context)
782 struct tevent_req *req;
783 struct netlogon_creds_cli_lock_state *state;
784 struct netlogon_creds_cli_locked_state *locked_state;
785 struct tevent_req *subreq;
787 req = tevent_req_create(mem_ctx, &state,
788 struct netlogon_creds_cli_lock_state);
793 if (context->db.locked_state != NULL) {
794 tevent_req_nterror(req, NT_STATUS_LOCK_NOT_GRANTED);
795 return tevent_req_post(req, ev);
798 locked_state = talloc_zero(state, struct netlogon_creds_cli_locked_state);
799 if (tevent_req_nomem(locked_state, req)) {
800 return tevent_req_post(req, ev);
802 talloc_set_destructor(locked_state,
803 netlogon_creds_cli_locked_state_destructor);
804 locked_state->context = context;
806 context->db.locked_state = locked_state;
807 state->locked_state = locked_state;
809 if (context->db.g_ctx == NULL) {
810 netlogon_creds_cli_lock_fetch(req);
811 if (!tevent_req_is_in_progress(req)) {
812 return tevent_req_post(req, ev);
818 subreq = g_lock_lock_send(state, ev,
820 context->db.key_name,
822 if (tevent_req_nomem(subreq, req)) {
823 return tevent_req_post(req, ev);
825 tevent_req_set_callback(subreq, netlogon_creds_cli_lock_done, req);
830 static void netlogon_creds_cli_lock_done(struct tevent_req *subreq)
832 struct tevent_req *req =
833 tevent_req_callback_data(subreq,
835 struct netlogon_creds_cli_lock_state *state =
837 struct netlogon_creds_cli_lock_state);
840 status = g_lock_lock_recv(subreq);
842 if (tevent_req_nterror(req, status)) {
845 state->locked_state->is_glocked = true;
847 netlogon_creds_cli_lock_fetch(req);
850 static void netlogon_creds_cli_lock_fetch(struct tevent_req *req)
852 struct netlogon_creds_cli_lock_state *state =
854 struct netlogon_creds_cli_lock_state);
855 struct netlogon_creds_cli_context *context = state->locked_state->context;
856 struct netlogon_creds_cli_fetch_state fstate = {
857 .status = NT_STATUS_INTERNAL_ERROR,
858 .required_flags = context->client.required_flags,
862 fstate.mem_ctx = state;
863 status = dbwrap_parse_record(context->db.ctx,
864 context->db.key_data,
865 netlogon_creds_cli_fetch_parser,
867 if (tevent_req_nterror(req, status)) {
870 status = fstate.status;
871 if (tevent_req_nterror(req, status)) {
875 if (context->server.cached_flags == fstate.creds->negotiate_flags) {
876 state->creds = fstate.creds;
877 tevent_req_done(req);
881 context->server.cached_flags = fstate.creds->negotiate_flags;
882 context->server.try_validation6 = true;
883 context->server.try_logon_ex = true;
884 context->server.try_logon_with = true;
886 if (!(context->server.cached_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
887 context->server.try_validation6 = false;
888 context->server.try_logon_ex = false;
890 if (!(context->server.cached_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) {
891 context->server.try_validation6 = false;
894 state->creds = fstate.creds;
895 tevent_req_done(req);
899 NTSTATUS netlogon_creds_cli_lock_recv(struct tevent_req *req,
901 struct netlogon_creds_CredentialState **creds)
903 struct netlogon_creds_cli_lock_state *state =
905 struct netlogon_creds_cli_lock_state);
908 if (tevent_req_is_nterror(req, &status)) {
909 tevent_req_received(req);
913 talloc_steal(state->creds, state->locked_state);
914 state->locked_state->creds = state->creds;
915 *creds = talloc_move(mem_ctx, &state->creds);
916 tevent_req_received(req);
920 NTSTATUS netlogon_creds_cli_lock(struct netlogon_creds_cli_context *context,
922 struct netlogon_creds_CredentialState **creds)
924 TALLOC_CTX *frame = talloc_stackframe();
925 struct tevent_context *ev;
926 struct tevent_req *req;
927 NTSTATUS status = NT_STATUS_NO_MEMORY;
929 ev = samba_tevent_context_init(frame);
933 req = netlogon_creds_cli_lock_send(frame, ev, context);
937 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
940 status = netlogon_creds_cli_lock_recv(req, mem_ctx, creds);
946 struct netlogon_creds_cli_auth_state {
947 struct tevent_context *ev;
948 struct netlogon_creds_cli_context *context;
949 struct dcerpc_binding_handle *binding_handle;
950 uint8_t num_nt_hashes;
951 uint8_t idx_nt_hashes;
952 const struct samr_Password * const *nt_hashes;
953 const struct samr_Password *used_nt_hash;
954 char *srv_name_slash;
955 uint32_t current_flags;
956 struct netr_Credential client_challenge;
957 struct netr_Credential server_challenge;
958 struct netlogon_creds_CredentialState *creds;
959 struct netr_Credential client_credential;
960 struct netr_Credential server_credential;
965 struct netlogon_creds_cli_locked_state *locked_state;
968 static void netlogon_creds_cli_auth_locked(struct tevent_req *subreq);
969 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req *req);
971 struct tevent_req *netlogon_creds_cli_auth_send(TALLOC_CTX *mem_ctx,
972 struct tevent_context *ev,
973 struct netlogon_creds_cli_context *context,
974 struct dcerpc_binding_handle *b,
975 uint8_t num_nt_hashes,
976 const struct samr_Password * const *nt_hashes)
978 struct tevent_req *req;
979 struct netlogon_creds_cli_auth_state *state;
980 struct netlogon_creds_cli_locked_state *locked_state;
983 req = tevent_req_create(mem_ctx, &state,
984 struct netlogon_creds_cli_auth_state);
990 state->context = context;
991 state->binding_handle = b;
992 if (num_nt_hashes < 1) {
993 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
994 return tevent_req_post(req, ev);
996 if (num_nt_hashes > 4) {
997 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
998 return tevent_req_post(req, ev);
1001 state->num_nt_hashes = num_nt_hashes;
1002 state->idx_nt_hashes = 0;
1003 state->nt_hashes = nt_hashes;
1005 if (context->db.locked_state != NULL) {
1006 tevent_req_nterror(req, NT_STATUS_LOCK_NOT_GRANTED);
1007 return tevent_req_post(req, ev);
1010 locked_state = talloc_zero(state, struct netlogon_creds_cli_locked_state);
1011 if (tevent_req_nomem(locked_state, req)) {
1012 return tevent_req_post(req, ev);
1014 talloc_set_destructor(locked_state,
1015 netlogon_creds_cli_locked_state_destructor);
1016 locked_state->context = context;
1018 context->db.locked_state = locked_state;
1019 state->locked_state = locked_state;
1021 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
1022 context->server.computer);
1023 if (tevent_req_nomem(state->srv_name_slash, req)) {
1024 return tevent_req_post(req, ev);
1027 state->try_auth3 = true;
1028 state->try_auth2 = true;
1030 if (context->client.required_flags != 0) {
1031 state->require_auth2 = true;
1034 state->used_nt_hash = state->nt_hashes[state->idx_nt_hashes];
1035 state->current_flags = context->client.proposed_flags;
1037 if (context->db.g_ctx != NULL) {
1038 struct tevent_req *subreq;
1040 subreq = g_lock_lock_send(state, ev,
1042 context->db.key_name,
1044 if (tevent_req_nomem(subreq, req)) {
1045 return tevent_req_post(req, ev);
1047 tevent_req_set_callback(subreq,
1048 netlogon_creds_cli_auth_locked,
1054 status = dbwrap_purge(state->context->db.ctx,
1055 state->context->db.key_data);
1056 if (tevent_req_nterror(req, status)) {
1057 return tevent_req_post(req, ev);
1060 netlogon_creds_cli_auth_challenge_start(req);
1061 if (!tevent_req_is_in_progress(req)) {
1062 return tevent_req_post(req, ev);
1068 static void netlogon_creds_cli_auth_locked(struct tevent_req *subreq)
1070 struct tevent_req *req =
1071 tevent_req_callback_data(subreq,
1073 struct netlogon_creds_cli_auth_state *state =
1074 tevent_req_data(req,
1075 struct netlogon_creds_cli_auth_state);
1078 status = g_lock_lock_recv(subreq);
1079 TALLOC_FREE(subreq);
1080 if (tevent_req_nterror(req, status)) {
1083 state->locked_state->is_glocked = true;
1085 status = dbwrap_purge(state->context->db.ctx,
1086 state->context->db.key_data);
1087 if (tevent_req_nterror(req, status)) {
1091 netlogon_creds_cli_auth_challenge_start(req);
1094 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq);
1096 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req *req)
1098 struct netlogon_creds_cli_auth_state *state =
1099 tevent_req_data(req,
1100 struct netlogon_creds_cli_auth_state);
1101 struct tevent_req *subreq;
1103 TALLOC_FREE(state->creds);
1105 generate_random_buffer(state->client_challenge.data,
1106 sizeof(state->client_challenge.data));
1108 subreq = dcerpc_netr_ServerReqChallenge_send(state, state->ev,
1109 state->binding_handle,
1110 state->srv_name_slash,
1111 state->context->client.computer,
1112 &state->client_challenge,
1113 &state->server_challenge);
1114 if (tevent_req_nomem(subreq, req)) {
1117 tevent_req_set_callback(subreq,
1118 netlogon_creds_cli_auth_challenge_done,
1122 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq);
1124 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq)
1126 struct tevent_req *req =
1127 tevent_req_callback_data(subreq,
1129 struct netlogon_creds_cli_auth_state *state =
1130 tevent_req_data(req,
1131 struct netlogon_creds_cli_auth_state);
1135 status = dcerpc_netr_ServerReqChallenge_recv(subreq, state, &result);
1136 TALLOC_FREE(subreq);
1137 if (tevent_req_nterror(req, status)) {
1140 if (tevent_req_nterror(req, result)) {
1144 if (!state->try_auth3 && !state->try_auth2) {
1145 state->current_flags = 0;
1148 /* Calculate the session key and client credentials */
1150 state->creds = netlogon_creds_client_init(state,
1151 state->context->client.account,
1152 state->context->client.computer,
1153 state->context->client.type,
1154 &state->client_challenge,
1155 &state->server_challenge,
1156 state->used_nt_hash,
1157 &state->client_credential,
1158 state->current_flags);
1159 if (tevent_req_nomem(state->creds, req)) {
1163 if (state->try_auth3) {
1164 subreq = dcerpc_netr_ServerAuthenticate3_send(state, state->ev,
1165 state->binding_handle,
1166 state->srv_name_slash,
1167 state->context->client.account,
1168 state->context->client.type,
1169 state->context->client.computer,
1170 &state->client_credential,
1171 &state->server_credential,
1172 &state->creds->negotiate_flags,
1174 if (tevent_req_nomem(subreq, req)) {
1177 } else if (state->try_auth2) {
1180 subreq = dcerpc_netr_ServerAuthenticate2_send(state, state->ev,
1181 state->binding_handle,
1182 state->srv_name_slash,
1183 state->context->client.account,
1184 state->context->client.type,
1185 state->context->client.computer,
1186 &state->client_credential,
1187 &state->server_credential,
1188 &state->creds->negotiate_flags);
1189 if (tevent_req_nomem(subreq, req)) {
1195 subreq = dcerpc_netr_ServerAuthenticate_send(state, state->ev,
1196 state->binding_handle,
1197 state->srv_name_slash,
1198 state->context->client.account,
1199 state->context->client.type,
1200 state->context->client.computer,
1201 &state->client_credential,
1202 &state->server_credential);
1203 if (tevent_req_nomem(subreq, req)) {
1207 tevent_req_set_callback(subreq,
1208 netlogon_creds_cli_auth_srvauth_done,
1212 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq)
1214 struct tevent_req *req =
1215 tevent_req_callback_data(subreq,
1217 struct netlogon_creds_cli_auth_state *state =
1218 tevent_req_data(req,
1219 struct netlogon_creds_cli_auth_state);
1223 enum ndr_err_code ndr_err;
1228 if (state->try_auth3) {
1229 status = dcerpc_netr_ServerAuthenticate3_recv(subreq, state,
1231 TALLOC_FREE(subreq);
1232 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1233 state->try_auth3 = false;
1234 netlogon_creds_cli_auth_challenge_start(req);
1237 if (tevent_req_nterror(req, status)) {
1240 } else if (state->try_auth2) {
1241 status = dcerpc_netr_ServerAuthenticate2_recv(subreq, state,
1243 TALLOC_FREE(subreq);
1244 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1245 state->try_auth2 = false;
1246 if (state->require_auth2) {
1247 status = NT_STATUS_DOWNGRADE_DETECTED;
1248 tevent_req_nterror(req, status);
1251 netlogon_creds_cli_auth_challenge_start(req);
1254 if (tevent_req_nterror(req, status)) {
1258 status = dcerpc_netr_ServerAuthenticate_recv(subreq, state,
1260 TALLOC_FREE(subreq);
1261 if (tevent_req_nterror(req, status)) {
1266 if (!NT_STATUS_IS_OK(result) &&
1267 !NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED))
1269 tevent_req_nterror(req, result);
1273 tmp_flags = state->creds->negotiate_flags;
1274 tmp_flags &= state->context->client.required_flags;
1275 if (tmp_flags != state->context->client.required_flags) {
1276 if (NT_STATUS_IS_OK(result)) {
1277 tevent_req_nterror(req, NT_STATUS_DOWNGRADE_DETECTED);
1280 tevent_req_nterror(req, result);
1284 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
1286 tmp_flags = state->context->client.proposed_flags;
1287 if ((state->current_flags == tmp_flags) &&
1288 (state->creds->negotiate_flags != tmp_flags))
1291 * lets retry with the negotiated flags
1293 state->current_flags = state->creds->negotiate_flags;
1294 netlogon_creds_cli_auth_challenge_start(req);
1298 state->idx_nt_hashes += 1;
1299 if (state->idx_nt_hashes >= state->num_nt_hashes) {
1301 * we already retried, giving up...
1303 tevent_req_nterror(req, result);
1308 * lets retry with the old nt hash.
1310 state->used_nt_hash = state->nt_hashes[state->idx_nt_hashes];
1311 state->current_flags = state->context->client.proposed_flags;
1312 netlogon_creds_cli_auth_challenge_start(req);
1316 ok = netlogon_creds_client_check(state->creds,
1317 &state->server_credential);
1319 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1323 ndr_err = ndr_push_struct_blob(&blob, state, state->creds,
1324 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
1325 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1326 status = ndr_map_error2ntstatus(ndr_err);
1327 tevent_req_nterror(req, status);
1331 data.dptr = blob.data;
1332 data.dsize = blob.length;
1334 status = dbwrap_store(state->context->db.ctx,
1335 state->context->db.key_data,
1337 TALLOC_FREE(state->locked_state);
1338 if (tevent_req_nterror(req, status)) {
1342 tevent_req_done(req);
1345 NTSTATUS netlogon_creds_cli_auth_recv(struct tevent_req *req,
1346 uint8_t *idx_nt_hashes)
1348 struct netlogon_creds_cli_auth_state *state =
1349 tevent_req_data(req,
1350 struct netlogon_creds_cli_auth_state);
1355 if (tevent_req_is_nterror(req, &status)) {
1356 tevent_req_received(req);
1360 *idx_nt_hashes = state->idx_nt_hashes;
1361 tevent_req_received(req);
1362 return NT_STATUS_OK;
1365 NTSTATUS netlogon_creds_cli_auth(struct netlogon_creds_cli_context *context,
1366 struct dcerpc_binding_handle *b,
1367 uint8_t num_nt_hashes,
1368 const struct samr_Password * const *nt_hashes,
1369 uint8_t *idx_nt_hashes)
1371 TALLOC_CTX *frame = talloc_stackframe();
1372 struct tevent_context *ev;
1373 struct tevent_req *req;
1374 NTSTATUS status = NT_STATUS_NO_MEMORY;
1378 ev = samba_tevent_context_init(frame);
1382 req = netlogon_creds_cli_auth_send(frame, ev, context, b,
1383 num_nt_hashes, nt_hashes);
1387 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1390 status = netlogon_creds_cli_auth_recv(req, idx_nt_hashes);
1396 struct netlogon_creds_cli_check_state {
1397 struct tevent_context *ev;
1398 struct netlogon_creds_cli_context *context;
1399 struct dcerpc_binding_handle *binding_handle;
1401 char *srv_name_slash;
1403 union netr_Capabilities caps;
1405 struct netlogon_creds_CredentialState *creds;
1406 struct netlogon_creds_CredentialState tmp_creds;
1407 struct netr_Authenticator req_auth;
1408 struct netr_Authenticator rep_auth;
1411 static void netlogon_creds_cli_check_cleanup(struct tevent_req *req,
1413 static void netlogon_creds_cli_check_locked(struct tevent_req *subreq);
1415 struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx,
1416 struct tevent_context *ev,
1417 struct netlogon_creds_cli_context *context,
1418 struct dcerpc_binding_handle *b)
1420 struct tevent_req *req;
1421 struct netlogon_creds_cli_check_state *state;
1422 struct tevent_req *subreq;
1423 enum dcerpc_AuthType auth_type;
1424 enum dcerpc_AuthLevel auth_level;
1426 req = tevent_req_create(mem_ctx, &state,
1427 struct netlogon_creds_cli_check_state);
1433 state->context = context;
1434 state->binding_handle = b;
1436 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
1437 context->server.computer);
1438 if (tevent_req_nomem(state->srv_name_slash, req)) {
1439 return tevent_req_post(req, ev);
1442 dcerpc_binding_handle_auth_info(state->binding_handle,
1443 &auth_type, &auth_level);
1445 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1446 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1447 return tevent_req_post(req, ev);
1450 switch (auth_level) {
1451 case DCERPC_AUTH_LEVEL_INTEGRITY:
1452 case DCERPC_AUTH_LEVEL_PRIVACY:
1455 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1456 return tevent_req_post(req, ev);
1459 subreq = netlogon_creds_cli_lock_send(state, state->ev,
1461 if (tevent_req_nomem(subreq, req)) {
1462 return tevent_req_post(req, ev);
1465 tevent_req_set_callback(subreq,
1466 netlogon_creds_cli_check_locked,
1472 static void netlogon_creds_cli_check_cleanup(struct tevent_req *req,
1475 struct netlogon_creds_cli_check_state *state =
1476 tevent_req_data(req,
1477 struct netlogon_creds_cli_check_state);
1479 if (state->creds == NULL) {
1483 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
1484 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
1485 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
1486 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
1487 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1488 TALLOC_FREE(state->creds);
1492 netlogon_creds_cli_delete(state->context, &state->creds);
1495 static void netlogon_creds_cli_check_caps(struct tevent_req *subreq);
1497 static void netlogon_creds_cli_check_locked(struct tevent_req *subreq)
1499 struct tevent_req *req =
1500 tevent_req_callback_data(subreq,
1502 struct netlogon_creds_cli_check_state *state =
1503 tevent_req_data(req,
1504 struct netlogon_creds_cli_check_state);
1507 status = netlogon_creds_cli_lock_recv(subreq, state,
1509 TALLOC_FREE(subreq);
1510 if (tevent_req_nterror(req, status)) {
1515 * we defer all callbacks in order to cleanup
1516 * the database record.
1518 tevent_req_defer_callback(req, state->ev);
1520 state->tmp_creds = *state->creds;
1521 netlogon_creds_client_authenticator(&state->tmp_creds,
1523 ZERO_STRUCT(state->rep_auth);
1525 subreq = dcerpc_netr_LogonGetCapabilities_send(state, state->ev,
1526 state->binding_handle,
1527 state->srv_name_slash,
1528 state->context->client.computer,
1533 if (tevent_req_nomem(subreq, req)) {
1534 status = NT_STATUS_NO_MEMORY;
1535 netlogon_creds_cli_check_cleanup(req, status);
1538 tevent_req_set_callback(subreq,
1539 netlogon_creds_cli_check_caps,
1543 static void netlogon_creds_cli_check_caps(struct tevent_req *subreq)
1545 struct tevent_req *req =
1546 tevent_req_callback_data(subreq,
1548 struct netlogon_creds_cli_check_state *state =
1549 tevent_req_data(req,
1550 struct netlogon_creds_cli_check_state);
1555 status = dcerpc_netr_LogonGetCapabilities_recv(subreq, state,
1557 TALLOC_FREE(subreq);
1558 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1560 * Note that the negotiated flags are already checked
1561 * for our required flags after the ServerAuthenticate3/2 call.
1563 uint32_t negotiated = state->tmp_creds.negotiate_flags;
1565 if (negotiated & NETLOGON_NEG_SUPPORTS_AES) {
1567 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1568 * already, we expect this to work!
1570 status = NT_STATUS_DOWNGRADE_DETECTED;
1571 tevent_req_nterror(req, status);
1572 netlogon_creds_cli_check_cleanup(req, status);
1576 if (negotiated & NETLOGON_NEG_STRONG_KEYS) {
1578 * If we have negotiated NETLOGON_NEG_STRONG_KEYS
1579 * we expect this to work at least as far as the
1580 * NOT_SUPPORTED error handled below!
1582 * NT 4.0 and Old Samba servers are not
1583 * allowed without "require strong key = no"
1585 status = NT_STATUS_DOWNGRADE_DETECTED;
1586 tevent_req_nterror(req, status);
1587 netlogon_creds_cli_check_cleanup(req, status);
1592 * If we not require NETLOGON_NEG_SUPPORTS_AES or
1593 * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore
1594 * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
1596 * This is needed against NT 4.0 and old Samba servers.
1598 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
1599 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
1600 * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
1601 * with the next request as the sequence number processing
1604 netlogon_creds_cli_check_cleanup(req, status);
1605 tevent_req_done(req);
1608 if (tevent_req_nterror(req, status)) {
1609 netlogon_creds_cli_check_cleanup(req, status);
1613 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
1615 * Note that the negotiated flags are already checked
1616 * for our required flags after the ServerAuthenticate3/2 call.
1618 uint32_t negotiated = state->tmp_creds.negotiate_flags;
1620 if (negotiated & NETLOGON_NEG_SUPPORTS_AES) {
1622 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1623 * already, we expect this to work!
1625 status = NT_STATUS_DOWNGRADE_DETECTED;
1626 tevent_req_nterror(req, status);
1627 netlogon_creds_cli_check_cleanup(req, status);
1632 * This is ok, the server does not support
1633 * NETLOGON_NEG_SUPPORTS_AES.
1635 * netr_LogonGetCapabilities() was
1636 * netr_LogonDummyRoutine1() before
1637 * NETLOGON_NEG_SUPPORTS_AES was invented.
1639 netlogon_creds_cli_check_cleanup(req, result);
1640 tevent_req_done(req);
1644 ok = netlogon_creds_client_check(&state->tmp_creds,
1645 &state->rep_auth.cred);
1647 status = NT_STATUS_ACCESS_DENIED;
1648 tevent_req_nterror(req, status);
1649 netlogon_creds_cli_check_cleanup(req, status);
1653 if (tevent_req_nterror(req, result)) {
1654 netlogon_creds_cli_check_cleanup(req, result);
1658 if (state->caps.server_capabilities != state->tmp_creds.negotiate_flags) {
1659 status = NT_STATUS_DOWNGRADE_DETECTED;
1660 tevent_req_nterror(req, status);
1661 netlogon_creds_cli_check_cleanup(req, status);
1666 * This is the key check that makes this check secure. If we
1667 * get OK here (rather than NOT_SUPPORTED), then the server
1668 * did support AES. If the server only proposed STRONG_KEYS
1669 * and not AES, then it should have failed with
1670 * NOT_IMPLEMENTED. We always send AES as a client, so the
1671 * server should always have returned it.
1673 if (!(state->caps.server_capabilities & NETLOGON_NEG_SUPPORTS_AES)) {
1674 status = NT_STATUS_DOWNGRADE_DETECTED;
1675 tevent_req_nterror(req, status);
1676 netlogon_creds_cli_check_cleanup(req, status);
1680 *state->creds = state->tmp_creds;
1681 status = netlogon_creds_cli_store(state->context,
1683 netlogon_creds_cli_check_cleanup(req, status);
1684 if (tevent_req_nterror(req, status)) {
1688 tevent_req_done(req);
1691 NTSTATUS netlogon_creds_cli_check_recv(struct tevent_req *req)
1695 if (tevent_req_is_nterror(req, &status)) {
1696 netlogon_creds_cli_check_cleanup(req, status);
1697 tevent_req_received(req);
1701 tevent_req_received(req);
1702 return NT_STATUS_OK;
1705 NTSTATUS netlogon_creds_cli_check(struct netlogon_creds_cli_context *context,
1706 struct dcerpc_binding_handle *b)
1708 TALLOC_CTX *frame = talloc_stackframe();
1709 struct tevent_context *ev;
1710 struct tevent_req *req;
1711 NTSTATUS status = NT_STATUS_NO_MEMORY;
1713 ev = samba_tevent_context_init(frame);
1717 req = netlogon_creds_cli_check_send(frame, ev, context, b);
1721 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1724 status = netlogon_creds_cli_check_recv(req);
1730 struct netlogon_creds_cli_ServerPasswordSet_state {
1731 struct tevent_context *ev;
1732 struct netlogon_creds_cli_context *context;
1733 struct dcerpc_binding_handle *binding_handle;
1734 uint32_t old_timeout;
1736 char *srv_name_slash;
1737 enum dcerpc_AuthType auth_type;
1738 enum dcerpc_AuthLevel auth_level;
1740 struct samr_CryptPassword samr_crypt_password;
1741 struct netr_CryptPassword netr_crypt_password;
1742 struct samr_Password samr_password;
1744 struct netlogon_creds_CredentialState *creds;
1745 struct netlogon_creds_CredentialState tmp_creds;
1746 struct netr_Authenticator req_auth;
1747 struct netr_Authenticator rep_auth;
1750 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req *req,
1752 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subreq);
1754 struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx,
1755 struct tevent_context *ev,
1756 struct netlogon_creds_cli_context *context,
1757 struct dcerpc_binding_handle *b,
1758 const DATA_BLOB *new_password,
1759 const uint32_t *new_version)
1761 struct tevent_req *req;
1762 struct netlogon_creds_cli_ServerPasswordSet_state *state;
1763 struct tevent_req *subreq;
1766 req = tevent_req_create(mem_ctx, &state,
1767 struct netlogon_creds_cli_ServerPasswordSet_state);
1773 state->context = context;
1774 state->binding_handle = b;
1776 if (new_password->length < 14) {
1777 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1778 return tevent_req_post(req, ev);
1782 * netr_ServerPasswordSet
1784 mdfour(state->samr_password.hash, new_password->data, new_password->length);
1787 * netr_ServerPasswordSet2
1789 ok = set_pw_in_buffer(state->samr_crypt_password.data,
1792 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1793 return tevent_req_post(req, ev);
1796 if (new_version != NULL) {
1797 struct NL_PASSWORD_VERSION version;
1798 uint32_t len = IVAL(state->samr_crypt_password.data, 512);
1799 uint32_t ofs = 512 - len;
1803 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1804 return tevent_req_post(req, ev);
1808 version.ReservedField = 0;
1809 version.PasswordVersionNumber = *new_version;
1810 version.PasswordVersionPresent =
1811 NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT;
1813 p = state->samr_crypt_password.data + ofs;
1814 SIVAL(p, 0, version.ReservedField);
1815 SIVAL(p, 4, version.PasswordVersionNumber);
1816 SIVAL(p, 8, version.PasswordVersionPresent);
1819 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
1820 context->server.computer);
1821 if (tevent_req_nomem(state->srv_name_slash, req)) {
1822 return tevent_req_post(req, ev);
1825 dcerpc_binding_handle_auth_info(state->binding_handle,
1827 &state->auth_level);
1829 subreq = netlogon_creds_cli_lock_send(state, state->ev,
1831 if (tevent_req_nomem(subreq, req)) {
1832 return tevent_req_post(req, ev);
1835 tevent_req_set_callback(subreq,
1836 netlogon_creds_cli_ServerPasswordSet_locked,
1842 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req *req,
1845 struct netlogon_creds_cli_ServerPasswordSet_state *state =
1846 tevent_req_data(req,
1847 struct netlogon_creds_cli_ServerPasswordSet_state);
1849 if (state->creds == NULL) {
1853 dcerpc_binding_handle_set_timeout(state->binding_handle,
1854 state->old_timeout);
1856 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
1857 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
1858 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
1859 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
1860 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1861 TALLOC_FREE(state->creds);
1865 netlogon_creds_cli_delete(state->context, &state->creds);
1868 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq);
1870 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subreq)
1872 struct tevent_req *req =
1873 tevent_req_callback_data(subreq,
1875 struct netlogon_creds_cli_ServerPasswordSet_state *state =
1876 tevent_req_data(req,
1877 struct netlogon_creds_cli_ServerPasswordSet_state);
1880 status = netlogon_creds_cli_lock_recv(subreq, state,
1882 TALLOC_FREE(subreq);
1883 if (tevent_req_nterror(req, status)) {
1887 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
1888 switch (state->auth_level) {
1889 case DCERPC_AUTH_LEVEL_INTEGRITY:
1890 case DCERPC_AUTH_LEVEL_PRIVACY:
1893 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1897 uint32_t tmp = state->creds->negotiate_flags;
1899 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
1901 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
1902 * it should be used, which means
1903 * we had a chance to verify no downgrade
1906 * This relies on netlogon_creds_cli_check*
1907 * being called before, as first request after
1910 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1915 state->old_timeout = dcerpc_binding_handle_set_timeout(
1916 state->binding_handle, 600000);
1919 * we defer all callbacks in order to cleanup
1920 * the database record.
1922 tevent_req_defer_callback(req, state->ev);
1924 state->tmp_creds = *state->creds;
1925 netlogon_creds_client_authenticator(&state->tmp_creds,
1927 ZERO_STRUCT(state->rep_auth);
1929 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) {
1931 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1932 netlogon_creds_aes_encrypt(&state->tmp_creds,
1933 state->samr_crypt_password.data,
1936 netlogon_creds_arcfour_crypt(&state->tmp_creds,
1937 state->samr_crypt_password.data,
1941 memcpy(state->netr_crypt_password.data,
1942 state->samr_crypt_password.data, 512);
1943 state->netr_crypt_password.length =
1944 IVAL(state->samr_crypt_password.data, 512);
1946 subreq = dcerpc_netr_ServerPasswordSet2_send(state, state->ev,
1947 state->binding_handle,
1948 state->srv_name_slash,
1949 state->tmp_creds.account_name,
1950 state->tmp_creds.secure_channel_type,
1951 state->tmp_creds.computer_name,
1954 &state->netr_crypt_password);
1955 if (tevent_req_nomem(subreq, req)) {
1956 status = NT_STATUS_NO_MEMORY;
1957 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1961 netlogon_creds_des_encrypt(&state->tmp_creds,
1962 &state->samr_password);
1964 subreq = dcerpc_netr_ServerPasswordSet_send(state, state->ev,
1965 state->binding_handle,
1966 state->srv_name_slash,
1967 state->tmp_creds.account_name,
1968 state->tmp_creds.secure_channel_type,
1969 state->tmp_creds.computer_name,
1972 &state->samr_password);
1973 if (tevent_req_nomem(subreq, req)) {
1974 status = NT_STATUS_NO_MEMORY;
1975 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
1980 tevent_req_set_callback(subreq,
1981 netlogon_creds_cli_ServerPasswordSet_done,
1985 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq)
1987 struct tevent_req *req =
1988 tevent_req_callback_data(subreq,
1990 struct netlogon_creds_cli_ServerPasswordSet_state *state =
1991 tevent_req_data(req,
1992 struct netlogon_creds_cli_ServerPasswordSet_state);
1997 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) {
1998 status = dcerpc_netr_ServerPasswordSet2_recv(subreq, state,
2000 TALLOC_FREE(subreq);
2001 if (tevent_req_nterror(req, status)) {
2002 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2006 status = dcerpc_netr_ServerPasswordSet_recv(subreq, state,
2008 TALLOC_FREE(subreq);
2009 if (tevent_req_nterror(req, status)) {
2010 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2015 ok = netlogon_creds_client_check(&state->tmp_creds,
2016 &state->rep_auth.cred);
2018 status = NT_STATUS_ACCESS_DENIED;
2019 tevent_req_nterror(req, status);
2020 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2024 if (tevent_req_nterror(req, result)) {
2025 netlogon_creds_cli_ServerPasswordSet_cleanup(req, result);
2029 dcerpc_binding_handle_set_timeout(state->binding_handle,
2030 state->old_timeout);
2032 *state->creds = state->tmp_creds;
2033 status = netlogon_creds_cli_store(state->context,
2035 if (tevent_req_nterror(req, status)) {
2036 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2040 tevent_req_done(req);
2043 NTSTATUS netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req *req)
2047 if (tevent_req_is_nterror(req, &status)) {
2048 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2049 tevent_req_received(req);
2053 tevent_req_received(req);
2054 return NT_STATUS_OK;
2057 NTSTATUS netlogon_creds_cli_ServerPasswordSet(
2058 struct netlogon_creds_cli_context *context,
2059 struct dcerpc_binding_handle *b,
2060 const DATA_BLOB *new_password,
2061 const uint32_t *new_version)
2063 TALLOC_CTX *frame = talloc_stackframe();
2064 struct tevent_context *ev;
2065 struct tevent_req *req;
2066 NTSTATUS status = NT_STATUS_NO_MEMORY;
2068 ev = samba_tevent_context_init(frame);
2072 req = netlogon_creds_cli_ServerPasswordSet_send(frame, ev, context, b,
2078 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2081 status = netlogon_creds_cli_ServerPasswordSet_recv(req);
2087 struct netlogon_creds_cli_LogonSamLogon_state {
2088 struct tevent_context *ev;
2089 struct netlogon_creds_cli_context *context;
2090 struct dcerpc_binding_handle *binding_handle;
2092 char *srv_name_slash;
2094 enum netr_LogonInfoClass logon_level;
2095 const union netr_LogonLevel *const_logon;
2096 union netr_LogonLevel *logon;
2099 uint16_t validation_level;
2100 union netr_Validation *validation;
2101 uint8_t authoritative;
2104 * do we need encryption at the application layer?
2108 bool try_validation6;
2111 * the read only credentials before we started the operation
2112 * used for netr_LogonSamLogonEx() if required (validation_level = 3).
2114 struct netlogon_creds_CredentialState *ro_creds;
2117 * The (locked) credentials used for the credential chain
2118 * used for netr_LogonSamLogonWithFlags() or
2119 * netr_LogonSamLogonWith().
2121 struct netlogon_creds_CredentialState *lk_creds;
2124 * While we have locked the global credentials (lk_creds above)
2125 * we operate an a temporary copy, because a server
2126 * may not support netr_LogonSamLogonWithFlags() and
2127 * didn't process our netr_Authenticator, so we need to
2128 * restart from lk_creds.
2130 struct netlogon_creds_CredentialState tmp_creds;
2131 struct netr_Authenticator req_auth;
2132 struct netr_Authenticator rep_auth;
2135 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req);
2136 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req *req,
2139 struct tevent_req *netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX *mem_ctx,
2140 struct tevent_context *ev,
2141 struct netlogon_creds_cli_context *context,
2142 struct dcerpc_binding_handle *b,
2143 enum netr_LogonInfoClass logon_level,
2144 const union netr_LogonLevel *logon,
2147 struct tevent_req *req;
2148 struct netlogon_creds_cli_LogonSamLogon_state *state;
2150 req = tevent_req_create(mem_ctx, &state,
2151 struct netlogon_creds_cli_LogonSamLogon_state);
2157 state->context = context;
2158 state->binding_handle = b;
2160 state->logon_level = logon_level;
2161 state->const_logon = logon;
2162 state->flags = flags;
2164 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
2165 context->server.computer);
2166 if (tevent_req_nomem(state->srv_name_slash, req)) {
2167 return tevent_req_post(req, ev);
2170 switch (logon_level) {
2171 case NetlogonInteractiveInformation:
2172 case NetlogonInteractiveTransitiveInformation:
2173 case NetlogonServiceInformation:
2174 case NetlogonServiceTransitiveInformation:
2175 case NetlogonGenericInformation:
2176 state->user_encrypt = true;
2179 case NetlogonNetworkInformation:
2180 case NetlogonNetworkTransitiveInformation:
2184 state->validation = talloc_zero(state, union netr_Validation);
2185 if (tevent_req_nomem(state->validation, req)) {
2186 return tevent_req_post(req, ev);
2189 netlogon_creds_cli_LogonSamLogon_start(req);
2190 if (!tevent_req_is_in_progress(req)) {
2191 return tevent_req_post(req, ev);
2195 * we defer all callbacks in order to cleanup
2196 * the database record.
2198 tevent_req_defer_callback(req, state->ev);
2202 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req *req,
2205 struct netlogon_creds_cli_LogonSamLogon_state *state =
2206 tevent_req_data(req,
2207 struct netlogon_creds_cli_LogonSamLogon_state);
2209 if (state->lk_creds == NULL) {
2213 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2215 * This is a hack to recover from a bug in old
2216 * Samba servers, when LogonSamLogonEx() fails:
2218 * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
2220 * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2222 * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE,
2223 * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR
2224 * If the sign/seal check fails.
2226 * In that case we need to cleanup the netlogon session.
2228 * It's the job of the caller to disconnect the current
2229 * connection, if netlogon_creds_cli_LogonSamLogon()
2230 * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2232 if (!state->context->server.try_logon_with) {
2233 status = NT_STATUS_NETWORK_ACCESS_DENIED;
2237 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
2238 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
2239 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
2240 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
2241 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
2242 TALLOC_FREE(state->lk_creds);
2246 netlogon_creds_cli_delete(state->context, &state->lk_creds);
2249 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq);
2251 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req)
2253 struct netlogon_creds_cli_LogonSamLogon_state *state =
2254 tevent_req_data(req,
2255 struct netlogon_creds_cli_LogonSamLogon_state);
2256 struct tevent_req *subreq;
2258 enum dcerpc_AuthType auth_type;
2259 enum dcerpc_AuthLevel auth_level;
2261 TALLOC_FREE(state->ro_creds);
2262 TALLOC_FREE(state->logon);
2263 ZERO_STRUCTP(state->validation);
2265 dcerpc_binding_handle_auth_info(state->binding_handle,
2266 &auth_type, &auth_level);
2268 state->try_logon_ex = state->context->server.try_logon_ex;
2269 state->try_validation6 = state->context->server.try_validation6;
2271 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
2272 state->try_logon_ex = false;
2275 if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
2276 state->try_validation6 = false;
2279 if (state->try_logon_ex) {
2280 if (state->try_validation6) {
2281 state->validation_level = 6;
2283 state->validation_level = 3;
2284 state->user_encrypt = true;
2287 state->logon = netlogon_creds_shallow_copy_logon(state,
2289 state->const_logon);
2290 if (tevent_req_nomem(state->logon, req)) {
2291 status = NT_STATUS_NO_MEMORY;
2292 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2296 if (state->user_encrypt) {
2297 status = netlogon_creds_cli_get(state->context,
2300 if (!NT_STATUS_IS_OK(status)) {
2301 status = NT_STATUS_ACCESS_DENIED;
2302 tevent_req_nterror(req, status);
2303 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2307 netlogon_creds_encrypt_samlogon_logon(state->ro_creds,
2312 subreq = dcerpc_netr_LogonSamLogonEx_send(state, state->ev,
2313 state->binding_handle,
2314 state->srv_name_slash,
2315 state->context->client.computer,
2318 state->validation_level,
2320 &state->authoritative,
2322 if (tevent_req_nomem(subreq, req)) {
2323 status = NT_STATUS_NO_MEMORY;
2324 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2327 tevent_req_set_callback(subreq,
2328 netlogon_creds_cli_LogonSamLogon_done,
2333 if (state->lk_creds == NULL) {
2334 subreq = netlogon_creds_cli_lock_send(state, state->ev,
2336 if (tevent_req_nomem(subreq, req)) {
2337 status = NT_STATUS_NO_MEMORY;
2338 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2341 tevent_req_set_callback(subreq,
2342 netlogon_creds_cli_LogonSamLogon_done,
2347 state->tmp_creds = *state->lk_creds;
2348 netlogon_creds_client_authenticator(&state->tmp_creds,
2350 ZERO_STRUCT(state->rep_auth);
2352 state->logon = netlogon_creds_shallow_copy_logon(state,
2354 state->const_logon);
2355 if (tevent_req_nomem(state->logon, req)) {
2356 status = NT_STATUS_NO_MEMORY;
2357 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2361 netlogon_creds_encrypt_samlogon_logon(&state->tmp_creds,
2365 state->validation_level = 3;
2367 if (state->context->server.try_logon_with) {
2368 subreq = dcerpc_netr_LogonSamLogonWithFlags_send(state, state->ev,
2369 state->binding_handle,
2370 state->srv_name_slash,
2371 state->context->client.computer,
2376 state->validation_level,
2378 &state->authoritative,
2380 if (tevent_req_nomem(subreq, req)) {
2381 status = NT_STATUS_NO_MEMORY;
2382 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2388 subreq = dcerpc_netr_LogonSamLogon_send(state, state->ev,
2389 state->binding_handle,
2390 state->srv_name_slash,
2391 state->context->client.computer,
2396 state->validation_level,
2398 &state->authoritative);
2399 if (tevent_req_nomem(subreq, req)) {
2400 status = NT_STATUS_NO_MEMORY;
2401 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2406 tevent_req_set_callback(subreq,
2407 netlogon_creds_cli_LogonSamLogon_done,
2411 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq)
2413 struct tevent_req *req =
2414 tevent_req_callback_data(subreq,
2416 struct netlogon_creds_cli_LogonSamLogon_state *state =
2417 tevent_req_data(req,
2418 struct netlogon_creds_cli_LogonSamLogon_state);
2423 if (state->try_logon_ex) {
2424 status = dcerpc_netr_LogonSamLogonEx_recv(subreq,
2427 TALLOC_FREE(subreq);
2428 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2429 state->context->server.try_validation6 = false;
2430 state->context->server.try_logon_ex = false;
2431 netlogon_creds_cli_LogonSamLogon_start(req);
2434 if (tevent_req_nterror(req, status)) {
2435 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2439 if ((state->validation_level == 6) &&
2440 (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS) ||
2441 NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PARAMETER) ||
2442 NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL)))
2444 state->context->server.try_validation6 = false;
2445 netlogon_creds_cli_LogonSamLogon_start(req);
2449 if (tevent_req_nterror(req, result)) {
2450 netlogon_creds_cli_LogonSamLogon_cleanup(req, result);
2454 if (state->ro_creds == NULL) {
2455 tevent_req_done(req);
2459 ok = netlogon_creds_cli_validate(state->context, state->ro_creds);
2462 * We got a race, lets retry with on authenticator
2465 * netlogon_creds_cli_LogonSamLogon_start()
2466 * will TALLOC_FREE(state->ro_creds);
2468 state->try_logon_ex = false;
2469 netlogon_creds_cli_LogonSamLogon_start(req);
2473 netlogon_creds_decrypt_samlogon_validation(state->ro_creds,
2474 state->validation_level,
2477 tevent_req_done(req);
2481 if (state->lk_creds == NULL) {
2482 status = netlogon_creds_cli_lock_recv(subreq, state,
2484 TALLOC_FREE(subreq);
2485 if (tevent_req_nterror(req, status)) {
2486 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2490 netlogon_creds_cli_LogonSamLogon_start(req);
2494 if (state->context->server.try_logon_with) {
2495 status = dcerpc_netr_LogonSamLogonWithFlags_recv(subreq,
2498 TALLOC_FREE(subreq);
2499 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2500 state->context->server.try_logon_with = false;
2501 netlogon_creds_cli_LogonSamLogon_start(req);
2504 if (tevent_req_nterror(req, status)) {
2505 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2509 status = dcerpc_netr_LogonSamLogon_recv(subreq,
2512 TALLOC_FREE(subreq);
2513 if (tevent_req_nterror(req, status)) {
2514 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2519 ok = netlogon_creds_client_check(&state->tmp_creds,
2520 &state->rep_auth.cred);
2522 status = NT_STATUS_ACCESS_DENIED;
2523 tevent_req_nterror(req, status);
2524 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2528 *state->lk_creds = state->tmp_creds;
2529 status = netlogon_creds_cli_store(state->context,
2531 if (tevent_req_nterror(req, status)) {
2532 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2536 if (tevent_req_nterror(req, result)) {
2537 netlogon_creds_cli_LogonSamLogon_cleanup(req, result);
2541 netlogon_creds_decrypt_samlogon_validation(&state->tmp_creds,
2542 state->validation_level,
2545 tevent_req_done(req);
2548 NTSTATUS netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req *req,
2549 TALLOC_CTX *mem_ctx,
2550 uint16_t *validation_level,
2551 union netr_Validation **validation,
2552 uint8_t *authoritative,
2555 struct netlogon_creds_cli_LogonSamLogon_state *state =
2556 tevent_req_data(req,
2557 struct netlogon_creds_cli_LogonSamLogon_state);
2560 /* authoritative is also returned on error */
2561 *authoritative = state->authoritative;
2563 if (tevent_req_is_nterror(req, &status)) {
2564 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2565 tevent_req_received(req);
2569 *validation_level = state->validation_level;
2570 *validation = talloc_move(mem_ctx, &state->validation);
2571 *flags = state->flags;
2573 tevent_req_received(req);
2574 return NT_STATUS_OK;
2577 NTSTATUS netlogon_creds_cli_LogonSamLogon(
2578 struct netlogon_creds_cli_context *context,
2579 struct dcerpc_binding_handle *b,
2580 enum netr_LogonInfoClass logon_level,
2581 const union netr_LogonLevel *logon,
2582 TALLOC_CTX *mem_ctx,
2583 uint16_t *validation_level,
2584 union netr_Validation **validation,
2585 uint8_t *authoritative,
2588 TALLOC_CTX *frame = talloc_stackframe();
2589 struct tevent_context *ev;
2590 struct tevent_req *req;
2591 NTSTATUS status = NT_STATUS_NO_MEMORY;
2593 ev = samba_tevent_context_init(frame);
2597 req = netlogon_creds_cli_LogonSamLogon_send(frame, ev, context, b,
2603 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2606 status = netlogon_creds_cli_LogonSamLogon_recv(req, mem_ctx,
2616 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state {
2617 struct tevent_context *ev;
2618 struct netlogon_creds_cli_context *context;
2619 struct dcerpc_binding_handle *binding_handle;
2621 char *srv_name_slash;
2622 enum dcerpc_AuthType auth_type;
2623 enum dcerpc_AuthLevel auth_level;
2625 const char *site_name;
2627 struct NL_DNS_NAME_INFO_ARRAY *dns_names;
2629 struct netlogon_creds_CredentialState *creds;
2630 struct netlogon_creds_CredentialState tmp_creds;
2631 struct netr_Authenticator req_auth;
2632 struct netr_Authenticator rep_auth;
2635 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req *req,
2637 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req *subreq);
2639 struct tevent_req *netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(TALLOC_CTX *mem_ctx,
2640 struct tevent_context *ev,
2641 struct netlogon_creds_cli_context *context,
2642 struct dcerpc_binding_handle *b,
2643 const char *site_name,
2645 struct NL_DNS_NAME_INFO_ARRAY *dns_names)
2647 struct tevent_req *req;
2648 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state;
2649 struct tevent_req *subreq;
2651 req = tevent_req_create(mem_ctx, &state,
2652 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2658 state->context = context;
2659 state->binding_handle = b;
2661 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
2662 context->server.computer);
2663 if (tevent_req_nomem(state->srv_name_slash, req)) {
2664 return tevent_req_post(req, ev);
2667 state->site_name = site_name;
2668 state->dns_ttl = dns_ttl;
2669 state->dns_names = dns_names;
2671 dcerpc_binding_handle_auth_info(state->binding_handle,
2673 &state->auth_level);
2675 subreq = netlogon_creds_cli_lock_send(state, state->ev,
2677 if (tevent_req_nomem(subreq, req)) {
2678 return tevent_req_post(req, ev);
2681 tevent_req_set_callback(subreq,
2682 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked,
2688 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req *req,
2691 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
2692 tevent_req_data(req,
2693 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2695 if (state->creds == NULL) {
2699 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
2700 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
2701 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
2702 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
2703 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
2704 TALLOC_FREE(state->creds);
2708 netlogon_creds_cli_delete(state->context, &state->creds);
2711 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req *subreq);
2713 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req *subreq)
2715 struct tevent_req *req =
2716 tevent_req_callback_data(subreq,
2718 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
2719 tevent_req_data(req,
2720 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2723 status = netlogon_creds_cli_lock_recv(subreq, state,
2725 TALLOC_FREE(subreq);
2726 if (tevent_req_nterror(req, status)) {
2730 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
2731 switch (state->auth_level) {
2732 case DCERPC_AUTH_LEVEL_INTEGRITY:
2733 case DCERPC_AUTH_LEVEL_PRIVACY:
2736 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2740 uint32_t tmp = state->creds->negotiate_flags;
2742 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
2744 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
2745 * it should be used, which means
2746 * we had a chance to verify no downgrade
2749 * This relies on netlogon_creds_cli_check*
2750 * being called before, as first request after
2753 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2759 * we defer all callbacks in order to cleanup
2760 * the database record.
2762 tevent_req_defer_callback(req, state->ev);
2764 state->tmp_creds = *state->creds;
2765 netlogon_creds_client_authenticator(&state->tmp_creds,
2767 ZERO_STRUCT(state->rep_auth);
2769 subreq = dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_send(state, state->ev,
2770 state->binding_handle,
2771 state->srv_name_slash,
2772 state->tmp_creds.computer_name,
2778 if (tevent_req_nomem(subreq, req)) {
2779 status = NT_STATUS_NO_MEMORY;
2780 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2784 tevent_req_set_callback(subreq,
2785 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done,
2789 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req *subreq)
2791 struct tevent_req *req =
2792 tevent_req_callback_data(subreq,
2794 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
2795 tevent_req_data(req,
2796 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2802 * We use state->dns_names as the memory context, as this is
2803 * the only in/out variable and it has been overwritten by the
2804 * out parameter from the server.
2806 * We need to preserve the return value until the caller can use it.
2808 status = dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_recv(subreq, state->dns_names,
2810 TALLOC_FREE(subreq);
2811 if (tevent_req_nterror(req, status)) {
2812 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2816 ok = netlogon_creds_client_check(&state->tmp_creds,
2817 &state->rep_auth.cred);
2819 status = NT_STATUS_ACCESS_DENIED;
2820 tevent_req_nterror(req, status);
2821 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2825 *state->creds = state->tmp_creds;
2826 status = netlogon_creds_cli_store(state->context,
2829 if (tevent_req_nterror(req, status)) {
2830 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2834 if (tevent_req_nterror(req, result)) {
2835 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, result);
2839 tevent_req_done(req);
2842 NTSTATUS netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(struct tevent_req *req)
2846 if (tevent_req_is_nterror(req, &status)) {
2847 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2848 tevent_req_received(req);
2852 tevent_req_received(req);
2853 return NT_STATUS_OK;
2856 NTSTATUS netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(
2857 struct netlogon_creds_cli_context *context,
2858 struct dcerpc_binding_handle *b,
2859 const char *site_name,
2861 struct NL_DNS_NAME_INFO_ARRAY *dns_names)
2863 TALLOC_CTX *frame = talloc_stackframe();
2864 struct tevent_context *ev;
2865 struct tevent_req *req;
2866 NTSTATUS status = NT_STATUS_NO_MEMORY;
2868 ev = samba_tevent_context_init(frame);
2872 req = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(frame, ev, context, b,
2879 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2882 status = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(req);
2888 struct netlogon_creds_cli_ServerGetTrustInfo_state {
2889 struct tevent_context *ev;
2890 struct netlogon_creds_cli_context *context;
2891 struct dcerpc_binding_handle *binding_handle;
2893 char *srv_name_slash;
2894 enum dcerpc_AuthType auth_type;
2895 enum dcerpc_AuthLevel auth_level;
2897 struct samr_Password new_owf_password;
2898 struct samr_Password old_owf_password;
2899 struct netr_TrustInfo *trust_info;
2901 struct netlogon_creds_CredentialState *creds;
2902 struct netlogon_creds_CredentialState tmp_creds;
2903 struct netr_Authenticator req_auth;
2904 struct netr_Authenticator rep_auth;
2907 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req *req,
2909 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req *subreq);
2911 struct tevent_req *netlogon_creds_cli_ServerGetTrustInfo_send(TALLOC_CTX *mem_ctx,
2912 struct tevent_context *ev,
2913 struct netlogon_creds_cli_context *context,
2914 struct dcerpc_binding_handle *b)
2916 struct tevent_req *req;
2917 struct netlogon_creds_cli_ServerGetTrustInfo_state *state;
2918 struct tevent_req *subreq;
2920 req = tevent_req_create(mem_ctx, &state,
2921 struct netlogon_creds_cli_ServerGetTrustInfo_state);
2927 state->context = context;
2928 state->binding_handle = b;
2930 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
2931 context->server.computer);
2932 if (tevent_req_nomem(state->srv_name_slash, req)) {
2933 return tevent_req_post(req, ev);
2936 dcerpc_binding_handle_auth_info(state->binding_handle,
2938 &state->auth_level);
2940 subreq = netlogon_creds_cli_lock_send(state, state->ev,
2942 if (tevent_req_nomem(subreq, req)) {
2943 return tevent_req_post(req, ev);
2946 tevent_req_set_callback(subreq,
2947 netlogon_creds_cli_ServerGetTrustInfo_locked,
2953 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req *req,
2956 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
2957 tevent_req_data(req,
2958 struct netlogon_creds_cli_ServerGetTrustInfo_state);
2960 if (state->creds == NULL) {
2964 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
2965 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
2966 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
2967 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
2968 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
2969 TALLOC_FREE(state->creds);
2973 netlogon_creds_cli_delete(state->context, &state->creds);
2976 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req *subreq);
2978 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req *subreq)
2980 struct tevent_req *req =
2981 tevent_req_callback_data(subreq,
2983 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
2984 tevent_req_data(req,
2985 struct netlogon_creds_cli_ServerGetTrustInfo_state);
2988 status = netlogon_creds_cli_lock_recv(subreq, state,
2990 TALLOC_FREE(subreq);
2991 if (tevent_req_nterror(req, status)) {
2995 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
2996 switch (state->auth_level) {
2997 case DCERPC_AUTH_LEVEL_PRIVACY:
3000 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3004 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3009 * we defer all callbacks in order to cleanup
3010 * the database record.
3012 tevent_req_defer_callback(req, state->ev);
3014 state->tmp_creds = *state->creds;
3015 netlogon_creds_client_authenticator(&state->tmp_creds,
3017 ZERO_STRUCT(state->rep_auth);
3019 subreq = dcerpc_netr_ServerGetTrustInfo_send(state, state->ev,
3020 state->binding_handle,
3021 state->srv_name_slash,
3022 state->tmp_creds.account_name,
3023 state->tmp_creds.secure_channel_type,
3024 state->tmp_creds.computer_name,
3027 &state->new_owf_password,
3028 &state->old_owf_password,
3029 &state->trust_info);
3030 if (tevent_req_nomem(subreq, req)) {
3031 status = NT_STATUS_NO_MEMORY;
3032 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3036 tevent_req_set_callback(subreq,
3037 netlogon_creds_cli_ServerGetTrustInfo_done,
3041 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req *subreq)
3043 struct tevent_req *req =
3044 tevent_req_callback_data(subreq,
3046 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
3047 tevent_req_data(req,
3048 struct netlogon_creds_cli_ServerGetTrustInfo_state);
3051 const struct samr_Password zero = {};
3056 * We use state->dns_names as the memory context, as this is
3057 * the only in/out variable and it has been overwritten by the
3058 * out parameter from the server.
3060 * We need to preserve the return value until the caller can use it.
3062 status = dcerpc_netr_ServerGetTrustInfo_recv(subreq, state, &result);
3063 TALLOC_FREE(subreq);
3064 if (tevent_req_nterror(req, status)) {
3065 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3069 ok = netlogon_creds_client_check(&state->tmp_creds,
3070 &state->rep_auth.cred);
3072 status = NT_STATUS_ACCESS_DENIED;
3073 tevent_req_nterror(req, status);
3074 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3078 cmp = memcmp(state->new_owf_password.hash,
3079 zero.hash, sizeof(zero.hash));
3081 netlogon_creds_des_decrypt(&state->tmp_creds,
3082 &state->new_owf_password);
3084 cmp = memcmp(state->old_owf_password.hash,
3085 zero.hash, sizeof(zero.hash));
3087 netlogon_creds_des_decrypt(&state->tmp_creds,
3088 &state->old_owf_password);
3091 *state->creds = state->tmp_creds;
3092 status = netlogon_creds_cli_store(state->context,
3094 if (tevent_req_nterror(req, status)) {
3095 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3099 if (tevent_req_nterror(req, result)) {
3100 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, result);
3104 tevent_req_done(req);
3107 NTSTATUS netlogon_creds_cli_ServerGetTrustInfo_recv(struct tevent_req *req,
3108 TALLOC_CTX *mem_ctx,
3109 struct samr_Password *new_owf_password,
3110 struct samr_Password *old_owf_password,
3111 struct netr_TrustInfo **trust_info)
3113 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
3114 tevent_req_data(req,
3115 struct netlogon_creds_cli_ServerGetTrustInfo_state);
3118 if (tevent_req_is_nterror(req, &status)) {
3119 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3120 tevent_req_received(req);
3124 if (new_owf_password != NULL) {
3125 *new_owf_password = state->new_owf_password;
3127 if (old_owf_password != NULL) {
3128 *old_owf_password = state->old_owf_password;
3130 if (trust_info != NULL) {
3131 *trust_info = talloc_move(mem_ctx, &state->trust_info);
3134 tevent_req_received(req);
3135 return NT_STATUS_OK;
3138 NTSTATUS netlogon_creds_cli_ServerGetTrustInfo(
3139 struct netlogon_creds_cli_context *context,
3140 struct dcerpc_binding_handle *b,
3141 TALLOC_CTX *mem_ctx,
3142 struct samr_Password *new_owf_password,
3143 struct samr_Password *old_owf_password,
3144 struct netr_TrustInfo **trust_info)
3146 TALLOC_CTX *frame = talloc_stackframe();
3147 struct tevent_context *ev;
3148 struct tevent_req *req;
3149 NTSTATUS status = NT_STATUS_NO_MEMORY;
3151 ev = samba_tevent_context_init(frame);
3155 req = netlogon_creds_cli_ServerGetTrustInfo_send(frame, ev, context, b);
3159 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3162 status = netlogon_creds_cli_ServerGetTrustInfo_recv(req,
3172 struct netlogon_creds_cli_GetForestTrustInformation_state {
3173 struct tevent_context *ev;
3174 struct netlogon_creds_cli_context *context;
3175 struct dcerpc_binding_handle *binding_handle;
3177 char *srv_name_slash;
3178 enum dcerpc_AuthType auth_type;
3179 enum dcerpc_AuthLevel auth_level;
3182 struct lsa_ForestTrustInformation *forest_trust_info;
3184 struct netlogon_creds_CredentialState *creds;
3185 struct netlogon_creds_CredentialState tmp_creds;
3186 struct netr_Authenticator req_auth;
3187 struct netr_Authenticator rep_auth;
3190 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req *req,
3192 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req *subreq);
3194 struct tevent_req *netlogon_creds_cli_GetForestTrustInformation_send(TALLOC_CTX *mem_ctx,
3195 struct tevent_context *ev,
3196 struct netlogon_creds_cli_context *context,
3197 struct dcerpc_binding_handle *b)
3199 struct tevent_req *req;
3200 struct netlogon_creds_cli_GetForestTrustInformation_state *state;
3201 struct tevent_req *subreq;
3203 req = tevent_req_create(mem_ctx, &state,
3204 struct netlogon_creds_cli_GetForestTrustInformation_state);
3210 state->context = context;
3211 state->binding_handle = b;
3213 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
3214 context->server.computer);
3215 if (tevent_req_nomem(state->srv_name_slash, req)) {
3216 return tevent_req_post(req, ev);
3221 dcerpc_binding_handle_auth_info(state->binding_handle,
3223 &state->auth_level);
3225 subreq = netlogon_creds_cli_lock_send(state, state->ev,
3227 if (tevent_req_nomem(subreq, req)) {
3228 return tevent_req_post(req, ev);
3231 tevent_req_set_callback(subreq,
3232 netlogon_creds_cli_GetForestTrustInformation_locked,
3238 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req *req,
3241 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3242 tevent_req_data(req,
3243 struct netlogon_creds_cli_GetForestTrustInformation_state);
3245 if (state->creds == NULL) {
3249 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
3250 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
3251 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
3252 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
3253 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
3254 TALLOC_FREE(state->creds);
3258 netlogon_creds_cli_delete(state->context, &state->creds);
3261 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req *subreq);
3263 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req *subreq)
3265 struct tevent_req *req =
3266 tevent_req_callback_data(subreq,
3268 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3269 tevent_req_data(req,
3270 struct netlogon_creds_cli_GetForestTrustInformation_state);
3273 status = netlogon_creds_cli_lock_recv(subreq, state,
3275 TALLOC_FREE(subreq);
3276 if (tevent_req_nterror(req, status)) {
3280 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
3281 switch (state->auth_level) {
3282 case DCERPC_AUTH_LEVEL_INTEGRITY:
3283 case DCERPC_AUTH_LEVEL_PRIVACY:
3286 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3290 uint32_t tmp = state->creds->negotiate_flags;
3292 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
3294 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3295 * it should be used, which means
3296 * we had a chance to verify no downgrade
3299 * This relies on netlogon_creds_cli_check*
3300 * being called before, as first request after
3303 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3309 * we defer all callbacks in order to cleanup
3310 * the database record.
3312 tevent_req_defer_callback(req, state->ev);
3314 state->tmp_creds = *state->creds;
3315 netlogon_creds_client_authenticator(&state->tmp_creds,
3317 ZERO_STRUCT(state->rep_auth);
3319 subreq = dcerpc_netr_GetForestTrustInformation_send(state, state->ev,
3320 state->binding_handle,
3321 state->srv_name_slash,
3322 state->tmp_creds.computer_name,
3326 &state->forest_trust_info);
3327 if (tevent_req_nomem(subreq, req)) {
3328 status = NT_STATUS_NO_MEMORY;
3329 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3333 tevent_req_set_callback(subreq,
3334 netlogon_creds_cli_GetForestTrustInformation_done,
3338 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req *subreq)
3340 struct tevent_req *req =
3341 tevent_req_callback_data(subreq,
3343 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3344 tevent_req_data(req,
3345 struct netlogon_creds_cli_GetForestTrustInformation_state);
3351 * We use state->dns_names as the memory context, as this is
3352 * the only in/out variable and it has been overwritten by the
3353 * out parameter from the server.
3355 * We need to preserve the return value until the caller can use it.
3357 status = dcerpc_netr_GetForestTrustInformation_recv(subreq, state, &result);
3358 TALLOC_FREE(subreq);
3359 if (tevent_req_nterror(req, status)) {
3360 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3364 ok = netlogon_creds_client_check(&state->tmp_creds,
3365 &state->rep_auth.cred);
3367 status = NT_STATUS_ACCESS_DENIED;
3368 tevent_req_nterror(req, status);
3369 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3373 *state->creds = state->tmp_creds;
3374 status = netlogon_creds_cli_store(state->context,
3377 if (tevent_req_nterror(req, status)) {
3378 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3382 if (tevent_req_nterror(req, result)) {
3383 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, result);
3387 tevent_req_done(req);
3390 NTSTATUS netlogon_creds_cli_GetForestTrustInformation_recv(struct tevent_req *req,
3391 TALLOC_CTX *mem_ctx,
3392 struct lsa_ForestTrustInformation **forest_trust_info)
3394 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3395 tevent_req_data(req,
3396 struct netlogon_creds_cli_GetForestTrustInformation_state);
3399 if (tevent_req_is_nterror(req, &status)) {
3400 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3401 tevent_req_received(req);
3405 *forest_trust_info = talloc_move(mem_ctx, &state->forest_trust_info);
3407 tevent_req_received(req);
3408 return NT_STATUS_OK;
3411 NTSTATUS netlogon_creds_cli_GetForestTrustInformation(
3412 struct netlogon_creds_cli_context *context,
3413 struct dcerpc_binding_handle *b,
3414 TALLOC_CTX *mem_ctx,
3415 struct lsa_ForestTrustInformation **forest_trust_info)
3417 TALLOC_CTX *frame = talloc_stackframe();
3418 struct tevent_context *ev;
3419 struct tevent_req *req;
3420 NTSTATUS status = NT_STATUS_NO_MEMORY;
3422 ev = samba_tevent_context_init(frame);
3426 req = netlogon_creds_cli_GetForestTrustInformation_send(frame, ev, context, b);
3430 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3433 status = netlogon_creds_cli_GetForestTrustInformation_recv(req,
3441 struct netlogon_creds_cli_SendToSam_state {
3442 struct tevent_context *ev;
3443 struct netlogon_creds_cli_context *context;
3444 struct dcerpc_binding_handle *binding_handle;
3446 char *srv_name_slash;
3447 enum dcerpc_AuthType auth_type;
3448 enum dcerpc_AuthLevel auth_level;
3452 struct netlogon_creds_CredentialState *creds;
3453 struct netlogon_creds_CredentialState tmp_creds;
3454 struct netr_Authenticator req_auth;
3455 struct netr_Authenticator rep_auth;
3458 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req *req,
3460 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req *subreq);
3462 struct tevent_req *netlogon_creds_cli_SendToSam_send(TALLOC_CTX *mem_ctx,
3463 struct tevent_context *ev,
3464 struct netlogon_creds_cli_context *context,
3465 struct dcerpc_binding_handle *b,
3466 struct netr_SendToSamBase *message)
3468 struct tevent_req *req;
3469 struct netlogon_creds_cli_SendToSam_state *state;
3470 struct tevent_req *subreq;
3471 enum ndr_err_code ndr_err;
3473 req = tevent_req_create(mem_ctx, &state,
3474 struct netlogon_creds_cli_SendToSam_state);
3480 state->context = context;
3481 state->binding_handle = b;
3483 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
3484 context->server.computer);
3485 if (tevent_req_nomem(state->srv_name_slash, req)) {
3486 return tevent_req_post(req, ev);
3489 ndr_err = ndr_push_struct_blob(&state->opaque, mem_ctx, message,
3490 (ndr_push_flags_fn_t)ndr_push_netr_SendToSamBase);
3491 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3492 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
3493 tevent_req_nterror(req, status);
3494 return tevent_req_post(req, ev);
3497 dcerpc_binding_handle_auth_info(state->binding_handle,
3499 &state->auth_level);
3501 subreq = netlogon_creds_cli_lock_send(state, state->ev,
3503 if (tevent_req_nomem(subreq, req)) {
3504 return tevent_req_post(req, ev);
3507 tevent_req_set_callback(subreq,
3508 netlogon_creds_cli_SendToSam_locked,
3514 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req *req,
3517 struct netlogon_creds_cli_SendToSam_state *state =
3518 tevent_req_data(req,
3519 struct netlogon_creds_cli_SendToSam_state);
3521 if (state->creds == NULL) {
3525 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
3526 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
3527 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
3528 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
3529 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
3530 TALLOC_FREE(state->creds);
3534 netlogon_creds_cli_delete(state->context, &state->creds);
3537 static void netlogon_creds_cli_SendToSam_done(struct tevent_req *subreq);
3539 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req *subreq)
3541 struct tevent_req *req =
3542 tevent_req_callback_data(subreq,
3544 struct netlogon_creds_cli_SendToSam_state *state =
3545 tevent_req_data(req,
3546 struct netlogon_creds_cli_SendToSam_state);
3549 status = netlogon_creds_cli_lock_recv(subreq, state,
3551 TALLOC_FREE(subreq);
3552 if (tevent_req_nterror(req, status)) {
3556 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
3557 switch (state->auth_level) {
3558 case DCERPC_AUTH_LEVEL_INTEGRITY:
3559 case DCERPC_AUTH_LEVEL_PRIVACY:
3562 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3566 uint32_t tmp = state->creds->negotiate_flags;
3568 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
3570 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3571 * it should be used, which means
3572 * we had a chance to verify no downgrade
3575 * This relies on netlogon_creds_cli_check*
3576 * being called before, as first request after
3579 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3585 * we defer all callbacks in order to cleanup
3586 * the database record.
3588 tevent_req_defer_callback(req, state->ev);
3590 state->tmp_creds = *state->creds;
3591 netlogon_creds_client_authenticator(&state->tmp_creds,
3593 ZERO_STRUCT(state->rep_auth);
3595 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
3596 netlogon_creds_aes_encrypt(&state->tmp_creds,
3598 state->opaque.length);
3600 netlogon_creds_arcfour_crypt(&state->tmp_creds,
3602 state->opaque.length);
3605 subreq = dcerpc_netr_NetrLogonSendToSam_send(state, state->ev,
3606 state->binding_handle,
3607 state->srv_name_slash,
3608 state->tmp_creds.computer_name,
3612 state->opaque.length);
3613 if (tevent_req_nomem(subreq, req)) {
3614 status = NT_STATUS_NO_MEMORY;
3615 netlogon_creds_cli_SendToSam_cleanup(req, status);
3619 tevent_req_set_callback(subreq,
3620 netlogon_creds_cli_SendToSam_done,
3624 static void netlogon_creds_cli_SendToSam_done(struct tevent_req *subreq)
3626 struct tevent_req *req =
3627 tevent_req_callback_data(subreq,
3629 struct netlogon_creds_cli_SendToSam_state *state =
3630 tevent_req_data(req,
3631 struct netlogon_creds_cli_SendToSam_state);
3636 status = dcerpc_netr_NetrLogonSendToSam_recv(subreq, state, &result);
3637 TALLOC_FREE(subreq);
3638 if (tevent_req_nterror(req, status)) {
3639 netlogon_creds_cli_SendToSam_cleanup(req, status);
3643 ok = netlogon_creds_client_check(&state->tmp_creds,
3644 &state->rep_auth.cred);
3646 status = NT_STATUS_ACCESS_DENIED;
3647 tevent_req_nterror(req, status);
3648 netlogon_creds_cli_SendToSam_cleanup(req, status);
3652 *state->creds = state->tmp_creds;
3653 status = netlogon_creds_cli_store(state->context,
3656 if (tevent_req_nterror(req, status)) {
3657 netlogon_creds_cli_SendToSam_cleanup(req, status);
3662 * Creds must be stored before we send back application errors
3663 * e.g. NT_STATUS_NOT_IMPLEMENTED
3665 if (tevent_req_nterror(req, result)) {
3666 netlogon_creds_cli_SendToSam_cleanup(req, result);
3670 tevent_req_done(req);
3673 NTSTATUS netlogon_creds_cli_SendToSam(struct netlogon_creds_cli_context *context,
3674 struct dcerpc_binding_handle *b,
3675 struct netr_SendToSamBase *message)
3677 TALLOC_CTX *frame = talloc_stackframe();
3678 struct tevent_context *ev;
3679 struct tevent_req *req;
3680 NTSTATUS status = NT_STATUS_OK;
3682 ev = samba_tevent_context_init(frame);
3686 req = netlogon_creds_cli_SendToSam_send(frame, ev, context, b, message);
3690 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3694 /* Ignore the result */