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