115f70b0e196f6511808d6e2682b21c5b6f81be3
[platform/upstream/cmake.git] / Utilities / cmcurl / lib / vauth / ntlm.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2022, 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  ***************************************************************************/
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 "sendf.h"
38 #include "curl_ntlm_core.h"
39 #include "curl_gethostname.h"
40 #include "curl_multibyte.h"
41 #include "curl_md5.h"
42 #include "warnless.h"
43 #include "rand.h"
44 #include "vtls/vtls.h"
45
46 /* SSL backend-specific #if branches in this file must be kept in the order
47    documented in curl_ntlm_core. */
48 #if defined(NTLM_NEEDS_NSS_INIT)
49 #include "vtls/nssg.h" /* for Curl_nss_force_init() */
50 #endif
51
52 #define BUILDING_CURL_NTLM_MSGS_C
53 #include "vauth/vauth.h"
54 #include "vauth/ntlm.h"
55 #include "curl_endian.h"
56 #include "curl_printf.h"
57
58 /* The last #include files should be: */
59 #include "curl_memory.h"
60 #include "memdebug.h"
61
62 /* "NTLMSSP" signature is always in ASCII regardless of the platform */
63 #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
64
65 #if DEBUG_ME
66 # define DEBUG_OUT(x) x
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_NETWARE)
86     fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
87   if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
88     fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
89   if(flags & (1<<10))
90     fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
91   if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS)
92     fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS ");
93   if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
94     fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
95   if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
96     fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
97   if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
98     fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
99   if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
100     fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
101   if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
102     fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
103   if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
104     fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
105   if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
106     fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
107   if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
108     fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
109   if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
110     fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
111   if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
112     fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
113   if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
114     fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
115   if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
116     fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
117   if(flags & (1<<24))
118     fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
119   if(flags & (1<<25))
120     fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
121   if(flags & (1<<26))
122     fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
123   if(flags & (1<<27))
124     fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
125   if(flags & (1<<28))
126     fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
127   if(flags & NTLMFLAG_NEGOTIATE_128)
128     fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
129   if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
130     fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
131   if(flags & NTLMFLAG_NEGOTIATE_56)
132     fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
133 }
134
135 static void ntlm_print_hex(FILE *handle, const char *buf, size_t len)
136 {
137   const char *p = buf;
138
139   (void) handle;
140
141   fprintf(stderr, "0x");
142   while(len-- > 0)
143     fprintf(stderr, "%02.2x", (unsigned int)*p++);
144 }
145 #else
146 # define DEBUG_OUT(x) Curl_nop_stmt
147 #endif
148
149 /*
150  * ntlm_decode_type2_target()
151  *
152  * This is used to decode the "target info" in the NTLM type-2 message
153  * received.
154  *
155  * Parameters:
156  *
157  * data      [in]     - The session handle.
158  * type2ref  [in]     - The type-2 message.
159  * ntlm      [in/out] - The NTLM data struct being used and modified.
160  *
161  * Returns CURLE_OK on success.
162  */
163 static CURLcode ntlm_decode_type2_target(struct Curl_easy *data,
164                                          const struct bufref *type2ref,
165                                          struct ntlmdata *ntlm)
166 {
167   unsigned short target_info_len = 0;
168   unsigned int target_info_offset = 0;
169   const unsigned char *type2 = Curl_bufref_ptr(type2ref);
170   size_t type2len = Curl_bufref_len(type2ref);
171
172 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
173   (void) data;
174 #endif
175
176   if(type2len >= 48) {
177     target_info_len = Curl_read16_le(&type2[40]);
178     target_info_offset = Curl_read32_le(&type2[44]);
179     if(target_info_len > 0) {
180       if((target_info_offset > type2len) ||
181          (target_info_offset + target_info_len) > type2len ||
182          target_info_offset < 48) {
183         infof(data, "NTLM handshake failure (bad type-2 message). "
184               "Target Info Offset Len is set incorrect by the peer");
185         return CURLE_BAD_CONTENT_ENCODING;
186       }
187
188       free(ntlm->target_info); /* replace any previous data */
189       ntlm->target_info = malloc(target_info_len);
190       if(!ntlm->target_info)
191         return CURLE_OUT_OF_MEMORY;
192
193       memcpy(ntlm->target_info, &type2[target_info_offset], target_info_len);
194     }
195   }
196
197   ntlm->target_info_len = target_info_len;
198
199   return CURLE_OK;
200 }
201
202 /*
203   NTLM message structure notes:
204
205   A 'short' is a 'network short', a little-endian 16-bit unsigned value.
206
207   A 'long' is a 'network long', a little-endian, 32-bit unsigned value.
208
209   A 'security buffer' represents a triplet used to point to a buffer,
210   consisting of two shorts and one long:
211
212     1. A 'short' containing the length of the buffer content in bytes.
213     2. A 'short' containing the allocated space for the buffer in bytes.
214     3. A 'long' containing the offset to the start of the buffer in bytes,
215        from the beginning of the NTLM message.
216 */
217
218 /*
219  * Curl_auth_is_ntlm_supported()
220  *
221  * This is used to evaluate if NTLM is supported.
222  *
223  * Parameters: None
224  *
225  * Returns TRUE as NTLM as handled by libcurl.
226  */
227 bool Curl_auth_is_ntlm_supported(void)
228 {
229   return TRUE;
230 }
231
232 /*
233  * Curl_auth_decode_ntlm_type2_message()
234  *
235  * This is used to decode an NTLM type-2 message. The raw NTLM message is
236  * checked * for validity before the appropriate data for creating a type-3
237  * message is * written to the given NTLM data structure.
238  *
239  * Parameters:
240  *
241  * data     [in]     - The session handle.
242  * type2ref [in]     - The type-2 message.
243  * ntlm     [in/out] - The NTLM data struct being used and modified.
244  *
245  * Returns CURLE_OK on success.
246  */
247 CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
248                                              const struct bufref *type2ref,
249                                              struct ntlmdata *ntlm)
250 {
251   static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
252
253   /* NTLM type-2 message structure:
254
255           Index  Description            Content
256             0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
257                                         (0x4e544c4d53535000)
258             8    NTLM Message Type      long (0x02000000)
259            12    Target Name            security buffer
260            20    Flags                  long
261            24    Challenge              8 bytes
262           (32)   Context                8 bytes (two consecutive longs) (*)
263           (40)   Target Information     security buffer (*)
264           (48)   OS Version Structure   8 bytes (*)
265   32 (48) (56)   Start of data block    (*)
266                                         (*) -> Optional
267   */
268
269   CURLcode result = CURLE_OK;
270   const unsigned char *type2 = Curl_bufref_ptr(type2ref);
271   size_t type2len = Curl_bufref_len(type2ref);
272
273 #if defined(NTLM_NEEDS_NSS_INIT)
274   /* Make sure the crypto backend is initialized */
275   result = Curl_nss_force_init(data);
276   if(result)
277     return result;
278 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
279   (void)data;
280 #endif
281
282   ntlm->flags = 0;
283
284   if((type2len < 32) ||
285      (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) ||
286      (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) {
287     /* This was not a good enough type-2 message */
288     infof(data, "NTLM handshake failure (bad type-2 message)");
289     return CURLE_BAD_CONTENT_ENCODING;
290   }
291
292   ntlm->flags = Curl_read32_le(&type2[20]);
293   memcpy(ntlm->nonce, &type2[24], 8);
294
295   if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) {
296     result = ntlm_decode_type2_target(data, type2ref, ntlm);
297     if(result) {
298       infof(data, "NTLM handshake failure (bad type-2 message)");
299       return result;
300     }
301   }
302
303   DEBUG_OUT({
304     fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
305     ntlm_print_flags(stderr, ntlm->flags);
306     fprintf(stderr, "\n                  nonce=");
307     ntlm_print_hex(stderr, (char *)ntlm->nonce, 8);
308     fprintf(stderr, "\n****\n");
309     fprintf(stderr, "**** Header %s\n ", header);
310   });
311
312   return result;
313 }
314
315 /* copy the source to the destination and fill in zeroes in every
316    other destination byte! */
317 static void unicodecpy(unsigned char *dest, const char *src, size_t length)
318 {
319   size_t i;
320   for(i = 0; i < length; i++) {
321     dest[2 * i] = (unsigned char)src[i];
322     dest[2 * i + 1] = '\0';
323   }
324 }
325
326 /*
327  * Curl_auth_create_ntlm_type1_message()
328  *
329  * This is used to generate an NTLM type-1 message ready for sending to the
330  * recipient using the appropriate compile time crypto API.
331  *
332  * Parameters:
333  *
334  * data    [in]     - The session handle.
335  * userp   [in]     - The user name in the format User or Domain\User.
336  * passwdp [in]     - The user's password.
337  * service [in]     - The service type such as http, smtp, pop or imap.
338  * host    [in]     - The host name.
339  * ntlm    [in/out] - The NTLM data struct being used and modified.
340  * out     [out]    - The result storage.
341  *
342  * Returns CURLE_OK on success.
343  */
344 CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
345                                              const char *userp,
346                                              const char *passwdp,
347                                              const char *service,
348                                              const char *hostname,
349                                              struct ntlmdata *ntlm,
350                                              struct bufref *out)
351 {
352   /* NTLM type-1 message structure:
353
354        Index  Description            Content
355          0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
356                                      (0x4e544c4d53535000)
357          8    NTLM Message Type      long (0x01000000)
358         12    Flags                  long
359        (16)   Supplied Domain        security buffer (*)
360        (24)   Supplied Workstation   security buffer (*)
361        (32)   OS Version Structure   8 bytes (*)
362   (32) (40)   Start of data block    (*)
363                                      (*) -> Optional
364   */
365
366   size_t size;
367
368   char *ntlmbuf;
369   const char *host = "";              /* empty */
370   const char *domain = "";            /* empty */
371   size_t hostlen = 0;
372   size_t domlen = 0;
373   size_t hostoff = 0;
374   size_t domoff = hostoff + hostlen;  /* This is 0: remember that host and
375                                          domain are empty */
376   (void)data;
377   (void)userp;
378   (void)passwdp;
379   (void)service,
380   (void)hostname,
381
382   /* Clean up any former leftovers and initialise to defaults */
383   Curl_auth_cleanup_ntlm(ntlm);
384
385   ntlmbuf = aprintf(NTLMSSP_SIGNATURE "%c"
386                     "\x01%c%c%c" /* 32-bit type = 1 */
387                     "%c%c%c%c"   /* 32-bit NTLM flag field */
388                     "%c%c"       /* domain length */
389                     "%c%c"       /* domain allocated space */
390                     "%c%c"       /* domain name offset */
391                     "%c%c"       /* 2 zeroes */
392                     "%c%c"       /* host length */
393                     "%c%c"       /* host allocated space */
394                     "%c%c"       /* host name offset */
395                     "%c%c"       /* 2 zeroes */
396                     "%s"         /* host name */
397                     "%s",        /* domain string */
398                     0,           /* trailing zero */
399                     0, 0, 0,     /* part of type-1 long */
400
401                     LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
402                                 NTLMFLAG_REQUEST_TARGET |
403                                 NTLMFLAG_NEGOTIATE_NTLM_KEY |
404                                 NTLMFLAG_NEGOTIATE_NTLM2_KEY |
405                                 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
406                     SHORTPAIR(domlen),
407                     SHORTPAIR(domlen),
408                     SHORTPAIR(domoff),
409                     0, 0,
410                     SHORTPAIR(hostlen),
411                     SHORTPAIR(hostlen),
412                     SHORTPAIR(hostoff),
413                     0, 0,
414                     host,  /* this is empty */
415                     domain /* this is empty */);
416
417   if(!ntlmbuf)
418     return CURLE_OUT_OF_MEMORY;
419
420   /* Initial packet length */
421   size = 32 + hostlen + domlen;
422
423   DEBUG_OUT({
424     fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x "
425             "0x%08.8x ",
426             LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
427                         NTLMFLAG_REQUEST_TARGET |
428                         NTLMFLAG_NEGOTIATE_NTLM_KEY |
429                         NTLMFLAG_NEGOTIATE_NTLM2_KEY |
430                         NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
431             NTLMFLAG_NEGOTIATE_OEM |
432             NTLMFLAG_REQUEST_TARGET |
433             NTLMFLAG_NEGOTIATE_NTLM_KEY |
434             NTLMFLAG_NEGOTIATE_NTLM2_KEY |
435             NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
436     ntlm_print_flags(stderr,
437                      NTLMFLAG_NEGOTIATE_OEM |
438                      NTLMFLAG_REQUEST_TARGET |
439                      NTLMFLAG_NEGOTIATE_NTLM_KEY |
440                      NTLMFLAG_NEGOTIATE_NTLM2_KEY |
441                      NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
442     fprintf(stderr, "\n****\n");
443   });
444
445   Curl_bufref_set(out, ntlmbuf, size, curl_free);
446   return CURLE_OK;
447 }
448
449 /*
450  * Curl_auth_create_ntlm_type3_message()
451  *
452  * This is used to generate an already encoded NTLM type-3 message ready for
453  * sending to the recipient using the appropriate compile time crypto API.
454  *
455  * Parameters:
456  *
457  * data    [in]     - The session handle.
458  * userp   [in]     - The user name in the format User or Domain\User.
459  * passwdp [in]     - The user's password.
460  * ntlm    [in/out] - The NTLM data struct being used and modified.
461  * out     [out]    - The result storage.
462  *
463  * Returns CURLE_OK on success.
464  */
465 CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
466                                              const char *userp,
467                                              const char *passwdp,
468                                              struct ntlmdata *ntlm,
469                                              struct bufref *out)
470 {
471   /* NTLM type-3 message structure:
472
473           Index  Description            Content
474             0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
475                                         (0x4e544c4d53535000)
476             8    NTLM Message Type      long (0x03000000)
477            12    LM/LMv2 Response       security buffer
478            20    NTLM/NTLMv2 Response   security buffer
479            28    Target Name            security buffer
480            36    User Name              security buffer
481            44    Workstation Name       security buffer
482           (52)   Session Key            security buffer (*)
483           (60)   Flags                  long (*)
484           (64)   OS Version Structure   8 bytes (*)
485   52 (64) (72)   Start of data block
486                                           (*) -> Optional
487   */
488
489   CURLcode result = CURLE_OK;
490   size_t size;
491   unsigned char ntlmbuf[NTLM_BUFSIZE];
492   int lmrespoff;
493   unsigned char lmresp[24]; /* fixed-size */
494   int ntrespoff;
495   unsigned int ntresplen = 24;
496   unsigned char ntresp[24]; /* fixed-size */
497   unsigned char *ptr_ntresp = &ntresp[0];
498   unsigned char *ntlmv2resp = NULL;
499   bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE;
500   char host[HOSTNAME_MAX + 1] = "";
501   const char *user;
502   const char *domain = "";
503   size_t hostoff = 0;
504   size_t useroff = 0;
505   size_t domoff = 0;
506   size_t hostlen = 0;
507   size_t userlen = 0;
508   size_t domlen = 0;
509
510   user = strchr(userp, '\\');
511   if(!user)
512     user = strchr(userp, '/');
513
514   if(user) {
515     domain = userp;
516     domlen = (user - domain);
517     user++;
518   }
519   else
520     user = userp;
521
522   userlen = strlen(user);
523
524   /* Get the machine's un-qualified host name as NTLM doesn't like the fully
525      qualified domain name */
526   if(Curl_gethostname(host, sizeof(host))) {
527     infof(data, "gethostname() failed, continuing without");
528     hostlen = 0;
529   }
530   else {
531     hostlen = strlen(host);
532   }
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.io/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,                /* zero 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  */
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 */