LCOV - code coverage report
Current view: top level - libcli/auth - credentials.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 408 557 73.2 %
Date: 2024-02-28 12:06:22 Functions: 28 30 93.3 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    code to manipulate domain credentials
       5             : 
       6             :    Copyright (C) Andrew Tridgell 1997-2003
       7             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
       8             : 
       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.
      13             : 
      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.
      18             : 
      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/>.
      21             : */
      22             : 
      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"
      28             : 
      29             : #include "lib/crypto/gnutls_helpers.h"
      30             : #include <gnutls/gnutls.h>
      31             : #include <gnutls/crypto.h>
      32             : 
      33       27861 : bool netlogon_creds_is_random_challenge(const struct netr_Credential *challenge)
      34             : {
      35             :         /*
      36             :          * If none of the first 5 bytes of the client challenge is unique, the
      37             :          * server MUST fail session-key negotiation without further processing
      38             :          * of the following steps.
      39             :          */
      40             : 
      41       27861 :         if (challenge->data[1] == challenge->data[0] &&
      42       13117 :             challenge->data[2] == challenge->data[0] &&
      43       13054 :             challenge->data[3] == challenge->data[0] &&
      44       13054 :             challenge->data[4] == challenge->data[0])
      45             :         {
      46       13043 :                 return false;
      47             :         }
      48             : 
      49       13509 :         return true;
      50             : }
      51             : 
      52       13021 : void netlogon_creds_random_challenge(struct netr_Credential *challenge)
      53             : {
      54       13021 :         ZERO_STRUCTP(challenge);
      55       26042 :         while (!netlogon_creds_is_random_challenge(challenge)) {
      56       13021 :                 generate_random_buffer(challenge->data, sizeof(challenge->data));
      57             :         }
      58       13021 : }
      59             : 
      60       74822 : static NTSTATUS netlogon_creds_step_crypt(struct netlogon_creds_CredentialState *creds,
      61             :                                           const struct netr_Credential *in,
      62             :                                           struct netr_Credential *out)
      63             : {
      64        7172 :         NTSTATUS status;
      65        7172 :         int rc;
      66             : 
      67       74822 :         if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
      68       47052 :                 memcpy(out->data, in->data, sizeof(out->data));
      69             : 
      70       47052 :                 status = netlogon_creds_aes_encrypt(creds,
      71       41612 :                                                     out->data,
      72             :                                                     sizeof(out->data));
      73       47052 :                 if (!NT_STATUS_IS_OK(status)) {
      74           0 :                         return status;
      75             :                 }
      76             :         } else {
      77       27770 :                 rc = des_crypt112(out->data, in->data, creds->session_key, SAMBA_GNUTLS_ENCRYPT);
      78       27770 :                 if (rc != 0) {
      79           0 :                         return gnutls_error_to_ntstatus(rc,
      80             :                                                         NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
      81             :                 }
      82             :         }
      83             : 
      84       74822 :         return NT_STATUS_OK;
      85             : }
      86             : 
      87             : /*
      88             :   initialise the credentials state for old-style 64 bit session keys
      89             : 
      90             :   this call is made after the netr_ServerReqChallenge call
      91             : */
      92         459 : static NTSTATUS netlogon_creds_init_64bit(struct netlogon_creds_CredentialState *creds,
      93             :                                          const struct netr_Credential *client_challenge,
      94             :                                          const struct netr_Credential *server_challenge,
      95             :                                          const struct samr_Password *machine_password)
      96             : {
      97          48 :         uint32_t sum[2];
      98          48 :         uint8_t sum2[8];
      99          48 :         int rc;
     100             : 
     101         459 :         sum[0] = IVAL(client_challenge->data, 0) + IVAL(server_challenge->data, 0);
     102         459 :         sum[1] = IVAL(client_challenge->data, 4) + IVAL(server_challenge->data, 4);
     103             : 
     104         459 :         SIVAL(sum2,0,sum[0]);
     105         459 :         SIVAL(sum2,4,sum[1]);
     106             : 
     107         459 :         ZERO_ARRAY(creds->session_key);
     108             : 
     109         459 :         rc = des_crypt128(creds->session_key, sum2, machine_password->hash);
     110         459 :         if (rc != 0) {
     111           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
     112             :         }
     113             : 
     114         459 :         return NT_STATUS_OK;
     115             : }
     116             : 
     117             : /*
     118             :   initialise the credentials state for ADS-style 128 bit session keys
     119             : 
     120             :   this call is made after the netr_ServerReqChallenge call
     121             : */
     122         370 : static NTSTATUS netlogon_creds_init_128bit(struct netlogon_creds_CredentialState *creds,
     123             :                                        const struct netr_Credential *client_challenge,
     124             :                                        const struct netr_Credential *server_challenge,
     125             :                                        const struct samr_Password *machine_password)
     126         370 : {
     127         370 :         uint8_t zero[4] = {0};
     128        1014 :         uint8_t tmp[gnutls_hash_get_len(GNUTLS_DIG_MD5)];
     129         370 :         gnutls_hash_hd_t hash_hnd = NULL;
     130          48 :         int rc;
     131             : 
     132         370 :         ZERO_ARRAY(creds->session_key);
     133             : 
     134         370 :         rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
     135         370 :         if (rc < 0) {
     136           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
     137             :         }
     138             : 
     139         370 :         rc = gnutls_hash(hash_hnd, zero, sizeof(zero));
     140         370 :         if (rc < 0) {
     141           0 :                 gnutls_hash_deinit(hash_hnd, NULL);
     142           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
     143             :         }
     144         370 :         rc = gnutls_hash(hash_hnd, client_challenge->data, 8);
     145         370 :         if (rc < 0) {
     146           0 :                 gnutls_hash_deinit(hash_hnd, NULL);
     147           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
     148             :         }
     149         370 :         rc = gnutls_hash(hash_hnd, server_challenge->data, 8);
     150         370 :         if (rc < 0) {
     151           0 :                 gnutls_hash_deinit(hash_hnd, NULL);
     152           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
     153             :         }
     154             : 
     155         370 :         gnutls_hash_deinit(hash_hnd, tmp);
     156             : 
     157             :         /* This doesn't require HMAC MD5 RFC2104 as the hash is only 16 bytes */
     158         418 :         rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
     159         370 :                               machine_password->hash,
     160             :                               sizeof(machine_password->hash),
     161             :                               tmp,
     162         322 :                               sizeof(tmp),
     163         322 :                               creds->session_key);
     164         370 :         ZERO_ARRAY(tmp);
     165             : 
     166         370 :         if (rc < 0) {
     167           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
     168             :         }
     169             : 
     170         370 :         return NT_STATUS_OK;
     171             : }
     172             : 
     173             : /*
     174             :   initialise the credentials state for AES/HMAC-SHA256-style 128 bit session keys
     175             : 
     176             :   this call is made after the netr_ServerReqChallenge call
     177             : */
     178       12635 : static NTSTATUS netlogon_creds_init_hmac_sha256(struct netlogon_creds_CredentialState *creds,
     179             :                                                 const struct netr_Credential *client_challenge,
     180             :                                                 const struct netr_Credential *server_challenge,
     181             :                                                 const struct samr_Password *machine_password)
     182       12635 : {
     183       12635 :         gnutls_hmac_hd_t hmac_hnd = NULL;
     184       24205 :         uint8_t digest[gnutls_hmac_get_len(GNUTLS_MAC_SHA256)];
     185        1065 :         int rc;
     186             : 
     187       12635 :         ZERO_ARRAY(creds->session_key);
     188             : 
     189       13700 :         rc = gnutls_hmac_init(&hmac_hnd,
     190             :                               GNUTLS_MAC_SHA256,
     191       12635 :                               machine_password->hash,
     192             :                               sizeof(machine_password->hash));
     193       12635 :         if (rc < 0) {
     194           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     195             :         }
     196       13700 :         rc = gnutls_hmac(hmac_hnd,
     197       12635 :                          client_challenge->data,
     198             :                          8);
     199       12635 :         if (rc < 0) {
     200           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     201           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     202             :         }
     203       13700 :         rc  = gnutls_hmac(hmac_hnd,
     204       12635 :                           server_challenge->data,
     205             :                           8);
     206       12635 :         if (rc < 0) {
     207           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     208           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     209             :         }
     210       12635 :         gnutls_hmac_deinit(hmac_hnd, digest);
     211             : 
     212       12635 :         memcpy(creds->session_key, digest, sizeof(creds->session_key));
     213             : 
     214       12635 :         ZERO_ARRAY(digest);
     215             : 
     216       12635 :         return NT_STATUS_OK;
     217             : }
     218             : 
     219       13464 : static NTSTATUS netlogon_creds_first_step(struct netlogon_creds_CredentialState *creds,
     220             :                                           const struct netr_Credential *client_challenge,
     221             :                                           const struct netr_Credential *server_challenge)
     222             : {
     223        1161 :         NTSTATUS status;
     224             : 
     225       13464 :         status = netlogon_creds_step_crypt(creds,
     226             :                                            client_challenge,
     227             :                                            &creds->client);
     228       13464 :         if (!NT_STATUS_IS_OK(status)) {
     229           0 :                 return status;
     230             :         }
     231             : 
     232       13464 :         status = netlogon_creds_step_crypt(creds,
     233             :                                            server_challenge,
     234             :                                            &creds->server);
     235       13464 :         if (!NT_STATUS_IS_OK(status)) {
     236           0 :                 return status;
     237             :         }
     238             : 
     239       13464 :         creds->seed = creds->client;
     240             : 
     241       13464 :         return NT_STATUS_OK;
     242             : }
     243             : 
     244             : /*
     245             :   step the credentials to the next element in the chain, updating the
     246             :   current client and server credentials and the seed
     247             : */
     248       23947 : static NTSTATUS netlogon_creds_step(struct netlogon_creds_CredentialState *creds)
     249             : {
     250        2425 :         struct netr_Credential time_cred;
     251        2425 :         NTSTATUS status;
     252             : 
     253       23947 :         DEBUG(5,("\tseed        %08x:%08x\n",
     254             :                  IVAL(creds->seed.data, 0), IVAL(creds->seed.data, 4)));
     255             : 
     256       23947 :         SIVAL(time_cred.data, 0, IVAL(creds->seed.data, 0) + creds->sequence);
     257       23947 :         SIVAL(time_cred.data, 4, IVAL(creds->seed.data, 4));
     258             : 
     259       23947 :         DEBUG(5,("\tseed+time   %08x:%08x\n", IVAL(time_cred.data, 0), IVAL(time_cred.data, 4)));
     260             : 
     261       23947 :         status = netlogon_creds_step_crypt(creds,
     262             :                                            &time_cred,
     263             :                                            &creds->client);
     264       23947 :         if (!NT_STATUS_IS_OK(status)) {
     265           0 :                 return status;
     266             :         }
     267             : 
     268       23947 :         DEBUG(5,("\tCLIENT      %08x:%08x\n",
     269             :                  IVAL(creds->client.data, 0), IVAL(creds->client.data, 4)));
     270             : 
     271       23947 :         SIVAL(time_cred.data, 0, IVAL(creds->seed.data, 0) + creds->sequence + 1);
     272       23947 :         SIVAL(time_cred.data, 4, IVAL(creds->seed.data, 4));
     273             : 
     274       23947 :         DEBUG(5,("\tseed+time+1 %08x:%08x\n",
     275             :                  IVAL(time_cred.data, 0), IVAL(time_cred.data, 4)));
     276             : 
     277       23947 :         status = netlogon_creds_step_crypt(creds, &time_cred, &creds->server);
     278       23947 :         if (!NT_STATUS_IS_OK(status)) {
     279           0 :                 return status;
     280             :         }
     281             : 
     282       23947 :         DEBUG(5,("\tSERVER      %08x:%08x\n",
     283             :                  IVAL(creds->server.data, 0), IVAL(creds->server.data, 4)));
     284             : 
     285       23947 :         creds->seed = time_cred;
     286             : 
     287       23947 :         return NT_STATUS_OK;
     288             : }
     289             : 
     290             : /*
     291             :   DES encrypt a 8 byte LMSessionKey buffer using the Netlogon session key
     292             : */
     293          54 : NTSTATUS netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState *creds,
     294             :                                           struct netr_LMSessionKey *key)
     295             : {
     296           0 :         int rc;
     297           0 :         struct netr_LMSessionKey tmp;
     298             : 
     299          54 :         rc = des_crypt56_gnutls(tmp.key, key->key, creds->session_key, SAMBA_GNUTLS_ENCRYPT);
     300          54 :         if (rc < 0) {
     301           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
     302             :         }
     303          54 :         *key = tmp;
     304             : 
     305          54 :         return NT_STATUS_OK;
     306             : }
     307             : 
     308             : /*
     309             :   DES decrypt a 8 byte LMSessionKey buffer using the Netlogon session key
     310             : */
     311           0 : NTSTATUS netlogon_creds_des_decrypt_LMKey(struct netlogon_creds_CredentialState *creds,
     312             :                                           struct netr_LMSessionKey *key)
     313             : {
     314           0 :         int rc;
     315           0 :         struct netr_LMSessionKey tmp;
     316             : 
     317           0 :         rc = des_crypt56_gnutls(tmp.key, key->key, creds->session_key, SAMBA_GNUTLS_DECRYPT);
     318           0 :         if (rc < 0) {
     319           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
     320             :         }
     321           0 :         *key = tmp;
     322             : 
     323           0 :         return NT_STATUS_OK;
     324             : }
     325             : 
     326             : /*
     327             :   DES encrypt a 16 byte password buffer using the session key
     328             : */
     329         245 : NTSTATUS netlogon_creds_des_encrypt(struct netlogon_creds_CredentialState *creds,
     330             :                                     struct samr_Password *pass)
     331             : {
     332          21 :         struct samr_Password tmp;
     333          21 :         int rc;
     334             : 
     335         245 :         rc = des_crypt112_16(tmp.hash, pass->hash, creds->session_key, SAMBA_GNUTLS_ENCRYPT);
     336         245 :         if (rc < 0) {
     337           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
     338             :         }
     339         245 :         *pass = tmp;
     340             : 
     341         245 :         return NT_STATUS_OK;
     342             : }
     343             : 
     344             : /*
     345             :   DES decrypt a 16 byte password buffer using the session key
     346             : */
     347         100 : NTSTATUS netlogon_creds_des_decrypt(struct netlogon_creds_CredentialState *creds,
     348             :                                     struct samr_Password *pass)
     349             : {
     350          12 :         struct samr_Password tmp;
     351          12 :         int rc;
     352             : 
     353         100 :         rc = des_crypt112_16(tmp.hash, pass->hash, creds->session_key, SAMBA_GNUTLS_DECRYPT);
     354         100 :         if (rc < 0) {
     355           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
     356             :         }
     357         100 :         *pass = tmp;
     358             : 
     359         100 :         return NT_STATUS_OK;
     360             : }
     361             : 
     362             : /*
     363             :   ARCFOUR encrypt/decrypt a password buffer using the session key
     364             : */
     365       10899 : NTSTATUS netlogon_creds_arcfour_crypt(struct netlogon_creds_CredentialState *creds,
     366             :                                       uint8_t *data,
     367             :                                       size_t len)
     368             : {
     369       10899 :         gnutls_cipher_hd_t cipher_hnd = NULL;
     370       10899 :         gnutls_datum_t session_key = {
     371       10899 :                 .data = creds->session_key,
     372             :                 .size = sizeof(creds->session_key),
     373             :         };
     374         985 :         int rc;
     375             : 
     376       10899 :         rc = gnutls_cipher_init(&cipher_hnd,
     377             :                                 GNUTLS_CIPHER_ARCFOUR_128,
     378             :                                 &session_key,
     379             :                                 NULL);
     380       10899 :         if (rc < 0) {
     381           0 :                 return gnutls_error_to_ntstatus(rc,
     382             :                                                 NT_STATUS_CRYPTO_SYSTEM_INVALID);
     383             :         }
     384       10899 :         rc = gnutls_cipher_encrypt(cipher_hnd,
     385             :                                    data,
     386             :                                    len);
     387       10899 :         gnutls_cipher_deinit(cipher_hnd);
     388       10899 :         if (rc < 0) {
     389           0 :                 return gnutls_error_to_ntstatus(rc,
     390             :                                                 NT_STATUS_CRYPTO_SYSTEM_INVALID);
     391             :         }
     392             : 
     393       10899 :         return NT_STATUS_OK;
     394             : }
     395             : 
     396             : /*
     397             :   AES encrypt a password buffer using the session key
     398             : */
     399       57084 : NTSTATUS netlogon_creds_aes_encrypt(struct netlogon_creds_CredentialState *creds,
     400             :                                     uint8_t *data,
     401             :                                     size_t len)
     402       57084 : {
     403       57084 :         gnutls_cipher_hd_t cipher_hnd = NULL;
     404       57084 :         gnutls_datum_t key = {
     405       57084 :                 .data = creds->session_key,
     406             :                 .size = sizeof(creds->session_key),
     407             :         };
     408        7095 :         uint32_t iv_size =
     409       57084 :                 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
     410       57084 :         uint8_t _iv[iv_size];
     411       57084 :         gnutls_datum_t iv = {
     412             :                 .data = _iv,
     413             :                 .size = iv_size,
     414             :         };
     415        7095 :         int rc;
     416             : 
     417       57084 :         ZERO_ARRAY(_iv);
     418             : 
     419       57084 :         rc = gnutls_cipher_init(&cipher_hnd,
     420             :                                 GNUTLS_CIPHER_AES_128_CFB8,
     421             :                                 &key,
     422             :                                 &iv);
     423       57084 :         if (rc < 0) {
     424           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     425             :         }
     426             : 
     427       57084 :         rc = gnutls_cipher_encrypt(cipher_hnd, data, len);
     428       57084 :         gnutls_cipher_deinit(cipher_hnd);
     429       57084 :         if (rc < 0) {
     430           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     431             :         }
     432             : 
     433       57084 :         return NT_STATUS_OK;
     434             : }
     435             : 
     436             : /*
     437             :   AES decrypt a password buffer using the session key
     438             : */
     439        3770 : NTSTATUS netlogon_creds_aes_decrypt(struct netlogon_creds_CredentialState *creds, uint8_t *data, size_t len)
     440        3770 : {
     441        3770 :         gnutls_cipher_hd_t cipher_hnd = NULL;
     442        3770 :         gnutls_datum_t key = {
     443        3770 :                 .data = creds->session_key,
     444             :                 .size = sizeof(creds->session_key),
     445             :         };
     446         406 :         uint32_t iv_size =
     447        3770 :                 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
     448        3770 :         uint8_t _iv[iv_size];
     449        3770 :         gnutls_datum_t iv = {
     450             :                 .data = _iv,
     451             :                 .size = iv_size,
     452             :         };
     453         406 :         int rc;
     454             : 
     455        3770 :         ZERO_ARRAY(_iv);
     456             : 
     457        3770 :         rc = gnutls_cipher_init(&cipher_hnd,
     458             :                                 GNUTLS_CIPHER_AES_128_CFB8,
     459             :                                 &key,
     460             :                                 &iv);
     461        3770 :         if (rc < 0) {
     462           0 :                 return gnutls_error_to_ntstatus(rc,
     463             :                                                 NT_STATUS_CRYPTO_SYSTEM_INVALID);
     464             :         }
     465             : 
     466        3770 :         rc = gnutls_cipher_decrypt(cipher_hnd, data, len);
     467        3770 :         gnutls_cipher_deinit(cipher_hnd);
     468        3770 :         if (rc < 0) {
     469           0 :                 return gnutls_error_to_ntstatus(rc,
     470             :                                                 NT_STATUS_CRYPTO_SYSTEM_INVALID);
     471             :         }
     472             : 
     473        3770 :         return NT_STATUS_OK;
     474             : }
     475             : 
     476             : /*****************************************************************
     477             : The above functions are common to the client and server interface
     478             : next comes the client specific functions
     479             : ******************************************************************/
     480             : 
     481             : /*
     482             :   initialise the credentials chain and return the first client
     483             :   credentials
     484             : */
     485             : 
     486       11667 : struct netlogon_creds_CredentialState *netlogon_creds_client_init(TALLOC_CTX *mem_ctx,
     487             :                                                                   const char *client_account,
     488             :                                                                   const char *client_computer_name,
     489             :                                                                   uint16_t secure_channel_type,
     490             :                                                                   const struct netr_Credential *client_challenge,
     491             :                                                                   const struct netr_Credential *server_challenge,
     492             :                                                                   const struct samr_Password *machine_password,
     493             :                                                                   struct netr_Credential *initial_credential,
     494             :                                                                   uint32_t negotiate_flags)
     495             : {
     496       11667 :         struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
     497        1001 :         NTSTATUS status;
     498             : 
     499       11667 :         if (!creds) {
     500           0 :                 return NULL;
     501             :         }
     502             : 
     503       11667 :         creds->sequence = time(NULL);
     504       11667 :         creds->negotiate_flags = negotiate_flags;
     505       11667 :         creds->secure_channel_type = secure_channel_type;
     506             : 
     507       11667 :         creds->computer_name = talloc_strdup(creds, client_computer_name);
     508       11667 :         if (!creds->computer_name) {
     509           0 :                 talloc_free(creds);
     510           0 :                 return NULL;
     511             :         }
     512       11667 :         creds->account_name = talloc_strdup(creds, client_account);
     513       11667 :         if (!creds->account_name) {
     514           0 :                 talloc_free(creds);
     515           0 :                 return NULL;
     516             :         }
     517             : 
     518       11667 :         dump_data_pw("Client chall", client_challenge->data, sizeof(client_challenge->data));
     519       11667 :         dump_data_pw("Server chall", server_challenge->data, sizeof(server_challenge->data));
     520       11667 :         dump_data_pw("Machine Pass", machine_password->hash, sizeof(machine_password->hash));
     521             : 
     522       11667 :         if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     523       11163 :                 status = netlogon_creds_init_hmac_sha256(creds,
     524             :                                                          client_challenge,
     525             :                                                          server_challenge,
     526             :                                                          machine_password);
     527       11163 :                 if (!NT_STATUS_IS_OK(status)) {
     528           0 :                         talloc_free(creds);
     529           0 :                         return NULL;
     530             :                 }
     531         504 :         } else if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
     532         189 :                 status = netlogon_creds_init_128bit(creds,
     533             :                                                     client_challenge,
     534             :                                                     server_challenge,
     535             :                                                     machine_password);
     536         189 :                 if (!NT_STATUS_IS_OK(status)) {
     537           0 :                         talloc_free(creds);
     538           0 :                         return NULL;
     539             :                 }
     540             :         } else {
     541         315 :                 status = netlogon_creds_init_64bit(creds,
     542             :                                                    client_challenge,
     543             :                                                    server_challenge,
     544             :                                                    machine_password);
     545         315 :                 if (!NT_STATUS_IS_OK(status)) {
     546           0 :                         talloc_free(creds);
     547           0 :                         return NULL;
     548             :                 }
     549             :         }
     550             : 
     551       11667 :         status = netlogon_creds_first_step(creds,
     552             :                                            client_challenge,
     553             :                                            server_challenge);
     554       11667 :         if (!NT_STATUS_IS_OK(status)) {
     555           0 :                 talloc_free(creds);
     556           0 :                 return NULL;
     557             :         }
     558             : 
     559       11667 :         dump_data_pw("Session key", creds->session_key, 16);
     560       11667 :         dump_data_pw("Credential ", creds->client.data, 8);
     561             : 
     562       11667 :         *initial_credential = creds->client;
     563       11667 :         return creds;
     564             : }
     565             : 
     566             : /*
     567             :   initialise the credentials structure with only a session key.  The caller better know what they are doing!
     568             :  */
     569             : 
     570           0 : struct netlogon_creds_CredentialState *netlogon_creds_client_init_session_key(TALLOC_CTX *mem_ctx,
     571             :                                                                               const uint8_t session_key[16])
     572             : {
     573           0 :         struct netlogon_creds_CredentialState *creds;
     574             : 
     575           0 :         creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
     576           0 :         if (!creds) {
     577           0 :                 return NULL;
     578             :         }
     579             : 
     580           0 :         memcpy(creds->session_key, session_key, 16);
     581             : 
     582           0 :         return creds;
     583             : }
     584             : 
     585             : /*
     586             :   step the credentials to the next element in the chain, updating the
     587             :   current client and server credentials and the seed
     588             : 
     589             :   produce the next authenticator in the sequence ready to send to
     590             :   the server
     591             : */
     592             : NTSTATUS
     593       12998 : netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState *creds,
     594             :                                     struct netr_Authenticator *next)
     595             : {
     596       12998 :         uint32_t t32n = (uint32_t)time(NULL);
     597        1364 :         NTSTATUS status;
     598             : 
     599             :         /*
     600             :          * we always increment and ignore an overflow here
     601             :          */
     602       12998 :         creds->sequence += 2;
     603             : 
     604       12998 :         if (t32n > creds->sequence) {
     605             :                 /*
     606             :                  * we may increment more
     607             :                  */
     608          14 :                 creds->sequence = t32n;
     609             :         } else {
     610       12984 :                 uint32_t d = creds->sequence - t32n;
     611             : 
     612       12984 :                 if (d >= INT32_MAX) {
     613             :                         /*
     614             :                          * got an overflow of time_t vs. uint32_t
     615             :                          */
     616           0 :                         creds->sequence = t32n;
     617             :                 }
     618             :         }
     619             : 
     620       12998 :         status = netlogon_creds_step(creds);
     621       12998 :         if (!NT_STATUS_IS_OK(status)) {
     622           0 :                 return status;
     623             :         }
     624             : 
     625       12998 :         next->cred = creds->client;
     626       12998 :         next->timestamp = creds->sequence;
     627             : 
     628       12998 :         return NT_STATUS_OK;
     629             : }
     630             : 
     631             : /*
     632             :   check that a credentials reply from a server is correct
     633             : */
     634       12297 : bool netlogon_creds_client_check(struct netlogon_creds_CredentialState *creds,
     635             :                         const struct netr_Credential *received_credentials)
     636             : {
     637       13492 :         if (!received_credentials ||
     638       12297 :             !mem_equal_const_time(received_credentials->data, creds->server.data, 8)) {
     639          18 :                 DEBUG(2,("credentials check failed\n"));
     640          18 :                 return false;
     641             :         }
     642       11087 :         return true;
     643             : }
     644             : 
     645             : 
     646             : /*****************************************************************
     647             : The above functions are common to the client and server interface
     648             : next comes the server specific functions
     649             : ******************************************************************/
     650             : 
     651             : /*
     652             :   check that a credentials reply from a server is correct
     653             : */
     654       12746 : static bool netlogon_creds_server_check_internal(const struct netlogon_creds_CredentialState *creds,
     655             :                                                  const struct netr_Credential *received_credentials)
     656             : {
     657       12746 :         if (!mem_equal_const_time(received_credentials->data, creds->client.data, 8)) {
     658         168 :                 DEBUG(2,("credentials check failed\n"));
     659         168 :                 dump_data_pw("client creds", creds->client.data, 8);
     660         168 :                 dump_data_pw("calc   creds", received_credentials->data, 8);
     661         168 :                 return false;
     662             :         }
     663       11360 :         return true;
     664             : }
     665             : 
     666             : /*
     667             :   initialise the credentials chain and return the first server
     668             :   credentials
     669             : */
     670        1819 : struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *mem_ctx,
     671             :                                                                   const char *client_account,
     672             :                                                                   const char *client_computer_name,
     673             :                                                                   uint16_t secure_channel_type,
     674             :                                                                   const struct netr_Credential *client_challenge,
     675             :                                                                   const struct netr_Credential *server_challenge,
     676             :                                                                   const struct samr_Password *machine_password,
     677             :                                                                   const struct netr_Credential *credentials_in,
     678             :                                                                   struct netr_Credential *credentials_out,
     679             :                                                                   uint32_t negotiate_flags)
     680             : {
     681             : 
     682        1819 :         struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
     683         162 :         NTSTATUS status;
     684         162 :         bool ok;
     685             : 
     686        1819 :         if (!creds) {
     687           0 :                 return NULL;
     688             :         }
     689             : 
     690        1819 :         creds->negotiate_flags = negotiate_flags;
     691        1819 :         creds->secure_channel_type = secure_channel_type;
     692             : 
     693        1819 :         dump_data_pw("Client chall", client_challenge->data, sizeof(client_challenge->data));
     694        1819 :         dump_data_pw("Server chall", server_challenge->data, sizeof(server_challenge->data));
     695        1819 :         dump_data_pw("Machine Pass", machine_password->hash, sizeof(machine_password->hash));
     696             : 
     697        1819 :         ok = netlogon_creds_is_random_challenge(client_challenge);
     698        1819 :         if (!ok) {
     699          22 :                 DBG_WARNING("CVE-2020-1472(ZeroLogon): "
     700             :                             "non-random client challenge rejected for "
     701             :                             "client_account[%s] client_computer_name[%s]\n",
     702             :                             log_escape(mem_ctx, client_account),
     703             :                             log_escape(mem_ctx, client_computer_name));
     704          22 :                 dump_data(DBGLVL_WARNING,
     705          20 :                           client_challenge->data,
     706             :                           sizeof(client_challenge->data));
     707          22 :                 talloc_free(creds);
     708          22 :                 return NULL;
     709             :         }
     710             : 
     711        1797 :         creds->computer_name = talloc_strdup(creds, client_computer_name);
     712        1797 :         if (!creds->computer_name) {
     713           0 :                 talloc_free(creds);
     714           0 :                 return NULL;
     715             :         }
     716        1797 :         creds->account_name = talloc_strdup(creds, client_account);
     717        1797 :         if (!creds->account_name) {
     718           0 :                 talloc_free(creds);
     719           0 :                 return NULL;
     720             :         }
     721             : 
     722        1797 :         if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     723        1472 :                 status = netlogon_creds_init_hmac_sha256(creds,
     724             :                                                          client_challenge,
     725             :                                                          server_challenge,
     726             :                                                          machine_password);
     727        1472 :                 if (!NT_STATUS_IS_OK(status)) {
     728           0 :                         talloc_free(creds);
     729           0 :                         return NULL;
     730             :                 }
     731         325 :         } else if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
     732         181 :                 status = netlogon_creds_init_128bit(creds,
     733             :                                                     client_challenge,
     734             :                                                     server_challenge,
     735             :                                                     machine_password);
     736         181 :                 if (!NT_STATUS_IS_OK(status)) {
     737           0 :                         talloc_free(creds);
     738           0 :                         return NULL;
     739             :                 }
     740             :         } else {
     741         144 :                 status = netlogon_creds_init_64bit(creds,
     742             :                                                    client_challenge,
     743             :                                                    server_challenge,
     744             :                                                    machine_password);
     745         144 :                 if (!NT_STATUS_IS_OK(status)) {
     746           0 :                         talloc_free(creds);
     747           0 :                         return NULL;
     748             :                 }
     749             :         }
     750             : 
     751        1797 :         status = netlogon_creds_first_step(creds,
     752             :                                            client_challenge,
     753             :                                            server_challenge);
     754        1797 :         if (!NT_STATUS_IS_OK(status)) {
     755           0 :                 talloc_free(creds);
     756           0 :                 return NULL;
     757             :         }
     758             : 
     759        1797 :         dump_data_pw("Session key", creds->session_key, 16);
     760        1797 :         dump_data_pw("Client Credential ", creds->client.data, 8);
     761        1797 :         dump_data_pw("Server Credential ", creds->server.data, 8);
     762             : 
     763        1797 :         dump_data_pw("Credentials in", credentials_in->data, sizeof(credentials_in->data));
     764             : 
     765             :         /* And before we leak information about the machine account
     766             :          * password, check that they got the first go right */
     767        1797 :         if (!netlogon_creds_server_check_internal(creds, credentials_in)) {
     768         168 :                 talloc_free(creds);
     769         168 :                 return NULL;
     770             :         }
     771             : 
     772        1629 :         *credentials_out = creds->server;
     773             : 
     774        1629 :         dump_data_pw("Credentials out", credentials_out->data, sizeof(credentials_out->data));
     775             : 
     776        1629 :         return creds;
     777             : }
     778             : 
     779       10949 : NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState *creds,
     780             :                                  const struct netr_Authenticator *received_authenticator,
     781             :                                  struct netr_Authenticator *return_authenticator)
     782             : {
     783        1061 :         NTSTATUS status;
     784             : 
     785       10949 :         if (!received_authenticator || !return_authenticator) {
     786           0 :                 return NT_STATUS_INVALID_PARAMETER;
     787             :         }
     788             : 
     789       10949 :         if (!creds) {
     790           0 :                 return NT_STATUS_ACCESS_DENIED;
     791             :         }
     792             : 
     793       10949 :         creds->sequence = received_authenticator->timestamp;
     794       10949 :         status = netlogon_creds_step(creds);
     795       10949 :         if (!NT_STATUS_IS_OK(status)) {
     796           0 :                 ZERO_STRUCTP(return_authenticator);
     797           0 :                 return status;
     798             :         }
     799             : 
     800       10949 :         if (netlogon_creds_server_check_internal(creds, &received_authenticator->cred)) {
     801       10949 :                 return_authenticator->cred = creds->server;
     802       10949 :                 return_authenticator->timestamp = 0;
     803       10949 :                 return NT_STATUS_OK;
     804             :         } else {
     805           0 :                 ZERO_STRUCTP(return_authenticator);
     806           0 :                 return NT_STATUS_ACCESS_DENIED;
     807             :         }
     808             : }
     809             : 
     810       14562 : static NTSTATUS netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_CredentialState *creds,
     811             :                                                          uint16_t validation_level,
     812             :                                                          union netr_Validation *validation,
     813             :                                                          bool do_encrypt)
     814             : {
     815       14562 :         struct netr_SamBaseInfo *base = NULL;
     816        1274 :         NTSTATUS status;
     817             : 
     818       14562 :         if (validation == NULL) {
     819           0 :                 return NT_STATUS_INVALID_PARAMETER;
     820             :         }
     821             : 
     822       14562 :         switch (validation_level) {
     823        5464 :         case 2:
     824        5464 :                 if (validation->sam2) {
     825        5464 :                         base = &validation->sam2->base;
     826             :                 }
     827        4863 :                 break;
     828        5578 :         case 3:
     829        5578 :                 if (validation->sam3) {
     830        5578 :                         base = &validation->sam3->base;
     831             :                 }
     832        4977 :                 break;
     833        3470 :         case 6:
     834        3470 :                 if (validation->sam6) {
     835        3470 :                         base = &validation->sam6->base;
     836             :                 }
     837        3398 :                 break;
     838          50 :         default:
     839             :                 /* If we can't find it, we can't very well decrypt it */
     840          50 :                 return NT_STATUS_INVALID_INFO_CLASS;
     841             :         }
     842             : 
     843       14512 :         if (!base) {
     844           0 :                 return NT_STATUS_INVALID_INFO_CLASS;
     845             :         }
     846             : 
     847             :         /* find and decrypt the session keys, return in parameters above */
     848       14512 :         if (validation_level == 6) {
     849             :                 /* they aren't encrypted! */
     850       11042 :         } else if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     851             :                 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
     852        4722 :                 if (!all_zero(base->key.key, sizeof(base->key.key))) {
     853        4664 :                         if (do_encrypt) {
     854        4660 :                                 status = netlogon_creds_aes_encrypt(
     855             :                                         creds,
     856        3842 :                                         base->key.key,
     857             :                                         sizeof(base->key.key));
     858             :                         } else {
     859           4 :                                 status = netlogon_creds_aes_decrypt(
     860             :                                         creds,
     861           4 :                                         base->key.key,
     862             :                                         sizeof(base->key.key));
     863             :                         }
     864        4664 :                         if (!NT_STATUS_IS_OK(status)) {
     865           0 :                                 return status;
     866             :                         }
     867             :                 }
     868             : 
     869        4722 :                 if (!all_zero(base->LMSessKey.key,
     870             :                               sizeof(base->LMSessKey.key))) {
     871        4574 :                         if (do_encrypt) {
     872        4574 :                                 status = netlogon_creds_aes_encrypt(
     873             :                                         creds,
     874        3756 :                                         base->LMSessKey.key,
     875             :                                         sizeof(base->LMSessKey.key));
     876             :                         } else {
     877           0 :                                 status = netlogon_creds_aes_decrypt(
     878             :                                         creds,
     879           0 :                                         base->LMSessKey.key,
     880             :                                         sizeof(base->LMSessKey.key));
     881             :                         }
     882        4574 :                         if (!NT_STATUS_IS_OK(status)) {
     883           0 :                                 return status;
     884             :                         }
     885             :                 }
     886        6320 :         } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
     887             :                 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
     888        6266 :                 if (!all_zero(base->key.key, sizeof(base->key.key))) {
     889        5402 :                         status = netlogon_creds_arcfour_crypt(creds,
     890        5018 :                                                               base->key.key,
     891             :                                                               sizeof(base->key.key));
     892        5402 :                         if (!NT_STATUS_IS_OK(status)) {
     893           0 :                                 return status;
     894             :                         }
     895             :                 }
     896             : 
     897        6266 :                 if (!all_zero(base->LMSessKey.key,
     898             :                               sizeof(base->LMSessKey.key))) {
     899        3890 :                         status = netlogon_creds_arcfour_crypt(creds,
     900        3506 :                                                               base->LMSessKey.key,
     901             :                                                               sizeof(base->LMSessKey.key));
     902        3890 :                         if (!NT_STATUS_IS_OK(status)) {
     903           0 :                                 return status;
     904             :                         }
     905             :                 }
     906             :         } else {
     907             :                 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
     908          54 :                 if (!all_zero(base->LMSessKey.key,
     909             :                               sizeof(base->LMSessKey.key))) {
     910          54 :                         if (do_encrypt) {
     911          54 :                                 status = netlogon_creds_des_encrypt_LMKey(creds,
     912             :                                                                           &base->LMSessKey);
     913             :                         } else {
     914           0 :                                 status = netlogon_creds_des_decrypt_LMKey(creds,
     915             :                                                                           &base->LMSessKey);
     916             :                         }
     917          54 :                         if (!NT_STATUS_IS_OK(status)) {
     918           0 :                                 return status;
     919             :                         }
     920             :                 }
     921             :         }
     922             : 
     923       14512 :         return NT_STATUS_OK;
     924             : }
     925             : 
     926        3174 : NTSTATUS netlogon_creds_decrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds,
     927             :                                                     uint16_t validation_level,
     928             :                                                     union netr_Validation *validation)
     929             : {
     930        3174 :         return netlogon_creds_crypt_samlogon_validation(creds,
     931             :                                                         validation_level,
     932             :                                                         validation,
     933             :                                                         false);
     934             : }
     935             : 
     936       11388 : NTSTATUS netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds,
     937             :                                                     uint16_t validation_level,
     938             :                                                     union netr_Validation *validation)
     939             : {
     940       11388 :         return netlogon_creds_crypt_samlogon_validation(creds,
     941             :                                                         validation_level,
     942             :                                                         validation,
     943             :                                                         true);
     944             : }
     945             : 
     946       15358 : static NTSTATUS netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_CredentialState *creds,
     947             :                                                     enum netr_LogonInfoClass level,
     948             :                                                     union netr_LogonLevel *logon,
     949             :                                                     bool do_encrypt)
     950             : {
     951        1274 :         NTSTATUS status;
     952             : 
     953       15358 :         if (logon == NULL) {
     954           0 :                 return NT_STATUS_INVALID_PARAMETER;
     955             :         }
     956             : 
     957       15358 :         switch (level) {
     958         677 :         case NetlogonInteractiveInformation:
     959             :         case NetlogonInteractiveTransitiveInformation:
     960             :         case NetlogonServiceInformation:
     961             :         case NetlogonServiceTransitiveInformation:
     962         677 :                 if (logon->password == NULL) {
     963           0 :                         return NT_STATUS_INVALID_PARAMETER;
     964             :                 }
     965             : 
     966         677 :                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     967           0 :                         uint8_t *h;
     968             : 
     969         658 :                         h = logon->password->lmpassword.hash;
     970         658 :                         if (!all_zero(h, 16)) {
     971         544 :                                 if (do_encrypt) {
     972           6 :                                         status = netlogon_creds_aes_encrypt(
     973             :                                                 creds,
     974             :                                                 h,
     975             :                                                 16);
     976             :                                 } else {
     977         538 :                                         status = netlogon_creds_aes_decrypt(
     978             :                                                 creds,
     979             :                                                 h,
     980             :                                                 16);
     981             :                                 }
     982         544 :                                 if (!NT_STATUS_IS_OK(status)) {
     983           0 :                                         return status;
     984             :                                 }
     985             :                         }
     986             : 
     987         658 :                         h = logon->password->ntpassword.hash;
     988         658 :                         if (!all_zero(h, 16)) {
     989         658 :                                 if (do_encrypt) {
     990           6 :                                         status = netlogon_creds_aes_encrypt(creds,
     991             :                                                                    h,
     992             :                                                                    16);
     993             :                                 } else {
     994         652 :                                         status = netlogon_creds_aes_decrypt(creds,
     995             :                                                                    h,
     996             :                                                                    16);
     997             :                                 }
     998         658 :                                 if (!NT_STATUS_IS_OK(status)) {
     999           0 :                                         return status;
    1000             :                                 }
    1001             :                         }
    1002          19 :                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
    1003           0 :                         uint8_t *h;
    1004             : 
    1005          19 :                         h = logon->password->lmpassword.hash;
    1006          19 :                         if (!all_zero(h, 16)) {
    1007          19 :                                 status = netlogon_creds_arcfour_crypt(creds,
    1008             :                                                                       h,
    1009             :                                                                       16);
    1010          19 :                                 if (!NT_STATUS_IS_OK(status)) {
    1011           0 :                                         return status;
    1012             :                                 }
    1013             :                         }
    1014             : 
    1015          19 :                         h = logon->password->ntpassword.hash;
    1016          19 :                         if (!all_zero(h, 16)) {
    1017          19 :                                 status = netlogon_creds_arcfour_crypt(creds,
    1018             :                                                                       h,
    1019             :                                                                       16);
    1020          19 :                                 if (!NT_STATUS_IS_OK(status)) {
    1021           0 :                                         return status;
    1022             :                                 }
    1023             :                         }
    1024             :                 } else {
    1025           0 :                         struct samr_Password *p;
    1026             : 
    1027           0 :                         p = &logon->password->lmpassword;
    1028           0 :                         if (!all_zero(p->hash, 16)) {
    1029           0 :                                 if (do_encrypt) {
    1030           0 :                                         status = netlogon_creds_des_encrypt(creds, p);
    1031             :                                 } else {
    1032           0 :                                         status = netlogon_creds_des_decrypt(creds, p);
    1033             :                                 }
    1034           0 :                                 if (!NT_STATUS_IS_OK(status)) {
    1035           0 :                                         return status;
    1036             :                                 }
    1037             :                         }
    1038           0 :                         p = &logon->password->ntpassword;
    1039           0 :                         if (!all_zero(p->hash, 16)) {
    1040           0 :                                 if (do_encrypt) {
    1041           0 :                                         status = netlogon_creds_des_encrypt(creds, p);
    1042             :                                 } else {
    1043           0 :                                         status = netlogon_creds_des_decrypt(creds, p);
    1044             :                                 }
    1045           0 :                                 if (!NT_STATUS_IS_OK(status)) {
    1046           0 :                                         return status;
    1047             :                                 }
    1048             :                         }
    1049             :                 }
    1050         677 :                 break;
    1051             : 
    1052       13157 :         case NetlogonNetworkInformation:
    1053             :         case NetlogonNetworkTransitiveInformation:
    1054       13157 :                 break;
    1055             : 
    1056         250 :         case NetlogonGenericInformation:
    1057         250 :                 if (logon->generic == NULL) {
    1058           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1059             :                 }
    1060             : 
    1061         250 :                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
    1062         125 :                         if (do_encrypt) {
    1063           0 :                                 status = netlogon_creds_aes_encrypt(
    1064             :                                         creds,
    1065           0 :                                         logon->generic->data,
    1066           0 :                                         logon->generic->length);
    1067             :                         } else {
    1068         125 :                                 status = netlogon_creds_aes_decrypt(
    1069             :                                         creds,
    1070         125 :                                         logon->generic->data,
    1071         125 :                                         logon->generic->length);
    1072             :                         }
    1073         125 :                         if (!NT_STATUS_IS_OK(status)) {
    1074           0 :                                 return status;
    1075             :                         }
    1076         125 :                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
    1077         125 :                         status = netlogon_creds_arcfour_crypt(creds,
    1078         125 :                                                               logon->generic->data,
    1079         125 :                                                               logon->generic->length);
    1080         125 :                         if (!NT_STATUS_IS_OK(status)) {
    1081           0 :                                 return status;
    1082             :                         }
    1083             :                 } else {
    1084             :                         /* Using DES to verify kerberos tickets makes no sense */
    1085             :                 }
    1086         250 :                 break;
    1087             :         }
    1088             : 
    1089       15358 :         return NT_STATUS_OK;
    1090             : }
    1091             : 
    1092       15340 : NTSTATUS netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds,
    1093             :                                                enum netr_LogonInfoClass level,
    1094             :                                                union netr_LogonLevel *logon)
    1095             : {
    1096       15340 :         return netlogon_creds_crypt_samlogon_logon(creds, level, logon, false);
    1097             : }
    1098             : 
    1099          18 : NTSTATUS netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds,
    1100             :                                                enum netr_LogonInfoClass level,
    1101             :                                                union netr_LogonLevel *logon)
    1102             : {
    1103          18 :         return netlogon_creds_crypt_samlogon_logon(creds, level, logon, true);
    1104             : }
    1105             : 
    1106         362 : union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx,
    1107             :                                         enum netr_LogonInfoClass level,
    1108             :                                         const union netr_LogonLevel *in)
    1109             : {
    1110           0 :         union netr_LogonLevel *out;
    1111             : 
    1112         362 :         if (in == NULL) {
    1113           0 :                 return NULL;
    1114             :         }
    1115             : 
    1116         362 :         out = talloc(mem_ctx, union netr_LogonLevel);
    1117         362 :         if (out == NULL) {
    1118           0 :                 return NULL;
    1119             :         }
    1120             : 
    1121         362 :         *out = *in;
    1122             : 
    1123         362 :         switch (level) {
    1124          22 :         case NetlogonInteractiveInformation:
    1125             :         case NetlogonInteractiveTransitiveInformation:
    1126             :         case NetlogonServiceInformation:
    1127             :         case NetlogonServiceTransitiveInformation:
    1128          22 :                 if (in->password == NULL) {
    1129           0 :                         return out;
    1130             :                 }
    1131             : 
    1132          22 :                 out->password = talloc(out, struct netr_PasswordInfo);
    1133          22 :                 if (out->password == NULL) {
    1134           0 :                         talloc_free(out);
    1135           0 :                         return NULL;
    1136             :                 }
    1137          22 :                 *out->password = *in->password;
    1138             : 
    1139          22 :                 return out;
    1140             : 
    1141         340 :         case NetlogonNetworkInformation:
    1142             :         case NetlogonNetworkTransitiveInformation:
    1143         340 :                 break;
    1144             : 
    1145           0 :         case NetlogonGenericInformation:
    1146           0 :                 if (in->generic == NULL) {
    1147           0 :                         return out;
    1148             :                 }
    1149             : 
    1150           0 :                 out->generic = talloc(out, struct netr_GenericInfo);
    1151           0 :                 if (out->generic == NULL) {
    1152           0 :                         talloc_free(out);
    1153           0 :                         return NULL;
    1154             :                 }
    1155           0 :                 *out->generic = *in->generic;
    1156             : 
    1157           0 :                 if (in->generic->data == NULL) {
    1158           0 :                         return out;
    1159             :                 }
    1160             : 
    1161           0 :                 if (in->generic->length == 0) {
    1162           0 :                         return out;
    1163             :                 }
    1164             : 
    1165           0 :                 out->generic->data = talloc_memdup(out->generic,
    1166             :                                                    in->generic->data,
    1167             :                                                    in->generic->length);
    1168           0 :                 if (out->generic->data == NULL) {
    1169           0 :                         talloc_free(out);
    1170           0 :                         return NULL;
    1171             :                 }
    1172             : 
    1173           0 :                 return out;
    1174             :         }
    1175             : 
    1176         340 :         return out;
    1177             : }
    1178             : 
    1179             : /*
    1180             :   copy a netlogon_creds_CredentialState struct
    1181             : */
    1182             : 
    1183        5901 : struct netlogon_creds_CredentialState *netlogon_creds_copy(
    1184             :         TALLOC_CTX *mem_ctx,
    1185             :         const struct netlogon_creds_CredentialState *creds_in)
    1186             : {
    1187        5901 :         struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
    1188             : 
    1189        5901 :         if (!creds) {
    1190           0 :                 return NULL;
    1191             :         }
    1192             : 
    1193        5901 :         creds->sequence                      = creds_in->sequence;
    1194        5901 :         creds->negotiate_flags               = creds_in->negotiate_flags;
    1195        5901 :         creds->secure_channel_type   = creds_in->secure_channel_type;
    1196             : 
    1197        5901 :         creds->computer_name = talloc_strdup(creds, creds_in->computer_name);
    1198        5901 :         if (!creds->computer_name) {
    1199           0 :                 talloc_free(creds);
    1200           0 :                 return NULL;
    1201             :         }
    1202        5901 :         creds->account_name = talloc_strdup(creds, creds_in->account_name);
    1203        5901 :         if (!creds->account_name) {
    1204           0 :                 talloc_free(creds);
    1205           0 :                 return NULL;
    1206             :         }
    1207             : 
    1208        5901 :         if (creds_in->sid) {
    1209        2429 :                 creds->sid = dom_sid_dup(creds, creds_in->sid);
    1210        2429 :                 if (!creds->sid) {
    1211           0 :                         talloc_free(creds);
    1212           0 :                         return NULL;
    1213             :                 }
    1214             :         }
    1215             : 
    1216        5901 :         memcpy(creds->session_key, creds_in->session_key, sizeof(creds->session_key));
    1217        5901 :         memcpy(creds->seed.data, creds_in->seed.data, sizeof(creds->seed.data));
    1218        5901 :         memcpy(creds->client.data, creds_in->client.data, sizeof(creds->client.data));
    1219        5901 :         memcpy(creds->server.data, creds_in->server.data, sizeof(creds->server.data));
    1220             : 
    1221        5901 :         return creds;
    1222             : }

Generated by: LCOV version 1.14