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 :
|