LCOV - code coverage report
Current view: top level - src/tds - challenge.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 229 291 78.7 %
Date: 2024-04-18 21:21:48 Functions: 12 14 85.7 %

          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             : 
      49             : /**
      50             :  * \ingroup libtds
      51             :  * \defgroup auth Authentication
      52             :  * Functions for handling authentication.
      53             :  */
      54             : 
      55             : /**
      56             :  * \addtogroup auth
      57             :  * @{ 
      58             :  */
      59             : 
      60             : /*
      61             :  * The following code is based on some psuedo-C code from ronald@innovation.ch
      62             :  */
      63             : 
      64             : typedef struct tds_answer
      65             : {
      66             :         unsigned char lm_resp[24];
      67             :         unsigned char nt_resp[24];
      68             : } TDSANSWER;
      69             : 
      70             : 
      71             : typedef struct
      72             : {
      73             :         uint8_t  response_type;
      74             :         uint8_t  max_response_type;
      75             :         uint16_t reserved1;
      76             :         uint32_t reserved2;
      77             :         uint64_t timestamp;
      78             :         uint8_t  challenge[8];
      79             :         uint32_t unknown;
      80             :         /* target info block - variable length */
      81             :         uint8_t  target_info[4];
      82             : } names_blob_prefix_t;
      83             : 
      84             : static TDSRET
      85             : tds_answer_challenge(TDSSOCKET * tds,
      86             :                      TDSLOGIN * login,
      87             :                      const unsigned char *challenge,
      88             :                      uint32_t * flags,
      89             :                      const unsigned char *names_blob, int names_blob_len, TDSANSWER * answer, unsigned char **ntlm_v2_response);
      90             : static void tds_encrypt_answer(const unsigned char *hash, const unsigned char *challenge, unsigned char *answer);
      91             : static void tds_convert_key(const unsigned char *key_56, DES_KEY * ks);
      92             : 
      93             : static void
      94         706 : convert_to_upper(char *buf, size_t len)
      95             : {
      96             :         size_t i;
      97             : 
      98        9884 :         for (i = 0; i < len; i++)
      99        9178 :                 buf[i] = toupper((unsigned char) buf[i]);
     100         706 : }
     101             : 
     102             : static size_t
     103        3530 : convert_to_usc2le_string(TDSSOCKET * tds, const char *s, size_t len, char *out)
     104             : {
     105             :         const char *ib;
     106             :         char *ob;
     107             :         size_t il, ol;
     108             : 
     109        3530 :         TDSICONV * char_conv = tds->conn->char_convs[client2ucs2];
     110             : 
     111             :         /* char_conv is only mostly const */
     112        3530 :         TDS_ERRNO_MESSAGE_FLAGS *suppress = (TDS_ERRNO_MESSAGE_FLAGS *) & char_conv->suppress;
     113             : 
     114        3530 :         if (char_conv->flags == TDS_ENCODING_MEMCPY) {
     115           0 :                 memcpy(out, s, len);
     116           0 :                 return len;
     117             :         }
     118             : 
     119             :         /* convert */
     120        3530 :         ib = s;
     121        3530 :         il = len;
     122        3530 :         ob = out;
     123        3530 :         ol = len * 2;
     124        3530 :         memset(suppress, 0, sizeof(char_conv->suppress));
     125        3530 :         if (tds_iconv(tds, char_conv, to_server, &ib, &il, &ob, &ol) == (size_t) - 1)
     126             :                 return (size_t) -1;
     127             : 
     128        3530 :         return ob - out;
     129             : }
     130             : 
     131             : static TDSRET
     132         706 : make_ntlm_hash(TDSSOCKET * tds, const char *passwd, unsigned char ntlm_hash[16])
     133             : {
     134             :         MD4_CTX context;
     135         706 :         size_t passwd_len = 0;
     136             :         char passwd_usc2le[256];
     137         706 :         size_t passwd_usc2le_len = 0;
     138             : 
     139         706 :         passwd_len = strlen(passwd);
     140             : 
     141         706 :         if (passwd_len > 128)
     142           0 :                 passwd_len = 128;
     143             : 
     144         706 :         passwd_usc2le_len = convert_to_usc2le_string(tds, passwd, passwd_len, passwd_usc2le);
     145         706 :         if (passwd_usc2le_len == (size_t) -1) {
     146             :                 memset((char *) passwd_usc2le, 0, sizeof(passwd_usc2le));
     147             :                 return TDS_FAIL;
     148             :         }
     149             : 
     150             :         /* compute NTLM hash */
     151         706 :         MD4Init(&context);
     152         706 :         MD4Update(&context, (unsigned char *) passwd_usc2le, passwd_usc2le_len);
     153         706 :         MD4Final(&context, ntlm_hash);
     154             : 
     155             :         /* with security is best be pedantic */
     156             :         memset((char *) passwd_usc2le, 0, passwd_usc2le_len);
     157             :         memset(&context, 0, sizeof(context));
     158         706 :         return TDS_SUCCESS;
     159             : }
     160             : 
     161             : 
     162             : static TDSRET
     163         706 : make_ntlm_v2_hash(TDSSOCKET * tds, const char *passwd, unsigned char ntlm_v2_hash[16])
     164             : {
     165             :         const char *user_name, *domain;
     166         706 :         size_t domain_len, user_name_len, len, buf_usc2le_len = 0;
     167             :         const char *p;
     168             : 
     169             :         unsigned char ntlm_hash[16];
     170             :         char buf[128];
     171             :         char buf_usc2le[512];
     172             :         TDSRET res;
     173             : 
     174        1412 :         user_name = tds_dstr_cstr(&tds->login->user_name);
     175             : 
     176             :         /* parse domain\username */
     177         706 :         p = strchr(user_name, '\\');
     178             : 
     179         706 :         domain = user_name;
     180         706 :         domain_len = p - user_name;
     181             : 
     182         706 :         user_name = p + 1;
     183         706 :         user_name_len = strlen(user_name);
     184             : 
     185         706 :         if (user_name_len > 128)
     186           0 :                 user_name_len = 128;
     187         706 :         memcpy(buf, user_name, user_name_len);
     188         706 :         convert_to_upper(buf, user_name_len);
     189             : 
     190         706 :         len = convert_to_usc2le_string(tds, buf, user_name_len, buf_usc2le);
     191         706 :         if (len == (size_t) -1)
     192             :                 return TDS_FAIL;
     193         706 :         buf_usc2le_len = len;
     194             : 
     195         706 :         if (domain_len > 128)
     196           0 :                 domain_len = 128;
     197             :         /* Target is supposed to be case-sensitive */
     198             : 
     199         706 :         len = convert_to_usc2le_string(tds, domain, domain_len, buf_usc2le + len);
     200         706 :         if (len == (size_t) -1)
     201             :                 return TDS_FAIL;
     202         706 :         buf_usc2le_len += len;
     203             : 
     204             : 
     205         706 :         res = make_ntlm_hash(tds, passwd, ntlm_hash);
     206         706 :         hmac_md5(ntlm_hash, (const unsigned char *) buf_usc2le, buf_usc2le_len, ntlm_v2_hash);
     207             : 
     208             :         /* with security is best be pedantic */
     209             :         memset(&ntlm_hash, 0, sizeof(ntlm_hash));
     210             :         memset(buf, 0, sizeof(buf));
     211             :         memset((char *) buf_usc2le, 0, buf_usc2le_len);
     212         706 :         return res;
     213             : }
     214             : 
     215             : 
     216             : /*
     217             :  * hash - The NTLMv2 Hash.
     218             :  * client_data - The client data (blob or client nonce).
     219             :  * challenge - The server challenge from the Type 2 message.
     220             :  */
     221             : static unsigned char *
     222        1412 : make_lm_v2_response(const unsigned char ntlm_v2_hash[16],
     223             :                     const unsigned char *client_data, int client_data_len, const unsigned char challenge[8])
     224             : {
     225        1412 :         int mac_len = 16 + client_data_len;
     226             :         unsigned char *mac;
     227             : 
     228        1412 :         mac = tds_new(unsigned char, mac_len);
     229        1412 :         if (!mac)
     230             :                 return NULL;
     231             : 
     232        1412 :         memcpy(mac + 8, challenge, 8);
     233        1412 :         memcpy(mac + 16, client_data, client_data_len);
     234        1412 :         hmac_md5(ntlm_v2_hash, mac + 8, client_data_len + 8, mac);
     235             : 
     236        1412 :         return mac;
     237             : }
     238             : 
     239             : static TDSRET
     240         706 : tds_answer_challenge_ntlmv2(TDSSOCKET * tds,
     241             :                      TDSLOGIN * login,
     242             :                      const unsigned char *challenge,
     243             :                      uint32_t * flags,
     244             :                      const unsigned char *names_blob, int names_blob_len, TDSANSWER * answer, unsigned char **ntlm_v2_response)
     245             : {
     246             :         TDSRET res;
     247        1412 :         const char *passwd = tds_dstr_cstr(&login->password);
     248             : 
     249             :         /* NTLMv2 */
     250             :         unsigned char *lm_v2_response;
     251             :         unsigned char ntlm_v2_hash[16];
     252             :         const names_blob_prefix_t *names_blob_prefix;
     253             : 
     254         706 :         if (!names_blob)
     255             :                 return TDS_FAIL;
     256             : 
     257         706 :         res = make_ntlm_v2_hash(tds, passwd, ntlm_v2_hash);
     258         706 :         if (TDS_FAILED(res))
     259             :                 return res;
     260             : 
     261             :         /* LMv2 response */
     262             :         /* Take client's challenge from names_blob */
     263         706 :         names_blob_prefix = (const names_blob_prefix_t *) names_blob;
     264         706 :         lm_v2_response = make_lm_v2_response(ntlm_v2_hash, names_blob_prefix->challenge, 8, challenge);
     265         706 :         if (!lm_v2_response)
     266             :                 return TDS_FAIL;
     267         706 :         memcpy(answer->lm_resp, lm_v2_response, 24);
     268         706 :         free(lm_v2_response);
     269             : 
     270             :         /* NTLMv2 response */
     271             :         /* Size of lm_v2_response is 16 + names_blob_len */
     272         706 :         *ntlm_v2_response = make_lm_v2_response(ntlm_v2_hash, names_blob, names_blob_len, challenge);
     273         706 :         if (!*ntlm_v2_response)
     274             :                 return TDS_FAIL;
     275             : 
     276             :         memset(ntlm_v2_hash, 0, sizeof(ntlm_v2_hash));
     277             : 
     278             :         /* local not supported */
     279         706 :         *flags &= ~0x4000;
     280         706 :         return TDS_SUCCESS;
     281             : }
     282             : 
     283             : /**
     284             :  * Crypt a given password using schema required for NTLMv1 or NTLM2 authentication
     285             :  * @param passwd clear text domain password
     286             :  * @param challenge challenge data given by server
     287             :  * @param flags NTLM flags from server side
     288             :  * @param answer buffer where to store crypted password
     289             :  */
     290             : static TDSRET
     291         706 : tds_answer_challenge(TDSSOCKET * tds,
     292             :                      TDSLOGIN * login,
     293             :                      const unsigned char *challenge,
     294             :                      uint32_t * flags,
     295             :                      const unsigned char *names_blob, int names_blob_len, TDSANSWER * answer, unsigned char **ntlm_v2_response)
     296             : {
     297             : #define MAX_PW_SZ 14
     298        1412 :         const char *passwd = tds_dstr_cstr(&login->password);
     299             :         DES_KEY ks;
     300             :         unsigned char hash[24], ntlm2_challenge[16];
     301             :         TDSRET res;
     302             : 
     303         706 :         memset(answer, 0, sizeof(TDSANSWER));
     304             : 
     305         706 :         if (login->use_ntlmv2) {
     306         706 :                 return tds_answer_challenge_ntlmv2(tds, login, challenge, flags,
     307             :                                                    names_blob, names_blob_len, answer, ntlm_v2_response);
     308           0 :         } else if ((*flags & 0x80000) != 0) {
     309             :                 /* NTLM2 */
     310             :                 MD5_CTX md5_ctx;
     311             : 
     312           0 :                 tds_random_buffer(hash, 8);
     313           0 :                 memset(hash + 8, 0, 16);
     314           0 :                 memcpy(answer->lm_resp, hash, 24);
     315             : 
     316           0 :                 MD5Init(&md5_ctx);
     317           0 :                 MD5Update(&md5_ctx, challenge, 8);
     318           0 :                 MD5Update(&md5_ctx, hash, 8);
     319           0 :                 MD5Final(&md5_ctx, ntlm2_challenge);
     320           0 :                 challenge = ntlm2_challenge;
     321             :                 memset(&md5_ctx, 0, sizeof(md5_ctx));
     322           0 :         } else if (login->use_lanman) {
     323             :                 /* LM */
     324             :                 size_t len, i;
     325             :                 unsigned char passwd_buf[MAX_PW_SZ];
     326             :                 static const des_cblock magic = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
     327             : 
     328             :                 /* convert password to upper and pad to 14 chars */
     329           0 :                 memset(passwd_buf, 0, MAX_PW_SZ);
     330           0 :                 len = strlen(passwd);
     331           0 :                 if (len > MAX_PW_SZ)
     332           0 :                         len = MAX_PW_SZ;
     333           0 :                 for (i = 0; i < len; i++)
     334           0 :                         passwd_buf[i] = toupper((unsigned char) passwd[i]);
     335             : 
     336             :                 /* hash the first 7 characters */
     337           0 :                 tds_convert_key(passwd_buf, &ks);
     338           0 :                 tds_des_ecb_encrypt(&magic, sizeof(magic), &ks, (hash + 0));
     339             : 
     340             :                 /* hash the second 7 characters */
     341           0 :                 tds_convert_key(passwd_buf + 7, &ks);
     342           0 :                 tds_des_ecb_encrypt(&magic, sizeof(magic), &ks, (hash + 8));
     343             : 
     344           0 :                 memset(hash + 16, 0, 5);
     345             : 
     346           0 :                 tds_encrypt_answer(hash, challenge, answer->lm_resp);
     347             :                 memset(passwd_buf, 0, sizeof(passwd_buf));
     348             :         } else {
     349           0 :                 memset(answer->lm_resp, 0, sizeof(answer->lm_resp));
     350             :         }
     351           0 :         *flags = 0x8201;
     352             : 
     353             :         /* NTLM/NTLM2 response */
     354           0 :         res = make_ntlm_hash(tds, passwd, hash);
     355           0 :         memset(hash + 16, 0, 5);
     356             : 
     357           0 :         tds_encrypt_answer(hash, challenge, answer->nt_resp);
     358             : 
     359             :         /* with security is best be pedantic */
     360             :         memset(&ks, 0, sizeof(ks));
     361             :         memset(hash, 0, sizeof(hash));
     362             :         memset(ntlm2_challenge, 0, sizeof(ntlm2_challenge));
     363           0 :         return res;
     364             : }
     365             : 
     366             : 
     367             : /*
     368             : * takes a 21 byte array and treats it as 3 56-bit DES keys. The
     369             : * 8 byte plaintext is encrypted with each key and the resulting 24
     370             : * bytes are stored in the results array.
     371             : */
     372             : static void
     373           0 : tds_encrypt_answer(const unsigned char *hash, const unsigned char *challenge, unsigned char *answer)
     374             : {
     375             :         DES_KEY ks;
     376             : 
     377           0 :         tds_convert_key(hash, &ks);
     378           0 :         tds_des_ecb_encrypt(challenge, 8, &ks, answer);
     379             : 
     380           0 :         tds_convert_key(&hash[7], &ks);
     381           0 :         tds_des_ecb_encrypt(challenge, 8, &ks, &answer[8]);
     382             : 
     383           0 :         tds_convert_key(&hash[14], &ks);
     384           0 :         tds_des_ecb_encrypt(challenge, 8, &ks, &answer[16]);
     385             : 
     386             :         memset(&ks, 0, sizeof(ks));
     387           0 : }
     388             : 
     389             : 
     390             : /*
     391             : * turns a 56 bit key into the 64 bit, odd parity key and sets the key.
     392             : * The key schedule ks is also set.
     393             : */
     394             : static void
     395           0 : tds_convert_key(const unsigned char *key_56, DES_KEY * ks)
     396             : {
     397             :         des_cblock key;
     398             : 
     399           0 :         key[0] = key_56[0];
     400           0 :         key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
     401           0 :         key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
     402           0 :         key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
     403           0 :         key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
     404           0 :         key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
     405           0 :         key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
     406           0 :         key[7] = (key_56[6] << 1) & 0xFF;
     407             : 
     408           0 :         tds_des_set_odd_parity(key);
     409           0 :         tds_des_set_key(ks, key, sizeof(key));
     410             : 
     411             :         memset(&key, 0, sizeof(key));
     412           0 : }
     413             : 
     414             : static TDSRET
     415         706 : tds7_send_auth(TDSSOCKET * tds,
     416             :                const unsigned char *challenge, uint32_t flags, const unsigned char *names_blob, int names_blob_len)
     417             : {
     418             :         size_t current_pos;
     419             :         TDSANSWER answer;
     420             : 
     421             :         /* FIXME: stuff duplicate in tds7_send_login */
     422             :         const char *domain;
     423             :         const char *user_name;
     424             :         const char *host_name;
     425             :         const char *p;
     426             :         char *convert_buffer;
     427             :         size_t user_name_len, host_name_len, domain_len;
     428             :         TDSRET rc;
     429             : 
     430         706 :         unsigned char *ntlm_v2_response = NULL;
     431         706 :         unsigned int ntlm_response_len = 24;
     432         706 :         const unsigned int lm_response_len = 24;
     433             : 
     434         706 :         TDSLOGIN *login = tds->login;
     435             : 
     436             :         /* check connection */
     437         706 :         if (!login)
     438             :                 return TDS_FAIL;
     439             : 
     440             :         /* parse a bit of config */
     441        1412 :         user_name = tds_dstr_cstr(&login->user_name);
     442        1412 :         user_name_len = tds_dstr_len(&login->user_name);
     443        1412 :         host_name = tds_dstr_cstr(&login->client_host_name);
     444        1412 :         host_name_len = tds_dstr_len(&login->client_host_name);
     445             : 
     446             :         /* convert strings */
     447         706 :         convert_buffer = tds_new(char, (user_name_len + host_name_len) * 2);
     448         706 :         if (!convert_buffer)
     449             :                 return TDS_FAIL;
     450             : 
     451         706 :         user_name_len = convert_to_usc2le_string(tds, user_name, user_name_len, convert_buffer);
     452         706 :         user_name = convert_buffer;
     453         706 :         if (user_name_len != (size_t) -1) {
     454         706 :                 host_name_len = convert_to_usc2le_string(tds, host_name, host_name_len, convert_buffer + user_name_len);
     455         706 :                 host_name = convert_buffer + user_name_len;
     456             :         }
     457         706 :         if (user_name_len == (size_t) -1 || host_name_len == (size_t) -1) {
     458           0 :                 free(convert_buffer);
     459           0 :                 return TDS_FAIL;
     460             :         }
     461             : 
     462             :         /* parse domain\username */
     463             :         p = user_name;
     464             :         for (;;) {
     465       10590 :                 if (p >= user_name + user_name_len) {
     466           0 :                         free(convert_buffer);
     467           0 :                         return TDS_FAIL;
     468             :                 }
     469        5648 :                 if (p[0] == '\\' && p[1] == 0)
     470             :                         break;
     471        4942 :                 p += 2;
     472             :         }
     473             : 
     474         706 :         domain = user_name;
     475         706 :         domain_len = p - user_name;
     476             : 
     477         706 :         user_name = p + 2;
     478         706 :         user_name_len = domain + user_name_len - user_name;
     479             : 
     480         706 :         rc = tds_answer_challenge(tds, login, challenge, &flags, names_blob, names_blob_len, &answer, &ntlm_v2_response);
     481         706 :         if (TDS_FAILED(rc)) {
     482           0 :                 free(convert_buffer);
     483           0 :                 return rc;
     484             :         }
     485             : 
     486         706 :         ntlm_response_len = ntlm_v2_response ? 16 + names_blob_len : 24;
     487             :         /* ntlm_response_len = 0; */
     488             : 
     489         706 :         tds->out_flag = TDS7_AUTH;
     490         706 :         tds_put_n(tds, "NTLMSSP", 8);
     491         706 :         tds_put_int(tds, 3);    /* sequence 3 */
     492             : 
     493         706 :         current_pos = 64u + domain_len + user_name_len + host_name_len;
     494             : 
     495             :         /* LM/LMv2 Response */
     496         706 :         tds_put_smallint(tds, lm_response_len); /* lan man resp length */
     497         706 :         tds_put_smallint(tds, lm_response_len); /* lan man resp length */
     498         706 :         TDS_PUT_INT(tds, current_pos);  /* resp offset */
     499         706 :         current_pos += lm_response_len;
     500             : 
     501             :         /* NTLM/NTLMv2 Response */
     502         706 :         tds_put_smallint(tds, ntlm_response_len);       /* nt resp length */
     503         706 :         tds_put_smallint(tds, ntlm_response_len);       /* nt resp length */
     504         706 :         TDS_PUT_INT(tds, current_pos);  /* nt resp offset */
     505             : 
     506         706 :         current_pos = 64;
     507             : 
     508             :         /* Target Name - domain or server name */
     509         706 :         TDS_PUT_SMALLINT(tds, domain_len);
     510         706 :         TDS_PUT_SMALLINT(tds, domain_len);
     511         706 :         TDS_PUT_INT(tds, current_pos);
     512         706 :         current_pos += domain_len;
     513             : 
     514             :         /* username */
     515         706 :         TDS_PUT_SMALLINT(tds, user_name_len);
     516         706 :         TDS_PUT_SMALLINT(tds, user_name_len);
     517         706 :         TDS_PUT_INT(tds, current_pos);
     518         706 :         current_pos += user_name_len;
     519             : 
     520             :         /* Workstation Name */
     521         706 :         TDS_PUT_SMALLINT(tds, host_name_len);
     522         706 :         TDS_PUT_SMALLINT(tds, host_name_len);
     523         706 :         TDS_PUT_INT(tds, current_pos);
     524         706 :         current_pos += host_name_len;
     525             : 
     526             :         /* Session Key (optional) */
     527         706 :         tds_put_smallint(tds, 0);
     528         706 :         tds_put_smallint(tds, 0);
     529         706 :         TDS_PUT_INT(tds, current_pos + lm_response_len + ntlm_response_len);
     530             : 
     531             :         /* flags */
     532             :         /* "challenge" is 8 bytes long */
     533             :         /* tds_answer_challenge(tds_dstr_cstr(&login->password), challenge, &flags, &answer); */
     534         706 :         tds_put_int(tds, flags);
     535             : 
     536             :         /* OS Version Structure (Optional) */
     537             : 
     538             :         /* Data itself */
     539         706 :         tds_put_n(tds, domain, domain_len);
     540         706 :         tds_put_n(tds, user_name, user_name_len);
     541         706 :         tds_put_n(tds, host_name, host_name_len);
     542             : 
     543             :         /* data block */
     544         706 :         tds_put_n(tds, answer.lm_resp, lm_response_len);
     545             : 
     546         706 :         if (ntlm_v2_response == NULL) {
     547             :                 /* NTLMv1 */
     548           0 :                 tds_put_n(tds, answer.nt_resp, ntlm_response_len);
     549             :         } else {
     550             :                 /* NTLMv2 */
     551         706 :                 tds_put_n(tds, ntlm_v2_response, ntlm_response_len);
     552         706 :                 memset(ntlm_v2_response, 0, ntlm_response_len);
     553         706 :                 free(ntlm_v2_response);
     554             :         }
     555             : 
     556             :         /* for security reason clear structure */
     557         706 :         memset(&answer, 0, sizeof(TDSANSWER));
     558             : 
     559         706 :         free(convert_buffer);
     560         706 :         return tds_flush_packet(tds);
     561             : }
     562             : 
     563             : typedef struct tds_ntlm_auth
     564             : {
     565             :         TDSAUTHENTICATION tds_auth;
     566             : } TDSNTLMAUTH;
     567             : 
     568             : static TDSRET
     569         706 : tds_ntlm_free(TDSCONNECTION * conn, TDSAUTHENTICATION * tds_auth)
     570             : {
     571         706 :         TDSNTLMAUTH *auth = (TDSNTLMAUTH *) tds_auth;
     572             : 
     573         706 :         free(auth->tds_auth.packet);
     574         706 :         free(auth);
     575             : 
     576         706 :         return TDS_SUCCESS;
     577             : }
     578             : 
     579             : static const unsigned char ntlm_id[] = "NTLMSSP";
     580             : 
     581             : /**
     582             :  * put a 8 byte filetime from a time_t
     583             :  * This takes GMT as input
     584             :  */
     585             : static void
     586             : unix_to_nt_time(uint64_t * nt, struct timeval *tv)
     587             : {
     588             :         /* C time start on 1970, nt time on 1600 */
     589             : #define TIME_FIXUP_CONSTANT (((uint64_t) 134774U) * 86400U)
     590             : 
     591             :         uint64_t t2;
     592             : 
     593         706 :         t2 = tv->tv_sec;
     594         706 :         t2 += TIME_FIXUP_CONSTANT;
     595         706 :         t2 *= 1000u * 1000u * 10u;
     596         706 :         t2 += tv->tv_usec * 10u;
     597             : 
     598         706 :         *nt = t2;
     599             : }
     600             : 
     601             : static void
     602         706 : fill_names_blob_prefix(names_blob_prefix_t * prefix)
     603             : {
     604             :         struct timeval tv;
     605         706 :         uint64_t nttime = 0;
     606             : 
     607         706 :         gettimeofday(&tv, NULL);
     608         706 :         unix_to_nt_time(&nttime, &tv);
     609             : 
     610         706 :         prefix->response_type = 0x01;
     611         706 :         prefix->max_response_type = 0x01;
     612         706 :         prefix->reserved1 = 0x0000;
     613         706 :         prefix->reserved2 = 0x00000000;
     614             : #ifdef WORDS_BIGENDIAN
     615             :         tds_swap_bytes(&nttime, 8);
     616             : #endif
     617         706 :         prefix->timestamp = nttime;
     618         706 :         tds_random_buffer(prefix->challenge, sizeof(prefix->challenge));
     619             : 
     620         706 :         prefix->unknown = 0x00000000;
     621         706 : }
     622             : 
     623             : static TDSRET
     624         706 : tds_ntlm_handle_next(TDSSOCKET * tds, struct tds_authentication * auth, size_t len)
     625             : {
     626         706 :         const int length = (int)len;
     627             :         unsigned char nonce[8];
     628             :         uint32_t flags;
     629             :         int where;
     630             : 
     631             :         int data_block_offset;
     632             : 
     633         706 :         int names_blob_len = 0;
     634         706 :         unsigned char *names_blob = NULL;
     635             : 
     636             :         TDSRET rc;
     637             : 
     638             :         /* at least 32 bytes (till context) */
     639         706 :         if (len < 32)
     640             :                 return TDS_FAIL;
     641             : 
     642         706 :         tds_get_n(tds, nonce, 8);       /* NTLMSSP\0 */
     643         706 :         if (memcmp(nonce, ntlm_id, 8) != 0)
     644             :                 return TDS_FAIL;
     645         706 :         if (tds_get_int(tds) != 2)      /* sequence -> 2 */
     646             :                 return TDS_FAIL;
     647         706 :         tds_get_smallint(tds);  /* domain len */
     648         706 :         tds_get_smallint(tds);  /* domain len */
     649         706 :         data_block_offset = tds_get_int(tds);   /* domain offset */
     650         706 :         flags = tds_get_int(tds);       /* flags */
     651         706 :         tds_get_n(tds, nonce, 8);
     652         706 :         tdsdump_dump_buf(TDS_DBG_INFO1, "TDS_AUTH_TOKEN nonce", nonce, 8);
     653         706 :         where = 32;
     654             : 
     655             :         /*data_block_offset == 32 */
     656             :         /* Version 1 -- The Context, Target Information, and OS Version structure are all omitted */
     657             : 
     658         706 :         if (data_block_offset >= 48 && where + 16 <= length) {
     659             :                 int target_info_len, target_info_offset;
     660             : 
     661             :                 /* Version 2 -- The Context and Target Information fields are present, but the OS Version structure is not. */
     662         706 :                 tds_get_n(tds, NULL, 8);        /* Context (two consecutive longs) */
     663             : 
     664         706 :                 target_info_len = tds_get_smallint(tds);        /* Target Information len */
     665         706 :                 target_info_len = tds_get_smallint(tds);        /* Target Information len */
     666         706 :                 target_info_offset = tds_get_int(tds);  /* Target Information offset */
     667             : 
     668         706 :                 where += 16;
     669             : 
     670         706 :                 if (data_block_offset >= 56 && where + 8 <= length) {
     671             :                         /* Version 3 -- The Context, Target Information, and OS Version structure are all present. */
     672         706 :                         tds_get_n(tds, NULL, 8);        /* OS Version Structure */
     673             : #if 0
     674             :                         /* if we have a version server handle NTLMv2 */
     675             :                         if (target_info_len > 0)
     676             :                                 flags &= ~0x80000;
     677             : #endif
     678         706 :                         where += 8;
     679             :                 }
     680             : 
     681             :                 /* read Target Info if possible */
     682         706 :                 if (target_info_len > 0 && target_info_offset >= where && target_info_offset + target_info_len <= length) {
     683         706 :                         tds_get_n(tds, NULL, target_info_offset - where);
     684         706 :                         where = target_info_offset;
     685             : 
     686             :                         /*
     687             :                          * the + 4 came from blob structure, after Target Info 4
     688             :                          * additional reserved bytes must be present
     689             :                          * Search "davenport port"
     690             :                          * (currently http://davenport.sourceforge.net/ntlm.html)
     691             :                          */
     692         706 :                         names_blob_len = TDS_OFFSET(names_blob_prefix_t, target_info) + target_info_len + 4;
     693             : 
     694             :                         /* read Target Info */
     695         706 :                         names_blob = tds_new0(unsigned char, names_blob_len);
     696         706 :                         if (!names_blob)
     697             :                                 return TDS_FAIL;
     698             : 
     699         706 :                         fill_names_blob_prefix((names_blob_prefix_t *) names_blob);
     700         706 :                         tds_get_n(tds, names_blob + TDS_OFFSET(names_blob_prefix_t, target_info), target_info_len);
     701         706 :                         where += target_info_len;
     702             :                 }
     703             :         }
     704             :         /* discard anything left */
     705         706 :         tds_get_n(tds, NULL, length - where);
     706         706 :         tdsdump_log(TDS_DBG_INFO1, "Draining %d bytes\n", (int) (len - where));
     707             : 
     708         706 :         rc = tds7_send_auth(tds, nonce, flags, names_blob, names_blob_len);
     709             : 
     710         706 :         free(names_blob);
     711             : 
     712         706 :         return rc;
     713             : }
     714             : 
     715             : /**
     716             :  * Build a NTLMSPP packet to send to server
     717             :  * @param tds     A pointer to the TDSSOCKET structure managing a client/server operation.
     718             :  * @return authentication info
     719             :  */
     720             : TDSAUTHENTICATION * 
     721         706 : tds_ntlm_get_auth(TDSSOCKET * tds)
     722             : {
     723             :         const char *domain;
     724             :         const char *user_name;
     725             :         const char *p;
     726             :         uint8_t *packet;
     727             :         int host_name_len;
     728             :         int domain_len;
     729             :         int auth_len;
     730             :         struct tds_ntlm_auth *auth;
     731             : 
     732         706 :         if (!tds->login)
     733             :                 return NULL;
     734             : 
     735        1412 :         user_name = tds_dstr_cstr(&tds->login->user_name);
     736        1412 :         host_name_len = (int)tds_dstr_len(&tds->login->client_host_name);
     737             : 
     738             :         /* check override of domain */
     739         706 :         if ((p = strchr(user_name, '\\')) == NULL)
     740             :                 return NULL;
     741             : 
     742         706 :         domain = user_name;
     743         706 :         domain_len = (int)(p - user_name);
     744             : 
     745         706 :         auth = tds_new0(struct tds_ntlm_auth, 1);
     746             : 
     747         706 :         if (!auth)
     748             :                 return NULL;
     749             : 
     750         706 :         auth->tds_auth.free = tds_ntlm_free;
     751         706 :         auth->tds_auth.handle_next = tds_ntlm_handle_next;
     752             : 
     753         706 :         auth->tds_auth.packet_len = auth_len = 40 + host_name_len + domain_len;
     754         706 :         auth->tds_auth.packet = packet = tds_new(uint8_t, auth_len);
     755         706 :         if (!packet) {
     756           0 :                 free(auth);
     757           0 :                 return NULL;
     758             :         }
     759             : 
     760             :         /* built NTLMSSP authentication packet */
     761         706 :         memcpy(packet, ntlm_id, 8);
     762             :         /* sequence 1 client -> server */
     763         706 :         TDS_PUT_A4(packet + 8, TDS_HOST4LE(1));
     764             :         /* flags */
     765         706 :         TDS_PUT_A4(packet + 12, TDS_HOST4LE(0x08b201));
     766             : 
     767             :         /* domain info */
     768         706 :         TDS_PUT_A2LE(packet + 16, domain_len);
     769         706 :         TDS_PUT_A2LE(packet + 18, domain_len);
     770         706 :         TDS_PUT_A4LE(packet + 20, 40 + host_name_len);
     771             : 
     772             :         /* hostname info */
     773         706 :         TDS_PUT_A2LE(packet + 24, host_name_len);
     774         706 :         TDS_PUT_A2LE(packet + 26, host_name_len);
     775         706 :         TDS_PUT_A4  (packet + 28, TDS_HOST4LE(40));
     776             : 
     777             :         /*
     778             :          * here XP put version like 05 01 28 0a (5.1.2600),
     779             :          * similar to GetVersion result
     780             :          * and some unknown bytes like 00 00 00 0f
     781             :          */
     782         706 :         TDS_PUT_A4(packet + 32, TDS_HOST4LE(0x0a280105));
     783         706 :         TDS_PUT_A4(packet + 36, TDS_HOST4LE(0x0f000000));
     784             : 
     785             :         /* hostname and domain */
     786        1412 :         memcpy(packet + 40, tds_dstr_cstr(&tds->login->client_host_name), host_name_len);
     787         706 :         memcpy(packet + 40 + host_name_len, domain, domain_len);
     788             : 
     789         706 :         return (TDSAUTHENTICATION *) auth;
     790             : }
     791             : 
     792             : /** @} */
     793             : 

Generated by: LCOV version 1.13