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"
41 #include "auth/credentials/credentials.h"
43 struct netlogon_creds_cli_locked_state;
45 struct netlogon_creds_cli_context {
49 uint32_t proposed_flags;
50 uint32_t required_flags;
51 enum netr_SchannelType type;
52 enum dcerpc_AuthLevel auth_level;
57 const char *netbios_domain;
58 const char *dns_domain;
59 uint32_t cached_flags;
68 struct db_context *ctx;
69 struct g_lock_ctx *g_ctx;
70 struct netlogon_creds_cli_locked_state *locked_state;
71 enum netlogon_creds_cli_lck_type lock;
75 struct netlogon_creds_cli_locked_state {
76 struct netlogon_creds_cli_context *context;
78 struct netlogon_creds_CredentialState *creds;
81 static int netlogon_creds_cli_locked_state_destructor(
82 struct netlogon_creds_cli_locked_state *state)
84 struct netlogon_creds_cli_context *context = state->context;
86 if (context == NULL) {
90 if (context->db.locked_state == state) {
91 context->db.locked_state = NULL;
94 if (state->is_glocked) {
95 g_lock_unlock(context->db.g_ctx,
96 string_term_tdb_data(context->db.key_name));
102 static NTSTATUS netlogon_creds_cli_context_common(
103 const char *client_computer,
104 const char *client_account,
105 enum netr_SchannelType type,
106 enum dcerpc_AuthLevel auth_level,
107 uint32_t proposed_flags,
108 uint32_t required_flags,
109 const char *server_computer,
110 const char *server_netbios_domain,
111 const char *server_dns_domain,
113 struct netlogon_creds_cli_context **_context)
115 struct netlogon_creds_cli_context *context = NULL;
116 char *_key_name = NULL;
117 size_t server_netbios_name_len;
122 context = talloc_zero(mem_ctx, struct netlogon_creds_cli_context);
123 if (context == NULL) {
124 return NT_STATUS_NO_MEMORY;
127 context->client.computer = talloc_strdup(context, client_computer);
128 if (context->client.computer == NULL) {
129 TALLOC_FREE(context);
130 return NT_STATUS_NO_MEMORY;
133 context->client.account = talloc_strdup(context, client_account);
134 if (context->client.account == NULL) {
135 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);
147 return NT_STATUS_NO_MEMORY;
150 context->server.netbios_domain = talloc_strdup(context, server_netbios_domain);
151 if (context->server.netbios_domain == NULL) {
152 TALLOC_FREE(context);
153 return NT_STATUS_NO_MEMORY;
156 context->server.dns_domain = talloc_strdup(context, server_dns_domain);
157 if (context->server.dns_domain == NULL) {
158 TALLOC_FREE(context);
159 return NT_STATUS_NO_MEMORY;
164 * Force the callers to provide a unique
165 * value for server_computer and use this directly.
167 * For now we have to deal with
168 * "HOSTNAME" vs. "hostname.example.com".
171 p = strchr(server_computer, '.');
173 server_netbios_name_len = p-server_computer;
175 server_netbios_name_len = strlen(server_computer);
178 _key_name = talloc_asprintf(context, "CLI[%s/%s]/SRV[%.*s/%s]",
181 (int)server_netbios_name_len,
183 server_netbios_domain);
184 if (_key_name == NULL) {
185 TALLOC_FREE(context);
186 return NT_STATUS_NO_MEMORY;
189 context->db.key_name = talloc_strdup_upper(context, _key_name);
190 TALLOC_FREE(_key_name);
191 if (context->db.key_name == NULL) {
192 TALLOC_FREE(context);
193 return NT_STATUS_NO_MEMORY;
196 context->db.key_data = string_term_tdb_data(context->db.key_name);
202 static struct db_context *netlogon_creds_cli_global_db;
204 NTSTATUS netlogon_creds_cli_set_global_db(struct db_context **db)
206 if (netlogon_creds_cli_global_db != NULL) {
207 return NT_STATUS_INVALID_PARAMETER_MIX;
210 netlogon_creds_cli_global_db = talloc_move(NULL, db);
214 NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx)
217 struct db_context *global_db;
219 if (netlogon_creds_cli_global_db != NULL) {
223 fname = lpcfg_private_db_path(NULL, lp_ctx, "netlogon_creds_cli");
225 return NT_STATUS_NO_MEMORY;
228 global_db = dbwrap_local_open(NULL, lp_ctx,
230 TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
232 0600, DBWRAP_LOCK_ORDER_2,
234 if (global_db == NULL) {
235 DEBUG(0,("netlogon_creds_cli_open_global_db: Failed to open %s - %s\n",
236 fname, strerror(errno)));
238 return NT_STATUS_NO_MEMORY;
242 netlogon_creds_cli_global_db = global_db;
246 void netlogon_creds_cli_close_global_db(void)
248 TALLOC_FREE(netlogon_creds_cli_global_db);
251 NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx,
252 struct messaging_context *msg_ctx,
253 const char *client_account,
254 enum netr_SchannelType type,
255 const char *server_computer,
256 const char *server_netbios_domain,
257 const char *server_dns_domain,
259 struct netlogon_creds_cli_context **_context)
261 TALLOC_CTX *frame = talloc_stackframe();
263 struct netlogon_creds_cli_context *context = NULL;
264 const char *client_computer;
265 uint32_t proposed_flags;
266 uint32_t required_flags = 0;
267 bool reject_md5_servers = false;
268 bool require_strong_key = false;
269 int require_sign_or_seal = true;
270 bool seal_secure_channel = true;
271 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
272 bool neutralize_nt4_emulation = false;
276 if (msg_ctx == NULL) {
278 return NT_STATUS_INVALID_PARAMETER_MIX;
281 client_computer = lpcfg_netbios_name(lp_ctx);
282 if (strlen(client_computer) > 15) {
284 return NT_STATUS_INVALID_PARAMETER_MIX;
288 * allow overwrite per domain
289 * reject md5 servers:<netbios_domain>
291 reject_md5_servers = lpcfg_reject_md5_servers(lp_ctx);
292 reject_md5_servers = lpcfg_parm_bool(lp_ctx, NULL,
293 "reject md5 servers",
294 server_netbios_domain,
298 * allow overwrite per domain
299 * require strong key:<netbios_domain>
301 require_strong_key = lpcfg_require_strong_key(lp_ctx);
302 require_strong_key = lpcfg_parm_bool(lp_ctx, NULL,
303 "require strong key",
304 server_netbios_domain,
308 * allow overwrite per domain
309 * client schannel:<netbios_domain>
311 require_sign_or_seal = lpcfg_client_schannel(lp_ctx);
312 require_sign_or_seal = lpcfg_parm_int(lp_ctx, NULL,
314 server_netbios_domain,
315 require_sign_or_seal);
318 * allow overwrite per domain
319 * winbind sealed pipes:<netbios_domain>
321 seal_secure_channel = lpcfg_winbind_sealed_pipes(lp_ctx);
322 seal_secure_channel = lpcfg_parm_bool(lp_ctx, NULL,
323 "winbind sealed pipes",
324 server_netbios_domain,
325 seal_secure_channel);
328 * allow overwrite per domain
329 * neutralize nt4 emulation:<netbios_domain>
331 neutralize_nt4_emulation = lpcfg_neutralize_nt4_emulation(lp_ctx);
332 neutralize_nt4_emulation = lpcfg_parm_bool(lp_ctx, NULL,
333 "neutralize nt4 emulation",
334 server_netbios_domain,
335 neutralize_nt4_emulation);
337 proposed_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
338 proposed_flags |= NETLOGON_NEG_SUPPORTS_AES;
342 if (lpcfg_security(lp_ctx) == SEC_ADS) {
344 * AD domains should be secure
346 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
347 require_sign_or_seal = true;
348 require_strong_key = true;
352 case SEC_CHAN_DOMAIN:
355 case SEC_CHAN_DNS_DOMAIN:
357 * AD domains should be secure
359 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
360 require_sign_or_seal = true;
361 require_strong_key = true;
362 neutralize_nt4_emulation = true;
366 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
367 require_sign_or_seal = true;
368 require_strong_key = true;
372 required_flags |= NETLOGON_NEG_RODC_PASSTHROUGH;
373 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
374 require_sign_or_seal = true;
375 require_strong_key = true;
376 neutralize_nt4_emulation = true;
381 return NT_STATUS_INVALID_PARAMETER;
384 if (neutralize_nt4_emulation) {
385 proposed_flags |= NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION;
388 if (require_sign_or_seal) {
389 required_flags |= NETLOGON_NEG_ARCFOUR;
390 required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC;
392 proposed_flags &= ~NETLOGON_NEG_AUTHENTICATED_RPC;
395 if (reject_md5_servers) {
396 required_flags |= NETLOGON_NEG_ARCFOUR;
397 required_flags |= NETLOGON_NEG_PASSWORD_SET2;
398 required_flags |= NETLOGON_NEG_SUPPORTS_AES;
399 required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC;
402 if (require_strong_key) {
403 required_flags |= NETLOGON_NEG_ARCFOUR;
404 required_flags |= NETLOGON_NEG_STRONG_KEYS;
405 required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC;
408 proposed_flags |= required_flags;
410 if (seal_secure_channel) {
411 auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
413 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
416 status = netlogon_creds_cli_context_common(client_computer,
423 server_netbios_domain,
427 if (!NT_STATUS_IS_OK(status)) {
432 context->db.g_ctx = g_lock_ctx_init(context, msg_ctx);
433 if (context->db.g_ctx == NULL) {
434 TALLOC_FREE(context);
436 return NT_STATUS_NO_MEMORY;
439 status = netlogon_creds_cli_open_global_db(lp_ctx);
440 if (!NT_STATUS_IS_OK(status)) {
441 TALLOC_FREE(context);
443 return NT_STATUS_NO_MEMORY;
446 context->db.ctx = netlogon_creds_cli_global_db;
452 NTSTATUS netlogon_creds_bind_cli_credentials(
453 struct netlogon_creds_cli_context *context, TALLOC_CTX *mem_ctx,
454 struct cli_credentials **pcli_creds)
456 struct cli_credentials *cli_creds;
457 struct netlogon_creds_CredentialState *ncreds;
460 cli_creds = cli_credentials_init(mem_ctx);
461 if (cli_creds == NULL) {
462 return NT_STATUS_NO_MEMORY;
464 cli_credentials_set_secure_channel_type(cli_creds,
465 context->client.type);
466 cli_credentials_set_username(cli_creds, context->client.account,
468 cli_credentials_set_domain(cli_creds, context->server.netbios_domain,
470 cli_credentials_set_realm(cli_creds, context->server.dns_domain,
473 status = netlogon_creds_cli_get(context, cli_creds, &ncreds);
474 if (!NT_STATUS_IS_OK(status)) {
475 TALLOC_FREE(cli_creds);
478 cli_credentials_set_netlogon_creds(cli_creds, ncreds);
480 *pcli_creds = cli_creds;
484 char *netlogon_creds_cli_debug_string(
485 const struct netlogon_creds_cli_context *context,
488 return talloc_asprintf(mem_ctx, "netlogon_creds_cli:%s",
489 context->db.key_name);
492 enum dcerpc_AuthLevel netlogon_creds_cli_auth_level(
493 struct netlogon_creds_cli_context *context)
495 return context->client.auth_level;
498 struct netlogon_creds_cli_fetch_state {
500 struct netlogon_creds_CredentialState *creds;
501 uint32_t required_flags;
505 static void netlogon_creds_cli_fetch_parser(TDB_DATA key, TDB_DATA data,
508 struct netlogon_creds_cli_fetch_state *state =
509 (struct netlogon_creds_cli_fetch_state *)private_data;
510 enum ndr_err_code ndr_err;
514 state->creds = talloc_zero(state->mem_ctx,
515 struct netlogon_creds_CredentialState);
516 if (state->creds == NULL) {
517 state->status = NT_STATUS_NO_MEMORY;
521 blob.data = data.dptr;
522 blob.length = data.dsize;
524 ndr_err = ndr_pull_struct_blob(&blob, state->creds, state->creds,
525 (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState);
526 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
527 TALLOC_FREE(state->creds);
528 state->status = ndr_map_error2ntstatus(ndr_err);
532 if (DEBUGLEVEL >= 10) {
533 NDR_PRINT_DEBUG(netlogon_creds_CredentialState, state->creds);
536 tmp_flags = state->creds->negotiate_flags;
537 tmp_flags &= state->required_flags;
538 if (tmp_flags != state->required_flags) {
539 TALLOC_FREE(state->creds);
540 state->status = NT_STATUS_DOWNGRADE_DETECTED;
544 state->status = NT_STATUS_OK;
547 static NTSTATUS netlogon_creds_cli_get_internal(
548 struct netlogon_creds_cli_context *context,
549 TALLOC_CTX *mem_ctx, struct netlogon_creds_CredentialState **pcreds);
551 NTSTATUS netlogon_creds_cli_get(struct netlogon_creds_cli_context *context,
553 struct netlogon_creds_CredentialState **_creds)
556 struct netlogon_creds_CredentialState *creds;
560 status = netlogon_creds_cli_get_internal(context, mem_ctx, &creds);
561 if (!NT_STATUS_IS_OK(status)) {
566 * mark it as invalid for step operations.
569 creds->seed = (struct netr_Credential) {{0}};
570 creds->client = (struct netr_Credential) {{0}};
571 creds->server = (struct netr_Credential) {{0}};
577 bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context *context,
578 const struct netlogon_creds_CredentialState *creds1)
580 TALLOC_CTX *frame = talloc_stackframe();
581 struct netlogon_creds_CredentialState *creds2;
585 enum ndr_err_code ndr_err;
588 status = netlogon_creds_cli_get(context, frame, &creds2);
589 if (!NT_STATUS_IS_OK(status)) {
594 ndr_err = ndr_push_struct_blob(&blob1, frame, creds1,
595 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
596 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
601 ndr_err = ndr_push_struct_blob(&blob2, frame, creds2,
602 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
603 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
608 cmp = data_blob_cmp(&blob1, &blob2);
615 static NTSTATUS netlogon_creds_cli_store_internal(
616 struct netlogon_creds_cli_context *context,
617 struct netlogon_creds_CredentialState *creds)
620 enum ndr_err_code ndr_err;
624 if (DEBUGLEVEL >= 10) {
625 NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds);
628 ndr_err = ndr_push_struct_blob(&blob, creds, creds,
629 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
630 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
631 status = ndr_map_error2ntstatus(ndr_err);
635 data.dptr = blob.data;
636 data.dsize = blob.length;
638 status = dbwrap_store(context->db.ctx,
639 context->db.key_data,
641 TALLOC_FREE(data.dptr);
642 if (!NT_STATUS_IS_OK(status)) {
649 NTSTATUS netlogon_creds_cli_store(struct netlogon_creds_cli_context *context,
650 struct netlogon_creds_CredentialState *creds)
654 if (context->db.locked_state == NULL) {
656 * this was not the result of netlogon_creds_cli_lock*()
658 return NT_STATUS_INVALID_PAGE_PROTECTION;
661 if (context->db.locked_state->creds != creds) {
663 * this was not the result of netlogon_creds_cli_lock*()
665 return NT_STATUS_INVALID_PAGE_PROTECTION;
668 status = netlogon_creds_cli_store_internal(context, creds);
672 static NTSTATUS netlogon_creds_cli_delete_internal(
673 struct netlogon_creds_cli_context *context)
676 status = dbwrap_delete(context->db.ctx, context->db.key_data);
680 NTSTATUS netlogon_creds_cli_delete_lck(
681 struct netlogon_creds_cli_context *context)
685 if (context->db.lock != NETLOGON_CREDS_CLI_LCK_EXCLUSIVE) {
686 return NT_STATUS_NOT_LOCKED;
689 status = netlogon_creds_cli_delete_internal(context);
693 NTSTATUS netlogon_creds_cli_delete(struct netlogon_creds_cli_context *context,
694 struct netlogon_creds_CredentialState *creds)
698 if (context->db.locked_state == NULL) {
700 * this was not the result of netlogon_creds_cli_lock*()
702 return NT_STATUS_INVALID_PAGE_PROTECTION;
705 if (context->db.locked_state->creds != creds) {
707 * this was not the result of netlogon_creds_cli_lock*()
709 return NT_STATUS_INVALID_PAGE_PROTECTION;
712 status = netlogon_creds_cli_delete_internal(context);
716 struct netlogon_creds_cli_lock_state {
717 struct netlogon_creds_cli_locked_state *locked_state;
718 struct netlogon_creds_CredentialState *creds;
721 static void netlogon_creds_cli_lock_done(struct tevent_req *subreq);
723 struct tevent_req *netlogon_creds_cli_lock_send(TALLOC_CTX *mem_ctx,
724 struct tevent_context *ev,
725 struct netlogon_creds_cli_context *context)
727 struct tevent_req *req;
728 struct netlogon_creds_cli_lock_state *state;
729 struct netlogon_creds_cli_locked_state *locked_state;
730 struct tevent_req *subreq;
732 req = tevent_req_create(mem_ctx, &state,
733 struct netlogon_creds_cli_lock_state);
738 if (context->db.locked_state != NULL) {
739 tevent_req_nterror(req, NT_STATUS_LOCK_NOT_GRANTED);
740 return tevent_req_post(req, ev);
743 locked_state = talloc_zero(state, struct netlogon_creds_cli_locked_state);
744 if (tevent_req_nomem(locked_state, req)) {
745 return tevent_req_post(req, ev);
747 talloc_set_destructor(locked_state,
748 netlogon_creds_cli_locked_state_destructor);
749 locked_state->context = context;
751 context->db.locked_state = locked_state;
752 state->locked_state = locked_state;
754 if (context->db.g_ctx == NULL) {
757 status = netlogon_creds_cli_get_internal(
758 context, state, &state->creds);
759 if (tevent_req_nterror(req, status)) {
760 return tevent_req_post(req, ev);
766 subreq = g_lock_lock_send(state, ev,
768 string_term_tdb_data(context->db.key_name),
770 if (tevent_req_nomem(subreq, req)) {
771 return tevent_req_post(req, ev);
773 tevent_req_set_callback(subreq, netlogon_creds_cli_lock_done, req);
778 static void netlogon_creds_cli_lock_done(struct tevent_req *subreq)
780 struct tevent_req *req =
781 tevent_req_callback_data(subreq,
783 struct netlogon_creds_cli_lock_state *state =
785 struct netlogon_creds_cli_lock_state);
788 status = g_lock_lock_recv(subreq);
790 if (tevent_req_nterror(req, status)) {
793 state->locked_state->is_glocked = true;
795 status = netlogon_creds_cli_get_internal(state->locked_state->context,
796 state, &state->creds);
797 if (tevent_req_nterror(req, status)) {
800 tevent_req_done(req);
803 static NTSTATUS netlogon_creds_cli_get_internal(
804 struct netlogon_creds_cli_context *context,
805 TALLOC_CTX *mem_ctx, struct netlogon_creds_CredentialState **pcreds)
807 struct netlogon_creds_cli_fetch_state fstate = {
808 .status = NT_STATUS_INTERNAL_ERROR,
809 .required_flags = context->client.required_flags,
813 fstate.mem_ctx = mem_ctx;
814 status = dbwrap_parse_record(context->db.ctx,
815 context->db.key_data,
816 netlogon_creds_cli_fetch_parser,
818 if (!NT_STATUS_IS_OK(status)) {
821 if (!NT_STATUS_IS_OK(fstate.status)) {
822 return fstate.status;
825 if (context->server.cached_flags == fstate.creds->negotiate_flags) {
826 *pcreds = fstate.creds;
831 * It is really important to try SamLogonEx here,
832 * because multiple processes can talk to the same
833 * domain controller, without using the credential
836 * With a normal SamLogon call, we must keep the
837 * credentials chain updated and intact between all
838 * users of the machine account (which would imply
839 * cross-node communication for every NTLM logon).
841 * The credentials chain is not per NETLOGON pipe
842 * connection, but globally on the server/client pair
845 * It's also important to use NetlogonValidationSamInfo4 (6),
846 * because it relies on the rpc transport encryption
847 * and avoids using the global netlogon schannel
848 * session key to en/decrypt secret information
849 * like the user_session_key for network logons.
851 * [MS-APDS] 3.1.5.2 NTLM Network Logon
852 * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and
853 * NETLOGON_NEG_AUTHENTICATED_RPC set together
854 * are the indication that the server supports
855 * NetlogonValidationSamInfo4 (6). And it must only
856 * be used if "SealSecureChannel" is used.
858 * The "SealSecureChannel" AUTH_TYPE_SCHANNEL/AUTH_LEVEL_PRIVACY
859 * check is done in netlogon_creds_cli_LogonSamLogon*().
862 context->server.cached_flags = fstate.creds->negotiate_flags;
863 context->server.try_validation6 = true;
864 context->server.try_logon_ex = true;
865 context->server.try_logon_with = true;
867 if (!(context->server.cached_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
868 context->server.try_validation6 = false;
869 context->server.try_logon_ex = false;
871 if (!(context->server.cached_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) {
872 context->server.try_validation6 = false;
875 *pcreds = fstate.creds;
879 NTSTATUS netlogon_creds_cli_lock_recv(struct tevent_req *req,
881 struct netlogon_creds_CredentialState **creds)
883 struct netlogon_creds_cli_lock_state *state =
885 struct netlogon_creds_cli_lock_state);
888 if (tevent_req_is_nterror(req, &status)) {
889 tevent_req_received(req);
893 talloc_steal(state->creds, state->locked_state);
894 state->locked_state->creds = state->creds;
895 *creds = talloc_move(mem_ctx, &state->creds);
896 tevent_req_received(req);
900 NTSTATUS netlogon_creds_cli_lock(struct netlogon_creds_cli_context *context,
902 struct netlogon_creds_CredentialState **creds)
904 TALLOC_CTX *frame = talloc_stackframe();
905 struct tevent_context *ev;
906 struct tevent_req *req;
907 NTSTATUS status = NT_STATUS_NO_MEMORY;
909 ev = samba_tevent_context_init(frame);
913 req = netlogon_creds_cli_lock_send(frame, ev, context);
917 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
920 status = netlogon_creds_cli_lock_recv(req, mem_ctx, creds);
926 struct netlogon_creds_cli_lck {
927 struct netlogon_creds_cli_context *context;
930 struct netlogon_creds_cli_lck_state {
931 struct netlogon_creds_cli_lck *lck;
932 enum netlogon_creds_cli_lck_type type;
935 static void netlogon_creds_cli_lck_locked(struct tevent_req *subreq);
936 static int netlogon_creds_cli_lck_destructor(
937 struct netlogon_creds_cli_lck *lck);
939 struct tevent_req *netlogon_creds_cli_lck_send(
940 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
941 struct netlogon_creds_cli_context *context,
942 enum netlogon_creds_cli_lck_type type)
944 struct tevent_req *req, *subreq;
945 struct netlogon_creds_cli_lck_state *state;
946 enum g_lock_type gtype;
948 req = tevent_req_create(mem_ctx, &state,
949 struct netlogon_creds_cli_lck_state);
954 if (context->db.lock != NETLOGON_CREDS_CLI_LCK_NONE) {
955 DBG_DEBUG("context already locked\n");
956 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
957 return tevent_req_post(req, ev);
961 case NETLOGON_CREDS_CLI_LCK_SHARED:
964 case NETLOGON_CREDS_CLI_LCK_EXCLUSIVE:
965 gtype = G_LOCK_WRITE;
968 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
969 return tevent_req_post(req, ev);
972 state->lck = talloc(state, struct netlogon_creds_cli_lck);
973 if (tevent_req_nomem(state->lck, req)) {
974 return tevent_req_post(req, ev);
976 state->lck->context = context;
979 subreq = g_lock_lock_send(state, ev,
981 string_term_tdb_data(context->db.key_name),
983 if (tevent_req_nomem(subreq, req)) {
984 return tevent_req_post(req, ev);
986 tevent_req_set_callback(subreq, netlogon_creds_cli_lck_locked, req);
991 static void netlogon_creds_cli_lck_locked(struct tevent_req *subreq)
993 struct tevent_req *req = tevent_req_callback_data(
994 subreq, struct tevent_req);
995 struct netlogon_creds_cli_lck_state *state = tevent_req_data(
996 req, struct netlogon_creds_cli_lck_state);
999 status = g_lock_lock_recv(subreq);
1000 TALLOC_FREE(subreq);
1001 if (tevent_req_nterror(req, status)) {
1005 state->lck->context->db.lock = state->type;
1006 talloc_set_destructor(state->lck, netlogon_creds_cli_lck_destructor);
1008 tevent_req_done(req);
1011 static int netlogon_creds_cli_lck_destructor(
1012 struct netlogon_creds_cli_lck *lck)
1014 struct netlogon_creds_cli_context *ctx = lck->context;
1017 status = g_lock_unlock(ctx->db.g_ctx,
1018 string_term_tdb_data(ctx->db.key_name));
1019 if (!NT_STATUS_IS_OK(status)) {
1020 DBG_WARNING("g_lock_unlock failed: %s\n", nt_errstr(status));
1021 smb_panic("g_lock_unlock failed");
1023 ctx->db.lock = NETLOGON_CREDS_CLI_LCK_NONE;
1027 NTSTATUS netlogon_creds_cli_lck_recv(
1028 struct tevent_req *req, TALLOC_CTX *mem_ctx,
1029 struct netlogon_creds_cli_lck **lck)
1031 struct netlogon_creds_cli_lck_state *state = tevent_req_data(
1032 req, struct netlogon_creds_cli_lck_state);
1035 if (tevent_req_is_nterror(req, &status)) {
1038 *lck = talloc_move(mem_ctx, &state->lck);
1039 return NT_STATUS_OK;
1042 NTSTATUS netlogon_creds_cli_lck(
1043 struct netlogon_creds_cli_context *context,
1044 enum netlogon_creds_cli_lck_type type,
1045 TALLOC_CTX *mem_ctx, struct netlogon_creds_cli_lck **lck)
1047 TALLOC_CTX *frame = talloc_stackframe();
1048 struct tevent_context *ev;
1049 struct tevent_req *req;
1050 NTSTATUS status = NT_STATUS_NO_MEMORY;
1052 ev = samba_tevent_context_init(frame);
1056 req = netlogon_creds_cli_lck_send(frame, ev, context, type);
1060 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1063 status = netlogon_creds_cli_lck_recv(req, mem_ctx, lck);
1069 struct netlogon_creds_cli_auth_state {
1070 struct tevent_context *ev;
1071 struct netlogon_creds_cli_context *context;
1072 struct dcerpc_binding_handle *binding_handle;
1073 uint8_t num_nt_hashes;
1074 uint8_t idx_nt_hashes;
1075 const struct samr_Password * const *nt_hashes;
1076 const struct samr_Password *used_nt_hash;
1077 char *srv_name_slash;
1078 uint32_t current_flags;
1079 struct netr_Credential client_challenge;
1080 struct netr_Credential server_challenge;
1081 struct netlogon_creds_CredentialState *creds;
1082 struct netr_Credential client_credential;
1083 struct netr_Credential server_credential;
1090 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req *req);
1092 struct tevent_req *netlogon_creds_cli_auth_send(TALLOC_CTX *mem_ctx,
1093 struct tevent_context *ev,
1094 struct netlogon_creds_cli_context *context,
1095 struct dcerpc_binding_handle *b,
1096 uint8_t num_nt_hashes,
1097 const struct samr_Password * const *nt_hashes)
1099 struct tevent_req *req;
1100 struct netlogon_creds_cli_auth_state *state;
1103 req = tevent_req_create(mem_ctx, &state,
1104 struct netlogon_creds_cli_auth_state);
1110 state->context = context;
1111 state->binding_handle = b;
1112 if (num_nt_hashes < 1) {
1113 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1114 return tevent_req_post(req, ev);
1116 if (num_nt_hashes > 4) {
1117 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1118 return tevent_req_post(req, ev);
1121 state->num_nt_hashes = num_nt_hashes;
1122 state->idx_nt_hashes = 0;
1123 state->nt_hashes = nt_hashes;
1125 if (context->db.lock != NETLOGON_CREDS_CLI_LCK_EXCLUSIVE) {
1126 tevent_req_nterror(req, NT_STATUS_NOT_LOCKED);
1127 return tevent_req_post(req, ev);
1130 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
1131 context->server.computer);
1132 if (tevent_req_nomem(state->srv_name_slash, req)) {
1133 return tevent_req_post(req, ev);
1136 state->try_auth3 = true;
1137 state->try_auth2 = true;
1139 if (context->client.required_flags != 0) {
1140 state->require_auth2 = true;
1143 state->used_nt_hash = state->nt_hashes[state->idx_nt_hashes];
1144 state->current_flags = context->client.proposed_flags;
1146 status = dbwrap_purge(state->context->db.ctx,
1147 state->context->db.key_data);
1148 if (tevent_req_nterror(req, status)) {
1149 return tevent_req_post(req, ev);
1152 netlogon_creds_cli_auth_challenge_start(req);
1153 if (!tevent_req_is_in_progress(req)) {
1154 return tevent_req_post(req, ev);
1160 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq);
1162 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req *req)
1164 struct netlogon_creds_cli_auth_state *state =
1165 tevent_req_data(req,
1166 struct netlogon_creds_cli_auth_state);
1167 struct tevent_req *subreq;
1169 TALLOC_FREE(state->creds);
1171 generate_random_buffer(state->client_challenge.data,
1172 sizeof(state->client_challenge.data));
1174 subreq = dcerpc_netr_ServerReqChallenge_send(state, state->ev,
1175 state->binding_handle,
1176 state->srv_name_slash,
1177 state->context->client.computer,
1178 &state->client_challenge,
1179 &state->server_challenge);
1180 if (tevent_req_nomem(subreq, req)) {
1183 tevent_req_set_callback(subreq,
1184 netlogon_creds_cli_auth_challenge_done,
1188 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq);
1190 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq)
1192 struct tevent_req *req =
1193 tevent_req_callback_data(subreq,
1195 struct netlogon_creds_cli_auth_state *state =
1196 tevent_req_data(req,
1197 struct netlogon_creds_cli_auth_state);
1201 status = dcerpc_netr_ServerReqChallenge_recv(subreq, state, &result);
1202 TALLOC_FREE(subreq);
1203 if (tevent_req_nterror(req, status)) {
1206 if (tevent_req_nterror(req, result)) {
1210 if (!state->try_auth3 && !state->try_auth2) {
1211 state->current_flags = 0;
1214 /* Calculate the session key and client credentials */
1216 state->creds = netlogon_creds_client_init(state,
1217 state->context->client.account,
1218 state->context->client.computer,
1219 state->context->client.type,
1220 &state->client_challenge,
1221 &state->server_challenge,
1222 state->used_nt_hash,
1223 &state->client_credential,
1224 state->current_flags);
1225 if (tevent_req_nomem(state->creds, req)) {
1229 if (state->try_auth3) {
1230 subreq = dcerpc_netr_ServerAuthenticate3_send(state, state->ev,
1231 state->binding_handle,
1232 state->srv_name_slash,
1233 state->context->client.account,
1234 state->context->client.type,
1235 state->context->client.computer,
1236 &state->client_credential,
1237 &state->server_credential,
1238 &state->creds->negotiate_flags,
1240 if (tevent_req_nomem(subreq, req)) {
1243 } else if (state->try_auth2) {
1246 subreq = dcerpc_netr_ServerAuthenticate2_send(state, state->ev,
1247 state->binding_handle,
1248 state->srv_name_slash,
1249 state->context->client.account,
1250 state->context->client.type,
1251 state->context->client.computer,
1252 &state->client_credential,
1253 &state->server_credential,
1254 &state->creds->negotiate_flags);
1255 if (tevent_req_nomem(subreq, req)) {
1261 subreq = dcerpc_netr_ServerAuthenticate_send(state, state->ev,
1262 state->binding_handle,
1263 state->srv_name_slash,
1264 state->context->client.account,
1265 state->context->client.type,
1266 state->context->client.computer,
1267 &state->client_credential,
1268 &state->server_credential);
1269 if (tevent_req_nomem(subreq, req)) {
1273 tevent_req_set_callback(subreq,
1274 netlogon_creds_cli_auth_srvauth_done,
1278 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq)
1280 struct tevent_req *req =
1281 tevent_req_callback_data(subreq,
1283 struct netlogon_creds_cli_auth_state *state =
1284 tevent_req_data(req,
1285 struct netlogon_creds_cli_auth_state);
1289 enum ndr_err_code ndr_err;
1294 if (state->try_auth3) {
1295 status = dcerpc_netr_ServerAuthenticate3_recv(subreq, state,
1297 TALLOC_FREE(subreq);
1298 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1299 state->try_auth3 = false;
1300 netlogon_creds_cli_auth_challenge_start(req);
1303 if (tevent_req_nterror(req, status)) {
1306 } else if (state->try_auth2) {
1307 status = dcerpc_netr_ServerAuthenticate2_recv(subreq, state,
1309 TALLOC_FREE(subreq);
1310 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1311 state->try_auth2 = false;
1312 if (state->require_auth2) {
1313 status = NT_STATUS_DOWNGRADE_DETECTED;
1314 tevent_req_nterror(req, status);
1317 netlogon_creds_cli_auth_challenge_start(req);
1320 if (tevent_req_nterror(req, status)) {
1324 status = dcerpc_netr_ServerAuthenticate_recv(subreq, state,
1326 TALLOC_FREE(subreq);
1327 if (tevent_req_nterror(req, status)) {
1332 if (!NT_STATUS_IS_OK(result) &&
1333 !NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED))
1335 tevent_req_nterror(req, result);
1339 tmp_flags = state->creds->negotiate_flags;
1340 tmp_flags &= state->context->client.required_flags;
1341 if (tmp_flags != state->context->client.required_flags) {
1342 if (NT_STATUS_IS_OK(result)) {
1343 tevent_req_nterror(req, NT_STATUS_DOWNGRADE_DETECTED);
1346 tevent_req_nterror(req, result);
1350 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
1352 tmp_flags = state->context->client.proposed_flags;
1353 if ((state->current_flags == tmp_flags) &&
1354 (state->creds->negotiate_flags != tmp_flags))
1357 * lets retry with the negotiated flags
1359 state->current_flags = state->creds->negotiate_flags;
1360 netlogon_creds_cli_auth_challenge_start(req);
1364 state->idx_nt_hashes += 1;
1365 if (state->idx_nt_hashes >= state->num_nt_hashes) {
1367 * we already retried, giving up...
1369 tevent_req_nterror(req, result);
1374 * lets retry with the old nt hash.
1376 state->used_nt_hash = state->nt_hashes[state->idx_nt_hashes];
1377 state->current_flags = state->context->client.proposed_flags;
1378 netlogon_creds_cli_auth_challenge_start(req);
1382 ok = netlogon_creds_client_check(state->creds,
1383 &state->server_credential);
1385 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1389 ndr_err = ndr_push_struct_blob(&blob, state, state->creds,
1390 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
1391 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1392 status = ndr_map_error2ntstatus(ndr_err);
1393 tevent_req_nterror(req, status);
1397 data.dptr = blob.data;
1398 data.dsize = blob.length;
1400 status = dbwrap_store(state->context->db.ctx,
1401 state->context->db.key_data,
1403 if (tevent_req_nterror(req, status)) {
1407 tevent_req_done(req);
1410 NTSTATUS netlogon_creds_cli_auth_recv(struct tevent_req *req,
1411 uint8_t *idx_nt_hashes)
1413 struct netlogon_creds_cli_auth_state *state =
1414 tevent_req_data(req,
1415 struct netlogon_creds_cli_auth_state);
1420 if (tevent_req_is_nterror(req, &status)) {
1421 tevent_req_received(req);
1425 *idx_nt_hashes = state->idx_nt_hashes;
1426 tevent_req_received(req);
1427 return NT_STATUS_OK;
1430 NTSTATUS netlogon_creds_cli_auth(struct netlogon_creds_cli_context *context,
1431 struct dcerpc_binding_handle *b,
1432 uint8_t num_nt_hashes,
1433 const struct samr_Password * const *nt_hashes,
1434 uint8_t *idx_nt_hashes)
1436 TALLOC_CTX *frame = talloc_stackframe();
1437 struct tevent_context *ev;
1438 struct tevent_req *req;
1439 NTSTATUS status = NT_STATUS_NO_MEMORY;
1443 ev = samba_tevent_context_init(frame);
1447 req = netlogon_creds_cli_auth_send(frame, ev, context, b,
1448 num_nt_hashes, nt_hashes);
1452 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1455 status = netlogon_creds_cli_auth_recv(req, idx_nt_hashes);
1461 struct netlogon_creds_cli_check_state {
1462 struct tevent_context *ev;
1463 struct netlogon_creds_cli_context *context;
1464 struct dcerpc_binding_handle *binding_handle;
1466 char *srv_name_slash;
1468 union netr_Capabilities caps;
1470 struct netlogon_creds_CredentialState *creds;
1471 struct netr_Authenticator req_auth;
1472 struct netr_Authenticator rep_auth;
1475 static void netlogon_creds_cli_check_cleanup(struct tevent_req *req,
1477 static void netlogon_creds_cli_check_caps(struct tevent_req *subreq);
1479 struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx,
1480 struct tevent_context *ev,
1481 struct netlogon_creds_cli_context *context,
1482 struct dcerpc_binding_handle *b)
1484 struct tevent_req *req;
1485 struct netlogon_creds_cli_check_state *state;
1486 struct tevent_req *subreq;
1487 enum dcerpc_AuthType auth_type;
1488 enum dcerpc_AuthLevel auth_level;
1491 req = tevent_req_create(mem_ctx, &state,
1492 struct netlogon_creds_cli_check_state);
1498 state->context = context;
1499 state->binding_handle = b;
1501 if (context->db.lock != NETLOGON_CREDS_CLI_LCK_EXCLUSIVE) {
1502 tevent_req_nterror(req, NT_STATUS_NOT_LOCKED);
1503 return tevent_req_post(req, ev);
1506 status = netlogon_creds_cli_get_internal(context, state,
1508 if (tevent_req_nterror(req, status)) {
1509 return tevent_req_post(req, ev);
1512 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
1513 context->server.computer);
1514 if (tevent_req_nomem(state->srv_name_slash, req)) {
1515 return tevent_req_post(req, ev);
1518 dcerpc_binding_handle_auth_info(state->binding_handle,
1519 &auth_type, &auth_level);
1521 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1522 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1523 return tevent_req_post(req, ev);
1526 switch (auth_level) {
1527 case DCERPC_AUTH_LEVEL_INTEGRITY:
1528 case DCERPC_AUTH_LEVEL_PRIVACY:
1531 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1532 return tevent_req_post(req, ev);
1536 * we defer all callbacks in order to cleanup
1537 * the database record.
1539 tevent_req_defer_callback(req, state->ev);
1541 netlogon_creds_client_authenticator(state->creds, &state->req_auth);
1542 ZERO_STRUCT(state->rep_auth);
1544 subreq = dcerpc_netr_LogonGetCapabilities_send(state, state->ev,
1545 state->binding_handle,
1546 state->srv_name_slash,
1547 state->context->client.computer,
1552 if (tevent_req_nomem(subreq, req)) {
1553 return tevent_req_post(req, ev);
1556 tevent_req_set_callback(subreq,
1557 netlogon_creds_cli_check_caps,
1563 static void netlogon_creds_cli_check_cleanup(struct tevent_req *req,
1566 struct netlogon_creds_cli_check_state *state =
1567 tevent_req_data(req,
1568 struct netlogon_creds_cli_check_state);
1570 if (state->creds == NULL) {
1574 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
1575 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
1576 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
1577 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
1578 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1579 TALLOC_FREE(state->creds);
1583 netlogon_creds_cli_delete_lck(state->context);
1584 TALLOC_FREE(state->creds);
1587 static void netlogon_creds_cli_check_caps(struct tevent_req *subreq)
1589 struct tevent_req *req =
1590 tevent_req_callback_data(subreq,
1592 struct netlogon_creds_cli_check_state *state =
1593 tevent_req_data(req,
1594 struct netlogon_creds_cli_check_state);
1599 status = dcerpc_netr_LogonGetCapabilities_recv(subreq, state,
1601 TALLOC_FREE(subreq);
1602 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1604 * Note that the negotiated flags are already checked
1605 * for our required flags after the ServerAuthenticate3/2 call.
1607 uint32_t negotiated = state->creds->negotiate_flags;
1609 if (negotiated & NETLOGON_NEG_SUPPORTS_AES) {
1611 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1612 * already, we expect this to work!
1614 status = NT_STATUS_DOWNGRADE_DETECTED;
1615 tevent_req_nterror(req, status);
1616 netlogon_creds_cli_check_cleanup(req, status);
1620 if (negotiated & NETLOGON_NEG_STRONG_KEYS) {
1622 * If we have negotiated NETLOGON_NEG_STRONG_KEYS
1623 * we expect this to work at least as far as the
1624 * NOT_SUPPORTED error handled below!
1626 * NT 4.0 and Old Samba servers are not
1627 * allowed without "require strong key = no"
1629 status = NT_STATUS_DOWNGRADE_DETECTED;
1630 tevent_req_nterror(req, status);
1631 netlogon_creds_cli_check_cleanup(req, status);
1636 * If we not require NETLOGON_NEG_SUPPORTS_AES or
1637 * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore
1638 * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
1640 * This is needed against NT 4.0 and old Samba servers.
1642 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
1643 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
1644 * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
1645 * with the next request as the sequence number processing
1648 netlogon_creds_cli_check_cleanup(req, status);
1649 tevent_req_done(req);
1652 if (tevent_req_nterror(req, status)) {
1653 netlogon_creds_cli_check_cleanup(req, status);
1657 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
1659 * Note that the negotiated flags are already checked
1660 * for our required flags after the ServerAuthenticate3/2 call.
1662 uint32_t negotiated = state->creds->negotiate_flags;
1664 if (negotiated & NETLOGON_NEG_SUPPORTS_AES) {
1666 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1667 * already, we expect this to work!
1669 status = NT_STATUS_DOWNGRADE_DETECTED;
1670 tevent_req_nterror(req, status);
1671 netlogon_creds_cli_check_cleanup(req, status);
1676 * This is ok, the server does not support
1677 * NETLOGON_NEG_SUPPORTS_AES.
1679 * netr_LogonGetCapabilities() was
1680 * netr_LogonDummyRoutine1() before
1681 * NETLOGON_NEG_SUPPORTS_AES was invented.
1683 netlogon_creds_cli_check_cleanup(req, result);
1684 tevent_req_done(req);
1688 ok = netlogon_creds_client_check(state->creds, &state->rep_auth.cred);
1690 status = NT_STATUS_ACCESS_DENIED;
1691 tevent_req_nterror(req, status);
1692 netlogon_creds_cli_check_cleanup(req, status);
1696 if (tevent_req_nterror(req, result)) {
1697 netlogon_creds_cli_check_cleanup(req, result);
1701 if (state->caps.server_capabilities != state->creds->negotiate_flags) {
1702 status = NT_STATUS_DOWNGRADE_DETECTED;
1703 tevent_req_nterror(req, status);
1704 netlogon_creds_cli_check_cleanup(req, status);
1709 * This is the key check that makes this check secure. If we
1710 * get OK here (rather than NOT_SUPPORTED), then the server
1711 * did support AES. If the server only proposed STRONG_KEYS
1712 * and not AES, then it should have failed with
1713 * NOT_IMPLEMENTED. We always send AES as a client, so the
1714 * server should always have returned it.
1716 if (!(state->caps.server_capabilities & NETLOGON_NEG_SUPPORTS_AES)) {
1717 status = NT_STATUS_DOWNGRADE_DETECTED;
1718 tevent_req_nterror(req, status);
1719 netlogon_creds_cli_check_cleanup(req, status);
1723 status = netlogon_creds_cli_store_internal(state->context,
1725 if (tevent_req_nterror(req, status)) {
1729 tevent_req_done(req);
1732 NTSTATUS netlogon_creds_cli_check_recv(struct tevent_req *req,
1733 union netr_Capabilities *capabilities)
1735 struct netlogon_creds_cli_check_state *state = tevent_req_data(
1736 req, struct netlogon_creds_cli_check_state);
1739 if (tevent_req_is_nterror(req, &status)) {
1740 netlogon_creds_cli_check_cleanup(req, status);
1741 tevent_req_received(req);
1745 if (capabilities != NULL) {
1746 *capabilities = state->caps;
1749 tevent_req_received(req);
1750 return NT_STATUS_OK;
1753 NTSTATUS netlogon_creds_cli_check(struct netlogon_creds_cli_context *context,
1754 struct dcerpc_binding_handle *b,
1755 union netr_Capabilities *capabilities)
1757 TALLOC_CTX *frame = talloc_stackframe();
1758 struct tevent_context *ev;
1759 struct tevent_req *req;
1760 NTSTATUS status = NT_STATUS_NO_MEMORY;
1762 ev = samba_tevent_context_init(frame);
1766 req = netlogon_creds_cli_check_send(frame, ev, context, b);
1770 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1773 status = netlogon_creds_cli_check_recv(req, capabilities);
1779 struct netlogon_creds_cli_ServerPasswordSet_state {
1780 struct tevent_context *ev;
1781 struct netlogon_creds_cli_context *context;
1782 struct dcerpc_binding_handle *binding_handle;
1783 uint32_t old_timeout;
1785 char *srv_name_slash;
1786 enum dcerpc_AuthType auth_type;
1787 enum dcerpc_AuthLevel auth_level;
1789 struct samr_CryptPassword samr_crypt_password;
1790 struct netr_CryptPassword netr_crypt_password;
1791 struct samr_Password samr_password;
1793 struct netlogon_creds_CredentialState *creds;
1794 struct netlogon_creds_CredentialState tmp_creds;
1795 struct netr_Authenticator req_auth;
1796 struct netr_Authenticator rep_auth;
1799 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req *req,
1801 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subreq);
1803 struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx,
1804 struct tevent_context *ev,
1805 struct netlogon_creds_cli_context *context,
1806 struct dcerpc_binding_handle *b,
1807 const DATA_BLOB *new_password,
1808 const uint32_t *new_version)
1810 struct tevent_req *req;
1811 struct netlogon_creds_cli_ServerPasswordSet_state *state;
1812 struct tevent_req *subreq;
1815 req = tevent_req_create(mem_ctx, &state,
1816 struct netlogon_creds_cli_ServerPasswordSet_state);
1822 state->context = context;
1823 state->binding_handle = b;
1825 if (new_password->length < 14) {
1826 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1827 return tevent_req_post(req, ev);
1831 * netr_ServerPasswordSet
1833 mdfour(state->samr_password.hash, new_password->data, new_password->length);
1836 * netr_ServerPasswordSet2
1838 ok = set_pw_in_buffer(state->samr_crypt_password.data,
1841 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1842 return tevent_req_post(req, ev);
1845 if (new_version != NULL) {
1846 struct NL_PASSWORD_VERSION version;
1847 uint32_t len = IVAL(state->samr_crypt_password.data, 512);
1848 uint32_t ofs = 512 - len;
1852 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1853 return tevent_req_post(req, ev);
1857 version.ReservedField = 0;
1858 version.PasswordVersionNumber = *new_version;
1859 version.PasswordVersionPresent =
1860 NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT;
1862 p = state->samr_crypt_password.data + ofs;
1863 SIVAL(p, 0, version.ReservedField);
1864 SIVAL(p, 4, version.PasswordVersionNumber);
1865 SIVAL(p, 8, version.PasswordVersionPresent);
1868 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
1869 context->server.computer);
1870 if (tevent_req_nomem(state->srv_name_slash, req)) {
1871 return tevent_req_post(req, ev);
1874 dcerpc_binding_handle_auth_info(state->binding_handle,
1876 &state->auth_level);
1878 subreq = netlogon_creds_cli_lock_send(state, state->ev,
1880 if (tevent_req_nomem(subreq, req)) {
1881 return tevent_req_post(req, ev);
1884 tevent_req_set_callback(subreq,
1885 netlogon_creds_cli_ServerPasswordSet_locked,
1891 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req *req,
1894 struct netlogon_creds_cli_ServerPasswordSet_state *state =
1895 tevent_req_data(req,
1896 struct netlogon_creds_cli_ServerPasswordSet_state);
1898 if (state->creds == NULL) {
1902 dcerpc_binding_handle_set_timeout(state->binding_handle,
1903 state->old_timeout);
1905 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
1906 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
1907 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
1908 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
1909 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1910 TALLOC_FREE(state->creds);
1914 netlogon_creds_cli_delete(state->context, state->creds);
1915 TALLOC_FREE(state->creds);
1918 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq);
1920 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subreq)
1922 struct tevent_req *req =
1923 tevent_req_callback_data(subreq,
1925 struct netlogon_creds_cli_ServerPasswordSet_state *state =
1926 tevent_req_data(req,
1927 struct netlogon_creds_cli_ServerPasswordSet_state);
1930 status = netlogon_creds_cli_lock_recv(subreq, state,
1932 TALLOC_FREE(subreq);
1933 if (tevent_req_nterror(req, status)) {
1937 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
1938 switch (state->auth_level) {
1939 case DCERPC_AUTH_LEVEL_INTEGRITY:
1940 case DCERPC_AUTH_LEVEL_PRIVACY:
1943 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1947 uint32_t tmp = state->creds->negotiate_flags;
1949 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
1951 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
1952 * it should be used, which means
1953 * we had a chance to verify no downgrade
1956 * This relies on netlogon_creds_cli_check*
1957 * being called before, as first request after
1960 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1965 state->old_timeout = dcerpc_binding_handle_set_timeout(
1966 state->binding_handle, 600000);
1969 * we defer all callbacks in order to cleanup
1970 * the database record.
1972 tevent_req_defer_callback(req, state->ev);
1974 state->tmp_creds = *state->creds;
1975 netlogon_creds_client_authenticator(&state->tmp_creds,
1977 ZERO_STRUCT(state->rep_auth);
1979 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) {
1981 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1982 netlogon_creds_aes_encrypt(&state->tmp_creds,
1983 state->samr_crypt_password.data,
1986 netlogon_creds_arcfour_crypt(&state->tmp_creds,
1987 state->samr_crypt_password.data,
1991 memcpy(state->netr_crypt_password.data,
1992 state->samr_crypt_password.data, 512);
1993 state->netr_crypt_password.length =
1994 IVAL(state->samr_crypt_password.data, 512);
1996 subreq = dcerpc_netr_ServerPasswordSet2_send(state, state->ev,
1997 state->binding_handle,
1998 state->srv_name_slash,
1999 state->tmp_creds.account_name,
2000 state->tmp_creds.secure_channel_type,
2001 state->tmp_creds.computer_name,
2004 &state->netr_crypt_password);
2005 if (tevent_req_nomem(subreq, req)) {
2006 status = NT_STATUS_NO_MEMORY;
2007 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2011 netlogon_creds_des_encrypt(&state->tmp_creds,
2012 &state->samr_password);
2014 subreq = dcerpc_netr_ServerPasswordSet_send(state, state->ev,
2015 state->binding_handle,
2016 state->srv_name_slash,
2017 state->tmp_creds.account_name,
2018 state->tmp_creds.secure_channel_type,
2019 state->tmp_creds.computer_name,
2022 &state->samr_password);
2023 if (tevent_req_nomem(subreq, req)) {
2024 status = NT_STATUS_NO_MEMORY;
2025 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2030 tevent_req_set_callback(subreq,
2031 netlogon_creds_cli_ServerPasswordSet_done,
2035 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq)
2037 struct tevent_req *req =
2038 tevent_req_callback_data(subreq,
2040 struct netlogon_creds_cli_ServerPasswordSet_state *state =
2041 tevent_req_data(req,
2042 struct netlogon_creds_cli_ServerPasswordSet_state);
2047 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) {
2048 status = dcerpc_netr_ServerPasswordSet2_recv(subreq, state,
2050 TALLOC_FREE(subreq);
2051 if (tevent_req_nterror(req, status)) {
2052 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2056 status = dcerpc_netr_ServerPasswordSet_recv(subreq, state,
2058 TALLOC_FREE(subreq);
2059 if (tevent_req_nterror(req, status)) {
2060 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2065 ok = netlogon_creds_client_check(&state->tmp_creds,
2066 &state->rep_auth.cred);
2068 status = NT_STATUS_ACCESS_DENIED;
2069 tevent_req_nterror(req, status);
2070 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2074 if (tevent_req_nterror(req, result)) {
2075 netlogon_creds_cli_ServerPasswordSet_cleanup(req, result);
2079 dcerpc_binding_handle_set_timeout(state->binding_handle,
2080 state->old_timeout);
2082 *state->creds = state->tmp_creds;
2083 status = netlogon_creds_cli_store(state->context,
2085 TALLOC_FREE(state->creds);
2086 if (tevent_req_nterror(req, status)) {
2087 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2091 tevent_req_done(req);
2094 NTSTATUS netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req *req)
2098 if (tevent_req_is_nterror(req, &status)) {
2099 netlogon_creds_cli_ServerPasswordSet_cleanup(req, status);
2100 tevent_req_received(req);
2104 tevent_req_received(req);
2105 return NT_STATUS_OK;
2108 NTSTATUS netlogon_creds_cli_ServerPasswordSet(
2109 struct netlogon_creds_cli_context *context,
2110 struct dcerpc_binding_handle *b,
2111 const DATA_BLOB *new_password,
2112 const uint32_t *new_version)
2114 TALLOC_CTX *frame = talloc_stackframe();
2115 struct tevent_context *ev;
2116 struct tevent_req *req;
2117 NTSTATUS status = NT_STATUS_NO_MEMORY;
2119 ev = samba_tevent_context_init(frame);
2123 req = netlogon_creds_cli_ServerPasswordSet_send(frame, ev, context, b,
2129 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2132 status = netlogon_creds_cli_ServerPasswordSet_recv(req);
2138 struct netlogon_creds_cli_LogonSamLogon_state {
2139 struct tevent_context *ev;
2140 struct netlogon_creds_cli_context *context;
2141 struct dcerpc_binding_handle *binding_handle;
2143 char *srv_name_slash;
2145 enum netr_LogonInfoClass logon_level;
2146 const union netr_LogonLevel *const_logon;
2147 union netr_LogonLevel *logon;
2150 uint16_t validation_level;
2151 union netr_Validation *validation;
2152 uint8_t authoritative;
2155 * do we need encryption at the application layer?
2159 bool try_validation6;
2162 * the read only credentials before we started the operation
2163 * used for netr_LogonSamLogonEx() if required (validation_level = 3).
2165 struct netlogon_creds_CredentialState *ro_creds;
2168 * The (locked) credentials used for the credential chain
2169 * used for netr_LogonSamLogonWithFlags() or
2170 * netr_LogonSamLogonWith().
2172 struct netlogon_creds_CredentialState *lk_creds;
2175 * While we have locked the global credentials (lk_creds above)
2176 * we operate an a temporary copy, because a server
2177 * may not support netr_LogonSamLogonWithFlags() and
2178 * didn't process our netr_Authenticator, so we need to
2179 * restart from lk_creds.
2181 struct netlogon_creds_CredentialState tmp_creds;
2182 struct netr_Authenticator req_auth;
2183 struct netr_Authenticator rep_auth;
2186 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req);
2187 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req *req,
2190 struct tevent_req *netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX *mem_ctx,
2191 struct tevent_context *ev,
2192 struct netlogon_creds_cli_context *context,
2193 struct dcerpc_binding_handle *b,
2194 enum netr_LogonInfoClass logon_level,
2195 const union netr_LogonLevel *logon,
2198 struct tevent_req *req;
2199 struct netlogon_creds_cli_LogonSamLogon_state *state;
2201 req = tevent_req_create(mem_ctx, &state,
2202 struct netlogon_creds_cli_LogonSamLogon_state);
2208 state->context = context;
2209 state->binding_handle = b;
2211 state->logon_level = logon_level;
2212 state->const_logon = logon;
2213 state->flags = flags;
2215 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
2216 context->server.computer);
2217 if (tevent_req_nomem(state->srv_name_slash, req)) {
2218 return tevent_req_post(req, ev);
2221 switch (logon_level) {
2222 case NetlogonInteractiveInformation:
2223 case NetlogonInteractiveTransitiveInformation:
2224 case NetlogonServiceInformation:
2225 case NetlogonServiceTransitiveInformation:
2226 case NetlogonGenericInformation:
2227 state->user_encrypt = true;
2230 case NetlogonNetworkInformation:
2231 case NetlogonNetworkTransitiveInformation:
2235 state->validation = talloc_zero(state, union netr_Validation);
2236 if (tevent_req_nomem(state->validation, req)) {
2237 return tevent_req_post(req, ev);
2240 netlogon_creds_cli_LogonSamLogon_start(req);
2241 if (!tevent_req_is_in_progress(req)) {
2242 return tevent_req_post(req, ev);
2246 * we defer all callbacks in order to cleanup
2247 * the database record.
2249 tevent_req_defer_callback(req, state->ev);
2253 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req *req,
2256 struct netlogon_creds_cli_LogonSamLogon_state *state =
2257 tevent_req_data(req,
2258 struct netlogon_creds_cli_LogonSamLogon_state);
2260 if (state->lk_creds == NULL) {
2264 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2266 * This is a hack to recover from a bug in old
2267 * Samba servers, when LogonSamLogonEx() fails:
2269 * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
2271 * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2273 * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE,
2274 * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR
2275 * If the sign/seal check fails.
2277 * In that case we need to cleanup the netlogon session.
2279 * It's the job of the caller to disconnect the current
2280 * connection, if netlogon_creds_cli_LogonSamLogon()
2281 * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2283 if (!state->context->server.try_logon_with) {
2284 status = NT_STATUS_NETWORK_ACCESS_DENIED;
2288 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
2289 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
2290 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
2291 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
2292 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
2293 TALLOC_FREE(state->lk_creds);
2297 netlogon_creds_cli_delete(state->context, state->lk_creds);
2298 TALLOC_FREE(state->lk_creds);
2301 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq);
2303 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req)
2305 struct netlogon_creds_cli_LogonSamLogon_state *state =
2306 tevent_req_data(req,
2307 struct netlogon_creds_cli_LogonSamLogon_state);
2308 struct tevent_req *subreq;
2310 enum dcerpc_AuthType auth_type;
2311 enum dcerpc_AuthLevel auth_level;
2313 TALLOC_FREE(state->ro_creds);
2314 TALLOC_FREE(state->logon);
2315 ZERO_STRUCTP(state->validation);
2317 dcerpc_binding_handle_auth_info(state->binding_handle,
2318 &auth_type, &auth_level);
2320 state->try_logon_ex = state->context->server.try_logon_ex;
2321 state->try_validation6 = state->context->server.try_validation6;
2323 state->try_logon_ex = false;
2325 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
2326 state->try_logon_ex = false;
2329 if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
2330 state->try_validation6 = false;
2333 if (state->try_logon_ex) {
2334 if (state->try_validation6) {
2335 state->validation_level = 6;
2337 state->validation_level = 3;
2338 state->user_encrypt = true;
2341 state->logon = netlogon_creds_shallow_copy_logon(state,
2343 state->const_logon);
2344 if (tevent_req_nomem(state->logon, req)) {
2345 status = NT_STATUS_NO_MEMORY;
2346 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2350 if (state->user_encrypt) {
2351 status = netlogon_creds_cli_get(state->context,
2354 if (!NT_STATUS_IS_OK(status)) {
2355 status = NT_STATUS_ACCESS_DENIED;
2356 tevent_req_nterror(req, status);
2357 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2361 netlogon_creds_encrypt_samlogon_logon(state->ro_creds,
2366 subreq = dcerpc_netr_LogonSamLogonEx_send(state, state->ev,
2367 state->binding_handle,
2368 state->srv_name_slash,
2369 state->context->client.computer,
2372 state->validation_level,
2374 &state->authoritative,
2376 if (tevent_req_nomem(subreq, req)) {
2377 status = NT_STATUS_NO_MEMORY;
2378 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2381 tevent_req_set_callback(subreq,
2382 netlogon_creds_cli_LogonSamLogon_done,
2387 if (state->lk_creds == NULL) {
2388 subreq = netlogon_creds_cli_lock_send(state, state->ev,
2390 if (tevent_req_nomem(subreq, req)) {
2391 status = NT_STATUS_NO_MEMORY;
2392 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2395 tevent_req_set_callback(subreq,
2396 netlogon_creds_cli_LogonSamLogon_done,
2401 state->tmp_creds = *state->lk_creds;
2402 netlogon_creds_client_authenticator(&state->tmp_creds,
2404 ZERO_STRUCT(state->rep_auth);
2406 state->logon = netlogon_creds_shallow_copy_logon(state,
2408 state->const_logon);
2409 if (tevent_req_nomem(state->logon, req)) {
2410 status = NT_STATUS_NO_MEMORY;
2411 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2415 netlogon_creds_encrypt_samlogon_logon(&state->tmp_creds,
2419 state->validation_level = 3;
2421 if (state->context->server.try_logon_with) {
2422 subreq = dcerpc_netr_LogonSamLogonWithFlags_send(state, state->ev,
2423 state->binding_handle,
2424 state->srv_name_slash,
2425 state->context->client.computer,
2430 state->validation_level,
2432 &state->authoritative,
2434 if (tevent_req_nomem(subreq, req)) {
2435 status = NT_STATUS_NO_MEMORY;
2436 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2442 subreq = dcerpc_netr_LogonSamLogon_send(state, state->ev,
2443 state->binding_handle,
2444 state->srv_name_slash,
2445 state->context->client.computer,
2450 state->validation_level,
2452 &state->authoritative);
2453 if (tevent_req_nomem(subreq, req)) {
2454 status = NT_STATUS_NO_MEMORY;
2455 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2460 tevent_req_set_callback(subreq,
2461 netlogon_creds_cli_LogonSamLogon_done,
2465 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq)
2467 struct tevent_req *req =
2468 tevent_req_callback_data(subreq,
2470 struct netlogon_creds_cli_LogonSamLogon_state *state =
2471 tevent_req_data(req,
2472 struct netlogon_creds_cli_LogonSamLogon_state);
2477 if (state->try_logon_ex) {
2478 status = dcerpc_netr_LogonSamLogonEx_recv(subreq,
2481 TALLOC_FREE(subreq);
2482 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2483 state->context->server.try_validation6 = false;
2484 state->context->server.try_logon_ex = false;
2485 netlogon_creds_cli_LogonSamLogon_start(req);
2488 if (tevent_req_nterror(req, status)) {
2489 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2493 if ((state->validation_level == 6) &&
2494 (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS) ||
2495 NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PARAMETER) ||
2496 NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL)))
2498 state->context->server.try_validation6 = false;
2499 netlogon_creds_cli_LogonSamLogon_start(req);
2503 if (tevent_req_nterror(req, result)) {
2504 netlogon_creds_cli_LogonSamLogon_cleanup(req, result);
2508 if (state->ro_creds == NULL) {
2509 tevent_req_done(req);
2513 ok = netlogon_creds_cli_validate(state->context, state->ro_creds);
2516 * We got a race, lets retry with on authenticator
2519 * netlogon_creds_cli_LogonSamLogon_start()
2520 * will TALLOC_FREE(state->ro_creds);
2522 state->try_logon_ex = false;
2523 netlogon_creds_cli_LogonSamLogon_start(req);
2527 netlogon_creds_decrypt_samlogon_validation(state->ro_creds,
2528 state->validation_level,
2531 tevent_req_done(req);
2535 if (state->lk_creds == NULL) {
2536 status = netlogon_creds_cli_lock_recv(subreq, state,
2538 TALLOC_FREE(subreq);
2539 if (tevent_req_nterror(req, status)) {
2540 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2544 netlogon_creds_cli_LogonSamLogon_start(req);
2548 if (state->context->server.try_logon_with) {
2549 status = dcerpc_netr_LogonSamLogonWithFlags_recv(subreq,
2552 TALLOC_FREE(subreq);
2553 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2554 state->context->server.try_logon_with = false;
2555 netlogon_creds_cli_LogonSamLogon_start(req);
2558 if (tevent_req_nterror(req, status)) {
2559 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2563 status = dcerpc_netr_LogonSamLogon_recv(subreq,
2566 TALLOC_FREE(subreq);
2567 if (tevent_req_nterror(req, status)) {
2568 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2573 ok = netlogon_creds_client_check(&state->tmp_creds,
2574 &state->rep_auth.cred);
2576 status = NT_STATUS_ACCESS_DENIED;
2577 tevent_req_nterror(req, status);
2578 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2582 *state->lk_creds = state->tmp_creds;
2583 status = netlogon_creds_cli_store(state->context,
2585 TALLOC_FREE(state->lk_creds);
2587 if (tevent_req_nterror(req, status)) {
2588 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2592 if (tevent_req_nterror(req, result)) {
2593 netlogon_creds_cli_LogonSamLogon_cleanup(req, result);
2597 netlogon_creds_decrypt_samlogon_validation(&state->tmp_creds,
2598 state->validation_level,
2601 tevent_req_done(req);
2604 NTSTATUS netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req *req,
2605 TALLOC_CTX *mem_ctx,
2606 uint16_t *validation_level,
2607 union netr_Validation **validation,
2608 uint8_t *authoritative,
2611 struct netlogon_creds_cli_LogonSamLogon_state *state =
2612 tevent_req_data(req,
2613 struct netlogon_creds_cli_LogonSamLogon_state);
2616 /* authoritative is also returned on error */
2617 *authoritative = state->authoritative;
2619 if (tevent_req_is_nterror(req, &status)) {
2620 netlogon_creds_cli_LogonSamLogon_cleanup(req, status);
2621 tevent_req_received(req);
2625 *validation_level = state->validation_level;
2626 *validation = talloc_move(mem_ctx, &state->validation);
2627 *flags = state->flags;
2629 tevent_req_received(req);
2630 return NT_STATUS_OK;
2633 NTSTATUS netlogon_creds_cli_LogonSamLogon(
2634 struct netlogon_creds_cli_context *context,
2635 struct dcerpc_binding_handle *b,
2636 enum netr_LogonInfoClass logon_level,
2637 const union netr_LogonLevel *logon,
2638 TALLOC_CTX *mem_ctx,
2639 uint16_t *validation_level,
2640 union netr_Validation **validation,
2641 uint8_t *authoritative,
2644 TALLOC_CTX *frame = talloc_stackframe();
2645 struct tevent_context *ev;
2646 struct tevent_req *req;
2647 NTSTATUS status = NT_STATUS_NO_MEMORY;
2649 ev = samba_tevent_context_init(frame);
2653 req = netlogon_creds_cli_LogonSamLogon_send(frame, ev, context, b,
2659 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2662 status = netlogon_creds_cli_LogonSamLogon_recv(req, mem_ctx,
2672 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state {
2673 struct tevent_context *ev;
2674 struct netlogon_creds_cli_context *context;
2675 struct dcerpc_binding_handle *binding_handle;
2677 char *srv_name_slash;
2678 enum dcerpc_AuthType auth_type;
2679 enum dcerpc_AuthLevel auth_level;
2681 const char *site_name;
2683 struct NL_DNS_NAME_INFO_ARRAY *dns_names;
2685 struct netlogon_creds_CredentialState *creds;
2686 struct netlogon_creds_CredentialState tmp_creds;
2687 struct netr_Authenticator req_auth;
2688 struct netr_Authenticator rep_auth;
2691 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req *req,
2693 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req *subreq);
2695 struct tevent_req *netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(TALLOC_CTX *mem_ctx,
2696 struct tevent_context *ev,
2697 struct netlogon_creds_cli_context *context,
2698 struct dcerpc_binding_handle *b,
2699 const char *site_name,
2701 struct NL_DNS_NAME_INFO_ARRAY *dns_names)
2703 struct tevent_req *req;
2704 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state;
2705 struct tevent_req *subreq;
2707 req = tevent_req_create(mem_ctx, &state,
2708 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2714 state->context = context;
2715 state->binding_handle = b;
2717 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
2718 context->server.computer);
2719 if (tevent_req_nomem(state->srv_name_slash, req)) {
2720 return tevent_req_post(req, ev);
2723 state->site_name = site_name;
2724 state->dns_ttl = dns_ttl;
2725 state->dns_names = dns_names;
2727 dcerpc_binding_handle_auth_info(state->binding_handle,
2729 &state->auth_level);
2731 subreq = netlogon_creds_cli_lock_send(state, state->ev,
2733 if (tevent_req_nomem(subreq, req)) {
2734 return tevent_req_post(req, ev);
2737 tevent_req_set_callback(subreq,
2738 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked,
2744 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req *req,
2747 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
2748 tevent_req_data(req,
2749 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2751 if (state->creds == NULL) {
2755 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
2756 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
2757 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
2758 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
2759 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
2760 TALLOC_FREE(state->creds);
2764 netlogon_creds_cli_delete(state->context, state->creds);
2765 TALLOC_FREE(state->creds);
2768 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req *subreq);
2770 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req *subreq)
2772 struct tevent_req *req =
2773 tevent_req_callback_data(subreq,
2775 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
2776 tevent_req_data(req,
2777 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2780 status = netlogon_creds_cli_lock_recv(subreq, state,
2782 TALLOC_FREE(subreq);
2783 if (tevent_req_nterror(req, status)) {
2787 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
2788 switch (state->auth_level) {
2789 case DCERPC_AUTH_LEVEL_INTEGRITY:
2790 case DCERPC_AUTH_LEVEL_PRIVACY:
2793 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2797 uint32_t tmp = state->creds->negotiate_flags;
2799 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
2801 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
2802 * it should be used, which means
2803 * we had a chance to verify no downgrade
2806 * This relies on netlogon_creds_cli_check*
2807 * being called before, as first request after
2810 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2816 * we defer all callbacks in order to cleanup
2817 * the database record.
2819 tevent_req_defer_callback(req, state->ev);
2821 state->tmp_creds = *state->creds;
2822 netlogon_creds_client_authenticator(&state->tmp_creds,
2824 ZERO_STRUCT(state->rep_auth);
2826 subreq = dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_send(state, state->ev,
2827 state->binding_handle,
2828 state->srv_name_slash,
2829 state->tmp_creds.computer_name,
2835 if (tevent_req_nomem(subreq, req)) {
2836 status = NT_STATUS_NO_MEMORY;
2837 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2841 tevent_req_set_callback(subreq,
2842 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done,
2846 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req *subreq)
2848 struct tevent_req *req =
2849 tevent_req_callback_data(subreq,
2851 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
2852 tevent_req_data(req,
2853 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
2859 * We use state->dns_names as the memory context, as this is
2860 * the only in/out variable and it has been overwritten by the
2861 * out parameter from the server.
2863 * We need to preserve the return value until the caller can use it.
2865 status = dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_recv(subreq, state->dns_names,
2867 TALLOC_FREE(subreq);
2868 if (tevent_req_nterror(req, status)) {
2869 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2873 ok = netlogon_creds_client_check(&state->tmp_creds,
2874 &state->rep_auth.cred);
2876 status = NT_STATUS_ACCESS_DENIED;
2877 tevent_req_nterror(req, status);
2878 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2882 *state->creds = state->tmp_creds;
2883 status = netlogon_creds_cli_store(state->context,
2885 TALLOC_FREE(state->creds);
2887 if (tevent_req_nterror(req, status)) {
2888 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2892 if (tevent_req_nterror(req, result)) {
2893 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, result);
2897 tevent_req_done(req);
2900 NTSTATUS netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(struct tevent_req *req)
2904 if (tevent_req_is_nterror(req, &status)) {
2905 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
2906 tevent_req_received(req);
2910 tevent_req_received(req);
2911 return NT_STATUS_OK;
2914 NTSTATUS netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(
2915 struct netlogon_creds_cli_context *context,
2916 struct dcerpc_binding_handle *b,
2917 const char *site_name,
2919 struct NL_DNS_NAME_INFO_ARRAY *dns_names)
2921 TALLOC_CTX *frame = talloc_stackframe();
2922 struct tevent_context *ev;
2923 struct tevent_req *req;
2924 NTSTATUS status = NT_STATUS_NO_MEMORY;
2926 ev = samba_tevent_context_init(frame);
2930 req = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(frame, ev, context, b,
2937 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2940 status = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(req);
2946 struct netlogon_creds_cli_ServerGetTrustInfo_state {
2947 struct tevent_context *ev;
2948 struct netlogon_creds_cli_context *context;
2949 struct dcerpc_binding_handle *binding_handle;
2951 char *srv_name_slash;
2952 enum dcerpc_AuthType auth_type;
2953 enum dcerpc_AuthLevel auth_level;
2955 struct samr_Password new_owf_password;
2956 struct samr_Password old_owf_password;
2957 struct netr_TrustInfo *trust_info;
2959 struct netlogon_creds_CredentialState *creds;
2960 struct netlogon_creds_CredentialState tmp_creds;
2961 struct netr_Authenticator req_auth;
2962 struct netr_Authenticator rep_auth;
2965 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req *req,
2967 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req *subreq);
2969 struct tevent_req *netlogon_creds_cli_ServerGetTrustInfo_send(TALLOC_CTX *mem_ctx,
2970 struct tevent_context *ev,
2971 struct netlogon_creds_cli_context *context,
2972 struct dcerpc_binding_handle *b)
2974 struct tevent_req *req;
2975 struct netlogon_creds_cli_ServerGetTrustInfo_state *state;
2976 struct tevent_req *subreq;
2978 req = tevent_req_create(mem_ctx, &state,
2979 struct netlogon_creds_cli_ServerGetTrustInfo_state);
2985 state->context = context;
2986 state->binding_handle = b;
2988 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
2989 context->server.computer);
2990 if (tevent_req_nomem(state->srv_name_slash, req)) {
2991 return tevent_req_post(req, ev);
2994 dcerpc_binding_handle_auth_info(state->binding_handle,
2996 &state->auth_level);
2998 subreq = netlogon_creds_cli_lock_send(state, state->ev,
3000 if (tevent_req_nomem(subreq, req)) {
3001 return tevent_req_post(req, ev);
3004 tevent_req_set_callback(subreq,
3005 netlogon_creds_cli_ServerGetTrustInfo_locked,
3011 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req *req,
3014 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
3015 tevent_req_data(req,
3016 struct netlogon_creds_cli_ServerGetTrustInfo_state);
3018 if (state->creds == NULL) {
3022 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
3023 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
3024 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
3025 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
3026 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
3027 TALLOC_FREE(state->creds);
3031 netlogon_creds_cli_delete(state->context, state->creds);
3032 TALLOC_FREE(state->creds);
3035 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req *subreq);
3037 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req *subreq)
3039 struct tevent_req *req =
3040 tevent_req_callback_data(subreq,
3042 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
3043 tevent_req_data(req,
3044 struct netlogon_creds_cli_ServerGetTrustInfo_state);
3047 status = netlogon_creds_cli_lock_recv(subreq, state,
3049 TALLOC_FREE(subreq);
3050 if (tevent_req_nterror(req, status)) {
3054 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
3055 switch (state->auth_level) {
3056 case DCERPC_AUTH_LEVEL_PRIVACY:
3059 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3063 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3068 * we defer all callbacks in order to cleanup
3069 * the database record.
3071 tevent_req_defer_callback(req, state->ev);
3073 state->tmp_creds = *state->creds;
3074 netlogon_creds_client_authenticator(&state->tmp_creds,
3076 ZERO_STRUCT(state->rep_auth);
3078 subreq = dcerpc_netr_ServerGetTrustInfo_send(state, state->ev,
3079 state->binding_handle,
3080 state->srv_name_slash,
3081 state->tmp_creds.account_name,
3082 state->tmp_creds.secure_channel_type,
3083 state->tmp_creds.computer_name,
3086 &state->new_owf_password,
3087 &state->old_owf_password,
3088 &state->trust_info);
3089 if (tevent_req_nomem(subreq, req)) {
3090 status = NT_STATUS_NO_MEMORY;
3091 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3095 tevent_req_set_callback(subreq,
3096 netlogon_creds_cli_ServerGetTrustInfo_done,
3100 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req *subreq)
3102 struct tevent_req *req =
3103 tevent_req_callback_data(subreq,
3105 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
3106 tevent_req_data(req,
3107 struct netlogon_creds_cli_ServerGetTrustInfo_state);
3110 const struct samr_Password zero = {};
3115 * We use state->dns_names as the memory context, as this is
3116 * the only in/out variable and it has been overwritten by the
3117 * out parameter from the server.
3119 * We need to preserve the return value until the caller can use it.
3121 status = dcerpc_netr_ServerGetTrustInfo_recv(subreq, state, &result);
3122 TALLOC_FREE(subreq);
3123 if (tevent_req_nterror(req, status)) {
3124 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3128 ok = netlogon_creds_client_check(&state->tmp_creds,
3129 &state->rep_auth.cred);
3131 status = NT_STATUS_ACCESS_DENIED;
3132 tevent_req_nterror(req, status);
3133 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3137 cmp = memcmp(state->new_owf_password.hash,
3138 zero.hash, sizeof(zero.hash));
3140 netlogon_creds_des_decrypt(&state->tmp_creds,
3141 &state->new_owf_password);
3143 cmp = memcmp(state->old_owf_password.hash,
3144 zero.hash, sizeof(zero.hash));
3146 netlogon_creds_des_decrypt(&state->tmp_creds,
3147 &state->old_owf_password);
3150 *state->creds = state->tmp_creds;
3151 status = netlogon_creds_cli_store(state->context,
3153 TALLOC_FREE(state->creds);
3154 if (tevent_req_nterror(req, status)) {
3155 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3159 if (tevent_req_nterror(req, result)) {
3160 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, result);
3164 tevent_req_done(req);
3167 NTSTATUS netlogon_creds_cli_ServerGetTrustInfo_recv(struct tevent_req *req,
3168 TALLOC_CTX *mem_ctx,
3169 struct samr_Password *new_owf_password,
3170 struct samr_Password *old_owf_password,
3171 struct netr_TrustInfo **trust_info)
3173 struct netlogon_creds_cli_ServerGetTrustInfo_state *state =
3174 tevent_req_data(req,
3175 struct netlogon_creds_cli_ServerGetTrustInfo_state);
3178 if (tevent_req_is_nterror(req, &status)) {
3179 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status);
3180 tevent_req_received(req);
3184 if (new_owf_password != NULL) {
3185 *new_owf_password = state->new_owf_password;
3187 if (old_owf_password != NULL) {
3188 *old_owf_password = state->old_owf_password;
3190 if (trust_info != NULL) {
3191 *trust_info = talloc_move(mem_ctx, &state->trust_info);
3194 tevent_req_received(req);
3195 return NT_STATUS_OK;
3198 NTSTATUS netlogon_creds_cli_ServerGetTrustInfo(
3199 struct netlogon_creds_cli_context *context,
3200 struct dcerpc_binding_handle *b,
3201 TALLOC_CTX *mem_ctx,
3202 struct samr_Password *new_owf_password,
3203 struct samr_Password *old_owf_password,
3204 struct netr_TrustInfo **trust_info)
3206 TALLOC_CTX *frame = talloc_stackframe();
3207 struct tevent_context *ev;
3208 struct tevent_req *req;
3209 NTSTATUS status = NT_STATUS_NO_MEMORY;
3211 ev = samba_tevent_context_init(frame);
3215 req = netlogon_creds_cli_ServerGetTrustInfo_send(frame, ev, context, b);
3219 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3222 status = netlogon_creds_cli_ServerGetTrustInfo_recv(req,
3232 struct netlogon_creds_cli_GetForestTrustInformation_state {
3233 struct tevent_context *ev;
3234 struct netlogon_creds_cli_context *context;
3235 struct dcerpc_binding_handle *binding_handle;
3237 char *srv_name_slash;
3238 enum dcerpc_AuthType auth_type;
3239 enum dcerpc_AuthLevel auth_level;
3242 struct lsa_ForestTrustInformation *forest_trust_info;
3244 struct netlogon_creds_CredentialState *creds;
3245 struct netlogon_creds_CredentialState tmp_creds;
3246 struct netr_Authenticator req_auth;
3247 struct netr_Authenticator rep_auth;
3250 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req *req,
3252 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req *subreq);
3254 struct tevent_req *netlogon_creds_cli_GetForestTrustInformation_send(TALLOC_CTX *mem_ctx,
3255 struct tevent_context *ev,
3256 struct netlogon_creds_cli_context *context,
3257 struct dcerpc_binding_handle *b)
3259 struct tevent_req *req;
3260 struct netlogon_creds_cli_GetForestTrustInformation_state *state;
3261 struct tevent_req *subreq;
3263 req = tevent_req_create(mem_ctx, &state,
3264 struct netlogon_creds_cli_GetForestTrustInformation_state);
3270 state->context = context;
3271 state->binding_handle = b;
3273 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
3274 context->server.computer);
3275 if (tevent_req_nomem(state->srv_name_slash, req)) {
3276 return tevent_req_post(req, ev);
3281 dcerpc_binding_handle_auth_info(state->binding_handle,
3283 &state->auth_level);
3285 subreq = netlogon_creds_cli_lock_send(state, state->ev,
3287 if (tevent_req_nomem(subreq, req)) {
3288 return tevent_req_post(req, ev);
3291 tevent_req_set_callback(subreq,
3292 netlogon_creds_cli_GetForestTrustInformation_locked,
3298 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req *req,
3301 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3302 tevent_req_data(req,
3303 struct netlogon_creds_cli_GetForestTrustInformation_state);
3305 if (state->creds == NULL) {
3309 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
3310 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
3311 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
3312 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
3313 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
3314 TALLOC_FREE(state->creds);
3318 netlogon_creds_cli_delete(state->context, state->creds);
3319 TALLOC_FREE(state->creds);
3322 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req *subreq);
3324 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req *subreq)
3326 struct tevent_req *req =
3327 tevent_req_callback_data(subreq,
3329 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3330 tevent_req_data(req,
3331 struct netlogon_creds_cli_GetForestTrustInformation_state);
3334 status = netlogon_creds_cli_lock_recv(subreq, state,
3336 TALLOC_FREE(subreq);
3337 if (tevent_req_nterror(req, status)) {
3341 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
3342 switch (state->auth_level) {
3343 case DCERPC_AUTH_LEVEL_INTEGRITY:
3344 case DCERPC_AUTH_LEVEL_PRIVACY:
3347 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3351 uint32_t tmp = state->creds->negotiate_flags;
3353 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
3355 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3356 * it should be used, which means
3357 * we had a chance to verify no downgrade
3360 * This relies on netlogon_creds_cli_check*
3361 * being called before, as first request after
3364 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3370 * we defer all callbacks in order to cleanup
3371 * the database record.
3373 tevent_req_defer_callback(req, state->ev);
3375 state->tmp_creds = *state->creds;
3376 netlogon_creds_client_authenticator(&state->tmp_creds,
3378 ZERO_STRUCT(state->rep_auth);
3380 subreq = dcerpc_netr_GetForestTrustInformation_send(state, state->ev,
3381 state->binding_handle,
3382 state->srv_name_slash,
3383 state->tmp_creds.computer_name,
3387 &state->forest_trust_info);
3388 if (tevent_req_nomem(subreq, req)) {
3389 status = NT_STATUS_NO_MEMORY;
3390 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3394 tevent_req_set_callback(subreq,
3395 netlogon_creds_cli_GetForestTrustInformation_done,
3399 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req *subreq)
3401 struct tevent_req *req =
3402 tevent_req_callback_data(subreq,
3404 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3405 tevent_req_data(req,
3406 struct netlogon_creds_cli_GetForestTrustInformation_state);
3412 * We use state->dns_names as the memory context, as this is
3413 * the only in/out variable and it has been overwritten by the
3414 * out parameter from the server.
3416 * We need to preserve the return value until the caller can use it.
3418 status = dcerpc_netr_GetForestTrustInformation_recv(subreq, state, &result);
3419 TALLOC_FREE(subreq);
3420 if (tevent_req_nterror(req, status)) {
3421 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3425 ok = netlogon_creds_client_check(&state->tmp_creds,
3426 &state->rep_auth.cred);
3428 status = NT_STATUS_ACCESS_DENIED;
3429 tevent_req_nterror(req, status);
3430 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3434 *state->creds = state->tmp_creds;
3435 status = netlogon_creds_cli_store(state->context,
3437 TALLOC_FREE(state->creds);
3439 if (tevent_req_nterror(req, status)) {
3440 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3444 if (tevent_req_nterror(req, result)) {
3445 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, result);
3449 tevent_req_done(req);
3452 NTSTATUS netlogon_creds_cli_GetForestTrustInformation_recv(struct tevent_req *req,
3453 TALLOC_CTX *mem_ctx,
3454 struct lsa_ForestTrustInformation **forest_trust_info)
3456 struct netlogon_creds_cli_GetForestTrustInformation_state *state =
3457 tevent_req_data(req,
3458 struct netlogon_creds_cli_GetForestTrustInformation_state);
3461 if (tevent_req_is_nterror(req, &status)) {
3462 netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status);
3463 tevent_req_received(req);
3467 *forest_trust_info = talloc_move(mem_ctx, &state->forest_trust_info);
3469 tevent_req_received(req);
3470 return NT_STATUS_OK;
3473 NTSTATUS netlogon_creds_cli_GetForestTrustInformation(
3474 struct netlogon_creds_cli_context *context,
3475 struct dcerpc_binding_handle *b,
3476 TALLOC_CTX *mem_ctx,
3477 struct lsa_ForestTrustInformation **forest_trust_info)
3479 TALLOC_CTX *frame = talloc_stackframe();
3480 struct tevent_context *ev;
3481 struct tevent_req *req;
3482 NTSTATUS status = NT_STATUS_NO_MEMORY;
3484 ev = samba_tevent_context_init(frame);
3488 req = netlogon_creds_cli_GetForestTrustInformation_send(frame, ev, context, b);
3492 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3495 status = netlogon_creds_cli_GetForestTrustInformation_recv(req,
3503 struct netlogon_creds_cli_SendToSam_state {
3504 struct tevent_context *ev;
3505 struct netlogon_creds_cli_context *context;
3506 struct dcerpc_binding_handle *binding_handle;
3508 char *srv_name_slash;
3509 enum dcerpc_AuthType auth_type;
3510 enum dcerpc_AuthLevel auth_level;
3514 struct netlogon_creds_CredentialState *creds;
3515 struct netlogon_creds_CredentialState tmp_creds;
3516 struct netr_Authenticator req_auth;
3517 struct netr_Authenticator rep_auth;
3520 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req *req,
3522 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req *subreq);
3524 struct tevent_req *netlogon_creds_cli_SendToSam_send(TALLOC_CTX *mem_ctx,
3525 struct tevent_context *ev,
3526 struct netlogon_creds_cli_context *context,
3527 struct dcerpc_binding_handle *b,
3528 struct netr_SendToSamBase *message)
3530 struct tevent_req *req;
3531 struct netlogon_creds_cli_SendToSam_state *state;
3532 struct tevent_req *subreq;
3533 enum ndr_err_code ndr_err;
3535 req = tevent_req_create(mem_ctx, &state,
3536 struct netlogon_creds_cli_SendToSam_state);
3542 state->context = context;
3543 state->binding_handle = b;
3545 state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
3546 context->server.computer);
3547 if (tevent_req_nomem(state->srv_name_slash, req)) {
3548 return tevent_req_post(req, ev);
3551 ndr_err = ndr_push_struct_blob(&state->opaque, mem_ctx, message,
3552 (ndr_push_flags_fn_t)ndr_push_netr_SendToSamBase);
3553 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3554 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
3555 tevent_req_nterror(req, status);
3556 return tevent_req_post(req, ev);
3559 dcerpc_binding_handle_auth_info(state->binding_handle,
3561 &state->auth_level);
3563 subreq = netlogon_creds_cli_lock_send(state, state->ev,
3565 if (tevent_req_nomem(subreq, req)) {
3566 return tevent_req_post(req, ev);
3569 tevent_req_set_callback(subreq,
3570 netlogon_creds_cli_SendToSam_locked,
3576 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req *req,
3579 struct netlogon_creds_cli_SendToSam_state *state =
3580 tevent_req_data(req,
3581 struct netlogon_creds_cli_SendToSam_state);
3583 if (state->creds == NULL) {
3587 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
3588 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
3589 !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
3590 !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
3591 !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
3592 TALLOC_FREE(state->creds);
3596 netlogon_creds_cli_delete(state->context, state->creds);
3597 TALLOC_FREE(state->creds);
3600 static void netlogon_creds_cli_SendToSam_done(struct tevent_req *subreq);
3602 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req *subreq)
3604 struct tevent_req *req =
3605 tevent_req_callback_data(subreq,
3607 struct netlogon_creds_cli_SendToSam_state *state =
3608 tevent_req_data(req,
3609 struct netlogon_creds_cli_SendToSam_state);
3612 status = netlogon_creds_cli_lock_recv(subreq, state,
3614 TALLOC_FREE(subreq);
3615 if (tevent_req_nterror(req, status)) {
3619 if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
3620 switch (state->auth_level) {
3621 case DCERPC_AUTH_LEVEL_INTEGRITY:
3622 case DCERPC_AUTH_LEVEL_PRIVACY:
3625 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3629 uint32_t tmp = state->creds->negotiate_flags;
3631 if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
3633 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3634 * it should be used, which means
3635 * we had a chance to verify no downgrade
3638 * This relies on netlogon_creds_cli_check*
3639 * being called before, as first request after
3642 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3648 * we defer all callbacks in order to cleanup
3649 * the database record.
3651 tevent_req_defer_callback(req, state->ev);
3653 state->tmp_creds = *state->creds;
3654 netlogon_creds_client_authenticator(&state->tmp_creds,
3656 ZERO_STRUCT(state->rep_auth);
3658 if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
3659 netlogon_creds_aes_encrypt(&state->tmp_creds,
3661 state->opaque.length);
3663 netlogon_creds_arcfour_crypt(&state->tmp_creds,
3665 state->opaque.length);
3668 subreq = dcerpc_netr_NetrLogonSendToSam_send(state, state->ev,
3669 state->binding_handle,
3670 state->srv_name_slash,
3671 state->tmp_creds.computer_name,
3675 state->opaque.length);
3676 if (tevent_req_nomem(subreq, req)) {
3677 status = NT_STATUS_NO_MEMORY;
3678 netlogon_creds_cli_SendToSam_cleanup(req, status);
3682 tevent_req_set_callback(subreq,
3683 netlogon_creds_cli_SendToSam_done,
3687 static void netlogon_creds_cli_SendToSam_done(struct tevent_req *subreq)
3689 struct tevent_req *req =
3690 tevent_req_callback_data(subreq,
3692 struct netlogon_creds_cli_SendToSam_state *state =
3693 tevent_req_data(req,
3694 struct netlogon_creds_cli_SendToSam_state);
3699 status = dcerpc_netr_NetrLogonSendToSam_recv(subreq, state, &result);
3700 TALLOC_FREE(subreq);
3701 if (tevent_req_nterror(req, status)) {
3702 netlogon_creds_cli_SendToSam_cleanup(req, status);
3706 ok = netlogon_creds_client_check(&state->tmp_creds,
3707 &state->rep_auth.cred);
3709 status = NT_STATUS_ACCESS_DENIED;
3710 tevent_req_nterror(req, status);
3711 netlogon_creds_cli_SendToSam_cleanup(req, status);
3715 *state->creds = state->tmp_creds;
3716 status = netlogon_creds_cli_store(state->context,
3718 TALLOC_FREE(state->creds);
3720 if (tevent_req_nterror(req, status)) {
3721 netlogon_creds_cli_SendToSam_cleanup(req, status);
3726 * Creds must be stored before we send back application errors
3727 * e.g. NT_STATUS_NOT_IMPLEMENTED
3729 if (tevent_req_nterror(req, result)) {
3730 netlogon_creds_cli_SendToSam_cleanup(req, result);
3734 tevent_req_done(req);
3737 NTSTATUS netlogon_creds_cli_SendToSam(struct netlogon_creds_cli_context *context,
3738 struct dcerpc_binding_handle *b,
3739 struct netr_SendToSamBase *message)
3741 TALLOC_CTX *frame = talloc_stackframe();
3742 struct tevent_context *ev;
3743 struct tevent_req *req;
3744 NTSTATUS status = NT_STATUS_OK;
3746 ev = samba_tevent_context_init(frame);
3750 req = netlogon_creds_cli_SendToSam_send(frame, ev, context, b, message);
3754 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3758 /* Ignore the result */