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