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