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 bool netlogon_creds_is_random_challenge(const struct netr_Credential
*challenge
)
36 * If none of the first 5 bytes of the client challenge is unique, the
37 * server MUST fail session-key negotiation without further processing
38 * of the following steps.
41 if (challenge
->data
[1] == challenge
->data
[0] &&
42 challenge
->data
[2] == challenge
->data
[0] &&
43 challenge
->data
[3] == challenge
->data
[0] &&
44 challenge
->data
[4] == challenge
->data
[0])
52 void netlogon_creds_random_challenge(struct netr_Credential
*challenge
)
54 ZERO_STRUCTP(challenge
);
55 while (!netlogon_creds_is_random_challenge(challenge
)) {
56 generate_random_buffer(challenge
->data
, sizeof(challenge
->data
));
60 static NTSTATUS
netlogon_creds_step_crypt(struct netlogon_creds_CredentialState
*creds
,
61 const struct netr_Credential
*in
,
62 struct netr_Credential
*out
)
67 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
68 memcpy(out
->data
, in
->data
, sizeof(out
->data
));
70 status
= netlogon_creds_aes_encrypt(creds
,
73 if (!NT_STATUS_IS_OK(status
)) {
77 rc
= des_crypt112(out
->data
, in
->data
, creds
->session_key
, SAMBA_GNUTLS_ENCRYPT
);
79 return gnutls_error_to_ntstatus(rc
,
80 NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
88 initialise the credentials state for old-style 64 bit session keys
90 this call is made after the netr_ServerReqChallenge call
92 static NTSTATUS
netlogon_creds_init_64bit(struct netlogon_creds_CredentialState
*creds
,
93 const struct netr_Credential
*client_challenge
,
94 const struct netr_Credential
*server_challenge
,
95 const struct samr_Password
*machine_password
)
101 sum
[0] = IVAL(client_challenge
->data
, 0) + IVAL(server_challenge
->data
, 0);
102 sum
[1] = IVAL(client_challenge
->data
, 4) + IVAL(server_challenge
->data
, 4);
104 SIVAL(sum2
,0,sum
[0]);
105 SIVAL(sum2
,4,sum
[1]);
107 ZERO_ARRAY(creds
->session_key
);
109 rc
= des_crypt128(creds
->session_key
, sum2
, machine_password
->hash
);
111 return gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
118 initialise the credentials state for ADS-style 128 bit session keys
120 this call is made after the netr_ServerReqChallenge call
122 static NTSTATUS
netlogon_creds_init_128bit(struct netlogon_creds_CredentialState
*creds
,
123 const struct netr_Credential
*client_challenge
,
124 const struct netr_Credential
*server_challenge
,
125 const struct samr_Password
*machine_password
)
127 uint8_t zero
[4] = {0};
128 uint8_t tmp
[gnutls_hash_get_len(GNUTLS_DIG_MD5
)];
129 gnutls_hash_hd_t hash_hnd
= NULL
;
132 ZERO_ARRAY(creds
->session_key
);
134 rc
= gnutls_hash_init(&hash_hnd
, GNUTLS_DIG_MD5
);
136 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
139 rc
= gnutls_hash(hash_hnd
, zero
, sizeof(zero
));
141 gnutls_hash_deinit(hash_hnd
, NULL
);
142 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
144 rc
= gnutls_hash(hash_hnd
, client_challenge
->data
, 8);
146 gnutls_hash_deinit(hash_hnd
, NULL
);
147 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
149 rc
= gnutls_hash(hash_hnd
, server_challenge
->data
, 8);
151 gnutls_hash_deinit(hash_hnd
, NULL
);
152 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
155 gnutls_hash_deinit(hash_hnd
, tmp
);
157 /* This doesn't require HMAC MD5 RFC2104 as the hash is only 16 bytes */
158 rc
= gnutls_hmac_fast(GNUTLS_MAC_MD5
,
159 machine_password
->hash
,
160 sizeof(machine_password
->hash
),
167 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
174 initialise the credentials state for AES/HMAC-SHA256-style 128 bit session keys
176 this call is made after the netr_ServerReqChallenge call
178 static NTSTATUS
netlogon_creds_init_hmac_sha256(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
)
183 gnutls_hmac_hd_t hmac_hnd
= NULL
;
184 uint8_t digest
[gnutls_hmac_get_len(GNUTLS_MAC_SHA256
)];
187 ZERO_ARRAY(creds
->session_key
);
189 rc
= gnutls_hmac_init(&hmac_hnd
,
191 machine_password
->hash
,
192 sizeof(machine_password
->hash
));
194 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
196 rc
= gnutls_hmac(hmac_hnd
,
197 client_challenge
->data
,
200 gnutls_hmac_deinit(hmac_hnd
, NULL
);
201 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
203 rc
= gnutls_hmac(hmac_hnd
,
204 server_challenge
->data
,
207 gnutls_hmac_deinit(hmac_hnd
, NULL
);
208 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
210 gnutls_hmac_deinit(hmac_hnd
, digest
);
212 memcpy(creds
->session_key
, digest
, sizeof(creds
->session_key
));
219 static NTSTATUS
netlogon_creds_first_step(struct netlogon_creds_CredentialState
*creds
,
220 const struct netr_Credential
*client_challenge
,
221 const struct netr_Credential
*server_challenge
)
225 status
= netlogon_creds_step_crypt(creds
,
228 if (!NT_STATUS_IS_OK(status
)) {
232 status
= netlogon_creds_step_crypt(creds
,
235 if (!NT_STATUS_IS_OK(status
)) {
239 creds
->seed
= creds
->client
;
245 step the credentials to the next element in the chain, updating the
246 current client and server credentials and the seed
248 static NTSTATUS
netlogon_creds_step(struct netlogon_creds_CredentialState
*creds
)
250 struct netr_Credential time_cred
;
253 DEBUG(5,("\tseed %08x:%08x\n",
254 IVAL(creds
->seed
.data
, 0), IVAL(creds
->seed
.data
, 4)));
256 SIVAL(time_cred
.data
, 0, IVAL(creds
->seed
.data
, 0) + creds
->sequence
);
257 SIVAL(time_cred
.data
, 4, IVAL(creds
->seed
.data
, 4));
259 DEBUG(5,("\tseed+time %08x:%08x\n", IVAL(time_cred
.data
, 0), IVAL(time_cred
.data
, 4)));
261 status
= netlogon_creds_step_crypt(creds
,
264 if (!NT_STATUS_IS_OK(status
)) {
268 DEBUG(5,("\tCLIENT %08x:%08x\n",
269 IVAL(creds
->client
.data
, 0), IVAL(creds
->client
.data
, 4)));
271 SIVAL(time_cred
.data
, 0, IVAL(creds
->seed
.data
, 0) + creds
->sequence
+ 1);
272 SIVAL(time_cred
.data
, 4, IVAL(creds
->seed
.data
, 4));
274 DEBUG(5,("\tseed+time+1 %08x:%08x\n",
275 IVAL(time_cred
.data
, 0), IVAL(time_cred
.data
, 4)));
277 status
= netlogon_creds_step_crypt(creds
, &time_cred
, &creds
->server
);
278 if (!NT_STATUS_IS_OK(status
)) {
282 DEBUG(5,("\tSERVER %08x:%08x\n",
283 IVAL(creds
->server
.data
, 0), IVAL(creds
->server
.data
, 4)));
285 creds
->seed
= time_cred
;
291 DES encrypt a 8 byte LMSessionKey buffer using the Netlogon session key
293 NTSTATUS
netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState
*creds
,
294 struct netr_LMSessionKey
*key
)
297 struct netr_LMSessionKey tmp
;
299 rc
= des_crypt56_gnutls(tmp
.key
, key
->key
, creds
->session_key
, SAMBA_GNUTLS_ENCRYPT
);
301 return gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
309 DES decrypt a 8 byte LMSessionKey buffer using the Netlogon session key
311 NTSTATUS
netlogon_creds_des_decrypt_LMKey(struct netlogon_creds_CredentialState
*creds
,
312 struct netr_LMSessionKey
*key
)
315 struct netr_LMSessionKey tmp
;
317 rc
= des_crypt56_gnutls(tmp
.key
, key
->key
, creds
->session_key
, SAMBA_GNUTLS_DECRYPT
);
319 return gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
327 DES encrypt a 16 byte password buffer using the session key
329 NTSTATUS
netlogon_creds_des_encrypt(struct netlogon_creds_CredentialState
*creds
,
330 struct samr_Password
*pass
)
332 struct samr_Password tmp
;
335 rc
= des_crypt112_16(tmp
.hash
, pass
->hash
, creds
->session_key
, SAMBA_GNUTLS_ENCRYPT
);
337 return gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
345 DES decrypt a 16 byte password buffer using the session key
347 NTSTATUS
netlogon_creds_des_decrypt(struct netlogon_creds_CredentialState
*creds
,
348 struct samr_Password
*pass
)
350 struct samr_Password tmp
;
353 rc
= des_crypt112_16(tmp
.hash
, pass
->hash
, creds
->session_key
, SAMBA_GNUTLS_DECRYPT
);
355 return gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
363 ARCFOUR encrypt/decrypt a password buffer using the session key
365 NTSTATUS
netlogon_creds_arcfour_crypt(struct netlogon_creds_CredentialState
*creds
,
369 gnutls_cipher_hd_t cipher_hnd
= NULL
;
370 gnutls_datum_t session_key
= {
371 .data
= creds
->session_key
,
372 .size
= sizeof(creds
->session_key
),
376 rc
= gnutls_cipher_init(&cipher_hnd
,
377 GNUTLS_CIPHER_ARCFOUR_128
,
381 return gnutls_error_to_ntstatus(rc
,
382 NT_STATUS_CRYPTO_SYSTEM_INVALID
);
384 rc
= gnutls_cipher_encrypt(cipher_hnd
,
387 gnutls_cipher_deinit(cipher_hnd
);
389 return gnutls_error_to_ntstatus(rc
,
390 NT_STATUS_CRYPTO_SYSTEM_INVALID
);
397 AES encrypt a password buffer using the session key
399 NTSTATUS
netlogon_creds_aes_encrypt(struct netlogon_creds_CredentialState
*creds
,
403 gnutls_cipher_hd_t cipher_hnd
= NULL
;
404 gnutls_datum_t key
= {
405 .data
= creds
->session_key
,
406 .size
= sizeof(creds
->session_key
),
409 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8
);
410 uint8_t _iv
[iv_size
];
411 gnutls_datum_t iv
= {
419 rc
= gnutls_cipher_init(&cipher_hnd
,
420 GNUTLS_CIPHER_AES_128_CFB8
,
424 return gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
427 rc
= gnutls_cipher_encrypt(cipher_hnd
, data
, len
);
428 gnutls_cipher_deinit(cipher_hnd
);
430 return gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
437 AES decrypt a password buffer using the session key
439 NTSTATUS
netlogon_creds_aes_decrypt(struct netlogon_creds_CredentialState
*creds
, uint8_t *data
, size_t len
)
441 gnutls_cipher_hd_t cipher_hnd
= NULL
;
442 gnutls_datum_t key
= {
443 .data
= creds
->session_key
,
444 .size
= sizeof(creds
->session_key
),
447 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8
);
448 uint8_t _iv
[iv_size
];
449 gnutls_datum_t iv
= {
457 rc
= gnutls_cipher_init(&cipher_hnd
,
458 GNUTLS_CIPHER_AES_128_CFB8
,
462 return gnutls_error_to_ntstatus(rc
,
463 NT_STATUS_CRYPTO_SYSTEM_INVALID
);
466 rc
= gnutls_cipher_decrypt(cipher_hnd
, data
, len
);
467 gnutls_cipher_deinit(cipher_hnd
);
469 return gnutls_error_to_ntstatus(rc
,
470 NT_STATUS_CRYPTO_SYSTEM_INVALID
);
476 /*****************************************************************
477 The above functions are common to the client and server interface
478 next comes the client specific functions
479 ******************************************************************/
482 initialise the credentials chain and return the first client
486 struct netlogon_creds_CredentialState
*netlogon_creds_client_init(TALLOC_CTX
*mem_ctx
,
487 const char *client_account
,
488 const char *client_computer_name
,
489 uint16_t secure_channel_type
,
490 const struct netr_Credential
*client_challenge
,
491 const struct netr_Credential
*server_challenge
,
492 const struct samr_Password
*machine_password
,
493 struct netr_Credential
*initial_credential
,
494 uint32_t negotiate_flags
)
496 struct netlogon_creds_CredentialState
*creds
= talloc_zero(mem_ctx
, struct netlogon_creds_CredentialState
);
503 creds
->sequence
= time(NULL
);
504 creds
->negotiate_flags
= negotiate_flags
;
505 creds
->secure_channel_type
= secure_channel_type
;
507 creds
->computer_name
= talloc_strdup(creds
, client_computer_name
);
508 if (!creds
->computer_name
) {
512 creds
->account_name
= talloc_strdup(creds
, client_account
);
513 if (!creds
->account_name
) {
518 dump_data_pw("Client chall", client_challenge
->data
, sizeof(client_challenge
->data
));
519 dump_data_pw("Server chall", server_challenge
->data
, sizeof(server_challenge
->data
));
520 dump_data_pw("Machine Pass", machine_password
->hash
, sizeof(machine_password
->hash
));
522 if (negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
523 status
= netlogon_creds_init_hmac_sha256(creds
,
527 if (!NT_STATUS_IS_OK(status
)) {
531 } else if (negotiate_flags
& NETLOGON_NEG_STRONG_KEYS
) {
532 status
= netlogon_creds_init_128bit(creds
,
536 if (!NT_STATUS_IS_OK(status
)) {
541 status
= netlogon_creds_init_64bit(creds
,
545 if (!NT_STATUS_IS_OK(status
)) {
551 status
= netlogon_creds_first_step(creds
,
554 if (!NT_STATUS_IS_OK(status
)) {
559 dump_data_pw("Session key", creds
->session_key
, 16);
560 dump_data_pw("Credential ", creds
->client
.data
, 8);
562 *initial_credential
= creds
->client
;
567 initialise the credentials structure with only a session key. The caller better know what they are doing!
570 struct netlogon_creds_CredentialState
*netlogon_creds_client_init_session_key(TALLOC_CTX
*mem_ctx
,
571 const uint8_t session_key
[16])
573 struct netlogon_creds_CredentialState
*creds
;
575 creds
= talloc_zero(mem_ctx
, struct netlogon_creds_CredentialState
);
580 memcpy(creds
->session_key
, session_key
, 16);
586 step the credentials to the next element in the chain, updating the
587 current client and server credentials and the seed
589 produce the next authenticator in the sequence ready to send to
593 netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState
*creds
,
594 struct netr_Authenticator
*next
)
596 uint32_t t32n
= (uint32_t)time(NULL
);
600 * we always increment and ignore an overflow here
602 creds
->sequence
+= 2;
604 if (t32n
> creds
->sequence
) {
606 * we may increment more
608 creds
->sequence
= t32n
;
610 uint32_t d
= creds
->sequence
- t32n
;
612 if (d
>= INT32_MAX
) {
614 * got an overflow of time_t vs. uint32_t
616 creds
->sequence
= t32n
;
620 status
= netlogon_creds_step(creds
);
621 if (!NT_STATUS_IS_OK(status
)) {
625 next
->cred
= creds
->client
;
626 next
->timestamp
= creds
->sequence
;
632 check that a credentials reply from a server is correct
634 bool netlogon_creds_client_check(struct netlogon_creds_CredentialState
*creds
,
635 const struct netr_Credential
*received_credentials
)
637 if (!received_credentials
||
638 !mem_equal_const_time(received_credentials
->data
, creds
->server
.data
, 8)) {
639 DEBUG(2,("credentials check failed\n"));
646 /*****************************************************************
647 The above functions are common to the client and server interface
648 next comes the server specific functions
649 ******************************************************************/
652 check that a credentials reply from a server is correct
654 static bool netlogon_creds_server_check_internal(const struct netlogon_creds_CredentialState
*creds
,
655 const struct netr_Credential
*received_credentials
)
657 if (!mem_equal_const_time(received_credentials
->data
, creds
->client
.data
, 8)) {
658 DEBUG(2,("credentials check failed\n"));
659 dump_data_pw("client creds", creds
->client
.data
, 8);
660 dump_data_pw("calc creds", received_credentials
->data
, 8);
667 initialise the credentials chain and return the first server
670 struct netlogon_creds_CredentialState
*netlogon_creds_server_init(TALLOC_CTX
*mem_ctx
,
671 const char *client_account
,
672 const char *client_computer_name
,
673 uint16_t secure_channel_type
,
674 const struct netr_Credential
*client_challenge
,
675 const struct netr_Credential
*server_challenge
,
676 const struct samr_Password
*machine_password
,
677 const struct netr_Credential
*credentials_in
,
678 struct netr_Credential
*credentials_out
,
679 uint32_t negotiate_flags
)
682 struct netlogon_creds_CredentialState
*creds
= talloc_zero(mem_ctx
, struct netlogon_creds_CredentialState
);
690 creds
->negotiate_flags
= negotiate_flags
;
691 creds
->secure_channel_type
= secure_channel_type
;
693 dump_data_pw("Client chall", client_challenge
->data
, sizeof(client_challenge
->data
));
694 dump_data_pw("Server chall", server_challenge
->data
, sizeof(server_challenge
->data
));
695 dump_data_pw("Machine Pass", machine_password
->hash
, sizeof(machine_password
->hash
));
697 ok
= netlogon_creds_is_random_challenge(client_challenge
);
699 DBG_WARNING("CVE-2020-1472(ZeroLogon): "
700 "non-random client challenge rejected for "
701 "client_account[%s] client_computer_name[%s]\n",
702 log_escape(mem_ctx
, client_account
),
703 log_escape(mem_ctx
, client_computer_name
));
704 dump_data(DBGLVL_WARNING
,
705 client_challenge
->data
,
706 sizeof(client_challenge
->data
));
711 creds
->computer_name
= talloc_strdup(creds
, client_computer_name
);
712 if (!creds
->computer_name
) {
716 creds
->account_name
= talloc_strdup(creds
, client_account
);
717 if (!creds
->account_name
) {
722 if (negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
723 status
= netlogon_creds_init_hmac_sha256(creds
,
727 if (!NT_STATUS_IS_OK(status
)) {
731 } else if (negotiate_flags
& NETLOGON_NEG_STRONG_KEYS
) {
732 status
= netlogon_creds_init_128bit(creds
,
736 if (!NT_STATUS_IS_OK(status
)) {
741 status
= netlogon_creds_init_64bit(creds
,
745 if (!NT_STATUS_IS_OK(status
)) {
751 status
= netlogon_creds_first_step(creds
,
754 if (!NT_STATUS_IS_OK(status
)) {
759 dump_data_pw("Session key", creds
->session_key
, 16);
760 dump_data_pw("Client Credential ", creds
->client
.data
, 8);
761 dump_data_pw("Server Credential ", creds
->server
.data
, 8);
763 dump_data_pw("Credentials in", credentials_in
->data
, sizeof(credentials_in
->data
));
765 /* And before we leak information about the machine account
766 * password, check that they got the first go right */
767 if (!netlogon_creds_server_check_internal(creds
, credentials_in
)) {
772 *credentials_out
= creds
->server
;
774 dump_data_pw("Credentials out", credentials_out
->data
, sizeof(credentials_out
->data
));
779 NTSTATUS
netlogon_creds_server_step_check(struct netlogon_creds_CredentialState
*creds
,
780 const struct netr_Authenticator
*received_authenticator
,
781 struct netr_Authenticator
*return_authenticator
)
785 if (!received_authenticator
|| !return_authenticator
) {
786 return NT_STATUS_INVALID_PARAMETER
;
790 return NT_STATUS_ACCESS_DENIED
;
793 creds
->sequence
= received_authenticator
->timestamp
;
794 status
= netlogon_creds_step(creds
);
795 if (!NT_STATUS_IS_OK(status
)) {
796 ZERO_STRUCTP(return_authenticator
);
800 if (netlogon_creds_server_check_internal(creds
, &received_authenticator
->cred
)) {
801 return_authenticator
->cred
= creds
->server
;
802 return_authenticator
->timestamp
= 0;
805 ZERO_STRUCTP(return_authenticator
);
806 return NT_STATUS_ACCESS_DENIED
;
810 static NTSTATUS
netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_CredentialState
*creds
,
811 uint16_t validation_level
,
812 union netr_Validation
*validation
,
815 struct netr_SamBaseInfo
*base
= NULL
;
818 if (validation
== NULL
) {
819 return NT_STATUS_INVALID_PARAMETER
;
822 switch (validation_level
) {
824 if (validation
->sam2
) {
825 base
= &validation
->sam2
->base
;
829 if (validation
->sam3
) {
830 base
= &validation
->sam3
->base
;
834 if (validation
->sam6
) {
835 base
= &validation
->sam6
->base
;
839 /* If we can't find it, we can't very well decrypt it */
840 return NT_STATUS_INVALID_INFO_CLASS
;
844 return NT_STATUS_INVALID_INFO_CLASS
;
847 /* find and decrypt the session keys, return in parameters above */
848 if (validation_level
== 6) {
849 /* they aren't encrypted! */
850 } else if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
851 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
852 if (!all_zero(base
->key
.key
, sizeof(base
->key
.key
))) {
854 status
= netlogon_creds_aes_encrypt(
857 sizeof(base
->key
.key
));
859 status
= netlogon_creds_aes_decrypt(
862 sizeof(base
->key
.key
));
864 if (!NT_STATUS_IS_OK(status
)) {
869 if (!all_zero(base
->LMSessKey
.key
,
870 sizeof(base
->LMSessKey
.key
))) {
872 status
= netlogon_creds_aes_encrypt(
875 sizeof(base
->LMSessKey
.key
));
877 status
= netlogon_creds_aes_decrypt(
880 sizeof(base
->LMSessKey
.key
));
882 if (!NT_STATUS_IS_OK(status
)) {
886 } else if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
887 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
888 if (!all_zero(base
->key
.key
, sizeof(base
->key
.key
))) {
889 status
= netlogon_creds_arcfour_crypt(creds
,
891 sizeof(base
->key
.key
));
892 if (!NT_STATUS_IS_OK(status
)) {
897 if (!all_zero(base
->LMSessKey
.key
,
898 sizeof(base
->LMSessKey
.key
))) {
899 status
= netlogon_creds_arcfour_crypt(creds
,
901 sizeof(base
->LMSessKey
.key
));
902 if (!NT_STATUS_IS_OK(status
)) {
907 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
908 if (!all_zero(base
->LMSessKey
.key
,
909 sizeof(base
->LMSessKey
.key
))) {
911 status
= netlogon_creds_des_encrypt_LMKey(creds
,
914 status
= netlogon_creds_des_decrypt_LMKey(creds
,
917 if (!NT_STATUS_IS_OK(status
)) {
926 NTSTATUS
netlogon_creds_decrypt_samlogon_validation(struct netlogon_creds_CredentialState
*creds
,
927 uint16_t validation_level
,
928 union netr_Validation
*validation
)
930 return netlogon_creds_crypt_samlogon_validation(creds
,
936 NTSTATUS
netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_CredentialState
*creds
,
937 uint16_t validation_level
,
938 union netr_Validation
*validation
)
940 return netlogon_creds_crypt_samlogon_validation(creds
,
946 static NTSTATUS
netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_CredentialState
*creds
,
947 enum netr_LogonInfoClass level
,
948 union netr_LogonLevel
*logon
,
954 return NT_STATUS_INVALID_PARAMETER
;
958 case NetlogonInteractiveInformation
:
959 case NetlogonInteractiveTransitiveInformation
:
960 case NetlogonServiceInformation
:
961 case NetlogonServiceTransitiveInformation
:
962 if (logon
->password
== NULL
) {
963 return NT_STATUS_INVALID_PARAMETER
;
966 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
969 h
= logon
->password
->lmpassword
.hash
;
970 if (!all_zero(h
, 16)) {
972 status
= netlogon_creds_aes_encrypt(
977 status
= netlogon_creds_aes_decrypt(
982 if (!NT_STATUS_IS_OK(status
)) {
987 h
= logon
->password
->ntpassword
.hash
;
988 if (!all_zero(h
, 16)) {
990 status
= netlogon_creds_aes_encrypt(creds
,
994 status
= netlogon_creds_aes_decrypt(creds
,
998 if (!NT_STATUS_IS_OK(status
)) {
1002 } else if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
1005 h
= logon
->password
->lmpassword
.hash
;
1006 if (!all_zero(h
, 16)) {
1007 status
= netlogon_creds_arcfour_crypt(creds
,
1010 if (!NT_STATUS_IS_OK(status
)) {
1015 h
= logon
->password
->ntpassword
.hash
;
1016 if (!all_zero(h
, 16)) {
1017 status
= netlogon_creds_arcfour_crypt(creds
,
1020 if (!NT_STATUS_IS_OK(status
)) {
1025 struct samr_Password
*p
;
1027 p
= &logon
->password
->lmpassword
;
1028 if (!all_zero(p
->hash
, 16)) {
1030 status
= netlogon_creds_des_encrypt(creds
, p
);
1032 status
= netlogon_creds_des_decrypt(creds
, p
);
1034 if (!NT_STATUS_IS_OK(status
)) {
1038 p
= &logon
->password
->ntpassword
;
1039 if (!all_zero(p
->hash
, 16)) {
1041 status
= netlogon_creds_des_encrypt(creds
, p
);
1043 status
= netlogon_creds_des_decrypt(creds
, p
);
1045 if (!NT_STATUS_IS_OK(status
)) {
1052 case NetlogonNetworkInformation
:
1053 case NetlogonNetworkTransitiveInformation
:
1056 case NetlogonGenericInformation
:
1057 if (logon
->generic
== NULL
) {
1058 return NT_STATUS_INVALID_PARAMETER
;
1061 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
1063 status
= netlogon_creds_aes_encrypt(
1065 logon
->generic
->data
,
1066 logon
->generic
->length
);
1068 status
= netlogon_creds_aes_decrypt(
1070 logon
->generic
->data
,
1071 logon
->generic
->length
);
1073 if (!NT_STATUS_IS_OK(status
)) {
1076 } else if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
1077 status
= netlogon_creds_arcfour_crypt(creds
,
1078 logon
->generic
->data
,
1079 logon
->generic
->length
);
1080 if (!NT_STATUS_IS_OK(status
)) {
1084 /* Using DES to verify kerberos tickets makes no sense */
1089 return NT_STATUS_OK
;
1092 NTSTATUS
netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState
*creds
,
1093 enum netr_LogonInfoClass level
,
1094 union netr_LogonLevel
*logon
)
1096 return netlogon_creds_crypt_samlogon_logon(creds
, level
, logon
, false);
1099 NTSTATUS
netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState
*creds
,
1100 enum netr_LogonInfoClass level
,
1101 union netr_LogonLevel
*logon
)
1103 return netlogon_creds_crypt_samlogon_logon(creds
, level
, logon
, true);
1106 union netr_LogonLevel
*netlogon_creds_shallow_copy_logon(TALLOC_CTX
*mem_ctx
,
1107 enum netr_LogonInfoClass level
,
1108 const union netr_LogonLevel
*in
)
1110 union netr_LogonLevel
*out
;
1116 out
= talloc(mem_ctx
, union netr_LogonLevel
);
1124 case NetlogonInteractiveInformation
:
1125 case NetlogonInteractiveTransitiveInformation
:
1126 case NetlogonServiceInformation
:
1127 case NetlogonServiceTransitiveInformation
:
1128 if (in
->password
== NULL
) {
1132 out
->password
= talloc(out
, struct netr_PasswordInfo
);
1133 if (out
->password
== NULL
) {
1137 *out
->password
= *in
->password
;
1141 case NetlogonNetworkInformation
:
1142 case NetlogonNetworkTransitiveInformation
:
1145 case NetlogonGenericInformation
:
1146 if (in
->generic
== NULL
) {
1150 out
->generic
= talloc(out
, struct netr_GenericInfo
);
1151 if (out
->generic
== NULL
) {
1155 *out
->generic
= *in
->generic
;
1157 if (in
->generic
->data
== NULL
) {
1161 if (in
->generic
->length
== 0) {
1165 out
->generic
->data
= talloc_memdup(out
->generic
,
1167 in
->generic
->length
);
1168 if (out
->generic
->data
== NULL
) {
1180 copy a netlogon_creds_CredentialState struct
1183 struct netlogon_creds_CredentialState
*netlogon_creds_copy(
1184 TALLOC_CTX
*mem_ctx
,
1185 const struct netlogon_creds_CredentialState
*creds_in
)
1187 struct netlogon_creds_CredentialState
*creds
= talloc_zero(mem_ctx
, struct netlogon_creds_CredentialState
);
1193 creds
->sequence
= creds_in
->sequence
;
1194 creds
->negotiate_flags
= creds_in
->negotiate_flags
;
1195 creds
->secure_channel_type
= creds_in
->secure_channel_type
;
1197 creds
->computer_name
= talloc_strdup(creds
, creds_in
->computer_name
);
1198 if (!creds
->computer_name
) {
1202 creds
->account_name
= talloc_strdup(creds
, creds_in
->account_name
);
1203 if (!creds
->account_name
) {
1208 if (creds_in
->sid
) {
1209 creds
->sid
= dom_sid_dup(creds
, creds_in
->sid
);
1216 memcpy(creds
->session_key
, creds_in
->session_key
, sizeof(creds
->session_key
));
1217 memcpy(creds
->seed
.data
, creds_in
->seed
.data
, sizeof(creds
->seed
.data
));
1218 memcpy(creds
->client
.data
, creds_in
->client
.data
, sizeof(creds
->client
.data
));
1219 memcpy(creds
->server
.data
, creds_in
->server
.data
, sizeof(creds
->server
.data
));