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