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
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 
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  */
ntlm_decode_type2_target(struct SessionHandle * data,unsigned char * buffer,size_t size,struct ntlmdata * ntlm)167 static CURLcode ntlm_decode_type2_target(struct SessionHandle *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  */
Curl_auth_decode_ntlm_type2_message(struct SessionHandle * data,const char * type2msg,struct ntlmdata * ntlm)235 CURLcode Curl_auth_decode_ntlm_type2_message(struct SessionHandle *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! */
unicodecpy(unsigned char * dest,const char * src,size_t length)322 static 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  */
Curl_auth_create_ntlm_type1_message(const char * userp,const char * passwdp,struct ntlmdata * ntlm,char ** outptr,size_t * outlen)348 CURLcode 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  */
Curl_auth_create_ntlm_type3_message(struct SessionHandle * data,const char * userp,const char * passwdp,struct ntlmdata * ntlm,char ** outptr,size_t * outlen)468 CURLcode Curl_auth_create_ntlm_type3_message(struct SessionHandle *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 */
Curl_auth_ntlm_cleanup(struct ntlmdata * ntlm)833 void 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