smbd: trigger NOTIFY_ACTION_DIRLEASE_BREAK when closing a modified file
[samba4-gss.git] / libcli / auth / credentials.c
blob7a1f6038ef278f099fcc655cb0798fdcb1b7958c
1 /*
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/>.
23 #include "includes.h"
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])
52 return false;
55 return true;
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)
70 NTSTATUS status;
71 int rc;
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,
77 out->data,
78 sizeof(out->data));
79 if (!NT_STATUS_IS_OK(status)) {
80 return status;
82 } else {
83 rc = des_crypt112(out->data, in->data, creds->session_key, SAMBA_GNUTLS_ENCRYPT);
84 if (rc != 0) {
85 return gnutls_error_to_ntstatus(rc,
86 NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
90 return NT_STATUS_OK;
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)
103 uint32_t sum[2];
104 uint8_t sum2[8];
105 int rc;
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);
116 if (rc != 0) {
117 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
120 return NT_STATUS_OK;
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;
136 int rc;
138 ZERO_ARRAY(creds->session_key);
140 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
141 if (rc < 0) {
142 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
145 rc = gnutls_hash(hash_hnd, zero, sizeof(zero));
146 if (rc < 0) {
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);
151 if (rc < 0) {
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);
156 if (rc < 0) {
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),
167 tmp,
168 sizeof(tmp),
169 creds->session_key);
170 ZERO_ARRAY(tmp);
172 if (rc < 0) {
173 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
176 return NT_STATUS_OK;
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)];
191 int rc;
193 ZERO_ARRAY(creds->session_key);
195 rc = gnutls_hmac_init(&hmac_hnd,
196 GNUTLS_MAC_SHA256,
197 machine_password->hash,
198 sizeof(machine_password->hash));
199 if (rc < 0) {
200 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
202 rc = gnutls_hmac(hmac_hnd,
203 client_challenge->data,
205 if (rc < 0) {
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,
212 if (rc < 0) {
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));
220 ZERO_ARRAY(digest);
222 return NT_STATUS_OK;
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)
229 NTSTATUS status;
231 status = netlogon_creds_step_crypt(creds,
232 client_challenge,
233 &creds->client);
234 if (!NT_STATUS_IS_OK(status)) {
235 return status;
238 status = netlogon_creds_step_crypt(creds,
239 server_challenge,
240 &creds->server);
241 if (!NT_STATUS_IS_OK(status)) {
242 return status;
245 creds->seed = creds->client;
247 return NT_STATUS_OK;
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;
257 NTSTATUS status;
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,
268 &time_cred,
269 &creds->client);
270 if (!NT_STATUS_IS_OK(status)) {
271 return 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)) {
285 return status;
288 DEBUG(5,("\tSERVER %08x:%08x\n",
289 IVAL(creds->server.data, 0), IVAL(creds->server.data, 4)));
291 creds->seed = time_cred;
293 return NT_STATUS_OK;
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)
302 int rc;
303 struct netr_LMSessionKey tmp;
305 rc = des_crypt56_gnutls(tmp.key, key->key, creds->session_key, SAMBA_GNUTLS_ENCRYPT);
306 if (rc < 0) {
307 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
309 *key = tmp;
311 return NT_STATUS_OK;
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)
320 int rc;
321 struct netr_LMSessionKey tmp;
323 rc = des_crypt56_gnutls(tmp.key, key->key, creds->session_key, SAMBA_GNUTLS_DECRYPT);
324 if (rc < 0) {
325 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
327 *key = tmp;
329 return NT_STATUS_OK;
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;
339 int rc;
341 rc = des_crypt112_16(tmp.hash, pass->hash, creds->session_key, SAMBA_GNUTLS_ENCRYPT);
342 if (rc < 0) {
343 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
345 *pass = tmp;
347 return NT_STATUS_OK;
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;
357 int rc;
359 rc = des_crypt112_16(tmp.hash, pass->hash, creds->session_key, SAMBA_GNUTLS_DECRYPT);
360 if (rc < 0) {
361 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
363 *pass = tmp;
365 return NT_STATUS_OK;
369 ARCFOUR encrypt/decrypt a password buffer using the session key
371 NTSTATUS netlogon_creds_arcfour_crypt(struct netlogon_creds_CredentialState *creds,
372 uint8_t *data,
373 size_t len)
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),
380 int rc;
382 rc = gnutls_cipher_init(&cipher_hnd,
383 GNUTLS_CIPHER_ARCFOUR_128,
384 &session_key,
385 NULL);
386 if (rc < 0) {
387 return gnutls_error_to_ntstatus(rc,
388 NT_STATUS_CRYPTO_SYSTEM_INVALID);
390 rc = gnutls_cipher_encrypt(cipher_hnd,
391 data,
392 len);
393 gnutls_cipher_deinit(cipher_hnd);
394 if (rc < 0) {
395 return gnutls_error_to_ntstatus(rc,
396 NT_STATUS_CRYPTO_SYSTEM_INVALID);
399 return NT_STATUS_OK;
403 AES encrypt a password buffer using the session key
405 NTSTATUS netlogon_creds_aes_encrypt(struct netlogon_creds_CredentialState *creds,
406 uint8_t *data,
407 size_t len)
409 gnutls_cipher_hd_t cipher_hnd = NULL;
410 gnutls_datum_t key = {
411 .data = creds->session_key,
412 .size = sizeof(creds->session_key),
414 uint32_t iv_size =
415 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
416 uint8_t _iv[iv_size];
417 gnutls_datum_t iv = {
418 .data = _iv,
419 .size = iv_size,
421 int rc;
423 ZERO_ARRAY(_iv);
425 rc = gnutls_cipher_init(&cipher_hnd,
426 GNUTLS_CIPHER_AES_128_CFB8,
427 &key,
428 &iv);
429 if (rc < 0) {
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);
435 if (rc < 0) {
436 return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
439 return NT_STATUS_OK;
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),
452 uint32_t iv_size =
453 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
454 uint8_t _iv[iv_size];
455 gnutls_datum_t iv = {
456 .data = _iv,
457 .size = iv_size,
459 int rc;
461 ZERO_ARRAY(_iv);
463 rc = gnutls_cipher_init(&cipher_hnd,
464 GNUTLS_CIPHER_AES_128_CFB8,
465 &key,
466 &iv);
467 if (rc < 0) {
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);
474 if (rc < 0) {
475 return gnutls_error_to_ntstatus(rc,
476 NT_STATUS_CRYPTO_SYSTEM_INVALID);
479 return NT_STATUS_OK;
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);
496 if (creds == NULL) {
497 return NULL;
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) {
508 talloc_free(creds);
509 return NULL;
511 creds->account_name = talloc_strdup(creds, client_account);
512 if (!creds->account_name) {
513 talloc_free(creds);
514 return NULL;
517 creds->ex = talloc_zero(creds,
518 struct netlogon_creds_CredentialState_extra_info);
519 if (creds->ex == NULL) {
520 talloc_free(creds);
521 return 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;
527 } else {
528 creds->ex->client_sid = global_sid_NULL;
531 return creds;
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
541 credentials
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;
556 NTSTATUS status;
558 creds = netlogon_creds_alloc(mem_ctx,
559 client_account,
560 client_computer_name,
561 secure_channel_type,
562 client_requested_flags,
563 NULL, /* client_sid */
564 negotiate_flags);
565 if (!creds) {
566 return NULL;
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,
575 client_challenge,
576 server_challenge,
577 machine_password);
578 if (!NT_STATUS_IS_OK(status)) {
579 talloc_free(creds);
580 return NULL;
582 } else if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
583 status = netlogon_creds_init_128bit(creds,
584 client_challenge,
585 server_challenge,
586 machine_password);
587 if (!NT_STATUS_IS_OK(status)) {
588 talloc_free(creds);
589 return NULL;
591 } else {
592 status = netlogon_creds_init_64bit(creds,
593 client_challenge,
594 server_challenge,
595 machine_password);
596 if (!NT_STATUS_IS_OK(status)) {
597 talloc_free(creds);
598 return NULL;
602 status = netlogon_creds_first_step(creds,
603 client_challenge,
604 server_challenge);
605 if (!NT_STATUS_IS_OK(status)) {
606 talloc_free(creds);
607 return NULL;
610 dump_data_pw("Session key", creds->session_key, 16);
611 dump_data_pw("Credential ", creds->client.data, 8);
613 *initial_credential = creds->client;
614 return creds;
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
622 the server
624 NTSTATUS
625 netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState *creds,
626 struct netr_Authenticator *next)
628 uint32_t t32n = (uint32_t)time(NULL);
629 NTSTATUS status;
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;
641 } else {
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)) {
654 return status;
657 next->cred = creds->client;
658 next->timestamp = creds->sequence;
660 return NT_STATUS_OK;
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;
676 return NT_STATUS_OK;
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;
684 NTSTATUS status;
686 status = netlogon_creds_client_verify(creds,
687 received_credentials,
688 auth_type,
689 auth_level);
690 if (!NT_STATUS_IS_OK(status)) {
691 return false;
694 return true;
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);
713 return false;
715 return true;
719 initialise the credentials chain and return the first server
720 credentials
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;
736 NTSTATUS status;
737 bool ok;
739 creds = netlogon_creds_alloc(mem_ctx,
740 client_account,
741 client_computer_name,
742 secure_channel_type,
743 client_requested_flags,
744 client_sid,
745 negotiate_flags);
746 if (!creds) {
747 return NULL;
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);
755 if (!ok) {
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));
764 talloc_free(creds);
765 return NULL;
768 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
769 status = netlogon_creds_init_hmac_sha256(creds,
770 client_challenge,
771 server_challenge,
772 machine_password);
773 if (!NT_STATUS_IS_OK(status)) {
774 talloc_free(creds);
775 return NULL;
777 } else if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
778 status = netlogon_creds_init_128bit(creds,
779 client_challenge,
780 server_challenge,
781 machine_password);
782 if (!NT_STATUS_IS_OK(status)) {
783 talloc_free(creds);
784 return NULL;
786 } else {
787 status = netlogon_creds_init_64bit(creds,
788 client_challenge,
789 server_challenge,
790 machine_password);
791 if (!NT_STATUS_IS_OK(status)) {
792 talloc_free(creds);
793 return NULL;
797 status = netlogon_creds_first_step(creds,
798 client_challenge,
799 server_challenge);
800 if (!NT_STATUS_IS_OK(status)) {
801 talloc_free(creds);
802 return NULL;
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)) {
814 talloc_free(creds);
815 return NULL;
818 *credentials_out = creds->server;
820 dump_data_pw("Credentials out", credentials_out->data, sizeof(credentials_out->data));
822 return creds;
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)
831 NTSTATUS status;
833 if (!received_authenticator || !return_authenticator) {
834 return NT_STATUS_INVALID_PARAMETER;
837 if (!creds) {
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);
845 return status;
848 if (netlogon_creds_server_check_internal(creds, &received_authenticator->cred)) {
849 return_authenticator->cred = creds->server;
850 return_authenticator->timestamp = 0;
851 return NT_STATUS_OK;
852 } else {
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,
863 bool do_encrypt)
865 struct netr_SamBaseInfo *base = NULL;
866 NTSTATUS status;
868 if (validation == NULL) {
869 return NT_STATUS_INVALID_PARAMETER;
872 switch (validation_level) {
873 case 2:
874 if (validation->sam2) {
875 base = &validation->sam2->base;
877 break;
878 case 3:
879 if (validation->sam3) {
880 base = &validation->sam3->base;
882 break;
883 case 6:
884 if (validation->sam6) {
885 base = &validation->sam6->base;
887 break;
888 default:
889 /* If we can't find it, we can't very well decrypt it */
890 return NT_STATUS_INVALID_INFO_CLASS;
893 if (!base) {
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))) {
903 if (do_encrypt) {
904 status = netlogon_creds_aes_encrypt(
905 creds,
906 base->key.key,
907 sizeof(base->key.key));
908 } else {
909 status = netlogon_creds_aes_decrypt(
910 creds,
911 base->key.key,
912 sizeof(base->key.key));
914 if (!NT_STATUS_IS_OK(status)) {
915 return status;
919 if (!all_zero(base->LMSessKey.key,
920 sizeof(base->LMSessKey.key))) {
921 if (do_encrypt) {
922 status = netlogon_creds_aes_encrypt(
923 creds,
924 base->LMSessKey.key,
925 sizeof(base->LMSessKey.key));
926 } else {
927 status = netlogon_creds_aes_decrypt(
928 creds,
929 base->LMSessKey.key,
930 sizeof(base->LMSessKey.key));
932 if (!NT_STATUS_IS_OK(status)) {
933 return 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,
940 base->key.key,
941 sizeof(base->key.key));
942 if (!NT_STATUS_IS_OK(status)) {
943 return status;
947 if (!all_zero(base->LMSessKey.key,
948 sizeof(base->LMSessKey.key))) {
949 status = netlogon_creds_arcfour_crypt(creds,
950 base->LMSessKey.key,
951 sizeof(base->LMSessKey.key));
952 if (!NT_STATUS_IS_OK(status)) {
953 return status;
956 } else {
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))) {
960 if (do_encrypt) {
961 status = netlogon_creds_des_encrypt_LMKey(creds,
962 &base->LMSessKey);
963 } else {
964 status = netlogon_creds_des_decrypt_LMKey(creds,
965 &base->LMSessKey);
967 if (!NT_STATUS_IS_OK(status)) {
968 return status;
973 return NT_STATUS_OK;
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,
983 validation_level,
984 validation,
985 auth_type,
986 auth_level,
987 false);
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,
997 validation_level,
998 validation,
999 auth_type,
1000 auth_level,
1001 true);
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,
1009 bool do_encrypt)
1011 NTSTATUS status;
1013 if (logon == NULL) {
1014 return NT_STATUS_INVALID_PARAMETER;
1017 switch (level) {
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) {
1027 uint8_t *h;
1029 h = logon->password->lmpassword.hash;
1030 if (!all_zero(h, 16)) {
1031 if (do_encrypt) {
1032 status = netlogon_creds_aes_encrypt(
1033 creds,
1035 16);
1036 } else {
1037 status = netlogon_creds_aes_decrypt(
1038 creds,
1040 16);
1042 if (!NT_STATUS_IS_OK(status)) {
1043 return status;
1047 h = logon->password->ntpassword.hash;
1048 if (!all_zero(h, 16)) {
1049 if (do_encrypt) {
1050 status = netlogon_creds_aes_encrypt(creds,
1052 16);
1053 } else {
1054 status = netlogon_creds_aes_decrypt(creds,
1056 16);
1058 if (!NT_STATUS_IS_OK(status)) {
1059 return status;
1062 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1063 uint8_t *h;
1065 h = logon->password->lmpassword.hash;
1066 if (!all_zero(h, 16)) {
1067 status = netlogon_creds_arcfour_crypt(creds,
1069 16);
1070 if (!NT_STATUS_IS_OK(status)) {
1071 return status;
1075 h = logon->password->ntpassword.hash;
1076 if (!all_zero(h, 16)) {
1077 status = netlogon_creds_arcfour_crypt(creds,
1079 16);
1080 if (!NT_STATUS_IS_OK(status)) {
1081 return status;
1084 } else {
1085 struct samr_Password *p;
1087 p = &logon->password->lmpassword;
1088 if (!all_zero(p->hash, 16)) {
1089 if (do_encrypt) {
1090 status = netlogon_creds_des_encrypt(creds, p);
1091 } else {
1092 status = netlogon_creds_des_decrypt(creds, p);
1094 if (!NT_STATUS_IS_OK(status)) {
1095 return status;
1098 p = &logon->password->ntpassword;
1099 if (!all_zero(p->hash, 16)) {
1100 if (do_encrypt) {
1101 status = netlogon_creds_des_encrypt(creds, p);
1102 } else {
1103 status = netlogon_creds_des_decrypt(creds, p);
1105 if (!NT_STATUS_IS_OK(status)) {
1106 return status;
1110 break;
1112 case NetlogonNetworkInformation:
1113 case NetlogonNetworkTransitiveInformation:
1114 break;
1116 case NetlogonGenericInformation:
1117 if (logon->generic == NULL) {
1118 return NT_STATUS_INVALID_PARAMETER;
1121 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1122 if (do_encrypt) {
1123 status = netlogon_creds_aes_encrypt(
1124 creds,
1125 logon->generic->data,
1126 logon->generic->length);
1127 } else {
1128 status = netlogon_creds_aes_decrypt(
1129 creds,
1130 logon->generic->data,
1131 logon->generic->length);
1133 if (!NT_STATUS_IS_OK(status)) {
1134 return 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)) {
1141 return status;
1143 } else {
1144 /* Using DES to verify kerberos tickets makes no sense */
1145 return NT_STATUS_INVALID_PARAMETER;
1147 break;
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,
1160 level,
1161 logon,
1162 auth_type,
1163 auth_level,
1164 false);
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,
1174 level,
1175 logon,
1176 auth_type,
1177 auth_level,
1178 true);
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,
1186 bool do_encrypt)
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
1197 if (do_encrypt) {
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,
1210 pass,
1211 auth_type,
1212 auth_level,
1213 false);
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,
1222 pass,
1223 auth_type,
1224 auth_level,
1225 true);
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,
1233 bool do_encrypt)
1235 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1236 if (do_encrypt) {
1237 return netlogon_creds_aes_encrypt(creds,
1238 pass->data,
1239 ARRAY_SIZE(pass->data));
1242 return netlogon_creds_aes_decrypt(creds,
1243 pass->data,
1244 ARRAY_SIZE(pass->data));
1247 return netlogon_creds_arcfour_crypt(creds,
1248 pass->data,
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,
1258 pass,
1259 auth_type,
1260 auth_level,
1261 false);
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,
1270 pass,
1271 auth_type,
1272 auth_level,
1273 true);
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,
1282 bool do_encrypt)
1284 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1285 if (do_encrypt) {
1286 return netlogon_creds_aes_encrypt(creds,
1287 opaque_data,
1288 opaque_length);
1291 return netlogon_creds_aes_decrypt(creds,
1292 opaque_data,
1293 opaque_length);
1296 return netlogon_creds_arcfour_crypt(creds,
1297 opaque_data,
1298 opaque_length);
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,
1308 opaque_data,
1309 opaque_length,
1310 auth_type,
1311 auth_level,
1312 false);
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,
1322 opaque_data,
1323 opaque_length,
1324 auth_type,
1325 auth_level,
1326 true);
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;
1335 if (in == NULL) {
1336 return NULL;
1339 out = talloc(mem_ctx, union netr_LogonLevel);
1340 if (out == NULL) {
1341 return NULL;
1344 *out = *in;
1346 switch (level) {
1347 case NetlogonInteractiveInformation:
1348 case NetlogonInteractiveTransitiveInformation:
1349 case NetlogonServiceInformation:
1350 case NetlogonServiceTransitiveInformation:
1351 if (in->password == NULL) {
1352 return out;
1355 out->password = talloc(out, struct netr_PasswordInfo);
1356 if (out->password == NULL) {
1357 talloc_free(out);
1358 return NULL;
1360 *out->password = *in->password;
1362 return out;
1364 case NetlogonNetworkInformation:
1365 case NetlogonNetworkTransitiveInformation:
1366 break;
1368 case NetlogonGenericInformation:
1369 if (in->generic == NULL) {
1370 return out;
1373 out->generic = talloc(out, struct netr_GenericInfo);
1374 if (out->generic == NULL) {
1375 talloc_free(out);
1376 return NULL;
1378 *out->generic = *in->generic;
1380 if (in->generic->data == NULL) {
1381 return out;
1384 if (in->generic->length == 0) {
1385 return out;
1388 out->generic->data = talloc_memdup(out->generic,
1389 in->generic->data,
1390 in->generic->length);
1391 if (out->generic->data == NULL) {
1392 talloc_free(out);
1393 return NULL;
1396 return out;
1399 return out;
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);
1412 if (!creds) {
1413 return NULL;
1416 *creds = *creds_in;
1418 creds->computer_name = talloc_strdup(creds, creds_in->computer_name);
1419 if (!creds->computer_name) {
1420 talloc_free(creds);
1421 return NULL;
1423 creds->account_name = talloc_strdup(creds, creds_in->account_name);
1424 if (!creds->account_name) {
1425 talloc_free(creds);
1426 return NULL;
1429 if (creds_in->ex != NULL) {
1430 creds->ex = talloc_zero(creds,
1431 struct netlogon_creds_CredentialState_extra_info);
1432 if (creds->ex == NULL) {
1433 talloc_free(creds);
1434 return NULL;
1436 *creds->ex = *creds_in->ex;
1439 return creds;