ctdb-scripts: Improve update and listing code
[samba4-gss.git] / libcli / auth / credentials.c
blob8470815b82eb1be0630e026e7d2a54595a2479f6
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 "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])
53 return false;
56 return true;
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,
62 bool *skip)
64 *skip = false;
66 if (creds == NULL) {
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;
85 *skip = true;
88 return NT_STATUS_OK;
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,
94 bool *skip)
96 *skip = false;
98 if (creds == NULL) {
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;
125 *skip = true;
128 return NT_STATUS_OK;
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)
143 NTSTATUS status;
144 int rc;
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,
157 out->data,
158 sizeof(out->data));
159 if (!NT_STATUS_IS_OK(status)) {
160 return status;
162 } else {
163 rc = des_crypt112(out->data, in->data, creds->session_key, SAMBA_GNUTLS_ENCRYPT);
164 if (rc != 0) {
165 return gnutls_error_to_ntstatus(rc,
166 NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
170 return NT_STATUS_OK;
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)
183 uint32_t sum[2];
184 uint8_t sum2[8];
185 int rc;
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);
196 if (rc != 0) {
197 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
200 return NT_STATUS_OK;
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;
216 int rc;
218 ZERO_ARRAY(creds->session_key);
220 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
221 if (rc < 0) {
222 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
225 rc = gnutls_hash(hash_hnd, zero, sizeof(zero));
226 if (rc < 0) {
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);
231 if (rc < 0) {
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);
236 if (rc < 0) {
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),
247 tmp,
248 sizeof(tmp),
249 creds->session_key);
250 ZERO_ARRAY(tmp);
252 if (rc < 0) {
253 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
256 return NT_STATUS_OK;
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)];
271 int rc;
273 ZERO_ARRAY(creds->session_key);
275 rc = gnutls_hmac_init(&hmac_hnd,
276 GNUTLS_MAC_SHA256,
277 machine_password->hash,
278 sizeof(machine_password->hash));
279 if (rc < 0) {
280 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
282 rc = gnutls_hmac(hmac_hnd,
283 client_challenge->data,
285 if (rc < 0) {
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,
292 if (rc < 0) {
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));
300 ZERO_ARRAY(digest);
302 return NT_STATUS_OK;
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)
309 NTSTATUS status;
311 status = netlogon_creds_step_crypt(creds,
312 client_challenge,
313 &creds->client);
314 if (!NT_STATUS_IS_OK(status)) {
315 return status;
318 status = netlogon_creds_step_crypt(creds,
319 server_challenge,
320 &creds->server);
321 if (!NT_STATUS_IS_OK(status)) {
322 return status;
325 creds->seed = creds->client;
327 return NT_STATUS_OK;
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;
337 NTSTATUS status;
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));
347 return NT_STATUS_OK;
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,
359 &time_cred,
360 &creds->client);
361 if (!NT_STATUS_IS_OK(status)) {
362 return 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)) {
376 return status;
379 DEBUG(5,("\tSERVER %08x:%08x\n",
380 IVAL(creds->server.data, 0), IVAL(creds->server.data, 4)));
382 creds->seed = time_cred;
384 return NT_STATUS_OK;
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)
393 int rc;
394 struct netr_LMSessionKey tmp;
396 rc = des_crypt56_gnutls(tmp.key, key->key, creds->session_key, SAMBA_GNUTLS_ENCRYPT);
397 if (rc < 0) {
398 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
400 *key = tmp;
402 return NT_STATUS_OK;
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)
411 int rc;
412 struct netr_LMSessionKey tmp;
414 rc = des_crypt56_gnutls(tmp.key, key->key, creds->session_key, SAMBA_GNUTLS_DECRYPT);
415 if (rc < 0) {
416 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
418 *key = tmp;
420 return NT_STATUS_OK;
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;
430 int rc;
432 rc = des_crypt112_16(tmp.hash, pass->hash, creds->session_key, SAMBA_GNUTLS_ENCRYPT);
433 if (rc < 0) {
434 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
436 *pass = tmp;
438 return NT_STATUS_OK;
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;
448 int rc;
450 rc = des_crypt112_16(tmp.hash, pass->hash, creds->session_key, SAMBA_GNUTLS_DECRYPT);
451 if (rc < 0) {
452 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
454 *pass = tmp;
456 return NT_STATUS_OK;
460 ARCFOUR encrypt/decrypt a password buffer using the session key
462 NTSTATUS netlogon_creds_arcfour_crypt(struct netlogon_creds_CredentialState *creds,
463 uint8_t *data,
464 size_t len)
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),
471 int rc;
473 rc = gnutls_cipher_init(&cipher_hnd,
474 GNUTLS_CIPHER_ARCFOUR_128,
475 &session_key,
476 NULL);
477 if (rc < 0) {
478 return gnutls_error_to_ntstatus(rc,
479 NT_STATUS_CRYPTO_SYSTEM_INVALID);
481 rc = gnutls_cipher_encrypt(cipher_hnd,
482 data,
483 len);
484 gnutls_cipher_deinit(cipher_hnd);
485 if (rc < 0) {
486 return gnutls_error_to_ntstatus(rc,
487 NT_STATUS_CRYPTO_SYSTEM_INVALID);
490 return NT_STATUS_OK;
494 AES encrypt a password buffer using the session key
496 NTSTATUS netlogon_creds_aes_encrypt(struct netlogon_creds_CredentialState *creds,
497 uint8_t *data,
498 size_t len)
500 gnutls_cipher_hd_t cipher_hnd = NULL;
501 gnutls_datum_t key = {
502 .data = creds->session_key,
503 .size = sizeof(creds->session_key),
505 uint32_t iv_size =
506 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
507 uint8_t _iv[iv_size];
508 gnutls_datum_t iv = {
509 .data = _iv,
510 .size = iv_size,
512 int rc;
514 ZERO_ARRAY(_iv);
516 rc = gnutls_cipher_init(&cipher_hnd,
517 GNUTLS_CIPHER_AES_128_CFB8,
518 &key,
519 &iv);
520 if (rc < 0) {
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);
526 if (rc < 0) {
527 return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
530 return NT_STATUS_OK;
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),
543 uint32_t iv_size =
544 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
545 uint8_t _iv[iv_size];
546 gnutls_datum_t iv = {
547 .data = _iv,
548 .size = iv_size,
550 int rc;
552 ZERO_ARRAY(_iv);
554 rc = gnutls_cipher_init(&cipher_hnd,
555 GNUTLS_CIPHER_AES_128_CFB8,
556 &key,
557 &iv);
558 if (rc < 0) {
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);
565 if (rc < 0) {
566 return gnutls_error_to_ntstatus(rc,
567 NT_STATUS_CRYPTO_SYSTEM_INVALID);
570 return NT_STATUS_OK;
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);
588 if (creds == NULL) {
589 return NULL;
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) {
600 talloc_free(creds);
601 return NULL;
603 creds->account_name = talloc_strdup(creds, client_account);
604 if (!creds->account_name) {
605 talloc_free(creds);
606 return NULL;
609 creds->client_requested_flags = client_requested_flags;
610 creds->auth_time = now;
611 if (client_sid != NULL) {
612 creds->client_sid = *client_sid;
613 } else {
614 creds->client_sid = global_sid_NULL;
617 name = talloc_get_name(creds);
618 _talloc_keep_secret(creds, name);
619 return creds;
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,
633 client_account,
634 client_computer_name,
635 secure_channel_type,
636 client_requested_flags,
637 client_sid,
638 negotiate_flags);
639 if (creds == NULL) {
640 return NULL;
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
655 * is set too.
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));
677 return creds;
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
687 credentials
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;
702 NTSTATUS status;
704 creds = netlogon_creds_alloc(mem_ctx,
705 client_account,
706 client_computer_name,
707 secure_channel_type,
708 client_requested_flags,
709 NULL, /* client_sid */
710 negotiate_flags);
711 if (!creds) {
712 return NULL;
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,
721 client_challenge,
722 server_challenge,
723 machine_password);
724 if (!NT_STATUS_IS_OK(status)) {
725 talloc_free(creds);
726 return NULL;
728 } else if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
729 status = netlogon_creds_init_128bit(creds,
730 client_challenge,
731 server_challenge,
732 machine_password);
733 if (!NT_STATUS_IS_OK(status)) {
734 talloc_free(creds);
735 return NULL;
737 } else {
738 status = netlogon_creds_init_64bit(creds,
739 client_challenge,
740 server_challenge,
741 machine_password);
742 if (!NT_STATUS_IS_OK(status)) {
743 talloc_free(creds);
744 return NULL;
748 status = netlogon_creds_first_step(creds,
749 client_challenge,
750 server_challenge);
751 if (!NT_STATUS_IS_OK(status)) {
752 talloc_free(creds);
753 return NULL;
756 dump_data_pw("Session key", creds->session_key, 16);
757 dump_data_pw("Credential ", creds->client.data, 8);
759 *initial_credential = creds->client;
760 return creds;
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
768 the server
770 NTSTATUS
771 netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState *creds,
772 struct netr_Authenticator *next)
774 uint32_t t32n = (uint32_t)time(NULL);
775 NTSTATUS status;
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;
787 } else {
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)) {
800 return status;
803 next->cred = creds->client;
804 next->timestamp = creds->sequence;
806 return NT_STATUS_OK;
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)
817 NTSTATUS status;
818 bool skip_crypto = false;
820 status = netlogon_creds_no_step_check(creds,
821 auth_type,
822 auth_level,
823 &skip_crypto);
824 if (!NT_STATUS_IS_OK(status)) {
825 return status;
828 if (skip_crypto) {
829 return NT_STATUS_OK;
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;
837 return NT_STATUS_OK;
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;
845 NTSTATUS status;
847 status = netlogon_creds_client_verify(creds,
848 received_credentials,
849 auth_type,
850 auth_level);
851 if (!NT_STATUS_IS_OK(status)) {
852 return false;
855 return true;
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);
874 return false;
876 return true;
880 initialise the credentials chain and return the first server
881 credentials
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;
897 NTSTATUS status;
898 bool ok;
900 creds = netlogon_creds_alloc(mem_ctx,
901 client_account,
902 client_computer_name,
903 secure_channel_type,
904 client_requested_flags,
905 client_sid,
906 negotiate_flags);
907 if (!creds) {
908 return NULL;
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);
916 if (!ok) {
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));
925 talloc_free(creds);
926 return NULL;
929 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
930 status = netlogon_creds_init_hmac_sha256(creds,
931 client_challenge,
932 server_challenge,
933 machine_password);
934 if (!NT_STATUS_IS_OK(status)) {
935 talloc_free(creds);
936 return NULL;
938 } else if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
939 status = netlogon_creds_init_128bit(creds,
940 client_challenge,
941 server_challenge,
942 machine_password);
943 if (!NT_STATUS_IS_OK(status)) {
944 talloc_free(creds);
945 return NULL;
947 } else {
948 status = netlogon_creds_init_64bit(creds,
949 client_challenge,
950 server_challenge,
951 machine_password);
952 if (!NT_STATUS_IS_OK(status)) {
953 talloc_free(creds);
954 return NULL;
958 status = netlogon_creds_first_step(creds,
959 client_challenge,
960 server_challenge);
961 if (!NT_STATUS_IS_OK(status)) {
962 talloc_free(creds);
963 return NULL;
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)) {
975 talloc_free(creds);
976 return NULL;
979 *credentials_out = creds->server;
981 dump_data_pw("Credentials out", credentials_out->data, sizeof(credentials_out->data));
983 return creds;
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)
992 NTSTATUS status;
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,
1000 auth_type,
1001 auth_level,
1002 &skip_crypto);
1003 if (!NT_STATUS_IS_OK(status)) {
1004 ZERO_STRUCTP(return_authenticator);
1005 return status;
1007 if (skip_crypto) {
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);
1016 return status;
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;
1023 } else {
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,
1034 bool do_encrypt)
1036 struct netr_SamBaseInfo *base = NULL;
1037 NTSTATUS status;
1038 bool skip_crypto = false;
1040 if (validation == NULL) {
1041 return NT_STATUS_INVALID_PARAMETER;
1044 switch (validation_level) {
1045 case 2:
1046 if (validation->sam2) {
1047 base = &validation->sam2->base;
1049 break;
1050 case 3:
1051 if (validation->sam3) {
1052 base = &validation->sam3->base;
1054 break;
1055 case 5:
1056 /* NetlogonValidationGenericInfo2 */
1057 if (validation->generic != NULL &&
1058 validation->generic->length == 0)
1061 * For "Kerberos"
1062 * KERB_VERIFY_PAC_REQUEST there's
1063 * not response, so there's nothing
1064 * to encrypt.
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
1078 * for now.
1080 log_stack_trace();
1081 return NT_STATUS_INTERNAL_ERROR;
1082 case 6:
1083 if (validation->sam6) {
1084 base = &validation->sam6->base;
1086 break;
1087 case 7:
1088 /* NetlogonValidationTicketLogon */
1089 return NT_STATUS_OK;
1090 default:
1091 /* If we can't find it, we can't very well decrypt it */
1092 return NT_STATUS_INVALID_INFO_CLASS;
1095 if (!base) {
1096 return NT_STATUS_INVALID_INFO_CLASS;
1099 status = netlogon_creds_no_buffer_crypt(creds,
1100 auth_type,
1101 auth_level,
1102 &skip_crypto);
1103 if (!NT_STATUS_IS_OK(status)) {
1104 return 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))) {
1120 if (do_encrypt) {
1121 status = netlogon_creds_aes_encrypt(
1122 creds,
1123 base->key.key,
1124 sizeof(base->key.key));
1125 } else {
1126 status = netlogon_creds_aes_decrypt(
1127 creds,
1128 base->key.key,
1129 sizeof(base->key.key));
1131 if (!NT_STATUS_IS_OK(status)) {
1132 return status;
1136 if (creds->authenticate_kerberos ||
1137 !all_zero(base->LMSessKey.key,
1138 sizeof(base->LMSessKey.key))) {
1139 if (do_encrypt) {
1140 status = netlogon_creds_aes_encrypt(
1141 creds,
1142 base->LMSessKey.key,
1143 sizeof(base->LMSessKey.key));
1144 } else {
1145 status = netlogon_creds_aes_decrypt(
1146 creds,
1147 base->LMSessKey.key,
1148 sizeof(base->LMSessKey.key));
1150 if (!NT_STATUS_IS_OK(status)) {
1151 return 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,
1165 base->key.key,
1166 sizeof(base->key.key));
1167 if (!NT_STATUS_IS_OK(status)) {
1168 return 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)) {
1179 return status;
1182 } else {
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))) {
1193 if (do_encrypt) {
1194 status = netlogon_creds_des_encrypt_LMKey(creds,
1195 &base->LMSessKey);
1196 } else {
1197 status = netlogon_creds_des_decrypt_LMKey(creds,
1198 &base->LMSessKey);
1200 if (!NT_STATUS_IS_OK(status)) {
1201 return 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,
1216 validation_level,
1217 validation,
1218 auth_type,
1219 auth_level,
1220 false);
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,
1230 validation_level,
1231 validation,
1232 auth_type,
1233 auth_level,
1234 true);
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,
1242 bool do_encrypt)
1244 NTSTATUS status;
1245 bool skip_crypto = false;
1247 status = netlogon_creds_no_buffer_crypt(creds,
1248 auth_type,
1249 auth_level,
1250 &skip_crypto);
1251 if (!NT_STATUS_IS_OK(status)) {
1252 return status;
1255 if (logon == NULL) {
1256 return NT_STATUS_INVALID_PARAMETER;
1259 switch (level) {
1260 case NetlogonInteractiveInformation:
1261 case NetlogonInteractiveTransitiveInformation:
1262 case NetlogonServiceInformation:
1263 case NetlogonServiceTransitiveInformation:
1264 if (logon->password == NULL) {
1265 return NT_STATUS_INVALID_PARAMETER;
1268 if (skip_crypto) {
1269 break;
1272 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1273 uint8_t *h;
1275 h = logon->password->lmpassword.hash;
1276 if (!all_zero(h, 16)) {
1277 if (do_encrypt) {
1278 status = netlogon_creds_aes_encrypt(
1279 creds,
1281 16);
1282 } else {
1283 status = netlogon_creds_aes_decrypt(
1284 creds,
1286 16);
1288 if (!NT_STATUS_IS_OK(status)) {
1289 return status;
1293 h = logon->password->ntpassword.hash;
1294 if (!all_zero(h, 16)) {
1295 if (do_encrypt) {
1296 status = netlogon_creds_aes_encrypt(creds,
1298 16);
1299 } else {
1300 status = netlogon_creds_aes_decrypt(creds,
1302 16);
1304 if (!NT_STATUS_IS_OK(status)) {
1305 return status;
1308 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1309 uint8_t *h;
1311 h = logon->password->lmpassword.hash;
1312 if (!all_zero(h, 16)) {
1313 status = netlogon_creds_arcfour_crypt(creds,
1315 16);
1316 if (!NT_STATUS_IS_OK(status)) {
1317 return status;
1321 h = logon->password->ntpassword.hash;
1322 if (!all_zero(h, 16)) {
1323 status = netlogon_creds_arcfour_crypt(creds,
1325 16);
1326 if (!NT_STATUS_IS_OK(status)) {
1327 return status;
1330 } else {
1331 struct samr_Password *p;
1333 p = &logon->password->lmpassword;
1334 if (!all_zero(p->hash, 16)) {
1335 if (do_encrypt) {
1336 status = netlogon_creds_des_encrypt(creds, p);
1337 } else {
1338 status = netlogon_creds_des_decrypt(creds, p);
1340 if (!NT_STATUS_IS_OK(status)) {
1341 return status;
1344 p = &logon->password->ntpassword;
1345 if (!all_zero(p->hash, 16)) {
1346 if (do_encrypt) {
1347 status = netlogon_creds_des_encrypt(creds, p);
1348 } else {
1349 status = netlogon_creds_des_decrypt(creds, p);
1351 if (!NT_STATUS_IS_OK(status)) {
1352 return status;
1356 break;
1358 case NetlogonNetworkInformation:
1359 case NetlogonNetworkTransitiveInformation:
1360 break;
1362 case NetlogonGenericInformation:
1363 if (logon->generic == NULL) {
1364 return NT_STATUS_INVALID_PARAMETER;
1367 if (skip_crypto) {
1368 break;
1371 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1372 if (do_encrypt) {
1373 status = netlogon_creds_aes_encrypt(
1374 creds,
1375 logon->generic->data,
1376 logon->generic->length);
1377 } else {
1378 status = netlogon_creds_aes_decrypt(
1379 creds,
1380 logon->generic->data,
1381 logon->generic->length);
1383 if (!NT_STATUS_IS_OK(status)) {
1384 return 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)) {
1391 return 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;
1400 break;
1402 case NetlogonTicketLogonInformation:
1403 break;
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,
1416 level,
1417 logon,
1418 auth_type,
1419 auth_level,
1420 false);
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,
1430 level,
1431 logon,
1432 auth_type,
1433 auth_level,
1434 true);
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,
1442 bool do_encrypt)
1444 NTSTATUS status;
1445 bool skip_crypto = false;
1447 status = netlogon_creds_no_buffer_crypt(creds,
1448 auth_type,
1449 auth_level,
1450 &skip_crypto);
1451 if (!NT_STATUS_IS_OK(status)) {
1452 return status;
1455 if (skip_crypto) {
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
1468 if (do_encrypt) {
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,
1481 pass,
1482 auth_type,
1483 auth_level,
1484 false);
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,
1493 pass,
1494 auth_type,
1495 auth_level,
1496 true);
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,
1504 bool do_encrypt)
1506 NTSTATUS status;
1507 bool skip_crypto = false;
1509 status = netlogon_creds_no_buffer_crypt(creds,
1510 auth_type,
1511 auth_level,
1512 &skip_crypto);
1513 if (!NT_STATUS_IS_OK(status)) {
1514 return status;
1517 if (skip_crypto) {
1518 return NT_STATUS_OK;
1521 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1522 if (do_encrypt) {
1523 return netlogon_creds_aes_encrypt(creds,
1524 pass->data,
1525 ARRAY_SIZE(pass->data));
1528 return netlogon_creds_aes_decrypt(creds,
1529 pass->data,
1530 ARRAY_SIZE(pass->data));
1533 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1534 return netlogon_creds_arcfour_crypt(creds,
1535 pass->data,
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,
1556 pass,
1557 auth_type,
1558 auth_level,
1559 false);
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,
1568 pass,
1569 auth_type,
1570 auth_level,
1571 true);
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,
1580 bool do_encrypt)
1582 NTSTATUS status;
1583 bool skip_crypto = false;
1585 status = netlogon_creds_no_buffer_crypt(creds,
1586 auth_type,
1587 auth_level,
1588 &skip_crypto);
1589 if (!NT_STATUS_IS_OK(status)) {
1590 return status;
1593 if (skip_crypto) {
1594 return NT_STATUS_OK;
1597 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1598 if (do_encrypt) {
1599 return netlogon_creds_aes_encrypt(creds,
1600 opaque_data,
1601 opaque_length);
1604 return netlogon_creds_aes_decrypt(creds,
1605 opaque_data,
1606 opaque_length);
1609 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1610 return netlogon_creds_arcfour_crypt(creds,
1611 opaque_data,
1612 opaque_length);
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,
1633 opaque_data,
1634 opaque_length,
1635 auth_type,
1636 auth_level,
1637 false);
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,
1647 opaque_data,
1648 opaque_length,
1649 auth_type,
1650 auth_level,
1651 true);
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;
1660 if (in == NULL) {
1661 return NULL;
1664 out = talloc(mem_ctx, union netr_LogonLevel);
1665 if (out == NULL) {
1666 return NULL;
1669 *out = *in;
1671 switch (level) {
1672 case NetlogonInteractiveInformation:
1673 case NetlogonInteractiveTransitiveInformation:
1674 case NetlogonServiceInformation:
1675 case NetlogonServiceTransitiveInformation:
1676 if (in->password == NULL) {
1677 return out;
1680 out->password = talloc(out, struct netr_PasswordInfo);
1681 if (out->password == NULL) {
1682 talloc_free(out);
1683 return NULL;
1685 *out->password = *in->password;
1687 return out;
1689 case NetlogonNetworkInformation:
1690 case NetlogonNetworkTransitiveInformation:
1691 break;
1693 case NetlogonGenericInformation:
1694 if (in->generic == NULL) {
1695 return out;
1698 out->generic = talloc(out, struct netr_GenericInfo);
1699 if (out->generic == NULL) {
1700 talloc_free(out);
1701 return NULL;
1703 *out->generic = *in->generic;
1705 if (in->generic->data == NULL) {
1706 return out;
1709 if (in->generic->length == 0) {
1710 return out;
1713 out->generic->data = talloc_memdup(out->generic,
1714 in->generic->data,
1715 in->generic->length);
1716 if (out->generic->data == NULL) {
1717 talloc_free(out);
1718 return NULL;
1721 return out;
1723 case NetlogonTicketLogonInformation:
1724 break;
1727 return out;
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;
1741 if (!creds) {
1742 return NULL;
1745 ndr_err = ndr_deepcopy_struct(netlogon_creds_CredentialState,
1746 creds_in, creds, creds);
1747 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1748 TALLOC_FREE(creds);
1749 return NULL;
1752 return creds;