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