summaryrefslogtreecommitdiffstats
path: root/src/ntlm.h
blob: 51204ec580f8e06b2e0b4c28ec8ec7b8838363bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
/*
   Copyright (C) 2013 Simo Sorce <simo@samba.org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 3 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _NTLM_H_
#define _NTLM_H

#include <stdbool.h>

#include "ntlm_common.h"

/* Negotiate Flags */
#define NTLMSSP_NEGOTIATE_56                        (1 << 31)
#define NTLMSSP_NEGOTIATE_KEY_EXCH                  (1 << 30)
#define NTLMSSP_NEGOTIATE_128                       (1 << 29)
#define UNUSED_R1                                   (1 << 28)
#define UNUSED_R2                                   (1 << 27)
#define UNUSED_R3                                   (1 << 26)
#define NTLMSSP_NEGOTIATE_VERSION                   (1 << 25)
#define UNUSED_R4                                   (1 << 24)
#define NTLMSSP_NEGOTIATE_TARGET_INFO               (1 << 23)
#define NTLMSSP_REQUEST_NON_NT_SESSION_KEY          (1 << 22)
#define UNUSED_R5 /* Davenport: NEGOTIATE_ACCEPT */ (1 << 21)
#define NTLMSSP_NEGOTIATE_IDENTIFY                  (1 << 20)
#define NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY  (1 << 19)
#define UNUSED_R6 /* Davenport:TARGET_TYPE_SHARE */ (1 << 18)
#define NTLMSSP_TARGET_TYPE_SERVER                  (1 << 17)
#define NTLMSSP_TARGET_TYPE_DOMAIN                  (1 << 16)
#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN               (1 << 15)
#define UNUSED_R7 /* Davenport:LOCAL_CALL */        (1 << 14)
#define NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED  (1 << 13)
#define NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED       (1 << 12)
#define NTLMSSP_ANONYMOUS                           (1 << 11)
#define UNUSED_R8                                   (1 << 10)
#define NTLMSSP_NEGOTIATE_NTLM                      (1 << 9)
#define UNUSED_R9                                   (1 << 8)
#define NTLMSSP_NEGOTIATE_LM_KEY                    (1 << 7)
#define NTLMSSP_NEGOTIATE_DATAGRAM                  (1 << 6)
#define NTLMSSP_NEGOTIATE_SEAL                      (1 << 5)
#define NTLMSSP_NEGOTIATE_SIGN                      (1 << 4)
#define UNUSED_R10                                  (1 << 3)
#define NTLMSSP_REQUEST_TARGET                      (1 << 2)
#define NTLMSSP_NEGOTIATE_OEM                       (1 << 1)
#define NTLMSSP_NEGOTIATE_UNICODE                   (1 << 0)

/* (2.2.2.10 VERSION) */
#define WINDOWS_MAJOR_VERSION_5 0x05
#define WINDOWS_MAJOR_VERSION_6 0x06
#define WINDOWS_MINOR_VERSION_0 0x00
#define WINDOWS_MINOR_VERSION_1 0x01
#define WINDOWS_MINOR_VERSION_2 0x02
#define NTLMSSP_REVISION_W2K3 0x0F

#define NTLMSSP_VERSION_MAJOR WINDOWS_MAJOR_VERSION_6
#define NTLMSSP_VERSION_MINOR WINDOWS_MINOR_VERSION_2
#define NTLMSSP_VERSION_BUILD 0
#define NTLMSSP_VERSION_REV NTLMSSP_REVISION_W2K3

#define NTLMSSP_MESSAGE_SIGNATURE_VERSION 0x00000001

#define NEGOTIATE_MESSAGE       0x00000001
#define CHALLENGE_MESSAGE       0x00000002
#define AUTHENTICATE_MESSAGE    0x00000003

#define MSVAVFLAGS_AUTH_CONSTRAINED 0x01
#define MSVAVFLAGS_MIC_PRESENT      0x02
#define MSVAVFLAGS_UNVERIFIED_SPN   0x04

#define NTLM_SIGNATURE_SIZE 16

struct ntlm_ctx;

/**
 * @brief           Create a ntlm_ctx initialized to the initial state
 *
 * @param ctx       The returned context
 *
 * @return 0 if successful, an error otherwise
 */
int ntlm_init_ctx(struct ntlm_ctx **ctx);

