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

Generated by: LCOV version 1.13