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