/**
 * @brief           Frees a ntlm_ctx
 *
 * @param ctx       Pointer to a context to be freed
 *
 * @return 0 if successful, an error otherwise
 * NOTE: even if an error is returned the contetx is freed and NULLed
 */
int ntlm_free_ctx(struct ntlm_ctx **ctx);

void ntlm_free_buffer_data(struct ntlm_buffer *buf);

uint64_t ntlm_timestamp_now(void);

bool ntlm_casecmp(const char *s1, const char *s2);

/**
 * @brief Sets the NTLMSSP version
 *        Mostly used to emulate Windows versions for test vectors
 *
 * @param major     major version number (ex. 6)
 * @param minor     minor version number (ex. 1)
 * @param build     build version number (ex. 7600)
 * @param revision  revision version number (ex. 16)
 */
void ntlm_internal_set_version(uint8_t major, uint8_t minor,
                               uint16_t build, uint8_t revision);

/* ############### CRYPTO FUNCTIONS ################ */

struct ntlm_key {
    uint8_t data[16]; /* up to 16 bytes (128 bits) */
    size_t length;
};

struct ntlm_signseal_handle {
    struct ntlm_key sign_key;
    struct ntlm_key seal_key;
    struct ntlm_rc4_handle *seal_handle;
    uint32_t seq_num;
};

struct ntlm_signseal_state {
    struct ntlm_signseal_handle send;
    struct ntlm_signseal_handle recv;
    bool datagram;
    bool ext_sec;
};

#define NTLM_SEND 1
#define NTLM_RECV 2

/**
 * @brief   Turns a utf8 password into an NT Hash
 *
 * @param password      The password
 * @param result        The returned hash
 *
 * @return 0 on success or an error;
 */
int NTOWFv1(const char *password, struct ntlm_key *result);

/**
 * @brief   Turns a utf8 password into an LM Hash
 *
 * @param password      The password
 * @param result        The returned hash
 *
 * @return 0 on success or an error;
 */
int LMOWFv1(const char *password, struct ntlm_key *result);

/**
 * @brief   Generate the challenge used in NTLMv1 w/ Extended Security
 *
 * @param server_chal   An 8 byte long buffer w/ the server challenge
 * @param client_chal   An 8 byte long buffer w/ the client challenge
 * @param result_chal   An 8 byte long buffer w/ for the result
 *
 * @return 0 on success or ERR_CRYPTO
 */
int ntlm_compute_ext_sec_challenge(uint8_t *server_chal,
                                   uint8_t *client_chal,
                                   uint8_t *result_chal);
/**
 * @brief   Generates a v1 NT Response
 *
 * @param nt_key            The NTLMv1 key computed by NTOWFv1()
 * @param ext_sec           Whether Extended Security has been negotiated
 * @param server_chal[8]    The server challenge
 * @param client_chal[8]    The client challenge (only with Extended Security)
 * @param nt_response       The output buffer (must be 24 bytes preallocated)
 *
 * @return 0 on success or ERR_CRYPTO
 */
int ntlm_compute_nt_response(struct ntlm_key *nt_key, bool ext_sec,
                             uint8_t server_chal[8], uint8_t client_chal[8],
                             struct ntlm_buffer *nt_response);

/**
 * @brief   Generates a v1 LM Response
 *
 * @param lm_key            The LMv1 key computed by LMOWFv1()
 * @param ext_sec           Whether Extended Security has been negotiated
 * @param server_chal[8]    The server challenge
 * @param client_chal[8]    The client challenge (only with Extended Security)
 * @param lm_response       The output buffer (must be 24 bytes preallocated)
 *
 * @return 0 on success or ERR_CRYPTO
 */
int ntlm_compute_lm_response(struct ntlm_key *lm_key, bool ext_sec,
                             uint8_t server_chal[8], uint8_t client_chal[8],
                             struct ntlm_buffer *lm_response);

/**
 * @brief   Returns the v1 session key
 *
 * @param nt_key            The NTLMv1 key computed by NTOWFv1()
 * @param session_base_key  The output buffer (must be 16 bytes preallocated)
 *
 * @return 0 on success or ERR_CRYPTO
 */
int ntlm_session_base_key(struct ntlm_key *nt_key,
                          struct ntlm_key *session_base_key);

