NCBI C++ ToolKit
challenge.c
Go to the documentation of this file.

Go to the SVN repository for this file.

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