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