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
;
74 struct netlogon_creds_cli_locked_state
{
75 struct netlogon_creds_cli_context
*context
;
77 struct netlogon_creds_CredentialState
*creds
;
80 static int netlogon_creds_cli_locked_state_destructor(
81 struct netlogon_creds_cli_locked_state
*state
)
83 struct netlogon_creds_cli_context
*context
= state
->context
;
85 if (context
== NULL
) {
89 if (context
->db
.locked_state
== state
) {
90 context
->db
.locked_state
= NULL
;
93 if (state
->is_glocked
) {
94 g_lock_unlock(context
->db
.g_ctx
,
95 context
->db
.key_name
);
101 static NTSTATUS
netlogon_creds_cli_context_common(
102 const char *client_computer
,
103 const char *client_account
,
104 enum netr_SchannelType type
,
105 enum dcerpc_AuthLevel auth_level
,
106 uint32_t proposed_flags
,
107 uint32_t required_flags
,
108 const char *server_computer
,
109 const char *server_netbios_domain
,
110 const char *server_dns_domain
,
112 struct netlogon_creds_cli_context
**_context
)
114 struct netlogon_creds_cli_context
*context
= NULL
;
115 char *_key_name
= NULL
;
116 size_t server_netbios_name_len
;
121 context
= talloc_zero(mem_ctx
, struct netlogon_creds_cli_context
);
122 if (context
== NULL
) {
123 return NT_STATUS_NO_MEMORY
;
126 context
->client
.computer
= talloc_strdup(context
, client_computer
);
127 if (context
->client
.computer
== NULL
) {
128 TALLOC_FREE(context
);
129 return NT_STATUS_NO_MEMORY
;
132 context
->client
.account
= talloc_strdup(context
, client_account
);
133 if (context
->client
.account
== NULL
) {
134 TALLOC_FREE(context
);
135 return NT_STATUS_NO_MEMORY
;
138 context
->client
.proposed_flags
= proposed_flags
;
139 context
->client
.required_flags
= required_flags
;
140 context
->client
.type
= type
;
141 context
->client
.auth_level
= auth_level
;
143 context
->server
.computer
= talloc_strdup(context
, server_computer
);
144 if (context
->server
.computer
== NULL
) {
145 TALLOC_FREE(context
);
146 return NT_STATUS_NO_MEMORY
;
149 context
->server
.netbios_domain
= talloc_strdup(context
, server_netbios_domain
);
150 if (context
->server
.netbios_domain
== NULL
) {
151 TALLOC_FREE(context
);
152 return NT_STATUS_NO_MEMORY
;
155 context
->server
.dns_domain
= talloc_strdup(context
, server_dns_domain
);
156 if (context
->server
.dns_domain
== NULL
) {
157 TALLOC_FREE(context
);
158 return NT_STATUS_NO_MEMORY
;
163 * Force the callers to provide a unique
164 * value for server_computer and use this directly.
166 * For now we have to deal with
167 * "HOSTNAME" vs. "hostname.example.com".
170 p
= strchr(server_computer
, '.');
172 server_netbios_name_len
= p
-server_computer
;
174 server_netbios_name_len
= strlen(server_computer
);
177 _key_name
= talloc_asprintf(context
, "CLI[%s/%s]/SRV[%.*s/%s]",
180 (int)server_netbios_name_len
,
182 server_netbios_domain
);
183 if (_key_name
== NULL
) {
184 TALLOC_FREE(context
);
185 return NT_STATUS_NO_MEMORY
;
188 context
->db
.key_name
= talloc_strdup_upper(context
, _key_name
);
189 TALLOC_FREE(_key_name
);
190 if (context
->db
.key_name
== NULL
) {
191 TALLOC_FREE(context
);
192 return NT_STATUS_NO_MEMORY
;
195 context
->db
.key_data
= string_term_tdb_data(context
->db
.key_name
);
201 static struct db_context
*netlogon_creds_cli_global_db
;
203 NTSTATUS
netlogon_creds_cli_set_global_db(struct db_context
**db
)
205 if (netlogon_creds_cli_global_db
!= NULL
) {
206 return NT_STATUS_INVALID_PARAMETER_MIX
;
209 netlogon_creds_cli_global_db
= talloc_move(NULL
, db
);
213 NTSTATUS
netlogon_creds_cli_open_global_db(struct loadparm_context
*lp_ctx
)
216 struct db_context
*global_db
;
218 if (netlogon_creds_cli_global_db
!= NULL
) {
222 fname
= lpcfg_private_db_path(NULL
, lp_ctx
, "netlogon_creds_cli");
224 return NT_STATUS_NO_MEMORY
;
227 global_db
= dbwrap_local_open(NULL
, lp_ctx
,
229 TDB_CLEAR_IF_FIRST
|TDB_INCOMPATIBLE_HASH
,
231 0600, DBWRAP_LOCK_ORDER_2
,
233 if (global_db
== NULL
) {
234 DEBUG(0,("netlogon_creds_cli_open_global_db: Failed to open %s - %s\n",
235 fname
, strerror(errno
)));
237 return NT_STATUS_NO_MEMORY
;
241 netlogon_creds_cli_global_db
= global_db
;
245 void netlogon_creds_cli_close_global_db(void)
247 TALLOC_FREE(netlogon_creds_cli_global_db
);
250 NTSTATUS
netlogon_creds_cli_context_global(struct loadparm_context
*lp_ctx
,
251 struct messaging_context
*msg_ctx
,
252 const char *client_account
,
253 enum netr_SchannelType type
,
254 const char *server_computer
,
255 const char *server_netbios_domain
,
256 const char *server_dns_domain
,
258 struct netlogon_creds_cli_context
**_context
)
260 TALLOC_CTX
*frame
= talloc_stackframe();
262 struct netlogon_creds_cli_context
*context
= NULL
;
263 const char *client_computer
;
264 uint32_t proposed_flags
;
265 uint32_t required_flags
= 0;
266 bool reject_md5_servers
= false;
267 bool require_strong_key
= false;
268 int require_sign_or_seal
= true;
269 bool seal_secure_channel
= true;
270 enum dcerpc_AuthLevel auth_level
= DCERPC_AUTH_LEVEL_NONE
;
271 bool neutralize_nt4_emulation
= false;
275 if (msg_ctx
== NULL
) {
277 return NT_STATUS_INVALID_PARAMETER_MIX
;
280 client_computer
= lpcfg_netbios_name(lp_ctx
);
281 if (strlen(client_computer
) > 15) {
283 return NT_STATUS_INVALID_PARAMETER_MIX
;
287 * allow overwrite per domain
288 * reject md5 servers:<netbios_domain>
290 reject_md5_servers
= lpcfg_reject_md5_servers(lp_ctx
);
291 reject_md5_servers
= lpcfg_parm_bool(lp_ctx
, NULL
,
292 "reject md5 servers",
293 server_netbios_domain
,
297 * allow overwrite per domain
298 * require strong key:<netbios_domain>
300 require_strong_key
= lpcfg_require_strong_key(lp_ctx
);
301 require_strong_key
= lpcfg_parm_bool(lp_ctx
, NULL
,
302 "require strong key",
303 server_netbios_domain
,
307 * allow overwrite per domain
308 * client schannel:<netbios_domain>
310 require_sign_or_seal
= lpcfg_client_schannel(lp_ctx
);
311 require_sign_or_seal
= lpcfg_parm_int(lp_ctx
, NULL
,
313 server_netbios_domain
,
314 require_sign_or_seal
);
317 * allow overwrite per domain
318 * winbind sealed pipes:<netbios_domain>
320 seal_secure_channel
= lpcfg_winbind_sealed_pipes(lp_ctx
);
321 seal_secure_channel
= lpcfg_parm_bool(lp_ctx
, NULL
,
322 "winbind sealed pipes",
323 server_netbios_domain
,
324 seal_secure_channel
);
327 * allow overwrite per domain
328 * neutralize nt4 emulation:<netbios_domain>
330 neutralize_nt4_emulation
= lpcfg_neutralize_nt4_emulation(lp_ctx
);
331 neutralize_nt4_emulation
= lpcfg_parm_bool(lp_ctx
, NULL
,
332 "neutralize nt4 emulation",
333 server_netbios_domain
,
334 neutralize_nt4_emulation
);
336 proposed_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
337 proposed_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
341 if (lpcfg_security(lp_ctx
) == SEC_ADS
) {
343 * AD domains should be secure
345 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
346 require_sign_or_seal
= true;
347 require_strong_key
= true;
351 case SEC_CHAN_DOMAIN
:
354 case SEC_CHAN_DNS_DOMAIN
:
356 * AD domains should be secure
358 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
359 require_sign_or_seal
= true;
360 require_strong_key
= true;
361 neutralize_nt4_emulation
= true;
365 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
366 require_sign_or_seal
= true;
367 require_strong_key
= true;
371 required_flags
|= NETLOGON_NEG_RODC_PASSTHROUGH
;
372 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
373 require_sign_or_seal
= true;
374 require_strong_key
= true;
375 neutralize_nt4_emulation
= true;
380 return NT_STATUS_INVALID_PARAMETER
;
383 if (neutralize_nt4_emulation
) {
384 proposed_flags
|= NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION
;
387 if (require_sign_or_seal
) {
388 required_flags
|= NETLOGON_NEG_ARCFOUR
;
389 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
391 proposed_flags
&= ~NETLOGON_NEG_AUTHENTICATED_RPC
;
394 if (reject_md5_servers
) {
395 required_flags
|= NETLOGON_NEG_ARCFOUR
;
396 required_flags
|= NETLOGON_NEG_PASSWORD_SET2
;
397 required_flags
|= NETLOGON_NEG_SUPPORTS_AES
;
398 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
401 if (require_strong_key
) {
402 required_flags
|= NETLOGON_NEG_ARCFOUR
;
403 required_flags
|= NETLOGON_NEG_STRONG_KEYS
;
404 required_flags
|= NETLOGON_NEG_AUTHENTICATED_RPC
;
407 proposed_flags
|= required_flags
;
409 if (seal_secure_channel
) {
410 auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
412 auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
415 status
= netlogon_creds_cli_context_common(client_computer
,
422 server_netbios_domain
,
426 if (!NT_STATUS_IS_OK(status
)) {
431 context
->db
.g_ctx
= g_lock_ctx_init(context
, msg_ctx
);
432 if (context
->db
.g_ctx
== NULL
) {
433 TALLOC_FREE(context
);
435 return NT_STATUS_NO_MEMORY
;
438 status
= netlogon_creds_cli_open_global_db(lp_ctx
);
439 if (!NT_STATUS_IS_OK(status
)) {
440 TALLOC_FREE(context
);
442 return NT_STATUS_NO_MEMORY
;
445 context
->db
.ctx
= netlogon_creds_cli_global_db
;
451 NTSTATUS
netlogon_creds_bind_cli_credentials(
452 struct netlogon_creds_cli_context
*context
, TALLOC_CTX
*mem_ctx
,
453 struct cli_credentials
**pcli_creds
)
455 struct cli_credentials
*cli_creds
;
456 struct netlogon_creds_CredentialState
*ncreds
;
459 cli_creds
= cli_credentials_init(mem_ctx
);
460 if (cli_creds
== NULL
) {
461 return NT_STATUS_NO_MEMORY
;
463 cli_credentials_set_secure_channel_type(cli_creds
,
464 context
->client
.type
);
465 cli_credentials_set_username(cli_creds
, context
->client
.account
,
467 cli_credentials_set_domain(cli_creds
, context
->server
.netbios_domain
,
469 cli_credentials_set_realm(cli_creds
, context
->server
.dns_domain
,
472 status
= netlogon_creds_cli_get(context
, cli_creds
, &ncreds
);
473 if (!NT_STATUS_IS_OK(status
)) {
474 TALLOC_FREE(cli_creds
);
477 cli_credentials_set_netlogon_creds(cli_creds
, ncreds
);
479 *pcli_creds
= cli_creds
;
483 char *netlogon_creds_cli_debug_string(
484 const struct netlogon_creds_cli_context
*context
,
487 return talloc_asprintf(mem_ctx
, "netlogon_creds_cli:%s",
488 context
->db
.key_name
);
491 enum dcerpc_AuthLevel
netlogon_creds_cli_auth_level(
492 struct netlogon_creds_cli_context
*context
)
494 return context
->client
.auth_level
;
497 struct netlogon_creds_cli_fetch_state
{
499 struct netlogon_creds_CredentialState
*creds
;
500 uint32_t required_flags
;
504 static void netlogon_creds_cli_fetch_parser(TDB_DATA key
, TDB_DATA data
,
507 struct netlogon_creds_cli_fetch_state
*state
=
508 (struct netlogon_creds_cli_fetch_state
*)private_data
;
509 enum ndr_err_code ndr_err
;
513 state
->creds
= talloc_zero(state
->mem_ctx
,
514 struct netlogon_creds_CredentialState
);
515 if (state
->creds
== NULL
) {
516 state
->status
= NT_STATUS_NO_MEMORY
;
520 blob
.data
= data
.dptr
;
521 blob
.length
= data
.dsize
;
523 ndr_err
= ndr_pull_struct_blob(&blob
, state
->creds
, state
->creds
,
524 (ndr_pull_flags_fn_t
)ndr_pull_netlogon_creds_CredentialState
);
525 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
526 TALLOC_FREE(state
->creds
);
527 state
->status
= ndr_map_error2ntstatus(ndr_err
);
531 if (DEBUGLEVEL
>= 10) {
532 NDR_PRINT_DEBUG(netlogon_creds_CredentialState
, state
->creds
);
535 tmp_flags
= state
->creds
->negotiate_flags
;
536 tmp_flags
&= state
->required_flags
;
537 if (tmp_flags
!= state
->required_flags
) {
538 TALLOC_FREE(state
->creds
);
539 state
->status
= NT_STATUS_DOWNGRADE_DETECTED
;
543 state
->status
= NT_STATUS_OK
;
546 static NTSTATUS
netlogon_creds_cli_get_internal(
547 struct netlogon_creds_cli_context
*context
,
548 TALLOC_CTX
*mem_ctx
, struct netlogon_creds_CredentialState
**pcreds
);
550 NTSTATUS
netlogon_creds_cli_get(struct netlogon_creds_cli_context
*context
,
552 struct netlogon_creds_CredentialState
**_creds
)
555 struct netlogon_creds_CredentialState
*creds
;
559 status
= netlogon_creds_cli_get_internal(context
, mem_ctx
, &creds
);
560 if (!NT_STATUS_IS_OK(status
)) {
565 * mark it as invalid for step operations.
568 creds
->seed
= (struct netr_Credential
) {{0}};
569 creds
->client
= (struct netr_Credential
) {{0}};
570 creds
->server
= (struct netr_Credential
) {{0}};
576 bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context
*context
,
577 const struct netlogon_creds_CredentialState
*creds1
)
579 TALLOC_CTX
*frame
= talloc_stackframe();
580 struct netlogon_creds_CredentialState
*creds2
;
584 enum ndr_err_code ndr_err
;
587 status
= netlogon_creds_cli_get(context
, frame
, &creds2
);
588 if (!NT_STATUS_IS_OK(status
)) {
593 ndr_err
= ndr_push_struct_blob(&blob1
, frame
, creds1
,
594 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
595 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
600 ndr_err
= ndr_push_struct_blob(&blob2
, frame
, creds2
,
601 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
602 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
607 cmp
= data_blob_cmp(&blob1
, &blob2
);
614 static NTSTATUS
netlogon_creds_cli_store_internal(
615 struct netlogon_creds_cli_context
*context
,
616 struct netlogon_creds_CredentialState
*creds
)
619 enum ndr_err_code ndr_err
;
623 if (DEBUGLEVEL
>= 10) {
624 NDR_PRINT_DEBUG(netlogon_creds_CredentialState
, creds
);
627 ndr_err
= ndr_push_struct_blob(&blob
, creds
, creds
,
628 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
629 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
630 status
= ndr_map_error2ntstatus(ndr_err
);
634 data
.dptr
= blob
.data
;
635 data
.dsize
= blob
.length
;
637 status
= dbwrap_store(context
->db
.ctx
,
638 context
->db
.key_data
,
640 TALLOC_FREE(data
.dptr
);
641 if (!NT_STATUS_IS_OK(status
)) {
648 NTSTATUS
netlogon_creds_cli_store(struct netlogon_creds_cli_context
*context
,
649 struct netlogon_creds_CredentialState
*creds
)
653 if (context
->db
.locked_state
== NULL
) {
655 * this was not the result of netlogon_creds_cli_lock*()
657 return NT_STATUS_INVALID_PAGE_PROTECTION
;
660 if (context
->db
.locked_state
->creds
!= creds
) {
662 * this was not the result of netlogon_creds_cli_lock*()
664 return NT_STATUS_INVALID_PAGE_PROTECTION
;
667 status
= netlogon_creds_cli_store_internal(context
, creds
);
671 static NTSTATUS
netlogon_creds_cli_delete_internal(
672 struct netlogon_creds_cli_context
*context
)
675 status
= dbwrap_delete(context
->db
.ctx
, context
->db
.key_data
);
679 NTSTATUS
netlogon_creds_cli_delete(struct netlogon_creds_cli_context
*context
,
680 struct netlogon_creds_CredentialState
*creds
)
684 if (context
->db
.locked_state
== NULL
) {
686 * this was not the result of netlogon_creds_cli_lock*()
688 return NT_STATUS_INVALID_PAGE_PROTECTION
;
691 if (context
->db
.locked_state
->creds
!= creds
) {
693 * this was not the result of netlogon_creds_cli_lock*()
695 return NT_STATUS_INVALID_PAGE_PROTECTION
;
698 status
= netlogon_creds_cli_delete_internal(context
);
702 struct netlogon_creds_cli_lock_state
{
703 struct netlogon_creds_cli_locked_state
*locked_state
;
704 struct netlogon_creds_CredentialState
*creds
;
707 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
);
709 struct tevent_req
*netlogon_creds_cli_lock_send(TALLOC_CTX
*mem_ctx
,
710 struct tevent_context
*ev
,
711 struct netlogon_creds_cli_context
*context
)
713 struct tevent_req
*req
;
714 struct netlogon_creds_cli_lock_state
*state
;
715 struct netlogon_creds_cli_locked_state
*locked_state
;
716 struct tevent_req
*subreq
;
718 req
= tevent_req_create(mem_ctx
, &state
,
719 struct netlogon_creds_cli_lock_state
);
724 if (context
->db
.locked_state
!= NULL
) {
725 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
726 return tevent_req_post(req
, ev
);
729 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
730 if (tevent_req_nomem(locked_state
, req
)) {
731 return tevent_req_post(req
, ev
);
733 talloc_set_destructor(locked_state
,
734 netlogon_creds_cli_locked_state_destructor
);
735 locked_state
->context
= context
;
737 context
->db
.locked_state
= locked_state
;
738 state
->locked_state
= locked_state
;
740 if (context
->db
.g_ctx
== NULL
) {
743 status
= netlogon_creds_cli_get_internal(
744 context
, state
, &state
->creds
);
745 if (tevent_req_nterror(req
, status
)) {
746 return tevent_req_post(req
, ev
);
752 subreq
= g_lock_lock_send(state
, ev
,
754 context
->db
.key_name
,
756 if (tevent_req_nomem(subreq
, req
)) {
757 return tevent_req_post(req
, ev
);
759 tevent_req_set_callback(subreq
, netlogon_creds_cli_lock_done
, req
);
764 static void netlogon_creds_cli_lock_done(struct tevent_req
*subreq
)
766 struct tevent_req
*req
=
767 tevent_req_callback_data(subreq
,
769 struct netlogon_creds_cli_lock_state
*state
=
771 struct netlogon_creds_cli_lock_state
);
774 status
= g_lock_lock_recv(subreq
);
776 if (tevent_req_nterror(req
, status
)) {
779 state
->locked_state
->is_glocked
= true;
781 status
= netlogon_creds_cli_get_internal(state
->locked_state
->context
,
782 state
, &state
->creds
);
783 if (tevent_req_nterror(req
, status
)) {
786 tevent_req_done(req
);
789 static NTSTATUS
netlogon_creds_cli_get_internal(
790 struct netlogon_creds_cli_context
*context
,
791 TALLOC_CTX
*mem_ctx
, struct netlogon_creds_CredentialState
**pcreds
)
793 struct netlogon_creds_cli_fetch_state fstate
= {
794 .status
= NT_STATUS_INTERNAL_ERROR
,
795 .required_flags
= context
->client
.required_flags
,
799 fstate
.mem_ctx
= mem_ctx
;
800 status
= dbwrap_parse_record(context
->db
.ctx
,
801 context
->db
.key_data
,
802 netlogon_creds_cli_fetch_parser
,
804 if (!NT_STATUS_IS_OK(status
)) {
807 if (!NT_STATUS_IS_OK(fstate
.status
)) {
808 return fstate
.status
;
811 if (context
->server
.cached_flags
== fstate
.creds
->negotiate_flags
) {
812 *pcreds
= fstate
.creds
;
817 * It is really important to try SamLogonEx here,
818 * because multiple processes can talk to the same
819 * domain controller, without using the credential
822 * With a normal SamLogon call, we must keep the
823 * credentials chain updated and intact between all
824 * users of the machine account (which would imply
825 * cross-node communication for every NTLM logon).
827 * The credentials chain is not per NETLOGON pipe
828 * connection, but globally on the server/client pair
831 * It's also important to use NetlogonValidationSamInfo4 (6),
832 * because it relies on the rpc transport encryption
833 * and avoids using the global netlogon schannel
834 * session key to en/decrypt secret information
835 * like the user_session_key for network logons.
837 * [MS-APDS] 3.1.5.2 NTLM Network Logon
838 * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and
839 * NETLOGON_NEG_AUTHENTICATED_RPC set together
840 * are the indication that the server supports
841 * NetlogonValidationSamInfo4 (6). And it must only
842 * be used if "SealSecureChannel" is used.
844 * The "SealSecureChannel" AUTH_TYPE_SCHANNEL/AUTH_LEVEL_PRIVACY
845 * check is done in netlogon_creds_cli_LogonSamLogon*().
848 context
->server
.cached_flags
= fstate
.creds
->negotiate_flags
;
849 context
->server
.try_validation6
= true;
850 context
->server
.try_logon_ex
= true;
851 context
->server
.try_logon_with
= true;
853 if (!(context
->server
.cached_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
854 context
->server
.try_validation6
= false;
855 context
->server
.try_logon_ex
= false;
857 if (!(context
->server
.cached_flags
& NETLOGON_NEG_CROSS_FOREST_TRUSTS
)) {
858 context
->server
.try_validation6
= false;
861 *pcreds
= fstate
.creds
;
865 NTSTATUS
netlogon_creds_cli_lock_recv(struct tevent_req
*req
,
867 struct netlogon_creds_CredentialState
**creds
)
869 struct netlogon_creds_cli_lock_state
*state
=
871 struct netlogon_creds_cli_lock_state
);
874 if (tevent_req_is_nterror(req
, &status
)) {
875 tevent_req_received(req
);
879 talloc_steal(state
->creds
, state
->locked_state
);
880 state
->locked_state
->creds
= state
->creds
;
881 *creds
= talloc_move(mem_ctx
, &state
->creds
);
882 tevent_req_received(req
);
886 NTSTATUS
netlogon_creds_cli_lock(struct netlogon_creds_cli_context
*context
,
888 struct netlogon_creds_CredentialState
**creds
)
890 TALLOC_CTX
*frame
= talloc_stackframe();
891 struct tevent_context
*ev
;
892 struct tevent_req
*req
;
893 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
895 ev
= samba_tevent_context_init(frame
);
899 req
= netlogon_creds_cli_lock_send(frame
, ev
, context
);
903 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
906 status
= netlogon_creds_cli_lock_recv(req
, mem_ctx
, creds
);
912 struct netlogon_creds_cli_auth_state
{
913 struct tevent_context
*ev
;
914 struct netlogon_creds_cli_context
*context
;
915 struct dcerpc_binding_handle
*binding_handle
;
916 uint8_t num_nt_hashes
;
917 uint8_t idx_nt_hashes
;
918 const struct samr_Password
* const *nt_hashes
;
919 const struct samr_Password
*used_nt_hash
;
920 char *srv_name_slash
;
921 uint32_t current_flags
;
922 struct netr_Credential client_challenge
;
923 struct netr_Credential server_challenge
;
924 struct netlogon_creds_CredentialState
*creds
;
925 struct netr_Credential client_credential
;
926 struct netr_Credential server_credential
;
931 struct netlogon_creds_cli_locked_state
*locked_state
;
934 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
);
935 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
);
937 struct tevent_req
*netlogon_creds_cli_auth_send(TALLOC_CTX
*mem_ctx
,
938 struct tevent_context
*ev
,
939 struct netlogon_creds_cli_context
*context
,
940 struct dcerpc_binding_handle
*b
,
941 uint8_t num_nt_hashes
,
942 const struct samr_Password
* const *nt_hashes
)
944 struct tevent_req
*req
;
945 struct netlogon_creds_cli_auth_state
*state
;
946 struct netlogon_creds_cli_locked_state
*locked_state
;
949 req
= tevent_req_create(mem_ctx
, &state
,
950 struct netlogon_creds_cli_auth_state
);
956 state
->context
= context
;
957 state
->binding_handle
= b
;
958 if (num_nt_hashes
< 1) {
959 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
960 return tevent_req_post(req
, ev
);
962 if (num_nt_hashes
> 4) {
963 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
964 return tevent_req_post(req
, ev
);
967 state
->num_nt_hashes
= num_nt_hashes
;
968 state
->idx_nt_hashes
= 0;
969 state
->nt_hashes
= nt_hashes
;
971 if (context
->db
.locked_state
!= NULL
) {
972 tevent_req_nterror(req
, NT_STATUS_LOCK_NOT_GRANTED
);
973 return tevent_req_post(req
, ev
);
976 locked_state
= talloc_zero(state
, struct netlogon_creds_cli_locked_state
);
977 if (tevent_req_nomem(locked_state
, req
)) {
978 return tevent_req_post(req
, ev
);
980 talloc_set_destructor(locked_state
,
981 netlogon_creds_cli_locked_state_destructor
);
982 locked_state
->context
= context
;
984 context
->db
.locked_state
= locked_state
;
985 state
->locked_state
= locked_state
;
987 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
988 context
->server
.computer
);
989 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
990 return tevent_req_post(req
, ev
);
993 state
->try_auth3
= true;
994 state
->try_auth2
= true;
996 if (context
->client
.required_flags
!= 0) {
997 state
->require_auth2
= true;
1000 state
->used_nt_hash
= state
->nt_hashes
[state
->idx_nt_hashes
];
1001 state
->current_flags
= context
->client
.proposed_flags
;
1003 if (context
->db
.g_ctx
!= NULL
) {
1004 struct tevent_req
*subreq
;
1006 subreq
= g_lock_lock_send(state
, ev
,
1008 context
->db
.key_name
,
1010 if (tevent_req_nomem(subreq
, req
)) {
1011 return tevent_req_post(req
, ev
);
1013 tevent_req_set_callback(subreq
,
1014 netlogon_creds_cli_auth_locked
,
1020 status
= dbwrap_purge(state
->context
->db
.ctx
,
1021 state
->context
->db
.key_data
);
1022 if (tevent_req_nterror(req
, status
)) {
1023 return tevent_req_post(req
, ev
);
1026 netlogon_creds_cli_auth_challenge_start(req
);
1027 if (!tevent_req_is_in_progress(req
)) {
1028 return tevent_req_post(req
, ev
);
1034 static void netlogon_creds_cli_auth_locked(struct tevent_req
*subreq
)
1036 struct tevent_req
*req
=
1037 tevent_req_callback_data(subreq
,
1039 struct netlogon_creds_cli_auth_state
*state
=
1040 tevent_req_data(req
,
1041 struct netlogon_creds_cli_auth_state
);
1044 status
= g_lock_lock_recv(subreq
);
1045 TALLOC_FREE(subreq
);
1046 if (tevent_req_nterror(req
, status
)) {
1049 state
->locked_state
->is_glocked
= true;
1051 status
= dbwrap_purge(state
->context
->db
.ctx
,
1052 state
->context
->db
.key_data
);
1053 if (tevent_req_nterror(req
, status
)) {
1057 netlogon_creds_cli_auth_challenge_start(req
);
1060 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
);
1062 static void netlogon_creds_cli_auth_challenge_start(struct tevent_req
*req
)
1064 struct netlogon_creds_cli_auth_state
*state
=
1065 tevent_req_data(req
,
1066 struct netlogon_creds_cli_auth_state
);
1067 struct tevent_req
*subreq
;
1069 TALLOC_FREE(state
->creds
);
1071 generate_random_buffer(state
->client_challenge
.data
,
1072 sizeof(state
->client_challenge
.data
));
1074 subreq
= dcerpc_netr_ServerReqChallenge_send(state
, state
->ev
,
1075 state
->binding_handle
,
1076 state
->srv_name_slash
,
1077 state
->context
->client
.computer
,
1078 &state
->client_challenge
,
1079 &state
->server_challenge
);
1080 if (tevent_req_nomem(subreq
, req
)) {
1083 tevent_req_set_callback(subreq
,
1084 netlogon_creds_cli_auth_challenge_done
,
1088 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
);
1090 static void netlogon_creds_cli_auth_challenge_done(struct tevent_req
*subreq
)
1092 struct tevent_req
*req
=
1093 tevent_req_callback_data(subreq
,
1095 struct netlogon_creds_cli_auth_state
*state
=
1096 tevent_req_data(req
,
1097 struct netlogon_creds_cli_auth_state
);
1101 status
= dcerpc_netr_ServerReqChallenge_recv(subreq
, state
, &result
);
1102 TALLOC_FREE(subreq
);
1103 if (tevent_req_nterror(req
, status
)) {
1106 if (tevent_req_nterror(req
, result
)) {
1110 if (!state
->try_auth3
&& !state
->try_auth2
) {
1111 state
->current_flags
= 0;
1114 /* Calculate the session key and client credentials */
1116 state
->creds
= netlogon_creds_client_init(state
,
1117 state
->context
->client
.account
,
1118 state
->context
->client
.computer
,
1119 state
->context
->client
.type
,
1120 &state
->client_challenge
,
1121 &state
->server_challenge
,
1122 state
->used_nt_hash
,
1123 &state
->client_credential
,
1124 state
->current_flags
);
1125 if (tevent_req_nomem(state
->creds
, req
)) {
1129 if (state
->try_auth3
) {
1130 subreq
= dcerpc_netr_ServerAuthenticate3_send(state
, state
->ev
,
1131 state
->binding_handle
,
1132 state
->srv_name_slash
,
1133 state
->context
->client
.account
,
1134 state
->context
->client
.type
,
1135 state
->context
->client
.computer
,
1136 &state
->client_credential
,
1137 &state
->server_credential
,
1138 &state
->creds
->negotiate_flags
,
1140 if (tevent_req_nomem(subreq
, req
)) {
1143 } else if (state
->try_auth2
) {
1146 subreq
= dcerpc_netr_ServerAuthenticate2_send(state
, state
->ev
,
1147 state
->binding_handle
,
1148 state
->srv_name_slash
,
1149 state
->context
->client
.account
,
1150 state
->context
->client
.type
,
1151 state
->context
->client
.computer
,
1152 &state
->client_credential
,
1153 &state
->server_credential
,
1154 &state
->creds
->negotiate_flags
);
1155 if (tevent_req_nomem(subreq
, req
)) {
1161 subreq
= dcerpc_netr_ServerAuthenticate_send(state
, state
->ev
,
1162 state
->binding_handle
,
1163 state
->srv_name_slash
,
1164 state
->context
->client
.account
,
1165 state
->context
->client
.type
,
1166 state
->context
->client
.computer
,
1167 &state
->client_credential
,
1168 &state
->server_credential
);
1169 if (tevent_req_nomem(subreq
, req
)) {
1173 tevent_req_set_callback(subreq
,
1174 netlogon_creds_cli_auth_srvauth_done
,
1178 static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req
*subreq
)
1180 struct tevent_req
*req
=
1181 tevent_req_callback_data(subreq
,
1183 struct netlogon_creds_cli_auth_state
*state
=
1184 tevent_req_data(req
,
1185 struct netlogon_creds_cli_auth_state
);
1189 enum ndr_err_code ndr_err
;
1194 if (state
->try_auth3
) {
1195 status
= dcerpc_netr_ServerAuthenticate3_recv(subreq
, state
,
1197 TALLOC_FREE(subreq
);
1198 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1199 state
->try_auth3
= false;
1200 netlogon_creds_cli_auth_challenge_start(req
);
1203 if (tevent_req_nterror(req
, status
)) {
1206 } else if (state
->try_auth2
) {
1207 status
= dcerpc_netr_ServerAuthenticate2_recv(subreq
, state
,
1209 TALLOC_FREE(subreq
);
1210 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1211 state
->try_auth2
= false;
1212 if (state
->require_auth2
) {
1213 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1214 tevent_req_nterror(req
, status
);
1217 netlogon_creds_cli_auth_challenge_start(req
);
1220 if (tevent_req_nterror(req
, status
)) {
1224 status
= dcerpc_netr_ServerAuthenticate_recv(subreq
, state
,
1226 TALLOC_FREE(subreq
);
1227 if (tevent_req_nterror(req
, status
)) {
1232 if (!NT_STATUS_IS_OK(result
) &&
1233 !NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
))
1235 tevent_req_nterror(req
, result
);
1239 tmp_flags
= state
->creds
->negotiate_flags
;
1240 tmp_flags
&= state
->context
->client
.required_flags
;
1241 if (tmp_flags
!= state
->context
->client
.required_flags
) {
1242 if (NT_STATUS_IS_OK(result
)) {
1243 tevent_req_nterror(req
, NT_STATUS_DOWNGRADE_DETECTED
);
1246 tevent_req_nterror(req
, result
);
1250 if (NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
)) {
1252 tmp_flags
= state
->context
->client
.proposed_flags
;
1253 if ((state
->current_flags
== tmp_flags
) &&
1254 (state
->creds
->negotiate_flags
!= tmp_flags
))
1257 * lets retry with the negotiated flags
1259 state
->current_flags
= state
->creds
->negotiate_flags
;
1260 netlogon_creds_cli_auth_challenge_start(req
);
1264 state
->idx_nt_hashes
+= 1;
1265 if (state
->idx_nt_hashes
>= state
->num_nt_hashes
) {
1267 * we already retried, giving up...
1269 tevent_req_nterror(req
, result
);
1274 * lets retry with the old nt hash.
1276 state
->used_nt_hash
= state
->nt_hashes
[state
->idx_nt_hashes
];
1277 state
->current_flags
= state
->context
->client
.proposed_flags
;
1278 netlogon_creds_cli_auth_challenge_start(req
);
1282 ok
= netlogon_creds_client_check(state
->creds
,
1283 &state
->server_credential
);
1285 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1289 ndr_err
= ndr_push_struct_blob(&blob
, state
, state
->creds
,
1290 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
1291 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1292 status
= ndr_map_error2ntstatus(ndr_err
);
1293 tevent_req_nterror(req
, status
);
1297 data
.dptr
= blob
.data
;
1298 data
.dsize
= blob
.length
;
1300 status
= dbwrap_store(state
->context
->db
.ctx
,
1301 state
->context
->db
.key_data
,
1303 TALLOC_FREE(state
->locked_state
);
1304 if (tevent_req_nterror(req
, status
)) {
1308 tevent_req_done(req
);
1311 NTSTATUS
netlogon_creds_cli_auth_recv(struct tevent_req
*req
,
1312 uint8_t *idx_nt_hashes
)
1314 struct netlogon_creds_cli_auth_state
*state
=
1315 tevent_req_data(req
,
1316 struct netlogon_creds_cli_auth_state
);
1321 if (tevent_req_is_nterror(req
, &status
)) {
1322 tevent_req_received(req
);
1326 *idx_nt_hashes
= state
->idx_nt_hashes
;
1327 tevent_req_received(req
);
1328 return NT_STATUS_OK
;
1331 NTSTATUS
netlogon_creds_cli_auth(struct netlogon_creds_cli_context
*context
,
1332 struct dcerpc_binding_handle
*b
,
1333 uint8_t num_nt_hashes
,
1334 const struct samr_Password
* const *nt_hashes
,
1335 uint8_t *idx_nt_hashes
)
1337 TALLOC_CTX
*frame
= talloc_stackframe();
1338 struct tevent_context
*ev
;
1339 struct tevent_req
*req
;
1340 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1344 ev
= samba_tevent_context_init(frame
);
1348 req
= netlogon_creds_cli_auth_send(frame
, ev
, context
, b
,
1349 num_nt_hashes
, nt_hashes
);
1353 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1356 status
= netlogon_creds_cli_auth_recv(req
, idx_nt_hashes
);
1362 struct netlogon_creds_cli_check_state
{
1363 struct tevent_context
*ev
;
1364 struct netlogon_creds_cli_context
*context
;
1365 struct dcerpc_binding_handle
*binding_handle
;
1367 char *srv_name_slash
;
1369 union netr_Capabilities caps
;
1371 struct netlogon_creds_CredentialState
*creds
;
1372 struct netlogon_creds_CredentialState tmp_creds
;
1373 struct netr_Authenticator req_auth
;
1374 struct netr_Authenticator rep_auth
;
1377 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1379 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
);
1381 struct tevent_req
*netlogon_creds_cli_check_send(TALLOC_CTX
*mem_ctx
,
1382 struct tevent_context
*ev
,
1383 struct netlogon_creds_cli_context
*context
,
1384 struct dcerpc_binding_handle
*b
)
1386 struct tevent_req
*req
;
1387 struct netlogon_creds_cli_check_state
*state
;
1388 struct tevent_req
*subreq
;
1389 enum dcerpc_AuthType auth_type
;
1390 enum dcerpc_AuthLevel auth_level
;
1392 req
= tevent_req_create(mem_ctx
, &state
,
1393 struct netlogon_creds_cli_check_state
);
1399 state
->context
= context
;
1400 state
->binding_handle
= b
;
1402 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1403 context
->server
.computer
);
1404 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1405 return tevent_req_post(req
, ev
);
1408 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1409 &auth_type
, &auth_level
);
1411 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
1412 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1413 return tevent_req_post(req
, ev
);
1416 switch (auth_level
) {
1417 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1418 case DCERPC_AUTH_LEVEL_PRIVACY
:
1421 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1422 return tevent_req_post(req
, ev
);
1425 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1427 if (tevent_req_nomem(subreq
, req
)) {
1428 return tevent_req_post(req
, ev
);
1431 tevent_req_set_callback(subreq
,
1432 netlogon_creds_cli_check_locked
,
1438 static void netlogon_creds_cli_check_cleanup(struct tevent_req
*req
,
1441 struct netlogon_creds_cli_check_state
*state
=
1442 tevent_req_data(req
,
1443 struct netlogon_creds_cli_check_state
);
1445 if (state
->creds
== NULL
) {
1449 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1450 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1451 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1452 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1453 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1454 TALLOC_FREE(state
->creds
);
1458 netlogon_creds_cli_delete(state
->context
, state
->creds
);
1459 TALLOC_FREE(state
->creds
);
1462 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
);
1464 static void netlogon_creds_cli_check_locked(struct tevent_req
*subreq
)
1466 struct tevent_req
*req
=
1467 tevent_req_callback_data(subreq
,
1469 struct netlogon_creds_cli_check_state
*state
=
1470 tevent_req_data(req
,
1471 struct netlogon_creds_cli_check_state
);
1474 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1476 TALLOC_FREE(subreq
);
1477 if (tevent_req_nterror(req
, status
)) {
1482 * we defer all callbacks in order to cleanup
1483 * the database record.
1485 tevent_req_defer_callback(req
, state
->ev
);
1487 state
->tmp_creds
= *state
->creds
;
1488 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1490 ZERO_STRUCT(state
->rep_auth
);
1492 subreq
= dcerpc_netr_LogonGetCapabilities_send(state
, state
->ev
,
1493 state
->binding_handle
,
1494 state
->srv_name_slash
,
1495 state
->context
->client
.computer
,
1500 if (tevent_req_nomem(subreq
, req
)) {
1501 status
= NT_STATUS_NO_MEMORY
;
1502 netlogon_creds_cli_check_cleanup(req
, status
);
1505 tevent_req_set_callback(subreq
,
1506 netlogon_creds_cli_check_caps
,
1510 static void netlogon_creds_cli_check_caps(struct tevent_req
*subreq
)
1512 struct tevent_req
*req
=
1513 tevent_req_callback_data(subreq
,
1515 struct netlogon_creds_cli_check_state
*state
=
1516 tevent_req_data(req
,
1517 struct netlogon_creds_cli_check_state
);
1522 status
= dcerpc_netr_LogonGetCapabilities_recv(subreq
, state
,
1524 TALLOC_FREE(subreq
);
1525 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1527 * Note that the negotiated flags are already checked
1528 * for our required flags after the ServerAuthenticate3/2 call.
1530 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1532 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1534 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1535 * already, we expect this to work!
1537 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1538 tevent_req_nterror(req
, status
);
1539 netlogon_creds_cli_check_cleanup(req
, status
);
1543 if (negotiated
& NETLOGON_NEG_STRONG_KEYS
) {
1545 * If we have negotiated NETLOGON_NEG_STRONG_KEYS
1546 * we expect this to work at least as far as the
1547 * NOT_SUPPORTED error handled below!
1549 * NT 4.0 and Old Samba servers are not
1550 * allowed without "require strong key = no"
1552 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1553 tevent_req_nterror(req
, status
);
1554 netlogon_creds_cli_check_cleanup(req
, status
);
1559 * If we not require NETLOGON_NEG_SUPPORTS_AES or
1560 * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore
1561 * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
1563 * This is needed against NT 4.0 and old Samba servers.
1565 * As we're using DCERPC_AUTH_TYPE_SCHANNEL with
1566 * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY
1567 * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
1568 * with the next request as the sequence number processing
1571 netlogon_creds_cli_check_cleanup(req
, status
);
1572 tevent_req_done(req
);
1575 if (tevent_req_nterror(req
, status
)) {
1576 netlogon_creds_cli_check_cleanup(req
, status
);
1580 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOT_IMPLEMENTED
)) {
1582 * Note that the negotiated flags are already checked
1583 * for our required flags after the ServerAuthenticate3/2 call.
1585 uint32_t negotiated
= state
->tmp_creds
.negotiate_flags
;
1587 if (negotiated
& NETLOGON_NEG_SUPPORTS_AES
) {
1589 * If we have negotiated NETLOGON_NEG_SUPPORTS_AES
1590 * already, we expect this to work!
1592 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1593 tevent_req_nterror(req
, status
);
1594 netlogon_creds_cli_check_cleanup(req
, status
);
1599 * This is ok, the server does not support
1600 * NETLOGON_NEG_SUPPORTS_AES.
1602 * netr_LogonGetCapabilities() was
1603 * netr_LogonDummyRoutine1() before
1604 * NETLOGON_NEG_SUPPORTS_AES was invented.
1606 netlogon_creds_cli_check_cleanup(req
, result
);
1607 tevent_req_done(req
);
1611 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1612 &state
->rep_auth
.cred
);
1614 status
= NT_STATUS_ACCESS_DENIED
;
1615 tevent_req_nterror(req
, status
);
1616 netlogon_creds_cli_check_cleanup(req
, status
);
1620 if (tevent_req_nterror(req
, result
)) {
1621 netlogon_creds_cli_check_cleanup(req
, result
);
1625 if (state
->caps
.server_capabilities
!= state
->tmp_creds
.negotiate_flags
) {
1626 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1627 tevent_req_nterror(req
, status
);
1628 netlogon_creds_cli_check_cleanup(req
, status
);
1633 * This is the key check that makes this check secure. If we
1634 * get OK here (rather than NOT_SUPPORTED), then the server
1635 * did support AES. If the server only proposed STRONG_KEYS
1636 * and not AES, then it should have failed with
1637 * NOT_IMPLEMENTED. We always send AES as a client, so the
1638 * server should always have returned it.
1640 if (!(state
->caps
.server_capabilities
& NETLOGON_NEG_SUPPORTS_AES
)) {
1641 status
= NT_STATUS_DOWNGRADE_DETECTED
;
1642 tevent_req_nterror(req
, status
);
1643 netlogon_creds_cli_check_cleanup(req
, status
);
1647 *state
->creds
= state
->tmp_creds
;
1648 status
= netlogon_creds_cli_store(state
->context
,
1650 TALLOC_FREE(state
->creds
);
1651 if (tevent_req_nterror(req
, status
)) {
1655 tevent_req_done(req
);
1658 NTSTATUS
netlogon_creds_cli_check_recv(struct tevent_req
*req
)
1662 if (tevent_req_is_nterror(req
, &status
)) {
1663 netlogon_creds_cli_check_cleanup(req
, status
);
1664 tevent_req_received(req
);
1668 tevent_req_received(req
);
1669 return NT_STATUS_OK
;
1672 NTSTATUS
netlogon_creds_cli_check(struct netlogon_creds_cli_context
*context
,
1673 struct dcerpc_binding_handle
*b
)
1675 TALLOC_CTX
*frame
= talloc_stackframe();
1676 struct tevent_context
*ev
;
1677 struct tevent_req
*req
;
1678 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1680 ev
= samba_tevent_context_init(frame
);
1684 req
= netlogon_creds_cli_check_send(frame
, ev
, context
, b
);
1688 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1691 status
= netlogon_creds_cli_check_recv(req
);
1697 struct netlogon_creds_cli_ServerPasswordSet_state
{
1698 struct tevent_context
*ev
;
1699 struct netlogon_creds_cli_context
*context
;
1700 struct dcerpc_binding_handle
*binding_handle
;
1701 uint32_t old_timeout
;
1703 char *srv_name_slash
;
1704 enum dcerpc_AuthType auth_type
;
1705 enum dcerpc_AuthLevel auth_level
;
1707 struct samr_CryptPassword samr_crypt_password
;
1708 struct netr_CryptPassword netr_crypt_password
;
1709 struct samr_Password samr_password
;
1711 struct netlogon_creds_CredentialState
*creds
;
1712 struct netlogon_creds_CredentialState tmp_creds
;
1713 struct netr_Authenticator req_auth
;
1714 struct netr_Authenticator rep_auth
;
1717 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1719 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
);
1721 struct tevent_req
*netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX
*mem_ctx
,
1722 struct tevent_context
*ev
,
1723 struct netlogon_creds_cli_context
*context
,
1724 struct dcerpc_binding_handle
*b
,
1725 const DATA_BLOB
*new_password
,
1726 const uint32_t *new_version
)
1728 struct tevent_req
*req
;
1729 struct netlogon_creds_cli_ServerPasswordSet_state
*state
;
1730 struct tevent_req
*subreq
;
1733 req
= tevent_req_create(mem_ctx
, &state
,
1734 struct netlogon_creds_cli_ServerPasswordSet_state
);
1740 state
->context
= context
;
1741 state
->binding_handle
= b
;
1743 if (new_password
->length
< 14) {
1744 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1745 return tevent_req_post(req
, ev
);
1749 * netr_ServerPasswordSet
1751 mdfour(state
->samr_password
.hash
, new_password
->data
, new_password
->length
);
1754 * netr_ServerPasswordSet2
1756 ok
= set_pw_in_buffer(state
->samr_crypt_password
.data
,
1759 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1760 return tevent_req_post(req
, ev
);
1763 if (new_version
!= NULL
) {
1764 struct NL_PASSWORD_VERSION version
;
1765 uint32_t len
= IVAL(state
->samr_crypt_password
.data
, 512);
1766 uint32_t ofs
= 512 - len
;
1770 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1771 return tevent_req_post(req
, ev
);
1775 version
.ReservedField
= 0;
1776 version
.PasswordVersionNumber
= *new_version
;
1777 version
.PasswordVersionPresent
=
1778 NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT
;
1780 p
= state
->samr_crypt_password
.data
+ ofs
;
1781 SIVAL(p
, 0, version
.ReservedField
);
1782 SIVAL(p
, 4, version
.PasswordVersionNumber
);
1783 SIVAL(p
, 8, version
.PasswordVersionPresent
);
1786 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
1787 context
->server
.computer
);
1788 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
1789 return tevent_req_post(req
, ev
);
1792 dcerpc_binding_handle_auth_info(state
->binding_handle
,
1794 &state
->auth_level
);
1796 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
1798 if (tevent_req_nomem(subreq
, req
)) {
1799 return tevent_req_post(req
, ev
);
1802 tevent_req_set_callback(subreq
,
1803 netlogon_creds_cli_ServerPasswordSet_locked
,
1809 static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req
*req
,
1812 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1813 tevent_req_data(req
,
1814 struct netlogon_creds_cli_ServerPasswordSet_state
);
1816 if (state
->creds
== NULL
) {
1820 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
1821 state
->old_timeout
);
1823 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
1824 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
1825 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
1826 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
1827 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1828 TALLOC_FREE(state
->creds
);
1832 netlogon_creds_cli_delete(state
->context
, state
->creds
);
1833 TALLOC_FREE(state
->creds
);
1836 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
);
1838 static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req
*subreq
)
1840 struct tevent_req
*req
=
1841 tevent_req_callback_data(subreq
,
1843 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1844 tevent_req_data(req
,
1845 struct netlogon_creds_cli_ServerPasswordSet_state
);
1848 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
1850 TALLOC_FREE(subreq
);
1851 if (tevent_req_nterror(req
, status
)) {
1855 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
1856 switch (state
->auth_level
) {
1857 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1858 case DCERPC_AUTH_LEVEL_PRIVACY
:
1861 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1865 uint32_t tmp
= state
->creds
->negotiate_flags
;
1867 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
1869 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
1870 * it should be used, which means
1871 * we had a chance to verify no downgrade
1874 * This relies on netlogon_creds_cli_check*
1875 * being called before, as first request after
1878 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
1883 state
->old_timeout
= dcerpc_binding_handle_set_timeout(
1884 state
->binding_handle
, 600000);
1887 * we defer all callbacks in order to cleanup
1888 * the database record.
1890 tevent_req_defer_callback(req
, state
->ev
);
1892 state
->tmp_creds
= *state
->creds
;
1893 netlogon_creds_client_authenticator(&state
->tmp_creds
,
1895 ZERO_STRUCT(state
->rep_auth
);
1897 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1899 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1900 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
1901 state
->samr_crypt_password
.data
,
1904 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
1905 state
->samr_crypt_password
.data
,
1909 memcpy(state
->netr_crypt_password
.data
,
1910 state
->samr_crypt_password
.data
, 512);
1911 state
->netr_crypt_password
.length
=
1912 IVAL(state
->samr_crypt_password
.data
, 512);
1914 subreq
= dcerpc_netr_ServerPasswordSet2_send(state
, state
->ev
,
1915 state
->binding_handle
,
1916 state
->srv_name_slash
,
1917 state
->tmp_creds
.account_name
,
1918 state
->tmp_creds
.secure_channel_type
,
1919 state
->tmp_creds
.computer_name
,
1922 &state
->netr_crypt_password
);
1923 if (tevent_req_nomem(subreq
, req
)) {
1924 status
= NT_STATUS_NO_MEMORY
;
1925 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1929 netlogon_creds_des_encrypt(&state
->tmp_creds
,
1930 &state
->samr_password
);
1932 subreq
= dcerpc_netr_ServerPasswordSet_send(state
, state
->ev
,
1933 state
->binding_handle
,
1934 state
->srv_name_slash
,
1935 state
->tmp_creds
.account_name
,
1936 state
->tmp_creds
.secure_channel_type
,
1937 state
->tmp_creds
.computer_name
,
1940 &state
->samr_password
);
1941 if (tevent_req_nomem(subreq
, req
)) {
1942 status
= NT_STATUS_NO_MEMORY
;
1943 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1948 tevent_req_set_callback(subreq
,
1949 netlogon_creds_cli_ServerPasswordSet_done
,
1953 static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req
*subreq
)
1955 struct tevent_req
*req
=
1956 tevent_req_callback_data(subreq
,
1958 struct netlogon_creds_cli_ServerPasswordSet_state
*state
=
1959 tevent_req_data(req
,
1960 struct netlogon_creds_cli_ServerPasswordSet_state
);
1965 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
1966 status
= dcerpc_netr_ServerPasswordSet2_recv(subreq
, state
,
1968 TALLOC_FREE(subreq
);
1969 if (tevent_req_nterror(req
, status
)) {
1970 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1974 status
= dcerpc_netr_ServerPasswordSet_recv(subreq
, state
,
1976 TALLOC_FREE(subreq
);
1977 if (tevent_req_nterror(req
, status
)) {
1978 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1983 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
1984 &state
->rep_auth
.cred
);
1986 status
= NT_STATUS_ACCESS_DENIED
;
1987 tevent_req_nterror(req
, status
);
1988 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
1992 if (tevent_req_nterror(req
, result
)) {
1993 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, result
);
1997 dcerpc_binding_handle_set_timeout(state
->binding_handle
,
1998 state
->old_timeout
);
2000 *state
->creds
= state
->tmp_creds
;
2001 status
= netlogon_creds_cli_store(state
->context
,
2003 TALLOC_FREE(state
->creds
);
2004 if (tevent_req_nterror(req
, status
)) {
2005 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2009 tevent_req_done(req
);
2012 NTSTATUS
netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req
*req
)
2016 if (tevent_req_is_nterror(req
, &status
)) {
2017 netlogon_creds_cli_ServerPasswordSet_cleanup(req
, status
);
2018 tevent_req_received(req
);
2022 tevent_req_received(req
);
2023 return NT_STATUS_OK
;
2026 NTSTATUS
netlogon_creds_cli_ServerPasswordSet(
2027 struct netlogon_creds_cli_context
*context
,
2028 struct dcerpc_binding_handle
*b
,
2029 const DATA_BLOB
*new_password
,
2030 const uint32_t *new_version
)
2032 TALLOC_CTX
*frame
= talloc_stackframe();
2033 struct tevent_context
*ev
;
2034 struct tevent_req
*req
;
2035 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2037 ev
= samba_tevent_context_init(frame
);
2041 req
= netlogon_creds_cli_ServerPasswordSet_send(frame
, ev
, context
, b
,
2047 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2050 status
= netlogon_creds_cli_ServerPasswordSet_recv(req
);
2056 struct netlogon_creds_cli_LogonSamLogon_state
{
2057 struct tevent_context
*ev
;
2058 struct netlogon_creds_cli_context
*context
;
2059 struct dcerpc_binding_handle
*binding_handle
;
2061 char *srv_name_slash
;
2063 enum netr_LogonInfoClass logon_level
;
2064 const union netr_LogonLevel
*const_logon
;
2065 union netr_LogonLevel
*logon
;
2068 uint16_t validation_level
;
2069 union netr_Validation
*validation
;
2070 uint8_t authoritative
;
2073 * do we need encryption at the application layer?
2077 bool try_validation6
;
2080 * the read only credentials before we started the operation
2081 * used for netr_LogonSamLogonEx() if required (validation_level = 3).
2083 struct netlogon_creds_CredentialState
*ro_creds
;
2086 * The (locked) credentials used for the credential chain
2087 * used for netr_LogonSamLogonWithFlags() or
2088 * netr_LogonSamLogonWith().
2090 struct netlogon_creds_CredentialState
*lk_creds
;
2093 * While we have locked the global credentials (lk_creds above)
2094 * we operate an a temporary copy, because a server
2095 * may not support netr_LogonSamLogonWithFlags() and
2096 * didn't process our netr_Authenticator, so we need to
2097 * restart from lk_creds.
2099 struct netlogon_creds_CredentialState tmp_creds
;
2100 struct netr_Authenticator req_auth
;
2101 struct netr_Authenticator rep_auth
;
2104 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
);
2105 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2108 struct tevent_req
*netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX
*mem_ctx
,
2109 struct tevent_context
*ev
,
2110 struct netlogon_creds_cli_context
*context
,
2111 struct dcerpc_binding_handle
*b
,
2112 enum netr_LogonInfoClass logon_level
,
2113 const union netr_LogonLevel
*logon
,
2116 struct tevent_req
*req
;
2117 struct netlogon_creds_cli_LogonSamLogon_state
*state
;
2119 req
= tevent_req_create(mem_ctx
, &state
,
2120 struct netlogon_creds_cli_LogonSamLogon_state
);
2126 state
->context
= context
;
2127 state
->binding_handle
= b
;
2129 state
->logon_level
= logon_level
;
2130 state
->const_logon
= logon
;
2131 state
->flags
= flags
;
2133 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2134 context
->server
.computer
);
2135 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2136 return tevent_req_post(req
, ev
);
2139 switch (logon_level
) {
2140 case NetlogonInteractiveInformation
:
2141 case NetlogonInteractiveTransitiveInformation
:
2142 case NetlogonServiceInformation
:
2143 case NetlogonServiceTransitiveInformation
:
2144 case NetlogonGenericInformation
:
2145 state
->user_encrypt
= true;
2148 case NetlogonNetworkInformation
:
2149 case NetlogonNetworkTransitiveInformation
:
2153 state
->validation
= talloc_zero(state
, union netr_Validation
);
2154 if (tevent_req_nomem(state
->validation
, req
)) {
2155 return tevent_req_post(req
, ev
);
2158 netlogon_creds_cli_LogonSamLogon_start(req
);
2159 if (!tevent_req_is_in_progress(req
)) {
2160 return tevent_req_post(req
, ev
);
2164 * we defer all callbacks in order to cleanup
2165 * the database record.
2167 tevent_req_defer_callback(req
, state
->ev
);
2171 static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req
*req
,
2174 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2175 tevent_req_data(req
,
2176 struct netlogon_creds_cli_LogonSamLogon_state
);
2178 if (state
->lk_creds
== NULL
) {
2182 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2184 * This is a hack to recover from a bug in old
2185 * Samba servers, when LogonSamLogonEx() fails:
2187 * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
2189 * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2191 * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE,
2192 * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR
2193 * If the sign/seal check fails.
2195 * In that case we need to cleanup the netlogon session.
2197 * It's the job of the caller to disconnect the current
2198 * connection, if netlogon_creds_cli_LogonSamLogon()
2199 * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
2201 if (!state
->context
->server
.try_logon_with
) {
2202 status
= NT_STATUS_NETWORK_ACCESS_DENIED
;
2206 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2207 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2208 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2209 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2210 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2211 TALLOC_FREE(state
->lk_creds
);
2215 netlogon_creds_cli_delete(state
->context
, state
->lk_creds
);
2216 TALLOC_FREE(state
->lk_creds
);
2219 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
);
2221 static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req
*req
)
2223 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2224 tevent_req_data(req
,
2225 struct netlogon_creds_cli_LogonSamLogon_state
);
2226 struct tevent_req
*subreq
;
2228 enum dcerpc_AuthType auth_type
;
2229 enum dcerpc_AuthLevel auth_level
;
2231 TALLOC_FREE(state
->ro_creds
);
2232 TALLOC_FREE(state
->logon
);
2233 ZERO_STRUCTP(state
->validation
);
2235 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2236 &auth_type
, &auth_level
);
2238 state
->try_logon_ex
= state
->context
->server
.try_logon_ex
;
2239 state
->try_validation6
= state
->context
->server
.try_validation6
;
2241 if (auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
2242 state
->try_logon_ex
= false;
2245 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
2246 state
->try_validation6
= false;
2249 if (state
->try_logon_ex
) {
2250 if (state
->try_validation6
) {
2251 state
->validation_level
= 6;
2253 state
->validation_level
= 3;
2254 state
->user_encrypt
= true;
2257 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2259 state
->const_logon
);
2260 if (tevent_req_nomem(state
->logon
, req
)) {
2261 status
= NT_STATUS_NO_MEMORY
;
2262 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2266 if (state
->user_encrypt
) {
2267 status
= netlogon_creds_cli_get(state
->context
,
2270 if (!NT_STATUS_IS_OK(status
)) {
2271 status
= NT_STATUS_ACCESS_DENIED
;
2272 tevent_req_nterror(req
, status
);
2273 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2277 netlogon_creds_encrypt_samlogon_logon(state
->ro_creds
,
2282 subreq
= dcerpc_netr_LogonSamLogonEx_send(state
, state
->ev
,
2283 state
->binding_handle
,
2284 state
->srv_name_slash
,
2285 state
->context
->client
.computer
,
2288 state
->validation_level
,
2290 &state
->authoritative
,
2292 if (tevent_req_nomem(subreq
, req
)) {
2293 status
= NT_STATUS_NO_MEMORY
;
2294 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2297 tevent_req_set_callback(subreq
,
2298 netlogon_creds_cli_LogonSamLogon_done
,
2303 if (state
->lk_creds
== NULL
) {
2304 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2306 if (tevent_req_nomem(subreq
, req
)) {
2307 status
= NT_STATUS_NO_MEMORY
;
2308 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2311 tevent_req_set_callback(subreq
,
2312 netlogon_creds_cli_LogonSamLogon_done
,
2317 state
->tmp_creds
= *state
->lk_creds
;
2318 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2320 ZERO_STRUCT(state
->rep_auth
);
2322 state
->logon
= netlogon_creds_shallow_copy_logon(state
,
2324 state
->const_logon
);
2325 if (tevent_req_nomem(state
->logon
, req
)) {
2326 status
= NT_STATUS_NO_MEMORY
;
2327 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2331 netlogon_creds_encrypt_samlogon_logon(&state
->tmp_creds
,
2335 state
->validation_level
= 3;
2337 if (state
->context
->server
.try_logon_with
) {
2338 subreq
= dcerpc_netr_LogonSamLogonWithFlags_send(state
, state
->ev
,
2339 state
->binding_handle
,
2340 state
->srv_name_slash
,
2341 state
->context
->client
.computer
,
2346 state
->validation_level
,
2348 &state
->authoritative
,
2350 if (tevent_req_nomem(subreq
, req
)) {
2351 status
= NT_STATUS_NO_MEMORY
;
2352 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2358 subreq
= dcerpc_netr_LogonSamLogon_send(state
, state
->ev
,
2359 state
->binding_handle
,
2360 state
->srv_name_slash
,
2361 state
->context
->client
.computer
,
2366 state
->validation_level
,
2368 &state
->authoritative
);
2369 if (tevent_req_nomem(subreq
, req
)) {
2370 status
= NT_STATUS_NO_MEMORY
;
2371 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2376 tevent_req_set_callback(subreq
,
2377 netlogon_creds_cli_LogonSamLogon_done
,
2381 static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req
*subreq
)
2383 struct tevent_req
*req
=
2384 tevent_req_callback_data(subreq
,
2386 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2387 tevent_req_data(req
,
2388 struct netlogon_creds_cli_LogonSamLogon_state
);
2393 if (state
->try_logon_ex
) {
2394 status
= dcerpc_netr_LogonSamLogonEx_recv(subreq
,
2397 TALLOC_FREE(subreq
);
2398 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2399 state
->context
->server
.try_validation6
= false;
2400 state
->context
->server
.try_logon_ex
= false;
2401 netlogon_creds_cli_LogonSamLogon_start(req
);
2404 if (tevent_req_nterror(req
, status
)) {
2405 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2409 if ((state
->validation_level
== 6) &&
2410 (NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_INFO_CLASS
) ||
2411 NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_PARAMETER
) ||
2412 NT_STATUS_EQUAL(result
, NT_STATUS_BUFFER_TOO_SMALL
)))
2414 state
->context
->server
.try_validation6
= false;
2415 netlogon_creds_cli_LogonSamLogon_start(req
);
2419 if (tevent_req_nterror(req
, result
)) {
2420 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2424 if (state
->ro_creds
== NULL
) {
2425 tevent_req_done(req
);
2429 ok
= netlogon_creds_cli_validate(state
->context
, state
->ro_creds
);
2432 * We got a race, lets retry with on authenticator
2435 * netlogon_creds_cli_LogonSamLogon_start()
2436 * will TALLOC_FREE(state->ro_creds);
2438 state
->try_logon_ex
= false;
2439 netlogon_creds_cli_LogonSamLogon_start(req
);
2443 netlogon_creds_decrypt_samlogon_validation(state
->ro_creds
,
2444 state
->validation_level
,
2447 tevent_req_done(req
);
2451 if (state
->lk_creds
== NULL
) {
2452 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2454 TALLOC_FREE(subreq
);
2455 if (tevent_req_nterror(req
, status
)) {
2456 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2460 netlogon_creds_cli_LogonSamLogon_start(req
);
2464 if (state
->context
->server
.try_logon_with
) {
2465 status
= dcerpc_netr_LogonSamLogonWithFlags_recv(subreq
,
2468 TALLOC_FREE(subreq
);
2469 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2470 state
->context
->server
.try_logon_with
= false;
2471 netlogon_creds_cli_LogonSamLogon_start(req
);
2474 if (tevent_req_nterror(req
, status
)) {
2475 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2479 status
= dcerpc_netr_LogonSamLogon_recv(subreq
,
2482 TALLOC_FREE(subreq
);
2483 if (tevent_req_nterror(req
, status
)) {
2484 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2489 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2490 &state
->rep_auth
.cred
);
2492 status
= NT_STATUS_ACCESS_DENIED
;
2493 tevent_req_nterror(req
, status
);
2494 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2498 *state
->lk_creds
= state
->tmp_creds
;
2499 status
= netlogon_creds_cli_store(state
->context
,
2501 TALLOC_FREE(state
->lk_creds
);
2503 if (tevent_req_nterror(req
, status
)) {
2504 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2508 if (tevent_req_nterror(req
, result
)) {
2509 netlogon_creds_cli_LogonSamLogon_cleanup(req
, result
);
2513 netlogon_creds_decrypt_samlogon_validation(&state
->tmp_creds
,
2514 state
->validation_level
,
2517 tevent_req_done(req
);
2520 NTSTATUS
netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req
*req
,
2521 TALLOC_CTX
*mem_ctx
,
2522 uint16_t *validation_level
,
2523 union netr_Validation
**validation
,
2524 uint8_t *authoritative
,
2527 struct netlogon_creds_cli_LogonSamLogon_state
*state
=
2528 tevent_req_data(req
,
2529 struct netlogon_creds_cli_LogonSamLogon_state
);
2532 /* authoritative is also returned on error */
2533 *authoritative
= state
->authoritative
;
2535 if (tevent_req_is_nterror(req
, &status
)) {
2536 netlogon_creds_cli_LogonSamLogon_cleanup(req
, status
);
2537 tevent_req_received(req
);
2541 *validation_level
= state
->validation_level
;
2542 *validation
= talloc_move(mem_ctx
, &state
->validation
);
2543 *flags
= state
->flags
;
2545 tevent_req_received(req
);
2546 return NT_STATUS_OK
;
2549 NTSTATUS
netlogon_creds_cli_LogonSamLogon(
2550 struct netlogon_creds_cli_context
*context
,
2551 struct dcerpc_binding_handle
*b
,
2552 enum netr_LogonInfoClass logon_level
,
2553 const union netr_LogonLevel
*logon
,
2554 TALLOC_CTX
*mem_ctx
,
2555 uint16_t *validation_level
,
2556 union netr_Validation
**validation
,
2557 uint8_t *authoritative
,
2560 TALLOC_CTX
*frame
= talloc_stackframe();
2561 struct tevent_context
*ev
;
2562 struct tevent_req
*req
;
2563 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2565 ev
= samba_tevent_context_init(frame
);
2569 req
= netlogon_creds_cli_LogonSamLogon_send(frame
, ev
, context
, b
,
2575 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2578 status
= netlogon_creds_cli_LogonSamLogon_recv(req
, mem_ctx
,
2588 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
{
2589 struct tevent_context
*ev
;
2590 struct netlogon_creds_cli_context
*context
;
2591 struct dcerpc_binding_handle
*binding_handle
;
2593 char *srv_name_slash
;
2594 enum dcerpc_AuthType auth_type
;
2595 enum dcerpc_AuthLevel auth_level
;
2597 const char *site_name
;
2599 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
;
2601 struct netlogon_creds_CredentialState
*creds
;
2602 struct netlogon_creds_CredentialState tmp_creds
;
2603 struct netr_Authenticator req_auth
;
2604 struct netr_Authenticator rep_auth
;
2607 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2609 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
);
2611 struct tevent_req
*netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(TALLOC_CTX
*mem_ctx
,
2612 struct tevent_context
*ev
,
2613 struct netlogon_creds_cli_context
*context
,
2614 struct dcerpc_binding_handle
*b
,
2615 const char *site_name
,
2617 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2619 struct tevent_req
*req
;
2620 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
;
2621 struct tevent_req
*subreq
;
2623 req
= tevent_req_create(mem_ctx
, &state
,
2624 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2630 state
->context
= context
;
2631 state
->binding_handle
= b
;
2633 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2634 context
->server
.computer
);
2635 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2636 return tevent_req_post(req
, ev
);
2639 state
->site_name
= site_name
;
2640 state
->dns_ttl
= dns_ttl
;
2641 state
->dns_names
= dns_names
;
2643 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2645 &state
->auth_level
);
2647 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2649 if (tevent_req_nomem(subreq
, req
)) {
2650 return tevent_req_post(req
, ev
);
2653 tevent_req_set_callback(subreq
,
2654 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked
,
2660 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req
*req
,
2663 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2664 tevent_req_data(req
,
2665 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2667 if (state
->creds
== NULL
) {
2671 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2672 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2673 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2674 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2675 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2676 TALLOC_FREE(state
->creds
);
2680 netlogon_creds_cli_delete(state
->context
, state
->creds
);
2681 TALLOC_FREE(state
->creds
);
2684 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
);
2686 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req
*subreq
)
2688 struct tevent_req
*req
=
2689 tevent_req_callback_data(subreq
,
2691 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2692 tevent_req_data(req
,
2693 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2696 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2698 TALLOC_FREE(subreq
);
2699 if (tevent_req_nterror(req
, status
)) {
2703 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
2704 switch (state
->auth_level
) {
2705 case DCERPC_AUTH_LEVEL_INTEGRITY
:
2706 case DCERPC_AUTH_LEVEL_PRIVACY
:
2709 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2713 uint32_t tmp
= state
->creds
->negotiate_flags
;
2715 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
2717 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
2718 * it should be used, which means
2719 * we had a chance to verify no downgrade
2722 * This relies on netlogon_creds_cli_check*
2723 * being called before, as first request after
2726 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2732 * we defer all callbacks in order to cleanup
2733 * the database record.
2735 tevent_req_defer_callback(req
, state
->ev
);
2737 state
->tmp_creds
= *state
->creds
;
2738 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2740 ZERO_STRUCT(state
->rep_auth
);
2742 subreq
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_send(state
, state
->ev
,
2743 state
->binding_handle
,
2744 state
->srv_name_slash
,
2745 state
->tmp_creds
.computer_name
,
2751 if (tevent_req_nomem(subreq
, req
)) {
2752 status
= NT_STATUS_NO_MEMORY
;
2753 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2757 tevent_req_set_callback(subreq
,
2758 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done
,
2762 static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req
*subreq
)
2764 struct tevent_req
*req
=
2765 tevent_req_callback_data(subreq
,
2767 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
*state
=
2768 tevent_req_data(req
,
2769 struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state
);
2775 * We use state->dns_names as the memory context, as this is
2776 * the only in/out variable and it has been overwritten by the
2777 * out parameter from the server.
2779 * We need to preserve the return value until the caller can use it.
2781 status
= dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_recv(subreq
, state
->dns_names
,
2783 TALLOC_FREE(subreq
);
2784 if (tevent_req_nterror(req
, status
)) {
2785 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2789 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
2790 &state
->rep_auth
.cred
);
2792 status
= NT_STATUS_ACCESS_DENIED
;
2793 tevent_req_nterror(req
, status
);
2794 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2798 *state
->creds
= state
->tmp_creds
;
2799 status
= netlogon_creds_cli_store(state
->context
,
2801 TALLOC_FREE(state
->creds
);
2803 if (tevent_req_nterror(req
, status
)) {
2804 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2808 if (tevent_req_nterror(req
, result
)) {
2809 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, result
);
2813 tevent_req_done(req
);
2816 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(struct tevent_req
*req
)
2820 if (tevent_req_is_nterror(req
, &status
)) {
2821 netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req
, status
);
2822 tevent_req_received(req
);
2826 tevent_req_received(req
);
2827 return NT_STATUS_OK
;
2830 NTSTATUS
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(
2831 struct netlogon_creds_cli_context
*context
,
2832 struct dcerpc_binding_handle
*b
,
2833 const char *site_name
,
2835 struct NL_DNS_NAME_INFO_ARRAY
*dns_names
)
2837 TALLOC_CTX
*frame
= talloc_stackframe();
2838 struct tevent_context
*ev
;
2839 struct tevent_req
*req
;
2840 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2842 ev
= samba_tevent_context_init(frame
);
2846 req
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(frame
, ev
, context
, b
,
2853 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2856 status
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(req
);
2862 struct netlogon_creds_cli_ServerGetTrustInfo_state
{
2863 struct tevent_context
*ev
;
2864 struct netlogon_creds_cli_context
*context
;
2865 struct dcerpc_binding_handle
*binding_handle
;
2867 char *srv_name_slash
;
2868 enum dcerpc_AuthType auth_type
;
2869 enum dcerpc_AuthLevel auth_level
;
2871 struct samr_Password new_owf_password
;
2872 struct samr_Password old_owf_password
;
2873 struct netr_TrustInfo
*trust_info
;
2875 struct netlogon_creds_CredentialState
*creds
;
2876 struct netlogon_creds_CredentialState tmp_creds
;
2877 struct netr_Authenticator req_auth
;
2878 struct netr_Authenticator rep_auth
;
2881 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
2883 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
);
2885 struct tevent_req
*netlogon_creds_cli_ServerGetTrustInfo_send(TALLOC_CTX
*mem_ctx
,
2886 struct tevent_context
*ev
,
2887 struct netlogon_creds_cli_context
*context
,
2888 struct dcerpc_binding_handle
*b
)
2890 struct tevent_req
*req
;
2891 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
;
2892 struct tevent_req
*subreq
;
2894 req
= tevent_req_create(mem_ctx
, &state
,
2895 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2901 state
->context
= context
;
2902 state
->binding_handle
= b
;
2904 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
2905 context
->server
.computer
);
2906 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
2907 return tevent_req_post(req
, ev
);
2910 dcerpc_binding_handle_auth_info(state
->binding_handle
,
2912 &state
->auth_level
);
2914 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
2916 if (tevent_req_nomem(subreq
, req
)) {
2917 return tevent_req_post(req
, ev
);
2920 tevent_req_set_callback(subreq
,
2921 netlogon_creds_cli_ServerGetTrustInfo_locked
,
2927 static void netlogon_creds_cli_ServerGetTrustInfo_cleanup(struct tevent_req
*req
,
2930 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2931 tevent_req_data(req
,
2932 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2934 if (state
->creds
== NULL
) {
2938 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
2939 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
2940 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
2941 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2942 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
2943 TALLOC_FREE(state
->creds
);
2947 netlogon_creds_cli_delete(state
->context
, state
->creds
);
2948 TALLOC_FREE(state
->creds
);
2951 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
);
2953 static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req
*subreq
)
2955 struct tevent_req
*req
=
2956 tevent_req_callback_data(subreq
,
2958 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
2959 tevent_req_data(req
,
2960 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
2963 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
2965 TALLOC_FREE(subreq
);
2966 if (tevent_req_nterror(req
, status
)) {
2970 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
2971 switch (state
->auth_level
) {
2972 case DCERPC_AUTH_LEVEL_PRIVACY
:
2975 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2979 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
2984 * we defer all callbacks in order to cleanup
2985 * the database record.
2987 tevent_req_defer_callback(req
, state
->ev
);
2989 state
->tmp_creds
= *state
->creds
;
2990 netlogon_creds_client_authenticator(&state
->tmp_creds
,
2992 ZERO_STRUCT(state
->rep_auth
);
2994 subreq
= dcerpc_netr_ServerGetTrustInfo_send(state
, state
->ev
,
2995 state
->binding_handle
,
2996 state
->srv_name_slash
,
2997 state
->tmp_creds
.account_name
,
2998 state
->tmp_creds
.secure_channel_type
,
2999 state
->tmp_creds
.computer_name
,
3002 &state
->new_owf_password
,
3003 &state
->old_owf_password
,
3004 &state
->trust_info
);
3005 if (tevent_req_nomem(subreq
, req
)) {
3006 status
= NT_STATUS_NO_MEMORY
;
3007 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3011 tevent_req_set_callback(subreq
,
3012 netlogon_creds_cli_ServerGetTrustInfo_done
,
3016 static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req
*subreq
)
3018 struct tevent_req
*req
=
3019 tevent_req_callback_data(subreq
,
3021 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3022 tevent_req_data(req
,
3023 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3026 const struct samr_Password zero
= {};
3031 * We use state->dns_names as the memory context, as this is
3032 * the only in/out variable and it has been overwritten by the
3033 * out parameter from the server.
3035 * We need to preserve the return value until the caller can use it.
3037 status
= dcerpc_netr_ServerGetTrustInfo_recv(subreq
, state
, &result
);
3038 TALLOC_FREE(subreq
);
3039 if (tevent_req_nterror(req
, status
)) {
3040 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3044 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3045 &state
->rep_auth
.cred
);
3047 status
= NT_STATUS_ACCESS_DENIED
;
3048 tevent_req_nterror(req
, status
);
3049 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3053 cmp
= memcmp(state
->new_owf_password
.hash
,
3054 zero
.hash
, sizeof(zero
.hash
));
3056 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3057 &state
->new_owf_password
);
3059 cmp
= memcmp(state
->old_owf_password
.hash
,
3060 zero
.hash
, sizeof(zero
.hash
));
3062 netlogon_creds_des_decrypt(&state
->tmp_creds
,
3063 &state
->old_owf_password
);
3066 *state
->creds
= state
->tmp_creds
;
3067 status
= netlogon_creds_cli_store(state
->context
,
3069 TALLOC_FREE(state
->creds
);
3070 if (tevent_req_nterror(req
, status
)) {
3071 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3075 if (tevent_req_nterror(req
, result
)) {
3076 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, result
);
3080 tevent_req_done(req
);
3083 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo_recv(struct tevent_req
*req
,
3084 TALLOC_CTX
*mem_ctx
,
3085 struct samr_Password
*new_owf_password
,
3086 struct samr_Password
*old_owf_password
,
3087 struct netr_TrustInfo
**trust_info
)
3089 struct netlogon_creds_cli_ServerGetTrustInfo_state
*state
=
3090 tevent_req_data(req
,
3091 struct netlogon_creds_cli_ServerGetTrustInfo_state
);
3094 if (tevent_req_is_nterror(req
, &status
)) {
3095 netlogon_creds_cli_ServerGetTrustInfo_cleanup(req
, status
);
3096 tevent_req_received(req
);
3100 if (new_owf_password
!= NULL
) {
3101 *new_owf_password
= state
->new_owf_password
;
3103 if (old_owf_password
!= NULL
) {
3104 *old_owf_password
= state
->old_owf_password
;
3106 if (trust_info
!= NULL
) {
3107 *trust_info
= talloc_move(mem_ctx
, &state
->trust_info
);
3110 tevent_req_received(req
);
3111 return NT_STATUS_OK
;
3114 NTSTATUS
netlogon_creds_cli_ServerGetTrustInfo(
3115 struct netlogon_creds_cli_context
*context
,
3116 struct dcerpc_binding_handle
*b
,
3117 TALLOC_CTX
*mem_ctx
,
3118 struct samr_Password
*new_owf_password
,
3119 struct samr_Password
*old_owf_password
,
3120 struct netr_TrustInfo
**trust_info
)
3122 TALLOC_CTX
*frame
= talloc_stackframe();
3123 struct tevent_context
*ev
;
3124 struct tevent_req
*req
;
3125 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3127 ev
= samba_tevent_context_init(frame
);
3131 req
= netlogon_creds_cli_ServerGetTrustInfo_send(frame
, ev
, context
, b
);
3135 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3138 status
= netlogon_creds_cli_ServerGetTrustInfo_recv(req
,
3148 struct netlogon_creds_cli_GetForestTrustInformation_state
{
3149 struct tevent_context
*ev
;
3150 struct netlogon_creds_cli_context
*context
;
3151 struct dcerpc_binding_handle
*binding_handle
;
3153 char *srv_name_slash
;
3154 enum dcerpc_AuthType auth_type
;
3155 enum dcerpc_AuthLevel auth_level
;
3158 struct lsa_ForestTrustInformation
*forest_trust_info
;
3160 struct netlogon_creds_CredentialState
*creds
;
3161 struct netlogon_creds_CredentialState tmp_creds
;
3162 struct netr_Authenticator req_auth
;
3163 struct netr_Authenticator rep_auth
;
3166 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3168 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
);
3170 struct tevent_req
*netlogon_creds_cli_GetForestTrustInformation_send(TALLOC_CTX
*mem_ctx
,
3171 struct tevent_context
*ev
,
3172 struct netlogon_creds_cli_context
*context
,
3173 struct dcerpc_binding_handle
*b
)
3175 struct tevent_req
*req
;
3176 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
;
3177 struct tevent_req
*subreq
;
3179 req
= tevent_req_create(mem_ctx
, &state
,
3180 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3186 state
->context
= context
;
3187 state
->binding_handle
= b
;
3189 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3190 context
->server
.computer
);
3191 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3192 return tevent_req_post(req
, ev
);
3197 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3199 &state
->auth_level
);
3201 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3203 if (tevent_req_nomem(subreq
, req
)) {
3204 return tevent_req_post(req
, ev
);
3207 tevent_req_set_callback(subreq
,
3208 netlogon_creds_cli_GetForestTrustInformation_locked
,
3214 static void netlogon_creds_cli_GetForestTrustInformation_cleanup(struct tevent_req
*req
,
3217 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3218 tevent_req_data(req
,
3219 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3221 if (state
->creds
== NULL
) {
3225 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3226 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3227 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3228 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3229 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3230 TALLOC_FREE(state
->creds
);
3234 netlogon_creds_cli_delete(state
->context
, state
->creds
);
3235 TALLOC_FREE(state
->creds
);
3238 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
);
3240 static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_req
*subreq
)
3242 struct tevent_req
*req
=
3243 tevent_req_callback_data(subreq
,
3245 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3246 tevent_req_data(req
,
3247 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3250 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3252 TALLOC_FREE(subreq
);
3253 if (tevent_req_nterror(req
, status
)) {
3257 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3258 switch (state
->auth_level
) {
3259 case DCERPC_AUTH_LEVEL_INTEGRITY
:
3260 case DCERPC_AUTH_LEVEL_PRIVACY
:
3263 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3267 uint32_t tmp
= state
->creds
->negotiate_flags
;
3269 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
3271 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3272 * it should be used, which means
3273 * we had a chance to verify no downgrade
3276 * This relies on netlogon_creds_cli_check*
3277 * being called before, as first request after
3280 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3286 * we defer all callbacks in order to cleanup
3287 * the database record.
3289 tevent_req_defer_callback(req
, state
->ev
);
3291 state
->tmp_creds
= *state
->creds
;
3292 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3294 ZERO_STRUCT(state
->rep_auth
);
3296 subreq
= dcerpc_netr_GetForestTrustInformation_send(state
, state
->ev
,
3297 state
->binding_handle
,
3298 state
->srv_name_slash
,
3299 state
->tmp_creds
.computer_name
,
3303 &state
->forest_trust_info
);
3304 if (tevent_req_nomem(subreq
, req
)) {
3305 status
= NT_STATUS_NO_MEMORY
;
3306 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3310 tevent_req_set_callback(subreq
,
3311 netlogon_creds_cli_GetForestTrustInformation_done
,
3315 static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req
*subreq
)
3317 struct tevent_req
*req
=
3318 tevent_req_callback_data(subreq
,
3320 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3321 tevent_req_data(req
,
3322 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3328 * We use state->dns_names as the memory context, as this is
3329 * the only in/out variable and it has been overwritten by the
3330 * out parameter from the server.
3332 * We need to preserve the return value until the caller can use it.
3334 status
= dcerpc_netr_GetForestTrustInformation_recv(subreq
, state
, &result
);
3335 TALLOC_FREE(subreq
);
3336 if (tevent_req_nterror(req
, status
)) {
3337 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3341 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3342 &state
->rep_auth
.cred
);
3344 status
= NT_STATUS_ACCESS_DENIED
;
3345 tevent_req_nterror(req
, status
);
3346 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3350 *state
->creds
= state
->tmp_creds
;
3351 status
= netlogon_creds_cli_store(state
->context
,
3353 TALLOC_FREE(state
->creds
);
3355 if (tevent_req_nterror(req
, status
)) {
3356 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3360 if (tevent_req_nterror(req
, result
)) {
3361 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, result
);
3365 tevent_req_done(req
);
3368 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation_recv(struct tevent_req
*req
,
3369 TALLOC_CTX
*mem_ctx
,
3370 struct lsa_ForestTrustInformation
**forest_trust_info
)
3372 struct netlogon_creds_cli_GetForestTrustInformation_state
*state
=
3373 tevent_req_data(req
,
3374 struct netlogon_creds_cli_GetForestTrustInformation_state
);
3377 if (tevent_req_is_nterror(req
, &status
)) {
3378 netlogon_creds_cli_GetForestTrustInformation_cleanup(req
, status
);
3379 tevent_req_received(req
);
3383 *forest_trust_info
= talloc_move(mem_ctx
, &state
->forest_trust_info
);
3385 tevent_req_received(req
);
3386 return NT_STATUS_OK
;
3389 NTSTATUS
netlogon_creds_cli_GetForestTrustInformation(
3390 struct netlogon_creds_cli_context
*context
,
3391 struct dcerpc_binding_handle
*b
,
3392 TALLOC_CTX
*mem_ctx
,
3393 struct lsa_ForestTrustInformation
**forest_trust_info
)
3395 TALLOC_CTX
*frame
= talloc_stackframe();
3396 struct tevent_context
*ev
;
3397 struct tevent_req
*req
;
3398 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3400 ev
= samba_tevent_context_init(frame
);
3404 req
= netlogon_creds_cli_GetForestTrustInformation_send(frame
, ev
, context
, b
);
3408 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3411 status
= netlogon_creds_cli_GetForestTrustInformation_recv(req
,
3419 struct netlogon_creds_cli_SendToSam_state
{
3420 struct tevent_context
*ev
;
3421 struct netlogon_creds_cli_context
*context
;
3422 struct dcerpc_binding_handle
*binding_handle
;
3424 char *srv_name_slash
;
3425 enum dcerpc_AuthType auth_type
;
3426 enum dcerpc_AuthLevel auth_level
;
3430 struct netlogon_creds_CredentialState
*creds
;
3431 struct netlogon_creds_CredentialState tmp_creds
;
3432 struct netr_Authenticator req_auth
;
3433 struct netr_Authenticator rep_auth
;
3436 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req
*req
,
3438 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req
*subreq
);
3440 struct tevent_req
*netlogon_creds_cli_SendToSam_send(TALLOC_CTX
*mem_ctx
,
3441 struct tevent_context
*ev
,
3442 struct netlogon_creds_cli_context
*context
,
3443 struct dcerpc_binding_handle
*b
,
3444 struct netr_SendToSamBase
*message
)
3446 struct tevent_req
*req
;
3447 struct netlogon_creds_cli_SendToSam_state
*state
;
3448 struct tevent_req
*subreq
;
3449 enum ndr_err_code ndr_err
;
3451 req
= tevent_req_create(mem_ctx
, &state
,
3452 struct netlogon_creds_cli_SendToSam_state
);
3458 state
->context
= context
;
3459 state
->binding_handle
= b
;
3461 state
->srv_name_slash
= talloc_asprintf(state
, "\\\\%s",
3462 context
->server
.computer
);
3463 if (tevent_req_nomem(state
->srv_name_slash
, req
)) {
3464 return tevent_req_post(req
, ev
);
3467 ndr_err
= ndr_push_struct_blob(&state
->opaque
, mem_ctx
, message
,
3468 (ndr_push_flags_fn_t
)ndr_push_netr_SendToSamBase
);
3469 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
3470 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
3471 tevent_req_nterror(req
, status
);
3472 return tevent_req_post(req
, ev
);
3475 dcerpc_binding_handle_auth_info(state
->binding_handle
,
3477 &state
->auth_level
);
3479 subreq
= netlogon_creds_cli_lock_send(state
, state
->ev
,
3481 if (tevent_req_nomem(subreq
, req
)) {
3482 return tevent_req_post(req
, ev
);
3485 tevent_req_set_callback(subreq
,
3486 netlogon_creds_cli_SendToSam_locked
,
3492 static void netlogon_creds_cli_SendToSam_cleanup(struct tevent_req
*req
,
3495 struct netlogon_creds_cli_SendToSam_state
*state
=
3496 tevent_req_data(req
,
3497 struct netlogon_creds_cli_SendToSam_state
);
3499 if (state
->creds
== NULL
) {
3503 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
) &&
3504 !NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) &&
3505 !NT_STATUS_EQUAL(status
, NT_STATUS_DOWNGRADE_DETECTED
) &&
3506 !NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
3507 !NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
3508 TALLOC_FREE(state
->creds
);
3512 netlogon_creds_cli_delete(state
->context
, state
->creds
);
3513 TALLOC_FREE(state
->creds
);
3516 static void netlogon_creds_cli_SendToSam_done(struct tevent_req
*subreq
);
3518 static void netlogon_creds_cli_SendToSam_locked(struct tevent_req
*subreq
)
3520 struct tevent_req
*req
=
3521 tevent_req_callback_data(subreq
,
3523 struct netlogon_creds_cli_SendToSam_state
*state
=
3524 tevent_req_data(req
,
3525 struct netlogon_creds_cli_SendToSam_state
);
3528 status
= netlogon_creds_cli_lock_recv(subreq
, state
,
3530 TALLOC_FREE(subreq
);
3531 if (tevent_req_nterror(req
, status
)) {
3535 if (state
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
3536 switch (state
->auth_level
) {
3537 case DCERPC_AUTH_LEVEL_INTEGRITY
:
3538 case DCERPC_AUTH_LEVEL_PRIVACY
:
3541 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3545 uint32_t tmp
= state
->creds
->negotiate_flags
;
3547 if (tmp
& NETLOGON_NEG_AUTHENTICATED_RPC
) {
3549 * if DCERPC_AUTH_TYPE_SCHANNEL is supported
3550 * it should be used, which means
3551 * we had a chance to verify no downgrade
3554 * This relies on netlogon_creds_cli_check*
3555 * being called before, as first request after
3558 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
3564 * we defer all callbacks in order to cleanup
3565 * the database record.
3567 tevent_req_defer_callback(req
, state
->ev
);
3569 state
->tmp_creds
= *state
->creds
;
3570 netlogon_creds_client_authenticator(&state
->tmp_creds
,
3572 ZERO_STRUCT(state
->rep_auth
);
3574 if (state
->tmp_creds
.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
3575 netlogon_creds_aes_encrypt(&state
->tmp_creds
,
3577 state
->opaque
.length
);
3579 netlogon_creds_arcfour_crypt(&state
->tmp_creds
,
3581 state
->opaque
.length
);
3584 subreq
= dcerpc_netr_NetrLogonSendToSam_send(state
, state
->ev
,
3585 state
->binding_handle
,
3586 state
->srv_name_slash
,
3587 state
->tmp_creds
.computer_name
,
3591 state
->opaque
.length
);
3592 if (tevent_req_nomem(subreq
, req
)) {
3593 status
= NT_STATUS_NO_MEMORY
;
3594 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3598 tevent_req_set_callback(subreq
,
3599 netlogon_creds_cli_SendToSam_done
,
3603 static void netlogon_creds_cli_SendToSam_done(struct tevent_req
*subreq
)
3605 struct tevent_req
*req
=
3606 tevent_req_callback_data(subreq
,
3608 struct netlogon_creds_cli_SendToSam_state
*state
=
3609 tevent_req_data(req
,
3610 struct netlogon_creds_cli_SendToSam_state
);
3615 status
= dcerpc_netr_NetrLogonSendToSam_recv(subreq
, state
, &result
);
3616 TALLOC_FREE(subreq
);
3617 if (tevent_req_nterror(req
, status
)) {
3618 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3622 ok
= netlogon_creds_client_check(&state
->tmp_creds
,
3623 &state
->rep_auth
.cred
);
3625 status
= NT_STATUS_ACCESS_DENIED
;
3626 tevent_req_nterror(req
, status
);
3627 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3631 *state
->creds
= state
->tmp_creds
;
3632 status
= netlogon_creds_cli_store(state
->context
,
3634 TALLOC_FREE(state
->creds
);
3636 if (tevent_req_nterror(req
, status
)) {
3637 netlogon_creds_cli_SendToSam_cleanup(req
, status
);
3642 * Creds must be stored before we send back application errors
3643 * e.g. NT_STATUS_NOT_IMPLEMENTED
3645 if (tevent_req_nterror(req
, result
)) {
3646 netlogon_creds_cli_SendToSam_cleanup(req
, result
);
3650 tevent_req_done(req
);
3653 NTSTATUS
netlogon_creds_cli_SendToSam(struct netlogon_creds_cli_context
*context
,
3654 struct dcerpc_binding_handle
*b
,
3655 struct netr_SendToSamBase
*message
)
3657 TALLOC_CTX
*frame
= talloc_stackframe();
3658 struct tevent_context
*ev
;
3659 struct tevent_req
*req
;
3660 NTSTATUS status
= NT_STATUS_OK
;
3662 ev
= samba_tevent_context_init(frame
);
3666 req
= netlogon_creds_cli_SendToSam_send(frame
, ev
, context
, b
, message
);
3670 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3674 /* Ignore the result */