• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2017, 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  * https://davenport.sourceforge.io/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 #include "rand.h"
45 #include "vtls/vtls.h"
46 
47 /* SSL backend-specific #if branches in this file must be kept in the order
48    documented in curl_ntlm_core. */
49 #if defined(NTLM_NEEDS_NSS_INIT)
50 #include "vtls/nssg.h" /* for Curl_nss_force_init() */
51 #endif
52 
53 #define BUILDING_CURL_NTLM_MSGS_C
54 #include "vauth/vauth.h"
55 #include "vauth/ntlm.h"
56 #include "curl_endian.h"
57 #include "curl_printf.h"
58 
59 /* The last #include files should be: */
60 #include "curl_memory.h"
61 #include "memdebug.h"
62 
63 /* "NTLMSSP" signature is always in ASCII regardless of the platform */
64 #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
65 
66 #define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
67 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8) & 0xff), \
68   (((x) >> 16) & 0xff), (((x) >> 24) & 0xff)
69 
70 #if DEBUG_ME
71 # define DEBUG_OUT(x) x
ntlm_print_flags(FILE * handle,unsigned long flags)72 static void ntlm_print_flags(FILE *handle, unsigned long flags)
73 {
74   if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
75     fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
76   if(flags & NTLMFLAG_NEGOTIATE_OEM)
77     fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
78   if(flags & NTLMFLAG_REQUEST_TARGET)
79     fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
80   if(flags & (1<<3))
81     fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
82   if(flags & NTLMFLAG_NEGOTIATE_SIGN)
83     fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
84   if(flags & NTLMFLAG_NEGOTIATE_SEAL)
85     fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
86   if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
87     fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
88   if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
89     fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
90   if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
91     fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
92   if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
93     fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
94   if(flags & (1<<10))
95     fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
96   if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS)
97     fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS ");
98   if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
99     fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
100   if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
101     fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
102   if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
103     fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
104   if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
105     fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
106   if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
107     fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
108   if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
109     fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
110   if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
111     fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
112   if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
113     fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
114   if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
115     fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
116   if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
117     fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
118   if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
119     fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
120   if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
121     fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
122   if(flags & (1<<24))
123     fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
124   if(flags & (1<<25))
125     fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
126   if(flags & (1<<26))
127     fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
128   if(flags & (1<<27))
129     fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
130   if(flags & (1<<28))
131     fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
132   if(flags & NTLMFLAG_NEGOTIATE_128)
133     fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
134   if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
135     fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
136   if(flags & NTLMFLAG_NEGOTIATE_56)
137     fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
138 }
139 
ntlm_print_hex(FILE * handle,const char * buf,size_t len)140 static void ntlm_print_hex(FILE *handle, const char *buf, size_t len)
141 {
142   const char *p = buf;
143 
144   (void) handle;
145 
146   fprintf(stderr, "0x");
147   while(len-- > 0)
148     fprintf(stderr, "%02.2x", (unsigned int)*p++);
149 }
150 #else
151 # define DEBUG_OUT(x) Curl_nop_stmt
152 #endif
153 
154 /*
155  * ntlm_decode_type2_target()
156  *
157  * This is used to decode the "target info" in the NTLM type-2 message
158  * received.
159  *
160  * Parameters:
161  *
162  * data      [in]     - The session handle.
163  * buffer    [in]     - The decoded type-2 message.
164  * size      [in]     - The input buffer size, at least 32 bytes.
165  * ntlm      [in/out] - The NTLM data struct being used and modified.
166  *
167  * Returns CURLE_OK on success.
168  */
ntlm_decode_type2_target(struct Curl_easy * data,unsigned char * buffer,size_t size,struct ntlmdata * ntlm)169 static CURLcode ntlm_decode_type2_target(struct Curl_easy *data,
170                                          unsigned char *buffer,
171                                          size_t size,
172                                          struct ntlmdata *ntlm)
173 {
174   unsigned short target_info_len = 0;
175   unsigned int target_info_offset = 0;
176 
177 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
178   (void) data;
179 #endif
180 
181   if(size >= 48) {
182     target_info_len = Curl_read16_le(&buffer[40]);
183     target_info_offset = Curl_read32_le(&buffer[44]);
184     if(target_info_len > 0) {
185       if(((target_info_offset + target_info_len) > size) ||
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\n");
189         return CURLE_BAD_CONTENT_ENCODING;
190       }
191 
192       ntlm->target_info = malloc(target_info_len);
193       if(!ntlm->target_info)
194         return CURLE_OUT_OF_MEMORY;
195 
196       memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len);
197     }
198   }
199 
200   ntlm->target_info_len = target_info_len;
201 
202   return CURLE_OK;
203 }
204 
205 /*
206   NTLM message structure notes:
207 
208   A 'short' is a 'network short', a little-endian 16-bit unsigned value.
209 
210   A 'long' is a 'network long', a little-endian, 32-bit unsigned value.
211 
212   A 'security buffer' represents a triplet used to point to a buffer,
213   consisting of two shorts and one long:
214 
215     1. A 'short' containing the length of the buffer content in bytes.
216     2. A 'short' containing the allocated space for the buffer in bytes.
217     3. A 'long' containing the offset to the start of the buffer in bytes,
218        from the beginning of the NTLM message.
219 */
220 
221 /*
222  * Curl_auth_is_ntlm_supported()
223  *
224  * This is used to evaluate if NTLM is supported.
225  *
226  * Parameters: None
227  *
228  * Returns TRUE as NTLM as handled by libcurl.
229  */
Curl_auth_is_ntlm_supported(void)230 bool Curl_auth_is_ntlm_supported(void)
231 {
232   return TRUE;
233 }
234 
235 /*
236  * Curl_auth_decode_ntlm_type2_message()
237  *
238  * This is used to decode an already encoded NTLM type-2 message. The message
239  * is first decoded from a base64 string into a raw NTLM message and checked
240  * for validity before the appropriate data for creating a type-3 message is
241  * written to the given NTLM data structure.
242  *
243  * Parameters:
244  *
245  * data     [in]     - The session handle.
246  * type2msg [in]     - The base64 encoded 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 char * type2msg,struct ntlmdata * ntlm)251 CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
252                                              const char *type2msg,
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   unsigned char *type2 = NULL;
275   size_t type2_len = 0;
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   /* Decode the base-64 encoded type-2 message */
287   if(strlen(type2msg) && *type2msg != '=') {
288     result = Curl_base64_decode(type2msg, &type2, &type2_len);
289     if(result)
290       return result;
291   }
292 
293   /* Ensure we have a valid type-2 message */
294   if(!type2) {
295     infof(data, "NTLM handshake failure (empty type-2 message)\n");
296     return CURLE_BAD_CONTENT_ENCODING;
297   }
298 
299   ntlm->flags = 0;
300 
301   if((type2_len < 32) ||
302      (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) ||
303      (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) {
304     /* This was not a good enough type-2 message */
305     free(type2);
306     infof(data, "NTLM handshake failure (bad type-2 message)\n");
307     return CURLE_BAD_CONTENT_ENCODING;
308   }
309 
310   ntlm->flags = Curl_read32_le(&type2[20]);
311   memcpy(ntlm->nonce, &type2[24], 8);
312 
313   if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) {
314     result = ntlm_decode_type2_target(data, type2, type2_len, ntlm);
315     if(result) {
316       free(type2);
317       infof(data, "NTLM handshake failure (bad type-2 message)\n");
318       return result;
319     }
320   }
321 
322   DEBUG_OUT({
323     fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
324     ntlm_print_flags(stderr, ntlm->flags);
325     fprintf(stderr, "\n                  nonce=");
326     ntlm_print_hex(stderr, (char *)ntlm->nonce, 8);
327     fprintf(stderr, "\n****\n");
328     fprintf(stderr, "**** Header %s\n ", header);
329   });
330 
331   free(type2);
332 
333   return result;
334 }
335 
336 /* copy the source to the destination and fill in zeroes in every
337    other destination byte! */
unicodecpy(unsigned char * dest,const char * src,size_t length)338 static void unicodecpy(unsigned char *dest, const char *src, size_t length)
339 {
340   size_t i;
341   for(i = 0; i < length; i++) {
342     dest[2 * i] = (unsigned char)src[i];
343     dest[2 * i + 1] = '\0';
344   }
345 }
346 
347 /*
348  * Curl_auth_create_ntlm_type1_message()
349  *
350  * This is used to generate an already encoded NTLM type-1 message ready for
351  * sending to the recipient using the appropriate compile time crypto API.
352  *
353  * Parameters:
354  *
355  * data    [in]     - The session handle.
356  * userp   [in]     - The user name in the format User or Domain\User.
357  * passdwp [in]     - The user's password.
358  * ntlm    [in/out] - The NTLM data struct being used and modified.
359  * outptr  [in/out] - The address where a pointer to newly allocated memory
360  *                    holding the result will be stored upon completion.
361  * outlen  [out]    - The length of the output message.
362  *
363  * Returns CURLE_OK on success.
364  */
Curl_auth_create_ntlm_type1_message(struct Curl_easy * data,const char * userp,const char * passwdp,struct ntlmdata * ntlm,char ** outptr,size_t * outlen)365 CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
366                                              const char *userp,
367                                              const char *passwdp,
368                                              struct ntlmdata *ntlm,
369                                              char **outptr, size_t *outlen)
370 {
371   /* NTLM type-1 message structure:
372 
373        Index  Description            Content
374          0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
375                                      (0x4e544c4d53535000)
376          8    NTLM Message Type      long (0x01000000)
377         12    Flags                  long
378        (16)   Supplied Domain        security buffer (*)
379        (24)   Supplied Workstation   security buffer (*)
380        (32)   OS Version Structure   8 bytes (*)
381   (32) (40)   Start of data block    (*)
382                                      (*) -> Optional
383   */
384 
385   size_t size;
386 
387   unsigned char ntlmbuf[NTLM_BUFSIZE];
388   const char *host = "";              /* empty */
389   const char *domain = "";            /* empty */
390   size_t hostlen = 0;
391   size_t domlen = 0;
392   size_t hostoff = 0;
393   size_t domoff = hostoff + hostlen;  /* This is 0: remember that host and
394                                          domain are empty */
395   (void)userp;
396   (void)passwdp;
397 
398   /* Clean up any former leftovers and initialise to defaults */
399   Curl_auth_ntlm_cleanup(ntlm);
400 
401 #if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION)
402 #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
403 #else
404 #define NTLM2FLAG 0
405 #endif
406   snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
407            NTLMSSP_SIGNATURE "%c"
408            "\x01%c%c%c" /* 32-bit type = 1 */
409            "%c%c%c%c"   /* 32-bit NTLM flag field */
410            "%c%c"       /* domain length */
411            "%c%c"       /* domain allocated space */
412            "%c%c"       /* domain name offset */
413            "%c%c"       /* 2 zeroes */
414            "%c%c"       /* host length */
415            "%c%c"       /* host allocated space */
416            "%c%c"       /* host name offset */
417            "%c%c"       /* 2 zeroes */
418            "%s"         /* host name */
419            "%s",        /* domain string */
420            0,           /* trailing zero */
421            0, 0, 0,     /* part of type-1 long */
422 
423            LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
424                        NTLMFLAG_REQUEST_TARGET |
425                        NTLMFLAG_NEGOTIATE_NTLM_KEY |
426                        NTLM2FLAG |
427                        NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
428            SHORTPAIR(domlen),
429            SHORTPAIR(domlen),
430            SHORTPAIR(domoff),
431            0, 0,
432            SHORTPAIR(hostlen),
433            SHORTPAIR(hostlen),
434            SHORTPAIR(hostoff),
435            0, 0,
436            host,  /* this is empty */
437            domain /* this is empty */);
438 
439   /* Initial packet length */
440   size = 32 + hostlen + domlen;
441 
442   DEBUG_OUT({
443     fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x "
444             "0x%08.8x ",
445             LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
446                         NTLMFLAG_REQUEST_TARGET |
447                         NTLMFLAG_NEGOTIATE_NTLM_KEY |
448                         NTLM2FLAG |
449                         NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
450             NTLMFLAG_NEGOTIATE_OEM |
451             NTLMFLAG_REQUEST_TARGET |
452             NTLMFLAG_NEGOTIATE_NTLM_KEY |
453             NTLM2FLAG |
454             NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
455     ntlm_print_flags(stderr,
456                      NTLMFLAG_NEGOTIATE_OEM |
457                      NTLMFLAG_REQUEST_TARGET |
458                      NTLMFLAG_NEGOTIATE_NTLM_KEY |
459                      NTLM2FLAG |
460                      NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
461     fprintf(stderr, "\n****\n");
462   });
463 
464   /* Return with binary blob encoded into base64 */
465   return Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen);
466 }
467 
468 /*
469  * Curl_auth_create_ntlm_type3_message()
470  *
471  * This is used to generate an already encoded NTLM type-3 message ready for
472  * sending to the recipient using the appropriate compile time crypto API.
473  *
474  * Parameters:
475  *
476  * data    [in]     - The session handle.
477  * userp   [in]     - The user name in the format User or Domain\User.
478  * passdwp [in]     - The user's password.
479  * ntlm    [in/out] - The NTLM data struct being used and modified.
480  * outptr  [in/out] - The address where a pointer to newly allocated memory
481  *                    holding the result will be stored upon completion.
482  * outlen  [out]    - The length of the output message.
483  *
484  * Returns CURLE_OK on success.
485  */
Curl_auth_create_ntlm_type3_message(struct Curl_easy * data,const char * userp,const char * passwdp,struct ntlmdata * ntlm,char ** outptr,size_t * outlen)486 CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
487                                              const char *userp,
488                                              const char *passwdp,
489                                              struct ntlmdata *ntlm,
490                                              char **outptr, size_t *outlen)
491 
492 {
493   /* NTLM type-3 message structure:
494 
495           Index  Description            Content
496             0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
497                                         (0x4e544c4d53535000)
498             8    NTLM Message Type      long (0x03000000)
499            12    LM/LMv2 Response       security buffer
500            20    NTLM/NTLMv2 Response   security buffer
501            28    Target Name            security buffer
502            36    User Name              security buffer
503            44    Workstation Name       security buffer
504           (52)   Session Key            security buffer (*)
505           (60)   Flags                  long (*)
506           (64)   OS Version Structure   8 bytes (*)
507   52 (64) (72)   Start of data block
508                                           (*) -> Optional
509   */
510 
511   CURLcode result = CURLE_OK;
512   size_t size;
513   unsigned char ntlmbuf[NTLM_BUFSIZE];
514   int lmrespoff;
515   unsigned char lmresp[24]; /* fixed-size */
516 #ifdef USE_NTRESPONSES
517   int ntrespoff;
518   unsigned int ntresplen = 24;
519   unsigned char ntresp[24]; /* fixed-size */
520   unsigned char *ptr_ntresp = &ntresp[0];
521   unsigned char *ntlmv2resp = NULL;
522 #endif
523   bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE;
524   char host[HOSTNAME_MAX + 1] = "";
525   const char *user;
526   const char *domain = "";
527   size_t hostoff = 0;
528   size_t useroff = 0;
529   size_t domoff = 0;
530   size_t hostlen = 0;
531   size_t userlen = 0;
532   size_t domlen = 0;
533 
534   user = strchr(userp, '\\');
535   if(!user)
536     user = strchr(userp, '/');
537 
538   if(user) {
539     domain = userp;
540     domlen = (user - domain);
541     user++;
542   }
543   else
544     user = userp;
545 
546   userlen = strlen(user);
547 
548   /* Get the machine's un-qualified host name as NTLM doesn't like the fully
549      qualified domain name */
550   if(Curl_gethostname(host, sizeof(host))) {
551     infof(data, "gethostname() failed, continuing without!\n");
552     hostlen = 0;
553   }
554   else {
555     hostlen = strlen(host);
556   }
557 
558 #if defined(USE_NTRESPONSES) && defined(USE_NTLM_V2)
559   if(ntlm->target_info_len) {
560     unsigned char ntbuffer[0x18];
561     unsigned char entropy[8];
562     unsigned char ntlmv2hash[0x18];
563 
564     result = Curl_rand(data, entropy, 8);
565     if(result)
566       return result;
567 
568     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
569     if(result)
570       return result;
571 
572     result = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen,
573                                            ntbuffer, ntlmv2hash);
574     if(result)
575       return result;
576 
577     /* LMv2 response */
578     result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, entropy,
579                                          &ntlm->nonce[0], lmresp);
580     if(result)
581       return result;
582 
583     /* NTLMv2 response */
584     result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, entropy,
585                                            ntlm, &ntlmv2resp, &ntresplen);
586     if(result)
587       return result;
588 
589     ptr_ntresp = ntlmv2resp;
590   }
591   else
592 #endif
593 
594 #if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION)
595   /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
596   if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
597     unsigned char ntbuffer[0x18];
598     unsigned char tmp[0x18];
599     unsigned char md5sum[MD5_DIGEST_LENGTH];
600     unsigned char entropy[8];
601 
602     /* Need to create 8 bytes random data */
603     result = Curl_rand(data, entropy, 8);
604     if(result)
605       return result;
606 
607     /* 8 bytes random data as challenge in lmresp */
608     memcpy(lmresp, entropy, 8);
609 
610     /* Pad with zeros */
611     memset(lmresp + 8, 0, 0x10);
612 
613     /* Fill tmp with challenge(nonce?) + entropy */
614     memcpy(tmp, &ntlm->nonce[0], 8);
615     memcpy(tmp + 8, entropy, 8);
616 
617     result = Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH);
618     if(!result)
619       /* We shall only use the first 8 bytes of md5sum, but the des code in
620          Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
621       result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
622     if(result)
623       return result;
624 
625     Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp);
626 
627     /* End of NTLM2 Session code */
628 
629   }
630   else
631 #endif
632   {
633 
634 #ifdef USE_NTRESPONSES
635     unsigned char ntbuffer[0x18];
636 #endif
637     unsigned char lmbuffer[0x18];
638 
639 #ifdef USE_NTRESPONSES
640     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
641     if(result)
642       return result;
643 
644     Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
645 #endif
646 
647     result = Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer);
648     if(result)
649       return result;
650 
651     Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
652 
653     /* A safer but less compatible alternative is:
654      *   Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
655      * See https://davenport.sourceforge.io/ntlm.html#ntlmVersion2 */
656   }
657 
658   if(unicode) {
659     domlen = domlen * 2;
660     userlen = userlen * 2;
661     hostlen = hostlen * 2;
662   }
663 
664   lmrespoff = 64; /* size of the message header */
665 #ifdef USE_NTRESPONSES
666   ntrespoff = lmrespoff + 0x18;
667   domoff = ntrespoff + ntresplen;
668 #else
669   domoff = lmrespoff + 0x18;
670 #endif
671   useroff = domoff + domlen;
672   hostoff = useroff + userlen;
673 
674   /* Create the big type-3 message binary blob */
675   size = snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
676                   NTLMSSP_SIGNATURE "%c"
677                   "\x03%c%c%c"  /* 32-bit type = 3 */
678 
679                   "%c%c"  /* LanManager length */
680                   "%c%c"  /* LanManager allocated space */
681                   "%c%c"  /* LanManager offset */
682                   "%c%c"  /* 2 zeroes */
683 
684                   "%c%c"  /* NT-response length */
685                   "%c%c"  /* NT-response allocated space */
686                   "%c%c"  /* NT-response offset */
687                   "%c%c"  /* 2 zeroes */
688 
689                   "%c%c"  /* domain length */
690                   "%c%c"  /* domain allocated space */
691                   "%c%c"  /* domain name offset */
692                   "%c%c"  /* 2 zeroes */
693 
694                   "%c%c"  /* user length */
695                   "%c%c"  /* user allocated space */
696                   "%c%c"  /* user offset */
697                   "%c%c"  /* 2 zeroes */
698 
699                   "%c%c"  /* host length */
700                   "%c%c"  /* host allocated space */
701                   "%c%c"  /* host offset */
702                   "%c%c"  /* 2 zeroes */
703 
704                   "%c%c"  /* session key length (unknown purpose) */
705                   "%c%c"  /* session key allocated space (unknown purpose) */
706                   "%c%c"  /* session key offset (unknown purpose) */
707                   "%c%c"  /* 2 zeroes */
708 
709                   "%c%c%c%c",  /* flags */
710 
711                   /* domain string */
712                   /* user string */
713                   /* host string */
714                   /* LanManager response */
715                   /* NT response */
716 
717                   0,                /* zero termination */
718                   0, 0, 0,          /* type-3 long, the 24 upper bits */
719 
720                   SHORTPAIR(0x18),  /* LanManager response length, twice */
721                   SHORTPAIR(0x18),
722                   SHORTPAIR(lmrespoff),
723                   0x0, 0x0,
724 
725 #ifdef USE_NTRESPONSES
726                   SHORTPAIR(ntresplen),  /* NT-response length, twice */
727                   SHORTPAIR(ntresplen),
728                   SHORTPAIR(ntrespoff),
729                   0x0, 0x0,
730 #else
731                   0x0, 0x0,
732                   0x0, 0x0,
733                   0x0, 0x0,
734                   0x0, 0x0,
735 #endif
736                   SHORTPAIR(domlen),
737                   SHORTPAIR(domlen),
738                   SHORTPAIR(domoff),
739                   0x0, 0x0,
740 
741                   SHORTPAIR(userlen),
742                   SHORTPAIR(userlen),
743                   SHORTPAIR(useroff),
744                   0x0, 0x0,
745 
746                   SHORTPAIR(hostlen),
747                   SHORTPAIR(hostlen),
748                   SHORTPAIR(hostoff),
749                   0x0, 0x0,
750 
751                   0x0, 0x0,
752                   0x0, 0x0,
753                   0x0, 0x0,
754                   0x0, 0x0,
755 
756                   LONGQUARTET(ntlm->flags));
757 
758   DEBUGASSERT(size == 64);
759   DEBUGASSERT(size == (size_t)lmrespoff);
760 
761   /* We append the binary hashes */
762   if(size < (NTLM_BUFSIZE - 0x18)) {
763     memcpy(&ntlmbuf[size], lmresp, 0x18);
764     size += 0x18;
765   }
766 
767   DEBUG_OUT({
768     fprintf(stderr, "**** TYPE3 header lmresp=");
769     ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
770   });
771 
772 #ifdef USE_NTRESPONSES
773   if(size < (NTLM_BUFSIZE - ntresplen)) {
774     DEBUGASSERT(size == (size_t)ntrespoff);
775     memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen);
776     size += ntresplen;
777   }
778 
779   DEBUG_OUT({
780     fprintf(stderr, "\n   ntresp=");
781     ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen);
782   });
783 
784   free(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */
785 
786 #endif
787 
788   DEBUG_OUT({
789     fprintf(stderr, "\n   flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
790             LONGQUARTET(ntlm->flags), ntlm->flags);
791     ntlm_print_flags(stderr, ntlm->flags);
792     fprintf(stderr, "\n****\n");
793   });
794 
795   /* Make sure that the domain, user and host strings fit in the
796      buffer before we copy them there. */
797   if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) {
798     failf(data, "user + domain + host name too big");
799     return CURLE_OUT_OF_MEMORY;
800   }
801 
802   DEBUGASSERT(size == domoff);
803   if(unicode)
804     unicodecpy(&ntlmbuf[size], domain, domlen / 2);
805   else
806     memcpy(&ntlmbuf[size], domain, domlen);
807 
808   size += domlen;
809 
810   DEBUGASSERT(size == useroff);
811   if(unicode)
812     unicodecpy(&ntlmbuf[size], user, userlen / 2);
813   else
814     memcpy(&ntlmbuf[size], user, userlen);
815 
816   size += userlen;
817 
818   DEBUGASSERT(size == hostoff);
819   if(unicode)
820     unicodecpy(&ntlmbuf[size], host, hostlen / 2);
821   else
822     memcpy(&ntlmbuf[size], host, hostlen);
823 
824   size += hostlen;
825 
826   /* Convert domain, user, and host to ASCII but leave the rest as-is */
827   result = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff],
828                                    size - domoff);
829   if(result)
830     return CURLE_CONV_FAILED;
831 
832   /* Return with binary blob encoded into base64 */
833   result = Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen);
834 
835   Curl_auth_ntlm_cleanup(ntlm);
836 
837   return result;
838 }
839 
840 /*
841 * Curl_auth_ntlm_cleanup()
842 *
843 * This is used to clean up the NTLM specific data.
844 *
845 * Parameters:
846 *
847 * ntlm    [in/out] - The NTLM data struct being cleaned up.
848 *
849 */
Curl_auth_ntlm_cleanup(struct ntlmdata * ntlm)850 void Curl_auth_ntlm_cleanup(struct ntlmdata *ntlm)
851 {
852   /* Free the target info */
853   Curl_safefree(ntlm->target_info);
854 
855   /* Reset any variables */
856   ntlm->target_info_len = 0;
857 }
858 
859 #endif /* USE_NTLM && !USE_WINDOWS_SSPI */
860