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/tds/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/tds/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 : /** NTLMv2 session base key, valid if has_session_key is set */
70 : unsigned char session_key[16];
71 : bool has_session_key;
72 : } TDSANSWER;
73 :
74 : /* NTLM negotiate flags, see MS-NLMP */
75 : #define NTLMSSP_NEGOTIATE_UNICODE 0x00000001u
76 : #define NTLMSSP_NEGOTIATE_SIGN 0x00000010u
77 : #define NTLMSSP_NEGOTIATE_SEAL 0x00000020u
78 : #define NTLMSSP_NEGOTIATE_NTLM 0x00000200u
79 : #define NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED 0x00001000u
80 : #define NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED 0x00002000u
81 : #define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x00004000u
82 : #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x00008000u
83 : #define NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY 0x00080000u
84 : #define NTLMSSP_NEGOTIATE_VERSION 0x02000000u
85 : #define NTLMSSP_NEGOTIATE_128 0x20000000u
86 : #define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000u
87 :
88 : /* AV_PAIR identifiers, see MS-NLMP */
89 : #define MSV_AV_EOL 0x0000
90 : #define MSV_AV_FLAGS 0x0006
91 : #define MSV_AV_TIMESTAMP 0x0007
92 : #define MSV_AV_TARGET_NAME 0x0009
93 : #define MSV_AV_CHANNEL_BINDINGS 0x000A
94 :
95 : /* MsvAvFlags value, MIC is present */
96 : #define MSV_AV_FLAG_MIC 0x00000002u
97 :
98 : /* AUTHENTICATE_MESSAGE header sizes, without and with Version and MIC fields */
99 : #define NTLM_AUTH_HEADER_LEN 64
100 : #define NTLM_AUTH_HEADER_MIC_LEN 88
101 : #define NTLM_AUTH_MIC_OFFSET 72
102 :
103 : typedef struct
104 : {
105 : uint8_t response_type;
106 : uint8_t max_response_type;
107 : uint16_t reserved1;
108 : uint32_t reserved2;
109 : uint64_t timestamp;
110 : uint8_t challenge[8];
111 : uint32_t reserved3;
112 : /* target info block - variable length */
113 : uint8_t target_info[4];
114 : } names_blob_prefix_t;
115 :
116 : #define AV_PAIR_CBT_BYTES 20
117 :
118 : typedef struct
119 : {
120 : TDSAUTHENTICATION tds_auth;
121 : uint8_t cbt[16];
122 : bool has_cbt;
123 : /** service principal name, UTF-16LE */
124 : char *spn;
125 : size_t spn_len;
126 : /** CHALLENGE_MESSAGE received from server, used to compute MIC */
127 : unsigned char *challenge;
128 : size_t challenge_len;
129 : } TDSNTLMAUTH;
130 :
131 : static const unsigned char ntlm_id[] = "NTLMSSP";
132 :
133 : static TDSRET
134 : tds_answer_challenge(TDSSOCKET * tds,
135 : TDSLOGIN * login,
136 : const unsigned char *challenge,
137 : uint32_t * flags,
138 : const unsigned char *names_blob, int names_blob_len, TDSANSWER * answer, unsigned char **ntlm_v2_response);
139 : static void tds_encrypt_answer(const unsigned char *hash, const unsigned char *challenge, unsigned char *answer);
140 : static void tds_convert_key(const unsigned char *key_56, DES_KEY * ks);
141 :
142 : #include "ucs2_upper.h"
143 :
144 : /**
145 : * Convert a UTF-16 code unit to upper case, using Unicode simple case mapping
146 : * like Windows does.
147 : */
148 : static uint16_t
149 10334 : ucs2_upper(uint16_t c)
150 : {
151 10334 : size_t low = 0, high = TDS_VECTOR_SIZE(ucs2_upper_ranges);
152 :
153 10334 : if (c < 0x80)
154 10144 : return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c;
155 :
156 : /* binary search the range containing the character */
157 1390 : while (low < high) {
158 1340 : size_t mid = (low + high) / 2;
159 1340 : const ucs2_upper_range *r = &ucs2_upper_ranges[mid];
160 :
161 1340 : if (c < r->first) {
162 : high = mid;
163 650 : } else if (c > r->last) {
164 510 : low = mid + 1;
165 : } else {
166 : /* delta 0xffff (-1) ranges contain every other character */
167 140 : if (r->delta != 0xffff || ((c - r->first) & 1) == 0)
168 140 : return (uint16_t) (c + r->delta);
169 : return c;
170 : }
171 : }
172 : return c;
173 : }
174 :
175 : /**
176 : * Convert a UTF-16LE string to upper case.
177 : * Surrogates are not changed, characters outside the BMP have no simple mapping
178 : * to upper case in Windows.
179 : */
180 : static void
181 : ucs2le_to_upper(char *buf, size_t len)
182 : {
183 10 : unsigned char *p = (unsigned char *) buf;
184 :
185 10134 : for (; len >= 2; len -= 2, p += 2) {
186 10134 : uint16_t c = TDS_GET_UA2LE(p);
187 :
188 10134 : c = ucs2_upper(c);
189 10134 : TDS_PUT_UA2LE(p, c);
190 : }
191 : }
192 :
193 : static size_t
194 4668 : convert_to_usc2le_string(TDSSOCKET * tds, const char *s, size_t len, char *out)
195 : {
196 : const char *ib;
197 : char *ob;
198 : size_t il, ol;
199 :
200 4668 : TDSICONV * char_conv = tds->conn->char_convs[client2ucs2];
201 :
202 : /* char_conv is only mostly const */
203 4668 : TDS_ERRNO_MESSAGE_FLAGS *suppress = (TDS_ERRNO_MESSAGE_FLAGS *) & char_conv->suppress;
204 :
205 4668 : if (char_conv->flags == TDS_ENCODING_MEMCPY) {
206 0 : memcpy(out, s, len);
207 0 : return len;
208 : }
209 :
210 : /* convert */
211 4668 : ib = s;
212 4668 : il = len;
213 4668 : ob = out;
214 4668 : ol = len * 2;
215 4668 : memset(suppress, 0, sizeof(char_conv->suppress));
216 4668 : if (tds_iconv(tds, char_conv, to_server, &ib, &il, &ob, &ol) == (size_t) - 1)
217 : return (size_t) -1;
218 :
219 4668 : return ob - out;
220 : }
221 :
222 : static TDSRET
223 778 : make_ntlm_hash(TDSSOCKET *tds, const char *passwd, unsigned char ntlm_hash[16])
224 : {
225 : /*
226 : * Windows limits passwords to about 128 characters; a character can take
227 : * up to 4 bytes in client charset (like UTF-8), so allow 4 bytes per character.
228 : * Conversion needs an output buffer twice the input length.
229 : */
230 : #define MAX_NTLM_PASSWD_BYTES (128 * 4)
231 : MD4_CTX context;
232 778 : size_t passwd_len = 0;
233 : char passwd_usc2le[MAX_NTLM_PASSWD_BYTES * 2];
234 778 : size_t passwd_usc2le_len = 0;
235 :
236 778 : passwd_len = strlen(passwd);
237 :
238 778 : if (passwd_len > MAX_NTLM_PASSWD_BYTES)
239 0 : passwd_len = MAX_NTLM_PASSWD_BYTES;
240 :
241 778 : passwd_usc2le_len = convert_to_usc2le_string(tds, passwd, passwd_len, passwd_usc2le);
242 778 : if (passwd_usc2le_len == (size_t) -1) {
243 : memset((char *) passwd_usc2le, 0, sizeof(passwd_usc2le));
244 : return TDS_FAIL;
245 : }
246 :
247 : /* compute NTLM hash */
248 778 : MD4Init(&context);
249 778 : MD4Update(&context, (unsigned char *) passwd_usc2le, passwd_usc2le_len);
250 778 : MD4Final(&context, ntlm_hash);
251 :
252 : /* with security is best be pedantic */
253 : memset((char *) passwd_usc2le, 0, passwd_usc2le_len);
254 : memset(&context, 0, sizeof(context));
255 778 : return TDS_SUCCESS;
256 : }
257 :
258 :
259 : static TDSRET
260 778 : make_ntlm_v2_hash(TDSSOCKET * tds, const char *passwd, unsigned char ntlm_v2_hash[16])
261 : {
262 : const char *user_name, *domain;
263 778 : size_t domain_len, user_name_len, len, buf_usc2le_len = 0;
264 : const char *p;
265 :
266 : unsigned char ntlm_hash[16];
267 : char *buf_usc2le;
268 : TDSRET res;
269 :
270 1556 : user_name = tds_dstr_cstr(&tds->login->user_name);
271 :
272 : /* parse domain\username */
273 778 : p = strchr(user_name, '\\');
274 :
275 778 : domain = user_name;
276 778 : domain_len = p - user_name;
277 :
278 778 : user_name = p + 1;
279 778 : user_name_len = strlen(user_name);
280 :
281 : /* each byte can produce at most one UTF-16 code unit */
282 778 : buf_usc2le = tds_new(char, (user_name_len + domain_len) * 2 + 2);
283 :
284 778 : if (!buf_usc2le)
285 : return TDS_FAIL;
286 :
287 : /* user name is converted to upper case, after converting to UTF-16 */
288 778 : len = convert_to_usc2le_string(tds, user_name, user_name_len, buf_usc2le);
289 778 : if (len == (size_t) -1) {
290 0 : free(buf_usc2le);
291 0 : return TDS_FAIL;
292 : }
293 778 : ucs2le_to_upper(buf_usc2le, len);
294 778 : buf_usc2le_len = len;
295 :
296 : /* Target is supposed to be case-sensitive */
297 :
298 778 : len = convert_to_usc2le_string(tds, domain, domain_len, buf_usc2le + len);
299 778 : if (len == (size_t) -1) {
300 : memset(buf_usc2le, 0, buf_usc2le_len);
301 0 : free(buf_usc2le);
302 0 : return TDS_FAIL;
303 : }
304 778 : buf_usc2le_len += len;
305 :
306 778 : res = make_ntlm_hash(tds, passwd, ntlm_hash);
307 778 : hmac_md5(ntlm_hash, (const unsigned char *) buf_usc2le, buf_usc2le_len, ntlm_v2_hash);
308 :
309 : /* with security is best be pedantic */
310 : memset(&ntlm_hash, 0, sizeof(ntlm_hash));
311 : memset(buf_usc2le, 0, buf_usc2le_len);
312 778 : free(buf_usc2le);
313 778 : return res;
314 : }
315 :
316 :
317 : /*
318 : * hash - The NTLMv2 Hash.
319 : * client_data - The client data (blob or client nonce).
320 : * challenge - The server challenge from the Type 2 message.
321 : */
322 : static unsigned char *
323 1576 : make_lm_v2_response(const unsigned char ntlm_v2_hash[16],
324 : const unsigned char *client_data, int client_data_len, const unsigned char challenge[8])
325 : {
326 1576 : int mac_len = 16 + client_data_len;
327 : unsigned char *mac;
328 :
329 1576 : mac = tds_new(unsigned char, mac_len);
330 1576 : if (!mac)
331 : return NULL;
332 :
333 1576 : memcpy(mac + 8, challenge, 8);
334 1576 : memcpy(mac + 16, client_data, client_data_len);
335 1576 : hmac_md5(ntlm_v2_hash, mac + 8, client_data_len + 8, mac);
336 :
337 1576 : return mac;
338 : }
339 :
340 : static TDSRET
341 778 : tds_answer_challenge_ntlmv2(TDSSOCKET * tds,
342 : TDSLOGIN * login,
343 : const unsigned char *challenge,
344 : uint32_t * flags,
345 : const unsigned char *names_blob, int names_blob_len, TDSANSWER * answer, unsigned char **ntlm_v2_response)
346 : {
347 : TDSRET res;
348 1556 : const char *passwd = tds_dstr_cstr(&login->password);
349 :
350 : /* NTLMv2 */
351 : unsigned char *lm_v2_response;
352 : unsigned char ntlm_v2_hash[16];
353 : const names_blob_prefix_t *names_blob_prefix;
354 :
355 778 : if (!names_blob)
356 : return TDS_FAIL;
357 :
358 778 : res = make_ntlm_v2_hash(tds, passwd, ntlm_v2_hash);
359 778 : if (TDS_FAILED(res))
360 : return res;
361 :
362 : /* LMv2 response */
363 : /* Take client's challenge from names_blob */
364 778 : names_blob_prefix = (const names_blob_prefix_t *) names_blob;
365 778 : lm_v2_response = make_lm_v2_response(ntlm_v2_hash, names_blob_prefix->challenge, 8, challenge);
366 778 : if (!lm_v2_response)
367 : return TDS_FAIL;
368 778 : memcpy(answer->lm_resp, lm_v2_response, 24);
369 778 : free(lm_v2_response);
370 :
371 : /* NTLMv2 response */
372 : /* Size of lm_v2_response is 16 + names_blob_len */
373 778 : *ntlm_v2_response = make_lm_v2_response(ntlm_v2_hash, names_blob, names_blob_len, challenge);
374 778 : if (!*ntlm_v2_response)
375 : return TDS_FAIL;
376 :
377 : /* SessionBaseKey = HMAC_MD5(ResponseKeyNT, NTProofStr), NTProofStr is the first 16 bytes of the response */
378 778 : hmac_md5(ntlm_v2_hash, *ntlm_v2_response, 16, answer->session_key);
379 778 : answer->has_session_key = true;
380 :
381 : memset(ntlm_v2_hash, 0, sizeof(ntlm_v2_hash));
382 :
383 : /* local not supported */
384 778 : *flags &= ~NTLMSSP_NEGOTIATE_LOCAL_CALL;
385 778 : return TDS_SUCCESS;
386 : }
387 :
388 : /**
389 : * Crypt a given password using schema required for NTLMv1 or NTLM2 authentication
390 : * @param passwd clear text domain password
391 : * @param challenge challenge data given by server
392 : * @param flags NTLM flags from server side
393 : * @param answer buffer where to store crypted password
394 : */
395 : static TDSRET
396 778 : tds_answer_challenge(TDSSOCKET * tds,
397 : TDSLOGIN * login,
398 : const unsigned char *challenge,
399 : uint32_t * flags,
400 : const unsigned char *names_blob, int names_blob_len, TDSANSWER * answer, unsigned char **ntlm_v2_response)
401 : {
402 : #define MAX_PW_SZ 14
403 1556 : const char *passwd = tds_dstr_cstr(&login->password);
404 : DES_KEY ks;
405 : unsigned char hash[24], ntlm2_challenge[16];
406 : TDSRET res;
407 :
408 778 : memset(answer, 0, sizeof(TDSANSWER));
409 :
410 778 : if (login->use_ntlmv2) {
411 778 : return tds_answer_challenge_ntlmv2(tds, login, challenge, flags,
412 : names_blob, names_blob_len, answer, ntlm_v2_response);
413 0 : } else if ((*flags & 0x80000) != 0) {
414 : /* NTLM2 */
415 : MD5_CTX md5_ctx;
416 :
417 0 : tds_random_buffer(hash, 8);
418 0 : memset(hash + 8, 0, 16);
419 0 : memcpy(answer->lm_resp, hash, 24);
420 :
421 0 : MD5Init(&md5_ctx);
422 0 : MD5Update(&md5_ctx, challenge, 8);
423 0 : MD5Update(&md5_ctx, hash, 8);
424 0 : MD5Final(&md5_ctx, ntlm2_challenge);
425 0 : challenge = ntlm2_challenge;
426 : memset(&md5_ctx, 0, sizeof(md5_ctx));
427 0 : } else if (login->use_lanman) {
428 : /* LM */
429 : size_t len, i;
430 : unsigned char passwd_buf[MAX_PW_SZ];
431 : static const des_cblock magic = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
432 :
433 : /* convert password to upper and pad to 14 chars */
434 0 : memset(passwd_buf, 0, MAX_PW_SZ);
435 0 : len = strlen(passwd);
436 0 : if (len > MAX_PW_SZ)
437 0 : len = MAX_PW_SZ;
438 0 : for (i = 0; i < len; i++)
439 0 : passwd_buf[i] = toupper((unsigned char) passwd[i]);
440 :
441 : /* hash the first 7 characters */
442 0 : tds_convert_key(passwd_buf, &ks);
443 0 : tds_des_ecb_encrypt(&magic, sizeof(magic), &ks, (hash + 0));
444 :
445 : /* hash the second 7 characters */
446 0 : tds_convert_key(passwd_buf + 7, &ks);
447 0 : tds_des_ecb_encrypt(&magic, sizeof(magic), &ks, (hash + 8));
448 :
449 0 : memset(hash + 16, 0, 5);
450 :
451 0 : tds_encrypt_answer(hash, challenge, answer->lm_resp);
452 : memset(passwd_buf, 0, sizeof(passwd_buf));
453 : } else {
454 0 : memset(answer->lm_resp, 0, sizeof(answer->lm_resp));
455 : }
456 0 : *flags = 0x8201;
457 :
458 : /* NTLM/NTLM2 response */
459 0 : res = make_ntlm_hash(tds, passwd, hash);
460 0 : memset(hash + 16, 0, 5);
461 :
462 0 : tds_encrypt_answer(hash, challenge, answer->nt_resp);
463 :
464 : /* with security is best be pedantic */
465 : memset(&ks, 0, sizeof(ks));
466 : memset(hash, 0, sizeof(hash));
467 : memset(ntlm2_challenge, 0, sizeof(ntlm2_challenge));
468 0 : return res;
469 : }
470 :
471 :
472 : /*
473 : * takes a 21 byte array and treats it as 3 56-bit DES keys. The
474 : * 8 byte plaintext is encrypted with each key and the resulting 24
475 : * bytes are stored in the results array.
476 : */
477 : static void
478 0 : tds_encrypt_answer(const unsigned char *hash, const unsigned char *challenge, unsigned char *answer)
479 : {
480 : DES_KEY ks;
481 :
482 0 : tds_convert_key(hash, &ks);
483 0 : tds_des_ecb_encrypt(challenge, 8, &ks, answer);
484 :
485 0 : tds_convert_key(&hash[7], &ks);
486 0 : tds_des_ecb_encrypt(challenge, 8, &ks, &answer[8]);
487 :
488 0 : tds_convert_key(&hash[14], &ks);
489 0 : tds_des_ecb_encrypt(challenge, 8, &ks, &answer[16]);
490 :
491 : memset(&ks, 0, sizeof(ks));
492 0 : }
493 :
494 :
495 : /*
496 : * turns a 56 bit key into the 64 bit, odd parity key and sets the key.
497 : * The key schedule ks is also set.
498 : */
499 : static void
500 0 : tds_convert_key(const unsigned char *key_56, DES_KEY * ks)
501 : {
502 : des_cblock key;
503 :
504 0 : key[0] = key_56[0];
505 0 : key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
506 0 : key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
507 0 : key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
508 0 : key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
509 0 : key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
510 0 : key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
511 0 : key[7] = (key_56[6] << 1) & 0xFF;
512 :
513 0 : tds_des_set_odd_parity(key);
514 0 : tds_des_set_key(ks, key);
515 :
516 : memset(&key, 0, sizeof(key));
517 0 : }
518 :
519 : /**
520 : * RC4 encryption, used to encrypt NTLM exported session key.
521 : * @param key encryption key
522 : * @param key_len encryption key length
523 : * @param in data to encrypt
524 : * @param len length of data
525 : * @param out output buffer, len bytes
526 : */
527 : static void
528 788 : tds_rc4(const unsigned char *key, size_t key_len, const unsigned char *in, size_t len, unsigned char *out)
529 : {
530 : unsigned char s[256], t;
531 : unsigned int i, j;
532 : size_t n;
533 :
534 202516 : for (i = 0; i < 256; ++i)
535 201728 : s[i] = (unsigned char) i;
536 201728 : for (i = j = 0; i < 256; ++i) {
537 201728 : j = (j + s[i] + key[i % key_len]) & 0xff;
538 201728 : t = s[i];
539 201728 : s[i] = s[j];
540 201728 : s[j] = t;
541 : }
542 12608 : for (i = j = 0, n = 0; n < len; ++n) {
543 12608 : i = (i + 1) & 0xff;
544 12608 : j = (j + s[i]) & 0xff;
545 12608 : t = s[i];
546 12608 : s[i] = s[j];
547 12608 : s[j] = t;
548 12608 : out[n] = in[n] ^ s[(s[i] + s[j]) & 0xff];
549 : }
550 : memset(s, 0, sizeof(s));
551 788 : }
552 :
553 : /**
554 : * Compute NTLM message integrity code.
555 : * MIC = HMAC_MD5(ExportedSessionKey, NEGOTIATE_MESSAGE + CHALLENGE_MESSAGE + AUTHENTICATE_MESSAGE)
556 : * where AUTHENTICATE_MESSAGE has the MIC field set to zero.
557 : * @return false on memory error
558 : */
559 : static bool
560 10 : tds_ntlm_mic(const unsigned char key[16], const unsigned char *negotiate, size_t negotiate_len,
561 : const unsigned char *challenge, size_t challenge_len, const unsigned char *authenticate, size_t authenticate_len,
562 : unsigned char mic[16])
563 : {
564 : unsigned char *buf;
565 10 : size_t len = negotiate_len + challenge_len + authenticate_len;
566 :
567 10 : buf = tds_new(unsigned char, len);
568 :
569 10 : if (!buf)
570 : return false;
571 10 : memcpy(buf, negotiate, negotiate_len);
572 10 : memcpy(buf + negotiate_len, challenge, challenge_len);
573 10 : memcpy(buf + negotiate_len + challenge_len, authenticate, authenticate_len);
574 10 : hmac_md5(key, buf, len, mic);
575 : memset(buf, 0, len);
576 10 : free(buf);
577 10 : return true;
578 : }
579 :
580 : /**
581 : * Fill a field (length, maximum length and offset) of a NTLM message header and copy its data in the payload.
582 : * @param msg message buffer
583 : * @param field_pos position of the field in the header
584 : * @param data_pos position of data in the payload, updated
585 : * @param data field data
586 : * @param len field data length
587 : */
588 : static void
589 4668 : put_ntlm_field(unsigned char *msg, size_t field_pos, size_t *data_pos, const void *data, size_t len)
590 : {
591 4668 : TDS_PUT_UA2LE(msg + field_pos, len);
592 4668 : TDS_PUT_UA2LE(msg + field_pos + 2, len);
593 4668 : TDS_PUT_UA4LE(msg + field_pos + 4, *data_pos);
594 4668 : memcpy(msg + *data_pos, data, len);
595 4668 : *data_pos += len;
596 4668 : }
597 :
598 : /**
599 : * Send AUTHENTICATE_MESSAGE.
600 : * @param challenge server challenge (8 bytes)
601 : * @param flags negotiate flags from server
602 : * @param names_blob NTLMv2 client blob, NULL if not available
603 : * @param names_blob_len length of names_blob
604 : * @param use_mic add message integrity code, names_blob must have MsvAvFlags with MIC bit set
605 : */
606 : static TDSRET
607 778 : tds7_send_auth(TDSSOCKET *tds, TDSNTLMAUTH *auth, const unsigned char *challenge, uint32_t flags,
608 : const unsigned char *names_blob, int names_blob_len, bool use_mic)
609 : {
610 : TDSANSWER answer;
611 :
612 : /* FIXME: stuff duplicate in tds7_send_login */
613 : const char *domain;
614 : const char *user_name;
615 : const char *host_name;
616 : const char *p;
617 : char *convert_buffer;
618 : size_t user_name_len, host_name_len, domain_len;
619 : TDSRET rc;
620 :
621 778 : unsigned char *ntlm_v2_response = NULL;
622 778 : unsigned int ntlm_response_len = 24;
623 778 : const unsigned int lm_response_len = 24;
624 778 : unsigned int session_key_len = 0;
625 : unsigned char exported_key[16], encrypted_key[16];
626 : unsigned char *msg;
627 : size_t header_len, msg_len, data_pos;
628 :
629 778 : TDSLOGIN *login = tds->login;
630 :
631 : /* check connection */
632 778 : if (!login)
633 : return TDS_FAIL;
634 :
635 : /* parse a bit of config */
636 1556 : user_name = tds_dstr_cstr(&login->user_name);
637 1556 : user_name_len = tds_dstr_len(&login->user_name);
638 1556 : host_name = tds_dstr_cstr(&login->client_host_name);
639 1556 : host_name_len = tds_dstr_len(&login->client_host_name);
640 :
641 : /* convert strings */
642 778 : convert_buffer = tds_new(char, (user_name_len + host_name_len) * 2);
643 778 : if (!convert_buffer)
644 : return TDS_FAIL;
645 :
646 778 : user_name_len = convert_to_usc2le_string(tds, user_name, user_name_len, convert_buffer);
647 778 : user_name = convert_buffer;
648 778 : if (user_name_len != (size_t) -1) {
649 778 : host_name_len = convert_to_usc2le_string(tds, host_name, host_name_len, convert_buffer + user_name_len);
650 778 : host_name = convert_buffer + user_name_len;
651 : }
652 778 : if (user_name_len == (size_t) -1 || host_name_len == (size_t) -1) {
653 0 : free(convert_buffer);
654 0 : return TDS_FAIL;
655 : }
656 :
657 : /* parse domain\username */
658 : p = user_name;
659 : for (;;) {
660 11670 : if (p >= user_name + user_name_len) {
661 0 : free(convert_buffer);
662 0 : return TDS_FAIL;
663 : }
664 6224 : if (p[0] == '\\' && p[1] == 0)
665 : break;
666 5446 : p += 2;
667 : }
668 :
669 778 : domain = user_name;
670 778 : domain_len = p - user_name;
671 :
672 778 : user_name = p + 2;
673 778 : user_name_len = domain + user_name_len - user_name;
674 :
675 778 : rc = tds_answer_challenge(tds, login, challenge, &flags, names_blob, names_blob_len, &answer, &ntlm_v2_response);
676 778 : if (TDS_FAILED(rc)) {
677 0 : free(convert_buffer);
678 0 : return rc;
679 : }
680 :
681 778 : ntlm_response_len = ntlm_v2_response ? 16 + names_blob_len : 24;
682 :
683 : /*
684 : * compute exported session key, encrypting a random one if key exchange was negotiated;
685 : * key exchange is done only if signing or sealing is negotiated too (MS-NLMP 3.1.5.1.2)
686 : */
687 778 : if (answer.has_session_key) {
688 778 : if ((flags & NTLMSSP_NEGOTIATE_KEY_EXCH) != 0 && (flags & (NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL)) != 0) {
689 778 : tds_random_buffer(exported_key, sizeof(exported_key));
690 778 : tds_rc4(answer.session_key, sizeof(answer.session_key), exported_key, sizeof(exported_key), encrypted_key);
691 1556 : session_key_len = sizeof(encrypted_key);
692 : } else {
693 0 : memcpy(exported_key, answer.session_key, sizeof(exported_key));
694 : }
695 : } else {
696 0 : flags &= ~NTLMSSP_NEGOTIATE_KEY_EXCH;
697 0 : if (use_mic) {
698 0 : free(ntlm_v2_response);
699 0 : free(convert_buffer);
700 0 : return TDS_FAIL;
701 : }
702 : }
703 :
704 778 : if (use_mic) {
705 : /* MIC requires Version field, server sent a timestamp, LmChallengeResponse should be zero */
706 0 : header_len = NTLM_AUTH_HEADER_MIC_LEN;
707 0 : flags |= NTLMSSP_NEGOTIATE_VERSION;
708 0 : memset(answer.lm_resp, 0, sizeof(answer.lm_resp));
709 : } else {
710 778 : header_len = NTLM_AUTH_HEADER_LEN;
711 778 : flags &= ~NTLMSSP_NEGOTIATE_VERSION;
712 : }
713 :
714 778 : msg_len = header_len + domain_len + user_name_len + host_name_len + lm_response_len + ntlm_response_len + session_key_len;
715 778 : msg = tds_new0(unsigned char, msg_len);
716 :
717 778 : if (!msg) {
718 0 : if (ntlm_v2_response) {
719 0 : memset(ntlm_v2_response, 0, ntlm_response_len);
720 0 : free(ntlm_v2_response);
721 : }
722 : memset(&answer, 0, sizeof(answer));
723 0 : free(convert_buffer);
724 0 : return TDS_FAIL;
725 : }
726 :
727 778 : memcpy(msg, ntlm_id, 8);
728 778 : TDS_PUT_UA4LE(msg + 8, 3); /* sequence 3 */
729 :
730 778 : data_pos = header_len;
731 : /* Target Name - domain or server name */
732 778 : put_ntlm_field(msg, 28, &data_pos, domain, domain_len);
733 778 : put_ntlm_field(msg, 36, &data_pos, user_name, user_name_len);
734 : /* Workstation Name */
735 778 : put_ntlm_field(msg, 44, &data_pos, host_name, host_name_len);
736 : /* LM/LMv2 Response */
737 778 : put_ntlm_field(msg, 12, &data_pos, answer.lm_resp, lm_response_len);
738 : /* NTLM/NTLMv2 Response */
739 778 : put_ntlm_field(msg, 20, &data_pos, ntlm_v2_response ? ntlm_v2_response : answer.nt_resp, ntlm_response_len);
740 : /* Encrypted Random Session Key */
741 778 : put_ntlm_field(msg, 52, &data_pos, encrypted_key, session_key_len);
742 :
743 778 : TDS_PUT_UA4LE(msg + 60, flags);
744 :
745 778 : if (use_mic) {
746 : /* same version we sent in NEGOTIATE_MESSAGE */
747 0 : memcpy(msg + 64, auth->tds_auth.packet + 32, 8);
748 0 : if (!tds_ntlm_mic(exported_key, auth->tds_auth.packet, auth->tds_auth.packet_len,
749 0 : auth->challenge, auth->challenge_len, msg, msg_len, msg + NTLM_AUTH_MIC_OFFSET))
750 : rc = TDS_FAIL;
751 : }
752 :
753 : if (TDS_SUCCEED(rc)) {
754 778 : tds->out_flag = TDS7_AUTH;
755 778 : tds_put_n(tds, msg, msg_len);
756 : }
757 :
758 : /* for security reason clear sensitive data */
759 778 : if (ntlm_v2_response) {
760 778 : memset(ntlm_v2_response, 0, ntlm_response_len);
761 778 : free(ntlm_v2_response);
762 : }
763 778 : memset(&answer, 0, sizeof(answer));
764 778 : memset(exported_key, 0, sizeof(exported_key));
765 778 : memset(encrypted_key, 0, sizeof(encrypted_key));
766 : memset(msg, 0, msg_len);
767 778 : free(msg);
768 778 : free(convert_buffer);
769 :
770 778 : if (TDS_FAILED(rc))
771 : return rc;
772 778 : return tds_flush_packet(tds);
773 : }
774 :
775 : static TDSRET
776 778 : tds_ntlm_free(TDSCONNECTION *conn TDS_UNUSED, TDSAUTHENTICATION *tds_auth)
777 : {
778 778 : TDSNTLMAUTH *auth = (TDSNTLMAUTH *) tds_auth;
779 :
780 778 : free(auth->tds_auth.packet);
781 778 : free(auth->spn);
782 778 : free(auth->challenge);
783 778 : free(auth);
784 :
785 778 : return TDS_SUCCESS;
786 : }
787 :
788 : /**
789 : * put a 8 byte filetime from a time_t
790 : * This takes GMT as input
791 : */
792 : static void
793 : unix_to_nt_time(uint64_t * nt, struct timeval *tv)
794 : {
795 : /* C time start on 1970, nt time on 1600 */
796 : #define TIME_FIXUP_CONSTANT (((uint64_t) 134774U) * 86400U)
797 :
798 : uint64_t t2;
799 :
800 808 : t2 = tv->tv_sec;
801 808 : t2 += TIME_FIXUP_CONSTANT;
802 808 : t2 *= 1000u * 1000u * 10u;
803 808 : t2 += tv->tv_usec * 10u;
804 :
805 808 : *nt = t2;
806 : }
807 :
808 : /**
809 : * Compute channel binding token (MD5 of gss_channel_bindings_struct).
810 : * @param app_data channel binding application data, like "tls-unique:" followed by data
811 : * @param app_data_len application data length
812 : * @param cbt output token
813 : */
814 : static void
815 798 : tds_calc_cbt(const void *app_data, size_t app_data_len, unsigned char cbt[16])
816 : {
817 : MD5_CTX md5_ctx;
818 : unsigned char channel_binding_struct[20];
819 :
820 : /* Build channel binding structure */
821 : /* initiator_address: 8 bytes of zeros */
822 : /* acceptor_address: 8 bytes of zeros */
823 : /* application_data: 4 bytes length (little endian) + data */
824 798 : memset(channel_binding_struct, 0, sizeof(channel_binding_struct));
825 798 : TDS_PUT_UA4LE(channel_binding_struct + 16, app_data_len);
826 :
827 : /* Calculate MD5 hash */
828 798 : MD5Init(&md5_ctx);
829 798 : MD5Update(&md5_ctx, channel_binding_struct, sizeof(channel_binding_struct));
830 798 : MD5Update(&md5_ctx, app_data, app_data_len);
831 798 : MD5Final(&md5_ctx, cbt);
832 798 : }
833 :
834 : static void
835 778 : get_cbt(TDSSOCKET *tds, TDSNTLMAUTH *auth)
836 : {
837 : unsigned char app_data[256];
838 : size_t app_data_len;
839 :
840 778 : app_data_len = tds_ssl_get_cb(tds->conn, app_data, sizeof(app_data));
841 778 : if (app_data_len == 0)
842 0 : return;
843 :
844 778 : tdsdump_dump_buf(TDS_DBG_INFO1, "Channel Binding application data", app_data, app_data_len);
845 778 : tds_calc_cbt(app_data, app_data_len, auth->cbt);
846 778 : auth->has_cbt = true;
847 778 : tdsdump_dump_buf(TDS_DBG_INFO1, "Channel Binding Token", auth->cbt, 16);
848 : }
849 :
850 : /**
851 : * Compute the service principal name to send to the server.
852 : * SQL Server checks it when Extended Protection is enabled.
853 : */
854 : static void
855 778 : get_spn(TDSSOCKET *tds, TDSNTLMAUTH *auth)
856 : {
857 : char *spn;
858 : size_t spn_len;
859 :
860 778 : spn = tds_get_spn(tds);
861 778 : if (!spn)
862 : return;
863 :
864 778 : tdsdump_log(TDS_DBG_INFO1, "NTLM target name %s\n", spn);
865 778 : spn_len = strlen(spn);
866 778 : auth->spn = tds_new(char, spn_len * 2);
867 :
868 778 : if (auth->spn) {
869 778 : auth->spn_len = convert_to_usc2le_string(tds, spn, spn_len, auth->spn);
870 : /* AvLen is 16 bit */
871 778 : if (auth->spn_len == (size_t) -1 || auth->spn_len > 0xfff0) {
872 0 : free(auth->spn);
873 0 : auth->spn = NULL;
874 0 : auth->spn_len = 0;
875 : }
876 : }
877 778 : free(spn);
878 : }
879 :
880 : /**
881 : * Add an AV_PAIR to target_info in names_blob.
882 : * target_info is at the end of names_blob and ends with a MsvAvEOL terminator.
883 : * @param names_blob names_blob buffer, must have space for the new pair
884 : * @param names_blob_len current length (will be updated)
885 : * @param av_id AvId of the new pair
886 : * @param data data of the new pair
887 : * @param data_len length of data
888 : */
889 : static void
890 1586 : add_av_pair(unsigned char *names_blob, int *names_blob_len, uint16_t av_id, const void *data, size_t data_len)
891 : {
892 : /* The -4 is to override the old terminator */
893 1586 : unsigned char *av_pair = names_blob + *names_blob_len - 4;
894 :
895 1586 : TDS_PUT_UA2LE(av_pair, av_id);
896 1586 : TDS_PUT_UA2LE(av_pair + 2, data_len);
897 1586 : memcpy(av_pair + 4, data, data_len);
898 1586 : memset(av_pair + 4 + data_len, 0, 4); /* Terminator */
899 :
900 1586 : *names_blob_len += 4 + (int) data_len;
901 1586 : }
902 :
903 : /**
904 : * Add channel binding token (CBT) and target name AV_PAIRs to target_info in names_blob
905 : * @param auth NTLM authentication data
906 : * @param names_blob names_blob buffer
907 : * @param names_blob_len current length (will be updated)
908 : */
909 : static void
910 808 : add_av_pairs(TDSNTLMAUTH *auth, unsigned char *names_blob, int *names_blob_len)
911 : {
912 808 : if (auth->has_cbt)
913 788 : add_av_pair(names_blob, names_blob_len, MSV_AV_CHANNEL_BINDINGS, auth->cbt, sizeof(auth->cbt));
914 808 : if (auth->spn)
915 788 : add_av_pair(names_blob, names_blob_len, MSV_AV_TARGET_NAME, auth->spn, auth->spn_len);
916 :
917 808 : tdsdump_dump_buf(TDS_DBG_INFO1, "New names_blob\n", names_blob, *names_blob_len);
918 808 : }
919 :
920 : static void
921 808 : fill_names_blob_prefix(names_blob_prefix_t * prefix)
922 : {
923 : struct timeval tv;
924 808 : uint64_t nttime = 0;
925 :
926 808 : gettimeofday(&tv, NULL);
927 808 : unix_to_nt_time(&nttime, &tv);
928 :
929 808 : prefix->response_type = 0x01;
930 808 : prefix->max_response_type = 0x01;
931 808 : prefix->reserved1 = 0x0000;
932 808 : prefix->reserved2 = 0x00000000;
933 : #ifdef WORDS_BIGENDIAN
934 : tds_swap_bytes(&nttime, 8);
935 : #endif
936 808 : prefix->timestamp = nttime;
937 808 : tds_random_buffer(prefix->challenge, sizeof(prefix->challenge));
938 :
939 808 : prefix->reserved3 = 0x00000000;
940 808 : }
941 :
942 : /**
943 : * Build NTLMv2 client blob (names_blob) from server target information.
944 : * Server AV_PAIRs are kept, MsvAvFlags (if MIC is used), channel binding token and
945 : * target name are added. The server timestamp, if present, is used.
946 : * @param auth NTLM authentication data
947 : * @param target_info target information from CHALLENGE_MESSAGE
948 : * @param target_info_len length of target_info
949 : * @param mic_allowed whether we can provide a MIC
950 : * @param p_names_blob output names_blob, to be freed
951 : * @param p_names_blob_len output length of names_blob
952 : * @param p_use_mic output, whether MIC should be sent
953 : */
954 : static TDSRET
955 828 : build_names_blob(TDSNTLMAUTH *auth, const unsigned char *target_info, size_t target_info_len, bool mic_allowed,
956 : unsigned char **p_names_blob, int *p_names_blob_len, bool *p_use_mic)
957 : {
958 828 : const unsigned char *timestamp = NULL;
959 828 : size_t flags_pos = 0, pos = 0, pairs_len, alloc_len;
960 828 : const size_t prefix_len = TDS_OFFSET(names_blob_prefix_t, target_info);
961 : unsigned char *names_blob;
962 : int names_blob_len;
963 : bool use_mic;
964 :
965 : /* parse AV_PAIRs, checking they are well formed */
966 3212 : for (;;) {
967 : unsigned int av_id, av_len;
968 :
969 4040 : if (target_info_len - pos < 4)
970 : return TDS_FAIL;
971 4030 : av_id = TDS_GET_UA2LE(target_info + pos);
972 4030 : av_len = TDS_GET_UA2LE(target_info + pos + 2);
973 4030 : if (av_id == MSV_AV_EOL)
974 : break;
975 3222 : if (target_info_len - pos - 4 < av_len)
976 : return TDS_FAIL;
977 3212 : if (av_id == MSV_AV_TIMESTAMP && av_len == 8)
978 20 : timestamp = target_info + pos + 4;
979 3212 : if (av_id == MSV_AV_FLAGS && av_len == 4)
980 0 : flags_pos = pos + 4;
981 3212 : pos += 4 + av_len;
982 : }
983 808 : pairs_len = pos;
984 :
985 : /* MIC should be provided if server sent a timestamp */
986 808 : use_mic = mic_allowed && timestamp != NULL;
987 :
988 : /* prefix + pairs + MsvAvFlags + CBT + target name + MsvAvEOL + Z(4) */
989 808 : alloc_len = prefix_len + pairs_len + 8 + AV_PAIR_CBT_BYTES + 4 + auth->spn_len + 4 + 4;
990 808 : names_blob = tds_new0(unsigned char, alloc_len);
991 :
992 808 : if (!names_blob)
993 : return TDS_FAIL;
994 :
995 808 : fill_names_blob_prefix((names_blob_prefix_t *) names_blob);
996 808 : if (timestamp)
997 20 : memcpy(names_blob + TDS_OFFSET(names_blob_prefix_t, timestamp), timestamp, 8);
998 :
999 : /* copy server AV_PAIRs, the terminator is already zeroed */
1000 808 : memcpy(names_blob + prefix_len, target_info, pairs_len);
1001 808 : names_blob_len = (int) (prefix_len + pairs_len + 4);
1002 :
1003 808 : if (use_mic) {
1004 10 : if (flags_pos) {
1005 0 : unsigned char *p = names_blob + prefix_len + flags_pos;
1006 :
1007 0 : TDS_PUT_UA4LE(p, TDS_GET_UA4LE(p) | MSV_AV_FLAG_MIC);
1008 : } else {
1009 : unsigned char av_flags[4];
1010 :
1011 10 : TDS_PUT_UA4LE(av_flags, MSV_AV_FLAG_MIC);
1012 10 : add_av_pair(names_blob, &names_blob_len, MSV_AV_FLAGS, av_flags, sizeof(av_flags));
1013 : }
1014 : }
1015 :
1016 : /* Add channel binding token (CBT) and target name AV_PAIRs */
1017 808 : add_av_pairs(auth, names_blob, &names_blob_len);
1018 :
1019 : /* blob ends with Z(4) after AV_PAIRs, already zeroed */
1020 808 : names_blob_len += 4;
1021 :
1022 808 : *p_names_blob = names_blob;
1023 808 : *p_names_blob_len = names_blob_len;
1024 808 : *p_use_mic = use_mic;
1025 808 : return TDS_SUCCESS;
1026 : }
1027 :
1028 : static TDSRET
1029 778 : tds_ntlm_handle_next(TDSSOCKET *tds, TDSAUTHENTICATION *tds_auth, size_t len)
1030 : {
1031 778 : TDSNTLMAUTH *auth = (TDSNTLMAUTH *) tds_auth;
1032 : const unsigned char *msg;
1033 : uint32_t flags;
1034 : size_t data_block_offset;
1035 :
1036 778 : int names_blob_len = 0;
1037 778 : unsigned char *names_blob = NULL;
1038 778 : bool use_mic = false;
1039 :
1040 : TDSRET rc;
1041 :
1042 : /* at least 32 bytes (till context) */
1043 778 : if (len < 32 || len > 0xffff)
1044 : return TDS_FAIL;
1045 :
1046 : /* read the entire CHALLENGE_MESSAGE, it is needed to compute MIC */
1047 778 : free(auth->challenge);
1048 778 : auth->challenge_len = 0;
1049 778 : auth->challenge = tds_new(unsigned char, len);
1050 :
1051 778 : if (!auth->challenge)
1052 : return TDS_FAIL;
1053 778 : if (!tds_get_n(tds, auth->challenge, len))
1054 : return TDS_FAIL;
1055 778 : auth->challenge_len = len;
1056 778 : msg = auth->challenge;
1057 :
1058 778 : if (memcmp(msg, ntlm_id, 8) != 0)
1059 : return TDS_FAIL;
1060 778 : if (TDS_GET_UA4LE(msg + 8) != 2) /* sequence -> 2 */
1061 : return TDS_FAIL;
1062 778 : data_block_offset = TDS_GET_UA4LE(msg + 16); /* domain offset */
1063 778 : flags = TDS_GET_UA4LE(msg + 20);
1064 778 : tdsdump_dump_buf(TDS_DBG_INFO1, "TDS_AUTH_TOKEN nonce", msg + 24, 8);
1065 :
1066 : /* Version 1 -- The Context, Target Information, and OS Version structure are all omitted */
1067 : /* Version 2 -- The Context and Target Information fields are present, but the OS Version structure is not. */
1068 778 : if (data_block_offset >= 48 && len >= 48) {
1069 : size_t target_info_len, target_info_offset;
1070 :
1071 778 : target_info_len = TDS_GET_UA2LE(msg + 40);
1072 778 : target_info_offset = TDS_GET_UA4LE(msg + 44);
1073 :
1074 : /* read Target Info if possible */
1075 778 : if (target_info_len > 0 && target_info_offset >= 48 && target_info_offset <= len
1076 778 : && target_info_len <= len - target_info_offset) {
1077 778 : rc = build_names_blob(auth, msg + target_info_offset, target_info_len, tds->login->use_ntlmv2,
1078 : &names_blob, &names_blob_len, &use_mic);
1079 778 : if (TDS_FAILED(rc))
1080 : return rc;
1081 : }
1082 : }
1083 :
1084 778 : rc = tds7_send_auth(tds, auth, msg + 24, flags, names_blob, names_blob_len, use_mic);
1085 :
1086 778 : if (names_blob) {
1087 778 : memset(names_blob, 0, names_blob_len);
1088 778 : free(names_blob);
1089 : }
1090 :
1091 : return rc;
1092 : }
1093 :
1094 : /**
1095 : * Build a NTLMSPP packet to send to server
1096 : * @param tds A pointer to the TDSSOCKET structure managing a client/server operation.
1097 : * @return authentication info
1098 : */
1099 : TDSAUTHENTICATION *
1100 778 : tds_ntlm_get_auth(TDSSOCKET * tds)
1101 : {
1102 : const char *domain;
1103 : const char *user_name;
1104 : const char *p;
1105 : uint8_t *packet;
1106 : int host_name_len;
1107 : int domain_len;
1108 : int auth_len;
1109 : uint32_t flags;
1110 : TDSNTLMAUTH *auth;
1111 :
1112 778 : if (!tds->login)
1113 : return NULL;
1114 :
1115 1556 : user_name = tds_dstr_cstr(&tds->login->user_name);
1116 1556 : host_name_len = (int)tds_dstr_len(&tds->login->client_host_name);
1117 :
1118 : /* check override of domain */
1119 778 : if ((p = strchr(user_name, '\\')) == NULL)
1120 : return NULL;
1121 :
1122 778 : domain = user_name;
1123 778 : domain_len = (int) (p - user_name);
1124 :
1125 778 : auth = tds_new0(TDSNTLMAUTH, 1);
1126 :
1127 778 : if (!auth)
1128 : return NULL;
1129 :
1130 778 : auth->tds_auth.free = tds_ntlm_free;
1131 778 : auth->tds_auth.handle_next = tds_ntlm_handle_next;
1132 :
1133 778 : auth->tds_auth.packet_len = auth_len = 40 + host_name_len + domain_len;
1134 778 : auth->tds_auth.packet = packet = tds_new(uint8_t, auth_len);
1135 778 : if (!packet) {
1136 0 : free(auth);
1137 0 : return NULL;
1138 : }
1139 :
1140 : /* built NTLMSSP authentication packet */
1141 778 : memcpy(packet, ntlm_id, 8);
1142 : /* sequence 1 client -> server */
1143 778 : TDS_PUT_A4(packet + 8, TDS_HOST4LE(1));
1144 : /* flags */
1145 : /* key exchange requires signing (we don't sign messages, TDS uses TLS for integrity) */
1146 778 : flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_NTLM
1147 : | NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED | NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED
1148 : | NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
1149 : | NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_KEY_EXCH | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_VERSION;
1150 : /* no domain, like using an user principal name ("\\user@domain"), Windows rejects the flag with an empty domain */
1151 778 : if (domain_len == 0)
1152 0 : flags &= ~NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED;
1153 778 : TDS_PUT_A4(packet + 12, TDS_HOST4LE(flags));
1154 :
1155 : /* domain info */
1156 778 : TDS_PUT_A2LE(packet + 16, domain_len);
1157 778 : TDS_PUT_A2LE(packet + 18, domain_len);
1158 778 : TDS_PUT_A4LE(packet + 20, 40 + host_name_len);
1159 :
1160 : /* hostname info */
1161 778 : TDS_PUT_A2LE(packet + 24, host_name_len);
1162 778 : TDS_PUT_A2LE(packet + 26, host_name_len);
1163 778 : TDS_PUT_A4 (packet + 28, TDS_HOST4LE(40));
1164 :
1165 : /*
1166 : * Version: product major and minor version, build number (16 bit),
1167 : * 3 reserved bytes and NTLM revision (15).
1168 : * Report Windows 10.0 build 20348 (Windows Server 2022), it's informational only.
1169 : */
1170 778 : packet[32] = 10;
1171 778 : packet[33] = 0;
1172 778 : TDS_PUT_A2LE(packet + 34, 20348);
1173 778 : TDS_PUT_A4(packet + 36, TDS_HOST4LE(0x0f000000));
1174 :
1175 : /* hostname and domain */
1176 1556 : memcpy(packet + 40, tds_dstr_cstr(&tds->login->client_host_name), host_name_len);
1177 778 : memcpy(packet + 40 + host_name_len, domain, domain_len);
1178 :
1179 778 : get_cbt(tds, auth);
1180 778 : get_spn(tds, auth);
1181 :
1182 778 : return (TDSAUTHENTICATION *) auth;
1183 : }
1184 :
1185 : /** @} */
1186 :
|