source: EcnlProtoTool/trunk/curl-7.57.0/lib/vauth/ntlm.c@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

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