ntlm.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 
23 #include "curl_setup.h"
24 
25 #if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI)
26 
27 /*
28  * NTLM details:
29  *
30  * https://davenport.sourceforge.io/ntlm.html
31  * https://www.innovation.ch/java/ntlm.html
32  */
33 
34 #define DEBUG_ME 0
35 
36 #include "urldata.h"
37 #include "non-ascii.h"
38 #include "sendf.h"
39 #include "curl_base64.h"
40 #include "curl_ntlm_core.h"
41 #include "curl_gethostname.h"
42 #include "curl_multibyte.h"
43 #include "warnless.h"
44 #include "rand.h"
45 #include "vtls/vtls.h"
46 
47 /* SSL backend-specific #if branches in this file must be kept in the order
48  documented in curl_ntlm_core. */
49 #if defined(NTLM_NEEDS_NSS_INIT)
50 #include "vtls/nssg.h" /* for Curl_nss_force_init() */
51 #endif
52 
53 #define BUILDING_CURL_NTLM_MSGS_C
54 #include "vauth/vauth.h"
55 #include "vauth/ntlm.h"
56 #include "curl_endian.h"
57 #include "curl_printf.h"
58 
59 /* The last #include files should be: */
60 #include "curl_memory.h"
61 #include "memdebug.h"
62 
63 /* "NTLMSSP" signature is always in ASCII regardless of the platform */
64 #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
65 
66 #define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
67 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8) & 0xff), \
68  (((x) >> 16) & 0xff), (((x) >> 24) & 0xff)
69 
70 #if DEBUG_ME
71 # define DEBUG_OUT(x) x
72 static void ntlm_print_flags(FILE *handle, unsigned long flags)
73 {
74  if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
75  fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
76  if(flags & NTLMFLAG_NEGOTIATE_OEM)
77  fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
78  if(flags & NTLMFLAG_REQUEST_TARGET)
79  fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
80  if(flags & (1<<3))
81  fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
82  if(flags & NTLMFLAG_NEGOTIATE_SIGN)
83  fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
84  if(flags & NTLMFLAG_NEGOTIATE_SEAL)
85  fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
86  if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
87  fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
88  if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
89  fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
90  if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
91  fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
92  if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
93  fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
94  if(flags & (1<<10))
95  fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
96  if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS)
97  fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS ");
98  if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
99  fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
100  if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
101  fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
102  if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
103  fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
104  if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
105  fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
106  if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
107  fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
108  if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
109  fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
110  if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
111  fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
112  if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
113  fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
114  if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
115  fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
116  if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
117  fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
118  if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
119  fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
120  if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
121  fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
122  if(flags & (1<<24))
123  fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
124  if(flags & (1<<25))
125  fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
126  if(flags & (1<<26))
127  fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
128  if(flags & (1<<27))
129  fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
130  if(flags & (1<<28))
131  fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
132  if(flags & NTLMFLAG_NEGOTIATE_128)
133  fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
134  if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
135  fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
136  if(flags & NTLMFLAG_NEGOTIATE_56)
137  fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
138 }
139 
140 static void ntlm_print_hex(FILE *handle, const char *buf, size_t len)
141 {
142  const char *p = buf;
143 
144  (void) handle;
145 
146  fprintf(stderr, "0x");
147  while(len-- > 0)
148  fprintf(stderr, "%02.2x", (unsigned int)*p++);
149 }
150 #else
151 # define DEBUG_OUT(x) Curl_nop_stmt
152 #endif
153 
154 /*
155  * ntlm_decode_type2_target()
156  *
157  * This is used to decode the "target info" in the NTLM type-2 message
158  * received.
159  *
160  * Parameters:
161  *
162  * data [in] - The session handle.
163  * buffer [in] - The decoded type-2 message.
164  * size [in] - The input buffer size, at least 32 bytes.
165  * ntlm [in/out] - The NTLM data struct being used and modified.
166  *
167  * Returns CURLE_OK on success.
168  */
169 static CURLcode ntlm_decode_type2_target(struct Curl_easy *data,
170  unsigned char *buffer,
171  size_t size,
172  struct ntlmdata *ntlm)
173 {
174  unsigned short target_info_len = 0;
175  unsigned int target_info_offset = 0;
176 
177 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
178  (void) data;
179 #endif
180 
181  if(size >= 48) {
182  target_info_len = Curl_read16_le(&buffer[40]);
183  target_info_offset = Curl_read32_le(&buffer[44]);
184  if(target_info_len > 0) {
185  if(((target_info_offset + target_info_len) > size) ||
186  (target_info_offset < 48)) {
187  infof(data, "NTLM handshake failure (bad type-2 message). "
188  "Target Info Offset Len is set incorrect by the peer\n");
190  }
191 
192  ntlm->target_info = malloc(target_info_len);
193  if(!ntlm->target_info)
194  return CURLE_OUT_OF_MEMORY;
195 
196  memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len);
197  }
198  }
199 
200  ntlm->target_info_len = target_info_len;
201 
202  return CURLE_OK;
203 }
204 
205 /*
206  NTLM message structure notes:
207 
208  A 'short' is a 'network short', a little-endian 16-bit unsigned value.
209 
210  A 'long' is a 'network long', a little-endian, 32-bit unsigned value.
211 
212  A 'security buffer' represents a triplet used to point to a buffer,
213  consisting of two shorts and one long:
214 
215  1. A 'short' containing the length of the buffer content in bytes.
216  2. A 'short' containing the allocated space for the buffer in bytes.
217  3. A 'long' containing the offset to the start of the buffer in bytes,
218  from the beginning of the NTLM message.
219 */
220 
221 /*
222  * Curl_auth_is_ntlm_supported()
223  *
224  * This is used to evaluate if NTLM is supported.
225  *
226  * Parameters: None
227  *
228  * Returns TRUE as NTLM as handled by libcurl.
229  */
230 bool Curl_auth_is_ntlm_supported(void)
231 {
232  return TRUE;
233 }
234 
235 /*
236  * Curl_auth_decode_ntlm_type2_message()
237  *
238  * This is used to decode an already encoded NTLM type-2 message. The message
239  * is first decoded from a base64 string into a raw NTLM message and checked
240  * for validity before the appropriate data for creating a type-3 message is
241  * written to the given NTLM data structure.
242  *
243  * Parameters:
244  *
245  * data [in] - The session handle.
246  * type2msg [in] - The base64 encoded type-2 message.
247  * ntlm [in/out] - The NTLM data struct being used and modified.
248  *
249  * Returns CURLE_OK on success.
250  */
251 CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
252  const char *type2msg,
253  struct ntlmdata *ntlm)
254 {
255  static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
256 
257  /* NTLM type-2 message structure:
258 
259  Index Description Content
260  0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
261  (0x4e544c4d53535000)
262  8 NTLM Message Type long (0x02000000)
263  12 Target Name security buffer
264  20 Flags long
265  24 Challenge 8 bytes
266  (32) Context 8 bytes (two consecutive longs) (*)
267  (40) Target Information security buffer (*)
268  (48) OS Version Structure 8 bytes (*)
269  32 (48) (56) Start of data block (*)
270  (*) -> Optional
271  */
272 
274  unsigned char *type2 = NULL;
275  size_t type2_len = 0;
276 
277 #if defined(NTLM_NEEDS_NSS_INIT)
278  /* Make sure the crypto backend is initialized */
279  result = Curl_nss_force_init(data);
280  if(result)
281  return result;
282 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
283  (void)data;
284 #endif
285 
286  /* Decode the base-64 encoded type-2 message */
287  if(strlen(type2msg) && *type2msg != '=') {
288  result = Curl_base64_decode(type2msg, &type2, &type2_len);
289  if(result)
290  return result;
291  }
292 
293  /* Ensure we have a valid type-2 message */
294  if(!type2) {
295  infof(data, "NTLM handshake failure (empty type-2 message)\n");
297  }
298 
299  ntlm->flags = 0;
300 
301  if((type2_len < 32) ||
302  (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) ||
303  (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) {
304  /* This was not a good enough type-2 message */
305  free(type2);
306  infof(data, "NTLM handshake failure (bad type-2 message)\n");
308  }
309 
310  ntlm->flags = Curl_read32_le(&type2[20]);
311  memcpy(ntlm->nonce, &type2[24], 8);
312 
313  if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) {
314  result = ntlm_decode_type2_target(data, type2, type2_len, ntlm);
315  if(result) {
316  free(type2);
317  infof(data, "NTLM handshake failure (bad type-2 message)\n");
318  return result;
319  }
320  }
321 
322  DEBUG_OUT({
323  fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
324  ntlm_print_flags(stderr, ntlm->flags);
325  fprintf(stderr, "\n nonce=");
326  ntlm_print_hex(stderr, (char *)ntlm->nonce, 8);
327  fprintf(stderr, "\n****\n");
328  fprintf(stderr, "**** Header %s\n ", header);
329  });
330 
331  free(type2);
332 
333  return result;
334 }
335 
336 /* copy the source to the destination and fill in zeroes in every
337  other destination byte! */
338 static void unicodecpy(unsigned char *dest, const char *src, size_t length)
339 {
340  size_t i;
341  for(i = 0; i < length; i++) {
342  dest[2 * i] = (unsigned char)src[i];
343  dest[2 * i + 1] = '\0';
344  }
345 }
346 
347 /*
348  * Curl_auth_create_ntlm_type1_message()
349  *
350  * This is used to generate an already encoded NTLM type-1 message ready for
351  * sending to the recipient using the appropriate compile time crypto API.
352  *
353  * Parameters:
354  *
355  * data [in] - The session handle.
356  * userp [in] - The user name in the format User or Domain\User.
357  * passdwp [in] - The user's password.
358  * ntlm [in/out] - The NTLM data struct being used and modified.
359  * outptr [in/out] - The address where a pointer to newly allocated memory
360  * holding the result will be stored upon completion.
361  * outlen [out] - The length of the output message.
362  *
363  * Returns CURLE_OK on success.
364  */
365 CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
366  const char *userp,
367  const char *passwdp,
368  struct ntlmdata *ntlm,
369  char **outptr, size_t *outlen)
370 {
371  /* NTLM type-1 message structure:
372 
373  Index Description Content
374  0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
375  (0x4e544c4d53535000)
376  8 NTLM Message Type long (0x01000000)
377  12 Flags long
378  (16) Supplied Domain security buffer (*)
379  (24) Supplied Workstation security buffer (*)
380  (32) OS Version Structure 8 bytes (*)
381  (32) (40) Start of data block (*)
382  (*) -> Optional
383  */
384 
385  size_t size;
386 
387  unsigned char ntlmbuf[NTLM_BUFSIZE];
388  const char *host = ""; /* empty */
389  const char *domain = ""; /* empty */
390  size_t hostlen = 0;
391  size_t domlen = 0;
392  size_t hostoff = 0;
393  size_t domoff = hostoff + hostlen; /* This is 0: remember that host and
394  domain are empty */
395  (void)userp;
396  (void)passwdp;
397 
398  /* Clean up any former leftovers and initialise to defaults */
399  Curl_auth_ntlm_cleanup(ntlm);
400 
401 #if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION)
402 #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
403 #else
404 #define NTLM2FLAG 0
405 #endif
406  snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
407  NTLMSSP_SIGNATURE "%c"
408  "\x01%c%c%c" /* 32-bit type = 1 */
409  "%c%c%c%c" /* 32-bit NTLM flag field */
410  "%c%c" /* domain length */
411  "%c%c" /* domain allocated space */
412  "%c%c" /* domain name offset */
413  "%c%c" /* 2 zeroes */
414  "%c%c" /* host length */
415  "%c%c" /* host allocated space */
416  "%c%c" /* host name offset */
417  "%c%c" /* 2 zeroes */
418  "%s" /* host name */
419  "%s", /* domain string */
420  0, /* trailing zero */
421  0, 0, 0, /* part of type-1 long */
422 
423  LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
424  NTLMFLAG_REQUEST_TARGET |
425  NTLMFLAG_NEGOTIATE_NTLM_KEY |
426  NTLM2FLAG |
427  NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
428  SHORTPAIR(domlen),
429  SHORTPAIR(domlen),
430  SHORTPAIR(domoff),
431  0, 0,
432  SHORTPAIR(hostlen),
433  SHORTPAIR(hostlen),
434  SHORTPAIR(hostoff),
435  0, 0,
436  host, /* this is empty */
437  domain /* this is empty */);
438 
439  /* Initial packet length */
440  size = 32 + hostlen + domlen;
441 
442  DEBUG_OUT({
443  fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x "
444  "0x%08.8x ",
445  LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
446  NTLMFLAG_REQUEST_TARGET |
447  NTLMFLAG_NEGOTIATE_NTLM_KEY |
448  NTLM2FLAG |
449  NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
450  NTLMFLAG_NEGOTIATE_OEM |
451  NTLMFLAG_REQUEST_TARGET |
452  NTLMFLAG_NEGOTIATE_NTLM_KEY |
453  NTLM2FLAG |
454  NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
455  ntlm_print_flags(stderr,
456  NTLMFLAG_NEGOTIATE_OEM |
457  NTLMFLAG_REQUEST_TARGET |
458  NTLMFLAG_NEGOTIATE_NTLM_KEY |
459  NTLM2FLAG |
460  NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
461  fprintf(stderr, "\n****\n");
462  });
463 
464  /* Return with binary blob encoded into base64 */
465  return Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen);
466 }
467 
468 /*
469  * Curl_auth_create_ntlm_type3_message()
470  *
471  * This is used to generate an already encoded NTLM type-3 message ready for
472  * sending to the recipient using the appropriate compile time crypto API.
473  *
474  * Parameters:
475  *
476  * data [in] - The session handle.
477  * userp [in] - The user name in the format User or Domain\User.
478  * passdwp [in] - The user's password.
479  * ntlm [in/out] - The NTLM data struct being used and modified.
480  * outptr [in/out] - The address where a pointer to newly allocated memory
481  * holding the result will be stored upon completion.
482  * outlen [out] - The length of the output message.
483  *
484  * Returns CURLE_OK on success.
485  */
486 CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
487  const char *userp,
488  const char *passwdp,
489  struct ntlmdata *ntlm,
490  char **outptr, size_t *outlen)
491 
492 {
493  /* NTLM type-3 message structure:
494 
495  Index Description Content
496  0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
497  (0x4e544c4d53535000)
498  8 NTLM Message Type long (0x03000000)
499  12 LM/LMv2 Response security buffer
500  20 NTLM/NTLMv2 Response security buffer
501  28 Target Name security buffer
502  36 User Name security buffer
503  44 Workstation Name security buffer
504  (52) Session Key security buffer (*)
505  (60) Flags long (*)
506  (64) OS Version Structure 8 bytes (*)
507  52 (64) (72) Start of data block
508  (*) -> Optional
509  */
510 
511  CURLcode result = CURLE_OK;
512  size_t size;
513  unsigned char ntlmbuf[NTLM_BUFSIZE];
514  int lmrespoff;
515  unsigned char lmresp[24]; /* fixed-size */
516 #ifdef USE_NTRESPONSES
517  int ntrespoff;
518  unsigned int ntresplen = 24;
519  unsigned char ntresp[24]; /* fixed-size */
520  unsigned char *ptr_ntresp = &ntresp[0];
521  unsigned char *ntlmv2resp = NULL;
522 #endif
523  bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE;
524  char host[HOSTNAME_MAX + 1] = "";
525  const char *user;
526  const char *domain = "";
527  size_t hostoff = 0;
528  size_t useroff = 0;
529  size_t domoff = 0;
530  size_t hostlen = 0;
531  size_t userlen = 0;
532  size_t domlen = 0;
533 
534  user = strchr(userp, '\\');
535  if(!user)
536  user = strchr(userp, '/');
537 
538  if(user) {
539  domain = userp;
540  domlen = (user - domain);
541  user++;
542  }
543  else
544  user = userp;
545 
546  if(user)
547  userlen = strlen(user);
548 
549  /* Get the machine's un-qualified host name as NTLM doesn't like the fully
550  qualified domain name */
551  if(Curl_gethostname(host, sizeof(host))) {
552  infof(data, "gethostname() failed, continuing without!\n");
553  hostlen = 0;
554  }
555  else {
556  hostlen = strlen(host);
557  }
558 
559 #if defined(USE_NTRESPONSES) && defined(USE_NTLM_V2)
560  if(ntlm->target_info_len) {
561  unsigned char ntbuffer[0x18];
562  unsigned char entropy[8];
563  unsigned char ntlmv2hash[0x18];
564 
565  result = Curl_rand(data, entropy, 8);
566  if(result)
567  return result;
568 
569  result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
570  if(result)
571  return result;
572 
573  result = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen,
574  ntbuffer, ntlmv2hash);
575  if(result)
576  return result;
577 
578  /* LMv2 response */
579  result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, entropy,
580  &ntlm->nonce[0], lmresp);
581  if(result)
582  return result;
583 
584  /* NTLMv2 response */
585  result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, entropy,
586  ntlm, &ntlmv2resp, &ntresplen);
587  if(result)
588  return result;
589 
590  ptr_ntresp = ntlmv2resp;
591  }
592  else
593 #endif
594 
595 #if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION)
596  /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
597  if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
598  unsigned char ntbuffer[0x18];
599  unsigned char tmp[0x18];
600  unsigned char md5sum[MD5_DIGEST_LENGTH];
601  unsigned char entropy[8];
602 
603  /* Need to create 8 bytes random data */
604  result = Curl_rand(data, entropy, 8);
605  if(result)
606  return result;
607 
608  /* 8 bytes random data as challenge in lmresp */
609  memcpy(lmresp, entropy, 8);
610 
611  /* Pad with zeros */
612  memset(lmresp + 8, 0, 0x10);
613 
614  /* Fill tmp with challenge(nonce?) + entropy */
615  memcpy(tmp, &ntlm->nonce[0], 8);
616  memcpy(tmp + 8, entropy, 8);
617 
618  result = Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH);
619  if(!result)
620  /* We shall only use the first 8 bytes of md5sum, but the des code in
621  Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
622  result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
623  if(result)
624  return result;
625 
626  Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp);
627 
628  /* End of NTLM2 Session code */
629 
630  }
631  else
632 #endif
633  {
634 
635 #ifdef USE_NTRESPONSES
636  unsigned char ntbuffer[0x18];
637 #endif
638  unsigned char lmbuffer[0x18];
639 
640 #ifdef USE_NTRESPONSES
641  result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
642  if(result)
643  return result;
644 
645  Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
646 #endif
647 
648  result = Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer);
649  if(result)
650  return result;
651 
652  Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
653 
654  /* A safer but less compatible alternative is:
655  * Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
656  * See https://davenport.sourceforge.io/ntlm.html#ntlmVersion2 */
657  }
658 
659  if(unicode) {
660  domlen = domlen * 2;
661  userlen = userlen * 2;
662  hostlen = hostlen * 2;
663  }
664 
665  lmrespoff = 64; /* size of the message header */
666 #ifdef USE_NTRESPONSES
667  ntrespoff = lmrespoff + 0x18;
668  domoff = ntrespoff + ntresplen;
669 #else
670  domoff = lmrespoff + 0x18;
671 #endif
672  useroff = domoff + domlen;
673  hostoff = useroff + userlen;
674 
675  /* Create the big type-3 message binary blob */
676  size = snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
677  NTLMSSP_SIGNATURE "%c"
678  "\x03%c%c%c" /* 32-bit type = 3 */
679 
680  "%c%c" /* LanManager length */
681  "%c%c" /* LanManager allocated space */
682  "%c%c" /* LanManager offset */
683  "%c%c" /* 2 zeroes */
684 
685  "%c%c" /* NT-response length */
686  "%c%c" /* NT-response allocated space */
687  "%c%c" /* NT-response offset */
688  "%c%c" /* 2 zeroes */
689 
690  "%c%c" /* domain length */
691  "%c%c" /* domain allocated space */
692  "%c%c" /* domain name offset */
693  "%c%c" /* 2 zeroes */
694 
695  "%c%c" /* user length */
696  "%c%c" /* user allocated space */
697  "%c%c" /* user offset */
698  "%c%c" /* 2 zeroes */
699 
700  "%c%c" /* host length */
701  "%c%c" /* host allocated space */
702  "%c%c" /* host offset */
703  "%c%c" /* 2 zeroes */
704 
705  "%c%c" /* session key length (unknown purpose) */
706  "%c%c" /* session key allocated space (unknown purpose) */
707  "%c%c" /* session key offset (unknown purpose) */
708  "%c%c" /* 2 zeroes */
709 
710  "%c%c%c%c", /* flags */
711 
712  /* domain string */
713  /* user string */
714  /* host string */
715  /* LanManager response */
716  /* NT response */
717 
718  0, /* zero termination */
719  0, 0, 0, /* type-3 long, the 24 upper bits */
720 
721  SHORTPAIR(0x18), /* LanManager response length, twice */
722  SHORTPAIR(0x18),
723  SHORTPAIR(lmrespoff),
724  0x0, 0x0,
725 
726 #ifdef USE_NTRESPONSES
727  SHORTPAIR(ntresplen), /* NT-response length, twice */
728  SHORTPAIR(ntresplen),
729  SHORTPAIR(ntrespoff),
730  0x0, 0x0,
731 #else
732  0x0, 0x0,
733  0x0, 0x0,
734  0x0, 0x0,
735  0x0, 0x0,
736 #endif
737  SHORTPAIR(domlen),
738  SHORTPAIR(domlen),
739  SHORTPAIR(domoff),
740  0x0, 0x0,
741 
742  SHORTPAIR(userlen),
743  SHORTPAIR(userlen),
744  SHORTPAIR(useroff),
745  0x0, 0x0,
746 
747  SHORTPAIR(hostlen),
748  SHORTPAIR(hostlen),
749  SHORTPAIR(hostoff),
750  0x0, 0x0,
751 
752  0x0, 0x0,
753  0x0, 0x0,
754  0x0, 0x0,
755  0x0, 0x0,
756 
757  LONGQUARTET(ntlm->flags));
758 
759  DEBUGASSERT(size == 64);
760  DEBUGASSERT(size == (size_t)lmrespoff);
761 
762  /* We append the binary hashes */
763  if(size < (NTLM_BUFSIZE - 0x18)) {
764  memcpy(&ntlmbuf[size], lmresp, 0x18);
765  size += 0x18;
766  }
767 
768  DEBUG_OUT({
769  fprintf(stderr, "**** TYPE3 header lmresp=");
770  ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
771  });
772 
773 #ifdef USE_NTRESPONSES
774  if(size < (NTLM_BUFSIZE - ntresplen)) {
775  DEBUGASSERT(size == (size_t)ntrespoff);
776  memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen);
777  size += ntresplen;
778  }
779 
780  DEBUG_OUT({
781  fprintf(stderr, "\n ntresp=");
782  ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen);
783  });
784 
785  free(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */
786 
787 #endif
788 
789  DEBUG_OUT({
790  fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
791  LONGQUARTET(ntlm->flags), ntlm->flags);
792  ntlm_print_flags(stderr, ntlm->flags);
793  fprintf(stderr, "\n****\n");
794  });
795 
796  /* Make sure that the domain, user and host strings fit in the
797  buffer before we copy them there. */
798  if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) {
799  failf(data, "user + domain + host name too big");
800  return CURLE_OUT_OF_MEMORY;
801  }
802 
803  DEBUGASSERT(size == domoff);
804  if(unicode)
805  unicodecpy(&ntlmbuf[size], domain, domlen / 2);
806  else
807  memcpy(&ntlmbuf[size], domain, domlen);
808 
809  size += domlen;
810 
811  DEBUGASSERT(size == useroff);
812  if(unicode)
813  unicodecpy(&ntlmbuf[size], user, userlen / 2);
814  else
815  memcpy(&ntlmbuf[size], user, userlen);
816 
817  size += userlen;
818 
819  DEBUGASSERT(size == hostoff);
820  if(unicode)
821  unicodecpy(&ntlmbuf[size], host, hostlen / 2);
822  else
823  memcpy(&ntlmbuf[size], host, hostlen);
824 
825  size += hostlen;
826 
827  /* Convert domain, user, and host to ASCII but leave the rest as-is */
828  result = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff],
829  size - domoff);
830  if(result)
831  return CURLE_CONV_FAILED;
832 
833  /* Return with binary blob encoded into base64 */
834  result = Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen);
835 
836  Curl_auth_ntlm_cleanup(ntlm);
837 
838  return result;
839 }
840 
841 /*
842 * Curl_auth_ntlm_cleanup()
843 *
844 * This is used to clean up the NTLM specific data.
845 *
846 * Parameters:
847 *
848 * ntlm [in/out] - The NTLM data struct being cleaned up.
849 *
850 */
851 void Curl_auth_ntlm_cleanup(struct ntlmdata *ntlm)
852 {
853  /* Free the target info */
854  Curl_safefree(ntlm->target_info);
855 
856  /* Reset any variables */
857  ntlm->target_info_len = 0;
858 }
859 
860 #endif /* USE_NTLM && !USE_WINDOWS_SSPI */
#define free(ptr)
Definition: curl_memory.h:130
unsigned int Curl_read32_le(const unsigned char *buf)
Definition: curl_endian.c:59
CURLcode Curl_base64_decode(const char *src, unsigned char **outptr, size_t *outlen)
Definition: base64.c:100
#define failf
Definition: sendf.h:48
CURLcode Curl_base64_encode(struct Curl_easy *data, const char *inputbuff, size_t insize, char **outptr, size_t *outlen)
Definition: base64.c:291
#define DEBUGASSERT(x)
CURLcode
Definition: curl.h:454
#define malloc(size)
Definition: curl_memory.h:124
UNITTEST_START int result
Definition: unit1304.c:49
const char ** p
Definition: unit1394.c:76
char buffer[]
Definition: unit1308.c:48
unsigned int i
Definition: unit1303.c:79
size_t len
Definition: curl_sasl.c:55
memcpy(filename, filename1, strlen(filename1))
#define FALSE
#define Curl_convert_to_network(a, b, c)
Definition: non-ascii.h:56
CURLcode(* md5sum)(unsigned char *input, size_t inputlen, unsigned char *md5sum, size_t md5sumlen)
Definition: vtls.h:73
unsigned short Curl_read16_le(const unsigned char *buf)
Definition: curl_endian.c:40
Definition: curl.h:455
#define Curl_safefree(ptr)
Definition: memdebug.h:170
#define MD5_DIGEST_LENGTH
Definition: vtls.h:116
char buf[3]
Definition: unit1398.c:32
CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num)
Definition: rand.c:120
#define infof
Definition: sendf.h:44
size_t size
Definition: unit1302.c:52
#define fprintf
Definition: curl_printf.h:41
#define snprintf
Definition: curl_printf.h:42
#define TRUE
#define HOSTNAME_MAX
int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen)
Definition: debug.c:29


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:16