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"
28 #ifndef HAVE_GNUTLS_AES_CFB8
29 #include "lib/crypto/aes.h"
32 #include "lib/crypto/gnutls_helpers.h"
33 #include <gnutls/gnutls.h>
34 #include <gnutls/crypto.h>
36 static void netlogon_creds_step_crypt(struct netlogon_creds_CredentialState
*creds
,
37 const struct netr_Credential
*in
,
38 struct netr_Credential
*out
)
40 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
41 memcpy(out
->data
, in
->data
, sizeof(out
->data
));
43 netlogon_creds_aes_encrypt(creds
, out
->data
, sizeof(out
->data
));
45 des_crypt112(out
->data
, in
->data
, creds
->session_key
, 1);
50 initialise the credentials state for old-style 64 bit session keys
52 this call is made after the netr_ServerReqChallenge call
54 static void netlogon_creds_init_64bit(struct netlogon_creds_CredentialState
*creds
,
55 const struct netr_Credential
*client_challenge
,
56 const struct netr_Credential
*server_challenge
,
57 const struct samr_Password
*machine_password
)
62 sum
[0] = IVAL(client_challenge
->data
, 0) + IVAL(server_challenge
->data
, 0);
63 sum
[1] = IVAL(client_challenge
->data
, 4) + IVAL(server_challenge
->data
, 4);
68 ZERO_ARRAY(creds
->session_key
);
70 des_crypt128(creds
->session_key
, sum2
, machine_password
->hash
);
74 initialise the credentials state for ADS-style 128 bit session keys
76 this call is made after the netr_ServerReqChallenge call
78 static NTSTATUS
netlogon_creds_init_128bit(struct netlogon_creds_CredentialState
*creds
,
79 const struct netr_Credential
*client_challenge
,
80 const struct netr_Credential
*server_challenge
,
81 const struct samr_Password
*machine_password
)
83 uint8_t zero
[4] = {0};
84 uint8_t tmp
[gnutls_hash_get_len(GNUTLS_MAC_MD5
)];
85 gnutls_hash_hd_t hash_hnd
= NULL
;
88 ZERO_ARRAY(creds
->session_key
);
90 rc
= gnutls_hash_init(&hash_hnd
, GNUTLS_DIG_MD5
);
92 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
95 rc
= gnutls_hash(hash_hnd
, zero
, sizeof(zero
));
97 gnutls_hash_deinit(hash_hnd
, NULL
);
98 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
100 rc
= gnutls_hash(hash_hnd
, client_challenge
->data
, 8);
102 gnutls_hash_deinit(hash_hnd
, NULL
);
103 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
105 rc
= gnutls_hash(hash_hnd
, server_challenge
->data
, 8);
107 gnutls_hash_deinit(hash_hnd
, NULL
);
108 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
111 gnutls_hash_deinit(hash_hnd
, tmp
);
113 /* This doesn't require HMAC MD5 RFC2104 as the hash is only 16 bytes */
114 rc
= gnutls_hmac_fast(GNUTLS_MAC_MD5
,
115 machine_password
->hash
,
116 sizeof(machine_password
->hash
),
123 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
130 initialise the credentials state for AES/HMAC-SHA256-style 128 bit session keys
132 this call is made after the netr_ServerReqChallenge call
134 static NTSTATUS
netlogon_creds_init_hmac_sha256(struct netlogon_creds_CredentialState
*creds
,
135 const struct netr_Credential
*client_challenge
,
136 const struct netr_Credential
*server_challenge
,
137 const struct samr_Password
*machine_password
)
139 gnutls_hmac_hd_t hmac_hnd
= NULL
;
140 uint8_t digest
[gnutls_hash_get_len(GNUTLS_MAC_SHA256
)];
143 ZERO_ARRAY(creds
->session_key
);
145 rc
= gnutls_hmac_init(&hmac_hnd
,
147 machine_password
->hash
,
148 sizeof(machine_password
->hash
));
150 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
152 rc
= gnutls_hmac(hmac_hnd
,
153 client_challenge
->data
,
156 gnutls_hmac_deinit(hmac_hnd
, NULL
);
157 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
159 rc
= gnutls_hmac(hmac_hnd
,
160 server_challenge
->data
,
163 gnutls_hmac_deinit(hmac_hnd
, NULL
);
164 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
166 gnutls_hmac_deinit(hmac_hnd
, digest
);
168 memcpy(creds
->session_key
, digest
, sizeof(creds
->session_key
));
175 static void netlogon_creds_first_step(struct netlogon_creds_CredentialState
*creds
,
176 const struct netr_Credential
*client_challenge
,
177 const struct netr_Credential
*server_challenge
)
179 netlogon_creds_step_crypt(creds
, client_challenge
, &creds
->client
);
181 netlogon_creds_step_crypt(creds
, server_challenge
, &creds
->server
);
183 creds
->seed
= creds
->client
;
187 step the credentials to the next element in the chain, updating the
188 current client and server credentials and the seed
190 static void netlogon_creds_step(struct netlogon_creds_CredentialState
*creds
)
192 struct netr_Credential time_cred
;
194 DEBUG(5,("\tseed %08x:%08x\n",
195 IVAL(creds
->seed
.data
, 0), IVAL(creds
->seed
.data
, 4)));
197 SIVAL(time_cred
.data
, 0, IVAL(creds
->seed
.data
, 0) + creds
->sequence
);
198 SIVAL(time_cred
.data
, 4, IVAL(creds
->seed
.data
, 4));
200 DEBUG(5,("\tseed+time %08x:%08x\n", IVAL(time_cred
.data
, 0), IVAL(time_cred
.data
, 4)));
202 netlogon_creds_step_crypt(creds
, &time_cred
, &creds
->client
);
204 DEBUG(5,("\tCLIENT %08x:%08x\n",
205 IVAL(creds
->client
.data
, 0), IVAL(creds
->client
.data
, 4)));
207 SIVAL(time_cred
.data
, 0, IVAL(creds
->seed
.data
, 0) + creds
->sequence
+ 1);
208 SIVAL(time_cred
.data
, 4, IVAL(creds
->seed
.data
, 4));
210 DEBUG(5,("\tseed+time+1 %08x:%08x\n",
211 IVAL(time_cred
.data
, 0), IVAL(time_cred
.data
, 4)));
213 netlogon_creds_step_crypt(creds
, &time_cred
, &creds
->server
);
215 DEBUG(5,("\tSERVER %08x:%08x\n",
216 IVAL(creds
->server
.data
, 0), IVAL(creds
->server
.data
, 4)));
218 creds
->seed
= time_cred
;
223 DES encrypt a 8 byte LMSessionKey buffer using the Netlogon session key
225 void netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState
*creds
, struct netr_LMSessionKey
*key
)
227 struct netr_LMSessionKey tmp
;
228 des_crypt56(tmp
.key
, key
->key
, creds
->session_key
, 1);
233 DES decrypt a 8 byte LMSessionKey buffer using the Netlogon session key
235 void netlogon_creds_des_decrypt_LMKey(struct netlogon_creds_CredentialState
*creds
, struct netr_LMSessionKey
*key
)
237 struct netr_LMSessionKey tmp
;
238 des_crypt56(tmp
.key
, key
->key
, creds
->session_key
, 0);
243 DES encrypt a 16 byte password buffer using the session key
245 void netlogon_creds_des_encrypt(struct netlogon_creds_CredentialState
*creds
, struct samr_Password
*pass
)
247 struct samr_Password tmp
;
248 des_crypt112_16(tmp
.hash
, pass
->hash
, creds
->session_key
, 1);
253 DES decrypt a 16 byte password buffer using the session key
255 void netlogon_creds_des_decrypt(struct netlogon_creds_CredentialState
*creds
, struct samr_Password
*pass
)
257 struct samr_Password tmp
;
258 des_crypt112_16(tmp
.hash
, pass
->hash
, creds
->session_key
, 0);
263 ARCFOUR encrypt/decrypt a password buffer using the session key
265 NTSTATUS
netlogon_creds_arcfour_crypt(struct netlogon_creds_CredentialState
*creds
,
269 gnutls_cipher_hd_t cipher_hnd
= NULL
;
270 gnutls_datum_t session_key
= {
271 .data
= creds
->session_key
,
272 .size
= sizeof(creds
->session_key
),
276 rc
= gnutls_cipher_init(&cipher_hnd
,
277 GNUTLS_CIPHER_ARCFOUR_128
,
281 return gnutls_error_to_ntstatus(rc
,
282 NT_STATUS_CRYPTO_SYSTEM_INVALID
);
284 rc
= gnutls_cipher_encrypt(cipher_hnd
,
287 gnutls_cipher_deinit(cipher_hnd
);
289 return gnutls_error_to_ntstatus(rc
,
290 NT_STATUS_CRYPTO_SYSTEM_INVALID
);
297 AES encrypt a password buffer using the session key
299 NTSTATUS
netlogon_creds_aes_encrypt(struct netlogon_creds_CredentialState
*creds
,
303 #ifdef HAVE_GNUTLS_AES_CFB8
304 gnutls_cipher_hd_t cipher_hnd
= NULL
;
305 gnutls_datum_t key
= {
306 .data
= creds
->session_key
,
307 .size
= sizeof(creds
->session_key
),
310 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8
);
311 uint8_t _iv
[iv_size
];
312 gnutls_datum_t iv
= {
320 rc
= gnutls_cipher_init(&cipher_hnd
,
321 GNUTLS_CIPHER_AES_128_CFB8
,
325 return gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
328 rc
= gnutls_cipher_encrypt(cipher_hnd
, data
, len
);
329 gnutls_cipher_deinit(cipher_hnd
);
331 return gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
334 #else /* NOT HAVE_GNUTLS_AES_CFB8 */
336 uint8_t iv
[AES_BLOCK_SIZE
] = {0};
338 AES_set_encrypt_key(creds
->session_key
, 128, &key
);
340 aes_cfb8_encrypt(data
, data
, len
, &key
, iv
, AES_ENCRYPT
);
341 #endif /* HAVE_GNUTLS_AES_CFB8 */
347 AES decrypt a password buffer using the session key
349 NTSTATUS
netlogon_creds_aes_decrypt(struct netlogon_creds_CredentialState
*creds
, uint8_t *data
, size_t len
)
351 #ifdef HAVE_GNUTLS_AES_CFB8
352 gnutls_cipher_hd_t cipher_hnd
= NULL
;
353 gnutls_datum_t key
= {
354 .data
= creds
->session_key
,
355 .size
= sizeof(creds
->session_key
),
358 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8
);
359 uint8_t _iv
[iv_size
];
360 gnutls_datum_t iv
= {
368 rc
= gnutls_cipher_init(&cipher_hnd
,
369 GNUTLS_CIPHER_AES_128_CFB8
,
373 return gnutls_error_to_ntstatus(rc
,
374 NT_STATUS_CRYPTO_SYSTEM_INVALID
);
377 rc
= gnutls_cipher_decrypt(cipher_hnd
, data
, len
);
378 gnutls_cipher_deinit(cipher_hnd
);
380 return gnutls_error_to_ntstatus(rc
,
381 NT_STATUS_CRYPTO_SYSTEM_INVALID
);
384 #else /* NOT HAVE_GNUTLS_AES_CFB8 */
386 uint8_t iv
[AES_BLOCK_SIZE
] = {0};
388 AES_set_encrypt_key(creds
->session_key
, 128, &key
);
390 aes_cfb8_encrypt(data
, data
, len
, &key
, iv
, AES_DECRYPT
);
391 #endif /* HAVE_GNUTLS_AES_CFB8 */
396 /*****************************************************************
397 The above functions are common to the client and server interface
398 next comes the client specific functions
399 ******************************************************************/
402 initialise the credentials chain and return the first client
406 struct netlogon_creds_CredentialState
*netlogon_creds_client_init(TALLOC_CTX
*mem_ctx
,
407 const char *client_account
,
408 const char *client_computer_name
,
409 uint16_t secure_channel_type
,
410 const struct netr_Credential
*client_challenge
,
411 const struct netr_Credential
*server_challenge
,
412 const struct samr_Password
*machine_password
,
413 struct netr_Credential
*initial_credential
,
414 uint32_t negotiate_flags
)
416 struct netlogon_creds_CredentialState
*creds
= talloc_zero(mem_ctx
, struct netlogon_creds_CredentialState
);
423 creds
->sequence
= time(NULL
);
424 creds
->negotiate_flags
= negotiate_flags
;
425 creds
->secure_channel_type
= secure_channel_type
;
427 creds
->computer_name
= talloc_strdup(creds
, client_computer_name
);
428 if (!creds
->computer_name
) {
432 creds
->account_name
= talloc_strdup(creds
, client_account
);
433 if (!creds
->account_name
) {
438 dump_data_pw("Client chall", client_challenge
->data
, sizeof(client_challenge
->data
));
439 dump_data_pw("Server chall", server_challenge
->data
, sizeof(server_challenge
->data
));
440 dump_data_pw("Machine Pass", machine_password
->hash
, sizeof(machine_password
->hash
));
442 if (negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
443 status
= netlogon_creds_init_hmac_sha256(creds
,
447 if (!NT_STATUS_IS_OK(status
)) {
451 } else if (negotiate_flags
& NETLOGON_NEG_STRONG_KEYS
) {
452 status
= netlogon_creds_init_128bit(creds
,
456 if (!NT_STATUS_IS_OK(status
)) {
461 netlogon_creds_init_64bit(creds
, client_challenge
, server_challenge
, machine_password
);
464 netlogon_creds_first_step(creds
, client_challenge
, server_challenge
);
466 dump_data_pw("Session key", creds
->session_key
, 16);
467 dump_data_pw("Credential ", creds
->client
.data
, 8);
469 *initial_credential
= creds
->client
;
474 initialise the credentials structure with only a session key. The caller better know what they are doing!
477 struct netlogon_creds_CredentialState
*netlogon_creds_client_init_session_key(TALLOC_CTX
*mem_ctx
,
478 const uint8_t session_key
[16])
480 struct netlogon_creds_CredentialState
*creds
;
482 creds
= talloc_zero(mem_ctx
, struct netlogon_creds_CredentialState
);
487 memcpy(creds
->session_key
, session_key
, 16);
493 step the credentials to the next element in the chain, updating the
494 current client and server credentials and the seed
496 produce the next authenticator in the sequence ready to send to
499 void netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState
*creds
,
500 struct netr_Authenticator
*next
)
502 uint32_t t32n
= (uint32_t)time(NULL
);
505 * we always increment and ignore an overflow here
507 creds
->sequence
+= 2;
509 if (t32n
> creds
->sequence
) {
511 * we may increment more
513 creds
->sequence
= t32n
;
515 uint32_t d
= creds
->sequence
- t32n
;
517 if (d
>= INT32_MAX
) {
519 * got an overflow of time_t vs. uint32_t
521 creds
->sequence
= t32n
;
525 netlogon_creds_step(creds
);
527 next
->cred
= creds
->client
;
528 next
->timestamp
= creds
->sequence
;
532 check that a credentials reply from a server is correct
534 bool netlogon_creds_client_check(struct netlogon_creds_CredentialState
*creds
,
535 const struct netr_Credential
*received_credentials
)
537 if (!received_credentials
||
538 memcmp(received_credentials
->data
, creds
->server
.data
, 8) != 0) {
539 DEBUG(2,("credentials check failed\n"));
546 /*****************************************************************
547 The above functions are common to the client and server interface
548 next comes the server specific functions
549 ******************************************************************/
552 check that a credentials reply from a server is correct
554 static bool netlogon_creds_server_check_internal(const struct netlogon_creds_CredentialState
*creds
,
555 const struct netr_Credential
*received_credentials
)
557 if (memcmp(received_credentials
->data
, creds
->client
.data
, 8) != 0) {
558 DEBUG(2,("credentials check failed\n"));
559 dump_data_pw("client creds", creds
->client
.data
, 8);
560 dump_data_pw("calc creds", received_credentials
->data
, 8);
567 initialise the credentials chain and return the first server
570 struct netlogon_creds_CredentialState
*netlogon_creds_server_init(TALLOC_CTX
*mem_ctx
,
571 const char *client_account
,
572 const char *client_computer_name
,
573 uint16_t secure_channel_type
,
574 const struct netr_Credential
*client_challenge
,
575 const struct netr_Credential
*server_challenge
,
576 const struct samr_Password
*machine_password
,
577 const struct netr_Credential
*credentials_in
,
578 struct netr_Credential
*credentials_out
,
579 uint32_t negotiate_flags
)
582 struct netlogon_creds_CredentialState
*creds
= talloc_zero(mem_ctx
, struct netlogon_creds_CredentialState
);
588 creds
->negotiate_flags
= negotiate_flags
;
589 creds
->secure_channel_type
= secure_channel_type
;
591 dump_data_pw("Client chall", client_challenge
->data
, sizeof(client_challenge
->data
));
592 dump_data_pw("Server chall", server_challenge
->data
, sizeof(server_challenge
->data
));
593 dump_data_pw("Machine Pass", machine_password
->hash
, sizeof(machine_password
->hash
));
595 creds
->computer_name
= talloc_strdup(creds
, client_computer_name
);
596 if (!creds
->computer_name
) {
600 creds
->account_name
= talloc_strdup(creds
, client_account
);
601 if (!creds
->account_name
) {
606 if (negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
609 status
= netlogon_creds_init_hmac_sha256(creds
,
613 if (!NT_STATUS_IS_OK(status
)) {
617 } else if (negotiate_flags
& NETLOGON_NEG_STRONG_KEYS
) {
618 netlogon_creds_init_128bit(creds
, client_challenge
, server_challenge
,
621 netlogon_creds_init_64bit(creds
, client_challenge
, server_challenge
,
625 netlogon_creds_first_step(creds
, client_challenge
, server_challenge
);
627 dump_data_pw("Session key", creds
->session_key
, 16);
628 dump_data_pw("Client Credential ", creds
->client
.data
, 8);
629 dump_data_pw("Server Credential ", creds
->server
.data
, 8);
631 dump_data_pw("Credentials in", credentials_in
->data
, sizeof(credentials_in
->data
));
633 /* And before we leak information about the machine account
634 * password, check that they got the first go right */
635 if (!netlogon_creds_server_check_internal(creds
, credentials_in
)) {
640 *credentials_out
= creds
->server
;
642 dump_data_pw("Credentials out", credentials_out
->data
, sizeof(credentials_out
->data
));
647 NTSTATUS
netlogon_creds_server_step_check(struct netlogon_creds_CredentialState
*creds
,
648 const struct netr_Authenticator
*received_authenticator
,
649 struct netr_Authenticator
*return_authenticator
)
651 if (!received_authenticator
|| !return_authenticator
) {
652 return NT_STATUS_INVALID_PARAMETER
;
656 return NT_STATUS_ACCESS_DENIED
;
659 creds
->sequence
= received_authenticator
->timestamp
;
660 netlogon_creds_step(creds
);
661 if (netlogon_creds_server_check_internal(creds
, &received_authenticator
->cred
)) {
662 return_authenticator
->cred
= creds
->server
;
663 return_authenticator
->timestamp
= 0;
666 ZERO_STRUCTP(return_authenticator
);
667 return NT_STATUS_ACCESS_DENIED
;
671 static NTSTATUS
netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_CredentialState
*creds
,
672 uint16_t validation_level
,
673 union netr_Validation
*validation
,
676 struct netr_SamBaseInfo
*base
= NULL
;
679 if (validation
== NULL
) {
680 return NT_STATUS_INVALID_PARAMETER
;
683 switch (validation_level
) {
685 if (validation
->sam2
) {
686 base
= &validation
->sam2
->base
;
690 if (validation
->sam3
) {
691 base
= &validation
->sam3
->base
;
695 if (validation
->sam6
) {
696 base
= &validation
->sam6
->base
;
700 /* If we can't find it, we can't very well decrypt it */
701 return NT_STATUS_INVALID_INFO_CLASS
;
705 return NT_STATUS_INVALID_INFO_CLASS
;
708 /* find and decyrpt the session keys, return in parameters above */
709 if (validation_level
== 6) {
710 /* they aren't encrypted! */
711 } else if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
712 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
713 if (!all_zero(base
->key
.key
, sizeof(base
->key
.key
))) {
715 status
= netlogon_creds_aes_encrypt(
718 sizeof(base
->key
.key
));
720 status
= netlogon_creds_aes_decrypt(
723 sizeof(base
->key
.key
));
725 if (!NT_STATUS_IS_OK(status
)) {
730 if (!all_zero(base
->LMSessKey
.key
,
731 sizeof(base
->LMSessKey
.key
))) {
733 status
= netlogon_creds_aes_encrypt(
736 sizeof(base
->LMSessKey
.key
));
738 status
= netlogon_creds_aes_decrypt(
741 sizeof(base
->LMSessKey
.key
));
743 if (!NT_STATUS_IS_OK(status
)) {
747 } else if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
748 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
749 if (!all_zero(base
->key
.key
, sizeof(base
->key
.key
))) {
750 status
= netlogon_creds_arcfour_crypt(creds
,
752 sizeof(base
->key
.key
));
753 if (!NT_STATUS_IS_OK(status
)) {
758 if (!all_zero(base
->LMSessKey
.key
,
759 sizeof(base
->LMSessKey
.key
))) {
760 status
= netlogon_creds_arcfour_crypt(creds
,
762 sizeof(base
->LMSessKey
.key
));
763 if (!NT_STATUS_IS_OK(status
)) {
768 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
769 if (!all_zero(base
->LMSessKey
.key
,
770 sizeof(base
->LMSessKey
.key
))) {
772 netlogon_creds_des_encrypt_LMKey(creds
,
775 netlogon_creds_des_decrypt_LMKey(creds
,
784 NTSTATUS
netlogon_creds_decrypt_samlogon_validation(struct netlogon_creds_CredentialState
*creds
,
785 uint16_t validation_level
,
786 union netr_Validation
*validation
)
788 return netlogon_creds_crypt_samlogon_validation(creds
,
794 NTSTATUS
netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_CredentialState
*creds
,
795 uint16_t validation_level
,
796 union netr_Validation
*validation
)
798 return netlogon_creds_crypt_samlogon_validation(creds
,
804 static NTSTATUS
netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_CredentialState
*creds
,
805 enum netr_LogonInfoClass level
,
806 union netr_LogonLevel
*logon
,
812 return NT_STATUS_INVALID_PARAMETER
;
816 case NetlogonInteractiveInformation
:
817 case NetlogonInteractiveTransitiveInformation
:
818 case NetlogonServiceInformation
:
819 case NetlogonServiceTransitiveInformation
:
820 if (logon
->password
== NULL
) {
821 return NT_STATUS_INVALID_PARAMETER
;
824 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
827 h
= logon
->password
->lmpassword
.hash
;
828 if (!all_zero(h
, 16)) {
830 status
= netlogon_creds_aes_encrypt(
835 status
= netlogon_creds_aes_decrypt(
840 if (!NT_STATUS_IS_OK(status
)) {
845 h
= logon
->password
->ntpassword
.hash
;
846 if (!all_zero(h
, 16)) {
848 status
= netlogon_creds_aes_encrypt(creds
,
852 status
= netlogon_creds_aes_decrypt(creds
,
856 if (!NT_STATUS_IS_OK(status
)) {
860 } else if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
863 h
= logon
->password
->lmpassword
.hash
;
864 if (!all_zero(h
, 16)) {
865 status
= netlogon_creds_arcfour_crypt(creds
,
868 if (!NT_STATUS_IS_OK(status
)) {
873 h
= logon
->password
->ntpassword
.hash
;
874 if (!all_zero(h
, 16)) {
875 status
= netlogon_creds_arcfour_crypt(creds
,
878 if (!NT_STATUS_IS_OK(status
)) {
883 struct samr_Password
*p
;
885 p
= &logon
->password
->lmpassword
;
886 if (!all_zero(p
->hash
, 16)) {
888 netlogon_creds_des_encrypt(creds
, p
);
890 netlogon_creds_des_decrypt(creds
, p
);
893 p
= &logon
->password
->ntpassword
;
894 if (!all_zero(p
->hash
, 16)) {
896 netlogon_creds_des_encrypt(creds
, p
);
898 netlogon_creds_des_decrypt(creds
, p
);
904 case NetlogonNetworkInformation
:
905 case NetlogonNetworkTransitiveInformation
:
908 case NetlogonGenericInformation
:
909 if (logon
->generic
== NULL
) {
910 return NT_STATUS_INVALID_PARAMETER
;
913 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
915 status
= netlogon_creds_aes_encrypt(
917 logon
->generic
->data
,
918 logon
->generic
->length
);
920 status
= netlogon_creds_aes_decrypt(
922 logon
->generic
->data
,
923 logon
->generic
->length
);
925 if (!NT_STATUS_IS_OK(status
)) {
928 } else if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
929 status
= netlogon_creds_arcfour_crypt(creds
,
930 logon
->generic
->data
,
931 logon
->generic
->length
);
932 if (!NT_STATUS_IS_OK(status
)) {
936 /* Using DES to verify kerberos tickets makes no sense */
944 NTSTATUS
netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState
*creds
,
945 enum netr_LogonInfoClass level
,
946 union netr_LogonLevel
*logon
)
948 return netlogon_creds_crypt_samlogon_logon(creds
, level
, logon
, false);
951 NTSTATUS
netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState
*creds
,
952 enum netr_LogonInfoClass level
,
953 union netr_LogonLevel
*logon
)
955 return netlogon_creds_crypt_samlogon_logon(creds
, level
, logon
, true);
958 union netr_LogonLevel
*netlogon_creds_shallow_copy_logon(TALLOC_CTX
*mem_ctx
,
959 enum netr_LogonInfoClass level
,
960 const union netr_LogonLevel
*in
)
962 union netr_LogonLevel
*out
;
968 out
= talloc(mem_ctx
, union netr_LogonLevel
);
976 case NetlogonInteractiveInformation
:
977 case NetlogonInteractiveTransitiveInformation
:
978 case NetlogonServiceInformation
:
979 case NetlogonServiceTransitiveInformation
:
980 if (in
->password
== NULL
) {
984 out
->password
= talloc(out
, struct netr_PasswordInfo
);
985 if (out
->password
== NULL
) {
989 *out
->password
= *in
->password
;
993 case NetlogonNetworkInformation
:
994 case NetlogonNetworkTransitiveInformation
:
997 case NetlogonGenericInformation
:
998 if (in
->generic
== NULL
) {
1002 out
->generic
= talloc(out
, struct netr_GenericInfo
);
1003 if (out
->generic
== NULL
) {
1007 *out
->generic
= *in
->generic
;
1009 if (in
->generic
->data
== NULL
) {
1013 if (in
->generic
->length
== 0) {
1017 out
->generic
->data
= talloc_memdup(out
->generic
,
1019 in
->generic
->length
);
1020 if (out
->generic
->data
== NULL
) {
1032 copy a netlogon_creds_CredentialState struct
1035 struct netlogon_creds_CredentialState
*netlogon_creds_copy(
1036 TALLOC_CTX
*mem_ctx
,
1037 const struct netlogon_creds_CredentialState
*creds_in
)
1039 struct netlogon_creds_CredentialState
*creds
= talloc_zero(mem_ctx
, struct netlogon_creds_CredentialState
);
1045 creds
->sequence
= creds_in
->sequence
;
1046 creds
->negotiate_flags
= creds_in
->negotiate_flags
;
1047 creds
->secure_channel_type
= creds_in
->secure_channel_type
;
1049 creds
->computer_name
= talloc_strdup(creds
, creds_in
->computer_name
);
1050 if (!creds
->computer_name
) {
1054 creds
->account_name
= talloc_strdup(creds
, creds_in
->account_name
);
1055 if (!creds
->account_name
) {
1060 if (creds_in
->sid
) {
1061 creds
->sid
= dom_sid_dup(creds
, creds_in
->sid
);
1068 memcpy(creds
->session_key
, creds_in
->session_key
, sizeof(creds
->session_key
));
1069 memcpy(creds
->seed
.data
, creds_in
->seed
.data
, sizeof(creds
->seed
.data
));
1070 memcpy(creds
->client
.data
, creds_in
->client
.data
, sizeof(creds
->client
.data
));
1071 memcpy(creds
->server
.data
, creds_in
->server
.data
, sizeof(creds
->server
.data
));