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], ×tamp, 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