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