/**
 * @brief   V1 Key Exchange Key calculation
 *
 * @param ctx               An ntlm context
 * @param ext_sec           Whether Extended Security has been negotiated
 * @param neg_lm_key        Whether LM KEY has been negotiated
 * @param non_nt_sess_key   Whether non NT Session Key has been negotiated
 * @param server_chal       The server challenge (only with Extended Security)
 * @param lm_key            The LMv1 key computed by LMOWFv1()
 * @param session_base_key  The Session Base Key
 * @param lm_response       The LM v1 Response
 * @param key_exchange_key  The output buffer (must be 16 bytes preallocated)
 *
 * @return 0 on success or ERR_CRYPTO
 */
int KXKEY(struct ntlm_ctx *ctx,
          bool ext_sec,
          bool neg_lm_key,
          bool non_nt_sess_key,
          uint8_t server_chal[8],
          struct ntlm_key *lm_key,
          struct ntlm_key *session_base_key,
          struct ntlm_buffer *lm_response,
          struct ntlm_key *key_exchange_key);

/**
 * @brief   Generates a NTLMv2 Response Key
 *
 * @param ctx           An ntlm context
 * @param nt_hash       The NT Hash of the user password
 * @param user          The user name
 * @param domain        The user's domain
 * @param result        The resulting key
 *                          (must be a preallocated 16 bytes buffer)
 *
 * @return 0 on success or ERR_CRYPTO
 */
int NTOWFv2(struct ntlm_ctx *ctx, struct ntlm_key *nt_hash,
            const char *user, const char *domain, struct ntlm_key *result);

/**
 * @brief   Computes The NTLMv2 Response
 *
 * @param ntlmv2_key         The NTLMv2 key computed by NTOWFv2()
 * @param server_chal[8]     The server provided challenge
 * @param client_chal[8]     A client generated random challenge
 * @param timestamp          A FILETIME timestamp
 * @param target_info        The target info
 * @param nt_response        The resulting nt_response buffer
 *
 * @return 0 on success or error.
 */
int ntlmv2_compute_nt_response(struct ntlm_key *ntlmv2_key,
                               uint8_t server_chal[8], uint8_t client_chal[8],
                               uint64_t timestamp,
                               struct ntlm_buffer *target_info,
                               struct ntlm_buffer *nt_response);

/**
 * @brief   Computes The LMv2 Response
 *
 * @param ntlmv2_key         The NTLMv2 key computed by NTOWFv2()
 * @param server_chal[8]     The server provided challenge
 * @param client_chal[8]     A client generated random challenge
 * @param lm_response        The resulting lm_response buffer
 *
 * @return 0 on success or error.
 */
int ntlmv2_compute_lm_response(struct ntlm_key *ntlmv2_key,
                               uint8_t server_chal[8], uint8_t client_chal[8],
                               struct ntlm_buffer *lm_response);

/**
 * @brief   Computes the NTLMv2 SessionBaseKey
 *
 * @param ntlmv2_key            The NTLMv2 key computed by NTOWFv2()
 * @param nt_response           The NTLMv2 response
 * @param session_base_key      The resulting session key
 *
 * @return 0 on success or error.
 */
int ntlmv2_session_base_key(struct ntlm_key *ntlmv2_key,
                            struct ntlm_buffer *nt_response,
                            struct ntlm_key *session_base_key);

/**
 * @brief   Comutes the NTLM session key
 *
 * @param key_exchange_key[16]          The Key Exchange Key
 * @param key_exch                      KEY_EXCH has been negotited
 * @param exported_session_key[16]      Resulting exported session key
 *
 * @return 0 on success or error.
 */
int ntlm_exported_session_key(struct ntlm_key *key_exchange_key,
                              bool key_exch,
                              struct ntlm_key *exported_session_key);

/**
 * @brief   Encrypts or Decrypts the NTLM session key using RC4K
 *
 * @param key_exchange_key[16]          The Key Exchange Key
 * @param exported_session_key[16]      Resulting exported session key
 * @param encrypted_random_session_key  Resulting encrypted session key
 *
 * @return 0 on success or error.
 */
int ntlm_encrypted_session_key(struct ntlm_key *key,
                               struct ntlm_key *in, struct ntlm_key *out);

/**
 * @brief   Computes the extended security keys from the session key
 *
 * @param flags                 Incoming challenge/authenticate flags
 * @param client                Wheter this ia a client or a server
 * @param session_key           The session key
 * @param signseal_state        Sign and seal keys and state
 *
 * @return 0 on success or error.
 */
