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