LCOV - code coverage report
Current view: top level - libcli/auth - smbencrypt.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 347 485 71.5 %
Date: 2024-06-13 04:01:37 Functions: 30 33 90.9 %

          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        1548 : int SMBencrypt_hash(const uint8_t lm_hash[16], const uint8_t *c8, uint8_t p24[24])
      37             : {
      38             :         uint8_t p21[21];
      39             :         int rc;
      40             : 
      41        1548 :         memset(p21,'\0',21);
      42        1548 :         memcpy(p21, lm_hash, 16);
      43             : 
      44        1548 :         rc = SMBOWFencrypt(p21, c8, p24);
      45             : 
      46             : #ifdef DEBUG_PASSWORD
      47        1548 :         DEBUG(100,("SMBencrypt_hash: lm#, challenge, response\n"));
      48        1548 :         dump_data(100, p21, 16);
      49        1548 :         dump_data(100, c8, 8);
      50        1548 :         dump_data(100, p24, 24);
      51             : #endif
      52             : 
      53        1548 :         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        1346 : bool SMBencrypt(const char *passwd, const uint8_t *c8, uint8_t p24[24])
      65             : {
      66             :         bool ret;
      67             :         uint8_t lm_hash[16];
      68             :         int rc;
      69             : 
      70        1346 :         ret = E_deshash(passwd, lm_hash);
      71        1346 :         rc = SMBencrypt_hash(lm_hash, c8, p24);
      72        1346 :         if (rc != 0) {
      73           0 :                 ret = false;
      74             :         }
      75        1346 :         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       20996 : bool E_md4hash(const char *passwd, uint8_t p16[16])
      85             : {
      86             :         size_t len;
      87             :         smb_ucs2_t *wpwd;
      88             :         bool ret;
      89             : 
      90       20996 :         ret = push_ucs2_talloc(NULL, &wpwd, passwd, &len);
      91       20996 :         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       20996 :         len -= 2;
      99       20996 :         mdfour(p16, (const uint8_t *)wpwd, len);
     100             : 
     101       20996 :         talloc_free(wpwd);
     102       20996 :         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        8697 : bool E_deshash(const char *passwd, uint8_t p16[16])
     114             : {
     115             :         bool ret;
     116             :         int rc;
     117             :         uint8_t dospwd[14];
     118        8697 :         TALLOC_CTX *frame = talloc_stackframe();
     119             : 
     120             :         size_t converted_size;
     121             : 
     122             :         char *tmpbuf;
     123             : 
     124        8697 :         ZERO_STRUCT(dospwd);
     125             : 
     126        8697 :         tmpbuf = strupper_talloc(frame, passwd);
     127        8697 :         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        8697 :         ZERO_STRUCT(dospwd);
     136             : 
     137        8697 :         ret = convert_string_error(CH_UNIX, CH_DOS, tmpbuf, strlen(tmpbuf), dospwd, sizeof(dospwd), &converted_size);
     138        8697 :         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        8697 :         rc = E_P16((const uint8_t *)dospwd, p16);
     146        8697 :         if (rc != 0) {
     147           0 :                 ret = false;
     148             :         }
     149             : 
     150        8697 :         ZERO_STRUCT(dospwd);
     151             : 
     152        8697 :         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          27 : 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          27 :         memset(nt_p16, '\0', 16);
     168          27 :         E_md4hash(pwd, nt_p16);
     169             : 
     170             : #ifdef DEBUG_PASSWORD
     171          27 :         DEBUG(100,("nt_lm_owf_gen: pwd, nt#\n"));
     172          27 :         dump_data(120, (const uint8_t *)pwd, strlen(pwd));
     173          27 :         dump_data(100, nt_p16, 16);
     174             : #endif
     175             : 
     176          27 :         E_deshash(pwd, (uint8_t *)p16);
     177             : 
     178             : #ifdef DEBUG_PASSWORD
     179          27 :         DEBUG(100,("nt_lm_owf_gen: pwd, lm#\n"));
     180          27 :         dump_data(120, (const uint8_t *)pwd, strlen(pwd));
     181          27 :         dump_data(100, p16, 16);
     182             : #endif
     183          27 : }
     184             : 
     185             : /* Does both the NTLMv2 owfs of a user's password */
     186       38231 : 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             :         smb_ucs2_t *user;
     191             :         smb_ucs2_t *domain;
     192             :         size_t user_byte_len;
     193             :         size_t domain_byte_len;
     194       38231 :         gnutls_hmac_hd_t hmac_hnd = NULL;
     195             :         int rc;
     196       38231 :         bool ok = false;
     197       38231 :         TALLOC_CTX *mem_ctx = talloc_init("ntv2_owf_gen for %s\\%s", domain_in, user_in);
     198             : 
     199       38231 :         if (!mem_ctx) {
     200           0 :                 return false;
     201             :         }
     202             : 
     203       38231 :         if (!user_in) {
     204           0 :                 user_in = "";
     205             :         }
     206             : 
     207       38231 :         if (!domain_in) {
     208        1728 :                 domain_in = "";
     209             :         }
     210             : 
     211       38231 :         user_in = strupper_talloc(mem_ctx, user_in);
     212       38231 :         if (user_in == NULL) {
     213           0 :                 talloc_free(mem_ctx);
     214           0 :                 return false;
     215             :         }
     216             : 
     217       38231 :         ok = push_ucs2_talloc(mem_ctx, &user, user_in, &user_byte_len );
     218       38231 :         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       38231 :         ok = push_ucs2_talloc(mem_ctx, &domain, domain_in, &domain_byte_len);
     225       38231 :         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       38231 :         SMB_ASSERT(user_byte_len >= 2);
     232       38231 :         SMB_ASSERT(domain_byte_len >= 2);
     233             : 
     234             :         /* We don't want null termination */
     235       38231 :         user_byte_len = user_byte_len - 2;
     236       38231 :         domain_byte_len = domain_byte_len - 2;
     237             : 
     238       38231 :         rc = gnutls_hmac_init(&hmac_hnd,
     239             :                               GNUTLS_MAC_MD5,
     240             :                               owf,
     241             :                               16);
     242       38231 :         if (rc < 0) {
     243           0 :                 ok = false;
     244           0 :                 goto out;
     245             :         }
     246             : 
     247       38231 :         rc = gnutls_hmac(hmac_hnd, user, user_byte_len);
     248       38231 :         if (rc < 0) {
     249           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     250           0 :                 ok = false;
     251           0 :                 goto out;
     252             :         }
     253       38231 :         rc = gnutls_hmac(hmac_hnd, domain, domain_byte_len);
     254       38231 :         if (rc < 0) {
     255           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     256           0 :                 ok = false;
     257           0 :                 goto out;
     258             :         }
     259             : 
     260       38231 :         gnutls_hmac_deinit(hmac_hnd, kr_buf);
     261             : 
     262             : #ifdef DEBUG_PASSWORD
     263       38231 :         DEBUG(100, ("ntv2_owf_gen: user, domain, owfkey, kr\n"));
     264       38231 :         dump_data(100, (uint8_t *)user, user_byte_len);
     265       38231 :         dump_data(100, (uint8_t *)domain, domain_byte_len);
     266       38231 :         dump_data(100, owf, 16);
     267       38231 :         dump_data(100, kr_buf, 16);
     268             : #endif
     269             : 
     270       38231 :         ok = true;
     271       38231 : out:
     272       38231 :         talloc_free(mem_ctx);
     273       38231 :         return ok;
     274             : }
     275             : 
     276             : /* Does the des encryption from the NT or LM MD4 hash. */
     277        9941 : int SMBOWFencrypt(const uint8_t passwd[16], const uint8_t *c8, uint8_t p24[24])
     278             : {
     279             :         uint8_t p21[21];
     280             : 
     281        9941 :         ZERO_STRUCT(p21);
     282             : 
     283        9941 :         memcpy(p21, passwd, 16);
     284        9941 :         return E_P24(p21, c8, p24);
     285             : }
     286             : 
     287             : /* Does the des encryption. */
     288             : 
     289        3145 : int SMBNTencrypt_hash(const uint8_t nt_hash[16], const uint8_t *c8, uint8_t *p24)
     290             : {
     291             :         uint8_t p21[21];
     292             :         int rc;
     293             : 
     294        3145 :         memset(p21,'\0',21);
     295        3145 :         memcpy(p21, nt_hash, 16);
     296        3145 :         rc = SMBOWFencrypt(p21, c8, p24);
     297             : 
     298             : #ifdef DEBUG_PASSWORD
     299        3145 :         DEBUG(100,("SMBNTencrypt: nt#, challenge, response\n"));
     300        3145 :         dump_data(100, p21, 16);
     301        3145 :         dump_data(100, c8, 8);
     302        3145 :         dump_data(100, p24, 24);
     303             : #endif
     304             : 
     305        3145 :         return rc;
     306             : }
     307             : 
     308             : /* Does the NT MD4 hash then des encryption. Plaintext version of the above. */
     309             : 
     310        3145 : int SMBNTencrypt(const char *passwd, const uint8_t *c8, uint8_t *p24)
     311             : {
     312             :         uint8_t nt_hash[16];
     313        3145 :         E_md4hash(passwd, nt_hash);
     314        3145 :         return SMBNTencrypt_hash(nt_hash, c8, p24);
     315             : }
     316             : 
     317             : 
     318             : /* Does the md5 encryption from the Key Response for NTLMv2. */
     319       43782 : 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       43782 :         gnutls_hmac_hd_t hmac_hnd = NULL;
     325             :         NTSTATUS status;
     326             :         int rc;
     327             : 
     328       43782 :         rc = gnutls_hmac_init(&hmac_hnd,
     329             :                               GNUTLS_MAC_MD5,
     330             :                               kr,
     331             :                               16);
     332       43782 :         if (rc < 0) {
     333           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     334             :         }
     335             : 
     336       43782 :         rc = gnutls_hmac(hmac_hnd, srv_chal->data, srv_chal->length);
     337       43782 :         if (rc < 0) {
     338           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     339           0 :                 goto out;
     340             :         }
     341       43782 :         rc = gnutls_hmac(hmac_hnd, smbcli_chal->data, smbcli_chal->length);
     342       43782 :         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       43782 :         DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, smbcli_chal, resp_buf\n"));
     349       43782 :         dump_data(100, srv_chal->data, srv_chal->length);
     350       43782 :         dump_data(100, smbcli_chal->data, smbcli_chal->length);
     351       43782 :         dump_data(100, resp_buf, 16);
     352             : #endif
     353             : 
     354       43782 :         status = NT_STATUS_OK;
     355       43782 : out:
     356       43782 :         gnutls_hmac_deinit(hmac_hnd, resp_buf);
     357       43782 :         return status;
     358             : }
     359             : 
     360       31508 : NTSTATUS SMBsesskeygen_ntv2(const uint8_t kr[16],
     361             :                             const uint8_t *nt_resp,
     362             :                             uint8_t sess_key[16])
     363             : {
     364             :         int rc;
     365             : 
     366             :         /* a very nice, 128 bit, variable session key */
     367       31508 :         rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
     368             :                               kr,
     369             :                               16,
     370             :                               nt_resp,
     371             :                               16,
     372             :                               sess_key);
     373       31508 :         if (rc != 0) {
     374           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
     375             :         }
     376             : 
     377             : #ifdef DEBUG_PASSWORD
     378       31508 :         DEBUG(100, ("SMBsesskeygen_ntv2:\n"));
     379       31508 :         dump_data(100, sess_key, 16);
     380             : #endif
     381             : 
     382       31508 :         return NT_STATUS_OK;
     383             : }
     384             : 
     385        5028 : 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        5028 :         mdfour((uint8_t *)sess_key, kr, 16);
     391             : 
     392             : #ifdef DEBUG_PASSWORD
     393        5028 :         DEBUG(100, ("SMBsesskeygen_ntv1:\n"));
     394        5028 :         dump_data(100, sess_key, 16);
     395             : #endif
     396        5028 : }
     397             : 
     398           0 : 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             :         uint8_t p24[24];
     405             :         uint8_t partial_lm_hash[14];
     406             :         int rc;
     407             : 
     408           0 :         memcpy(partial_lm_hash, lm_hash, 8);
     409           0 :         memset(partial_lm_hash + 8, 0xbd, 6);
     410             : 
     411           0 :         rc = des_crypt56_gnutls(p24, lm_resp, partial_lm_hash, SAMBA_GNUTLS_ENCRYPT);
     412           0 :         if (rc < 0) {
     413           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
     414             :         }
     415           0 :         rc = des_crypt56_gnutls(p24+8, lm_resp, partial_lm_hash + 7, SAMBA_GNUTLS_ENCRYPT);
     416           0 :         if (rc < 0) {
     417           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
     418             :         }
     419             : 
     420           0 :         memcpy(sess_key, p24, 16);
     421             : 
     422             : #ifdef DEBUG_PASSWORD
     423           0 :         DEBUG(100, ("SMBsesskeygen_lm_sess_key: \n"));
     424           0 :         dump_data(100, sess_key, 16);
     425             : #endif
     426             : 
     427           0 :         return NT_STATUS_OK;
     428             : }
     429             : 
     430        4518 : DATA_BLOB NTLMv2_generate_names_blob(TALLOC_CTX *mem_ctx,
     431             :                                      const char *hostname,
     432             :                                      const char *domain)
     433             : {
     434        4518 :         DATA_BLOB names_blob = data_blob_talloc(mem_ctx, NULL, 0);
     435             : 
     436             :         /* Deliberately ignore return here.. */
     437        4518 :         if (hostname != NULL) {
     438        4512 :                 (void)msrpc_gen(mem_ctx, &names_blob,
     439             :                           "aaa",
     440             :                           MsvAvNbDomainName, domain,
     441             :                           MsvAvNbComputerName, hostname,
     442             :                           MsvAvEOL, "");
     443             :         } else {
     444           6 :                 (void)msrpc_gen(mem_ctx, &names_blob,
     445             :                           "aa",
     446             :                           MsvAvNbDomainName, domain,
     447             :                           MsvAvEOL, "");
     448             :         }
     449        4518 :         return names_blob;
     450             : }
     451             : 
     452       14081 : static DATA_BLOB NTLMv2_generate_client_data(TALLOC_CTX *mem_ctx,
     453             :                                              NTTIME nttime,
     454             :                                              const DATA_BLOB *names_blob)
     455             : {
     456             :         uint8_t client_chal[8];
     457       14081 :         DATA_BLOB response = data_blob(NULL, 0);
     458             :         uint8_t long_date[8];
     459             : 
     460       14081 :         generate_random_buffer(client_chal, sizeof(client_chal));
     461             : 
     462       14081 :         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       14081 :         (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        2788 :                   names_blob->data, names_blob->length);  /* End of name list */
     474             : 
     475       14081 :         return response;
     476             : }
     477             : 
     478       14081 : 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             :         uint8_t ntlmv2_response[16];
     485             :         DATA_BLOB ntlmv2_client_data;
     486             :         DATA_BLOB final_response;
     487             :         NTSTATUS status;
     488             : 
     489       14081 :         TALLOC_CTX *mem_ctx = talloc_named(out_mem_ctx, 0,
     490             :                                            "NTLMv2_generate_response internal context");
     491             : 
     492       14081 :         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       14081 :         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       14081 :         status = SMBOWFencrypt_ntv2(ntlm_v2_hash,
     503             :                                     server_chal,
     504             :                                     &ntlmv2_client_data,
     505             :                                     ntlmv2_response);
     506       14081 :         if (!NT_STATUS_IS_OK(status)) {
     507           0 :                 talloc_free(mem_ctx);
     508           0 :                 return data_blob(NULL, 0);
     509             :         }
     510             : 
     511       14081 :         final_response = data_blob_talloc(out_mem_ctx, NULL, sizeof(ntlmv2_response) + ntlmv2_client_data.length);
     512             : 
     513       14081 :         memcpy(final_response.data, ntlmv2_response, sizeof(ntlmv2_response));
     514             : 
     515       25374 :         memcpy(final_response.data+sizeof(ntlmv2_response),
     516       14081 :                ntlmv2_client_data.data, ntlmv2_client_data.length);
     517             : 
     518       14081 :         talloc_free(mem_ctx);
     519             : 
     520       14081 :         return final_response;
     521             : }
     522             : 
     523        5551 : 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             :         uint8_t lmv2_response[16];
     528        5551 :         DATA_BLOB lmv2_client_data = data_blob_talloc(mem_ctx, NULL, 8);
     529        5551 :         DATA_BLOB final_response = data_blob_talloc(mem_ctx, NULL,24);
     530             :         NTSTATUS status;
     531             : 
     532             :         /* LMv2 */
     533             :         /* client-supplied random data */
     534        5551 :         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        5551 :         status = SMBOWFencrypt_ntv2(ntlm_v2_hash,
     538             :                                     server_chal,
     539             :                                     &lmv2_client_data,
     540             :                                     lmv2_response);
     541        5551 :         if (!NT_STATUS_IS_OK(status)) {
     542           0 :                 data_blob_free(&lmv2_client_data);
     543           0 :                 return data_blob(NULL, 0);
     544             :         }
     545        5551 :         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       10533 :         memcpy(final_response.data+sizeof(lmv2_response),
     550        5551 :                lmv2_client_data.data, lmv2_client_data.length);
     551             : 
     552        5551 :         data_blob_free(&lmv2_client_data);
     553             : 
     554        5551 :         return final_response;
     555             : }
     556             : 
     557       14081 : 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             :         uint8_t ntlm_v2_hash[16];
     566             :         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       14081 :         if (!ntv2_owf_gen(nt_hash, user, domain, ntlm_v2_hash)) {
     573           0 :                 return false;
     574             :         }
     575             : 
     576       14081 :         if (nt_response) {
     577       14081 :                 const NTTIME *nttime = server_timestamp;
     578       14081 :                 NTTIME _now = 0;
     579             : 
     580       14081 :                 if (nttime == NULL) {
     581        5551 :                         struct timeval tv_now = timeval_current();
     582        5551 :                         _now = timeval_to_nttime(&tv_now);
     583        5551 :                         nttime = &_now;
     584             :                 }
     585             : 
     586       14081 :                 *nt_response = NTLMv2_generate_response(mem_ctx,
     587             :                                                         ntlm_v2_hash,
     588             :                                                         server_chal,
     589             :                                                         *nttime,
     590             :                                                         names_blob);
     591       14081 :                 if (user_session_key) {
     592       13992 :                         *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       25236 :                         status = SMBsesskeygen_ntv2(ntlm_v2_hash,
     597       13992 :                                                     nt_response->data,
     598             :                                                     user_session_key->data);
     599       13992 :                         if (!NT_STATUS_IS_OK(status)) {
     600           0 :                                 return false;
     601             :                         }
     602             :                 }
     603             :         }
     604             : 
     605             :         /* LMv2 */
     606             : 
     607       14081 :         if (lm_response) {
     608       14081 :                 if (server_timestamp != NULL) {
     609        8530 :                         *lm_response = data_blob_talloc_zero(mem_ctx, 24);
     610             :                 } else {
     611        5551 :                         *lm_response = LMv2_generate_response(mem_ctx,
     612             :                                                               ntlm_v2_hash,
     613             :                                                               server_chal);
     614             :                 }
     615       14081 :                 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        6532 :                         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       14081 :         return true;
     630             : }
     631             : 
     632        3387 : 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             :         uint8_t nt_hash[16];
     641        3387 :         E_md4hash(password, nt_hash);
     642             : 
     643        3387 :         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       10162 : 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       10162 :         TALLOC_CTX *frame = NULL;
     656             :         /* RespType + HiRespType */
     657             :         static const char *magic = "\x01\x01";
     658             :         int cmp;
     659             :         struct NTLMv2_RESPONSE v2_resp;
     660             :         enum ndr_err_code err;
     661       10162 :         const struct AV_PAIR *av_nb_cn = NULL;
     662       10162 :         const struct AV_PAIR *av_nb_dn = NULL;
     663             : 
     664       10162 :         if (response.length < 48) {
     665             :                 /*
     666             :                  * NTLMv2_RESPONSE has at least 48 bytes.
     667             :                  */
     668        4172 :                 return NT_STATUS_OK;
     669             :         }
     670             : 
     671        5990 :         cmp = memcmp(response.data + 16, magic, 2);
     672        5990 :         if (cmp != 0) {
     673             :                 /*
     674             :                  * It doesn't look like a valid NTLMv2_RESPONSE
     675             :                  */
     676         432 :                 return NT_STATUS_OK;
     677             :         }
     678             : 
     679        5558 :         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             :                 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         270 :                 cmp = memcmp(response.data + 16,
     716             :                              netapp_magic,
     717             :                              16);
     718         270 :                 if (cmp == 0) {
     719             :                         /*
     720             :                          * Then check everything after the
     721             :                          * client challenge
     722             :                          */
     723         540 :                         cmp = memcmp(response.data + 40,
     724         270 :                                      netapp_magic + 24,
     725         270 :                                      response.length - 40);
     726         270 :                         if (cmp == 0) {
     727         270 :                                 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         270 :                                 return NT_STATUS_OK;
     738             :                         }
     739             :                 }
     740             :         }
     741             : 
     742        5288 :         frame = talloc_stackframe();
     743             : 
     744        5288 :         err = ndr_pull_struct_blob(&response, frame, &v2_resp,
     745             :                 (ndr_pull_flags_fn_t)ndr_pull_NTLMv2_RESPONSE);
     746        5288 :         if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
     747             :                 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        5288 :         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        5288 :         if (creds->secure_channel_type == SEC_CHAN_WKSTA) {
     793        3286 :                 av_nb_cn = ndr_ntlmssp_find_av(&v2_resp.Challenge.AvPairs,
     794             :                                                MsvAvNbComputerName);
     795        3286 :                 av_nb_dn = ndr_ntlmssp_find_av(&v2_resp.Challenge.AvPairs,
     796             :                                                MsvAvNbDomainName);
     797             :         }
     798             : 
     799        5288 :         if (av_nb_cn != NULL) {
     800        3286 :                 const char *v = NULL;
     801        3286 :                 char *a = NULL;
     802             :                 size_t len;
     803             : 
     804        3286 :                 v = av_nb_cn->Value.AvNbComputerName;
     805             : 
     806        3286 :                 a = talloc_strdup(frame, creds->account_name);
     807        3286 :                 if (a == NULL) {
     808           0 :                         TALLOC_FREE(frame);
     809           0 :                         return NT_STATUS_NO_MEMORY;
     810             :                 }
     811        3286 :                 len = strlen(a);
     812        3286 :                 if (len > 0 && a[len - 1] == '$') {
     813        3286 :                         a[len - 1] = '\0';
     814             :                 }
     815             : 
     816        3286 :                 cmp = strcasecmp_m(a, v);
     817        3286 :                 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        5288 :         if (av_nb_dn != NULL) {
     834        3286 :                 const char *v = NULL;
     835             : 
     836        3286 :                 v = av_nb_dn->Value.AvNbDomainName;
     837             : 
     838        3286 :                 cmp = strcasecmp_m(workgroup, v);
     839        3286 :                 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        5288 :         TALLOC_FREE(frame);
     857        5288 :         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        3108 : 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             :         ssize_t new_pw_len;
     873        3108 :         size_t pw_pos = 0;
     874        3108 :         size_t random_pos = 0;
     875        3108 :         size_t random_len = 0;
     876             : 
     877             :         /* The incoming buffer can be any alignment. */
     878        3108 :         string_flags |= STR_NOALIGN;
     879             : 
     880        3108 :         new_pw_len = push_string(buf,
     881             :                                  password,
     882             :                                  PASSWORD_BUFFER_LEN,
     883             :                                  string_flags);
     884        3108 :         if (new_pw_len < 0) {
     885           0 :                 BURN_DATA_SIZE(buf, PASSWORD_BUFFER_LEN);
     886           0 :                 return -1;
     887             :         }
     888             : 
     889        3108 :         if (new_pw_len == PASSWORD_BUFFER_LEN) {
     890           0 :                 return new_pw_len;
     891             :         }
     892             : 
     893        3108 :         switch (order) {
     894         107 :         case ENCODE_ORDER_PASSWORD_FIRST:
     895         107 :                 pw_pos = 0;
     896         107 :                 random_pos = new_pw_len;
     897         107 :                 random_len = PASSWORD_BUFFER_LEN - random_pos;
     898         107 :                 break;
     899        3001 :         case ENCODE_ORDER_PASSWORD_LAST:
     900        3001 :                 pw_pos = PASSWORD_BUFFER_LEN - new_pw_len;
     901        3001 :                 random_pos = 0;
     902        3001 :                 random_len = pw_pos;
     903        3001 :                 memmove(buf + pw_pos, buf, new_pw_len);
     904        3001 :                 break;
     905             :         }
     906             : 
     907        3108 :         generate_random_buffer(buf + random_pos, random_len);
     908             : 
     909        3108 :         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        3001 : bool encode_pw_buffer(uint8_t buffer[516], const char *password, int string_flags)
     917             : {
     918             :         ssize_t pw_len;
     919             : 
     920        3001 :         pw_len = _encode_pwd_buffer_from_str(buffer,
     921             :                                              password,
     922             :                                              string_flags,
     923             :                                              ENCODE_ORDER_PASSWORD_LAST);
     924        3001 :         if (pw_len < 0 || pw_len > PASSWORD_BUFFER_LEN) {
     925           0 :                 return false;
     926             :         }
     927             : 
     928        3001 :         PUSH_LE_U32(buffer, PASSWORD_BUFFER_LEN, pw_len);
     929             : 
     930        3001 :         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           2 : 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             :         DATA_BLOB new_password;
     947           2 :         int byte_len=0;
     948             :         bool ok;
     949             : 
     950           2 :         *pp_new_pwrd = NULL;
     951           2 :         *new_pw_len = 0;
     952             : 
     953           2 :         ok = extract_pw_from_buffer(ctx, in_buffer, &new_password);
     954           2 :         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           4 :         ok = convert_string_talloc(ctx,
     967             :                                    string_charset,
     968             :                                    CH_UNIX,
     969           2 :                                    new_password.data,
     970             :                                    new_password.length,
     971             :                                    (void *)pp_new_pwrd,
     972             :                                    new_pw_len);
     973           2 :         data_blob_free(&new_password);
     974           2 :         if (!ok) {
     975           0 :                 DBG_ERR("Failed to convert incoming password\n");
     976           0 :                 return false;
     977             :         }
     978           2 :         talloc_keep_secret(*pp_new_pwrd);
     979             : 
     980             : #ifdef DEBUG_PASSWORD
     981           2 :         DEBUG(100,("decode_pw_buffer: new_pwrd: "));
     982           2 :         dump_data(100, (uint8_t *)*pp_new_pwrd, *new_pw_len);
     983           2 :         DEBUG(100,("multibyte len:%lu\n", (unsigned long int)*new_pw_len));
     984           2 :         DEBUG(100,("original char len:%d\n", byte_len/2));
     985             : #endif
     986             : 
     987           2 :         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         107 : bool encode_pwd_buffer514_from_str(uint8_t buffer[514],
     997             :                                    const char *password,
     998             :                                    uint32_t string_flags)
     999             : {
    1000             :         ssize_t pw_len;
    1001             : 
    1002         107 :         pw_len = _encode_pwd_buffer_from_str(buffer + 2,
    1003             :                                              password,
    1004             :                                              string_flags,
    1005             :                                              ENCODE_ORDER_PASSWORD_FIRST);
    1006         107 :         if (pw_len < 0) {
    1007           0 :                 return false;
    1008             :         }
    1009             : 
    1010         107 :         PUSH_LE_U16(buffer, 0, pw_len);
    1011             : 
    1012         107 :         return true;
    1013             : }
    1014             : 
    1015          66 : 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          66 :         DEBUG(100, ("in_buffer: "));
    1021          66 :         dump_data(100, in_buffer, 514);
    1022             : #endif
    1023             : 
    1024          66 :         new_password->length = PULL_LE_U16(in_buffer, 0);
    1025          66 :         if (new_password->length == 0 || new_password->length > 512) {
    1026           0 :                 return false;
    1027             :         }
    1028             : 
    1029          66 :         new_password->data =
    1030          66 :                 talloc_memdup(mem_ctx, in_buffer + 2, new_password->length);
    1031          66 :         if (new_password->data == NULL) {
    1032           0 :                 return false;
    1033             :         }
    1034          66 :         talloc_keep_secret(new_password->data);
    1035             : 
    1036             : #ifdef DEBUG_PASSWORD
    1037          66 :         DEBUG(100, ("new_pwd_len: %zu\n", new_password->length));
    1038          66 :         DEBUG(100, ("new_pwd: "));
    1039          66 :         dump_data(100, new_password->data, new_password->length);
    1040             : #endif
    1041             : 
    1042          66 :         return true;
    1043             : }
    1044             : 
    1045           1 : 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           1 :         DATA_BLOB new_password = {
    1051             :                 .length = 0,
    1052             :         };
    1053             :         bool ok;
    1054             : 
    1055           1 :         ok = extract_pwd_blob_from_buffer514(mem_ctx, in_buffer, &new_password);
    1056           1 :         if (!ok) {
    1057           0 :                 return false;
    1058             :         }
    1059             : 
    1060           1 :         ok = convert_string_talloc(mem_ctx,
    1061             :                                    string_charset,
    1062             :                                    CH_UNIX,
    1063           1 :                                    new_password.data,
    1064             :                                    new_password.length,
    1065           1 :                                    (void *)&decoded_password->data,
    1066             :                                    &decoded_password->length);
    1067           1 :         data_blob_free(&new_password);
    1068           1 :         if (!ok) {
    1069           0 :                 return false;
    1070             :         }
    1071           1 :         talloc_keep_secret(decoded_password->data);
    1072             : 
    1073           1 :         return true;
    1074             : }
    1075             : 
    1076             : /***********************************************************
    1077             :  Encode an arc4 password change buffer.
    1078             : ************************************************************/
    1079         422 : NTSTATUS encode_rc4_passwd_buffer(const char *passwd,
    1080             :                                   const DATA_BLOB *session_key,
    1081             :                                   struct samr_CryptPasswordEx *out_crypt_pwd)
    1082             : {
    1083         422 :         uint8_t _confounder[16] = {0};
    1084         422 :         DATA_BLOB confounder = data_blob_const(_confounder, 16);
    1085         422 :         DATA_BLOB pw_data = data_blob_const(out_crypt_pwd->data, 516);
    1086             :         bool ok;
    1087             :         int rc;
    1088             : 
    1089         422 :         ok = encode_pw_buffer(pw_data.data, passwd, STR_UNICODE);
    1090         422 :         if (!ok) {
    1091           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1092             :         }
    1093             : 
    1094         422 :         generate_random_buffer(confounder.data, confounder.length);
    1095             : 
    1096         422 :         rc = samba_gnutls_arcfour_confounded_md5(&confounder,
    1097             :                                                  session_key,
    1098             :                                                  &pw_data,
    1099             :                                                  SAMBA_GNUTLS_ENCRYPT);
    1100         422 :         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             :          * pasword followed by the 16 byte counfounder
    1109             :          * The confounder is a salt to prevent pre-computed hash attacks on the
    1110             :          * database.
    1111             :          */
    1112         422 :         memcpy(&out_crypt_pwd->data[516], confounder.data, confounder.length);
    1113         422 :         ZERO_ARRAY(_confounder);
    1114             : 
    1115         422 :         return NT_STATUS_OK;
    1116             : }
    1117             : 
    1118             : /***********************************************************
    1119             :  Decode an arc4 encrypted password change buffer.
    1120             : ************************************************************/
    1121             : 
    1122           1 : 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           1 :         DATA_BLOB confounder = data_blob_const(&inout_crypt_pwd->data[516], 16);
    1127           1 :         DATA_BLOB pw_data = data_blob_const(&inout_crypt_pwd->data, 516);
    1128             :         int rc;
    1129             : 
    1130           1 :         rc = samba_gnutls_arcfour_confounded_md5(&confounder,
    1131             :                                                  psession_key,
    1132             :                                                  &pw_data,
    1133             :                                                  SAMBA_GNUTLS_DECRYPT);
    1134           1 :         if (rc < 0) {
    1135           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
    1136             :         }
    1137             : 
    1138           1 :         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          42 : static bool create_pw_buffer_from_blob(uint8_t buffer[512],
    1147             :                                        const DATA_BLOB *in_password,
    1148             :                                        enum encode_order order)
    1149             : {
    1150          42 :         size_t pwd_pos = 0;
    1151          42 :         size_t random_pos = 0;
    1152          42 :         size_t random_len = 0;
    1153             : 
    1154          42 :         if (in_password->length > 512) {
    1155           0 :                 return false;
    1156             :         }
    1157             : 
    1158          42 :         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          42 :         case ENCODE_ORDER_PASSWORD_LAST:
    1164          42 :                 pwd_pos = PASSWORD_BUFFER_LEN - in_password->length;
    1165          42 :                 random_pos = 0;
    1166          42 :                 break;
    1167             :         }
    1168          42 :         random_len = PASSWORD_BUFFER_LEN - in_password->length;
    1169             : 
    1170          42 :         memcpy(buffer + pwd_pos, in_password->data, in_password->length);
    1171          42 :         generate_random_buffer(buffer + random_pos, random_len);
    1172             : 
    1173          42 :         return true;
    1174             : }
    1175             : 
    1176          42 : bool set_pw_in_buffer(uint8_t buffer[516], const DATA_BLOB *password)
    1177             : {
    1178             :         bool ok;
    1179             : 
    1180          42 :         ok = create_pw_buffer_from_blob(buffer,
    1181             :                                         password,
    1182             :                                         ENCODE_ORDER_PASSWORD_LAST);
    1183          42 :         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          42 :         PUSH_LE_U32(buffer, PASSWORD_BUFFER_LEN, password->length);
    1192             : 
    1193          42 :         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        1934 : bool extract_pw_from_buffer(TALLOC_CTX *mem_ctx,
    1201             :                             uint8_t in_buffer[516], DATA_BLOB *new_pass)
    1202             : {
    1203        1934 :         int byte_len=0;
    1204             : 
    1205             :         /* The length of the new password is in the last 4 bytes of the data buffer. */
    1206             : 
    1207        1934 :         byte_len = IVAL(in_buffer, 512);
    1208             : 
    1209             : #ifdef DEBUG_PASSWORD
    1210        1934 :         dump_data(100, in_buffer, 516);
    1211             : #endif
    1212             : 
    1213             :         /* Password cannot be longer than the size of the password buffer */
    1214        1934 :         if ( (byte_len < 0) || (byte_len > 512)) {
    1215         452 :                 return false;
    1216             :         }
    1217             : 
    1218        1482 :         *new_pass = data_blob_talloc(mem_ctx, &in_buffer[512 - byte_len], byte_len);
    1219             : 
    1220        1482 :         if (!new_pass->data) {
    1221           0 :                 return false;
    1222             :         }
    1223        1482 :         talloc_keep_secret(new_pass->data);
    1224             : 
    1225        1482 :         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           0 : 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           0 :         struct wkssvc_PasswordBuffer *pwd_buf = NULL;
    1242           0 :         uint8_t _confounder[8] = {0};
    1243           0 :         DATA_BLOB confounder = data_blob_const(_confounder, 8);
    1244           0 :         uint8_t pwbuf[516] = {0};
    1245           0 :         DATA_BLOB encrypt_pwbuf = data_blob_const(pwbuf, 516);
    1246             :         int rc;
    1247             : 
    1248           0 :         pwd_buf = talloc_zero(mem_ctx, struct wkssvc_PasswordBuffer);
    1249           0 :         if (pwd_buf == NULL) {
    1250           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1251             :         }
    1252             : 
    1253           0 :         encode_pw_buffer(pwbuf, pwd, STR_UNICODE);
    1254             : 
    1255           0 :         generate_random_buffer(_confounder, sizeof(_confounder));
    1256             : 
    1257           0 :         rc = samba_gnutls_arcfour_confounded_md5(session_key,
    1258             :                                                  &confounder,
    1259             :                                                  &encrypt_pwbuf,
    1260             :                                                  SAMBA_GNUTLS_ENCRYPT);
    1261           0 :         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           0 :         memcpy(&pwd_buf->data[0], confounder.data, confounder.length);
    1268           0 :         ZERO_ARRAY(_confounder);
    1269           0 :         memcpy(&pwd_buf->data[8], encrypt_pwbuf.data, encrypt_pwbuf.length);
    1270           0 :         ZERO_ARRAY(pwbuf);
    1271             : 
    1272           0 :         *out_pwd_buf = pwd_buf;
    1273             : 
    1274           0 :         return WERR_OK;
    1275             : }
    1276             : 
    1277           0 : 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           0 :         uint8_t _confounder[8] = { 0 };
    1283           0 :         DATA_BLOB confounder = data_blob_const(_confounder, 8);
    1284           0 :         uint8_t pwbuf[516] = {0};
    1285           0 :         DATA_BLOB decrypt_pwbuf = data_blob_const(pwbuf, 516);
    1286             :         bool ok;
    1287             :         int rc;
    1288             : 
    1289           0 :         if (pwd_buf == NULL) {
    1290           0 :                 return WERR_INVALID_PASSWORD;
    1291             :         }
    1292             : 
    1293           0 :         *pwd = NULL;
    1294             : 
    1295           0 :         if (session_key->length != 16) {
    1296           0 :                 DEBUG(10,("invalid session key\n"));
    1297           0 :                 return WERR_INVALID_PASSWORD;
    1298             :         }
    1299             : 
    1300           0 :         confounder = data_blob_const(&pwd_buf->data[0], 8);
    1301           0 :         memcpy(&pwbuf, &pwd_buf->data[8], 516);
    1302             : 
    1303           0 :         rc = samba_gnutls_arcfour_confounded_md5(session_key,
    1304             :                                                  &confounder,
    1305             :                                                  &decrypt_pwbuf,
    1306             :                                                  SAMBA_GNUTLS_ENCRYPT);
    1307           0 :         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           0 :         ok = decode_pw_buffer(mem_ctx,
    1314             :                               decrypt_pwbuf.data,
    1315             :                               pwd,
    1316             :                               &decrypt_pwbuf.length,
    1317             :                               CH_UTF16);
    1318           0 :         ZERO_ARRAY(pwbuf);
    1319             : 
    1320           0 :         if (!ok) {
    1321           0 :                 return WERR_INVALID_PASSWORD;
    1322             :         }
    1323             : 
    1324           0 :         return WERR_OK;
    1325             : }

Generated by: LCOV version 1.13