int ntlm_signseal_keys(uint32_t flags, bool client,
                       struct ntlm_key *session_key,
                       struct ntlm_signseal_state *signseal_state);

/**
 * @brief   Verifies a NTLM v1 NT Response
 *
 * @param nt_response       The NT Response buffer
 * @param nt_key            The NTLMv1 NT Key
 * @param ext_sec           Whether Extended Security was negotiated
 * @param server_chal[8]    The Server Challenge
 * @param client_chal[8]    The Client Challenge
 *
 * @return 0 on success, or an error
 */
int ntlm_verify_nt_response(struct ntlm_buffer *nt_response,
                            struct ntlm_key *nt_key, bool ext_sec,
                            uint8_t server_chal[8], uint8_t client_chal[8]);

/**
 * @brief   Verifies a NTLM v1 LM Response
 *
 * @param lm_response       The LM Response buffer
 * @param lm_key            The NTLMv1 LM Key
 * @param ext_sec           Whether Extended Security was negotiated
 * @param server_chal[8]    The Server Challenge
 * @param client_chal[8]    The Client Challenge
 *
 * @return 0 on success, or an error
 */
int ntlm_verify_lm_response(struct ntlm_buffer *lm_response,
                            struct ntlm_key *lm_key, bool ext_sec,
                            uint8_t server_chal[8], uint8_t client_chal[8]);

/**
 * @brief   Verifies a NTLM v1 NT Response
 *
 * @param nt_response       The NT Response buffer
 * @param nt_key            The NTLMv1 NT Key
 * @param ext_sec           Whether Extended Security was negotiated
 * @param server_chal[8]    The Server Challenge
 * @param client_chal[8]    The Client Challenge
 *
 * @return 0 on success, or an error
 */
int ntlm_verify_nt_response(struct ntlm_buffer *nt_response,
                            struct ntlm_key *nt_key, bool ext_sec,
                            uint8_t server_chal[8], uint8_t client_chal[8]);

/**
 * @brief   Verifies a NTLM v1 LM Response
 *
 * @param lm_response       The LM Response buffer
 * @param lm_key            The NTLMv1 LM Key
 * @param ext_sec           Whether Extended Security was negotiated
 * @param server_chal[8]    The Server Challenge
 * @param client_chal[8]    The Client Challenge
 *
 * @return 0 on success, or an error
 */
int ntlm_verify_lm_response(struct ntlm_buffer *lm_response,
                            struct ntlm_key *lm_key, bool ext_sec,
                            uint8_t server_chal[8], uint8_t client_chal[8]);

/**
 * @brief   Verifies a 16 bit NT Response
 *
 * @param nt_response       The NT Response buffer including client challenge
 * @param ntlmv2_key        The NTLMv2 key
 * @param server_chal[8]    The server challenge used to compute the response
 *
 * @return 0 on success, or an error
 */
int ntlmv2_verify_nt_response(struct ntlm_buffer *nt_response,
                              struct ntlm_key *ntlmv2_key,
                              uint8_t server_chal[8]);

/**
 * @brief   Verifies a 16 bit LM Response
 *
 * @param nt_response       The LM Response buffer including client challenge
 * @param ntlmv2_key        The NTLMv2 key
 * @param server_chal[8]    The server challenge used to compute the response
 *
 * @return 0 on success, or an error
 */
int ntlmv2_verify_lm_response(struct ntlm_buffer *nt_response,
                              struct ntlm_key *ntlmv2_key,
                              uint8_t server_chal[8]);

/**
 * @brief Create NTLM signature for the provided message
 *
 * @param flags         Negotiated flags
 * @param state         Sign and seal keys and state
 * @param direction     Direction (true for send)
 * @param message       Message buffer
 * @param signature     Preallocated byffer of 16 bytes for signature
 *
 * @return 0 on success, or an error
 */
int ntlm_sign(uint32_t flags, int direction,
              struct ntlm_signseal_state *state,
              struct ntlm_buffer *message,
              struct ntlm_buffer *signature);

/**
 * @brief   NTLM seal the provided message
 *
 * @param flags         Negotiated flags
 * @param state         Sign and seal keys and state
 * @param message       Message buffer
 * @param output        Output buffer
 * @param signature     Signature
 *
 * @return 0 on success, or an error
 */
