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