VirtualBox

source: vbox/trunk/src/libs/curl-7.87.0/lib/vauth/ntlm.c@ 98339

最後變更 在這個檔案從98339是 98326,由 vboxsync 提交於 2 年 前

curl-7.87.0: Applied and adjusted our curl changes to 7.83.1. bugref:10356

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

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