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