int ntlm_seal(uint32_t flags,
              struct ntlm_signseal_state *state,
              struct ntlm_buffer *message,
              struct ntlm_buffer *output,
              struct ntlm_buffer *signature);

/**
 * @brief   NTLM unseal the provided message
 *
 * @param flags         Negotiated flags
 * @param state         Sign and seal keys and state
 * @param message       Message buffer
 * @param output        Output buffer
 * @param signature     Signature
 *
 * @return 0 on success, or an error
 */
int ntlm_unseal(uint32_t flags,
                struct ntlm_signseal_state *state,
                struct ntlm_buffer *message,
                struct ntlm_buffer *output,
                struct ntlm_buffer *signature);

/**
 * @brief   Creates a NTLM MIC
 *
 * @param exported_session_key      The Exported Session Key
 * @param negotiate_message         The NTLM Negotiate Message (or empty)
 * @param challenge_message         The NTLM Challenge Message
 * @param authenticate_message      The NTLM Authenticate Message
 * @param mic                       Preallocated byffer of 16 bytes
 *
 * @return 0 on success, or an error
 */
int ntlm_mic(struct ntlm_key *exported_session_key,
             struct ntlm_buffer *negotiate_message,
             struct ntlm_buffer *challenge_message,
             struct ntlm_buffer *authenticate_message,
             struct ntlm_buffer *mic);

/**
 * @brief  Verifies a MIC
 *
 * @param key                       The keys used to generate the original MIC
 * @param negotiate_message         The NTLM Negotiate Message (or empty)
 * @param challenge_message         The NTLM Challenge Message
 * @param authenticate_message      The NTLM Authenticate Message
 * @param mic                       The original MIC
 *
 * NOTE: This function zeros the area of memory where the MIC is held in the
 *       Authenticate Message
 *
 * @return 0 on success, EACCES if the MIC fails to verify, or an error
 */
int ntlm_verify_mic(struct ntlm_key *key,
                    struct ntlm_buffer *negotiate_message,
                    struct ntlm_buffer *challenge_message,
                    struct ntlm_buffer *authenticate_message,
                    struct ntlm_buffer *mic);

/**
 * @brief   NTLM hash client channel binding unhashed data
 *
 * @param unhashed      The unhashed channel bindings data
 * @param signature     The MD5 signature
 *
 * @return 0 on success, or an error
 */
int ntlm_hash_channel_bindings(struct ntlm_buffer *unhashed,
                               struct ntlm_buffer *signature);

/**
 * @brief   Verifies Channel binding signature from unhashed data.
 *
 * @param unhashed      The unhashed channel bindings data
 * @param signature     The recieved MD5 signature to check against
 *
 * @return 0 on success, EACCES if the CBT fails to verify, or an error
 */
int ntlm_verify_channel_bindings(struct ntlm_buffer *unhashed,
                                 struct ntlm_buffer *signature);

/* ############## ENCODING / DECODING ############## */

/**
 * @brief   A utility function to construct a target_info structure
 *
 * @param ctx                   The ntlm context
 * @param nb_computer_name      The NetBIOS Computer Name
 * @param nb_domain_name        The NetBIOS Domain Name
 * @param dns_computer_name     The DNS Fully Qualified Computer Name
 * @param dns_domain_name       The DNS Fully Qualified Domain Name
 * @param dns_tree_name         The DNS Tree Name
 * @param av_flags              The av flags
 * @param av_timestamp          A 64 bit FILETIME timestamp
 * @param av_single_host        A ntlm_buffer with the single host data
 * @param av_target_name        The target name
 * @param av_cb                 A ntlm_buffer with channel binding data
 * @param target_info           The buffer in which target_info is returned.
 *
 * NOTE: The caller is responsible for free()ing the buffer
 *
 * @return      0 if everyting parses correctly, or an error code
 */
int ntlm_encode_target_info(struct ntlm_ctx *ctx, char *nb_computer_name,
                            char *nb_domain_name, char *dns_computer_name,
                            char *dns_domain_name, char *dns_tree_name,
                            uint32_t *av_flags, uint64_t *av_timestamp,
                            struct ntlm_buffer *av_single_host,
                            char *av_target_name, struct ntlm_buffer *av_cb,
                            struct ntlm_buffer *target_info);


/**
 * @brief   A utility function to parse a target_info structure
 *
 * @param ctx                   The ntlm context
 * @param buffer                A ntlm_buffer containing the info to be parsed
 * @param nb_computer_name      The NetBIOS Computer Name
 * @param nb_domain_name        The NetBIOS Domain Name
 * @param dns_computer_name     The DNS Fully Qualified Computer Name
 * @param dns_domain_name       The DNS Fully Qualified Domain Name
 * @param dns_tree_name         The DNS Tree Name
 * @param av_flags              The av flags
 * @param av_timestamp          A 64 bit FILETIME timestamp
 * @param av_single_host        A ntlm_buffer with the single host data
 * @param av_target_name        The target name
 * @param av_cb                 A ntlm_buffer with channel binding data
 *
 * NOTE: The caller is responsible for free()ing all strings, while the
 *       ntlm_buffer types point directly at data in the provided buffer.
 *
 * @return      0 if everyting parses correctly, or an error code
 */
int ntlm_decode_target_info(struct ntlm_ctx *ctx, struct ntlm_buffer *buffer,
                            char **nb_computer_name, char **nb_domain_name,
                            char **dns_computer_name, char **dns_domain_name,
                            char **dns_tree_name, char **av_target_name,
                            uint32_t *av_flags, uint64_t *av_timestamp,
                            struct ntlm_buffer *av_single_host,
                            struct ntlm_buffer *av_cb);

/**
 * @brief   A utility function to process a target_info structure
 *
 * @param ctx                   The ntlm context
 * @param protect               Set if signing or sealing has been requested
 * @param in                    A ntlm_buffer containing the received info
 * @param server                The Client Supplied Server Name if available
 * @param unhashed_cb           A ntlm_buffer with channel binding data
 * @param out                   The processed target_info buffer
 * @param out_srv_time          A 64 bit FILETIME timestamp
 * @param add_mic               A pointer to a boolean. If NULL MIC flags will
 *                               not be set, otherwise if allowed the MIC flag
 *                               will be set and true will be returned.
 *
 * @return      0 if everyting parses correctly, or an error code
 */
int ntlm_process_target_info(struct ntlm_ctx *ctx, bool protect,
                             struct ntlm_buffer *in,
                             const char *server,
                             struct ntlm_buffer *unhashed_cb,
                             struct ntlm_buffer *out,
                             uint64_t *out_srv_time,
                             bool *add_mic);

/**
 * @brief Verifies the message signature is valid and the message
 * in sequence with the expected state
 *
 * @param ctx           The conversation context.
 * @param buffer        A ntlm_buffer containing the raw NTLMSSP packet
 *
 * @return      0 if everyting parses correctly, or an error code
 *
 * NOTE: Always use ntlm_detect_msg_type before calling other functions,
 * so that the signature and message type are checked, and the state is
 * validated.
 */
int ntlm_decode_msg_type(struct ntlm_ctx *ctx,
                         struct ntlm_buffer *buffer,
                         uint32_t *type);

/**
 * @brief This function encodes a NEGTIATE_MESSAGE which is the first message
 * a client will send to a server. It also updates the stage in the context.
 *
 * @param ctx           A fresh ntlm context.
 * @param flags         Requested flags
 * @param domain        Optional Domain Name
 * @param workstation   Optional Workstation Name
 * @param message       A ntlm_buffer containing the returned message
 *
 * NOTE: the caller is responsible for free()ing the message buffer.
 *
 * @return      0 if everyting encodes correctly, or an error code
 */
int ntlm_encode_neg_msg(struct ntlm_ctx *ctx, uint32_t flags,
                        const char *domain, const char *workstation,
                        struct ntlm_buffer *message);

/**
 * @brief This function decodes a NTLMSSP NEGTIATE_MESSAGE.
 *
 * @param ctx           A fresh ntlm context
 * @param buffer        A ntlm_buffer containing the raw NTLMSSP packet
 * @param flags         Returns the flags requested by the client
 * @param domain        Returns the domain provided by the client if any
 * @param workstation   Returns the workstation provided by the client if any
 *
 * @return      0 if everyting parses correctly, or an error code
 *
 */
int ntlm_decode_neg_msg(struct ntlm_ctx *ctx,
                        struct ntlm_buffer *buffer, uint32_t *flags,
                        char **domain, char **workstation);

/**
 * @brief This function encodes a CHALLENGE_MESSAGE which is the first message
 * a server will send to a client. It also updates the stage in the context.
 *
 * @param ctx           The ntlm context
 * @param flags         The challenge flags
 * @param target_name   The target name
 * @param challenge     A 64 bit value with a challenge
 * @param target_info   A buffer containing target_info data
 * @param message       A ntlm_buffer containing the encoded message
 *
 * NOTE: the caller is responsible for free()ing the message buffer
 *
 * @return      0 if everyting encodes correctly, or an error code
 */
int ntlm_encode_chal_msg(struct ntlm_ctx *ctx,
                         uint32_t flags,
                         const char *target_name,
                         struct ntlm_buffer *challenge,
                         struct ntlm_buffer *target_info,
                         struct ntlm_buffer *message);


/**
 * @brief This function decodes a NTLMSSP CHALLENGE_MESSAGE.
 *
 * @param ctx           The ntlm context
 * @param buffer        A ntlm_buffer containing the raw NTLMSSP packet
 * @param flags         The challenge flags
 * @param target_name   The target name
 * @param challenge     A 64 bit value with the server challenge
 *                      The caller MUST provide a preallocated buffer of
 *                      appropriate length (8 bytes)
 * @param target_info   A buffer containing returned target_info data
 *
 * @return      0 if everyting encodes correctly, or an error code
 */
int ntlm_decode_chal_msg(struct ntlm_ctx *ctx,
                         struct ntlm_buffer *buffer,
                         uint32_t *flags, char **target_name,
                         struct ntlm_buffer *challenge,
                         struct ntlm_buffer *target_info);


/**
 * @brief This function encodes a AUTHENTICATE_MESSAGE which is the second
 * message a client will send to a serve.
 * It also updates the stage in the context.
 *
 * @param ctx           The ntlm context
 * @param flags         The flags
 * @param lm_chalresp   A LM or LMv2 response
 * @param nt_chalresp   A NTLM or NTLMv2 response
 * @param domain_name   The Domain name
 * @param user_name     The User name
 * @param workstation   The Workstation name
 * @param enc_sess_key  The session key
 * @param mic           A MIC of the messages
 * @param message       A ntlm_buffer containing the encoded message
 *
 * @return      0 if everyting encodes correctly, or an error code
 */
int ntlm_encode_auth_msg(struct ntlm_ctx *ctx,
                         uint32_t flags,
                         struct ntlm_buffer *lm_chalresp,
                         struct ntlm_buffer *nt_chalresp,
                         char *domain_name, char *user_name,
                         char *workstation,
                         struct ntlm_buffer *enc_sess_key,
                         struct ntlm_buffer *mic,
                         struct ntlm_buffer *message);

/**
 * @brief This function decodes a NTLMSSP AUTHENTICATE_MESSAGE.
 *
 * @param ctx           The ntlm context
 * @param buffer        A ntlm_buffer containing the raw NTLMSSP packet
 * @param flags         The negotiated flags
 * @param lm_chalresp   A LM or LMv2 response
 * @param nt_chalresp   A NTLM or NTLMv2 response
 * @param domain_name   The Domain name
 * @param user_name     The User name
 * @param workstation   The Workstation name
 * @param enc_sess_key  The session key
 * @param target_info   The target_info AV_PAIR embedded in the NT Response
 * @param mic           A MIC of the messages
 *                      Passing a pointer to a mic means the caller has
 *                      previously requested the presence of a MIC field from
 *                      the peer. If a MIC is not returned by the peer the
 *                      secoding will fail. If not MIC ha sbeen previously
 *                      requested set this pointer to NULL.
 *                      The caller must provide a preallocated buffer of
 *                      appropriate length (16 bytes)
 *
 * NOTE: the caller is reponsible for freeing all allocated buffers
 * on success.
 *
 * @return      0 if everyting encodes correctly, or an error code
 */
int ntlm_decode_auth_msg(struct ntlm_ctx *ctx,
                         struct ntlm_buffer *buffer,
                         uint32_t flags,
                         struct ntlm_buffer *lm_chalresp,
                         struct ntlm_buffer *nt_chalresp,
                         char **domain_name, char **user_name,
                         char **workstation,
                         struct ntlm_buffer *enc_sess_key,
                         struct ntlm_buffer *target_info,
                         struct ntlm_buffer *mic);

#endif /* _NTLM_H_ */