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