VirtualBox

source: vbox/trunk/src/libs/curl-7.83.1/lib/vauth/ntlm.c@ 97122

最後變更 在這個檔案從97122是 95312,由 vboxsync 提交於 3 年 前

libs/{curl,libxml2}: OSE export fixes, bugref:8515

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette