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