LCOV - code coverage report
Current view: top level - libcli/auth - smbencrypt.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 443 544 81.4 %
Date: 2024-01-11 09:59:51 Functions: 33 33 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB parameters and setup
       4             :    Copyright (C) Andrew Tridgell 1992-1998
       5             :    Modified by Jeremy Allison 1995.
       6             :    Copyright (C) Jeremy Allison 1995-2000.
       7             :    Copyright (C) Luke Kennethc Casson Leighton 1996-2000.
       8             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
       9             : 
      10             :    This program is free software; you can redistribute it and/or modify
      11             :    it under the terms of the GNU General Public License as published by
      12             :    the Free Software Foundation; either version 3 of the License, or
      13             :    (at your option) any later version.
      14             : 
      15             :    This program is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :    GNU General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include "system/time.h"
      26             : #include "../libcli/auth/msrpc_parse.h"
      27             : #include "../lib/crypto/crypto.h"
      28             : #include "../libcli/auth/libcli_auth.h"
      29             : #include "../librpc/gen_ndr/ndr_ntlmssp.h"
      30             : #include "lib/util/bytearray.h"
      31             : 
      32             : #include "lib/crypto/gnutls_helpers.h"
      33             : #include <gnutls/gnutls.h>
      34             : #include <gnutls/crypto.h>
      35             : 
      36        2091 : int SMBencrypt_hash(const uint8_t lm_hash[16], const uint8_t *c8, uint8_t p24[24])
      37             : {
      38           2 :         uint8_t p21[21];
      39           2 :         int rc;
      40             : 
      41        2091 :         memset(p21,'\0',21);
      42        2091 :         memcpy(p21, lm_hash, 16);
      43             : 
      44        2091 :         rc = SMBOWFencrypt(p21, c8, p24);
      45             : 
      46             : #ifdef DEBUG_PASSWORD
      47        2091 :         DEBUG(100,("SMBencrypt_hash: lm#, challenge, response\n"));
      48        2091 :         dump_data(100, p21, 16);
      49        2091 :         dump_data(100, c8, 8);
      50        2091 :         dump_data(100, p24, 24);
      51             : #endif
      52             : 
      53        2091 :         return rc;
      54             : }
      55             : 
      56             : /*
      57             :    This implements the X/Open SMB password encryption
      58             :    It takes a password ('unix' string), a 8 byte "crypt key"
      59             :    and puts 24 bytes of encrypted password into p24
      60             : 
      61             :    Returns False if password must have been truncated to create LM hash
      62             : */
      63             : 
      64        1414 : bool SMBencrypt(const char *passwd, const uint8_t *c8, uint8_t p24[24])
      65             : {
      66           0 :         bool ret;
      67           0 :         uint8_t lm_hash[16];
      68           0 :         int rc;
      69             : 
      70        1414 :         ret = E_deshash(passwd, lm_hash);
      71        1414 :         rc = SMBencrypt_hash(lm_hash, c8, p24);
      72        1414 :         if (rc != 0) {
      73           0 :                 ret = false;
      74             :         }
      75        1414 :         return ret;
      76             : }
      77             : 
      78             : /**
      79             :  * Creates the MD4 Hash of the users password in NT UNICODE.
      80             :  * @param passwd password in 'unix' charset.
      81             :  * @param p16 return password hashed with md4, caller allocated 16 byte buffer
      82             :  */
      83             : 
      84       43294 : bool E_md4hash(const char *passwd, uint8_t p16[16])
      85             : {
      86         157 :         size_t len;
      87         157 :         smb_ucs2_t *wpwd;
      88         157 :         bool ret;
      89             : 
      90       43294 :         ret = push_ucs2_talloc(NULL, &wpwd, passwd, &len);
      91       43294 :         if (!ret || len < 2) {
      92             :                 /* We don't want to return fixed data, as most callers
      93             :                  * don't check */
      94           0 :                 mdfour(p16, (const uint8_t *)passwd, strlen(passwd));
      95           0 :                 return false;
      96             :         }
      97             : 
      98       43294 :         len -= 2;
      99       43294 :         mdfour(p16, (const uint8_t *)wpwd, len);
     100             : 
     101       43294 :         talloc_free(wpwd);
     102       43294 :         return true;
     103             : }
     104             : 
     105             : /**
     106             :  * Creates the DES forward-only Hash of the users password in DOS ASCII charset
     107             :  * @param passwd password in 'unix' charset.
     108             :  * @param p16 return password hashed with DES, caller allocated 16 byte buffer
     109             :  * @return false if password was > 14 characters, and therefore may be incorrect, otherwise true
     110             :  * @note p16 is filled in regardless
     111             :  */
     112             : 
     113       10181 : bool E_deshash(const char *passwd, uint8_t p16[16])
     114             : {
     115          14 :         bool ret;
     116          14 :         int rc;
     117          14 :         uint8_t dospwd[14];
     118       10181 :         TALLOC_CTX *frame = talloc_stackframe();
     119             : 
     120          14 :         size_t converted_size;
     121             : 
     122          14 :         char *tmpbuf;
     123             : 
     124       10181 :         ZERO_STRUCT(dospwd);
     125             : 
     126       10181 :         tmpbuf = strupper_talloc(frame, passwd);
     127       10181 :         if (tmpbuf == NULL) {
     128             :                 /* Too many callers don't check this result, we need to fill in the buffer with something */
     129           0 :                 strlcpy((char *)dospwd, passwd ? passwd : "", sizeof(dospwd));
     130           0 :                 E_P16(dospwd, p16);
     131           0 :                 talloc_free(frame);
     132           0 :                 return false;
     133             :         }
     134             : 
     135       10181 :         ZERO_STRUCT(dospwd);
     136             : 
     137       10181 :         ret = convert_string_error(CH_UNIX, CH_DOS, tmpbuf, strlen(tmpbuf), dospwd, sizeof(dospwd), &converted_size);
     138       10181 :         talloc_free(frame);
     139             : 
     140             :         /* Only the first 14 chars are considered, password need not
     141             :          * be null terminated.  We do this in the error and success
     142             :          * case to avoid returning a fixed 'password' buffer, but
     143             :          * callers should not use it when E_deshash returns false */
     144             : 
     145       10181 :         rc = E_P16((const uint8_t *)dospwd, p16);
     146       10181 :         if (rc != 0) {
     147           0 :                 ret = false;
     148             :         }
     149             : 
     150       10181 :         ZERO_STRUCT(dospwd);
     151             : 
     152       10181 :         return ret;
     153             : }
     154             : 
     155             : /**
     156             :  * Creates the MD4 and DES (LM) Hash of the users password.
     157             :  * MD4 is of the NT Unicode, DES is of the DOS UPPERCASE password.
     158             :  * @param passwd password in 'unix' charset.
     159             :  * @param nt_p16 return password hashed with md4, caller allocated 16 byte buffer
     160             :  * @param p16 return password hashed with des, caller allocated 16 byte buffer
     161             :  */
     162             : 
     163             : /* Does both the NT and LM owfs of a user's password */
     164          66 : void nt_lm_owf_gen(const char *pwd, uint8_t nt_p16[16], uint8_t p16[16])
     165             : {
     166             :         /* Calculate the MD4 hash (NT compatible) of the password */
     167          66 :         memset(nt_p16, '\0', 16);
     168          66 :         E_md4hash(pwd, nt_p16);
     169             : 
     170             : #ifdef DEBUG_PASSWORD
     171          66 :         DEBUG(100,("nt_lm_owf_gen: pwd, nt#\n"));
     172          66 :         dump_data(120, (const uint8_t *)pwd, strlen(pwd));
     173          66 :         dump_data(100, nt_p16, 16);
     174             : #endif
     175             : 
     176          66 :         E_deshash(pwd, (uint8_t *)p16);
     177             : 
     178             : #ifdef DEBUG_PASSWORD
     179          66 :         DEBUG(100,("nt_lm_owf_gen: pwd, lm#\n"));
     180          66 :         dump_data(120, (const uint8_t *)pwd, strlen(pwd));
     181          66 :         dump_data(100, p16, 16);
     182             : #endif
     183          66 : }
     184             : 
     185             : /* Does both the NTLMv2 owfs of a user's password */
     186       94323 : bool ntv2_owf_gen(const uint8_t owf[16],
     187             :                   const char *user_in, const char *domain_in,
     188             :                   uint8_t kr_buf[16])
     189             : {
     190        1911 :         smb_ucs2_t *user;
     191        1911 :         smb_ucs2_t *domain;
     192        1911 :         size_t user_byte_len;
     193        1911 :         size_t domain_byte_len;
     194       94323 :         gnutls_hmac_hd_t hmac_hnd = NULL;
     195        1911 :         int rc;
     196       94323 :         bool ok = false;
     197       94323 :         TALLOC_CTX *mem_ctx = talloc_init("ntv2_owf_gen for %s\\%s", domain_in, user_in);
     198             : 
     199       94323 :         if (!mem_ctx) {
     200           0 :                 return false;
     201             :         }
     202             : 
     203       94323 :         if (!user_in) {
     204           0 :                 user_in = "";
     205             :         }
     206             : 
     207       94323 :         if (!domain_in) {
     208        1728 :                 domain_in = "";
     209             :         }
     210             : 
     211       94323 :         user_in = strupper_talloc(mem_ctx, user_in);
     212       94323 :         if (user_in == NULL) {
     213           0 :                 talloc_free(mem_ctx);
     214           0 :                 return false;
     215             :         }
     216             : 
     217       94323 :         ok = push_ucs2_talloc(mem_ctx, &user, user_in, &user_byte_len );
     218       94323 :         if (!ok) {
     219           0 :                 DEBUG(0, ("push_uss2_talloc() for user failed)\n"));
     220           0 :                 talloc_free(mem_ctx);
     221           0 :                 return false;
     222             :         }
     223             : 
     224       94323 :         ok = push_ucs2_talloc(mem_ctx, &domain, domain_in, &domain_byte_len);
     225       94323 :         if (!ok) {
     226           0 :                 DEBUG(0, ("push_ucs2_talloc() for domain failed\n"));
     227           0 :                 talloc_free(mem_ctx);
     228           0 :                 return false;
     229             :         }
     230             : 
     231       94323 :         SMB_ASSERT(user_byte_len >= 2);
     232       94323 :         SMB_ASSERT(domain_byte_len >= 2);
     233             : 
     234             :         /* We don't want null termination */
     235       94323 :         user_byte_len = user_byte_len - 2;
     236       94323 :         domain_byte_len = domain_byte_len - 2;
     237             : 
     238       94323 :         rc = gnutls_hmac_init(&hmac_hnd,
     239             :                               GNUTLS_MAC_MD5,
     240             :                               owf,
     241             :                               16);
     242       94323 :         if (rc < 0) {
     243           0 :                 ok = false;
     244           0 :                 goto out;
     245             :         }
     246             : 
     247       94323 :         rc = gnutls_hmac(hmac_hnd, user, user_byte_len);
     248       94323 :         if (rc < 0) {
     249           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     250           0 :                 ok = false;
     251           0 :                 goto out;
     252             :         }
     253       94323 :         rc = gnutls_hmac(hmac_hnd, domain, domain_byte_len);
     254       94323 :         if (rc < 0) {
     255           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     256           0 :                 ok = false;
     257           0 :                 goto out;
     258             :         }
     259             : 
     260       94323 :         gnutls_hmac_deinit(hmac_hnd, kr_buf);
     261             : 
     262             : #ifdef DEBUG_PASSWORD
     263       94323 :         DEBUG(100, ("ntv2_owf_gen: user, domain, owfkey, kr\n"));
     264       94323 :         dump_data(100, (uint8_t *)user, user_byte_len);
     265       94323 :         dump_data(100, (uint8_t *)domain, domain_byte_len);
     266       94323 :         dump_data(100, owf, 16);
     267       94323 :         dump_data(100, kr_buf, 16);
     268             : #endif
     269             : 
     270       94323 :         ok = true;
     271       94323 : out:
     272       94323 :         talloc_free(mem_ctx);
     273       94323 :         return ok;
     274             : }
     275             : 
     276             : /* Does the des encryption from the NT or LM MD4 hash. */
     277       11980 : int SMBOWFencrypt(const uint8_t passwd[16], const uint8_t *c8, uint8_t p24[24])
     278             : {
     279          18 :         uint8_t p21[21];
     280             : 
     281       11980 :         ZERO_STRUCT(p21);
     282             : 
     283       11980 :         memcpy(p21, passwd, 16);
     284       11980 :         return E_P24(p21, c8, p24);
     285             : }
     286             : 
     287             : /* Does the des encryption. */
     288             : 
     289        3237 : int SMBNTencrypt_hash(const uint8_t nt_hash[16], const uint8_t *c8, uint8_t *p24)
     290             : {
     291           0 :         uint8_t p21[21];
     292           0 :         int rc;
     293             : 
     294        3237 :         memset(p21,'\0',21);
     295        3237 :         memcpy(p21, nt_hash, 16);
     296        3237 :         rc = SMBOWFencrypt(p21, c8, p24);
     297             : 
     298             : #ifdef DEBUG_PASSWORD
     299        3237 :         DEBUG(100,("SMBNTencrypt: nt#, challenge, response\n"));
     300        3237 :         dump_data(100, p21, 16);
     301        3237 :         dump_data(100, c8, 8);
     302        3237 :         dump_data(100, p24, 24);
     303             : #endif
     304             : 
     305        3237 :         return rc;
     306             : }
     307             : 
     308             : /* Does the NT MD4 hash then des encryption. Plaintext version of the above. */
     309             : 
     310        3237 : int SMBNTencrypt(const char *passwd, const uint8_t *c8, uint8_t *p24)
     311             : {
     312           0 :         uint8_t nt_hash[16];
     313        3237 :         E_md4hash(passwd, nt_hash);
     314        3237 :         return SMBNTencrypt_hash(nt_hash, c8, p24);
     315             : }
     316             : 
     317             : 
     318             : /* Does the md5 encryption from the Key Response for NTLMv2. */
     319      101768 : NTSTATUS SMBOWFencrypt_ntv2(const uint8_t kr[16],
     320             :                             const DATA_BLOB *srv_chal,
     321             :                             const DATA_BLOB *smbcli_chal,
     322             :                             uint8_t resp_buf[16])
     323             : {
     324      101768 :         gnutls_hmac_hd_t hmac_hnd = NULL;
     325        2219 :         NTSTATUS status;
     326        2219 :         int rc;
     327             : 
     328      101768 :         rc = gnutls_hmac_init(&hmac_hnd,
     329             :                               GNUTLS_MAC_MD5,
     330             :                               kr,
     331             :                               16);
     332      101768 :         if (rc < 0) {
     333           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     334             :         }
     335             : 
     336      101768 :         rc = gnutls_hmac(hmac_hnd, srv_chal->data, srv_chal->length);
     337      101768 :         if (rc < 0) {
     338           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     339           0 :                 goto out;
     340             :         }
     341      101768 :         rc = gnutls_hmac(hmac_hnd, smbcli_chal->data, smbcli_chal->length);
     342      101768 :         if (rc < 0) {
     343           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     344           0 :                 goto out;
     345             :         }
     346             : 
     347             : #ifdef DEBUG_PASSWORD
     348      101768 :         DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, smbcli_chal, resp_buf\n"));
     349      101768 :         dump_data(100, srv_chal->data, srv_chal->length);
     350      101768 :         dump_data(100, smbcli_chal->data, smbcli_chal->length);
     351      101768 :         dump_data(100, resp_buf, 16);
     352             : #endif
     353             : 
     354      101768 :         status = NT_STATUS_OK;
     355      101768 : out:
     356      101768 :         gnutls_hmac_deinit(hmac_hnd, resp_buf);
     357      101768 :         return status;
     358             : }
     359             : 
     360       86825 : NTSTATUS SMBsesskeygen_ntv2(const uint8_t kr[16],
     361             :                             const uint8_t *nt_resp,
     362             :                             uint8_t sess_key[16])
     363             : {
     364        1896 :         int rc;
     365             : 
     366             :         /* a very nice, 128 bit, variable session key */
     367       86825 :         rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
     368             :                               kr,
     369             :                               16,
     370             :                               nt_resp,
     371             :                               16,
     372             :                               sess_key);
     373       86825 :         if (rc != 0) {
     374           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     375             :         }
     376             : 
     377             : #ifdef DEBUG_PASSWORD
     378       86825 :         DEBUG(100, ("SMBsesskeygen_ntv2:\n"));
     379       86825 :         dump_data(100, sess_key, 16);
     380             : #endif
     381             : 
     382       86825 :         return NT_STATUS_OK;
     383             : }
     384             : 
     385        6347 : void SMBsesskeygen_ntv1(const uint8_t kr[16], uint8_t sess_key[16])
     386             : {
     387             :         /* yes, this session key does not change - yes, this
     388             :            is a problem - but it is 128 bits */
     389             : 
     390        6347 :         mdfour((uint8_t *)sess_key, kr, 16);
     391             : 
     392             : #ifdef DEBUG_PASSWORD
     393        6347 :         DEBUG(100, ("SMBsesskeygen_ntv1:\n"));
     394        6347 :         dump_data(100, sess_key, 16);
     395             : #endif
     396        6347 : }
     397             : 
     398           1 : NTSTATUS SMBsesskeygen_lm_sess_key(const uint8_t lm_hash[16],
     399             :                                const uint8_t lm_resp[24], /* only uses 8 */
     400             :                                uint8_t sess_key[16])
     401             : {
     402             :         /* Calculate the LM session key (effective length 40 bits,
     403             :            but changes with each session) */
     404           1 :         uint8_t p24[24];
     405           1 :         uint8_t partial_lm_hash[14];
     406           1 :         int rc;
     407             : 
     408           1 :         memcpy(partial_lm_hash, lm_hash, 8);
     409           1 :         memset(partial_lm_hash + 8, 0xbd, 6);
     410             : 
     411           1 :         rc = des_crypt56_gnutls(p24, lm_resp, partial_lm_hash, SAMBA_GNUTLS_ENCRYPT);
     412           1 :         if (rc < 0) {
     413           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
     414             :         }
     415           1 :         rc = des_crypt56_gnutls(p24+8, lm_resp, partial_lm_hash + 7, SAMBA_GNUTLS_ENCRYPT);
     416           1 :         if (rc < 0) {
     417           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
     418             :         }
     419             : 
     420           1 :         memcpy(sess_key, p24, 16);
     421             : 
     422             : #ifdef DEBUG_PASSWORD
     423           1 :         DEBUG(100, ("SMBsesskeygen_lm_sess_key: \n"));
     424           1 :         dump_data(100, sess_key, 16);
     425             : #endif
     426             : 
     427           1 :         return NT_STATUS_OK;
     428             : }
     429             : 
     430        5979 : DATA_BLOB NTLMv2_generate_names_blob(TALLOC_CTX *mem_ctx,
     431             :                                      const char *hostname,
     432             :                                      const char *domain)
     433             : {
     434        5979 :         DATA_BLOB names_blob = data_blob_talloc(mem_ctx, NULL, 0);
     435             : 
     436             :         /* Deliberately ignore return here.. */
     437        5979 :         if (hostname != NULL) {
     438        5951 :                 (void)msrpc_gen(mem_ctx, &names_blob,
     439             :                           "aaa",
     440             :                           MsvAvNbDomainName, domain,
     441             :                           MsvAvNbComputerName, hostname,
     442             :                           MsvAvEOL, "");
     443             :         } else {
     444          28 :                 (void)msrpc_gen(mem_ctx, &names_blob,
     445             :                           "aa",
     446             :                           MsvAvNbDomainName, domain,
     447             :                           MsvAvEOL, "");
     448             :         }
     449        5979 :         return names_blob;
     450             : }
     451             : 
     452       42929 : static DATA_BLOB NTLMv2_generate_client_data(TALLOC_CTX *mem_ctx,
     453             :                                              NTTIME nttime,
     454             :                                              const DATA_BLOB *names_blob)
     455             : {
     456         492 :         uint8_t client_chal[8];
     457       42929 :         DATA_BLOB response = data_blob(NULL, 0);
     458         492 :         uint8_t long_date[8];
     459             : 
     460       42929 :         generate_random_buffer(client_chal, sizeof(client_chal));
     461             : 
     462       42929 :         push_nttime(long_date, 0, nttime);
     463             : 
     464             :         /* See http://www.ubiqx.org/cifs/SMB.html#SMB.8.5 */
     465             : 
     466             :         /* Deliberately ignore return here.. */
     467       42929 :         (void)msrpc_gen(mem_ctx, &response, "ddbbdb",
     468             :                   0x00000101,     /* Header  */
     469             :                   0,              /* 'Reserved'  */
     470             :                   long_date, 8,   /* Timestamp */
     471             :                   client_chal, 8, /* client challenge */
     472             :                   0,              /* Unknown */
     473       42929 :                   names_blob->data, names_blob->length);  /* End of name list */
     474             : 
     475       42929 :         return response;
     476             : }
     477             : 
     478       42929 : static DATA_BLOB NTLMv2_generate_response(TALLOC_CTX *out_mem_ctx,
     479             :                                           const uint8_t ntlm_v2_hash[16],
     480             :                                           const DATA_BLOB *server_chal,
     481             :                                           NTTIME nttime,
     482             :                                           const DATA_BLOB *names_blob)
     483             : {
     484         492 :         uint8_t ntlmv2_response[16];
     485         492 :         DATA_BLOB ntlmv2_client_data;
     486         492 :         DATA_BLOB final_response;
     487         492 :         NTSTATUS status;
     488             : 
     489       42929 :         TALLOC_CTX *mem_ctx = talloc_named(out_mem_ctx, 0,
     490             :                                            "NTLMv2_generate_response internal context");
     491             : 
     492       42929 :         if (!mem_ctx) {
     493           0 :                 return data_blob(NULL, 0);
     494             :         }
     495             : 
     496             :         /* NTLMv2 */
     497             :         /* generate some data to pass into the response function - including
     498             :            the hostname and domain name of the server */
     499       42929 :         ntlmv2_client_data = NTLMv2_generate_client_data(mem_ctx, nttime, names_blob);
     500             : 
     501             :         /* Given that data, and the challenge from the server, generate a response */
     502       42929 :         status = SMBOWFencrypt_ntv2(ntlm_v2_hash,
     503             :                                     server_chal,
     504             :                                     &ntlmv2_client_data,
     505             :                                     ntlmv2_response);
     506       42929 :         if (!NT_STATUS_IS_OK(status)) {
     507           0 :                 talloc_free(mem_ctx);
     508           0 :                 return data_blob(NULL, 0);
     509             :         }
     510             : 
     511       42929 :         final_response = data_blob_talloc(out_mem_ctx, NULL, sizeof(ntlmv2_response) + ntlmv2_client_data.length);
     512             : 
     513       42929 :         memcpy(final_response.data, ntlmv2_response, sizeof(ntlmv2_response));
     514             : 
     515       42929 :         memcpy(final_response.data+sizeof(ntlmv2_response),
     516       42929 :                ntlmv2_client_data.data, ntlmv2_client_data.length);
     517             : 
     518       42929 :         talloc_free(mem_ctx);
     519             : 
     520       42929 :         return final_response;
     521             : }
     522             : 
     523        7445 : static DATA_BLOB LMv2_generate_response(TALLOC_CTX *mem_ctx,
     524             :                                         const uint8_t ntlm_v2_hash[16],
     525             :                                         const DATA_BLOB *server_chal)
     526             : {
     527         308 :         uint8_t lmv2_response[16];
     528        7445 :         DATA_BLOB lmv2_client_data = data_blob_talloc(mem_ctx, NULL, 8);
     529        7445 :         DATA_BLOB final_response = data_blob_talloc(mem_ctx, NULL,24);
     530         308 :         NTSTATUS status;
     531             : 
     532             :         /* LMv2 */
     533             :         /* client-supplied random data */
     534        7445 :         generate_random_buffer(lmv2_client_data.data, lmv2_client_data.length);
     535             : 
     536             :         /* Given that data, and the challenge from the server, generate a response */
     537        7445 :         status = SMBOWFencrypt_ntv2(ntlm_v2_hash,
     538             :                                     server_chal,
     539             :                                     &lmv2_client_data,
     540             :                                     lmv2_response);
     541        7445 :         if (!NT_STATUS_IS_OK(status)) {
     542           0 :                 data_blob_free(&lmv2_client_data);
     543           0 :                 return data_blob(NULL, 0);
     544             :         }
     545        7445 :         memcpy(final_response.data, lmv2_response, sizeof(lmv2_response));
     546             : 
     547             :         /* after the first 16 bytes is the random data we generated above,
     548             :            so the server can verify us with it */
     549        7445 :         memcpy(final_response.data+sizeof(lmv2_response),
     550        7445 :                lmv2_client_data.data, lmv2_client_data.length);
     551             : 
     552        7445 :         data_blob_free(&lmv2_client_data);
     553             : 
     554        7445 :         return final_response;
     555             : }
     556             : 
     557       42929 : bool SMBNTLMv2encrypt_hash(TALLOC_CTX *mem_ctx,
     558             :                            const char *user, const char *domain, const uint8_t nt_hash[16],
     559             :                            const DATA_BLOB *server_chal,
     560             :                            const NTTIME *server_timestamp,
     561             :                            const DATA_BLOB *names_blob,
     562             :                            DATA_BLOB *lm_response, DATA_BLOB *nt_response,
     563             :                            DATA_BLOB *lm_session_key, DATA_BLOB *user_session_key)
     564             : {
     565         492 :         uint8_t ntlm_v2_hash[16];
     566         492 :         NTSTATUS status;
     567             : 
     568             :         /* We don't use the NT# directly.  Instead we use it mashed up with
     569             :            the username and domain.
     570             :            This prevents username swapping during the auth exchange
     571             :         */
     572       42929 :         if (!ntv2_owf_gen(nt_hash, user, domain, ntlm_v2_hash)) {
     573           0 :                 return false;
     574             :         }
     575             : 
     576       42929 :         if (nt_response) {
     577       42929 :                 const NTTIME *nttime = server_timestamp;
     578       42929 :                 NTTIME _now = 0;
     579             : 
     580       42929 :                 if (nttime == NULL) {
     581        7445 :                         struct timeval tv_now = timeval_current();
     582        7445 :                         _now = timeval_to_nttime(&tv_now);
     583        7445 :                         nttime = &_now;
     584             :                 }
     585             : 
     586       42929 :                 *nt_response = NTLMv2_generate_response(mem_ctx,
     587             :                                                         ntlm_v2_hash,
     588             :                                                         server_chal,
     589             :                                                         *nttime,
     590             :                                                         names_blob);
     591       42929 :                 if (user_session_key) {
     592       42806 :                         *user_session_key = data_blob_talloc(mem_ctx, NULL, 16);
     593             : 
     594             :                         /* The NTLMv2 calculations also provide a session key, for signing etc later */
     595             :                         /* use only the first 16 bytes of nt_response for session key */
     596       43298 :                         status = SMBsesskeygen_ntv2(ntlm_v2_hash,
     597       42806 :                                                     nt_response->data,
     598             :                                                     user_session_key->data);
     599       42806 :                         if (!NT_STATUS_IS_OK(status)) {
     600           0 :                                 return false;
     601             :                         }
     602             :                 }
     603             :         }
     604             : 
     605             :         /* LMv2 */
     606             : 
     607       42929 :         if (lm_response) {
     608       42929 :                 if (server_timestamp != NULL) {
     609       35484 :                         *lm_response = data_blob_talloc_zero(mem_ctx, 24);
     610             :                 } else {
     611        7445 :                         *lm_response = LMv2_generate_response(mem_ctx,
     612             :                                                               ntlm_v2_hash,
     613             :                                                               server_chal);
     614             :                 }
     615       42929 :                 if (lm_session_key) {
     616        3266 :                         *lm_session_key = data_blob_talloc(mem_ctx, NULL, 16);
     617             : 
     618             :                         /* The NTLMv2 calculations also provide a session key, for signing etc later */
     619             :                         /* use only the first 16 bytes of lm_response for session key */
     620        3266 :                         status = SMBsesskeygen_ntv2(ntlm_v2_hash,
     621        3266 :                                                     lm_response->data,
     622             :                                                     lm_session_key->data);
     623        3266 :                         if (!NT_STATUS_IS_OK(status)) {
     624           0 :                                 return false;
     625             :                         }
     626             :                 }
     627             :         }
     628             : 
     629       42437 :         return true;
     630             : }
     631             : 
     632        3481 : bool SMBNTLMv2encrypt(TALLOC_CTX *mem_ctx,
     633             :                       const char *user, const char *domain,
     634             :                       const char *password,
     635             :                       const DATA_BLOB *server_chal,
     636             :                       const DATA_BLOB *names_blob,
     637             :                       DATA_BLOB *lm_response, DATA_BLOB *nt_response,
     638             :                       DATA_BLOB *lm_session_key, DATA_BLOB *user_session_key)
     639             : {
     640           0 :         uint8_t nt_hash[16];
     641        3481 :         E_md4hash(password, nt_hash);
     642             : 
     643        3481 :         return SMBNTLMv2encrypt_hash(mem_ctx,
     644             :                                      user, domain, nt_hash,
     645             :                                      server_chal, NULL, names_blob,
     646             :                                      lm_response, nt_response, lm_session_key, user_session_key);
     647             : }
     648             : 
     649       14413 : NTSTATUS NTLMv2_RESPONSE_verify_netlogon_creds(const char *account_name,
     650             :                         const char *account_domain,
     651             :                         const DATA_BLOB response,
     652             :                         const struct netlogon_creds_CredentialState *creds,
     653             :                         const char *workgroup)
     654             : {
     655       14413 :         TALLOC_CTX *frame = NULL;
     656             :         /* RespType + HiRespType */
     657        1274 :         static const char *magic = "\x01\x01";
     658        1274 :         int cmp;
     659        1274 :         struct NTLMv2_RESPONSE v2_resp;
     660        1274 :         enum ndr_err_code err;
     661       14413 :         const struct AV_PAIR *av_nb_cn = NULL;
     662       14413 :         const struct AV_PAIR *av_nb_dn = NULL;
     663             : 
     664       14413 :         if (response.length < 48) {
     665             :                 /*
     666             :                  * NTLMv2_RESPONSE has at least 48 bytes.
     667             :                  */
     668        4350 :                 return NT_STATUS_OK;
     669             :         }
     670             : 
     671       10063 :         cmp = memcmp(response.data + 16, magic, 2);
     672       10063 :         if (cmp != 0) {
     673             :                 /*
     674             :                  * It doesn't look like a valid NTLMv2_RESPONSE
     675             :                  */
     676         360 :                 return NT_STATUS_OK;
     677             :         }
     678             : 
     679        9703 :         if (response.length == 95) {
     680             :                 /*
     681             :                  * ndr_pull_NTLMv2_RESPONSE() fails on this strange blob,
     682             :                  * because the AvPairs content is not valid
     683             :                  * as AvLen of the first pair is 33032 (0x8108).
     684             :                  *
     685             :                  * I saw a single machine sending the following 3 times
     686             :                  * in a row, but I'm not sure if everything is static.
     687             :                  *
     688             :                  * Note this is NTLMv2_CLIENT_CHALLENGE only, not
     689             :                  * the full NTLMv2_RESPONSE (which has Response of 16 bytes
     690             :                  * before the NTLMv2_CLIENT_CHALLENGE).
     691             :                  *
     692             :                  * Note this code only prevents
     693             :                  * ndr_pull_error(Buffer Size Error): Pull bytes 39016
     694             :                  * debug message for a known case, the actual
     695             :                  * bug is also handled below in a generic way to
     696             :                  * map NT_STATUS_BUFFER_TOO_SMALL to NT_STATUS_OK.
     697             :                  *
     698             :                  * See https://bugzilla.samba.org/show_bug.cgi?id=14932
     699             :                  */
     700         120 :                 static const char *netapp_magic =
     701             :                         "\x01\x01\x00\x00\x00\x00\x00\x00"
     702             :                         "\x3f\x3f\x3f\x3f\x3f\x3f\x3f\x3f"
     703             :                         "\xb8\x82\x3a\xf1\xb3\xdd\x08\x15"
     704             :                         "\x00\x00\x00\x00\x11\xa2\x08\x81"
     705             :                         "\x50\x38\x22\x78\x2b\x94\x47\xfe"
     706             :                         "\x54\x94\x7b\xff\x17\x27\x5a\xb4"
     707             :                         "\xf4\x18\xba\xdc\x2c\x38\xfd\x5b"
     708             :                         "\xfb\x0e\xc1\x85\x1e\xcc\x92\xbb"
     709             :                         "\x9b\xb1\xc4\xd5\x53\x14\xff\x8c"
     710             :                         "\x76\x49\xf5\x45\x90\x19\xa2";
     711             :                 /*
     712             :                  * First we check the initial bytes
     713             :                  * and the 0x3F timestamp.
     714             :                  */
     715         654 :                 cmp = memcmp(response.data + 16,
     716             :                              netapp_magic,
     717             :                              16);
     718         654 :                 if (cmp == 0) {
     719             :                         /*
     720             :                          * Then check everything after the
     721             :                          * client challenge
     722             :                          */
     723         654 :                         cmp = memcmp(response.data + 40,
     724         654 :                                      netapp_magic + 24,
     725         534 :                                      response.length - 40);
     726         654 :                         if (cmp == 0) {
     727         654 :                                 DBG_DEBUG("Invalid NETAPP NTLMv2_RESPONSE "
     728             :                                           "for user[%s\\%s] against "
     729             :                                           "SEC_CHAN(%u)[%s/%s] "
     730             :                                           "in workgroup[%s]\n",
     731             :                                           account_domain,
     732             :                                           account_name,
     733             :                                           creds->secure_channel_type,
     734             :                                           creds->computer_name,
     735             :                                           creds->account_name,
     736             :                                           workgroup);
     737         654 :                                 return NT_STATUS_OK;
     738             :                         }
     739             :                 }
     740             :         }
     741             : 
     742        9049 :         frame = talloc_stackframe();
     743             : 
     744        9049 :         err = ndr_pull_struct_blob(&response, frame, &v2_resp,
     745             :                 (ndr_pull_flags_fn_t)ndr_pull_NTLMv2_RESPONSE);
     746        9049 :         if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
     747           0 :                 NTSTATUS status;
     748           0 :                 status = ndr_map_error2ntstatus(err);
     749           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_BUFFER_TOO_SMALL)) {
     750             :                         /*
     751             :                          * We are supposed to ignore invalid buffers,
     752             :                          * see https://bugzilla.samba.org/show_bug.cgi?id=14932
     753             :                          */
     754           0 :                         status = NT_STATUS_OK;
     755             :                 }
     756           0 :                 DEBUG(2,("%s: Failed to parse NTLMv2_RESPONSE length=%u "
     757             :                         "for user[%s\\%s] against SEC_CHAN(%u)[%s/%s] "
     758             :                         "in workgroup[%s] - %s %s %s\n",
     759             :                         __func__,
     760             :                         (unsigned)response.length,
     761             :                         account_domain,
     762             :                         account_name,
     763             :                         creds->secure_channel_type,
     764             :                         creds->computer_name,
     765             :                         creds->account_name,
     766             :                         workgroup,
     767             :                         ndr_map_error2string(err),
     768             :                         NT_STATUS_IS_OK(status) ? "(ignoring) =>" : "=>",
     769             :                         nt_errstr(status)));
     770           0 :                 dump_data(2, response.data, response.length);
     771           0 :                 TALLOC_FREE(frame);
     772           0 :                 return status;
     773             :         }
     774             : 
     775        9049 :         if (DEBUGLVL(10)) {
     776           0 :                 NDR_PRINT_DEBUG(NTLMv2_RESPONSE, &v2_resp);
     777             :         }
     778             : 
     779             :         /*
     780             :          * Make sure the netbios computer name in the
     781             :          * NTLMv2_RESPONSE matches the computer name
     782             :          * in the secure channel credentials for workstation
     783             :          * trusts.
     784             :          *
     785             :          * And the netbios domain name matches our
     786             :          * workgroup.
     787             :          *
     788             :          * This prevents workstations from requesting
     789             :          * the session key of NTLMSSP sessions of clients
     790             :          * to other hosts.
     791             :          */
     792        9049 :         if (creds->secure_channel_type == SEC_CHAN_WKSTA) {
     793        5203 :                 av_nb_cn = ndr_ntlmssp_find_av(&v2_resp.Challenge.AvPairs,
     794             :                                                MsvAvNbComputerName);
     795        5203 :                 av_nb_dn = ndr_ntlmssp_find_av(&v2_resp.Challenge.AvPairs,
     796             :                                                MsvAvNbDomainName);
     797             :         }
     798             : 
     799        8479 :         if (av_nb_cn != NULL) {
     800        5203 :                 const char *v = NULL;
     801        5203 :                 char *a = NULL;
     802         584 :                 size_t len;
     803             : 
     804        5203 :                 v = av_nb_cn->Value.AvNbComputerName;
     805             : 
     806        5203 :                 a = talloc_strdup(frame, creds->account_name);
     807        5203 :                 if (a == NULL) {
     808           0 :                         TALLOC_FREE(frame);
     809           0 :                         return NT_STATUS_NO_MEMORY;
     810             :                 }
     811        5203 :                 len = strlen(a);
     812        5203 :                 if (len > 0 && a[len - 1] == '$') {
     813        5203 :                         a[len - 1] = '\0';
     814             :                 }
     815             : 
     816        5203 :                 cmp = strcasecmp_m(a, v);
     817        5203 :                 if (cmp != 0) {
     818           0 :                         DEBUG(2,("%s: NTLMv2_RESPONSE with "
     819             :                                  "NbComputerName[%s] rejected "
     820             :                                  "for user[%s\\%s] "
     821             :                                  "against SEC_CHAN_WKSTA[%s/%s] "
     822             :                                  "in workgroup[%s]\n",
     823             :                                  __func__, v,
     824             :                                  account_domain,
     825             :                                  account_name,
     826             :                                  creds->computer_name,
     827             :                                  creds->account_name,
     828             :                                  workgroup));
     829           0 :                         TALLOC_FREE(frame);
     830           0 :                         return NT_STATUS_LOGON_FAILURE;
     831             :                 }
     832             :         }
     833        9049 :         if (av_nb_dn != NULL) {
     834        5203 :                 const char *v = NULL;
     835             : 
     836        5203 :                 v = av_nb_dn->Value.AvNbDomainName;
     837             : 
     838        5203 :                 cmp = strcasecmp_m(workgroup, v);
     839        5203 :                 if (cmp != 0) {
     840           0 :                         DEBUG(2,("%s: NTLMv2_RESPONSE with "
     841             :                                  "NbDomainName[%s] rejected "
     842             :                                  "for user[%s\\%s] "
     843             :                                  "against SEC_CHAN_WKSTA[%s/%s] "
     844             :                                  "in workgroup[%s]\n",
     845             :                                  __func__, v,
     846             :                                  account_domain,
     847             :                                  account_name,
     848             :                                  creds->computer_name,
     849             :                                  creds->account_name,
     850             :                                  workgroup));
     851           0 :                         TALLOC_FREE(frame);
     852           0 :                         return NT_STATUS_LOGON_FAILURE;
     853             :                 }
     854             :         }
     855             : 
     856        9049 :         TALLOC_FREE(frame);
     857        9049 :         return NT_STATUS_OK;
     858             : }
     859             : 
     860             : enum encode_order {
     861             :         ENCODE_ORDER_PASSWORD_FIRST,
     862             :         ENCODE_ORDER_PASSWORD_LAST,
     863             : };
     864             : 
     865             : #define PASSWORD_BUFFER_LEN 512
     866             : 
     867        4034 : static ssize_t _encode_pwd_buffer_from_str(uint8_t buf[PASSWORD_BUFFER_LEN],
     868             :                                            const char *password,
     869             :                                            int string_flags,
     870             :                                            enum encode_order order)
     871             : {
     872          94 :         ssize_t new_pw_len;
     873        4034 :         size_t pw_pos = 0;
     874        4034 :         size_t random_pos = 0;
     875        4034 :         size_t random_len = 0;
     876             : 
     877             :         /* The incoming buffer can be any alignment. */
     878        4034 :         string_flags |= STR_NOALIGN;
     879             : 
     880        4034 :         new_pw_len = push_string(buf,
     881             :                                  password,
     882             :                                  PASSWORD_BUFFER_LEN,
     883             :                                  string_flags);
     884        4034 :         if (new_pw_len < 0) {
     885           0 :                 BURN_DATA_SIZE(buf, PASSWORD_BUFFER_LEN);
     886           0 :                 return -1;
     887             :         }
     888             : 
     889        4034 :         if (new_pw_len == PASSWORD_BUFFER_LEN) {
     890           0 :                 return new_pw_len;
     891             :         }
     892             : 
     893        4034 :         switch (order) {
     894         201 :         case ENCODE_ORDER_PASSWORD_FIRST:
     895         201 :                 pw_pos = 0;
     896         201 :                 random_pos = new_pw_len;
     897         201 :                 random_len = PASSWORD_BUFFER_LEN - random_pos;
     898         201 :                 break;
     899        3833 :         case ENCODE_ORDER_PASSWORD_LAST:
     900        3833 :                 pw_pos = PASSWORD_BUFFER_LEN - new_pw_len;
     901        3833 :                 random_pos = 0;
     902        3833 :                 random_len = pw_pos;
     903        3833 :                 memmove(buf + pw_pos, buf, new_pw_len);
     904        3740 :                 break;
     905             :         }
     906             : 
     907        4034 :         generate_random_buffer(buf + random_pos, random_len);
     908             : 
     909        4034 :         return new_pw_len;
     910             : }
     911             : 
     912             : /***********************************************************
     913             :  encode a password buffer with a unicode password.  The buffer
     914             :  is filled with random data to make it harder to attack.
     915             : ************************************************************/
     916        3833 : bool encode_pw_buffer(uint8_t buffer[516], const char *password, int string_flags)
     917             : {
     918          93 :         ssize_t pw_len;
     919             : 
     920        3833 :         pw_len = _encode_pwd_buffer_from_str(buffer,
     921             :                                              password,
     922             :                                              string_flags,
     923             :                                              ENCODE_ORDER_PASSWORD_LAST);
     924        3833 :         if (pw_len < 0 || pw_len > PASSWORD_BUFFER_LEN) {
     925           0 :                 return false;
     926             :         }
     927             : 
     928        3833 :         PUSH_LE_U32(buffer, PASSWORD_BUFFER_LEN, pw_len);
     929             : 
     930        3833 :         return true;
     931             : }
     932             : 
     933             : 
     934             : /***********************************************************
     935             :  decode a password buffer
     936             :  *new_pw_len is the length in bytes of the possibly mulitbyte
     937             :  returned password including termination.
     938             : ************************************************************/
     939             : 
     940          74 : bool decode_pw_buffer(TALLOC_CTX *ctx,
     941             :                       uint8_t in_buffer[516],
     942             :                       char **pp_new_pwrd,
     943             :                       size_t *new_pw_len,
     944             :                       charset_t string_charset)
     945             : {
     946           5 :         DATA_BLOB new_password;
     947          74 :         int byte_len=0;
     948           5 :         bool ok;
     949             : 
     950          74 :         *pp_new_pwrd = NULL;
     951          74 :         *new_pw_len = 0;
     952             : 
     953          74 :         ok = extract_pw_from_buffer(ctx, in_buffer, &new_password);
     954          74 :         if (!ok) {
     955           0 :                 return false;
     956             :         }
     957             : 
     958             :         /*
     959             :           Warning !!! : This function is called from some rpc call.
     960             :           The password IN the buffer may be a UNICODE string.
     961             :           The password IN new_pwrd is an ASCII string
     962             :           If you reuse that code somewhere else check first.
     963             :         */
     964             : 
     965             :         /* decode into the return buffer. */
     966          79 :         ok = convert_string_talloc(ctx,
     967             :                                    string_charset,
     968             :                                    CH_UNIX,
     969          74 :                                    new_password.data,
     970             :                                    new_password.length,
     971             :                                    pp_new_pwrd,
     972             :                                    new_pw_len);
     973          74 :         data_blob_free(&new_password);
     974          74 :         if (!ok) {
     975           0 :                 DBG_ERR("Failed to convert incoming password\n");
     976           0 :                 return false;
     977             :         }
     978          74 :         talloc_keep_secret(*pp_new_pwrd);
     979             : 
     980             : #ifdef DEBUG_PASSWORD
     981          74 :         DEBUG(100,("decode_pw_buffer: new_pwrd: "));
     982          74 :         dump_data(100, (uint8_t *)*pp_new_pwrd, *new_pw_len);
     983          74 :         DEBUG(100,("multibyte len:%lu\n", (unsigned long int)*new_pw_len));
     984          74 :         DEBUG(100,("original char len:%d\n", byte_len/2));
     985             : #endif
     986             : 
     987          69 :         return true;
     988             : }
     989             : 
     990             : #define MAX_PASSWORD_LEN 256
     991             : 
     992             : /*
     993             :  * [MS-SAMR] 2.2.6.32 This creates the buffer to be sent. It is of type
     994             :  * SAMPR_USER_PASSWORD_AES.
     995             :  */
     996         201 : bool encode_pwd_buffer514_from_str(uint8_t buffer[514],
     997             :                                    const char *password,
     998             :                                    uint32_t string_flags)
     999             : {
    1000           1 :         ssize_t pw_len;
    1001             : 
    1002         201 :         pw_len = _encode_pwd_buffer_from_str(buffer + 2,
    1003             :                                              password,
    1004             :                                              string_flags,
    1005             :                                              ENCODE_ORDER_PASSWORD_FIRST);
    1006         201 :         if (pw_len < 0) {
    1007           0 :                 return false;
    1008             :         }
    1009             : 
    1010         201 :         PUSH_LE_U16(buffer, 0, pw_len);
    1011             : 
    1012         201 :         return true;
    1013             : }
    1014             : 
    1015         136 : bool extract_pwd_blob_from_buffer514(TALLOC_CTX *mem_ctx,
    1016             :                                      const uint8_t in_buffer[514],
    1017             :                                      DATA_BLOB *new_password)
    1018             : {
    1019             : #ifdef DEBUG_PASSWORD
    1020         136 :         DEBUG(100, ("in_buffer: "));
    1021         136 :         dump_data(100, in_buffer, 514);
    1022             : #endif
    1023             : 
    1024         136 :         new_password->length = PULL_LE_U16(in_buffer, 0);
    1025         136 :         if (new_password->length == 0 || new_password->length > 512) {
    1026           0 :                 return false;
    1027             :         }
    1028             : 
    1029         138 :         new_password->data =
    1030         136 :                 talloc_memdup(mem_ctx, in_buffer + 2, new_password->length);
    1031         136 :         if (new_password->data == NULL) {
    1032           0 :                 return false;
    1033             :         }
    1034         136 :         talloc_keep_secret(new_password->data);
    1035             : 
    1036             : #ifdef DEBUG_PASSWORD
    1037         136 :         DEBUG(100, ("new_pwd_len: %zu\n", new_password->length));
    1038         136 :         DEBUG(100, ("new_pwd: "));
    1039         136 :         dump_data(100, new_password->data, new_password->length);
    1040             : #endif
    1041             : 
    1042         136 :         return true;
    1043             : }
    1044             : 
    1045           5 : bool decode_pwd_string_from_buffer514(TALLOC_CTX *mem_ctx,
    1046             :                                       const uint8_t in_buffer[514],
    1047             :                                       charset_t string_charset,
    1048             :                                       DATA_BLOB *decoded_password)
    1049             : {
    1050           5 :         DATA_BLOB new_password = {
    1051             :                 .length = 0,
    1052             :         };
    1053           1 :         bool ok;
    1054             : 
    1055           5 :         ok = extract_pwd_blob_from_buffer514(mem_ctx, in_buffer, &new_password);
    1056           5 :         if (!ok) {
    1057           0 :                 return false;
    1058             :         }
    1059             : 
    1060           6 :         ok = convert_string_talloc(mem_ctx,
    1061             :                                    string_charset,
    1062             :                                    CH_UNIX,
    1063           5 :                                    new_password.data,
    1064             :                                    new_password.length,
    1065           5 :                                    &decoded_password->data,
    1066             :                                    &decoded_password->length);
    1067           5 :         data_blob_free(&new_password);
    1068           5 :         if (!ok) {
    1069           0 :                 return false;
    1070             :         }
    1071           5 :         talloc_keep_secret(decoded_password->data);
    1072             : 
    1073           5 :         return true;
    1074             : }
    1075             : 
    1076             : /***********************************************************
    1077             :  Encode an arc4 password change buffer.
    1078             : ************************************************************/
    1079         771 : NTSTATUS encode_rc4_passwd_buffer(const char *passwd,
    1080             :                                   const DATA_BLOB *session_key,
    1081             :                                   struct samr_CryptPasswordEx *out_crypt_pwd)
    1082             : {
    1083         771 :         uint8_t _confounder[16] = {0};
    1084         771 :         DATA_BLOB confounder = data_blob_const(_confounder, 16);
    1085         771 :         DATA_BLOB pw_data = data_blob_const(out_crypt_pwd->data, 516);
    1086          74 :         bool ok;
    1087          74 :         int rc;
    1088             : 
    1089         771 :         ok = encode_pw_buffer(pw_data.data, passwd, STR_UNICODE);
    1090         771 :         if (!ok) {
    1091           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1092             :         }
    1093             : 
    1094         771 :         generate_random_buffer(confounder.data, confounder.length);
    1095             : 
    1096         771 :         rc = samba_gnutls_arcfour_confounded_md5(&confounder,
    1097             :                                                  session_key,
    1098             :                                                  &pw_data,
    1099             :                                                  SAMBA_GNUTLS_ENCRYPT);
    1100         771 :         if (rc < 0) {
    1101           0 :                 ZERO_ARRAY(_confounder);
    1102           0 :                 data_blob_clear(&pw_data);
    1103           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
    1104             :         }
    1105             : 
    1106             :         /*
    1107             :          * The packet format is the 516 byte RC4 encrypted
    1108             :          * password followed by the 16 byte counfounder
    1109             :          * The confounder is a salt to prevent pre-computed hash attacks on the
    1110             :          * database.
    1111             :          */
    1112         771 :         memcpy(&out_crypt_pwd->data[516], confounder.data, confounder.length);
    1113         771 :         ZERO_ARRAY(_confounder);
    1114             : 
    1115         771 :         return NT_STATUS_OK;
    1116             : }
    1117             : 
    1118             : /***********************************************************
    1119             :  Decode an arc4 encrypted password change buffer.
    1120             : ************************************************************/
    1121             : 
    1122          52 : NTSTATUS decode_rc4_passwd_buffer(const DATA_BLOB *psession_key,
    1123             :                                   struct samr_CryptPasswordEx *inout_crypt_pwd)
    1124             : {
    1125             :         /* Confounder is last 16 bytes. */
    1126          52 :         DATA_BLOB confounder = data_blob_const(&inout_crypt_pwd->data[516], 16);
    1127          52 :         DATA_BLOB pw_data = data_blob_const(&inout_crypt_pwd->data, 516);
    1128           3 :         int rc;
    1129             : 
    1130          52 :         rc = samba_gnutls_arcfour_confounded_md5(&confounder,
    1131             :                                                  psession_key,
    1132             :                                                  &pw_data,
    1133             :                                                  SAMBA_GNUTLS_DECRYPT);
    1134          52 :         if (rc < 0) {
    1135           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
    1136             :         }
    1137             : 
    1138          52 :         return NT_STATUS_OK;
    1139             : }
    1140             : 
    1141             : /***********************************************************
    1142             :  encode a password buffer with an already unicode password.  The
    1143             :  rest of the buffer is filled with random data to make it harder to attack.
    1144             : ************************************************************/
    1145             : 
    1146          73 : static bool create_pw_buffer_from_blob(uint8_t buffer[512],
    1147             :                                        const DATA_BLOB *in_password,
    1148             :                                        enum encode_order order)
    1149             : {
    1150          73 :         size_t pwd_pos = 0;
    1151          73 :         size_t random_pos = 0;
    1152          73 :         size_t random_len = 0;
    1153             : 
    1154          73 :         if (in_password->length > 512) {
    1155           0 :                 return false;
    1156             :         }
    1157             : 
    1158          73 :         switch (order) {
    1159           0 :         case ENCODE_ORDER_PASSWORD_FIRST:
    1160           0 :                 pwd_pos = 0;
    1161           0 :                 random_pos = in_password->length;
    1162           0 :                 break;
    1163          73 :         case ENCODE_ORDER_PASSWORD_LAST:
    1164          73 :                 pwd_pos = PASSWORD_BUFFER_LEN - in_password->length;
    1165          73 :                 random_pos = 0;
    1166          73 :                 break;
    1167             :         }
    1168          73 :         random_len = PASSWORD_BUFFER_LEN - in_password->length;
    1169             : 
    1170          73 :         memcpy(buffer + pwd_pos, in_password->data, in_password->length);
    1171          73 :         generate_random_buffer(buffer + random_pos, random_len);
    1172             : 
    1173          73 :         return true;
    1174             : }
    1175             : 
    1176          73 : bool set_pw_in_buffer(uint8_t buffer[516], const DATA_BLOB *password)
    1177             : {
    1178           7 :         bool ok;
    1179             : 
    1180          73 :         ok = create_pw_buffer_from_blob(buffer,
    1181             :                                         password,
    1182             :                                         ENCODE_ORDER_PASSWORD_LAST);
    1183          73 :         if (!ok) {
    1184           0 :                 return false;
    1185             :         }
    1186             : 
    1187             :         /*
    1188             :          * The length of the new password is in the last 4 bytes of
    1189             :          * the data buffer.
    1190             :          */
    1191          73 :         PUSH_LE_U32(buffer, PASSWORD_BUFFER_LEN, password->length);
    1192             : 
    1193          73 :         return true;
    1194             : }
    1195             : 
    1196             : /***********************************************************
    1197             :  decode a password buffer
    1198             :  *new_pw_size is the length in bytes of the extracted unicode password
    1199             : ************************************************************/
    1200        2396 : bool extract_pw_from_buffer(TALLOC_CTX *mem_ctx,
    1201             :                             uint8_t in_buffer[516], DATA_BLOB *new_pass)
    1202             : {
    1203        2396 :         int byte_len=0;
    1204             : 
    1205             :         /* The length of the new password is in the last 4 bytes of the data buffer. */
    1206             : 
    1207        2396 :         byte_len = IVAL(in_buffer, 512);
    1208             : 
    1209             : #ifdef DEBUG_PASSWORD
    1210        2396 :         dump_data(100, in_buffer, 516);
    1211             : #endif
    1212             : 
    1213             :         /* Password cannot be longer than the size of the password buffer */
    1214        2396 :         if ( (byte_len < 0) || (byte_len > 512)) {
    1215         453 :                 return false;
    1216             :         }
    1217             : 
    1218        1943 :         *new_pass = data_blob_talloc(mem_ctx, &in_buffer[512 - byte_len], byte_len);
    1219             : 
    1220        1943 :         if (!new_pass->data) {
    1221           0 :                 return false;
    1222             :         }
    1223        1943 :         talloc_keep_secret(new_pass->data);
    1224             : 
    1225        1943 :         return true;
    1226             : }
    1227             : 
    1228             : 
    1229             : /* encode a wkssvc_PasswordBuffer:
    1230             :  *
    1231             :  * similar to samr_CryptPasswordEx. Different: 8byte confounder (instead of
    1232             :  * 16byte), confounder in front of the 516 byte buffer (instead of after that
    1233             :  * buffer), calling MD5Update() first with session_key and then with confounder
    1234             :  * (vice versa in samr) - Guenther */
    1235             : 
    1236           1 : WERROR encode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,
    1237             :                                           const char *pwd,
    1238             :                                           DATA_BLOB *session_key,
    1239             :                                           struct wkssvc_PasswordBuffer **out_pwd_buf)
    1240             : {
    1241           1 :         struct wkssvc_PasswordBuffer *pwd_buf = NULL;
    1242           1 :         uint8_t _confounder[8] = {0};
    1243           1 :         DATA_BLOB confounder = data_blob_const(_confounder, 8);
    1244           1 :         uint8_t pwbuf[516] = {0};
    1245           1 :         DATA_BLOB encrypt_pwbuf = data_blob_const(pwbuf, 516);
    1246           1 :         int rc;
    1247             : 
    1248           1 :         pwd_buf = talloc_zero(mem_ctx, struct wkssvc_PasswordBuffer);
    1249           1 :         if (pwd_buf == NULL) {
    1250           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1251             :         }
    1252             : 
    1253           1 :         encode_pw_buffer(pwbuf, pwd, STR_UNICODE);
    1254             : 
    1255           1 :         generate_random_buffer(_confounder, sizeof(_confounder));
    1256             : 
    1257           1 :         rc = samba_gnutls_arcfour_confounded_md5(session_key,
    1258             :                                                  &confounder,
    1259             :                                                  &encrypt_pwbuf,
    1260             :                                                  SAMBA_GNUTLS_ENCRYPT);
    1261           1 :         if (rc < 0) {
    1262           0 :                 ZERO_ARRAY(_confounder);
    1263           0 :                 TALLOC_FREE(pwd_buf);
    1264           0 :                 return gnutls_error_to_werror(rc, WERR_CONTENT_BLOCKED);
    1265             :         }
    1266             : 
    1267           1 :         memcpy(&pwd_buf->data[0], confounder.data, confounder.length);
    1268           1 :         ZERO_ARRAY(_confounder);
    1269           1 :         memcpy(&pwd_buf->data[8], encrypt_pwbuf.data, encrypt_pwbuf.length);
    1270           1 :         ZERO_ARRAY(pwbuf);
    1271             : 
    1272           1 :         *out_pwd_buf = pwd_buf;
    1273             : 
    1274           1 :         return WERR_OK;
    1275             : }
    1276             : 
    1277           2 : WERROR decode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,
    1278             :                                           struct wkssvc_PasswordBuffer *pwd_buf,
    1279             :                                           DATA_BLOB *session_key,
    1280             :                                           char **pwd)
    1281             : {
    1282           2 :         uint8_t _confounder[8] = { 0 };
    1283           2 :         DATA_BLOB confounder = data_blob_const(_confounder, 8);
    1284           2 :         uint8_t pwbuf[516] = {0};
    1285           2 :         DATA_BLOB decrypt_pwbuf = data_blob_const(pwbuf, 516);
    1286           2 :         bool ok;
    1287           2 :         int rc;
    1288             : 
    1289           2 :         if (pwd_buf == NULL) {
    1290           0 :                 return WERR_INVALID_PASSWORD;
    1291             :         }
    1292             : 
    1293           2 :         *pwd = NULL;
    1294             : 
    1295           2 :         if (session_key->length != 16) {
    1296           0 :                 DEBUG(10,("invalid session key\n"));
    1297           0 :                 return WERR_INVALID_PASSWORD;
    1298             :         }
    1299             : 
    1300           2 :         confounder = data_blob_const(&pwd_buf->data[0], 8);
    1301           2 :         memcpy(&pwbuf, &pwd_buf->data[8], 516);
    1302             : 
    1303           2 :         rc = samba_gnutls_arcfour_confounded_md5(session_key,
    1304             :                                                  &confounder,
    1305             :                                                  &decrypt_pwbuf,
    1306             :                                                  SAMBA_GNUTLS_ENCRYPT);
    1307           2 :         if (rc < 0) {
    1308           0 :                 ZERO_ARRAY(_confounder);
    1309           0 :                 TALLOC_FREE(pwd_buf);
    1310           0 :                 return gnutls_error_to_werror(rc, WERR_CONTENT_BLOCKED);
    1311             :         }
    1312             : 
    1313           2 :         ok = decode_pw_buffer(mem_ctx,
    1314             :                               decrypt_pwbuf.data,
    1315             :                               pwd,
    1316             :                               &decrypt_pwbuf.length,
    1317             :                               CH_UTF16);
    1318           2 :         ZERO_ARRAY(pwbuf);
    1319             : 
    1320           2 :         if (!ok) {
    1321           0 :                 return WERR_INVALID_PASSWORD;
    1322             :         }
    1323             : 
    1324           2 :         return WERR_OK;
    1325             : }

Generated by: LCOV version 1.14