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 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
2324 state
->try_logon_ex
= false;
2327 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
2328 state
->try_validation6
= false;
2331 if (state
->try_logon_ex
) {
2332 if (state
->try_validation6
) {
2333 state
->validation_level
= 6;
2335 state
->validation_level
= 3;
2336 state
->user_encrypt
= true;
2339 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2341 state
->const_logon
);
2342 if (tevent_req_nomem(state
->logon
, req
)) {
2343 status
= NT_STATUS_NO_MEMORY
;
2344 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2348 if (state
->user_encrypt
) {
2349 status
= netlogon_creds_cli_get(state
->context
,
2352 if (!NT_STATUS_IS_OK(status
)) {
2353 status
= NT_STATUS_ACCESS_DENIED
;
2354 tevent_req_nterror(req
, status
);
2355 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2359 netlogon_creds_encrypt_samlogon_logon(state
->ro_creds
,
2364 subreq
= dcerpc_netr_LogonSamLogonEx_send(state
, state
->ev
,
2365 state
->binding_handle
,
2366 state
->srv_name_slash
,
2367 state
->context
->client
.computer
,
2370 state
->validation_level
,
2372 &state
->authoritative
,
2374 if (tevent_req_nomem(subreq
, req
)) {
2375 status
= NT_STATUS_NO_MEMORY
;
2376 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2379 tevent_req_set_callback(subreq
,
2380 netlogon_creds_cli_LogonSamLogon_done
,
2385 if (state
->lk_creds
== NULL
) {
2386 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2388 if (tevent_req_nomem(subreq
, req
)) {
2389 status
= NT_STATUS_NO_MEMORY
;
2390 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2393 tevent_req_set_callback(subreq
,
2394 netlogon_creds_cli_LogonSamLogon_done
,
2399 state
->tmp_creds
= *state
->lk_creds
;
2400 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2402 ZERO_STRUCT(state
->rep_auth
);
2404 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2406 state
->const_logon
);
2407 if (tevent_req_nomem(state
->logon
, req
)) {
2408 status
= NT_STATUS_NO_MEMORY
;
2409 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2413 netlogon_creds_encrypt_samlogon_logon(&state
->tmp_creds
,
2417 state
->validation_level
= 3;
2419 if (state
->context
->server
.try_logon_with
) {
2420 subreq
= dcerpc_netr_LogonSamLogonWithFlags_send(state
, state
->ev
,
2421 state
->binding_handle
,
2422 state
->srv_name_slash
,
2423 state
->context
->client
.computer
,
2428 state
->validation_level
,
2430 &state
->authoritative
,
2432 if (tevent_req_nomem(subreq
, req
)) {
2433 status
= NT_STATUS_NO_MEMORY
;
2434 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2440 subreq
= dcerpc_netr_LogonSamLogon_send(state
, state
->ev
,
2441 state
->binding_handle
,
2442 state
->srv_name_slash
,
2443 state
->context
->client
.computer
,
2448 state
->validation_level
,
2450 &state
->authoritative
);
2451 if (tevent_req_nomem(subreq
, req
)) {
2452 status
= NT_STATUS_NO_MEMORY
;
2453 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2458 tevent_req_set_callback(subreq
,
2459 netlogon_creds_cli_LogonSamLogon_done
,
2463 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
)
2465 struct tevent_req
*req
=
2466 tevent_req_callback_data(subreq
,
2468 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2469 tevent_req_data(req
,
2470 struct netlogon_creds_cli_LogonSamLogon_state
);
2475 if (state
->try_logon_ex
) {
2476 status
= dcerpc_netr_LogonSamLogonEx_recv(subreq
,
2479 TALLOC_FREE(subreq
);
2480 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2481 state
->context
->server
.try_validation6
= false;
2482 state
->context
->server
.try_logon_ex
= false;
2483 netlogon_creds_cli_LogonSamLogon_start(req
);
2486 if (tevent_req_nterror(req
, status
)) {
2487 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2491 if ((state
->validation_level
== 6) &&
2492 (NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_INFO_CLASS
) ||
2493 NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_PARAMETER
) ||
2494 NT_STATUS_EQUAL(result
, NT_STATUS_BUFFER_TOO_SMALL
)))
2496 state
->context
->server
.try_validation6
= false;
2497 netlogon_creds_cli_LogonSamLogon_start(req
);
2501 if (tevent_req_nterror(req
, result
)) {
2502 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2506 if (state
->ro_creds
== NULL
) {
2507 tevent_req_done(req
);
2511 ok
= netlogon_creds_cli_validate(state
->context
, state
->ro_creds
);
2514 * We got a race, lets retry with on authenticator
2517 * netlogon_creds_cli_LogonSamLogon_start()
2518 * will TALLOC_FREE(state->ro_creds);
2520 state
->try_logon_ex
= false;
2521 netlogon_creds_cli_LogonSamLogon_start(req
);
2525 netlogon_creds_decrypt_samlogon_validation(state
->ro_creds
,
2526 state
->validation_level
,
2529 tevent_req_done(req
);
2533 if (state
->lk_creds
== NULL
) {
2534 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2536 TALLOC_FREE(subreq
);
2537 if (tevent_req_nterror(req
, status
)) {
2538 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2542 netlogon_creds_cli_LogonSamLogon_start(req
);
2546 if (state
->context
->server
.try_logon_with
) {
2547 status
= dcerpc_netr_LogonSamLogonWithFlags_recv(subreq
,
2550 TALLOC_FREE(subreq
);
2551 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2552 state
->context
->server
.try_logon_with
= false;
2553 netlogon_creds_cli_LogonSamLogon_start(req
);
2556 if (tevent_req_nterror(req
, status
)) {
2557 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2561 status
= dcerpc_netr_LogonSamLogon_recv(subreq
,
2564 TALLOC_FREE(subreq
);
2565 if (tevent_req_nterror(req
, status
)) {
2566 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2571 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2572 &state
->rep_auth
.cred
);
2574 status
= NT_STATUS_ACCESS_DENIED
;
2575 tevent_req_nterror(req
, status
);
2576 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2580 *state
->lk_creds
= state
->tmp_creds
;
2581 status
= netlogon_creds_cli_store(state
->context
,
2583 TALLOC_FREE(state
->lk_creds
);
2585 if (tevent_req_nterror(req
, status
)) {
2586 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2590 if (tevent_req_nterror(req
, result
)) {
2591 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2595 netlogon_creds_decrypt_samlogon_validation(&state
->tmp_creds
,
2596 state
->validation_level
,
2599 tevent_req_done(req
);
2602 NTSTATUS
netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req
*req
,
2603 TALLOC_CTX
*mem_ctx
,
2604 uint16_t *validation_level
,
2605 union netr_Validation
**validation
,
2606 uint8_t *authoritative
,
2609 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2610 tevent_req_data(req
,
2611 struct netlogon_creds_cli_LogonSamLogon_state
);
2614 /* authoritative is also returned on error */
2615 *authoritative
= state
->authoritative
;
2617 if (tevent_req_is_nterror(req
, &status
)) {
2618 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2619 tevent_req_received(req
);
2623 *validation_level
= state
->validation_level
;
2624 *validation
= talloc_move(mem_ctx
, &state
->validation
);
2625 *flags
= state
->flags
;
2627 tevent_req_received(req
);
2628 return NT_STATUS_OK
;
2631 NTSTATUS
netlogon_creds_cli_LogonSamLogon(
2632 struct netlogon_creds_cli_context
*context
,
2633 struct dcerpc_binding_handle
*b
,
2634 enum netr_LogonInfoClass logon_level
,
2635 const union netr_LogonLevel
*logon
,
2636 TALLOC_CTX
*mem_ctx
,
2637 uint16_t *validation_level
,
2638 union netr_Validation
**validation
,
2639 uint8_t *authoritative
,
2642 TALLOC_CTX
*frame
= talloc_stackframe();
2643 struct tevent_context
*ev
;
2644 struct tevent_req
*req
;
2645 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2647 ev
= samba_tevent_context_init(frame
);
2651 req
= netlogon_creds_cli_LogonSamLogon_send(frame
, ev
, context
, b
,
2657 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2660 status
= netlogon_creds_cli_LogonSamLogon_recv(req
, mem_ctx
,
2670 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
{
2671 struct tevent_context
*ev
;
2672 struct netlogon_creds_cli_context
*context
;
2673 struct dcerpc_binding_handle
*binding_handle
;
2675 char *srv_name_slash
;
2676 enum dcerpc_AuthType auth_type
;
2677 enum dcerpc_AuthLevel auth_level
;
2679 const char *site_name
;
2681 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
;
2683 struct netlogon_creds_CredentialState
*creds
;
2684 struct netlogon_creds_CredentialState tmp_creds
;
2685 struct netr_Authenticator req_auth
;
2686 struct netr_Authenticator rep_auth
;
2689 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2691 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
);
2693 struct tevent_req
*netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(TALLOC_CTX
*mem_ctx
,
2694 struct tevent_context
*ev
,
2695 struct netlogon_creds_cli_context
*context
,
2696 struct dcerpc_binding_handle
*b
,
2697 const char *site_name
,
2699 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2701 struct tevent_req
*req
;
2702 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
;
2703 struct tevent_req
*subreq
;
2705 req
= tevent_req_create(mem_ctx
, &state
,
2706 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2712 state
->context
= context
;
2713 state
->binding_handle
= b
;
2715 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2716 context
->server
.computer
);
2717 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2718 return tevent_req_post(req
, ev
);
2721 state
->site_name
= site_name
;
2722 state
->dns_ttl
= dns_ttl
;
2723 state
->dns_names
= dns_names
;
2725 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2727 &state
->auth_level
);
2729 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2731 if (tevent_req_nomem(subreq
, req
)) {
2732 return tevent_req_post(req
, ev
);
2735 tevent_req_set_callback(subreq
,
2736 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked
,
2742 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2745 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2746 tevent_req_data(req
,
2747 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2749 if (state
->creds
== NULL
) {
2753 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2754 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2755 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2756 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2757 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2758 TALLOC_FREE(state
->creds
);
2762 netlogon_creds_cli_delete(state
->context
, state
->creds
);
2763 TALLOC_FREE(state
->creds
);
2766 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
);
2768 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
)
2770 struct tevent_req
*req
=
2771 tevent_req_callback_data(subreq
,
2773 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2774 tevent_req_data(req
,
2775 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2778 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2780 TALLOC_FREE(subreq
);
2781 if (tevent_req_nterror(req
, status
)) {
2785 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
2786 switch (state
->auth_level
) {
2787 case DCERPC_AUTH_LEVEL_INTEGRITY
:
2788 case DCERPC_AUTH_LEVEL_PRIVACY
:
2791 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2795 uint32_t tmp
= state
->creds
->negotiate_flags
;
2797 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
2799 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
2800 * it should be used, which means
2801 * we had a chance to verify no downgrade
2804 * This relies on netlogon_creds_cli_check*
2805 * being called before, as first request after
2808 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2814 * we defer all callbacks in order to cleanup
2815 * the database record.
2817 tevent_req_defer_callback(req
, state
->ev
);
2819 state
->tmp_creds
= *state
->creds
;
2820 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2822 ZERO_STRUCT(state
->rep_auth
);
2824 subreq
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_send(state
, state
->ev
,
2825 state
->binding_handle
,
2826 state
->srv_name_slash
,
2827 state
->tmp_creds
.computer_name
,
2833 if (tevent_req_nomem(subreq
, req
)) {
2834 status
= NT_STATUS_NO_MEMORY
;
2835 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2839 tevent_req_set_callback(subreq
,
2840 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done
,
2844 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
)
2846 struct tevent_req
*req
=
2847 tevent_req_callback_data(subreq
,
2849 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2850 tevent_req_data(req
,
2851 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2857 * We use state->dns_names as the memory context, as this is
2858 * the only in/out variable and it has been overwritten by the
2859 * out parameter from the server.
2861 * We need to preserve the return value until the caller can use it.
2863 status
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_recv(subreq
, state
->dns_names
,
2865 TALLOC_FREE(subreq
);
2866 if (tevent_req_nterror(req
, status
)) {
2867 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2871 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2872 &state
->rep_auth
.cred
);
2874 status
= NT_STATUS_ACCESS_DENIED
;
2875 tevent_req_nterror(req
, status
);
2876 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2880 *state
->creds
= state
->tmp_creds
;
2881 status
= netlogon_creds_cli_store(state
->context
,
2883 TALLOC_FREE(state
->creds
);
2885 if (tevent_req_nterror(req
, status
)) {
2886 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2890 if (tevent_req_nterror(req
, result
)) {
2891 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, result
);
2895 tevent_req_done(req
);
2898 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(struct tevent_req
*req
)
2902 if (tevent_req_is_nterror(req
, &status
)) {
2903 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2904 tevent_req_received(req
);
2908 tevent_req_received(req
);
2909 return NT_STATUS_OK
;
2912 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(
2913 struct netlogon_creds_cli_context
*context
,
2914 struct dcerpc_binding_handle
*b
,
2915 const char *site_name
,
2917 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2919 TALLOC_CTX
*frame
= talloc_stackframe();
2920 struct tevent_context
*ev
;
2921 struct tevent_req
*req
;
2922 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2924 ev
= samba_tevent_context_init(frame
);
2928 req
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(frame
, ev
, context
, b
,
2935 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2938 status
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(req
);
2944 struct netlogon_creds_cli_ServerGetTrustInfo_state
{
2945 struct tevent_context
*ev
;
2946 struct netlogon_creds_cli_context
*context
;
2947 struct dcerpc_binding_handle
*binding_handle
;
2949 char *srv_name_slash
;
2950 enum dcerpc_AuthType auth_type
;
2951 enum dcerpc_AuthLevel auth_level
;
2953 struct samr_Password new_owf_password
;
2954 struct samr_Password old_owf_password
;
2955 struct netr_TrustInfo
*trust_info
;
2957 struct netlogon_creds_CredentialState
*creds
;
2958 struct netlogon_creds_CredentialState tmp_creds
;
2959 struct netr_Authenticator req_auth
;
2960 struct netr_Authenticator rep_auth
;
2963 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
2965 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
);
2967 struct tevent_req
*netlogon_creds_cli_ServerGetTrustInfo_send(TALLOC_CTX
*mem_ctx
,
2968 struct tevent_context
*ev
,
2969 struct netlogon_creds_cli_context
*context
,
2970 struct dcerpc_binding_handle
*b
)
2972 struct tevent_req
*req
;
2973 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
;
2974 struct tevent_req
*subreq
;
2976 req
= tevent_req_create(mem_ctx
, &state
,
2977 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2983 state
->context
= context
;
2984 state
->binding_handle
= b
;
2986 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2987 context
->server
.computer
);
2988 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2989 return tevent_req_post(req
, ev
);
2992 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2994 &state
->auth_level
);
2996 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2998 if (tevent_req_nomem(subreq
, req
)) {
2999 return tevent_req_post(req
, ev
);
3002 tevent_req_set_callback(subreq
,
3003 netlogon_creds_cli_ServerGetTrustInfo_locked
,
3009 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
3012 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3013 tevent_req_data(req
,
3014 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3016 if (state
->creds
== NULL
) {
3020 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3021 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3022 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3023 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3024 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3025 TALLOC_FREE(state
->creds
);
3029 netlogon_creds_cli_delete(state
->context
, state
->creds
);
3030 TALLOC_FREE(state
->creds
);
3033 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
);
3035 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
)
3037 struct tevent_req
*req
=
3038 tevent_req_callback_data(subreq
,
3040 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3041 tevent_req_data(req
,
3042 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3045 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3047 TALLOC_FREE(subreq
);
3048 if (tevent_req_nterror(req
, status
)) {
3052 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3053 switch (state
->auth_level
) {
3054 case DCERPC_AUTH_LEVEL_PRIVACY
:
3057 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3061 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3066 * we defer all callbacks in order to cleanup
3067 * the database record.
3069 tevent_req_defer_callback(req
, state
->ev
);
3071 state
->tmp_creds
= *state
->creds
;
3072 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3074 ZERO_STRUCT(state
->rep_auth
);
3076 subreq
= dcerpc_netr_ServerGetTrustInfo_send(state
, state
->ev
,
3077 state
->binding_handle
,
3078 state
->srv_name_slash
,
3079 state
->tmp_creds
.account_name
,
3080 state
->tmp_creds
.secure_channel_type
,
3081 state
->tmp_creds
.computer_name
,
3084 &state
->new_owf_password
,
3085 &state
->old_owf_password
,
3086 &state
->trust_info
);
3087 if (tevent_req_nomem(subreq
, req
)) {
3088 status
= NT_STATUS_NO_MEMORY
;
3089 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3093 tevent_req_set_callback(subreq
,
3094 netlogon_creds_cli_ServerGetTrustInfo_done
,
3098 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
)
3100 struct tevent_req
*req
=
3101 tevent_req_callback_data(subreq
,
3103 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3104 tevent_req_data(req
,
3105 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3108 const struct samr_Password zero
= {};
3113 * We use state->dns_names as the memory context, as this is
3114 * the only in/out variable and it has been overwritten by the
3115 * out parameter from the server.
3117 * We need to preserve the return value until the caller can use it.
3119 status
= dcerpc_netr_ServerGetTrustInfo_recv(subreq
, state
, &result
);
3120 TALLOC_FREE(subreq
);
3121 if (tevent_req_nterror(req
, status
)) {
3122 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3126 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3127 &state
->rep_auth
.cred
);
3129 status
= NT_STATUS_ACCESS_DENIED
;
3130 tevent_req_nterror(req
, status
);
3131 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3135 cmp
= memcmp(state
->new_owf_password
.hash
,
3136 zero
.hash
, sizeof(zero
.hash
));
3138 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3139 &state
->new_owf_password
);
3141 cmp
= memcmp(state
->old_owf_password
.hash
,
3142 zero
.hash
, sizeof(zero
.hash
));
3144 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3145 &state
->old_owf_password
);
3148 *state
->creds
= state
->tmp_creds
;
3149 status
= netlogon_creds_cli_store(state
->context
,
3151 TALLOC_FREE(state
->creds
);
3152 if (tevent_req_nterror(req
, status
)) {
3153 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3157 if (tevent_req_nterror(req
, result
)) {
3158 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, result
);
3162 tevent_req_done(req
);
3165 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo_recv(struct tevent_req
*req
,
3166 TALLOC_CTX
*mem_ctx
,
3167 struct samr_Password
*new_owf_password
,
3168 struct samr_Password
*old_owf_password
,
3169 struct netr_TrustInfo
**trust_info
)
3171 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3172 tevent_req_data(req
,
3173 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3176 if (tevent_req_is_nterror(req
, &status
)) {
3177 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3178 tevent_req_received(req
);
3182 if (new_owf_password
!= NULL
) {
3183 *new_owf_password
= state
->new_owf_password
;
3185 if (old_owf_password
!= NULL
) {
3186 *old_owf_password
= state
->old_owf_password
;
3188 if (trust_info
!= NULL
) {
3189 *trust_info
= talloc_move(mem_ctx
, &state
->trust_info
);
3192 tevent_req_received(req
);
3193 return NT_STATUS_OK
;
3196 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo(
3197 struct netlogon_creds_cli_context
*context
,
3198 struct dcerpc_binding_handle
*b
,
3199 TALLOC_CTX
*mem_ctx
,
3200 struct samr_Password
*new_owf_password
,
3201 struct samr_Password
*old_owf_password
,
3202 struct netr_TrustInfo
**trust_info
)
3204 TALLOC_CTX
*frame
= talloc_stackframe();
3205 struct tevent_context
*ev
;
3206 struct tevent_req
*req
;
3207 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3209 ev
= samba_tevent_context_init(frame
);
3213 req
= netlogon_creds_cli_ServerGetTrustInfo_send(frame
, ev
, context
, b
);
3217 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3220 status
= netlogon_creds_cli_ServerGetTrustInfo_recv(req
,
3230 struct netlogon_creds_cli_GetForestTrustInformation_state
{
3231 struct tevent_context
*ev
;
3232 struct netlogon_creds_cli_context
*context
;
3233 struct dcerpc_binding_handle
*binding_handle
;
3235 char *srv_name_slash
;
3236 enum dcerpc_AuthType auth_type
;
3237 enum dcerpc_AuthLevel auth_level
;
3240 struct lsa_ForestTrustInformation
*forest_trust_info
;
3242 struct netlogon_creds_CredentialState
*creds
;
3243 struct netlogon_creds_CredentialState tmp_creds
;
3244 struct netr_Authenticator req_auth
;
3245 struct netr_Authenticator rep_auth
;
3248 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3250 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
);
3252 struct tevent_req
*netlogon_creds_cli_GetForestTrustInformation_send(TALLOC_CTX
*mem_ctx
,
3253 struct tevent_context
*ev
,
3254 struct netlogon_creds_cli_context
*context
,
3255 struct dcerpc_binding_handle
*b
)
3257 struct tevent_req
*req
;
3258 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
;
3259 struct tevent_req
*subreq
;
3261 req
= tevent_req_create(mem_ctx
, &state
,
3262 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3268 state
->context
= context
;
3269 state
->binding_handle
= b
;
3271 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3272 context
->server
.computer
);
3273 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3274 return tevent_req_post(req
, ev
);
3279 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3281 &state
->auth_level
);
3283 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3285 if (tevent_req_nomem(subreq
, req
)) {
3286 return tevent_req_post(req
, ev
);
3289 tevent_req_set_callback(subreq
,
3290 netlogon_creds_cli_GetForestTrustInformation_locked
,
3296 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3299 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3300 tevent_req_data(req
,
3301 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3303 if (state
->creds
== NULL
) {
3307 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3308 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3309 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3310 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3311 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3312 TALLOC_FREE(state
->creds
);
3316 netlogon_creds_cli_delete(state
->context
, state
->creds
);
3317 TALLOC_FREE(state
->creds
);
3320 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
);
3322 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
)
3324 struct tevent_req
*req
=
3325 tevent_req_callback_data(subreq
,
3327 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3328 tevent_req_data(req
,
3329 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3332 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3334 TALLOC_FREE(subreq
);
3335 if (tevent_req_nterror(req
, status
)) {
3339 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3340 switch (state
->auth_level
) {
3341 case DCERPC_AUTH_LEVEL_INTEGRITY
:
3342 case DCERPC_AUTH_LEVEL_PRIVACY
:
3345 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3349 uint32_t tmp
= state
->creds
->negotiate_flags
;
3351 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
3353 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3354 * it should be used, which means
3355 * we had a chance to verify no downgrade
3358 * This relies on netlogon_creds_cli_check*
3359 * being called before, as first request after
3362 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3368 * we defer all callbacks in order to cleanup
3369 * the database record.
3371 tevent_req_defer_callback(req
, state
->ev
);
3373 state
->tmp_creds
= *state
->creds
;
3374 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3376 ZERO_STRUCT(state
->rep_auth
);
3378 subreq
= dcerpc_netr_GetForestTrustInformation_send(state
, state
->ev
,
3379 state
->binding_handle
,
3380 state
->srv_name_slash
,
3381 state
->tmp_creds
.computer_name
,
3385 &state
->forest_trust_info
);
3386 if (tevent_req_nomem(subreq
, req
)) {
3387 status
= NT_STATUS_NO_MEMORY
;
3388 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3392 tevent_req_set_callback(subreq
,
3393 netlogon_creds_cli_GetForestTrustInformation_done
,
3397 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
)
3399 struct tevent_req
*req
=
3400 tevent_req_callback_data(subreq
,
3402 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3403 tevent_req_data(req
,
3404 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3410 * We use state->dns_names as the memory context, as this is
3411 * the only in/out variable and it has been overwritten by the
3412 * out parameter from the server.
3414 * We need to preserve the return value until the caller can use it.
3416 status
= dcerpc_netr_GetForestTrustInformation_recv(subreq
, state
, &result
);
3417 TALLOC_FREE(subreq
);
3418 if (tevent_req_nterror(req
, status
)) {
3419 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3423 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3424 &state
->rep_auth
.cred
);
3426 status
= NT_STATUS_ACCESS_DENIED
;
3427 tevent_req_nterror(req
, status
);
3428 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3432 *state
->creds
= state
->tmp_creds
;
3433 status
= netlogon_creds_cli_store(state
->context
,
3435 TALLOC_FREE(state
->creds
);
3437 if (tevent_req_nterror(req
, status
)) {
3438 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3442 if (tevent_req_nterror(req
, result
)) {
3443 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, result
);
3447 tevent_req_done(req
);
3450 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation_recv(struct tevent_req
*req
,
3451 TALLOC_CTX
*mem_ctx
,
3452 struct lsa_ForestTrustInformation
**forest_trust_info
)
3454 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3455 tevent_req_data(req
,
3456 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3459 if (tevent_req_is_nterror(req
, &status
)) {
3460 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3461 tevent_req_received(req
);
3465 *forest_trust_info
= talloc_move(mem_ctx
, &state
->forest_trust_info
);
3467 tevent_req_received(req
);
3468 return NT_STATUS_OK
;
3471 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation(
3472 struct netlogon_creds_cli_context
*context
,
3473 struct dcerpc_binding_handle
*b
,
3474 TALLOC_CTX
*mem_ctx
,
3475 struct lsa_ForestTrustInformation
**forest_trust_info
)
3477 TALLOC_CTX
*frame
= talloc_stackframe();
3478 struct tevent_context
*ev
;
3479 struct tevent_req
*req
;
3480 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3482 ev
= samba_tevent_context_init(frame
);
3486 req
= netlogon_creds_cli_GetForestTrustInformation_send(frame
, ev
, context
, b
);
3490 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3493 status
= netlogon_creds_cli_GetForestTrustInformation_recv(req
,
3501 struct netlogon_creds_cli_SendToSam_state
{
3502 struct tevent_context
*ev
;
3503 struct netlogon_creds_cli_context
*context
;
3504 struct dcerpc_binding_handle
*binding_handle
;
3506 char *srv_name_slash
;
3507 enum dcerpc_AuthType auth_type
;
3508 enum dcerpc_AuthLevel auth_level
;
3512 struct netlogon_creds_CredentialState
*creds
;
3513 struct netlogon_creds_CredentialState tmp_creds
;
3514 struct netr_Authenticator req_auth
;
3515 struct netr_Authenticator rep_auth
;
3518 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req
*req
,
3520 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req
*subreq
);
3522 struct tevent_req
*netlogon_creds_cli_SendToSam_send(TALLOC_CTX
*mem_ctx
,
3523 struct tevent_context
*ev
,
3524 struct netlogon_creds_cli_context
*context
,
3525 struct dcerpc_binding_handle
*b
,
3526 struct netr_SendToSamBase
*message
)
3528 struct tevent_req
*req
;
3529 struct netlogon_creds_cli_SendToSam_state
*state
;
3530 struct tevent_req
*subreq
;
3531 enum ndr_err_code ndr_err
;
3533 req
= tevent_req_create(mem_ctx
, &state
,
3534 struct netlogon_creds_cli_SendToSam_state
);
3540 state
->context
= context
;
3541 state
->binding_handle
= b
;
3543 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3544 context
->server
.computer
);
3545 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3546 return tevent_req_post(req
, ev
);
3549 ndr_err
= ndr_push_struct_blob(&state
->opaque
, mem_ctx
, message
,
3550 (ndr_push_flags_fn_t
)ndr_push_netr_SendToSamBase
);
3551 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
3552 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
3553 tevent_req_nterror(req
, status
);
3554 return tevent_req_post(req
, ev
);
3557 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3559 &state
->auth_level
);
3561 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3563 if (tevent_req_nomem(subreq
, req
)) {
3564 return tevent_req_post(req
, ev
);
3567 tevent_req_set_callback(subreq
,
3568 netlogon_creds_cli_SendToSam_locked
,
3574 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req
*req
,
3577 struct netlogon_creds_cli_SendToSam_state
*state
=
3578 tevent_req_data(req
,
3579 struct netlogon_creds_cli_SendToSam_state
);
3581 if (state
->creds
== NULL
) {
3585 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3586 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3587 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3588 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3589 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3590 TALLOC_FREE(state
->creds
);
3594 netlogon_creds_cli_delete(state
->context
, state
->creds
);
3595 TALLOC_FREE(state
->creds
);
3598 static void netlogon_creds_cli_SendToSam_done(struct tevent_req
*subreq
);
3600 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req
*subreq
)
3602 struct tevent_req
*req
=
3603 tevent_req_callback_data(subreq
,
3605 struct netlogon_creds_cli_SendToSam_state
*state
=
3606 tevent_req_data(req
,
3607 struct netlogon_creds_cli_SendToSam_state
);
3610 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3612 TALLOC_FREE(subreq
);
3613 if (tevent_req_nterror(req
, status
)) {
3617 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3618 switch (state
->auth_level
) {
3619 case DCERPC_AUTH_LEVEL_INTEGRITY
:
3620 case DCERPC_AUTH_LEVEL_PRIVACY
:
3623 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3627 uint32_t tmp
= state
->creds
->negotiate_flags
;
3629 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
3631 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3632 * it should be used, which means
3633 * we had a chance to verify no downgrade
3636 * This relies on netlogon_creds_cli_check*
3637 * being called before, as first request after
3640 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3646 * we defer all callbacks in order to cleanup
3647 * the database record.
3649 tevent_req_defer_callback(req
, state
->ev
);
3651 state
->tmp_creds
= *state
->creds
;
3652 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3654 ZERO_STRUCT(state
->rep_auth
);
3656 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
3657 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
3659 state
->opaque
.length
);
3661 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
3663 state
->opaque
.length
);
3666 subreq
= dcerpc_netr_NetrLogonSendToSam_send(state
, state
->ev
,
3667 state
->binding_handle
,
3668 state
->srv_name_slash
,
3669 state
->tmp_creds
.computer_name
,
3673 state
->opaque
.length
);
3674 if (tevent_req_nomem(subreq
, req
)) {
3675 status
= NT_STATUS_NO_MEMORY
;
3676 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3680 tevent_req_set_callback(subreq
,
3681 netlogon_creds_cli_SendToSam_done
,
3685 static void netlogon_creds_cli_SendToSam_done(struct tevent_req
*subreq
)
3687 struct tevent_req
*req
=
3688 tevent_req_callback_data(subreq
,
3690 struct netlogon_creds_cli_SendToSam_state
*state
=
3691 tevent_req_data(req
,
3692 struct netlogon_creds_cli_SendToSam_state
);
3697 status
= dcerpc_netr_NetrLogonSendToSam_recv(subreq
, state
, &result
);
3698 TALLOC_FREE(subreq
);
3699 if (tevent_req_nterror(req
, status
)) {
3700 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3704 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3705 &state
->rep_auth
.cred
);
3707 status
= NT_STATUS_ACCESS_DENIED
;
3708 tevent_req_nterror(req
, status
);
3709 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3713 *state
->creds
= state
->tmp_creds
;
3714 status
= netlogon_creds_cli_store(state
->context
,
3716 TALLOC_FREE(state
->creds
);
3718 if (tevent_req_nterror(req
, status
)) {
3719 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3724 * Creds must be stored before we send back application errors
3725 * e.g. NT_STATUS_NOT_IMPLEMENTED
3727 if (tevent_req_nterror(req
, result
)) {
3728 netlogon_creds_cli_SendToSam_cleanup(req
, result
);
3732 tevent_req_done(req
);
3735 NTSTATUS
netlogon_creds_cli_SendToSam(struct netlogon_creds_cli_context
*context
,
3736 struct dcerpc_binding_handle
*b
,
3737 struct netr_SendToSamBase
*message
)
3739 TALLOC_CTX
*frame
= talloc_stackframe();
3740 struct tevent_context
*ev
;
3741 struct tevent_req
*req
;
3742 NTSTATUS status
= NT_STATUS_OK
;
3744 ev
= samba_tevent_context_init(frame
);
3748 req
= netlogon_creds_cli_SendToSam_send(frame
, ev
, context
, b
, message
);
3752 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3756 /* Ignore the result */