source: UsbWattMeter/trunk/curl-7.47.1/lib/curl_ntlm_msgs.c@ 164

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

TOPPERS/ECNLサンプルアプリ「USB充電器電力計」を追加

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