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