b484a011a2cd812e799a6ed394c416614859eef0
[platform/upstream/curl.git] / lib / vauth / ntlm.c
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
70 static 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
138 static 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  */
167 static 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_is_ntlm_supported()
221  *
222  * This is used to evaluate if NTLM is supported.
223  *
224  * Parameters: None
225  *
226  * Returns TRUE as NTLM as handled by libcurl.
227  */
228 bool Curl_auth_is_ntlm_supported(void)
229 {
230   return TRUE;
231 }
232
233 /*
234  * Curl_auth_decode_ntlm_type2_message()
235  *
236  * This is used to decode an already encoded NTLM type-2 message. The message
237  * is first decoded from a base64 string into a raw NTLM message and checked
238  * for validity before the appropriate data for creating a type-3 message is
239  * written to the given NTLM data structure.
240  *
241  * Parameters:
242  *
243  * data     [in]     - The session handle.
244  * type2msg [in]     - The base64 encoded type-2 message.
245  * ntlm     [in/out] - The NTLM data struct being used and modified.
246  *
247  * Returns CURLE_OK on success.
248  */
249 CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
250                                              const char *type2msg,
251                                              struct ntlmdata *ntlm)
252 {
253   static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
254
255   /* NTLM type-2 message structure:
256
257           Index  Description            Content
258             0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
259                                         (0x4e544c4d53535000)
260             8    NTLM Message Type      long (0x02000000)
261            12    Target Name            security buffer
262            20    Flags                  long
263            24    Challenge              8 bytes
264           (32)   Context                8 bytes (two consecutive longs) (*)
265           (40)   Target Information     security buffer (*)
266           (48)   OS Version Structure   8 bytes (*)
267   32 (48) (56)   Start of data block    (*)
268                                         (*) -> Optional
269   */
270
271   CURLcode result = CURLE_OK;
272   unsigned char *type2 = NULL;
273   size_t type2_len = 0;
274
275 #if defined(USE_NSS)
276   /* Make sure the crypto backend is initialized */
277   result = Curl_nss_force_init(data);
278   if(result)
279     return result;
280 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
281   (void)data;
282 #endif
283
284   /* Decode the base-64 encoded type-2 message */
285   if(strlen(type2msg) && *type2msg != '=') {
286     result = Curl_base64_decode(type2msg, &type2, &type2_len);
287     if(result)
288       return result;
289   }
290
291   /* Ensure we have a valid type-2 message */
292   if(!type2) {
293     infof(data, "NTLM handshake failure (empty type-2 message)\n");
294     return CURLE_BAD_CONTENT_ENCODING;
295   }
296
297   ntlm->flags = 0;
298
299   if((type2_len < 32) ||
300      (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) ||
301      (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) {
302     /* This was not a good enough type-2 message */
303     free(type2);
304     infof(data, "NTLM handshake failure (bad type-2 message)\n");
305     return CURLE_BAD_CONTENT_ENCODING;
306   }
307
308   ntlm->flags = Curl_read32_le(&type2[20]);
309   memcpy(ntlm->nonce, &type2[24], 8);
310
311   if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) {
312     result = ntlm_decode_type2_target(data, type2, type2_len, ntlm);
313     if(result) {
314       free(type2);
315       infof(data, "NTLM handshake failure (bad type-2 message)\n");
316       return result;
317     }
318   }
319
320   DEBUG_OUT({
321     fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
322     ntlm_print_flags(stderr, ntlm->flags);
323     fprintf(stderr, "\n                  nonce=");
324     ntlm_print_hex(stderr, (char *)ntlm->nonce, 8);
325     fprintf(stderr, "\n****\n");
326     fprintf(stderr, "**** Header %s\n ", header);
327   });
328
329   free(type2);
330
331   return result;
332 }
333
334 /* copy the source to the destination and fill in zeroes in every
335    other destination byte! */
336 static void unicodecpy(unsigned char *dest, const char *src, size_t length)
337 {
338   size_t i;
339   for(i = 0; i < length; i++) {
340     dest[2 * i] = (unsigned char)src[i];
341     dest[2 * i + 1] = '\0';
342   }
343 }
344
345 /*
346  * Curl_auth_create_ntlm_type1_message()
347  *
348  * This is used to generate an already encoded NTLM type-1 message ready for
349  * sending to the recipient using the appropriate compile time crypto API.
350  *
351  * Parameters:
352  *
353  * userp   [in]     - The user name in the format User or Domain\User.
354  * passdwp [in]     - The user's password.
355  * ntlm    [in/out] - The NTLM data struct being used and modified.
356  * outptr  [in/out] - The address where a pointer to newly allocated memory
357  *                    holding the result will be stored upon completion.
358  * outlen  [out]    - The length of the output message.
359  *
360  * Returns CURLE_OK on success.
361  */
362 CURLcode Curl_auth_create_ntlm_type1_message(const char *userp,
363                                              const char *passwdp,
364                                              struct ntlmdata *ntlm,
365                                              char **outptr, size_t *outlen)
366 {
367   /* NTLM type-1 message structure:
368
369        Index  Description            Content
370          0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
371                                      (0x4e544c4d53535000)
372          8    NTLM Message Type      long (0x01000000)
373         12    Flags                  long
374        (16)   Supplied Domain        security buffer (*)
375        (24)   Supplied Workstation   security buffer (*)
376        (32)   OS Version Structure   8 bytes (*)
377   (32) (40)   Start of data block    (*)
378                                      (*) -> Optional
379   */
380
381   size_t size;
382
383   unsigned char ntlmbuf[NTLM_BUFSIZE];
384   const char *host = "";              /* empty */
385   const char *domain = "";            /* empty */
386   size_t hostlen = 0;
387   size_t domlen = 0;
388   size_t hostoff = 0;
389   size_t domoff = hostoff + hostlen;  /* This is 0: remember that host and
390                                          domain are empty */
391   (void)userp;
392   (void)passwdp;
393
394   /* Clean up any former leftovers and initialise to defaults */
395   Curl_auth_ntlm_cleanup(ntlm);
396
397 #if USE_NTRESPONSES && USE_NTLM2SESSION
398 #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
399 #else
400 #define NTLM2FLAG 0
401 #endif
402   snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
403            NTLMSSP_SIGNATURE "%c"
404            "\x01%c%c%c" /* 32-bit type = 1 */
405            "%c%c%c%c"   /* 32-bit NTLM flag field */
406            "%c%c"       /* domain length */
407            "%c%c"       /* domain allocated space */
408            "%c%c"       /* domain name offset */
409            "%c%c"       /* 2 zeroes */
410            "%c%c"       /* host length */
411            "%c%c"       /* host allocated space */
412            "%c%c"       /* host name offset */
413            "%c%c"       /* 2 zeroes */
414            "%s"         /* host name */
415            "%s",        /* domain string */
416            0,           /* trailing zero */
417            0, 0, 0,     /* part of type-1 long */
418
419            LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
420                        NTLMFLAG_REQUEST_TARGET |
421                        NTLMFLAG_NEGOTIATE_NTLM_KEY |
422                        NTLM2FLAG |
423                        NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
424            SHORTPAIR(domlen),
425            SHORTPAIR(domlen),
426            SHORTPAIR(domoff),
427            0, 0,
428            SHORTPAIR(hostlen),
429            SHORTPAIR(hostlen),
430            SHORTPAIR(hostoff),
431            0, 0,
432            host,  /* this is empty */
433            domain /* this is empty */);
434
435   /* Initial packet length */
436   size = 32 + hostlen + domlen;
437
438   DEBUG_OUT({
439     fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x "
440             "0x%08.8x ",
441             LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
442                         NTLMFLAG_REQUEST_TARGET |
443                         NTLMFLAG_NEGOTIATE_NTLM_KEY |
444                         NTLM2FLAG |
445                         NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
446             NTLMFLAG_NEGOTIATE_OEM |
447             NTLMFLAG_REQUEST_TARGET |
448             NTLMFLAG_NEGOTIATE_NTLM_KEY |
449             NTLM2FLAG |
450             NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
451     ntlm_print_flags(stderr,
452                      NTLMFLAG_NEGOTIATE_OEM |
453                      NTLMFLAG_REQUEST_TARGET |
454                      NTLMFLAG_NEGOTIATE_NTLM_KEY |
455                      NTLM2FLAG |
456                      NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
457     fprintf(stderr, "\n****\n");
458   });
459
460   /* Return with binary blob encoded into base64 */
461   return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
462 }
463
464 /*
465  * Curl_auth_create_ntlm_type3_message()
466  *
467  * This is used to generate an already encoded NTLM type-3 message ready for
468  * sending to the recipient using the appropriate compile time crypto API.
469  *
470  * Parameters:
471  *
472  * data    [in]     - The session handle.
473  * userp   [in]     - The user name in the format User or Domain\User.
474  * passdwp [in]     - The user's password.
475  * ntlm    [in/out] - The NTLM data struct being used and modified.
476  * outptr  [in/out] - The address where a pointer to newly allocated memory
477  *                    holding the result will be stored upon completion.
478  * outlen  [out]    - The length of the output message.
479  *
480  * Returns CURLE_OK on success.
481  */
482 CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
483                                              const char *userp,
484                                              const char *passwdp,
485                                              struct ntlmdata *ntlm,
486                                              char **outptr, size_t *outlen)
487
488 {
489   /* NTLM type-3 message structure:
490
491           Index  Description            Content
492             0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
493                                         (0x4e544c4d53535000)
494             8    NTLM Message Type      long (0x03000000)
495            12    LM/LMv2 Response       security buffer
496            20    NTLM/NTLMv2 Response   security buffer
497            28    Target Name            security buffer
498            36    User Name              security buffer
499            44    Workstation Name       security buffer
500           (52)   Session Key            security buffer (*)
501           (60)   Flags                  long (*)
502           (64)   OS Version Structure   8 bytes (*)
503   52 (64) (72)   Start of data block
504                                           (*) -> Optional
505   */
506
507   CURLcode result = CURLE_OK;
508   size_t size;
509   unsigned char ntlmbuf[NTLM_BUFSIZE];
510   int lmrespoff;
511   unsigned char lmresp[24]; /* fixed-size */
512 #if USE_NTRESPONSES
513   int ntrespoff;
514   unsigned int ntresplen = 24;
515   unsigned char ntresp[24]; /* fixed-size */
516   unsigned char *ptr_ntresp = &ntresp[0];
517   unsigned char *ntlmv2resp = NULL;
518 #endif
519   bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE;
520   char host[HOSTNAME_MAX + 1] = "";
521   const char *user;
522   const char *domain = "";
523   size_t hostoff = 0;
524   size_t useroff = 0;
525   size_t domoff = 0;
526   size_t hostlen = 0;
527   size_t userlen = 0;
528   size_t domlen = 0;
529
530   user = strchr(userp, '\\');
531   if(!user)
532     user = strchr(userp, '/');
533
534   if(user) {
535     domain = userp;
536     domlen = (user - domain);
537     user++;
538   }
539   else
540     user = userp;
541
542   if(user)
543     userlen = strlen(user);
544
545   /* Get the machine's un-qualified host name as NTLM doesn't like the fully
546      qualified domain name */
547   if(Curl_gethostname(host, sizeof(host))) {
548     infof(data, "gethostname() failed, continuing without!\n");
549     hostlen = 0;
550   }
551   else {
552     hostlen = strlen(host);
553   }
554
555 #if USE_NTRESPONSES && USE_NTLM_V2
556   if(ntlm->target_info_len) {
557     unsigned char ntbuffer[0x18];
558     unsigned int entropy[2];
559     unsigned char ntlmv2hash[0x18];
560
561     entropy[0] = Curl_rand(data);
562     entropy[1] = Curl_rand(data);
563
564     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
565     if(result)
566       return result;
567
568     result = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen,
569                                            ntbuffer, ntlmv2hash);
570     if(result)
571       return result;
572
573     /* LMv2 response */
574     result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash,
575                                          (unsigned char *)&entropy[0],
576                                          &ntlm->nonce[0], lmresp);
577     if(result)
578       return result;
579
580     /* NTLMv2 response */
581     result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash,
582                                            (unsigned char *)&entropy[0],
583                                            ntlm, &ntlmv2resp, &ntresplen);
584     if(result)
585       return result;
586
587     ptr_ntresp = ntlmv2resp;
588   }
589   else
590 #endif
591
592 #if USE_NTRESPONSES && USE_NTLM2SESSION
593   /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
594   if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
595     unsigned char ntbuffer[0x18];
596     unsigned char tmp[0x18];
597     unsigned char md5sum[MD5_DIGEST_LENGTH];
598     unsigned int entropy[2];
599
600     /* Need to create 8 bytes random data */
601     entropy[0] = Curl_rand(data);
602     entropy[1] = Curl_rand(data);
603
604     /* 8 bytes random data as challenge in lmresp */
605     memcpy(lmresp, entropy, 8);
606
607     /* Pad with zeros */
608     memset(lmresp + 8, 0, 0x10);
609
610     /* Fill tmp with challenge(nonce?) + entropy */
611     memcpy(tmp, &ntlm->nonce[0], 8);
612     memcpy(tmp + 8, entropy, 8);
613
614     result = Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH);
615     if(!result)
616       /* We shall only use the first 8 bytes of md5sum, but the des code in
617          Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
618       result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
619     if(result)
620       return result;
621
622     Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp);
623
624     /* End of NTLM2 Session code */
625
626   }
627   else
628 #endif
629   {
630
631 #if USE_NTRESPONSES
632     unsigned char ntbuffer[0x18];
633 #endif
634     unsigned char lmbuffer[0x18];
635
636 #if USE_NTRESPONSES
637     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
638     if(result)
639       return result;
640
641     Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
642 #endif
643
644     result = Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer);
645     if(result)
646       return result;
647
648     Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
649
650     /* A safer but less compatible alternative is:
651      *   Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
652      * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
653   }
654
655   if(unicode) {
656     domlen = domlen * 2;
657     userlen = userlen * 2;
658     hostlen = hostlen * 2;
659   }
660
661   lmrespoff = 64; /* size of the message header */
662 #if USE_NTRESPONSES
663   ntrespoff = lmrespoff + 0x18;
664   domoff = ntrespoff + ntresplen;
665 #else
666   domoff = lmrespoff + 0x18;
667 #endif
668   useroff = domoff + domlen;
669   hostoff = useroff + userlen;
670
671   /* Create the big type-3 message binary blob */
672   size = snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
673                   NTLMSSP_SIGNATURE "%c"
674                   "\x03%c%c%c"  /* 32-bit type = 3 */
675
676                   "%c%c"  /* LanManager length */
677                   "%c%c"  /* LanManager allocated space */
678                   "%c%c"  /* LanManager offset */
679                   "%c%c"  /* 2 zeroes */
680
681                   "%c%c"  /* NT-response length */
682                   "%c%c"  /* NT-response allocated space */
683                   "%c%c"  /* NT-response offset */
684                   "%c%c"  /* 2 zeroes */
685
686                   "%c%c"  /* domain length */
687                   "%c%c"  /* domain allocated space */
688                   "%c%c"  /* domain name offset */
689                   "%c%c"  /* 2 zeroes */
690
691                   "%c%c"  /* user length */
692                   "%c%c"  /* user allocated space */
693                   "%c%c"  /* user offset */
694                   "%c%c"  /* 2 zeroes */
695
696                   "%c%c"  /* host length */
697                   "%c%c"  /* host allocated space */
698                   "%c%c"  /* host offset */
699                   "%c%c"  /* 2 zeroes */
700
701                   "%c%c"  /* session key length (unknown purpose) */
702                   "%c%c"  /* session key allocated space (unknown purpose) */
703                   "%c%c"  /* session key offset (unknown purpose) */
704                   "%c%c"  /* 2 zeroes */
705
706                   "%c%c%c%c",  /* flags */
707
708                   /* domain string */
709                   /* user string */
710                   /* host string */
711                   /* LanManager response */
712                   /* NT response */
713
714                   0,                /* zero termination */
715                   0, 0, 0,          /* type-3 long, the 24 upper bits */
716
717                   SHORTPAIR(0x18),  /* LanManager response length, twice */
718                   SHORTPAIR(0x18),
719                   SHORTPAIR(lmrespoff),
720                   0x0, 0x0,
721
722 #if USE_NTRESPONSES
723                   SHORTPAIR(ntresplen),  /* NT-response length, twice */
724                   SHORTPAIR(ntresplen),
725                   SHORTPAIR(ntrespoff),
726                   0x0, 0x0,
727 #else
728                   0x0, 0x0,
729                   0x0, 0x0,
730                   0x0, 0x0,
731                   0x0, 0x0,
732 #endif
733                   SHORTPAIR(domlen),
734                   SHORTPAIR(domlen),
735                   SHORTPAIR(domoff),
736                   0x0, 0x0,
737
738                   SHORTPAIR(userlen),
739                   SHORTPAIR(userlen),
740                   SHORTPAIR(useroff),
741                   0x0, 0x0,
742
743                   SHORTPAIR(hostlen),
744                   SHORTPAIR(hostlen),
745                   SHORTPAIR(hostoff),
746                   0x0, 0x0,
747
748                   0x0, 0x0,
749                   0x0, 0x0,
750                   0x0, 0x0,
751                   0x0, 0x0,
752
753                   LONGQUARTET(ntlm->flags));
754
755   DEBUGASSERT(size == 64);
756   DEBUGASSERT(size == (size_t)lmrespoff);
757
758   /* We append the binary hashes */
759   if(size < (NTLM_BUFSIZE - 0x18)) {
760     memcpy(&ntlmbuf[size], lmresp, 0x18);
761     size += 0x18;
762   }
763
764   DEBUG_OUT({
765     fprintf(stderr, "**** TYPE3 header lmresp=");
766     ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
767   });
768
769 #if USE_NTRESPONSES
770   if(size < (NTLM_BUFSIZE - ntresplen)) {
771     DEBUGASSERT(size == (size_t)ntrespoff);
772     memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen);
773     size += ntresplen;
774   }
775
776   DEBUG_OUT({
777     fprintf(stderr, "\n   ntresp=");
778     ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen);
779   });
780
781   free(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */
782
783 #endif
784
785   DEBUG_OUT({
786     fprintf(stderr, "\n   flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
787             LONGQUARTET(ntlm->flags), ntlm->flags);
788     ntlm_print_flags(stderr, ntlm->flags);
789     fprintf(stderr, "\n****\n");
790   });
791
792   /* Make sure that the domain, user and host strings fit in the
793      buffer before we copy them there. */
794   if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) {
795     failf(data, "user + domain + host name too big");
796     return CURLE_OUT_OF_MEMORY;
797   }
798
799   DEBUGASSERT(size == domoff);
800   if(unicode)
801     unicodecpy(&ntlmbuf[size], domain, domlen / 2);
802   else
803     memcpy(&ntlmbuf[size], domain, domlen);
804
805   size += domlen;
806
807   DEBUGASSERT(size == useroff);
808   if(unicode)
809     unicodecpy(&ntlmbuf[size], user, userlen / 2);
810   else
811     memcpy(&ntlmbuf[size], user, userlen);
812
813   size += userlen;
814
815   DEBUGASSERT(size == hostoff);
816   if(unicode)
817     unicodecpy(&ntlmbuf[size], host, hostlen / 2);
818   else
819     memcpy(&ntlmbuf[size], host, hostlen);
820
821   size += hostlen;
822
823   /* Convert domain, user, and host to ASCII but leave the rest as-is */
824   result = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff],
825                                    size - domoff);
826   if(result)
827     return CURLE_CONV_FAILED;
828
829   /* Return with binary blob encoded into base64 */
830   result = Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
831
832   Curl_auth_ntlm_cleanup(ntlm);
833
834   return result;
835 }
836
837 /*
838 * Curl_auth_ntlm_cleanup()
839 *
840 * This is used to clean up the NTLM specific data.
841 *
842 * Parameters:
843 *
844 * ntlm    [in/out] - The NTLM data struct being cleaned up.
845 *
846 */
847 void Curl_auth_ntlm_cleanup(struct ntlmdata *ntlm)
848 {
849   /* Free the target info */
850   Curl_safefree(ntlm->target_info);
851
852   /* Reset any variables */
853   ntlm->target_info_len = 0;
854 }
855
856 #endif /* USE_NTLM && !USE_WINDOWS_SSPI */