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