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 "librpc/gen_ndr/ndr_schannel.h"
26 #include "libcli/auth/libcli_auth.h"
27 #include "../libcli/security/dom_sid.h"
28 #include "lib/util/util_str_escape.h"
30 #include "lib/crypto/gnutls_helpers.h"
31 #include <gnutls/gnutls.h>
32 #include <gnutls/crypto.h>
34 #undef netlogon_creds_des_encrypt
35 #undef netlogon_creds_des_decrypt
36 #undef netlogon_creds_arcfour_crypt
37 #undef netlogon_creds_aes_encrypt
38 #undef netlogon_creds_aes_decrypt
40 bool netlogon_creds_is_random_challenge(const struct netr_Credential
*challenge
)
43 * If none of the first 5 bytes of the client challenge is unique, the
44 * server MUST fail session-key negotiation without further processing
45 * of the following steps.
48 if (challenge
->data
[1] == challenge
->data
[0] &&
49 challenge
->data
[2] == challenge
->data
[0] &&
50 challenge
->data
[3] == challenge
->data
[0] &&
51 challenge
->data
[4] == challenge
->data
[0])
59 static NTSTATUS
netlogon_creds_no_step_check(struct netlogon_creds_CredentialState
*creds
,
60 enum dcerpc_AuthType auth_type
,
61 enum dcerpc_AuthLevel auth_level
,
67 return NT_STATUS_ACCESS_DENIED
;
71 * Only if ServerAuthenticateKerberos() was
72 * used the content of the netr_Authenticator
73 * values are not checked.
75 * It is independent from the
76 * NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH flag.
78 if (creds
->authenticate_kerberos
) {
79 if (auth_type
!= DCERPC_AUTH_TYPE_KRB5
) {
80 return NT_STATUS_ACCESS_DENIED
;
82 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
83 return NT_STATUS_ACCESS_DENIED
;
91 static NTSTATUS
netlogon_creds_no_buffer_crypt(struct netlogon_creds_CredentialState
*creds
,
92 enum dcerpc_AuthType auth_type
,
93 enum dcerpc_AuthLevel auth_level
,
99 return NT_STATUS_ACCESS_DENIED
;
102 if (creds
->authenticate_kerberos
) {
103 if (auth_type
!= DCERPC_AUTH_TYPE_KRB5
) {
104 return NT_STATUS_ACCESS_DENIED
;
106 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
107 return NT_STATUS_ACCESS_DENIED
;
112 * Even if NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH is
113 * negotiated within ServerAuthenticate3()
114 * encryption on application buffers is skipped.
116 * Also ServerAuthenticateKerberos() without
117 * NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH uses
118 * encryption with a random session key.
120 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
) {
121 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
122 return NT_STATUS_ACCESS_DENIED
;
131 void netlogon_creds_random_challenge(struct netr_Credential
*challenge
)
133 ZERO_STRUCTP(challenge
);
134 while (!netlogon_creds_is_random_challenge(challenge
)) {
135 generate_random_buffer(challenge
->data
, sizeof(challenge
->data
));
139 static NTSTATUS
netlogon_creds_step_crypt(struct netlogon_creds_CredentialState
*creds
,
140 const struct netr_Credential
*in
,
141 struct netr_Credential
*out
)
146 if (creds
->authenticate_kerberos
) {
148 * The caller should have checked this already...
150 return NT_STATUS_INVALID_PARAMETER_MIX
;
153 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
154 memcpy(out
->data
, in
->data
, sizeof(out
->data
));
156 status
= netlogon_creds_aes_encrypt(creds
,
159 if (!NT_STATUS_IS_OK(status
)) {
163 rc
= des_crypt112(out
->data
, in
->data
, creds
->session_key
, SAMBA_GNUTLS_ENCRYPT
);
165 return gnutls_error_to_ntstatus(rc
,
166 NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
174 initialise the credentials state for old-style 64 bit session keys
176 this call is made after the netr_ServerReqChallenge call
178 static NTSTATUS
netlogon_creds_init_64bit(struct netlogon_creds_CredentialState
*creds
,
179 const struct netr_Credential
*client_challenge
,
180 const struct netr_Credential
*server_challenge
,
181 const struct samr_Password
*machine_password
)
187 sum
[0] = IVAL(client_challenge
->data
, 0) + IVAL(server_challenge
->data
, 0);
188 sum
[1] = IVAL(client_challenge
->data
, 4) + IVAL(server_challenge
->data
, 4);
190 SIVAL(sum2
,0,sum
[0]);
191 SIVAL(sum2
,4,sum
[1]);
193 ZERO_ARRAY(creds
->session_key
);
195 rc
= des_crypt128(creds
->session_key
, sum2
, machine_password
->hash
);
197 return gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
204 initialise the credentials state for ADS-style 128 bit session keys
206 this call is made after the netr_ServerReqChallenge call
208 static NTSTATUS
netlogon_creds_init_128bit(struct netlogon_creds_CredentialState
*creds
,
209 const struct netr_Credential
*client_challenge
,
210 const struct netr_Credential
*server_challenge
,
211 const struct samr_Password
*machine_password
)
213 uint8_t zero
[4] = {0};
214 uint8_t tmp
[gnutls_hash_get_len(GNUTLS_DIG_MD5
)];
215 gnutls_hash_hd_t hash_hnd
= NULL
;
218 ZERO_ARRAY(creds
->session_key
);
220 rc
= gnutls_hash_init(&hash_hnd
, GNUTLS_DIG_MD5
);
222 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
225 rc
= gnutls_hash(hash_hnd
, zero
, sizeof(zero
));
227 gnutls_hash_deinit(hash_hnd
, NULL
);
228 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
230 rc
= gnutls_hash(hash_hnd
, client_challenge
->data
, 8);
232 gnutls_hash_deinit(hash_hnd
, NULL
);
233 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
235 rc
= gnutls_hash(hash_hnd
, server_challenge
->data
, 8);
237 gnutls_hash_deinit(hash_hnd
, NULL
);
238 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
241 gnutls_hash_deinit(hash_hnd
, tmp
);
243 /* This doesn't require HMAC MD5 RFC2104 as the hash is only 16 bytes */
244 rc
= gnutls_hmac_fast(GNUTLS_MAC_MD5
,
245 machine_password
->hash
,
246 sizeof(machine_password
->hash
),
253 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
260 initialise the credentials state for AES/HMAC-SHA256-style 128 bit session keys
262 this call is made after the netr_ServerReqChallenge call
264 static NTSTATUS
netlogon_creds_init_hmac_sha256(struct netlogon_creds_CredentialState
*creds
,
265 const struct netr_Credential
*client_challenge
,
266 const struct netr_Credential
*server_challenge
,
267 const struct samr_Password
*machine_password
)
269 gnutls_hmac_hd_t hmac_hnd
= NULL
;
270 uint8_t digest
[gnutls_hmac_get_len(GNUTLS_MAC_SHA256
)];
273 ZERO_ARRAY(creds
->session_key
);
275 rc
= gnutls_hmac_init(&hmac_hnd
,
277 machine_password
->hash
,
278 sizeof(machine_password
->hash
));
280 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
282 rc
= gnutls_hmac(hmac_hnd
,
283 client_challenge
->data
,
286 gnutls_hmac_deinit(hmac_hnd
, NULL
);
287 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
289 rc
= gnutls_hmac(hmac_hnd
,
290 server_challenge
->data
,
293 gnutls_hmac_deinit(hmac_hnd
, NULL
);
294 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
296 gnutls_hmac_deinit(hmac_hnd
, digest
);
298 memcpy(creds
->session_key
, digest
, sizeof(creds
->session_key
));
305 static NTSTATUS
netlogon_creds_first_step(struct netlogon_creds_CredentialState
*creds
,
306 const struct netr_Credential
*client_challenge
,
307 const struct netr_Credential
*server_challenge
)
311 status
= netlogon_creds_step_crypt(creds
,
314 if (!NT_STATUS_IS_OK(status
)) {
318 status
= netlogon_creds_step_crypt(creds
,
321 if (!NT_STATUS_IS_OK(status
)) {
325 creds
->seed
= creds
->client
;
331 step the credentials to the next element in the chain, updating the
332 current client and server credentials and the seed
334 static NTSTATUS
netlogon_creds_step(struct netlogon_creds_CredentialState
*creds
)
336 struct netr_Credential time_cred
;
339 if (creds
->authenticate_kerberos
) {
340 /* This is only called on the client side */
341 generate_nonce_buffer(creds
->seed
.data
,
342 ARRAY_SIZE(creds
->seed
.data
));
343 generate_nonce_buffer(creds
->client
.data
,
344 ARRAY_SIZE(creds
->client
.data
));
345 generate_nonce_buffer(creds
->server
.data
,
346 ARRAY_SIZE(creds
->server
.data
));
350 DEBUG(5,("\tseed %08x:%08x\n",
351 IVAL(creds
->seed
.data
, 0), IVAL(creds
->seed
.data
, 4)));
353 SIVAL(time_cred
.data
, 0, IVAL(creds
->seed
.data
, 0) + creds
->sequence
);
354 SIVAL(time_cred
.data
, 4, IVAL(creds
->seed
.data
, 4));
356 DEBUG(5,("\tseed+time %08x:%08x\n", IVAL(time_cred
.data
, 0), IVAL(time_cred
.data
, 4)));
358 status
= netlogon_creds_step_crypt(creds
,
361 if (!NT_STATUS_IS_OK(status
)) {
365 DEBUG(5,("\tCLIENT %08x:%08x\n",
366 IVAL(creds
->client
.data
, 0), IVAL(creds
->client
.data
, 4)));
368 SIVAL(time_cred
.data
, 0, IVAL(creds
->seed
.data
, 0) + creds
->sequence
+ 1);
369 SIVAL(time_cred
.data
, 4, IVAL(creds
->seed
.data
, 4));
371 DEBUG(5,("\tseed+time+1 %08x:%08x\n",
372 IVAL(time_cred
.data
, 0), IVAL(time_cred
.data
, 4)));
374 status
= netlogon_creds_step_crypt(creds
, &time_cred
, &creds
->server
);
375 if (!NT_STATUS_IS_OK(status
)) {
379 DEBUG(5,("\tSERVER %08x:%08x\n",
380 IVAL(creds
->server
.data
, 0), IVAL(creds
->server
.data
, 4)));
382 creds
->seed
= time_cred
;
388 DES encrypt a 8 byte LMSessionKey buffer using the Netlogon session key
390 static NTSTATUS
netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState
*creds
,
391 struct netr_LMSessionKey
*key
)
394 struct netr_LMSessionKey tmp
;
396 rc
= des_crypt56_gnutls(tmp
.key
, key
->key
, creds
->session_key
, SAMBA_GNUTLS_ENCRYPT
);
398 return gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
406 DES decrypt a 8 byte LMSessionKey buffer using the Netlogon session key
408 static NTSTATUS
netlogon_creds_des_decrypt_LMKey(struct netlogon_creds_CredentialState
*creds
,
409 struct netr_LMSessionKey
*key
)
412 struct netr_LMSessionKey tmp
;
414 rc
= des_crypt56_gnutls(tmp
.key
, key
->key
, creds
->session_key
, SAMBA_GNUTLS_DECRYPT
);
416 return gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
424 DES encrypt a 16 byte password buffer using the session key
426 NTSTATUS
netlogon_creds_des_encrypt(struct netlogon_creds_CredentialState
*creds
,
427 struct samr_Password
*pass
)
429 struct samr_Password tmp
;
432 rc
= des_crypt112_16(tmp
.hash
, pass
->hash
, creds
->session_key
, SAMBA_GNUTLS_ENCRYPT
);
434 return gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
442 DES decrypt a 16 byte password buffer using the session key
444 NTSTATUS
netlogon_creds_des_decrypt(struct netlogon_creds_CredentialState
*creds
,
445 struct samr_Password
*pass
)
447 struct samr_Password tmp
;
450 rc
= des_crypt112_16(tmp
.hash
, pass
->hash
, creds
->session_key
, SAMBA_GNUTLS_DECRYPT
);
452 return gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
460 ARCFOUR encrypt/decrypt a password buffer using the session key
462 NTSTATUS
netlogon_creds_arcfour_crypt(struct netlogon_creds_CredentialState
*creds
,
466 gnutls_cipher_hd_t cipher_hnd
= NULL
;
467 gnutls_datum_t session_key
= {
468 .data
= creds
->session_key
,
469 .size
= sizeof(creds
->session_key
),
473 rc
= gnutls_cipher_init(&cipher_hnd
,
474 GNUTLS_CIPHER_ARCFOUR_128
,
478 return gnutls_error_to_ntstatus(rc
,
479 NT_STATUS_CRYPTO_SYSTEM_INVALID
);
481 rc
= gnutls_cipher_encrypt(cipher_hnd
,
484 gnutls_cipher_deinit(cipher_hnd
);
486 return gnutls_error_to_ntstatus(rc
,
487 NT_STATUS_CRYPTO_SYSTEM_INVALID
);
494 AES encrypt a password buffer using the session key
496 NTSTATUS
netlogon_creds_aes_encrypt(struct netlogon_creds_CredentialState
*creds
,
500 gnutls_cipher_hd_t cipher_hnd
= NULL
;
501 gnutls_datum_t key
= {
502 .data
= creds
->session_key
,
503 .size
= sizeof(creds
->session_key
),
506 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8
);
507 uint8_t _iv
[iv_size
];
508 gnutls_datum_t iv
= {
516 rc
= gnutls_cipher_init(&cipher_hnd
,
517 GNUTLS_CIPHER_AES_128_CFB8
,
521 return gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
524 rc
= gnutls_cipher_encrypt(cipher_hnd
, data
, len
);
525 gnutls_cipher_deinit(cipher_hnd
);
527 return gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
534 AES decrypt a password buffer using the session key
536 NTSTATUS
netlogon_creds_aes_decrypt(struct netlogon_creds_CredentialState
*creds
, uint8_t *data
, size_t len
)
538 gnutls_cipher_hd_t cipher_hnd
= NULL
;
539 gnutls_datum_t key
= {
540 .data
= creds
->session_key
,
541 .size
= sizeof(creds
->session_key
),
544 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8
);
545 uint8_t _iv
[iv_size
];
546 gnutls_datum_t iv
= {
554 rc
= gnutls_cipher_init(&cipher_hnd
,
555 GNUTLS_CIPHER_AES_128_CFB8
,
559 return gnutls_error_to_ntstatus(rc
,
560 NT_STATUS_CRYPTO_SYSTEM_INVALID
);
563 rc
= gnutls_cipher_decrypt(cipher_hnd
, data
, len
);
564 gnutls_cipher_deinit(cipher_hnd
);
566 return gnutls_error_to_ntstatus(rc
,
567 NT_STATUS_CRYPTO_SYSTEM_INVALID
);
573 static struct netlogon_creds_CredentialState
*
574 netlogon_creds_alloc(TALLOC_CTX
*mem_ctx
,
575 const char *client_account
,
576 const char *client_computer_name
,
577 uint16_t secure_channel_type
,
578 uint32_t client_requested_flags
,
579 const struct dom_sid
*client_sid
,
580 uint32_t negotiate_flags
)
582 struct netlogon_creds_CredentialState
*creds
= NULL
;
583 struct timeval tv
= timeval_current();
584 NTTIME now
= timeval_to_nttime(&tv
);
585 const char *name
= NULL
;
587 creds
= talloc_zero(mem_ctx
, struct netlogon_creds_CredentialState
);
592 if (client_sid
== NULL
) {
593 creds
->sequence
= tv
.tv_sec
;
595 creds
->negotiate_flags
= negotiate_flags
;
596 creds
->secure_channel_type
= secure_channel_type
;
598 creds
->computer_name
= talloc_strdup(creds
, client_computer_name
);
599 if (!creds
->computer_name
) {
603 creds
->account_name
= talloc_strdup(creds
, client_account
);
604 if (!creds
->account_name
) {
609 creds
->client_requested_flags
= client_requested_flags
;
610 creds
->auth_time
= now
;
611 if (client_sid
!= NULL
) {
612 creds
->client_sid
= *client_sid
;
614 creds
->client_sid
= global_sid_NULL
;
617 name
= talloc_get_name(creds
);
618 _talloc_keep_secret(creds
, name
);
622 struct netlogon_creds_CredentialState
*netlogon_creds_kerberos_init(TALLOC_CTX
*mem_ctx
,
623 const char *client_account
,
624 const char *client_computer_name
,
625 uint16_t secure_channel_type
,
626 uint32_t client_requested_flags
,
627 const struct dom_sid
*client_sid
,
628 uint32_t negotiate_flags
)
630 struct netlogon_creds_CredentialState
*creds
= NULL
;
632 creds
= netlogon_creds_alloc(mem_ctx
,
634 client_computer_name
,
636 client_requested_flags
,
644 * Some Windows versions used
645 * NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
646 * as a dummy flag in ServerAuthenticate3,
647 * so we should not use
648 * NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
649 * for any logic decisions.
651 * So we use a dedicated bool that
652 * is only set if ServerAuthenticateKerberos
653 * was really used. And for that we assert
654 * that NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
657 creds
->authenticate_kerberos
= true;
660 * This should not be required, but we better
661 * make sure we would not use a zero session key...
663 * It seems that's what Windows is also doing...
664 * as the values in netr_ServerPasswordGet() are
665 * encrypted in random ways if NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
666 * is missing in netr_ServerAuthenticateKerberos().
668 generate_nonce_buffer(creds
->session_key
,
669 ARRAY_SIZE(creds
->session_key
));
670 generate_nonce_buffer(creds
->seed
.data
,
671 ARRAY_SIZE(creds
->seed
.data
));
672 generate_nonce_buffer(creds
->client
.data
,
673 ARRAY_SIZE(creds
->client
.data
));
674 generate_nonce_buffer(creds
->server
.data
,
675 ARRAY_SIZE(creds
->server
.data
));
680 /*****************************************************************
681 The above functions are common to the client and server interface
682 next comes the client specific functions
683 ******************************************************************/
686 initialise the credentials chain and return the first client
690 struct netlogon_creds_CredentialState
*netlogon_creds_client_init(TALLOC_CTX
*mem_ctx
,
691 const char *client_account
,
692 const char *client_computer_name
,
693 uint16_t secure_channel_type
,
694 const struct netr_Credential
*client_challenge
,
695 const struct netr_Credential
*server_challenge
,
696 const struct samr_Password
*machine_password
,
697 struct netr_Credential
*initial_credential
,
698 uint32_t client_requested_flags
,
699 uint32_t negotiate_flags
)
701 struct netlogon_creds_CredentialState
*creds
= NULL
;
704 creds
= netlogon_creds_alloc(mem_ctx
,
706 client_computer_name
,
708 client_requested_flags
,
709 NULL
, /* client_sid */
715 dump_data_pw("Client chall", client_challenge
->data
, sizeof(client_challenge
->data
));
716 dump_data_pw("Server chall", server_challenge
->data
, sizeof(server_challenge
->data
));
717 dump_data_pw("Machine Pass", machine_password
->hash
, sizeof(machine_password
->hash
));
719 if (negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
720 status
= netlogon_creds_init_hmac_sha256(creds
,
724 if (!NT_STATUS_IS_OK(status
)) {
728 } else if (negotiate_flags
& NETLOGON_NEG_STRONG_KEYS
) {
729 status
= netlogon_creds_init_128bit(creds
,
733 if (!NT_STATUS_IS_OK(status
)) {
738 status
= netlogon_creds_init_64bit(creds
,
742 if (!NT_STATUS_IS_OK(status
)) {
748 status
= netlogon_creds_first_step(creds
,
751 if (!NT_STATUS_IS_OK(status
)) {
756 dump_data_pw("Session key", creds
->session_key
, 16);
757 dump_data_pw("Credential ", creds
->client
.data
, 8);
759 *initial_credential
= creds
->client
;
764 step the credentials to the next element in the chain, updating the
765 current client and server credentials and the seed
767 produce the next authenticator in the sequence ready to send to
771 netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState
*creds
,
772 struct netr_Authenticator
*next
)
774 uint32_t t32n
= (uint32_t)time(NULL
);
778 * we always increment and ignore an overflow here
780 creds
->sequence
+= 2;
782 if (t32n
> creds
->sequence
) {
784 * we may increment more
786 creds
->sequence
= t32n
;
788 uint32_t d
= creds
->sequence
- t32n
;
790 if (d
>= INT32_MAX
) {
792 * got an overflow of time_t vs. uint32_t
794 creds
->sequence
= t32n
;
798 status
= netlogon_creds_step(creds
);
799 if (!NT_STATUS_IS_OK(status
)) {
803 next
->cred
= creds
->client
;
804 next
->timestamp
= creds
->sequence
;
810 check that a credentials reply from a server is correct
812 NTSTATUS
netlogon_creds_client_verify(struct netlogon_creds_CredentialState
*creds
,
813 const struct netr_Credential
*received_credentials
,
814 enum dcerpc_AuthType auth_type
,
815 enum dcerpc_AuthLevel auth_level
)
818 bool skip_crypto
= false;
820 status
= netlogon_creds_no_step_check(creds
,
824 if (!NT_STATUS_IS_OK(status
)) {
832 if (!received_credentials
||
833 !mem_equal_const_time(received_credentials
->data
, creds
->server
.data
, 8)) {
834 DEBUG(2,("credentials check failed\n"));
835 return NT_STATUS_ACCESS_DENIED
;
840 bool netlogon_creds_client_check(struct netlogon_creds_CredentialState
*creds
,
841 const struct netr_Credential
*received_credentials
)
843 enum dcerpc_AuthType auth_type
= DCERPC_AUTH_TYPE_NONE
;
844 enum dcerpc_AuthLevel auth_level
= DCERPC_AUTH_LEVEL_NONE
;
847 status
= netlogon_creds_client_verify(creds
,
848 received_credentials
,
851 if (!NT_STATUS_IS_OK(status
)) {
859 /*****************************************************************
860 The above functions are common to the client and server interface
861 next comes the server specific functions
862 ******************************************************************/
865 check that a credentials reply from a server is correct
867 static bool netlogon_creds_server_check_internal(const struct netlogon_creds_CredentialState
*creds
,
868 const struct netr_Credential
*received_credentials
)
870 if (!mem_equal_const_time(received_credentials
->data
, creds
->client
.data
, 8)) {
871 DEBUG(2,("credentials check failed\n"));
872 dump_data_pw("client creds", creds
->client
.data
, 8);
873 dump_data_pw("calc creds", received_credentials
->data
, 8);
880 initialise the credentials chain and return the first server
883 struct netlogon_creds_CredentialState
*netlogon_creds_server_init(TALLOC_CTX
*mem_ctx
,
884 const char *client_account
,
885 const char *client_computer_name
,
886 uint16_t secure_channel_type
,
887 const struct netr_Credential
*client_challenge
,
888 const struct netr_Credential
*server_challenge
,
889 const struct samr_Password
*machine_password
,
890 const struct netr_Credential
*credentials_in
,
891 struct netr_Credential
*credentials_out
,
892 uint32_t client_requested_flags
,
893 const struct dom_sid
*client_sid
,
894 uint32_t negotiate_flags
)
896 struct netlogon_creds_CredentialState
*creds
= NULL
;
900 creds
= netlogon_creds_alloc(mem_ctx
,
902 client_computer_name
,
904 client_requested_flags
,
911 dump_data_pw("Client chall", client_challenge
->data
, sizeof(client_challenge
->data
));
912 dump_data_pw("Server chall", server_challenge
->data
, sizeof(server_challenge
->data
));
913 dump_data_pw("Machine Pass", machine_password
->hash
, sizeof(machine_password
->hash
));
915 ok
= netlogon_creds_is_random_challenge(client_challenge
);
917 DBG_WARNING("CVE-2020-1472(ZeroLogon): "
918 "non-random client challenge rejected for "
919 "client_account[%s] client_computer_name[%s]\n",
920 log_escape(mem_ctx
, client_account
),
921 log_escape(mem_ctx
, client_computer_name
));
922 dump_data(DBGLVL_WARNING
,
923 client_challenge
->data
,
924 sizeof(client_challenge
->data
));
929 if (negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
930 status
= netlogon_creds_init_hmac_sha256(creds
,
934 if (!NT_STATUS_IS_OK(status
)) {
938 } else if (negotiate_flags
& NETLOGON_NEG_STRONG_KEYS
) {
939 status
= netlogon_creds_init_128bit(creds
,
943 if (!NT_STATUS_IS_OK(status
)) {
948 status
= netlogon_creds_init_64bit(creds
,
952 if (!NT_STATUS_IS_OK(status
)) {
958 status
= netlogon_creds_first_step(creds
,
961 if (!NT_STATUS_IS_OK(status
)) {
966 dump_data_pw("Session key", creds
->session_key
, 16);
967 dump_data_pw("Client Credential ", creds
->client
.data
, 8);
968 dump_data_pw("Server Credential ", creds
->server
.data
, 8);
970 dump_data_pw("Credentials in", credentials_in
->data
, sizeof(credentials_in
->data
));
972 /* And before we leak information about the machine account
973 * password, check that they got the first go right */
974 if (!netlogon_creds_server_check_internal(creds
, credentials_in
)) {
979 *credentials_out
= creds
->server
;
981 dump_data_pw("Credentials out", credentials_out
->data
, sizeof(credentials_out
->data
));
986 NTSTATUS
netlogon_creds_server_step_check(struct netlogon_creds_CredentialState
*creds
,
987 const struct netr_Authenticator
*received_authenticator
,
988 struct netr_Authenticator
*return_authenticator
,
989 enum dcerpc_AuthType auth_type
,
990 enum dcerpc_AuthLevel auth_level
)
993 bool skip_crypto
= false;
995 if (!received_authenticator
|| !return_authenticator
) {
996 return NT_STATUS_INVALID_PARAMETER
;
999 status
= netlogon_creds_no_step_check(creds
,
1003 if (!NT_STATUS_IS_OK(status
)) {
1004 ZERO_STRUCTP(return_authenticator
);
1008 ZERO_STRUCTP(return_authenticator
);
1009 return NT_STATUS_OK
;
1012 creds
->sequence
= received_authenticator
->timestamp
;
1013 status
= netlogon_creds_step(creds
);
1014 if (!NT_STATUS_IS_OK(status
)) {
1015 ZERO_STRUCTP(return_authenticator
);
1019 if (netlogon_creds_server_check_internal(creds
, &received_authenticator
->cred
)) {
1020 return_authenticator
->cred
= creds
->server
;
1021 return_authenticator
->timestamp
= 0;
1022 return NT_STATUS_OK
;
1024 ZERO_STRUCTP(return_authenticator
);
1025 return NT_STATUS_ACCESS_DENIED
;
1029 static NTSTATUS
netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_CredentialState
*creds
,
1030 uint16_t validation_level
,
1031 union netr_Validation
*validation
,
1032 enum dcerpc_AuthType auth_type
,
1033 enum dcerpc_AuthLevel auth_level
,
1036 struct netr_SamBaseInfo
*base
= NULL
;
1038 bool skip_crypto
= false;
1040 if (validation
== NULL
) {
1041 return NT_STATUS_INVALID_PARAMETER
;
1044 switch (validation_level
) {
1046 if (validation
->sam2
) {
1047 base
= &validation
->sam2
->base
;
1051 if (validation
->sam3
) {
1052 base
= &validation
->sam3
->base
;
1056 /* NetlogonValidationGenericInfo2 */
1057 if (validation
->generic
!= NULL
&&
1058 validation
->generic
->length
== 0)
1062 * KERB_VERIFY_PAC_REQUEST there's
1063 * not response, so there's nothing
1066 return NT_STATUS_OK
;
1070 * We don't know if encryption is
1071 * required or not yet.
1073 * We would have to do tests
1074 * with DIGEST_VALIDATION_RESP
1076 * But as we don't support that
1077 * yet, we just return an error
1081 return NT_STATUS_INTERNAL_ERROR
;
1083 if (validation
->sam6
) {
1084 base
= &validation
->sam6
->base
;
1088 /* NetlogonValidationTicketLogon */
1089 return NT_STATUS_OK
;
1091 /* If we can't find it, we can't very well decrypt it */
1092 return NT_STATUS_INVALID_INFO_CLASS
;
1096 return NT_STATUS_INVALID_INFO_CLASS
;
1099 status
= netlogon_creds_no_buffer_crypt(creds
,
1103 if (!NT_STATUS_IS_OK(status
)) {
1107 /* find and decrypt the session keys, return in parameters above */
1108 if (skip_crypto
|| validation_level
== 6) {
1109 /* they aren't encrypted! */
1110 } else if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1112 * Don't crypt an all-zero key, it would give away
1113 * the NETLOGON pipe session key
1115 * But for ServerAuthenticateKerberos we don't care
1116 * as we use a random key
1118 if (creds
->authenticate_kerberos
||
1119 !all_zero(base
->key
.key
, sizeof(base
->key
.key
))) {
1121 status
= netlogon_creds_aes_encrypt(
1124 sizeof(base
->key
.key
));
1126 status
= netlogon_creds_aes_decrypt(
1129 sizeof(base
->key
.key
));
1131 if (!NT_STATUS_IS_OK(status
)) {
1136 if (creds
->authenticate_kerberos
||
1137 !all_zero(base
->LMSessKey
.key
,
1138 sizeof(base
->LMSessKey
.key
))) {
1140 status
= netlogon_creds_aes_encrypt(
1142 base
->LMSessKey
.key
,
1143 sizeof(base
->LMSessKey
.key
));
1145 status
= netlogon_creds_aes_decrypt(
1147 base
->LMSessKey
.key
,
1148 sizeof(base
->LMSessKey
.key
));
1150 if (!NT_STATUS_IS_OK(status
)) {
1154 } else if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
1156 * Don't crypt an all-zero key, it would give away
1157 * the NETLOGON pipe session key
1159 * But for ServerAuthenticateKerberos we don't care
1160 * as we use a random key
1162 if (creds
->authenticate_kerberos
||
1163 !all_zero(base
->key
.key
, sizeof(base
->key
.key
))) {
1164 status
= netlogon_creds_arcfour_crypt(creds
,
1166 sizeof(base
->key
.key
));
1167 if (!NT_STATUS_IS_OK(status
)) {
1172 if (creds
->authenticate_kerberos
||
1173 !all_zero(base
->LMSessKey
.key
,
1174 sizeof(base
->LMSessKey
.key
))) {
1175 status
= netlogon_creds_arcfour_crypt(creds
,
1176 base
->LMSessKey
.key
,
1177 sizeof(base
->LMSessKey
.key
));
1178 if (!NT_STATUS_IS_OK(status
)) {
1184 * Don't crypt an all-zero key, it would give away
1185 * the NETLOGON pipe session key
1187 * But for ServerAuthenticateKerberos we don't care
1188 * as we use a random key
1190 if (creds
->authenticate_kerberos
||
1191 !all_zero(base
->LMSessKey
.key
,
1192 sizeof(base
->LMSessKey
.key
))) {
1194 status
= netlogon_creds_des_encrypt_LMKey(creds
,
1197 status
= netlogon_creds_des_decrypt_LMKey(creds
,
1200 if (!NT_STATUS_IS_OK(status
)) {
1206 return NT_STATUS_OK
;
1209 NTSTATUS
netlogon_creds_decrypt_samlogon_validation(struct netlogon_creds_CredentialState
*creds
,
1210 uint16_t validation_level
,
1211 union netr_Validation
*validation
,
1212 enum dcerpc_AuthType auth_type
,
1213 enum dcerpc_AuthLevel auth_level
)
1215 return netlogon_creds_crypt_samlogon_validation(creds
,
1223 NTSTATUS
netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_CredentialState
*creds
,
1224 uint16_t validation_level
,
1225 union netr_Validation
*validation
,
1226 enum dcerpc_AuthType auth_type
,
1227 enum dcerpc_AuthLevel auth_level
)
1229 return netlogon_creds_crypt_samlogon_validation(creds
,
1237 static NTSTATUS
netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_CredentialState
*creds
,
1238 enum netr_LogonInfoClass level
,
1239 union netr_LogonLevel
*logon
,
1240 enum dcerpc_AuthType auth_type
,
1241 enum dcerpc_AuthLevel auth_level
,
1245 bool skip_crypto
= false;
1247 status
= netlogon_creds_no_buffer_crypt(creds
,
1251 if (!NT_STATUS_IS_OK(status
)) {
1255 if (logon
== NULL
) {
1256 return NT_STATUS_INVALID_PARAMETER
;
1260 case NetlogonInteractiveInformation
:
1261 case NetlogonInteractiveTransitiveInformation
:
1262 case NetlogonServiceInformation
:
1263 case NetlogonServiceTransitiveInformation
:
1264 if (logon
->password
== NULL
) {
1265 return NT_STATUS_INVALID_PARAMETER
;
1272 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1275 h
= logon
->password
->lmpassword
.hash
;
1276 if (!all_zero(h
, 16)) {
1278 status
= netlogon_creds_aes_encrypt(
1283 status
= netlogon_creds_aes_decrypt(
1288 if (!NT_STATUS_IS_OK(status
)) {
1293 h
= logon
->password
->ntpassword
.hash
;
1294 if (!all_zero(h
, 16)) {
1296 status
= netlogon_creds_aes_encrypt(creds
,
1300 status
= netlogon_creds_aes_decrypt(creds
,
1304 if (!NT_STATUS_IS_OK(status
)) {
1308 } else if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
1311 h
= logon
->password
->lmpassword
.hash
;
1312 if (!all_zero(h
, 16)) {
1313 status
= netlogon_creds_arcfour_crypt(creds
,
1316 if (!NT_STATUS_IS_OK(status
)) {
1321 h
= logon
->password
->ntpassword
.hash
;
1322 if (!all_zero(h
, 16)) {
1323 status
= netlogon_creds_arcfour_crypt(creds
,
1326 if (!NT_STATUS_IS_OK(status
)) {
1331 struct samr_Password
*p
;
1333 p
= &logon
->password
->lmpassword
;
1334 if (!all_zero(p
->hash
, 16)) {
1336 status
= netlogon_creds_des_encrypt(creds
, p
);
1338 status
= netlogon_creds_des_decrypt(creds
, p
);
1340 if (!NT_STATUS_IS_OK(status
)) {
1344 p
= &logon
->password
->ntpassword
;
1345 if (!all_zero(p
->hash
, 16)) {
1347 status
= netlogon_creds_des_encrypt(creds
, p
);
1349 status
= netlogon_creds_des_decrypt(creds
, p
);
1351 if (!NT_STATUS_IS_OK(status
)) {
1358 case NetlogonNetworkInformation
:
1359 case NetlogonNetworkTransitiveInformation
:
1362 case NetlogonGenericInformation
:
1363 if (logon
->generic
== NULL
) {
1364 return NT_STATUS_INVALID_PARAMETER
;
1371 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1373 status
= netlogon_creds_aes_encrypt(
1375 logon
->generic
->data
,
1376 logon
->generic
->length
);
1378 status
= netlogon_creds_aes_decrypt(
1380 logon
->generic
->data
,
1381 logon
->generic
->length
);
1383 if (!NT_STATUS_IS_OK(status
)) {
1386 } else if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
1387 status
= netlogon_creds_arcfour_crypt(creds
,
1388 logon
->generic
->data
,
1389 logon
->generic
->length
);
1390 if (!NT_STATUS_IS_OK(status
)) {
1393 } else if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
1395 * Using DES to verify kerberos tickets makes no sense,
1396 * but if the connection is encrypted we don't care...
1398 return NT_STATUS_INVALID_PARAMETER
;
1402 case NetlogonTicketLogonInformation
:
1406 return NT_STATUS_OK
;
1409 NTSTATUS
netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState
*creds
,
1410 enum netr_LogonInfoClass level
,
1411 union netr_LogonLevel
*logon
,
1412 enum dcerpc_AuthType auth_type
,
1413 enum dcerpc_AuthLevel auth_level
)
1415 return netlogon_creds_crypt_samlogon_logon(creds
,
1423 NTSTATUS
netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState
*creds
,
1424 enum netr_LogonInfoClass level
,
1425 union netr_LogonLevel
*logon
,
1426 enum dcerpc_AuthType auth_type
,
1427 enum dcerpc_AuthLevel auth_level
)
1429 return netlogon_creds_crypt_samlogon_logon(creds
,
1437 static NTSTATUS
netlogon_creds_crypt_samr_Password(
1438 struct netlogon_creds_CredentialState
*creds
,
1439 struct samr_Password
*pass
,
1440 enum dcerpc_AuthType auth_type
,
1441 enum dcerpc_AuthLevel auth_level
,
1445 bool skip_crypto
= false;
1447 status
= netlogon_creds_no_buffer_crypt(creds
,
1451 if (!NT_STATUS_IS_OK(status
)) {
1456 return NT_STATUS_OK
;
1459 if (all_zero(pass
->hash
, ARRAY_SIZE(pass
->hash
))) {
1460 return NT_STATUS_OK
;
1464 * Even with NETLOGON_NEG_SUPPORTS_AES or
1465 * NETLOGON_NEG_ARCFOUR this uses DES
1469 return netlogon_creds_des_encrypt(creds
, pass
);
1472 return netlogon_creds_des_decrypt(creds
, pass
);
1475 NTSTATUS
netlogon_creds_decrypt_samr_Password(struct netlogon_creds_CredentialState
*creds
,
1476 struct samr_Password
*pass
,
1477 enum dcerpc_AuthType auth_type
,
1478 enum dcerpc_AuthLevel auth_level
)
1480 return netlogon_creds_crypt_samr_Password(creds
,
1487 NTSTATUS
netlogon_creds_encrypt_samr_Password(struct netlogon_creds_CredentialState
*creds
,
1488 struct samr_Password
*pass
,
1489 enum dcerpc_AuthType auth_type
,
1490 enum dcerpc_AuthLevel auth_level
)
1492 return netlogon_creds_crypt_samr_Password(creds
,
1499 static NTSTATUS
netlogon_creds_crypt_samr_CryptPassword(
1500 struct netlogon_creds_CredentialState
*creds
,
1501 struct samr_CryptPassword
*pass
,
1502 enum dcerpc_AuthType auth_type
,
1503 enum dcerpc_AuthLevel auth_level
,
1507 bool skip_crypto
= false;
1509 status
= netlogon_creds_no_buffer_crypt(creds
,
1513 if (!NT_STATUS_IS_OK(status
)) {
1518 return NT_STATUS_OK
;
1521 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1523 return netlogon_creds_aes_encrypt(creds
,
1525 ARRAY_SIZE(pass
->data
));
1528 return netlogon_creds_aes_decrypt(creds
,
1530 ARRAY_SIZE(pass
->data
));
1533 if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
1534 return netlogon_creds_arcfour_crypt(creds
,
1536 ARRAY_SIZE(pass
->data
));
1540 * Using DES to verify to encrypt the password makes no sense,
1541 * but if the connection is encrypted we don't care...
1543 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
1544 return NT_STATUS_INVALID_PARAMETER
;
1547 return NT_STATUS_OK
;
1550 NTSTATUS
netlogon_creds_decrypt_samr_CryptPassword(struct netlogon_creds_CredentialState
*creds
,
1551 struct samr_CryptPassword
*pass
,
1552 enum dcerpc_AuthType auth_type
,
1553 enum dcerpc_AuthLevel auth_level
)
1555 return netlogon_creds_crypt_samr_CryptPassword(creds
,
1562 NTSTATUS
netlogon_creds_encrypt_samr_CryptPassword(struct netlogon_creds_CredentialState
*creds
,
1563 struct samr_CryptPassword
*pass
,
1564 enum dcerpc_AuthType auth_type
,
1565 enum dcerpc_AuthLevel auth_level
)
1567 return netlogon_creds_crypt_samr_CryptPassword(creds
,
1574 static NTSTATUS
netlogon_creds_crypt_SendToSam(
1575 struct netlogon_creds_CredentialState
*creds
,
1576 uint8_t *opaque_data
,
1577 size_t opaque_length
,
1578 enum dcerpc_AuthType auth_type
,
1579 enum dcerpc_AuthLevel auth_level
,
1583 bool skip_crypto
= false;
1585 status
= netlogon_creds_no_buffer_crypt(creds
,
1589 if (!NT_STATUS_IS_OK(status
)) {
1594 return NT_STATUS_OK
;
1597 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1599 return netlogon_creds_aes_encrypt(creds
,
1604 return netlogon_creds_aes_decrypt(creds
,
1609 if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
1610 return netlogon_creds_arcfour_crypt(creds
,
1616 * Using DES to verify to encrypt the data makes no sense,
1617 * but if the connection is encrypted we don't care...
1619 if (auth_level
!= DCERPC_AUTH_LEVEL_PRIVACY
) {
1620 return NT_STATUS_INVALID_PARAMETER
;
1623 return NT_STATUS_OK
;
1626 NTSTATUS
netlogon_creds_decrypt_SendToSam(struct netlogon_creds_CredentialState
*creds
,
1627 uint8_t *opaque_data
,
1628 size_t opaque_length
,
1629 enum dcerpc_AuthType auth_type
,
1630 enum dcerpc_AuthLevel auth_level
)
1632 return netlogon_creds_crypt_SendToSam(creds
,
1640 NTSTATUS
netlogon_creds_encrypt_SendToSam(struct netlogon_creds_CredentialState
*creds
,
1641 uint8_t *opaque_data
,
1642 size_t opaque_length
,
1643 enum dcerpc_AuthType auth_type
,
1644 enum dcerpc_AuthLevel auth_level
)
1646 return netlogon_creds_crypt_SendToSam(creds
,
1654 union netr_LogonLevel
*netlogon_creds_shallow_copy_logon(TALLOC_CTX
*mem_ctx
,
1655 enum netr_LogonInfoClass level
,
1656 const union netr_LogonLevel
*in
)
1658 union netr_LogonLevel
*out
;
1664 out
= talloc(mem_ctx
, union netr_LogonLevel
);
1672 case NetlogonInteractiveInformation
:
1673 case NetlogonInteractiveTransitiveInformation
:
1674 case NetlogonServiceInformation
:
1675 case NetlogonServiceTransitiveInformation
:
1676 if (in
->password
== NULL
) {
1680 out
->password
= talloc(out
, struct netr_PasswordInfo
);
1681 if (out
->password
== NULL
) {
1685 *out
->password
= *in
->password
;
1689 case NetlogonNetworkInformation
:
1690 case NetlogonNetworkTransitiveInformation
:
1693 case NetlogonGenericInformation
:
1694 if (in
->generic
== NULL
) {
1698 out
->generic
= talloc(out
, struct netr_GenericInfo
);
1699 if (out
->generic
== NULL
) {
1703 *out
->generic
= *in
->generic
;
1705 if (in
->generic
->data
== NULL
) {
1709 if (in
->generic
->length
== 0) {
1713 out
->generic
->data
= talloc_memdup(out
->generic
,
1715 in
->generic
->length
);
1716 if (out
->generic
->data
== NULL
) {
1723 case NetlogonTicketLogonInformation
:
1731 copy a netlogon_creds_CredentialState struct
1734 struct netlogon_creds_CredentialState
*netlogon_creds_copy(
1735 TALLOC_CTX
*mem_ctx
,
1736 const struct netlogon_creds_CredentialState
*creds_in
)
1738 struct netlogon_creds_CredentialState
*creds
= talloc_zero(mem_ctx
, struct netlogon_creds_CredentialState
);
1739 enum ndr_err_code ndr_err
;
1745 ndr_err
= ndr_deepcopy_struct(netlogon_creds_CredentialState
,
1746 creds_in
, creds
, creds
);
1747 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {