2 Unix SMB/CIFS implementation.
4 code to manipulate domain credentials
6 Copyright (C) Andrew Tridgell 1997-2003
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "system/time.h"
25 #include "libcli/auth/libcli_auth.h"
26 #include "../libcli/security/dom_sid.h"
27 #include "lib/util/util_str_escape.h"
29 #include "lib/crypto/gnutls_helpers.h"
30 #include <gnutls/gnutls.h>
31 #include <gnutls/crypto.h>
33 #undef netlogon_creds_des_encrypt
34 #undef netlogon_creds_des_decrypt
35 #undef netlogon_creds_arcfour_crypt
36 #undef netlogon_creds_aes_encrypt
37 #undef netlogon_creds_aes_decrypt
39 bool netlogon_creds_is_random_challenge(const struct netr_Credential
*challenge
)
42 * If none of the first 5 bytes of the client challenge is unique, the
43 * server MUST fail session-key negotiation without further processing
44 * of the following steps.
47 if (challenge
->data
[1] == challenge
->data
[0] &&
48 challenge
->data
[2] == challenge
->data
[0] &&
49 challenge
->data
[3] == challenge
->data
[0] &&
50 challenge
->data
[4] == challenge
->data
[0])
58 void netlogon_creds_random_challenge(struct netr_Credential
*challenge
)
60 ZERO_STRUCTP(challenge
);
61 while (!netlogon_creds_is_random_challenge(challenge
)) {
62 generate_random_buffer(challenge
->data
, sizeof(challenge
->data
));
66 static NTSTATUS
netlogon_creds_step_crypt(struct netlogon_creds_CredentialState
*creds
,
67 const struct netr_Credential
*in
,
68 struct netr_Credential
*out
)
73 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
74 memcpy(out
->data
, in
->data
, sizeof(out
->data
));
76 status
= netlogon_creds_aes_encrypt(creds
,
79 if (!NT_STATUS_IS_OK(status
)) {
83 rc
= des_crypt112(out
->data
, in
->data
, creds
->session_key
, SAMBA_GNUTLS_ENCRYPT
);
85 return gnutls_error_to_ntstatus(rc
,
86 NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
94 initialise the credentials state for old-style 64 bit session keys
96 this call is made after the netr_ServerReqChallenge call
98 static NTSTATUS
netlogon_creds_init_64bit(struct netlogon_creds_CredentialState
*creds
,
99 const struct netr_Credential
*client_challenge
,
100 const struct netr_Credential
*server_challenge
,
101 const struct samr_Password
*machine_password
)
107 sum
[0] = IVAL(client_challenge
->data
, 0) + IVAL(server_challenge
->data
, 0);
108 sum
[1] = IVAL(client_challenge
->data
, 4) + IVAL(server_challenge
->data
, 4);
110 SIVAL(sum2
,0,sum
[0]);
111 SIVAL(sum2
,4,sum
[1]);
113 ZERO_ARRAY(creds
->session_key
);
115 rc
= des_crypt128(creds
->session_key
, sum2
, machine_password
->hash
);
117 return gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
124 initialise the credentials state for ADS-style 128 bit session keys
126 this call is made after the netr_ServerReqChallenge call
128 static NTSTATUS
netlogon_creds_init_128bit(struct netlogon_creds_CredentialState
*creds
,
129 const struct netr_Credential
*client_challenge
,
130 const struct netr_Credential
*server_challenge
,
131 const struct samr_Password
*machine_password
)
133 uint8_t zero
[4] = {0};
134 uint8_t tmp
[gnutls_hash_get_len(GNUTLS_DIG_MD5
)];
135 gnutls_hash_hd_t hash_hnd
= NULL
;
138 ZERO_ARRAY(creds
->session_key
);
140 rc
= gnutls_hash_init(&hash_hnd
, GNUTLS_DIG_MD5
);
142 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
145 rc
= gnutls_hash(hash_hnd
, zero
, sizeof(zero
));
147 gnutls_hash_deinit(hash_hnd
, NULL
);
148 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
150 rc
= gnutls_hash(hash_hnd
, client_challenge
->data
, 8);
152 gnutls_hash_deinit(hash_hnd
, NULL
);
153 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
155 rc
= gnutls_hash(hash_hnd
, server_challenge
->data
, 8);
157 gnutls_hash_deinit(hash_hnd
, NULL
);
158 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
161 gnutls_hash_deinit(hash_hnd
, tmp
);
163 /* This doesn't require HMAC MD5 RFC2104 as the hash is only 16 bytes */
164 rc
= gnutls_hmac_fast(GNUTLS_MAC_MD5
,
165 machine_password
->hash
,
166 sizeof(machine_password
->hash
),
173 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
180 initialise the credentials state for AES/HMAC-SHA256-style 128 bit session keys
182 this call is made after the netr_ServerReqChallenge call
184 static NTSTATUS
netlogon_creds_init_hmac_sha256(struct netlogon_creds_CredentialState
*creds
,
185 const struct netr_Credential
*client_challenge
,
186 const struct netr_Credential
*server_challenge
,
187 const struct samr_Password
*machine_password
)
189 gnutls_hmac_hd_t hmac_hnd
= NULL
;
190 uint8_t digest
[gnutls_hmac_get_len(GNUTLS_MAC_SHA256
)];
193 ZERO_ARRAY(creds
->session_key
);
195 rc
= gnutls_hmac_init(&hmac_hnd
,
197 machine_password
->hash
,
198 sizeof(machine_password
->hash
));
200 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
202 rc
= gnutls_hmac(hmac_hnd
,
203 client_challenge
->data
,
206 gnutls_hmac_deinit(hmac_hnd
, NULL
);
207 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
209 rc
= gnutls_hmac(hmac_hnd
,
210 server_challenge
->data
,
213 gnutls_hmac_deinit(hmac_hnd
, NULL
);
214 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
216 gnutls_hmac_deinit(hmac_hnd
, digest
);
218 memcpy(creds
->session_key
, digest
, sizeof(creds
->session_key
));
225 static NTSTATUS
netlogon_creds_first_step(struct netlogon_creds_CredentialState
*creds
,
226 const struct netr_Credential
*client_challenge
,
227 const struct netr_Credential
*server_challenge
)
231 status
= netlogon_creds_step_crypt(creds
,
234 if (!NT_STATUS_IS_OK(status
)) {
238 status
= netlogon_creds_step_crypt(creds
,
241 if (!NT_STATUS_IS_OK(status
)) {
245 creds
->seed
= creds
->client
;
251 step the credentials to the next element in the chain, updating the
252 current client and server credentials and the seed
254 static NTSTATUS
netlogon_creds_step(struct netlogon_creds_CredentialState
*creds
)
256 struct netr_Credential time_cred
;
259 DEBUG(5,("\tseed %08x:%08x\n",
260 IVAL(creds
->seed
.data
, 0), IVAL(creds
->seed
.data
, 4)));
262 SIVAL(time_cred
.data
, 0, IVAL(creds
->seed
.data
, 0) + creds
->sequence
);
263 SIVAL(time_cred
.data
, 4, IVAL(creds
->seed
.data
, 4));
265 DEBUG(5,("\tseed+time %08x:%08x\n", IVAL(time_cred
.data
, 0), IVAL(time_cred
.data
, 4)));
267 status
= netlogon_creds_step_crypt(creds
,
270 if (!NT_STATUS_IS_OK(status
)) {
274 DEBUG(5,("\tCLIENT %08x:%08x\n",
275 IVAL(creds
->client
.data
, 0), IVAL(creds
->client
.data
, 4)));
277 SIVAL(time_cred
.data
, 0, IVAL(creds
->seed
.data
, 0) + creds
->sequence
+ 1);
278 SIVAL(time_cred
.data
, 4, IVAL(creds
->seed
.data
, 4));
280 DEBUG(5,("\tseed+time+1 %08x:%08x\n",
281 IVAL(time_cred
.data
, 0), IVAL(time_cred
.data
, 4)));
283 status
= netlogon_creds_step_crypt(creds
, &time_cred
, &creds
->server
);
284 if (!NT_STATUS_IS_OK(status
)) {
288 DEBUG(5,("\tSERVER %08x:%08x\n",
289 IVAL(creds
->server
.data
, 0), IVAL(creds
->server
.data
, 4)));
291 creds
->seed
= time_cred
;
297 DES encrypt a 8 byte LMSessionKey buffer using the Netlogon session key
299 static NTSTATUS
netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState
*creds
,
300 struct netr_LMSessionKey
*key
)
303 struct netr_LMSessionKey tmp
;
305 rc
= des_crypt56_gnutls(tmp
.key
, key
->key
, creds
->session_key
, SAMBA_GNUTLS_ENCRYPT
);
307 return gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
315 DES decrypt a 8 byte LMSessionKey buffer using the Netlogon session key
317 static NTSTATUS
netlogon_creds_des_decrypt_LMKey(struct netlogon_creds_CredentialState
*creds
,
318 struct netr_LMSessionKey
*key
)
321 struct netr_LMSessionKey tmp
;
323 rc
= des_crypt56_gnutls(tmp
.key
, key
->key
, creds
->session_key
, SAMBA_GNUTLS_DECRYPT
);
325 return gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
333 DES encrypt a 16 byte password buffer using the session key
335 NTSTATUS
netlogon_creds_des_encrypt(struct netlogon_creds_CredentialState
*creds
,
336 struct samr_Password
*pass
)
338 struct samr_Password tmp
;
341 rc
= des_crypt112_16(tmp
.hash
, pass
->hash
, creds
->session_key
, SAMBA_GNUTLS_ENCRYPT
);
343 return gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
351 DES decrypt a 16 byte password buffer using the session key
353 NTSTATUS
netlogon_creds_des_decrypt(struct netlogon_creds_CredentialState
*creds
,
354 struct samr_Password
*pass
)
356 struct samr_Password tmp
;
359 rc
= des_crypt112_16(tmp
.hash
, pass
->hash
, creds
->session_key
, SAMBA_GNUTLS_DECRYPT
);
361 return gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
369 ARCFOUR encrypt/decrypt a password buffer using the session key
371 NTSTATUS
netlogon_creds_arcfour_crypt(struct netlogon_creds_CredentialState
*creds
,
375 gnutls_cipher_hd_t cipher_hnd
= NULL
;
376 gnutls_datum_t session_key
= {
377 .data
= creds
->session_key
,
378 .size
= sizeof(creds
->session_key
),
382 rc
= gnutls_cipher_init(&cipher_hnd
,
383 GNUTLS_CIPHER_ARCFOUR_128
,
387 return gnutls_error_to_ntstatus(rc
,
388 NT_STATUS_CRYPTO_SYSTEM_INVALID
);
390 rc
= gnutls_cipher_encrypt(cipher_hnd
,
393 gnutls_cipher_deinit(cipher_hnd
);
395 return gnutls_error_to_ntstatus(rc
,
396 NT_STATUS_CRYPTO_SYSTEM_INVALID
);
403 AES encrypt a password buffer using the session key
405 NTSTATUS
netlogon_creds_aes_encrypt(struct netlogon_creds_CredentialState
*creds
,
409 gnutls_cipher_hd_t cipher_hnd
= NULL
;
410 gnutls_datum_t key
= {
411 .data
= creds
->session_key
,
412 .size
= sizeof(creds
->session_key
),
415 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8
);
416 uint8_t _iv
[iv_size
];
417 gnutls_datum_t iv
= {
425 rc
= gnutls_cipher_init(&cipher_hnd
,
426 GNUTLS_CIPHER_AES_128_CFB8
,
430 return gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
433 rc
= gnutls_cipher_encrypt(cipher_hnd
, data
, len
);
434 gnutls_cipher_deinit(cipher_hnd
);
436 return gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
443 AES decrypt a password buffer using the session key
445 NTSTATUS
netlogon_creds_aes_decrypt(struct netlogon_creds_CredentialState
*creds
, uint8_t *data
, size_t len
)
447 gnutls_cipher_hd_t cipher_hnd
= NULL
;
448 gnutls_datum_t key
= {
449 .data
= creds
->session_key
,
450 .size
= sizeof(creds
->session_key
),
453 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8
);
454 uint8_t _iv
[iv_size
];
455 gnutls_datum_t iv
= {
463 rc
= gnutls_cipher_init(&cipher_hnd
,
464 GNUTLS_CIPHER_AES_128_CFB8
,
468 return gnutls_error_to_ntstatus(rc
,
469 NT_STATUS_CRYPTO_SYSTEM_INVALID
);
472 rc
= gnutls_cipher_decrypt(cipher_hnd
, data
, len
);
473 gnutls_cipher_deinit(cipher_hnd
);
475 return gnutls_error_to_ntstatus(rc
,
476 NT_STATUS_CRYPTO_SYSTEM_INVALID
);
482 static struct netlogon_creds_CredentialState
*
483 netlogon_creds_alloc(TALLOC_CTX
*mem_ctx
,
484 const char *client_account
,
485 const char *client_computer_name
,
486 uint16_t secure_channel_type
,
487 uint32_t client_requested_flags
,
488 const struct dom_sid
*client_sid
,
489 uint32_t negotiate_flags
)
491 struct netlogon_creds_CredentialState
*creds
= NULL
;
492 struct timeval tv
= timeval_current();
493 NTTIME now
= timeval_to_nttime(&tv
);
495 creds
= talloc_zero(mem_ctx
, struct netlogon_creds_CredentialState
);
500 if (client_sid
== NULL
) {
501 creds
->sequence
= tv
.tv_sec
;
503 creds
->negotiate_flags
= negotiate_flags
;
504 creds
->secure_channel_type
= secure_channel_type
;
506 creds
->computer_name
= talloc_strdup(creds
, client_computer_name
);
507 if (!creds
->computer_name
) {
511 creds
->account_name
= talloc_strdup(creds
, client_account
);
512 if (!creds
->account_name
) {
517 creds
->ex
= talloc_zero(creds
,
518 struct netlogon_creds_CredentialState_extra_info
);
519 if (creds
->ex
== NULL
) {
523 creds
->ex
->client_requested_flags
= client_requested_flags
;
524 creds
->ex
->auth_time
= now
;
525 if (client_sid
!= NULL
) {
526 creds
->ex
->client_sid
= *client_sid
;
528 creds
->ex
->client_sid
= global_sid_NULL
;
534 /*****************************************************************
535 The above functions are common to the client and server interface
536 next comes the client specific functions
537 ******************************************************************/
540 initialise the credentials chain and return the first client
544 struct netlogon_creds_CredentialState
*netlogon_creds_client_init(TALLOC_CTX
*mem_ctx
,
545 const char *client_account
,
546 const char *client_computer_name
,
547 uint16_t secure_channel_type
,
548 const struct netr_Credential
*client_challenge
,
549 const struct netr_Credential
*server_challenge
,
550 const struct samr_Password
*machine_password
,
551 struct netr_Credential
*initial_credential
,
552 uint32_t client_requested_flags
,
553 uint32_t negotiate_flags
)
555 struct netlogon_creds_CredentialState
*creds
= NULL
;
558 creds
= netlogon_creds_alloc(mem_ctx
,
560 client_computer_name
,
562 client_requested_flags
,
563 NULL
, /* client_sid */
569 dump_data_pw("Client chall", client_challenge
->data
, sizeof(client_challenge
->data
));
570 dump_data_pw("Server chall", server_challenge
->data
, sizeof(server_challenge
->data
));
571 dump_data_pw("Machine Pass", machine_password
->hash
, sizeof(machine_password
->hash
));
573 if (negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
574 status
= netlogon_creds_init_hmac_sha256(creds
,
578 if (!NT_STATUS_IS_OK(status
)) {
582 } else if (negotiate_flags
& NETLOGON_NEG_STRONG_KEYS
) {
583 status
= netlogon_creds_init_128bit(creds
,
587 if (!NT_STATUS_IS_OK(status
)) {
592 status
= netlogon_creds_init_64bit(creds
,
596 if (!NT_STATUS_IS_OK(status
)) {
602 status
= netlogon_creds_first_step(creds
,
605 if (!NT_STATUS_IS_OK(status
)) {
610 dump_data_pw("Session key", creds
->session_key
, 16);
611 dump_data_pw("Credential ", creds
->client
.data
, 8);
613 *initial_credential
= creds
->client
;
618 step the credentials to the next element in the chain, updating the
619 current client and server credentials and the seed
621 produce the next authenticator in the sequence ready to send to
625 netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState
*creds
,
626 struct netr_Authenticator
*next
)
628 uint32_t t32n
= (uint32_t)time(NULL
);
632 * we always increment and ignore an overflow here
634 creds
->sequence
+= 2;
636 if (t32n
> creds
->sequence
) {
638 * we may increment more
640 creds
->sequence
= t32n
;
642 uint32_t d
= creds
->sequence
- t32n
;
644 if (d
>= INT32_MAX
) {
646 * got an overflow of time_t vs. uint32_t
648 creds
->sequence
= t32n
;
652 status
= netlogon_creds_step(creds
);
653 if (!NT_STATUS_IS_OK(status
)) {
657 next
->cred
= creds
->client
;
658 next
->timestamp
= creds
->sequence
;
664 check that a credentials reply from a server is correct
666 NTSTATUS
netlogon_creds_client_verify(struct netlogon_creds_CredentialState
*creds
,
667 const struct netr_Credential
*received_credentials
,
668 enum dcerpc_AuthType auth_type
,
669 enum dcerpc_AuthLevel auth_level
)
671 if (!received_credentials
||
672 !mem_equal_const_time(received_credentials
->data
, creds
->server
.data
, 8)) {
673 DEBUG(2,("credentials check failed\n"));
674 return NT_STATUS_ACCESS_DENIED
;
679 bool netlogon_creds_client_check(struct netlogon_creds_CredentialState
*creds
,
680 const struct netr_Credential
*received_credentials
)
682 enum dcerpc_AuthType auth_type
= DCERPC_AUTH_TYPE_NONE
;
683 enum dcerpc_AuthLevel auth_level
= DCERPC_AUTH_LEVEL_NONE
;
686 status
= netlogon_creds_client_verify(creds
,
687 received_credentials
,
690 if (!NT_STATUS_IS_OK(status
)) {
698 /*****************************************************************
699 The above functions are common to the client and server interface
700 next comes the server specific functions
701 ******************************************************************/
704 check that a credentials reply from a server is correct
706 static bool netlogon_creds_server_check_internal(const struct netlogon_creds_CredentialState
*creds
,
707 const struct netr_Credential
*received_credentials
)
709 if (!mem_equal_const_time(received_credentials
->data
, creds
->client
.data
, 8)) {
710 DEBUG(2,("credentials check failed\n"));
711 dump_data_pw("client creds", creds
->client
.data
, 8);
712 dump_data_pw("calc creds", received_credentials
->data
, 8);
719 initialise the credentials chain and return the first server
722 struct netlogon_creds_CredentialState
*netlogon_creds_server_init(TALLOC_CTX
*mem_ctx
,
723 const char *client_account
,
724 const char *client_computer_name
,
725 uint16_t secure_channel_type
,
726 const struct netr_Credential
*client_challenge
,
727 const struct netr_Credential
*server_challenge
,
728 const struct samr_Password
*machine_password
,
729 const struct netr_Credential
*credentials_in
,
730 struct netr_Credential
*credentials_out
,
731 uint32_t client_requested_flags
,
732 const struct dom_sid
*client_sid
,
733 uint32_t negotiate_flags
)
735 struct netlogon_creds_CredentialState
*creds
= NULL
;
739 creds
= netlogon_creds_alloc(mem_ctx
,
741 client_computer_name
,
743 client_requested_flags
,
750 dump_data_pw("Client chall", client_challenge
->data
, sizeof(client_challenge
->data
));
751 dump_data_pw("Server chall", server_challenge
->data
, sizeof(server_challenge
->data
));
752 dump_data_pw("Machine Pass", machine_password
->hash
, sizeof(machine_password
->hash
));
754 ok
= netlogon_creds_is_random_challenge(client_challenge
);
756 DBG_WARNING("CVE-2020-1472(ZeroLogon): "
757 "non-random client challenge rejected for "
758 "client_account[%s] client_computer_name[%s]\n",
759 log_escape(mem_ctx
, client_account
),
760 log_escape(mem_ctx
, client_computer_name
));
761 dump_data(DBGLVL_WARNING
,
762 client_challenge
->data
,
763 sizeof(client_challenge
->data
));
768 if (negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
769 status
= netlogon_creds_init_hmac_sha256(creds
,
773 if (!NT_STATUS_IS_OK(status
)) {
777 } else if (negotiate_flags
& NETLOGON_NEG_STRONG_KEYS
) {
778 status
= netlogon_creds_init_128bit(creds
,
782 if (!NT_STATUS_IS_OK(status
)) {
787 status
= netlogon_creds_init_64bit(creds
,
791 if (!NT_STATUS_IS_OK(status
)) {
797 status
= netlogon_creds_first_step(creds
,
800 if (!NT_STATUS_IS_OK(status
)) {
805 dump_data_pw("Session key", creds
->session_key
, 16);
806 dump_data_pw("Client Credential ", creds
->client
.data
, 8);
807 dump_data_pw("Server Credential ", creds
->server
.data
, 8);
809 dump_data_pw("Credentials in", credentials_in
->data
, sizeof(credentials_in
->data
));
811 /* And before we leak information about the machine account
812 * password, check that they got the first go right */
813 if (!netlogon_creds_server_check_internal(creds
, credentials_in
)) {
818 *credentials_out
= creds
->server
;
820 dump_data_pw("Credentials out", credentials_out
->data
, sizeof(credentials_out
->data
));
825 NTSTATUS
netlogon_creds_server_step_check(struct netlogon_creds_CredentialState
*creds
,
826 const struct netr_Authenticator
*received_authenticator
,
827 struct netr_Authenticator
*return_authenticator
,
828 enum dcerpc_AuthType auth_type
,
829 enum dcerpc_AuthLevel auth_level
)
833 if (!received_authenticator
|| !return_authenticator
) {
834 return NT_STATUS_INVALID_PARAMETER
;
838 return NT_STATUS_ACCESS_DENIED
;
841 creds
->sequence
= received_authenticator
->timestamp
;
842 status
= netlogon_creds_step(creds
);
843 if (!NT_STATUS_IS_OK(status
)) {
844 ZERO_STRUCTP(return_authenticator
);
848 if (netlogon_creds_server_check_internal(creds
, &received_authenticator
->cred
)) {
849 return_authenticator
->cred
= creds
->server
;
850 return_authenticator
->timestamp
= 0;
853 ZERO_STRUCTP(return_authenticator
);
854 return NT_STATUS_ACCESS_DENIED
;
858 static NTSTATUS
netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_CredentialState
*creds
,
859 uint16_t validation_level
,
860 union netr_Validation
*validation
,
861 enum dcerpc_AuthType auth_type
,
862 enum dcerpc_AuthLevel auth_level
,
865 struct netr_SamBaseInfo
*base
= NULL
;
868 if (validation
== NULL
) {
869 return NT_STATUS_INVALID_PARAMETER
;
872 switch (validation_level
) {
874 if (validation
->sam2
) {
875 base
= &validation
->sam2
->base
;
879 if (validation
->sam3
) {
880 base
= &validation
->sam3
->base
;
884 if (validation
->sam6
) {
885 base
= &validation
->sam6
->base
;
889 /* If we can't find it, we can't very well decrypt it */
890 return NT_STATUS_INVALID_INFO_CLASS
;
894 return NT_STATUS_INVALID_INFO_CLASS
;
897 /* find and decrypt the session keys, return in parameters above */
898 if (validation_level
== 6) {
899 /* they aren't encrypted! */
900 } else if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
901 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
902 if (!all_zero(base
->key
.key
, sizeof(base
->key
.key
))) {
904 status
= netlogon_creds_aes_encrypt(
907 sizeof(base
->key
.key
));
909 status
= netlogon_creds_aes_decrypt(
912 sizeof(base
->key
.key
));
914 if (!NT_STATUS_IS_OK(status
)) {
919 if (!all_zero(base
->LMSessKey
.key
,
920 sizeof(base
->LMSessKey
.key
))) {
922 status
= netlogon_creds_aes_encrypt(
925 sizeof(base
->LMSessKey
.key
));
927 status
= netlogon_creds_aes_decrypt(
930 sizeof(base
->LMSessKey
.key
));
932 if (!NT_STATUS_IS_OK(status
)) {
936 } else if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
937 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
938 if (!all_zero(base
->key
.key
, sizeof(base
->key
.key
))) {
939 status
= netlogon_creds_arcfour_crypt(creds
,
941 sizeof(base
->key
.key
));
942 if (!NT_STATUS_IS_OK(status
)) {
947 if (!all_zero(base
->LMSessKey
.key
,
948 sizeof(base
->LMSessKey
.key
))) {
949 status
= netlogon_creds_arcfour_crypt(creds
,
951 sizeof(base
->LMSessKey
.key
));
952 if (!NT_STATUS_IS_OK(status
)) {
957 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
958 if (!all_zero(base
->LMSessKey
.key
,
959 sizeof(base
->LMSessKey
.key
))) {
961 status
= netlogon_creds_des_encrypt_LMKey(creds
,
964 status
= netlogon_creds_des_decrypt_LMKey(creds
,
967 if (!NT_STATUS_IS_OK(status
)) {
976 NTSTATUS
netlogon_creds_decrypt_samlogon_validation(struct netlogon_creds_CredentialState
*creds
,
977 uint16_t validation_level
,
978 union netr_Validation
*validation
,
979 enum dcerpc_AuthType auth_type
,
980 enum dcerpc_AuthLevel auth_level
)
982 return netlogon_creds_crypt_samlogon_validation(creds
,
990 NTSTATUS
netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_CredentialState
*creds
,
991 uint16_t validation_level
,
992 union netr_Validation
*validation
,
993 enum dcerpc_AuthType auth_type
,
994 enum dcerpc_AuthLevel auth_level
)
996 return netlogon_creds_crypt_samlogon_validation(creds
,
1004 static NTSTATUS
netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_CredentialState
*creds
,
1005 enum netr_LogonInfoClass level
,
1006 union netr_LogonLevel
*logon
,
1007 enum dcerpc_AuthType auth_type
,
1008 enum dcerpc_AuthLevel auth_level
,
1013 if (logon
== NULL
) {
1014 return NT_STATUS_INVALID_PARAMETER
;
1018 case NetlogonInteractiveInformation
:
1019 case NetlogonInteractiveTransitiveInformation
:
1020 case NetlogonServiceInformation
:
1021 case NetlogonServiceTransitiveInformation
:
1022 if (logon
->password
== NULL
) {
1023 return NT_STATUS_INVALID_PARAMETER
;
1026 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1029 h
= logon
->password
->lmpassword
.hash
;
1030 if (!all_zero(h
, 16)) {
1032 status
= netlogon_creds_aes_encrypt(
1037 status
= netlogon_creds_aes_decrypt(
1042 if (!NT_STATUS_IS_OK(status
)) {
1047 h
= logon
->password
->ntpassword
.hash
;
1048 if (!all_zero(h
, 16)) {
1050 status
= netlogon_creds_aes_encrypt(creds
,
1054 status
= netlogon_creds_aes_decrypt(creds
,
1058 if (!NT_STATUS_IS_OK(status
)) {
1062 } else if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
1065 h
= logon
->password
->lmpassword
.hash
;
1066 if (!all_zero(h
, 16)) {
1067 status
= netlogon_creds_arcfour_crypt(creds
,
1070 if (!NT_STATUS_IS_OK(status
)) {
1075 h
= logon
->password
->ntpassword
.hash
;
1076 if (!all_zero(h
, 16)) {
1077 status
= netlogon_creds_arcfour_crypt(creds
,
1080 if (!NT_STATUS_IS_OK(status
)) {
1085 struct samr_Password
*p
;
1087 p
= &logon
->password
->lmpassword
;
1088 if (!all_zero(p
->hash
, 16)) {
1090 status
= netlogon_creds_des_encrypt(creds
, p
);
1092 status
= netlogon_creds_des_decrypt(creds
, p
);
1094 if (!NT_STATUS_IS_OK(status
)) {
1098 p
= &logon
->password
->ntpassword
;
1099 if (!all_zero(p
->hash
, 16)) {
1101 status
= netlogon_creds_des_encrypt(creds
, p
);
1103 status
= netlogon_creds_des_decrypt(creds
, p
);
1105 if (!NT_STATUS_IS_OK(status
)) {
1112 case NetlogonNetworkInformation
:
1113 case NetlogonNetworkTransitiveInformation
:
1116 case NetlogonGenericInformation
:
1117 if (logon
->generic
== NULL
) {
1118 return NT_STATUS_INVALID_PARAMETER
;
1121 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1123 status
= netlogon_creds_aes_encrypt(
1125 logon
->generic
->data
,
1126 logon
->generic
->length
);
1128 status
= netlogon_creds_aes_decrypt(
1130 logon
->generic
->data
,
1131 logon
->generic
->length
);
1133 if (!NT_STATUS_IS_OK(status
)) {
1136 } else if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
1137 status
= netlogon_creds_arcfour_crypt(creds
,
1138 logon
->generic
->data
,
1139 logon
->generic
->length
);
1140 if (!NT_STATUS_IS_OK(status
)) {
1144 /* Using DES to verify kerberos tickets makes no sense */
1145 return NT_STATUS_INVALID_PARAMETER
;
1150 return NT_STATUS_OK
;
1153 NTSTATUS
netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState
*creds
,
1154 enum netr_LogonInfoClass level
,
1155 union netr_LogonLevel
*logon
,
1156 enum dcerpc_AuthType auth_type
,
1157 enum dcerpc_AuthLevel auth_level
)
1159 return netlogon_creds_crypt_samlogon_logon(creds
,
1167 NTSTATUS
netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState
*creds
,
1168 enum netr_LogonInfoClass level
,
1169 union netr_LogonLevel
*logon
,
1170 enum dcerpc_AuthType auth_type
,
1171 enum dcerpc_AuthLevel auth_level
)
1173 return netlogon_creds_crypt_samlogon_logon(creds
,
1181 static NTSTATUS
netlogon_creds_crypt_samr_Password(
1182 struct netlogon_creds_CredentialState
*creds
,
1183 struct samr_Password
*pass
,
1184 enum dcerpc_AuthType auth_type
,
1185 enum dcerpc_AuthLevel auth_level
,
1188 if (all_zero(pass
->hash
, ARRAY_SIZE(pass
->hash
))) {
1189 return NT_STATUS_OK
;
1193 * Even with NETLOGON_NEG_SUPPORTS_AES or
1194 * NETLOGON_NEG_ARCFOUR this uses DES
1198 return netlogon_creds_des_encrypt(creds
, pass
);
1201 return netlogon_creds_des_decrypt(creds
, pass
);
1204 NTSTATUS
netlogon_creds_decrypt_samr_Password(struct netlogon_creds_CredentialState
*creds
,
1205 struct samr_Password
*pass
,
1206 enum dcerpc_AuthType auth_type
,
1207 enum dcerpc_AuthLevel auth_level
)
1209 return netlogon_creds_crypt_samr_Password(creds
,
1216 NTSTATUS
netlogon_creds_encrypt_samr_Password(struct netlogon_creds_CredentialState
*creds
,
1217 struct samr_Password
*pass
,
1218 enum dcerpc_AuthType auth_type
,
1219 enum dcerpc_AuthLevel auth_level
)
1221 return netlogon_creds_crypt_samr_Password(creds
,
1228 static NTSTATUS
netlogon_creds_crypt_samr_CryptPassword(
1229 struct netlogon_creds_CredentialState
*creds
,
1230 struct samr_CryptPassword
*pass
,
1231 enum dcerpc_AuthType auth_type
,
1232 enum dcerpc_AuthLevel auth_level
,
1235 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1237 return netlogon_creds_aes_encrypt(creds
,
1239 ARRAY_SIZE(pass
->data
));
1242 return netlogon_creds_aes_decrypt(creds
,
1244 ARRAY_SIZE(pass
->data
));
1247 return netlogon_creds_arcfour_crypt(creds
,
1249 ARRAY_SIZE(pass
->data
));
1252 NTSTATUS
netlogon_creds_decrypt_samr_CryptPassword(struct netlogon_creds_CredentialState
*creds
,
1253 struct samr_CryptPassword
*pass
,
1254 enum dcerpc_AuthType auth_type
,
1255 enum dcerpc_AuthLevel auth_level
)
1257 return netlogon_creds_crypt_samr_CryptPassword(creds
,
1264 NTSTATUS
netlogon_creds_encrypt_samr_CryptPassword(struct netlogon_creds_CredentialState
*creds
,
1265 struct samr_CryptPassword
*pass
,
1266 enum dcerpc_AuthType auth_type
,
1267 enum dcerpc_AuthLevel auth_level
)
1269 return netlogon_creds_crypt_samr_CryptPassword(creds
,
1276 static NTSTATUS
netlogon_creds_crypt_SendToSam(
1277 struct netlogon_creds_CredentialState
*creds
,
1278 uint8_t *opaque_data
,
1279 size_t opaque_length
,
1280 enum dcerpc_AuthType auth_type
,
1281 enum dcerpc_AuthLevel auth_level
,
1284 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1286 return netlogon_creds_aes_encrypt(creds
,
1291 return netlogon_creds_aes_decrypt(creds
,
1296 return netlogon_creds_arcfour_crypt(creds
,
1301 NTSTATUS
netlogon_creds_decrypt_SendToSam(struct netlogon_creds_CredentialState
*creds
,
1302 uint8_t *opaque_data
,
1303 size_t opaque_length
,
1304 enum dcerpc_AuthType auth_type
,
1305 enum dcerpc_AuthLevel auth_level
)
1307 return netlogon_creds_crypt_SendToSam(creds
,
1315 NTSTATUS
netlogon_creds_encrypt_SendToSam(struct netlogon_creds_CredentialState
*creds
,
1316 uint8_t *opaque_data
,
1317 size_t opaque_length
,
1318 enum dcerpc_AuthType auth_type
,
1319 enum dcerpc_AuthLevel auth_level
)
1321 return netlogon_creds_crypt_SendToSam(creds
,
1329 union netr_LogonLevel
*netlogon_creds_shallow_copy_logon(TALLOC_CTX
*mem_ctx
,
1330 enum netr_LogonInfoClass level
,
1331 const union netr_LogonLevel
*in
)
1333 union netr_LogonLevel
*out
;
1339 out
= talloc(mem_ctx
, union netr_LogonLevel
);
1347 case NetlogonInteractiveInformation
:
1348 case NetlogonInteractiveTransitiveInformation
:
1349 case NetlogonServiceInformation
:
1350 case NetlogonServiceTransitiveInformation
:
1351 if (in
->password
== NULL
) {
1355 out
->password
= talloc(out
, struct netr_PasswordInfo
);
1356 if (out
->password
== NULL
) {
1360 *out
->password
= *in
->password
;
1364 case NetlogonNetworkInformation
:
1365 case NetlogonNetworkTransitiveInformation
:
1368 case NetlogonGenericInformation
:
1369 if (in
->generic
== NULL
) {
1373 out
->generic
= talloc(out
, struct netr_GenericInfo
);
1374 if (out
->generic
== NULL
) {
1378 *out
->generic
= *in
->generic
;
1380 if (in
->generic
->data
== NULL
) {
1384 if (in
->generic
->length
== 0) {
1388 out
->generic
->data
= talloc_memdup(out
->generic
,
1390 in
->generic
->length
);
1391 if (out
->generic
->data
== NULL
) {
1403 copy a netlogon_creds_CredentialState struct
1406 struct netlogon_creds_CredentialState
*netlogon_creds_copy(
1407 TALLOC_CTX
*mem_ctx
,
1408 const struct netlogon_creds_CredentialState
*creds_in
)
1410 struct netlogon_creds_CredentialState
*creds
= talloc_zero(mem_ctx
, struct netlogon_creds_CredentialState
);
1418 creds
->computer_name
= talloc_strdup(creds
, creds_in
->computer_name
);
1419 if (!creds
->computer_name
) {
1423 creds
->account_name
= talloc_strdup(creds
, creds_in
->account_name
);
1424 if (!creds
->account_name
) {
1429 if (creds_in
->ex
!= NULL
) {
1430 creds
->ex
= talloc_zero(creds
,
1431 struct netlogon_creds_CredentialState_extra_info
);
1432 if (creds
->ex
== NULL
) {
1436 *creds
->ex
= *creds_in
->ex
;