LCOV - code coverage report
Current view: top level - src/tds - challenge.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 263 328 80.2 %
Date: 2025-12-05 20:38:13 Functions: 15 17 88.2 %

          Line data    Source code
       1             : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2             :  * Copyright (C) 1998-1999  Brian Bruns
       3             :  * Copyright (C) 2005-2015  Frediano Ziglio
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or
       6             :  * modify it under the terms of the GNU Library General Public
       7             :  * License as published by the Free Software Foundation; either
       8             :  * version 2 of the License, or (at your option) any later version.
       9             :  *
      10             :  * This library is distributed in the hope that it will be useful,
      11             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :  * Library General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU Library General Public
      16             :  * License along with this library; if not, write to the
      17             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      18             :  * Boston, MA 02111-1307, USA.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : 
      23             : #if HAVE_STDLIB_H
      24             : #include <stdlib.h>
      25             : #endif /* HAVE_STDLIB_H */
      26             : 
      27             : #if HAVE_STDDEF_H
      28             : #include <stddef.h>
      29             : #endif /* HAVE_STDDEF_H */
      30             : 
      31             : #include <ctype.h>
      32             : 
      33             : #if HAVE_STRING_H
      34             : #include <string.h>
      35             : #endif /* HAVE_STRING_H */
      36             : 
      37             : #include <freetds/time.h>
      38             : #include <freetds/tds.h>
      39             : #include <freetds/bytes.h>
      40             : #include <freetds/utils/string.h>
      41             : #include <freetds/iconv.h>
      42             : #include <freetds/utils.h>
      43             : #include <freetds/utils/md4.h>
      44             : #include <freetds/utils/md5.h>
      45             : #include <freetds/utils/hmac_md5.h>
      46             : #include <freetds/utils/des.h>
      47             : #include <freetds/replacements.h>
      48             : #include <freetds/tls.h>
      49             : 
      50             : /**
      51             :  * \ingroup libtds
      52             :  * \defgroup auth Authentication
      53             :  * Functions for handling authentication.
      54             :  */
      55             : 
      56             : /**
      57             :  * \addtogroup auth
      58             :  * @{ 
      59             :  */
      60             : 
      61             : /*
      62             :  * The following code is based on some psuedo-C code from ronald@innovation.ch
      63             :  */
      64             : 
      65             : typedef struct tds_answer
      66             : {
      67             :         unsigned char lm_resp[24];
      68             :         unsigned char nt_resp[24];
      69             : } TDSANSWER;
      70             : 
      71             : 
      72             : typedef struct
      73             : {
      74             :         uint8_t  response_type;
      75             :         uint8_t  max_response_type;
      76             :         uint16_t reserved1;
      77             :         uint32_t reserved2;
      78             :         uint64_t timestamp;
      79             :         uint8_t  challenge[8];
      80             :         uint32_t reserved3;
      81             :         /* target info block - variable length */
      82             :         uint8_t  target_info[4];
      83             : } names_blob_prefix_t;
      84             : 
      85             : static TDSRET
      86             : tds_answer_challenge(TDSSOCKET * tds,
      87             :                      TDSLOGIN * login,
      88             :                      const unsigned char *challenge,
      89             :                      uint32_t * flags,
      90             :                      const unsigned char *names_blob, int names_blob_len, TDSANSWER * answer, unsigned char **ntlm_v2_response);
      91             : static void tds_encrypt_answer(const unsigned char *hash, const unsigned char *challenge, unsigned char *answer);
      92             : static void tds_convert_key(const unsigned char *key_56, DES_KEY * ks);
      93             : 
      94             : static void
      95         720 : convert_to_upper(char *buf, size_t len)
      96             : {
      97             :         size_t i;
      98             : 
      99       10080 :         for (i = 0; i < len; i++)
     100        9360 :                 buf[i] = toupper((unsigned char) buf[i]);
     101         720 : }
     102             : 
     103             : static size_t
     104        3600 : convert_to_usc2le_string(TDSSOCKET * tds, const char *s, size_t len, char *out)
     105             : {
     106             :         const char *ib;
     107             :         char *ob;
     108             :         size_t il, ol;
     109             : 
     110        3600 :         TDSICONV * char_conv = tds->conn->char_convs[client2ucs2];
     111             : 
     112             :         /* char_conv is only mostly const */
     113        3600 :         TDS_ERRNO_MESSAGE_FLAGS *suppress = (TDS_ERRNO_MESSAGE_FLAGS *) & char_conv->suppress;
     114             : 
     115        3600 :         if (char_conv->flags == TDS_ENCODING_MEMCPY) {
     116           0 :                 memcpy(out, s, len);
     117           0 :                 return len;
     118             :         }
     119             : 
     120             :         /* convert */
     121        3600 :         ib = s;
     122        3600 :         il = len;
     123        3600 :         ob = out;
     124        3600 :         ol = len * 2;
     125        3600 :         memset(suppress, 0, sizeof(char_conv->suppress));
     126        3600 :         if (tds_iconv(tds, char_conv, to_server, &ib, &il, &ob, &ol) == (size_t) - 1)
     127             :                 return (size_t) -1;
     128             : 
     129        3600 :         return ob - out;
     130             : }
     131             : 
     132             : static TDSRET
     133         720 : make_ntlm_hash(TDSSOCKET * tds, const char *passwd, unsigned char ntlm_hash[16])
     134             : {
     135             :         MD4_CTX context;
     136         720 :         size_t passwd_len = 0;
     137             :         char passwd_usc2le[256];
     138         720 :         size_t passwd_usc2le_len = 0;
     139             : 
     140         720 :         passwd_len = strlen(passwd);
     141             : 
     142         720 :         if (passwd_len > 128)
     143           0 :                 passwd_len = 128;
     144             : 
     145         720 :         passwd_usc2le_len = convert_to_usc2le_string(tds, passwd, passwd_len, passwd_usc2le);
     146         720 :         if (passwd_usc2le_len == (size_t) -1) {
     147             :                 memset((char *) passwd_usc2le, 0, sizeof(passwd_usc2le));
     148             :                 return TDS_FAIL;
     149             :         }
     150             : 
     151             :         /* compute NTLM hash */
     152         720 :         MD4Init(&context);
     153         720 :         MD4Update(&context, (unsigned char *) passwd_usc2le, passwd_usc2le_len);
     154         720 :         MD4Final(&context, ntlm_hash);
     155             : 
     156             :         /* with security is best be pedantic */
     157             :         memset((char *) passwd_usc2le, 0, passwd_usc2le_len);
     158             :         memset(&context, 0, sizeof(context));
     159         720 :         return TDS_SUCCESS;
     160             : }
     161             : 
     162             : 
     163             : static TDSRET
     164         720 : make_ntlm_v2_hash(TDSSOCKET * tds, const char *passwd, unsigned char ntlm_v2_hash[16])
     165             : {
     166             :         const char *user_name, *domain;
     167         720 :         size_t domain_len, user_name_len, len, buf_usc2le_len = 0;
     168             :         const char *p;
     169             : 
     170             :         unsigned char ntlm_hash[16];
     171             :         char buf[128];
     172             :         char buf_usc2le[512];
     173             :         TDSRET res;
     174             : 
     175        1440 :         user_name = tds_dstr_cstr(&tds->login->user_name);
     176             : 
     177             :         /* parse domain\username */
     178         720 :         p = strchr(user_name, '\\');
     179             : 
     180         720 :         domain = user_name;
     181         720 :         domain_len = p - user_name;
     182             : 
     183         720 :         user_name = p + 1;
     184         720 :         user_name_len = strlen(user_name);
     185             : 
     186         720 :         if (user_name_len > 128)
     187           0 :                 user_name_len = 128;
     188         720 :         memcpy(buf, user_name, user_name_len);
     189         720 :         convert_to_upper(buf, user_name_len);
     190             : 
     191         720 :         len = convert_to_usc2le_string(tds, buf, user_name_len, buf_usc2le);
     192         720 :         if (len == (size_t) -1)
     193             :                 return TDS_FAIL;
     194         720 :         buf_usc2le_len = len;
     195             : 
     196         720 :         if (domain_len > 128)
     197           0 :                 domain_len = 128;
     198             :         /* Target is supposed to be case-sensitive */
     199             : 
     200         720 :         len = convert_to_usc2le_string(tds, domain, domain_len, buf_usc2le + len);
     201         720 :         if (len == (size_t) -1)
     202             :                 return TDS_FAIL;
     203         720 :         buf_usc2le_len += len;
     204             : 
     205             : 
     206         720 :         res = make_ntlm_hash(tds, passwd, ntlm_hash);
     207         720 :         hmac_md5(ntlm_hash, (const unsigned char *) buf_usc2le, buf_usc2le_len, ntlm_v2_hash);
     208             : 
     209             :         /* with security is best be pedantic */
     210             :         memset(&ntlm_hash, 0, sizeof(ntlm_hash));
     211             :         memset(buf, 0, sizeof(buf));
     212             :         memset((char *) buf_usc2le, 0, buf_usc2le_len);
     213         720 :         return res;
     214             : }
     215             : 
     216             : 
     217             : /*
     218             :  * hash - The NTLMv2 Hash.
     219             :  * client_data - The client data (blob or client nonce).
     220             :  * challenge - The server challenge from the Type 2 message.
     221             :  */
     222             : static unsigned char *
     223        1440 : make_lm_v2_response(const unsigned char ntlm_v2_hash[16],
     224             :                     const unsigned char *client_data, int client_data_len, const unsigned char challenge[8])
     225             : {
     226        1440 :         int mac_len = 16 + client_data_len;
     227             :         unsigned char *mac;
     228             : 
     229        1440 :         mac = tds_new(unsigned char, mac_len);
     230        1440 :         if (!mac)
     231             :                 return NULL;
     232             : 
     233        1440 :         memcpy(mac + 8, challenge, 8);
     234        1440 :         memcpy(mac + 16, client_data, client_data_len);
     235        1440 :         hmac_md5(ntlm_v2_hash, mac + 8, client_data_len + 8, mac);
     236             : 
     237        1440 :         return mac;
     238             : }
     239             : 
     240             : static TDSRET
     241         720 : tds_answer_challenge_ntlmv2(TDSSOCKET * tds,
     242             :                      TDSLOGIN * login,
     243             :                      const unsigned char *challenge,
     244             :                      uint32_t * flags,
     245             :                      const unsigned char *names_blob, int names_blob_len, TDSANSWER * answer, unsigned char **ntlm_v2_response)
     246             : {
     247             :         TDSRET res;
     248        1440 :         const char *passwd = tds_dstr_cstr(&login->password);
     249             : 
     250             :         /* NTLMv2 */
     251             :         unsigned char *lm_v2_response;
     252             :         unsigned char ntlm_v2_hash[16];
     253             :         const names_blob_prefix_t *names_blob_prefix;
     254             : 
     255         720 :         if (!names_blob)
     256             :                 return TDS_FAIL;
     257             : 
     258         720 :         res = make_ntlm_v2_hash(tds, passwd, ntlm_v2_hash);
     259         720 :         if (TDS_FAILED(res))
     260             :                 return res;
     261             : 
     262             :         /* LMv2 response */
     263             :         /* Take client's challenge from names_blob */
     264         720 :         names_blob_prefix = (const names_blob_prefix_t *) names_blob;
     265         720 :         lm_v2_response = make_lm_v2_response(ntlm_v2_hash, names_blob_prefix->challenge, 8, challenge);
     266         720 :         if (!lm_v2_response)
     267             :                 return TDS_FAIL;
     268         720 :         memcpy(answer->lm_resp, lm_v2_response, 24);
     269         720 :         free(lm_v2_response);
     270             : 
     271             :         /* NTLMv2 response */
     272             :         /* Size of lm_v2_response is 16 + names_blob_len */
     273         720 :         *ntlm_v2_response = make_lm_v2_response(ntlm_v2_hash, names_blob, names_blob_len, challenge);
     274         720 :         if (!*ntlm_v2_response)
     275             :                 return TDS_FAIL;
     276             : 
     277             :         memset(ntlm_v2_hash, 0, sizeof(ntlm_v2_hash));
     278             : 
     279             :         /* local not supported */
     280         720 :         *flags &= ~0x4000;
     281         720 :         return TDS_SUCCESS;
     282             : }
     283             : 
     284             : /**
     285             :  * Crypt a given password using schema required for NTLMv1 or NTLM2 authentication
     286             :  * @param passwd clear text domain password
     287             :  * @param challenge challenge data given by server
     288             :  * @param flags NTLM flags from server side
     289             :  * @param answer buffer where to store crypted password
     290             :  */
     291             : static TDSRET
     292         720 : tds_answer_challenge(TDSSOCKET * tds,
     293             :                      TDSLOGIN * login,
     294             :                      const unsigned char *challenge,
     295             :                      uint32_t * flags,
     296             :                      const unsigned char *names_blob, int names_blob_len, TDSANSWER * answer, unsigned char **ntlm_v2_response)
     297             : {
     298             : #define MAX_PW_SZ 14
     299        1440 :         const char *passwd = tds_dstr_cstr(&login->password);
     300             :         DES_KEY ks;
     301             :         unsigned char hash[24], ntlm2_challenge[16];
     302             :         TDSRET res;
     303             : 
     304         720 :         memset(answer, 0, sizeof(TDSANSWER));
     305             : 
     306         720 :         if (login->use_ntlmv2) {
     307         720 :                 return tds_answer_challenge_ntlmv2(tds, login, challenge, flags,
     308             :                                                    names_blob, names_blob_len, answer, ntlm_v2_response);
     309           0 :         } else if ((*flags & 0x80000) != 0) {
     310             :                 /* NTLM2 */
     311             :                 MD5_CTX md5_ctx;
     312             : 
     313           0 :                 tds_random_buffer(hash, 8);
     314           0 :                 memset(hash + 8, 0, 16);
     315           0 :                 memcpy(answer->lm_resp, hash, 24);
     316             : 
     317           0 :                 MD5Init(&md5_ctx);
     318           0 :                 MD5Update(&md5_ctx, challenge, 8);
     319           0 :                 MD5Update(&md5_ctx, hash, 8);
     320           0 :                 MD5Final(&md5_ctx, ntlm2_challenge);
     321           0 :                 challenge = ntlm2_challenge;
     322             :                 memset(&md5_ctx, 0, sizeof(md5_ctx));
     323           0 :         } else if (login->use_lanman) {
     324             :                 /* LM */
     325             :                 size_t len, i;
     326             :                 unsigned char passwd_buf[MAX_PW_SZ];
     327             :                 static const des_cblock magic = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
     328             : 
     329             :                 /* convert password to upper and pad to 14 chars */
     330           0 :                 memset(passwd_buf, 0, MAX_PW_SZ);
     331           0 :                 len = strlen(passwd);
     332           0 :                 if (len > MAX_PW_SZ)
     333           0 :                         len = MAX_PW_SZ;
     334           0 :                 for (i = 0; i < len; i++)
     335           0 :                         passwd_buf[i] = toupper((unsigned char) passwd[i]);
     336             : 
     337             :                 /* hash the first 7 characters */
     338           0 :                 tds_convert_key(passwd_buf, &ks);
     339           0 :                 tds_des_ecb_encrypt(&magic, sizeof(magic), &ks, (hash + 0));
     340             : 
     341             :                 /* hash the second 7 characters */
     342           0 :                 tds_convert_key(passwd_buf + 7, &ks);
     343           0 :                 tds_des_ecb_encrypt(&magic, sizeof(magic), &ks, (hash + 8));
     344             : 
     345           0 :                 memset(hash + 16, 0, 5);
     346             : 
     347           0 :                 tds_encrypt_answer(hash, challenge, answer->lm_resp);
     348             :                 memset(passwd_buf, 0, sizeof(passwd_buf));
     349             :         } else {
     350           0 :                 memset(answer->lm_resp, 0, sizeof(answer->lm_resp));
     351             :         }
     352           0 :         *flags = 0x8201;
     353             : 
     354             :         /* NTLM/NTLM2 response */
     355           0 :         res = make_ntlm_hash(tds, passwd, hash);
     356           0 :         memset(hash + 16, 0, 5);
     357             : 
     358           0 :         tds_encrypt_answer(hash, challenge, answer->nt_resp);
     359             : 
     360             :         /* with security is best be pedantic */
     361             :         memset(&ks, 0, sizeof(ks));
     362             :         memset(hash, 0, sizeof(hash));
     363             :         memset(ntlm2_challenge, 0, sizeof(ntlm2_challenge));
     364           0 :         return res;
     365             : }
     366             : 
     367             : 
     368             : /*
     369             : * takes a 21 byte array and treats it as 3 56-bit DES keys. The
     370             : * 8 byte plaintext is encrypted with each key and the resulting 24
     371             : * bytes are stored in the results array.
     372             : */
     373             : static void
     374           0 : tds_encrypt_answer(const unsigned char *hash, const unsigned char *challenge, unsigned char *answer)
     375             : {
     376             :         DES_KEY ks;
     377             : 
     378           0 :         tds_convert_key(hash, &ks);
     379           0 :         tds_des_ecb_encrypt(challenge, 8, &ks, answer);
     380             : 
     381           0 :         tds_convert_key(&hash[7], &ks);
     382           0 :         tds_des_ecb_encrypt(challenge, 8, &ks, &answer[8]);
     383             : 
     384           0 :         tds_convert_key(&hash[14], &ks);
     385           0 :         tds_des_ecb_encrypt(challenge, 8, &ks, &answer[16]);
     386             : 
     387             :         memset(&ks, 0, sizeof(ks));
     388           0 : }
     389             : 
     390             : 
     391             : /*
     392             : * turns a 56 bit key into the 64 bit, odd parity key and sets the key.
     393             : * The key schedule ks is also set.
     394             : */
     395             : static void
     396           0 : tds_convert_key(const unsigned char *key_56, DES_KEY * ks)
     397             : {
     398             :         des_cblock key;
     399             : 
     400           0 :         key[0] = key_56[0];
     401           0 :         key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
     402           0 :         key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
     403           0 :         key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
     404           0 :         key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
     405           0 :         key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
     406           0 :         key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
     407           0 :         key[7] = (key_56[6] << 1) & 0xFF;
     408             : 
     409           0 :         tds_des_set_odd_parity(key);
     410           0 :         tds_des_set_key(ks, key);
     411             : 
     412             :         memset(&key, 0, sizeof(key));
     413           0 : }
     414             : 
     415             : static TDSRET
     416         720 : tds7_send_auth(TDSSOCKET * tds,
     417             :                const unsigned char *challenge, uint32_t flags, const unsigned char *names_blob, int names_blob_len)
     418             : {
     419             :         size_t current_pos;
     420             :         TDSANSWER answer;
     421             : 
     422             :         /* FIXME: stuff duplicate in tds7_send_login */
     423             :         const char *domain;
     424             :         const char *user_name;
     425             :         const char *host_name;
     426             :         const char *p;
     427             :         char *convert_buffer;
     428             :         size_t user_name_len, host_name_len, domain_len;
     429             :         TDSRET rc;
     430             : 
     431         720 :         unsigned char *ntlm_v2_response = NULL;
     432         720 :         unsigned int ntlm_response_len = 24;
     433         720 :         const unsigned int lm_response_len = 24;
     434             : 
     435         720 :         TDSLOGIN *login = tds->login;
     436             : 
     437             :         /* check connection */
     438         720 :         if (!login)
     439             :                 return TDS_FAIL;
     440             : 
     441             :         /* parse a bit of config */
     442        1440 :         user_name = tds_dstr_cstr(&login->user_name);
     443        1440 :         user_name_len = tds_dstr_len(&login->user_name);
     444        1440 :         host_name = tds_dstr_cstr(&login->client_host_name);
     445        1440 :         host_name_len = tds_dstr_len(&login->client_host_name);
     446             : 
     447             :         /* convert strings */
     448         720 :         convert_buffer = tds_new(char, (user_name_len + host_name_len) * 2);
     449         720 :         if (!convert_buffer)
     450             :                 return TDS_FAIL;
     451             : 
     452         720 :         user_name_len = convert_to_usc2le_string(tds, user_name, user_name_len, convert_buffer);
     453         720 :         user_name = convert_buffer;
     454         720 :         if (user_name_len != (size_t) -1) {
     455         720 :                 host_name_len = convert_to_usc2le_string(tds, host_name, host_name_len, convert_buffer + user_name_len);
     456         720 :                 host_name = convert_buffer + user_name_len;
     457             :         }
     458         720 :         if (user_name_len == (size_t) -1 || host_name_len == (size_t) -1) {
     459           0 :                 free(convert_buffer);
     460           0 :                 return TDS_FAIL;
     461             :         }
     462             : 
     463             :         /* parse domain\username */
     464             :         p = user_name;
     465             :         for (;;) {
     466       10800 :                 if (p >= user_name + user_name_len) {
     467           0 :                         free(convert_buffer);
     468           0 :                         return TDS_FAIL;
     469             :                 }
     470        5760 :                 if (p[0] == '\\' && p[1] == 0)
     471             :                         break;
     472        5040 :                 p += 2;
     473             :         }
     474             : 
     475         720 :         domain = user_name;
     476         720 :         domain_len = p - user_name;
     477             : 
     478         720 :         user_name = p + 2;
     479         720 :         user_name_len = domain + user_name_len - user_name;
     480             : 
     481         720 :         rc = tds_answer_challenge(tds, login, challenge, &flags, names_blob, names_blob_len, &answer, &ntlm_v2_response);
     482         720 :         if (TDS_FAILED(rc)) {
     483           0 :                 free(convert_buffer);
     484           0 :                 return rc;
     485             :         }
     486             : 
     487         720 :         ntlm_response_len = ntlm_v2_response ? 16 + names_blob_len : 24;
     488             :         /* ntlm_response_len = 0; */
     489             : 
     490         720 :         tds->out_flag = TDS7_AUTH;
     491         720 :         tds_put_n(tds, "NTLMSSP", 8);
     492         720 :         tds_put_int(tds, 3);    /* sequence 3 */
     493             : 
     494         720 :         current_pos = 64u + domain_len + user_name_len + host_name_len;
     495             : 
     496             :         /* LM/LMv2 Response */
     497         720 :         tds_put_smallint(tds, lm_response_len); /* lan man resp length */
     498         720 :         tds_put_smallint(tds, lm_response_len); /* lan man resp length */
     499         720 :         TDS_PUT_INT(tds, current_pos);  /* resp offset */
     500         720 :         current_pos += lm_response_len;
     501             : 
     502             :         /* NTLM/NTLMv2 Response */
     503         720 :         tds_put_smallint(tds, ntlm_response_len);       /* nt resp length */
     504         720 :         tds_put_smallint(tds, ntlm_response_len);       /* nt resp length */
     505         720 :         TDS_PUT_INT(tds, current_pos);  /* nt resp offset */
     506             : 
     507         720 :         current_pos = 64;
     508             : 
     509             :         /* Target Name - domain or server name */
     510         720 :         TDS_PUT_SMALLINT(tds, domain_len);
     511         720 :         TDS_PUT_SMALLINT(tds, domain_len);
     512         720 :         TDS_PUT_INT(tds, current_pos);
     513         720 :         current_pos += domain_len;
     514             : 
     515             :         /* username */
     516         720 :         TDS_PUT_SMALLINT(tds, user_name_len);
     517         720 :         TDS_PUT_SMALLINT(tds, user_name_len);
     518         720 :         TDS_PUT_INT(tds, current_pos);
     519         720 :         current_pos += user_name_len;
     520             : 
     521             :         /* Workstation Name */
     522         720 :         TDS_PUT_SMALLINT(tds, host_name_len);
     523         720 :         TDS_PUT_SMALLINT(tds, host_name_len);
     524         720 :         TDS_PUT_INT(tds, current_pos);
     525         720 :         current_pos += host_name_len;
     526             : 
     527             :         /* Session Key (optional) */
     528         720 :         tds_put_smallint(tds, 0);
     529         720 :         tds_put_smallint(tds, 0);
     530         720 :         TDS_PUT_INT(tds, current_pos + lm_response_len + ntlm_response_len);
     531             : 
     532             :         /* flags */
     533             :         /* "challenge" is 8 bytes long */
     534             :         /* tds_answer_challenge(tds_dstr_cstr(&login->password), challenge, &flags, &answer); */
     535         720 :         tds_put_int(tds, flags);
     536             : 
     537             :         /* OS Version Structure (Optional) */
     538             : 
     539             :         /* Data itself */
     540         720 :         tds_put_n(tds, domain, domain_len);
     541         720 :         tds_put_n(tds, user_name, user_name_len);
     542         720 :         tds_put_n(tds, host_name, host_name_len);
     543             : 
     544             :         /* data block */
     545         720 :         tds_put_n(tds, answer.lm_resp, lm_response_len);
     546             : 
     547         720 :         if (ntlm_v2_response == NULL) {
     548             :                 /* NTLMv1 */
     549           0 :                 tds_put_n(tds, answer.nt_resp, ntlm_response_len);
     550             :         } else {
     551             :                 /* NTLMv2 */
     552         720 :                 tds_put_n(tds, ntlm_v2_response, ntlm_response_len);
     553         720 :                 memset(ntlm_v2_response, 0, ntlm_response_len);
     554         720 :                 free(ntlm_v2_response);
     555             :         }
     556             : 
     557             :         /* for security reason clear structure */
     558         720 :         memset(&answer, 0, sizeof(TDSANSWER));
     559             : 
     560         720 :         free(convert_buffer);
     561         720 :         return tds_flush_packet(tds);
     562             : }
     563             : 
     564             : #define AV_PAIR_CBT_BYTES 20
     565             : 
     566             : typedef struct tds_ntlm_auth
     567             : {
     568             :         TDSAUTHENTICATION tds_auth;
     569             :         uint8_t cbt[16];
     570             :         bool has_cbt;
     571             : } TDSNTLMAUTH;
     572             : 
     573             : static TDSRET
     574         720 : tds_ntlm_free(TDSCONNECTION * conn TDS_UNUSED, TDSAUTHENTICATION * tds_auth)
     575             : {
     576         720 :         TDSNTLMAUTH *auth = (TDSNTLMAUTH *) tds_auth;
     577             : 
     578         720 :         free(auth->tds_auth.packet);
     579         720 :         free(auth);
     580             : 
     581         720 :         return TDS_SUCCESS;
     582             : }
     583             : 
     584             : static const unsigned char ntlm_id[] = "NTLMSSP";
     585             : 
     586             : /**
     587             :  * put a 8 byte filetime from a time_t
     588             :  * This takes GMT as input
     589             :  */
     590             : static void
     591             : unix_to_nt_time(uint64_t * nt, struct timeval *tv)
     592             : {
     593             :         /* C time start on 1970, nt time on 1600 */
     594             : #define TIME_FIXUP_CONSTANT (((uint64_t) 134774U) * 86400U)
     595             : 
     596             :         uint64_t t2;
     597             : 
     598         720 :         t2 = tv->tv_sec;
     599         720 :         t2 += TIME_FIXUP_CONSTANT;
     600         720 :         t2 *= 1000u * 1000u * 10u;
     601         720 :         t2 += tv->tv_usec * 10u;
     602             : 
     603         720 :         *nt = t2;
     604             : }
     605             : 
     606             : static void
     607         730 : tds_calc_cbt_from_tls_unique(const void *tls_unique_buf, size_t tls_unique_len, unsigned char cbt[16])
     608             : {
     609             :         MD5_CTX md5_ctx;
     610             :         unsigned char channel_binding_struct[20 + 11];
     611             :         size_t struct_len;
     612             :         size_t application_data_raw_len;
     613             : 
     614             :         /* Build channel binding structure */
     615             :         /* initiator_address: 8 bytes of zeros */
     616             :         /* acceptor_address: 8 bytes of zeros */
     617             :         /* application_data: 4 bytes length (little endian) + "tls-unique:" + tls_unique */
     618         730 :         application_data_raw_len = 11 + tls_unique_len;
     619         730 :         struct_len = 8 + 8 + 4 + 11;
     620             : 
     621         730 :         memset(channel_binding_struct, 0, sizeof(channel_binding_struct));
     622             : 
     623             :         /* initiator_address: 8 bytes of zeros (already zeroed by memset) */
     624             :         /* acceptor_address: 8 bytes of zeros (already zeroed by memset) */
     625             :         /* Offset is 16 at this point */
     626             : 
     627             :         /* Build application_data: length + "tls-unique:" + tls_unique */
     628         730 :         TDS_PUT_UA4LE(channel_binding_struct + 16, application_data_raw_len);   /* length (4 bytes) */
     629         730 :         memcpy(channel_binding_struct + 20, "tls-unique:", 11);       /* "tls-unique:" prefix */
     630             : 
     631             :         /* Calculate MD5 hash */
     632         730 :         MD5Init(&md5_ctx);
     633         730 :         MD5Update(&md5_ctx, channel_binding_struct, struct_len);
     634         730 :         MD5Update(&md5_ctx, tls_unique_buf, tls_unique_len);        /* tls_unique data */
     635         730 :         MD5Final(&md5_ctx, cbt);
     636         730 : }
     637             : 
     638             : static void
     639         720 : get_cbt(TDSSOCKET *tds, TDSNTLMAUTH *auth)
     640             : {
     641             :         unsigned char tls_unique_buf[256];
     642             :         size_t tls_unique_len;
     643             : 
     644         720 :         tls_unique_len = tds_ssl_get_cb(tds->conn, tls_unique_buf, sizeof(tls_unique_buf));
     645         720 :         if (tls_unique_len == 0)
     646           0 :                 return;
     647             : 
     648         720 :         tds_calc_cbt_from_tls_unique(tls_unique_buf, tls_unique_len, auth->cbt);
     649         720 :         auth->has_cbt = true;
     650         720 :         tdsdump_dump_buf(TDS_DBG_INFO1, "Channel Binding Token", auth->cbt, 16);
     651             : }
     652             : 
     653             : /**
     654             :  * Add channel binding token (CBT) AV_PAIR to target_info in names_blob
     655             :  * @param tds TDSSOCKET structure
     656             :  * @param names_blob pointer to names_blob buffer
     657             :  * @param names_blob_len pointer to current length (will be updated)
     658             :  * @return TDS_SUCCESS or TDS_FAIL
     659             :  */
     660             : static void
     661         720 : add_cbt_data(TDSNTLMAUTH *auth, unsigned char *names_blob, int *names_blob_len, int target_info_len)
     662             : {
     663             :         int new_blob_len;
     664             :         int target_info_offset;
     665             :         unsigned char *cbt_av_pair;
     666             : 
     667             :         /* No CBT, skip channel binding */
     668         720 :         if (!auth->has_cbt)
     669             :                 return;
     670             : 
     671         720 :         target_info_offset = TDS_OFFSET(names_blob_prefix_t, target_info);
     672             : 
     673             :         /* Add CBT AV_PAIR (4 bytes header + 16 bytes CBT) */
     674         720 :         new_blob_len = *names_blob_len + 4 + 16;        /* +20 for CBT AV_PAIR */
     675             : 
     676             :         /* Insert CBT AV_PAIR */
     677             :         /* The -4 is to override the old terminator */
     678         720 :         cbt_av_pair = names_blob + target_info_offset + target_info_len - 4;
     679             : 
     680         720 :         TDS_PUT_UA2LE(cbt_av_pair, 0x000A);     /* AvId = 0xA (little endian) */
     681         720 :         TDS_PUT_UA2LE(cbt_av_pair + 2, 16);     /* AvLen = 16 (little endian) */
     682         720 :         memcpy(cbt_av_pair + 4, auth->cbt, 16);      /* CBT (16 bytes) */
     683         720 :         memset(cbt_av_pair + 20, 0, 4); /* Terminator */
     684             : 
     685         720 :         tdsdump_dump_buf(TDS_DBG_INFO1, "New names_blob\n", names_blob, new_blob_len);
     686             :         /* Update names_blob_len */
     687         720 :         *names_blob_len = new_blob_len;
     688             : }
     689             : 
     690             : static void
     691         720 : fill_names_blob_prefix(names_blob_prefix_t * prefix)
     692             : {
     693             :         struct timeval tv;
     694         720 :         uint64_t nttime = 0;
     695             : 
     696         720 :         gettimeofday(&tv, NULL);
     697         720 :         unix_to_nt_time(&nttime, &tv);
     698             : 
     699         720 :         prefix->response_type = 0x01;
     700         720 :         prefix->max_response_type = 0x01;
     701         720 :         prefix->reserved1 = 0x0000;
     702         720 :         prefix->reserved2 = 0x00000000;
     703             : #ifdef WORDS_BIGENDIAN
     704             :         tds_swap_bytes(&nttime, 8);
     705             : #endif
     706         720 :         prefix->timestamp = nttime;
     707         720 :         tds_random_buffer(prefix->challenge, sizeof(prefix->challenge));
     708             : 
     709         720 :         prefix->reserved3 = 0x00000000;
     710         720 : }
     711             : 
     712             : static TDSRET
     713         720 : tds_ntlm_handle_next(TDSSOCKET *tds, TDSAUTHENTICATION *tds_auth TDS_UNUSED, size_t len)
     714             : {
     715         720 :         TDSNTLMAUTH *auth = (TDSNTLMAUTH *) tds_auth;
     716             : 
     717         720 :         const int length = (int)len;
     718             :         unsigned char nonce[8];
     719             :         uint32_t flags;
     720             :         int where;
     721             : 
     722             :         int data_block_offset;
     723             : 
     724         720 :         int names_blob_len = 0;
     725         720 :         unsigned char *names_blob = NULL;
     726             : 
     727             :         TDSRET rc;
     728             : 
     729             :         /* at least 32 bytes (till context) */
     730         720 :         if (len < 32)
     731             :                 return TDS_FAIL;
     732             : 
     733         720 :         tds_get_n(tds, nonce, 8);       /* NTLMSSP\0 */
     734         720 :         if (memcmp(nonce, ntlm_id, 8) != 0)
     735             :                 return TDS_FAIL;
     736         720 :         if (tds_get_int(tds) != 2)      /* sequence -> 2 */
     737             :                 return TDS_FAIL;
     738         720 :         tds_get_smallint(tds);  /* domain len */
     739         720 :         tds_get_smallint(tds);  /* domain len */
     740         720 :         data_block_offset = tds_get_int(tds);   /* domain offset */
     741         720 :         flags = tds_get_int(tds);       /* flags */
     742         720 :         tds_get_n(tds, nonce, 8);
     743         720 :         tdsdump_dump_buf(TDS_DBG_INFO1, "TDS_AUTH_TOKEN nonce", nonce, 8);
     744         720 :         where = 32;
     745             : 
     746             :         /*data_block_offset == 32 */
     747             :         /* Version 1 -- The Context, Target Information, and OS Version structure are all omitted */
     748             : 
     749         720 :         if (data_block_offset >= 48 && where + 16 <= length) {
     750             :                 int target_info_len, target_info_offset;
     751             : 
     752             :                 /* Version 2 -- The Context and Target Information fields are present, but the OS Version structure is not. */
     753         720 :                 tds_get_n(tds, NULL, 8);        /* Context (two consecutive longs) */
     754             : 
     755         720 :                 target_info_len = tds_get_smallint(tds);        /* Target Information len */
     756         720 :                 target_info_len = tds_get_smallint(tds);        /* Target Information len */
     757         720 :                 target_info_offset = tds_get_int(tds);  /* Target Information offset */
     758             : 
     759         720 :                 where += 16;
     760             : 
     761         720 :                 if (data_block_offset >= 56 && where + 8 <= length) {
     762             :                         /* Version 3 -- The Context, Target Information, and OS Version structure are all present. */
     763         720 :                         tds_get_n(tds, NULL, 8);        /* OS Version Structure */
     764             : #if 0
     765             :                         /* if we have a version server handle NTLMv2 */
     766             :                         if (target_info_len > 0)
     767             :                                 flags &= ~0x80000;
     768             : #endif
     769         720 :                         where += 8;
     770             :                 }
     771             : 
     772             :                 /* read Target Info if possible */
     773         720 :                 if (target_info_len > 0 && target_info_offset >= where && target_info_offset + target_info_len <= length) {
     774             :                         uint32_t terminator;
     775             : 
     776         720 :                         tds_get_n(tds, NULL, target_info_offset - where);
     777         720 :                         where = target_info_offset;
     778             : 
     779             :                         /* target info must include terminator */
     780         720 :                         if (target_info_len < 4)
     781             :                                 return TDS_FAIL;
     782             : 
     783         720 :                         names_blob_len = TDS_OFFSET(names_blob_prefix_t, target_info) + target_info_len;
     784             : 
     785             :                         /* read Target Info */
     786         720 :                         names_blob = tds_new0(unsigned char, names_blob_len + AV_PAIR_CBT_BYTES);
     787         720 :                         if (!names_blob)
     788             :                                 return TDS_FAIL;
     789             : 
     790         720 :                         fill_names_blob_prefix((names_blob_prefix_t *) names_blob);
     791         720 :                         tds_get_n(tds, names_blob + TDS_OFFSET(names_blob_prefix_t, target_info), target_info_len);
     792         720 :                         terminator = TDS_GET_UA4(names_blob + TDS_OFFSET(names_blob_prefix_t, target_info) + target_info_len - 4);
     793         720 :                         if (terminator != 0) {
     794           0 :                                 free(names_blob);
     795           0 :                                 return TDS_FAIL;
     796             :                         }
     797         720 :                         where += target_info_len;
     798             : 
     799             :                         /* Add channel binding token (CBT) AV_PAIR to target_info in names_blob */
     800         720 :                         add_cbt_data(auth, names_blob, &names_blob_len, target_info_len);
     801             :                 }
     802             :         }
     803             :         /* discard anything left */
     804         720 :         tds_get_n(tds, NULL, length - where);
     805         720 :         tdsdump_log(TDS_DBG_INFO1, "Draining %d bytes\n", (int) (len - where));
     806             : 
     807         720 :         rc = tds7_send_auth(tds, nonce, flags, names_blob, names_blob_len);
     808             : 
     809         720 :         free(names_blob);
     810             : 
     811         720 :         return rc;
     812             : }
     813             : 
     814             : /**
     815             :  * Build a NTLMSPP packet to send to server
     816             :  * @param tds     A pointer to the TDSSOCKET structure managing a client/server operation.
     817             :  * @return authentication info
     818             :  */
     819             : TDSAUTHENTICATION * 
     820         720 : tds_ntlm_get_auth(TDSSOCKET * tds)
     821             : {
     822             :         const char *domain;
     823             :         const char *user_name;
     824             :         const char *p;
     825             :         uint8_t *packet;
     826             :         int host_name_len;
     827             :         int domain_len;
     828             :         int auth_len;
     829             :         struct tds_ntlm_auth *auth;
     830             : 
     831         720 :         if (!tds->login)
     832             :                 return NULL;
     833             : 
     834        1440 :         user_name = tds_dstr_cstr(&tds->login->user_name);
     835        1440 :         host_name_len = (int)tds_dstr_len(&tds->login->client_host_name);
     836             : 
     837             :         /* check override of domain */
     838         720 :         if ((p = strchr(user_name, '\\')) == NULL)
     839             :                 return NULL;
     840             : 
     841         720 :         domain = user_name;
     842         720 :         domain_len = (int)(p - user_name);
     843             : 
     844         720 :         auth = tds_new0(struct tds_ntlm_auth, 1);
     845             : 
     846         720 :         if (!auth)
     847             :                 return NULL;
     848             : 
     849         720 :         auth->tds_auth.free = tds_ntlm_free;
     850         720 :         auth->tds_auth.handle_next = tds_ntlm_handle_next;
     851             : 
     852         720 :         auth->tds_auth.packet_len = auth_len = 40 + host_name_len + domain_len;
     853         720 :         auth->tds_auth.packet = packet = tds_new(uint8_t, auth_len);
     854         720 :         if (!packet) {
     855           0 :                 free(auth);
     856           0 :                 return NULL;
     857             :         }
     858             : 
     859             :         /* built NTLMSSP authentication packet */
     860         720 :         memcpy(packet, ntlm_id, 8);
     861             :         /* sequence 1 client -> server */
     862         720 :         TDS_PUT_A4(packet + 8, TDS_HOST4LE(1));
     863             :         /* flags */
     864         720 :         TDS_PUT_A4(packet + 12, TDS_HOST4LE(0x08b201));
     865             : 
     866             :         /* domain info */
     867         720 :         TDS_PUT_A2LE(packet + 16, domain_len);
     868         720 :         TDS_PUT_A2LE(packet + 18, domain_len);
     869         720 :         TDS_PUT_A4LE(packet + 20, 40 + host_name_len);
     870             : 
     871             :         /* hostname info */
     872         720 :         TDS_PUT_A2LE(packet + 24, host_name_len);
     873         720 :         TDS_PUT_A2LE(packet + 26, host_name_len);
     874         720 :         TDS_PUT_A4  (packet + 28, TDS_HOST4LE(40));
     875             : 
     876             :         /*
     877             :          * here XP put version like 05 01 28 0a (5.1.2600),
     878             :          * similar to GetVersion result
     879             :          * and some unknown bytes like 00 00 00 0f
     880             :          */
     881         720 :         TDS_PUT_A4(packet + 32, TDS_HOST4LE(0x0a280105));
     882         720 :         TDS_PUT_A4(packet + 36, TDS_HOST4LE(0x0f000000));
     883             : 
     884             :         /* hostname and domain */
     885        1440 :         memcpy(packet + 40, tds_dstr_cstr(&tds->login->client_host_name), host_name_len);
     886         720 :         memcpy(packet + 40 + host_name_len, domain, domain_len);
     887             : 
     888         720 :         get_cbt(tds, auth);
     889             : 
     890         720 :         return (TDSAUTHENTICATION *) auth;
     891             : }
     892             : 
     893             : /** @} */
     894             : 

Generated by: LCOV version 1.13