1 /*
2  * Copyright (c) Edward Thomson.  All rights reserved.
3  *
4  * This file is part of ntlmclient, distributed under the MIT license.
5  * For full terms and copyright information, and for third-party
6  * copyright information, see the included LICENSE.txt file.
7  */
8 
9 #include <stdlib.h>
10 #include <stdint.h>
11 #include <string.h>
12 #include <errno.h>
13 #include <ctype.h>
14 #include <unistd.h>
15 #include <fcntl.h>
16 #include <time.h>
17 #include <arpa/inet.h>
18 
19 #include "ntlm.h"
20 #include "unicode.h"
21 #include "utf8.h"
22 #include "crypt.h"
23 #include "compat.h"
24 #include "util.h"
25 
26 #define NTLM_ASSERT_ARG(expr) do { \
27 		if (!(expr)) \
28 			return NTLM_CLIENT_ERROR_INVALID_INPUT; \
29 	} while(0)
30 
31 #define NTLM_ASSERT(ntlm, expr) do { \
32 		if (!(expr)) { \
33 			ntlm_client_set_errmsg(ntlm, "internal error: " #expr); \
34 			return -1; \
35 		} \
36 	} while(0)
37 
38 unsigned char ntlm_client_signature[] = NTLM_SIGNATURE;
39 
supports_unicode(ntlm_client * ntlm)40 static bool supports_unicode(ntlm_client *ntlm)
41 {
42 	return (ntlm->flags & NTLM_CLIENT_DISABLE_UNICODE) ?
43 		false : true;
44 }
45 
increment_size(size_t * out,size_t incr)46 static inline bool increment_size(size_t *out, size_t incr)
47 {
48 	if (SIZE_MAX - *out < incr) {
49 		*out = (size_t)-1;
50 		return false;
51 	}
52 
53 	*out = *out + incr;
54 	return true;
55 }
56 
ntlm_client_init(ntlm_client_flags flags)57 ntlm_client *ntlm_client_init(ntlm_client_flags flags)
58 {
59 	ntlm_client *ntlm = NULL;
60 
61 	if ((ntlm = calloc(1, sizeof(ntlm_client))) == NULL)
62 		return NULL;
63 
64 	ntlm->flags = flags;
65 
66 	return ntlm;
67 }
68 
69 #define ENSURE_INITIALIZED(ntlm) \
70 	do { \
71 		if (!(ntlm)->unicode_initialized) \
72 			(ntlm)->unicode_initialized = ntlm_unicode_init((ntlm)); \
73 		if (!(ntlm)->crypt_initialized) \
74 			(ntlm)->crypt_initialized = ntlm_crypt_init((ntlm)); \
75 		if (!(ntlm)->unicode_initialized || \
76 		    !(ntlm)->crypt_initialized) \
77 			return -1; \
78 	} while(0)
79 
ntlm_client_set_errmsg(ntlm_client * ntlm,const char * errmsg)80 void ntlm_client_set_errmsg(ntlm_client *ntlm, const char *errmsg)
81 {
82 	ntlm->state = NTLM_STATE_ERROR;
83 	ntlm->errmsg = errmsg;
84 }
85 
ntlm_client_errmsg(ntlm_client * ntlm)86 const char *ntlm_client_errmsg(ntlm_client *ntlm)
87 {
88 	if (!ntlm)
89 		return "internal error";
90 
91 	return ntlm->errmsg ? ntlm->errmsg : "no error";
92 }
93 
ntlm_client_set_version(ntlm_client * ntlm,uint8_t major,uint8_t minor,uint16_t build)94 int ntlm_client_set_version(
95 	ntlm_client *ntlm,
96 	uint8_t major,
97 	uint8_t minor,
98 	uint16_t build)
99 {
100 	NTLM_ASSERT_ARG(ntlm);
101 
102 	ntlm->host_version.major = major;
103 	ntlm->host_version.minor = minor;
104 	ntlm->host_version.build = build;
105 	ntlm->host_version.reserved = 0x0f000000;
106 
107 	ntlm->flags |= NTLM_ENABLE_HOSTVERSION;
108 
109 	return 0;
110 }
111 
112 #define reset(ptr) do { free(ptr); ptr = NULL; } while(0)
113 
free_hostname(ntlm_client * ntlm)114 static void free_hostname(ntlm_client *ntlm)
115 {
116 	reset(ntlm->hostname);
117 	reset(ntlm->hostdomain);
118 	reset(ntlm->hostname_utf16);
119 	ntlm->hostname_utf16_len = 0;
120 }
121 
ntlm_client_set_hostname(ntlm_client * ntlm,const char * hostname,const char * domain)122 int ntlm_client_set_hostname(
123 	ntlm_client *ntlm,
124 	const char *hostname,
125 	const char *domain)
126 {
127 	NTLM_ASSERT_ARG(ntlm);
128 	ENSURE_INITIALIZED(ntlm);
129 
130 	free_hostname(ntlm);
131 
132 	if (hostname && (ntlm->hostname = strdup(hostname)) == NULL) {
133 		ntlm_client_set_errmsg(ntlm, "out of memory");
134 		return -1;
135 	}
136 
137 	if (domain && (ntlm->hostdomain = strdup(domain)) == NULL) {
138 		ntlm_client_set_errmsg(ntlm, "out of memory");
139 		return -1;
140 	}
141 
142 	if (hostname && supports_unicode(ntlm) && !ntlm_unicode_utf8_to_16(
143 			&ntlm->hostname_utf16,
144 			&ntlm->hostname_utf16_len,
145 			ntlm,
146 			hostname,
147 			strlen(hostname)))
148 		return -1;
149 
150 	return 0;
151 }
152 
free_credentials(ntlm_client * ntlm)153 static void free_credentials(ntlm_client *ntlm)
154 {
155 	if (ntlm->password)
156 		ntlm_memzero(ntlm->password, strlen(ntlm->password));
157 
158 	if (ntlm->password_utf16)
159 		ntlm_memzero(ntlm->password_utf16, ntlm->password_utf16_len);
160 
161 	reset(ntlm->username);
162 	reset(ntlm->username_upper);
163 	reset(ntlm->userdomain);
164 	reset(ntlm->password);
165 
166 	reset(ntlm->username_utf16);
167 	reset(ntlm->username_upper_utf16);
168 	reset(ntlm->userdomain_utf16);
169 	reset(ntlm->password_utf16);
170 
171 	ntlm->username_utf16_len = 0;
172 	ntlm->username_upper_utf16_len = 0;
173 	ntlm->userdomain_utf16_len = 0;
174 	ntlm->password_utf16_len = 0;
175 }
176 
ntlm_client_set_credentials(ntlm_client * ntlm,const char * username,const char * domain,const char * password)177 int ntlm_client_set_credentials(
178 	ntlm_client *ntlm,
179 	const char *username,
180 	const char *domain,
181 	const char *password)
182 {
183 	NTLM_ASSERT_ARG(ntlm);
184 	ENSURE_INITIALIZED(ntlm);
185 
186 	free_credentials(ntlm);
187 
188 	if ((username && (ntlm->username = strdup(username)) == NULL) ||
189 		(domain && (ntlm->userdomain = strdup(domain)) == NULL) ||
190 		(password && (ntlm->password = strdup(password)) == NULL)) {
191 		ntlm_client_set_errmsg(ntlm, "out of memory");
192 		return -1;
193 	}
194 
195 	if (username && supports_unicode(ntlm)) {
196 		if ((ntlm->username_upper = strdup(username)) == NULL) {
197 			ntlm_client_set_errmsg(ntlm, "out of memory");
198 			return -1;
199 		}
200 		utf8upr(ntlm->username_upper);
201 
202 		if (!ntlm_unicode_utf8_to_16(
203 				&ntlm->username_utf16,
204 				&ntlm->username_utf16_len,
205 				ntlm,
206 				ntlm->username,
207 				strlen(ntlm->username)))
208 			return -1;
209 
210 		if (!ntlm_unicode_utf8_to_16(
211 				&ntlm->username_upper_utf16,
212 				&ntlm->username_upper_utf16_len,
213 				ntlm,
214 				ntlm->username_upper,
215 				strlen(ntlm->username_upper)))
216 			return -1;
217 	}
218 
219 	if (domain && supports_unicode(ntlm) && !ntlm_unicode_utf8_to_16(
220 			&ntlm->userdomain_utf16,
221 			&ntlm->userdomain_utf16_len,
222 			ntlm,
223 			ntlm->userdomain,
224 			strlen(ntlm->userdomain)))
225 		return -1;
226 
227 	return 0;
228 }
229 
ntlm_client_set_target(ntlm_client * ntlm,const char * target)230 int ntlm_client_set_target(ntlm_client *ntlm, const char *target)
231 {
232 	NTLM_ASSERT_ARG(ntlm);
233 	ENSURE_INITIALIZED(ntlm);
234 
235 	free(ntlm->target);
236 	free(ntlm->target_utf16);
237 
238 	ntlm->target = NULL;
239 	ntlm->target_utf16 = NULL;
240 
241 	if (target) {
242 		if ((ntlm->target = strdup(target)) == NULL) {
243 			ntlm_client_set_errmsg(ntlm, "out of memory");
244 			return -1;
245 		}
246 
247 		if (supports_unicode(ntlm) && !ntlm_unicode_utf8_to_16(
248 				&ntlm->target_utf16,
249 				&ntlm->target_utf16_len,
250 				ntlm,
251 				ntlm->target,
252 				strlen(ntlm->target)))
253 			return -1;
254 	}
255 
256 	return 0;
257 }
258 
ntlm_client_set_nonce(ntlm_client * ntlm,uint64_t nonce)259 int ntlm_client_set_nonce(ntlm_client *ntlm, uint64_t nonce)
260 {
261 	NTLM_ASSERT_ARG(ntlm);
262 
263 	ntlm->nonce = nonce;
264 	return 0;
265 }
266 
ntlm_client_set_timestamp(ntlm_client * ntlm,uint64_t timestamp)267 int ntlm_client_set_timestamp(ntlm_client *ntlm, uint64_t timestamp)
268 {
269 	NTLM_ASSERT_ARG(ntlm);
270 
271 	ntlm->timestamp = timestamp;
272 	return 0;
273 }
274 
write_buf(ntlm_client * ntlm,ntlm_buf * out,const unsigned char * buf,size_t len)275 static inline bool write_buf(
276 	ntlm_client *ntlm,
277 	ntlm_buf *out,
278 	const unsigned char *buf,
279 	size_t len)
280 {
281 	if (!len)
282 		return true;
283 
284 	if (out->len - out->pos < len) {
285 		ntlm_client_set_errmsg(ntlm, "out of buffer space");
286 		return false;
287 	}
288 
289 	memcpy(&out->buf[out->pos], buf, len);
290 	out->pos += len;
291 	return true;
292 }
293 
write_byte(ntlm_client * ntlm,ntlm_buf * out,uint8_t value)294 static inline bool write_byte(
295 	ntlm_client *ntlm,
296 	ntlm_buf *out,
297 	uint8_t value)
298 {
299 	if (out->len - out->pos < 1) {
300 		ntlm_client_set_errmsg(ntlm, "out of buffer space");
301 		return false;
302 	}
303 
304 	out->buf[out->pos++] = value;
305 	return true;
306 }
307 
write_int16(ntlm_client * ntlm,ntlm_buf * out,uint16_t value)308 static inline bool write_int16(
309 	ntlm_client *ntlm,
310 	ntlm_buf *out,
311 	uint16_t value)
312 {
313 	if (out->len - out->pos < 2) {
314 		ntlm_client_set_errmsg(ntlm, "out of buffer space");
315 		return false;
316 	}
317 
318 	out->buf[out->pos++] = (value & 0x000000ff);
319 	out->buf[out->pos++] = (value & 0x0000ff00) >> 8;
320 	return true;
321 }
322 
write_int32(ntlm_client * ntlm,ntlm_buf * out,uint32_t value)323 static inline bool write_int32(
324 	ntlm_client *ntlm,
325 	ntlm_buf *out,
326 	uint32_t value)
327 {
328 	if (out->len - out->pos < 2) {
329 		ntlm_client_set_errmsg(ntlm, "out of buffer space");
330 		return false;
331 	}
332 
333 	out->buf[out->pos++] = (value & 0x000000ff);
334 	out->buf[out->pos++] = (value & 0x0000ff00) >> 8;
335 	out->buf[out->pos++] = (value & 0x00ff0000) >> 16;
336 	out->buf[out->pos++] = (value & 0xff000000) >> 24;
337 	return true;
338 }
339 
write_version(ntlm_client * ntlm,ntlm_buf * out,ntlm_version * version)340 static inline bool write_version(
341 	ntlm_client *ntlm,
342 	ntlm_buf *out,
343 	ntlm_version *version)
344 {
345 	return write_byte(ntlm, out, version->major) &&
346 		write_byte(ntlm, out, version->minor) &&
347 		write_int16(ntlm, out, version->build) &&
348 		write_int32(ntlm, out, version->reserved);
349 }
350 
write_bufinfo(ntlm_client * ntlm,ntlm_buf * out,size_t len,size_t offset)351 static inline bool write_bufinfo(
352 	ntlm_client *ntlm,
353 	ntlm_buf *out,
354 	size_t len,
355 	size_t offset)
356 {
357 	if (len > UINT16_MAX) {
358 		ntlm_client_set_errmsg(ntlm, "invalid string, too long");
359 		return false;
360 	}
361 
362 	if (offset > UINT32_MAX) {
363 		ntlm_client_set_errmsg(ntlm, "invalid string, invalid offset");
364 		return false;
365 	}
366 
367 	return write_int16(ntlm, out, (uint16_t)len) &&
368 		write_int16(ntlm, out, (uint16_t)len) &&
369 		write_int32(ntlm, out, (uint32_t)offset);
370 }
371 
read_buf(unsigned char * out,ntlm_client * ntlm,ntlm_buf * message,size_t len)372 static inline bool read_buf(
373 	unsigned char *out,
374 	ntlm_client *ntlm,
375 	ntlm_buf *message,
376 	size_t len)
377 {
378 	if (message->len - message->pos < len) {
379 		ntlm_client_set_errmsg(ntlm, "truncated message");
380 		return false;
381 	}
382 
383 	memcpy(out, &message->buf[message->pos], len);
384 	message->pos += len;
385 
386 	return true;
387 }
388 
read_byte(uint8_t * out,ntlm_client * ntlm,ntlm_buf * message)389 static inline bool read_byte(
390 	uint8_t *out,
391 	ntlm_client *ntlm,
392 	ntlm_buf *message)
393 {
394 	if (message->len - message->pos < 1) {
395 		ntlm_client_set_errmsg(ntlm, "truncated message");
396 		return false;
397 	}
398 
399 	*out = message->buf[message->pos++];
400 	return true;
401 }
402 
read_int16(uint16_t * out,ntlm_client * ntlm,ntlm_buf * message)403 static inline bool read_int16(
404 	uint16_t *out,
405 	ntlm_client *ntlm,
406 	ntlm_buf *message)
407 {
408 	if (message->len - message->pos < 2) {
409 		ntlm_client_set_errmsg(ntlm, "truncated message");
410 		return false;
411 	}
412 
413 	*out =
414 		((message->buf[message->pos]   & 0xff)) |
415 		((message->buf[message->pos+1] & 0xff) << 8);
416 
417 	message->pos += 2;
418 	return true;
419 }
420 
read_int32(uint32_t * out,ntlm_client * ntlm,ntlm_buf * message)421 static inline bool read_int32(
422 	uint32_t *out,
423 	ntlm_client *ntlm,
424 	ntlm_buf *message)
425 {
426 	if (message->len - message->pos < 4) {
427 		ntlm_client_set_errmsg(ntlm, "truncated message");
428 		return false;
429 	}
430 
431 	*out =
432 		((message->buf[message->pos]   & 0xff)) |
433 		((message->buf[message->pos+1] & 0xff) << 8) |
434 		((message->buf[message->pos+2] & 0xff) << 16) |
435 		((message->buf[message->pos+3] & 0xff) << 24);
436 
437 	message->pos += 4;
438 	return true;
439 }
440 
read_int64(uint64_t * out,ntlm_client * ntlm,ntlm_buf * message)441 static inline bool read_int64(
442 	uint64_t *out,
443 	ntlm_client *ntlm,
444 	ntlm_buf *message)
445 {
446 	if (message->len - message->pos < 8) {
447 		ntlm_client_set_errmsg(ntlm, "truncated message");
448 		return false;
449 	}
450 
451 	*out =
452 		((uint64_t)(message->buf[message->pos]   & 0xff)) |
453 		((uint64_t)(message->buf[message->pos+1] & 0xff) << 8) |
454 		((uint64_t)(message->buf[message->pos+2] & 0xff) << 16) |
455 		((uint64_t)(message->buf[message->pos+3] & 0xff) << 24) |
456 		((uint64_t)(message->buf[message->pos+4] & 0xff) << 32) |
457 		((uint64_t)(message->buf[message->pos+5] & 0xff) << 40) |
458 		((uint64_t)(message->buf[message->pos+6] & 0xff) << 48) |
459 		((uint64_t)(message->buf[message->pos+7] & 0xff) << 56);
460 
461 	message->pos += 8;
462 	return true;
463 }
464 
read_version(ntlm_version * out,ntlm_client * ntlm,ntlm_buf * message)465 static inline bool read_version(
466 	ntlm_version *out,
467 	ntlm_client *ntlm,
468 	ntlm_buf *message)
469 {
470 	return read_byte(&out->major, ntlm, message) &&
471 		read_byte(&out->minor, ntlm, message) &&
472 		read_int16(&out->build, ntlm, message) &&
473 		read_int32(&out->reserved, ntlm, message);
474 }
475 
read_bufinfo(uint16_t * out_len,uint32_t * out_offset,ntlm_client * ntlm,ntlm_buf * message)476 static inline bool read_bufinfo(
477 	uint16_t *out_len,
478 	uint32_t *out_offset,
479 	ntlm_client *ntlm,
480 	ntlm_buf *message)
481 {
482 	uint16_t allocated;
483 
484 	return read_int16(out_len, ntlm, message) &&
485 		read_int16(&allocated, ntlm, message) &&
486 		read_int32(out_offset, ntlm, message);
487 }
488 
read_string_unicode(char ** out,ntlm_client * ntlm,ntlm_buf * message,uint8_t string_len)489 static inline bool read_string_unicode(
490 	char **out,
491 	ntlm_client *ntlm,
492 	ntlm_buf *message,
493 	uint8_t string_len)
494 {
495 	size_t out_len;
496 	int ret = ntlm_unicode_utf16_to_8(out,
497 		&out_len,
498 		ntlm,
499 		(char *)&message->buf[message->pos],
500 		string_len);
501 
502 	message->pos += string_len;
503 
504 	return ret;
505 }
506 
read_string_ascii(char ** out,ntlm_client * ntlm,ntlm_buf * message,uint8_t string_len)507 static inline bool read_string_ascii(
508 	char **out,
509 	ntlm_client *ntlm,
510 	ntlm_buf *message,
511 	uint8_t string_len)
512 {
513 	char *str;
514 
515 	if ((str = malloc(string_len + 1)) == NULL) {
516 		ntlm_client_set_errmsg(ntlm, "out of memory");
517 		return false;
518 	}
519 
520 	memcpy(str, &message->buf[message->pos], string_len);
521 	str[string_len] = '\0';
522 
523 	message->pos += string_len;
524 
525 	*out = str;
526 	return true;
527 }
528 
read_string(char ** out,ntlm_client * ntlm,ntlm_buf * message,uint8_t string_len,bool unicode)529 static inline bool read_string(
530 	char **out,
531 	ntlm_client *ntlm,
532 	ntlm_buf *message,
533 	uint8_t string_len,
534 	bool unicode)
535 {
536 	if (unicode)
537 		return read_string_unicode(out, ntlm, message, string_len);
538 	else
539 		return read_string_ascii(out, ntlm, message, string_len);
540 }
541 
read_target_info(char ** server_out,char ** domain_out,char ** server_dns_out,char ** domain_dns_out,ntlm_client * ntlm,ntlm_buf * message,bool unicode)542 static inline bool read_target_info(
543 	char **server_out,
544 	char **domain_out,
545 	char **server_dns_out,
546 	char **domain_dns_out,
547 	ntlm_client *ntlm,
548 	ntlm_buf *message,
549 	bool unicode)
550 {
551 	uint16_t block_type, block_len;
552 	bool done = false;
553 
554 	*server_out = NULL;
555 	*domain_out = NULL;
556 	*server_dns_out = NULL;
557 	*domain_dns_out = NULL;
558 
559 	while (!done && (message->len - message->pos) >= 4) {
560 		if (!read_int16(&block_type, ntlm, message) ||
561 			!read_int16(&block_len, ntlm, message)) {
562 			ntlm_client_set_errmsg(ntlm, "truncated target info block");
563 			return false;
564 		}
565 
566 		if (!block_type && block_len) {
567 			ntlm_client_set_errmsg(ntlm, "invalid target info block");
568 			return -1;
569 		}
570 
571 		switch (block_type) {
572 		case NTLM_TARGET_INFO_DOMAIN:
573 			if (!read_string(domain_out, ntlm, message, block_len, unicode))
574 				return -1;
575 			break;
576 		case NTLM_TARGET_INFO_SERVER:
577 			if (!read_string(server_out, ntlm, message, block_len, unicode))
578 				return -1;
579 			break;
580 		case NTLM_TARGET_INFO_DOMAIN_DNS:
581 			if (!read_string(domain_dns_out, ntlm, message, block_len, unicode))
582 				return -1;
583 			break;
584 		case NTLM_TARGET_INFO_SERVER_DNS:
585 			if (!read_string(server_dns_out, ntlm, message, block_len, unicode))
586 				return -1;
587 			break;
588 		case NTLM_TARGET_INFO_END:
589 			done = true;
590 			break;
591 		default:
592 			ntlm_client_set_errmsg(ntlm, "unknown target info block type");
593 			return -1;
594 		}
595 	}
596 
597 	if (message->len != message->pos) {
598 		ntlm_client_set_errmsg(ntlm,
599 			"invalid extra data in target info section");
600 		return false;
601 	}
602 
603 	return true;
604 }
605 
ntlm_client_negotiate(const unsigned char ** out,size_t * out_len,ntlm_client * ntlm)606 int ntlm_client_negotiate(
607 	const unsigned char **out,
608 	size_t *out_len,
609 	ntlm_client *ntlm)
610 {
611 	size_t hostname_len, domain_len;
612 	size_t domain_offset = 0;
613 	size_t hostname_offset = 0;
614 	uint32_t flags = 0;
615 
616 	NTLM_ASSERT_ARG(out);
617 	NTLM_ASSERT_ARG(out_len);
618 	NTLM_ASSERT_ARG(ntlm);
619 
620 	*out = NULL;
621 	*out_len = 0;
622 
623 	if (ntlm->state != NTLM_STATE_NEGOTIATE) {
624 		ntlm_client_set_errmsg(ntlm, "ntlm handle in invalid state");
625 		return -1;
626 	}
627 
628 	flags |= NTLM_NEGOTIATE_OEM;
629 
630 	if (supports_unicode(ntlm))
631 		flags |= NTLM_NEGOTIATE_UNICODE;
632 
633 	if (!(ntlm->flags & NTLM_CLIENT_DISABLE_NTLM2) ||
634 		(ntlm->flags & NTLM_CLIENT_ENABLE_NTLM))
635 		flags |= NTLM_NEGOTIATE_NTLM;
636 
637 	if (!(ntlm->flags & NTLM_CLIENT_DISABLE_REQUEST_TARGET))
638 		flags |= NTLM_NEGOTIATE_REQUEST_TARGET;
639 
640 	hostname_len = ntlm->hostname ? strlen(ntlm->hostname) : 0;
641 	domain_len = ntlm->hostdomain ? strlen(ntlm->hostdomain) : 0;
642 
643 	/* Minimum header size */
644 	ntlm->negotiate.len = 16;
645 
646 	/* Include space for security buffer descriptors */
647 	if (domain_len)
648 		increment_size(&ntlm->negotiate.len, 8);
649 
650 	if (hostname_len)
651 		increment_size(&ntlm->negotiate.len, 8);
652 
653 	if (ntlm->flags & NTLM_ENABLE_HOSTVERSION)
654 		increment_size(&ntlm->negotiate.len, 8);
655 
656 	/* Location of security buffers */
657 	if (hostname_len) {
658 		flags |= NTLM_NEGOTIATE_WORKSTATION_SUPPLIED;
659 		hostname_offset = ntlm->negotiate.len;
660 		increment_size(&ntlm->negotiate.len, hostname_len);
661 	}
662 
663 	if (domain_len) {
664 		flags |= NTLM_NEGOTIATE_DOMAIN_SUPPLIED;
665 		domain_offset = ntlm->negotiate.len;
666 		increment_size(&ntlm->negotiate.len, domain_len);
667 	}
668 
669 	if (ntlm->negotiate.len == (size_t)-1) {
670 		ntlm_client_set_errmsg(ntlm, "message too large");
671 		return -1;
672 	}
673 
674 	if ((ntlm->negotiate.buf = calloc(1, ntlm->negotiate.len)) == NULL) {
675 		ntlm_client_set_errmsg(ntlm, "out of memory");
676 		return -1;
677 	}
678 
679 	if (!write_buf(ntlm, &ntlm->negotiate,
680 			ntlm_client_signature, sizeof(ntlm_client_signature)) ||
681 		!write_int32(ntlm, &ntlm->negotiate, 1) ||
682 		!write_int32(ntlm, &ntlm->negotiate, flags))
683 		return -1;
684 
685 	/* Domain information */
686 	if (domain_len > 0 &&
687 		!write_bufinfo(ntlm, &ntlm->negotiate, domain_len, domain_offset))
688 		return -1;
689 
690 	/* Workstation information */
691 	if (hostname_len > 0 &&
692 		!write_bufinfo(ntlm, &ntlm->negotiate, hostname_len, hostname_offset))
693 		return -1;
694 
695 	/* Version number */
696 	if (!!(ntlm->flags & NTLM_ENABLE_HOSTVERSION) &&
697 		!write_version(ntlm, &ntlm->negotiate, &ntlm->host_version))
698 		return -1;
699 
700 	if (hostname_len > 0) {
701 		NTLM_ASSERT(ntlm, hostname_offset == ntlm->negotiate.pos);
702 
703 		if (!write_buf(ntlm, &ntlm->negotiate,
704 			(const unsigned char *)ntlm->hostname, hostname_len))
705 			return -1;
706 	}
707 
708 	if (domain_len > 0) {
709 		NTLM_ASSERT(ntlm, domain_offset == ntlm->negotiate.pos);
710 
711 		if (!write_buf(ntlm, &ntlm->negotiate,
712 			(const unsigned char *)ntlm->hostdomain, domain_len))
713 			return -1;
714 	}
715 
716 	NTLM_ASSERT(ntlm, ntlm->negotiate.pos == ntlm->negotiate.len);
717 
718 	ntlm->state = NTLM_STATE_CHALLENGE;
719 
720 	*out = ntlm->negotiate.buf;
721 	*out_len = ntlm->negotiate.len;
722 
723 	return 0;
724 }
725 
ntlm_client_set_challenge(ntlm_client * ntlm,const unsigned char * challenge_msg,size_t challenge_msg_len)726 int ntlm_client_set_challenge(
727 	ntlm_client *ntlm,
728 	const unsigned char *challenge_msg,
729 	size_t challenge_msg_len)
730 {
731 	unsigned char signature[8];
732 	ntlm_buf challenge;
733 	uint32_t type_indicator, header_end;
734 	uint16_t name_len, info_len = 0;
735 	uint32_t name_offset, info_offset = 0;
736 	bool unicode, has_target_info = false;
737 
738 	NTLM_ASSERT_ARG(ntlm);
739 	NTLM_ASSERT_ARG(challenge_msg || !challenge_msg_len);
740 
741 	ENSURE_INITIALIZED(ntlm);
742 
743 	if (ntlm->state != NTLM_STATE_NEGOTIATE &&
744 		ntlm->state != NTLM_STATE_CHALLENGE) {
745 		ntlm_client_set_errmsg(ntlm, "ntlm handle in invalid state");
746 		return -1;
747 	}
748 
749 	challenge.buf = (unsigned char *)challenge_msg;
750 	challenge.len = challenge_msg_len;
751 	challenge.pos = 0;
752 
753 	if (!read_buf(signature, ntlm, &challenge, 8) ||
754 		!read_int32(&type_indicator, ntlm, &challenge) ||
755 		!read_bufinfo(&name_len, &name_offset, ntlm, &challenge) ||
756 		!read_int32(&ntlm->challenge.flags, ntlm, &challenge) ||
757 		!read_int64(&ntlm->challenge.nonce, ntlm, &challenge))
758 		return -1;
759 
760 	if (memcmp(signature,
761 			ntlm_client_signature, sizeof(ntlm_client_signature)) != 0) {
762 		ntlm_client_set_errmsg(ntlm, "invalid message signature");
763 		return -1;
764 	}
765 
766 	if (type_indicator != 2) {
767 		ntlm_client_set_errmsg(ntlm, "invalid message indicator");
768 		return -1;
769 	}
770 
771 	/*
772 	 * If there's additional space before the data section, that's the
773 	 * target information description section.
774 	 */
775 	header_end = challenge.len;
776 
777 	if (name_offset && name_offset < header_end)
778 		header_end = name_offset;
779 
780 	if ((header_end - challenge.pos) >= 16) {
781 		has_target_info = true;
782 	}
783 
784 	if (!has_target_info &&
785 		(ntlm->challenge.flags & NTLM_NEGOTIATE_TARGET_INFO)) {
786 		ntlm_client_set_errmsg(ntlm,
787 			"truncated message; expected target info");
788 		return -1;
789 	}
790 
791 	/*
792 	 * If there's a target info section then advanced over the reserved
793 	 * space and read the target information.
794 	 */
795 	if (has_target_info) {
796 		uint64_t reserved;
797 
798 		if (!read_int64(&reserved, ntlm, &challenge)) {
799 			ntlm_client_set_errmsg(ntlm,
800 				"truncated message; expected reserved space");
801 			return -1;
802 		}
803 
804 		if (reserved != 0) {
805 			ntlm_client_set_errmsg(ntlm,
806 				"invalid message; expected reserved space to be empty");
807 			return -1;
808 		}
809 
810 		if (!read_bufinfo(&info_len, &info_offset, ntlm, &challenge)) {
811 			ntlm_client_set_errmsg(ntlm,
812 				"truncated message; expected target info");
813 			return -1;
814 		}
815 	}
816 
817 	unicode = !!(ntlm->challenge.flags & NTLM_NEGOTIATE_UNICODE);
818 
819 	/*
820 	 * If there's still additional space before the data section,
821 	 * that's the server's version information.
822 	 */
823 	if (info_offset && info_offset < header_end)
824 		header_end = info_offset;
825 
826 	if (ntlm->challenge.flags & NTLM_NEGOTIATE_VERSION) {
827 		if ((header_end - challenge.pos) != sizeof(ntlm_version) ||
828 			!read_version(&ntlm->challenge.target_version,
829 				ntlm, &challenge)) {
830 			ntlm_client_set_errmsg(ntlm,
831 				"truncated message; expected version");
832 			return -1;
833 		}
834 	}
835 
836 	/* validate data section */
837 	if ((name_offset && name_offset < challenge.pos) ||
838 		challenge.len < name_len ||
839 		(challenge.len - name_len) < name_offset) {
840 		ntlm_client_set_errmsg(ntlm,
841 			"invalid message; invalid target name buffer");
842 		return -1;
843 	}
844 	if ((info_offset && info_offset < challenge.pos) ||
845 		challenge.len < info_len ||
846 		(challenge.len - info_len) < info_offset) {
847 		ntlm_client_set_errmsg(ntlm,
848 			"invalid message; invalid target info buffer");
849 		return -1;
850 	}
851 
852 	/* advance to the data section */
853 	if (name_len && name_offset) {
854 		challenge.pos = name_offset;
855 
856 		if (!read_string(&ntlm->challenge.target,
857 			ntlm, &challenge, name_len, unicode)) {
858 			ntlm_client_set_errmsg(ntlm,
859 				"truncated message; truncated target name");
860 			return -1;
861 		}
862 	}
863 
864 	if (info_len && info_offset) {
865 		ntlm_buf info_buf;
866 
867 		challenge.pos = info_offset;
868 
869 		/* create a copy of the target info; we need the literal data */
870 		if ((ntlm->challenge.target_info = malloc(info_len)) == NULL) {
871 			ntlm_client_set_errmsg(ntlm, "out of memory");
872 			return -1;
873 		}
874 
875 		if (!read_buf(ntlm->challenge.target_info,
876 				ntlm, &challenge, info_len)) {
877 			ntlm_client_set_errmsg(ntlm,
878 				"truncated message; truncated target info");
879 			return -1;
880 		}
881 
882 		info_buf.buf = ntlm->challenge.target_info;
883 		info_buf.pos = 0;
884 		info_buf.len = info_len;
885 
886 		/* then set up the target info and parse it */
887 		if (!read_target_info(&ntlm->challenge.target_server,
888 				&ntlm->challenge.target_domain,
889 				&ntlm->challenge.target_server_dns,
890 				&ntlm->challenge.target_domain_dns,
891 				ntlm, &info_buf, unicode))
892 			return -1;
893 
894 		ntlm->challenge.target_info_len = info_len;
895 	}
896 
897 	ntlm->state = NTLM_STATE_RESPONSE;
898 
899 	return 0;
900 }
901 
ntlm_client_challenge_nonce(ntlm_client * ntlm)902 uint64_t ntlm_client_challenge_nonce(ntlm_client *ntlm)
903 {
904 	return ntlm->challenge.nonce;
905 }
906 
ntlm_client_target(ntlm_client * ntlm)907 const char *ntlm_client_target(ntlm_client *ntlm)
908 {
909 	return ntlm->challenge.target;
910 }
911 
ntlm_client_target_server(ntlm_client * ntlm)912 const char *ntlm_client_target_server(ntlm_client *ntlm)
913 {
914 	return ntlm->challenge.target_server;
915 }
916 
ntlm_client_target_domain(ntlm_client * ntlm)917 const char *ntlm_client_target_domain(ntlm_client *ntlm)
918 {
919 	return ntlm->challenge.target_domain;
920 }
921 
ntlm_client_target_server_dns(ntlm_client * ntlm)922 const char *ntlm_client_target_server_dns(ntlm_client *ntlm)
923 {
924 	return ntlm->challenge.target_server_dns;
925 }
926 
ntlm_client_target_domain_dns(ntlm_client * ntlm)927 const char *ntlm_client_target_domain_dns(ntlm_client *ntlm)
928 {
929 	return ntlm->challenge.target_domain_dns;
930 }
931 
932 #define EVEN_PARITY(a) \
933 	(!!((a) & 0x01ll) ^ !!((a) & 0x02ll) ^ \
934 	 !!((a) & 0x04ll) ^ !!((a) & 0x08ll) ^ \
935 	 !!((a) & 0x10ll) ^ !!((a) & 0x20ll) ^ \
936 	 !!((a) & 0x40ll) ^ !!((a) & 0x80ll))
937 
generate_odd_parity(ntlm_des_block * block)938 static void generate_odd_parity(ntlm_des_block *block)
939 {
940 	size_t i;
941 
942 	for (i = 0; i < sizeof(ntlm_des_block); i++)
943 		(*block)[i] |= (1 ^ EVEN_PARITY((*block)[i]));
944 }
945 
des_key_from_password(ntlm_des_block * out,const unsigned char * plaintext,size_t plaintext_len)946 static void des_key_from_password(
947 	ntlm_des_block *out,
948 	const unsigned char *plaintext,
949 	size_t plaintext_len)
950 {
951 	size_t i;
952 
953 	plaintext_len = MIN(plaintext_len, 7);
954 
955 	memset(*out, 0, sizeof(ntlm_des_block));
956 
957 	for (i = 0; i < plaintext_len; i++) {
958 		size_t j = (7 - i);
959 		uint8_t mask = (0xff >> j);
960 
961 		(*out)[i]   |= ((plaintext[i] & (0xff - mask)) >> i);
962 		(*out)[i+1] |= ((plaintext[i] & mask) << j);
963 	}
964 
965 	generate_odd_parity(out);
966 }
967 
generate_lm_hash(ntlm_des_block out[2],ntlm_client * ntlm,const char * password)968 static inline bool generate_lm_hash(
969 	ntlm_des_block out[2],
970 	ntlm_client *ntlm,
971 	const char *password)
972 {
973 	/* LM encrypts this known plaintext using the password as a key */
974 	ntlm_des_block plaintext = NTLM_LM_PLAINTEXT;
975 	ntlm_des_block keystr1, keystr2;
976 	size_t keystr1_len, keystr2_len;
977 	ntlm_des_block key1, key2;
978 	size_t password_len, i;
979 
980 	/* Copy the first 14 characters of the password, uppercased */
981 	memset(&keystr1, 0, sizeof(keystr1));
982 	memset(&keystr2, 0, sizeof(keystr2));
983 
984 	password_len = password ? strlen(password) : 0;
985 
986 	/* Split the password into two 7 byte chunks */
987 	keystr1_len = MIN(7, password_len);
988 	keystr2_len = (password_len > 7) ? MIN(14, password_len) - 7 : 0;
989 
990 	for (i = 0; i < keystr1_len; i++)
991 		keystr1[i] = (unsigned char)toupper(password[i]);
992 	for (i = 0; i < keystr2_len; i++)
993 		keystr2[i] = (unsigned char)toupper(password[i+7]);
994 
995 	/* DES encrypt the LM constant using the password as the key */
996 	des_key_from_password(&key1, keystr1, keystr1_len);
997 	des_key_from_password(&key2, keystr2, keystr2_len);
998 
999 	return ntlm_des_encrypt(&out[0], ntlm, &plaintext, &key1) &&
1000 		ntlm_des_encrypt(&out[1], ntlm, &plaintext, &key2);
1001 }
1002 
des_keys_from_lm_hash(ntlm_des_block out[3],ntlm_des_block lm_hash[2])1003 static void des_keys_from_lm_hash(ntlm_des_block out[3], ntlm_des_block lm_hash[2])
1004 {
1005 	ntlm_des_block split[3];
1006 
1007 	memcpy(&split[0][0], &lm_hash[0][0], 7);
1008 
1009 	memcpy(&split[1][0], &lm_hash[0][7], 1);
1010 	memcpy(&split[1][1], &lm_hash[1][0], 6);
1011 
1012 	memcpy(&split[2][0], &lm_hash[1][6], 2);
1013 
1014 	des_key_from_password(&out[0], split[0], 7);
1015 	des_key_from_password(&out[1], split[1], 7);
1016 	des_key_from_password(&out[2], split[2], 2);
1017 }
1018 
generate_lm_response(ntlm_client * ntlm)1019 static bool generate_lm_response(ntlm_client *ntlm)
1020 {
1021 	ntlm_des_block lm_hash[2], key[3], lm_response[3];
1022 	ntlm_des_block *challenge = (ntlm_des_block *)&ntlm->challenge.nonce;
1023 
1024 	/* Generate the LM hash from the password */
1025 	if (!generate_lm_hash(lm_hash, ntlm, ntlm->password))
1026 		return false;
1027 
1028 	/* Convert that LM hash to three DES keys */
1029 	des_keys_from_lm_hash(key, lm_hash);
1030 
1031 	/* Finally, encrypt the challenge with each of these keys */
1032 	if (!ntlm_des_encrypt(&lm_response[0], ntlm, challenge, &key[0]) ||
1033 		!ntlm_des_encrypt(&lm_response[1], ntlm, challenge, &key[1]) ||
1034 		!ntlm_des_encrypt(&lm_response[2], ntlm, challenge, &key[2]))
1035 		return false;
1036 
1037 	memcpy(&ntlm->lm_response[0], lm_response[0], 8);
1038 	memcpy(&ntlm->lm_response[8], lm_response[1], 8);
1039 	memcpy(&ntlm->lm_response[16], lm_response[2], 8);
1040 
1041 	ntlm->lm_response_len = sizeof(ntlm->lm_response);
1042 
1043 	return true;
1044 }
1045 
generate_ntlm_hash(unsigned char out[NTLM_NTLM_HASH_LEN],ntlm_client * ntlm)1046 static bool generate_ntlm_hash(
1047 	unsigned char out[NTLM_NTLM_HASH_LEN], ntlm_client *ntlm)
1048 {
1049 	/* Generate the LM hash from the (Unicode) password */
1050 	if (ntlm->password && !ntlm_unicode_utf8_to_16(
1051 			&ntlm->password_utf16,
1052 			&ntlm->password_utf16_len,
1053 			ntlm,
1054 			ntlm->password,
1055 			strlen(ntlm->password)))
1056 		return false;
1057 
1058 	return ntlm_md4_digest(out,
1059 		ntlm,
1060 		(const unsigned char *)ntlm->password_utf16,
1061 		ntlm->password_utf16_len);
1062 }
1063 
generate_ntlm_response(ntlm_client * ntlm)1064 static bool generate_ntlm_response(ntlm_client *ntlm)
1065 {
1066 	unsigned char ntlm_hash[NTLM_NTLM_HASH_LEN] = {0};
1067 	ntlm_des_block key[3], ntlm_response[3];
1068 	ntlm_des_block *challenge =
1069 		(ntlm_des_block *)&ntlm->challenge.nonce;
1070 
1071 	if (!generate_ntlm_hash(ntlm_hash, ntlm))
1072 		return false;
1073 
1074 	/* Convert that LM hash to three DES keys */
1075 	des_key_from_password(&key[0], &ntlm_hash[0], 7);
1076 	des_key_from_password(&key[1], &ntlm_hash[7], 7);
1077 	des_key_from_password(&key[2], &ntlm_hash[14], 2);
1078 
1079 	/* Finally, encrypt the challenge with each of these keys */
1080 	if (!ntlm_des_encrypt(&ntlm_response[0], ntlm, challenge, &key[0]) ||
1081 		!ntlm_des_encrypt(&ntlm_response[1], ntlm, challenge, &key[1]) ||
1082 		!ntlm_des_encrypt(&ntlm_response[2], ntlm, challenge, &key[2]))
1083 		return false;
1084 
1085 	memcpy(&ntlm->ntlm_response[0], ntlm_response[0], 8);
1086 	memcpy(&ntlm->ntlm_response[8], ntlm_response[1], 8);
1087 	memcpy(&ntlm->ntlm_response[16], ntlm_response[2], 8);
1088 
1089 	ntlm->ntlm_response_len = sizeof(ntlm->ntlm_response);
1090 	return true;
1091 }
1092 
generate_ntlm2_hash(unsigned char out[NTLM_NTLM2_HASH_LEN],ntlm_client * ntlm)1093 static bool generate_ntlm2_hash(
1094 	unsigned char out[NTLM_NTLM2_HASH_LEN], ntlm_client *ntlm)
1095 {
1096 	unsigned char ntlm_hash[NTLM_NTLM_HASH_LEN] = {0};
1097 	const unsigned char *username = NULL, *target = NULL;
1098 	size_t username_len = 0, target_len = 0, out_len = NTLM_NTLM2_HASH_LEN;
1099 
1100 	if (!generate_ntlm_hash(ntlm_hash, ntlm))
1101 		return false;
1102 
1103 	if (ntlm->username_upper_utf16) {
1104 		username = (const unsigned char *)ntlm->username_upper_utf16;
1105 		username_len = ntlm->username_upper_utf16_len;
1106 	}
1107 
1108 	if (ntlm->target_utf16) {
1109 		target = (const unsigned char *)ntlm->target_utf16;
1110 		target_len = ntlm->target_utf16_len;
1111 	}
1112 
1113 	if (!ntlm_hmac_md5_init(ntlm, ntlm_hash, sizeof(ntlm_hash)) ||
1114 		!ntlm_hmac_md5_update(ntlm, username, username_len) ||
1115 		!ntlm_hmac_md5_update(ntlm, target, target_len) ||
1116 		!ntlm_hmac_md5_final(out, &out_len, ntlm)) {
1117 		ntlm_client_set_errmsg(ntlm, "failed to create HMAC-MD5");
1118 		return false;
1119 	}
1120 
1121 	NTLM_ASSERT(ntlm, out_len == NTLM_NTLM2_HASH_LEN);
1122 	return true;
1123 }
1124 
generate_ntlm2_challengehash(unsigned char out[16],ntlm_client * ntlm,unsigned char ntlm2_hash[NTLM_NTLM2_HASH_LEN],const unsigned char * blob,size_t blob_len)1125 static bool generate_ntlm2_challengehash(
1126 	unsigned char out[16],
1127 	ntlm_client *ntlm,
1128 	unsigned char ntlm2_hash[NTLM_NTLM2_HASH_LEN],
1129 	const unsigned char *blob,
1130 	size_t blob_len)
1131 {
1132 	size_t out_len = 16;
1133 
1134 	if (!ntlm_hmac_md5_init(ntlm, ntlm2_hash, NTLM_NTLM2_HASH_LEN) ||
1135 		!ntlm_hmac_md5_update(ntlm, (const unsigned char *)&ntlm->challenge.nonce, 8) ||
1136 		!ntlm_hmac_md5_update(ntlm, blob, blob_len) ||
1137 		!ntlm_hmac_md5_final(out, &out_len, ntlm)) {
1138 		ntlm_client_set_errmsg(ntlm, "failed to create HMAC-MD5");
1139 		return false;
1140 	}
1141 
1142 	NTLM_ASSERT(ntlm, out_len == 16);
1143 	return true;
1144 }
1145 
generate_lm2_response(ntlm_client * ntlm,unsigned char ntlm2_hash[NTLM_NTLM2_HASH_LEN])1146 static bool generate_lm2_response(ntlm_client *ntlm,
1147 	unsigned char ntlm2_hash[NTLM_NTLM2_HASH_LEN])
1148 {
1149 	unsigned char lm2_challengehash[16] = {0};
1150 	size_t lm2_len = 16;
1151 	uint64_t local_nonce;
1152 
1153 	local_nonce = ntlm_htonll(ntlm->nonce);
1154 
1155 	if (!ntlm_hmac_md5_init(ntlm, ntlm2_hash, NTLM_NTLM2_HASH_LEN) ||
1156 		!ntlm_hmac_md5_update(ntlm, (const unsigned char *)&ntlm->challenge.nonce, 8) ||
1157 		!ntlm_hmac_md5_update(ntlm, (const unsigned char *)&local_nonce, 8) ||
1158 		!ntlm_hmac_md5_final(lm2_challengehash, &lm2_len, ntlm)) {
1159 		ntlm_client_set_errmsg(ntlm, "failed to create HMAC-MD5");
1160 		return false;
1161 	}
1162 
1163 	NTLM_ASSERT(ntlm, lm2_len == 16);
1164 
1165 	memcpy(&ntlm->lm_response[0], lm2_challengehash, 16);
1166 	memcpy(&ntlm->lm_response[16], &local_nonce, 8);
1167 
1168 	ntlm->lm_response_len = 24;
1169 	return true;
1170 }
1171 
generate_timestamp(ntlm_client * ntlm)1172 static bool generate_timestamp(ntlm_client *ntlm)
1173 {
1174 	if (!ntlm->timestamp)
1175 		ntlm->timestamp = (time(NULL) + 11644473600) * 10000000;
1176 
1177 	return true;
1178 }
1179 
generate_nonce(ntlm_client * ntlm)1180 static bool generate_nonce(ntlm_client *ntlm)
1181 {
1182 	unsigned char buf[8];
1183 
1184 	if (ntlm->nonce)
1185 		return true;
1186 
1187 	if (!ntlm_random_bytes(buf, ntlm, 8))
1188 		return false;
1189 
1190 	memcpy(&ntlm->nonce, buf, sizeof(uint64_t));
1191 	return true;
1192 }
1193 
generate_ntlm2_response(ntlm_client * ntlm)1194 static bool generate_ntlm2_response(ntlm_client *ntlm)
1195 {
1196 	size_t blob_len, ntlm2_response_len;
1197 	uint32_t signature;
1198 	uint64_t timestamp, nonce;
1199 	unsigned char ntlm2_hash[NTLM_NTLM2_HASH_LEN];
1200 	unsigned char challengehash[16] = {0};
1201 	unsigned char *blob;
1202 
1203 	if (!generate_timestamp(ntlm) ||
1204 		!generate_nonce(ntlm) ||
1205 		!generate_ntlm2_hash(ntlm2_hash, ntlm))
1206 		return false;
1207 
1208 	blob_len = ntlm->challenge.target_info_len + 32;
1209 	ntlm2_response_len = blob_len + 16;
1210 
1211 	if ((ntlm->ntlm2_response = malloc(ntlm2_response_len)) == NULL) {
1212 		ntlm_client_set_errmsg(ntlm, "out of memory");
1213 		return false;
1214 	}
1215 
1216 	/* position the blob in the response; we'll use it then return it */
1217 	blob = ntlm->ntlm2_response + 16;
1218 
1219 	/* the blob's integer values are in network byte order */
1220 	signature = htonl(0x01010000);
1221 	timestamp = ntlm_htonll(ntlm->timestamp);
1222 	nonce = ntlm_htonll(ntlm->nonce);
1223 
1224 	/* construct the blob */
1225 	memcpy(&blob[0], &signature, 4);
1226 	memset(&blob[4], 0, 4);
1227 	memcpy(&blob[8], &timestamp, 8);
1228 	memcpy(&blob[16], &nonce, 8);
1229 	memset(&blob[24], 0, 4);
1230 	memcpy(&blob[28], ntlm->challenge.target_info, ntlm->challenge.target_info_len);
1231 	memset(&blob[28 + ntlm->challenge.target_info_len], 0, 4);
1232 
1233 	if (!generate_ntlm2_challengehash(challengehash, ntlm, ntlm2_hash, blob, blob_len))
1234 		return false;
1235 
1236 	memcpy(ntlm->ntlm2_response, challengehash, 16);
1237 	ntlm->ntlm2_response_len = ntlm2_response_len;
1238 
1239 	if (!generate_lm2_response(ntlm, ntlm2_hash))
1240 		return false;
1241 
1242 	return true;
1243 }
1244 
ntlm_client_response(const unsigned char ** out,size_t * out_len,ntlm_client * ntlm)1245 int ntlm_client_response(
1246 	const unsigned char **out,
1247 	size_t *out_len,
1248 	ntlm_client *ntlm)
1249 {
1250 	unsigned char *domain, *username, *hostname, *ntlm_rep, *session;
1251 	size_t lm_rep_len, lm_rep_offset, ntlm_rep_len, ntlm_rep_offset,
1252 		domain_len, domain_offset, username_len, username_offset,
1253 		hostname_len, hostname_offset, session_len, session_offset;
1254 	uint32_t flags = 0;
1255 	bool unicode;
1256 
1257 	NTLM_ASSERT_ARG(out);
1258 	NTLM_ASSERT_ARG(out_len);
1259 	NTLM_ASSERT_ARG(ntlm);
1260 
1261 	ENSURE_INITIALIZED(ntlm);
1262 
1263 	*out = NULL;
1264 	*out_len = 0;
1265 
1266 	if (ntlm->state != NTLM_STATE_RESPONSE) {
1267 		ntlm_client_set_errmsg(ntlm, "ntlm handle in invalid state");
1268 		return -1;
1269 	}
1270 
1271 	/*
1272 	 * Minimum message size is 64 bytes:
1273 	 *   8 byte signature,
1274 	 *   4 byte message indicator,
1275 	 * 6x8 byte security buffers
1276 	 *   4 byte flags
1277 	 */
1278 	ntlm->response.len = 64;
1279 
1280 	unicode = supports_unicode(ntlm) &&
1281 		(ntlm->challenge.flags & NTLM_NEGOTIATE_UNICODE);
1282 
1283 	if (unicode)
1284 		flags |= NTLM_NEGOTIATE_UNICODE;
1285 	else
1286 		flags |= NTLM_NEGOTIATE_OEM;
1287 
1288 	if (unicode) {
1289 		domain = (unsigned char *)ntlm->userdomain_utf16;
1290 		domain_len = ntlm->userdomain_utf16_len;
1291 
1292 		username = (unsigned char *)ntlm->username_utf16;
1293 		username_len = ntlm->username_utf16_len;
1294 
1295 		hostname = (unsigned char *)ntlm->hostname_utf16;
1296 		hostname_len = ntlm->hostname_utf16_len;
1297 	} else {
1298 		domain = (unsigned char *)ntlm->userdomain;
1299 		domain_len = ntlm->userdomain ? strlen(ntlm->userdomain) : 0;
1300 
1301 		username = (unsigned char *)ntlm->username;
1302 		username_len = ntlm->username ? strlen(ntlm->username) : 0;
1303 
1304 		hostname = (unsigned char *)ntlm->hostname;
1305 		hostname_len = ntlm->hostname ? strlen(ntlm->hostname) : 0;
1306 	}
1307 
1308 	/* Negotiate our requested authentication type with the server's */
1309 	if (!(ntlm->flags & NTLM_CLIENT_DISABLE_NTLM2) &&
1310 		(ntlm->challenge.flags & NTLM_NEGOTIATE_NTLM)) {
1311 		flags |= NTLM_NEGOTIATE_NTLM;
1312 
1313 		if (!generate_ntlm2_response(ntlm))
1314 			return -1;
1315 	} else if ((ntlm->flags & NTLM_CLIENT_ENABLE_NTLM) &&
1316 		(ntlm->challenge.flags & NTLM_NEGOTIATE_NTLM)) {
1317 		flags |= NTLM_NEGOTIATE_NTLM;
1318 
1319 		if (!generate_ntlm_response(ntlm) ||
1320 			!generate_lm_response(ntlm))
1321 			return -1;
1322 	} else if (ntlm->flags & NTLM_CLIENT_ENABLE_LM) {
1323 		if (!generate_lm_response(ntlm))
1324 			return -1;
1325 	} else {
1326 		ntlm_client_set_errmsg(ntlm,
1327 			"no encryption options could be negotiated");
1328 		return -1;
1329 	}
1330 
1331 	domain_offset = ntlm->response.len;
1332 	increment_size(&ntlm->response.len, domain_len);
1333 
1334 	username_offset = ntlm->response.len;
1335 	increment_size(&ntlm->response.len, username_len);
1336 
1337 	hostname_offset = ntlm->response.len;
1338 	increment_size(&ntlm->response.len, hostname_len);
1339 
1340 	lm_rep_len = ntlm->lm_response_len;
1341 	lm_rep_offset = ntlm->response.len;
1342 	increment_size(&ntlm->response.len, lm_rep_len);
1343 
1344 	ntlm_rep = ntlm->ntlm2_response_len ?
1345 		ntlm->ntlm2_response : ntlm->ntlm_response;
1346 	ntlm_rep_len = ntlm->ntlm2_response_len ?
1347 		ntlm->ntlm2_response_len : ntlm->ntlm_response_len;
1348 	ntlm_rep_offset = ntlm->response.len;
1349 	increment_size(&ntlm->response.len, ntlm_rep_len);
1350 
1351 	session = NULL;
1352 	session_len = 0;
1353 	session_offset = ntlm->response.len;
1354 	increment_size(&ntlm->response.len, session_len);
1355 
1356 	if (ntlm->response.len == (size_t)-1) {
1357 		ntlm_client_set_errmsg(ntlm, "message too large");
1358 		return -1;
1359 	}
1360 
1361 	if ((ntlm->response.buf = calloc(1, ntlm->response.len)) == NULL) {
1362 		ntlm_client_set_errmsg(ntlm, "out of memory");
1363 		return -1;
1364 	}
1365 
1366 	if (!write_buf(ntlm, &ntlm->response,
1367 			ntlm_client_signature, sizeof(ntlm_client_signature)) ||
1368 		!write_int32(ntlm, &ntlm->response, 3) ||
1369 		!write_bufinfo(ntlm, &ntlm->response, lm_rep_len, lm_rep_offset) ||
1370 		!write_bufinfo(ntlm, &ntlm->response, ntlm_rep_len, ntlm_rep_offset) ||
1371 		!write_bufinfo(ntlm, &ntlm->response, domain_len, domain_offset) ||
1372 		!write_bufinfo(ntlm, &ntlm->response, username_len, username_offset) ||
1373 		!write_bufinfo(ntlm, &ntlm->response, hostname_len, hostname_offset) ||
1374 		!write_bufinfo(ntlm, &ntlm->response, session_len, session_offset) ||
1375 		!write_int32(ntlm, &ntlm->response, flags) ||
1376 		!write_buf(ntlm, &ntlm->response, domain, domain_len) ||
1377 		!write_buf(ntlm, &ntlm->response, username, username_len) ||
1378 		!write_buf(ntlm, &ntlm->response, hostname, hostname_len) ||
1379 		!write_buf(ntlm, &ntlm->response, ntlm->lm_response, lm_rep_len) ||
1380 		!write_buf(ntlm, &ntlm->response, ntlm_rep, ntlm_rep_len) ||
1381 		!write_buf(ntlm, &ntlm->response, session, session_len))
1382 		return -1;
1383 
1384 	NTLM_ASSERT(ntlm, ntlm->response.pos == ntlm->response.len);
1385 
1386 	ntlm->state = NTLM_STATE_COMPLETE;
1387 
1388 	*out = ntlm->response.buf;
1389 	*out_len = ntlm->response.len;
1390 
1391 	return 0;
1392 }
1393 
ntlm_client_reset(ntlm_client * ntlm)1394 void ntlm_client_reset(ntlm_client *ntlm)
1395 {
1396 	if (!ntlm)
1397 		return;
1398 
1399 	ntlm->state = NTLM_STATE_NEGOTIATE;
1400 
1401 	free_hostname(ntlm);
1402 
1403 	memset(&ntlm->host_version, 0, sizeof(ntlm_version));
1404 
1405 	reset(ntlm->target);
1406 	reset(ntlm->target_utf16);
1407 	ntlm->target_utf16_len = 0;
1408 
1409 	free_credentials(ntlm);
1410 
1411 	ntlm->nonce = 0;
1412 	ntlm->timestamp = 0;
1413 
1414 	memset(ntlm->lm_response, 0, NTLM_LM_RESPONSE_LEN);
1415 	ntlm->lm_response_len = 0;
1416 
1417 	memset(ntlm->ntlm_response, 0, NTLM_NTLM_RESPONSE_LEN);
1418 	ntlm->ntlm_response_len = 0;
1419 
1420 	reset(ntlm->ntlm2_response);
1421 	ntlm->ntlm2_response_len = 0;
1422 
1423 	reset(ntlm->negotiate.buf);
1424 	ntlm->negotiate.pos = 0;
1425 	ntlm->negotiate.len = 0;
1426 
1427 	reset(ntlm->response.buf);
1428 	ntlm->response.pos = 0;
1429 	ntlm->response.len = 0;
1430 
1431 	free(ntlm->challenge.target_info);
1432 	free(ntlm->challenge.target);
1433 	free(ntlm->challenge.target_domain);
1434 	free(ntlm->challenge.target_domain_dns);
1435 	free(ntlm->challenge.target_server);
1436 	free(ntlm->challenge.target_server_dns);
1437 	memset(&ntlm->challenge, 0, sizeof(ntlm_challenge));
1438 }
1439 
ntlm_client_free(ntlm_client * ntlm)1440 void ntlm_client_free(ntlm_client *ntlm)
1441 {
1442 	if (!ntlm)
1443 		return;
1444 
1445 	ntlm_crypt_shutdown(ntlm);
1446 	ntlm_unicode_shutdown(ntlm);
1447 
1448 	ntlm_client_reset(ntlm);
1449 
1450 	free(ntlm);
1451 }
1452