Initial commit - from Precise source
[freerdp-ubuntu-pcb-backport.git] / libfreerdp-core / ntlmssp.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Client
3  * NT LAN Manager Security Support Provider (NTLMSSP)
4  *
5  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #include <time.h>
21 #include <openssl/des.h>
22 #include <openssl/md4.h>
23 #include <openssl/hmac.h>
24 #include <openssl/rand.h>
25 #include <openssl/engine.h>
26 #include <freerdp/utils/memory.h>
27
28 #include "ntlmssp.h"
29
30 #define NTLMSSP_NEGOTIATE_56                                    0x80000000 /* W   (0) */
31 #define NTLMSSP_NEGOTIATE_KEY_EXCH                              0x40000000 /* V   (1) */
32 #define NTLMSSP_NEGOTIATE_128                                   0x20000000 /* U   (2) */
33 #define NTLMSSP_RESERVED1                                       0x10000000 /* r1  (3) */
34 #define NTLMSSP_RESERVED2                                       0x08000000 /* r2  (4) */
35 #define NTLMSSP_RESERVED3                                       0x04000000 /* r3  (5) */
36 #define NTLMSSP_NEGOTIATE_VERSION                               0x02000000 /* T   (6) */
37 #define NTLMSSP_RESERVED4                                       0x01000000 /* r4  (7) */
38 #define NTLMSSP_NEGOTIATE_TARGET_INFO                           0x00800000 /* S   (8) */
39 #define NTLMSSP_RESERVEDEQUEST_NON_NT_SESSION_KEY               0x00400000 /* R   (9) */
40 #define NTLMSSP_RESERVED5                                       0x00200000 /* r5  (10) */
41 #define NTLMSSP_NEGOTIATE_IDENTIFY                              0x00100000 /* Q   (11) */
42 #define NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY             0x00080000 /* P   (12) */
43 #define NTLMSSP_RESERVED6                                       0x00040000 /* r6  (13) */
44 #define NTLMSSP_TARGET_TYPE_SERVER                              0x00020000 /* O   (14) */
45 #define NTLMSSP_TARGET_TYPE_DOMAIN                              0x00010000 /* N   (15) */
46 #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN                           0x00008000 /* M   (16) */
47 #define NTLMSSP_RESERVED7                                       0x00004000 /* r7  (17) */
48 #define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED                  0x00002000 /* L   (18) */
49 #define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED                       0x00001000 /* K   (19) */
50 #define NTLMSSP_NEGOTIATE_ANONYMOUS                             0x00000800 /* J   (20) */
51 #define NTLMSSP_RESERVED8                                       0x00000400 /* r8  (21) */
52 #define NTLMSSP_NEGOTIATE_NTLM                                  0x00000200 /* H   (22) */
53 #define NTLMSSP_RESERVED9                                       0x00000100 /* r9  (23) */
54 #define NTLMSSP_NEGOTIATE_LM_KEY                                0x00000080 /* G   (24) */
55 #define NTLMSSP_NEGOTIATE_DATAGRAM                              0x00000040 /* F   (25) */
56 #define NTLMSSP_NEGOTIATE_SEAL                                  0x00000020 /* E   (26) */
57 #define NTLMSSP_NEGOTIATE_SIGN                                  0x00000010 /* D   (27) */
58 #define NTLMSSP_RESERVED10                                      0x00000008 /* r10 (28) */
59 #define NTLMSSP_REQUEST_TARGET                                  0x00000004 /* C   (29) */
60 #define NTLMSSP_NEGOTIATE_OEM                                   0x00000002 /* B   (30) */
61 #define NTLMSSP_NEGOTIATE_UNICODE                               0x00000001 /* A   (31) */
62
63 #define WINDOWS_MAJOR_VERSION_5         0x05
64 #define WINDOWS_MAJOR_VERSION_6         0x06
65 #define WINDOWS_MINOR_VERSION_0         0x00
66 #define WINDOWS_MINOR_VERSION_1         0x01
67 #define WINDOWS_MINOR_VERSION_2         0x02
68 #define NTLMSSP_REVISION_W2K3           0x0F
69
70 static const char ntlm_signature[] = "NTLMSSP";
71 static const char lm_magic[] = "KGS!@#$%";
72
73 static const char client_sign_magic[] = "session key to client-to-server signing key magic constant";
74 static const char server_sign_magic[] = "session key to server-to-client signing key magic constant";
75 static const char client_seal_magic[] = "session key to client-to-server sealing key magic constant";
76 static const char server_seal_magic[] = "session key to server-to-client sealing key magic constant";
77
78 static const char* const NTLMSSP_NEGOTIATE_STRINGS[] =
79 {
80         "NTLMSSP_NEGOTIATE_56",
81         "NTLMSSP_NEGOTIATE_KEY_EXCH",
82         "NTLMSSP_NEGOTIATE_128",
83         "NTLMSSP_RESERVED1",
84         "NTLMSSP_RESERVED2",
85         "NTLMSSP_RESERVED3",
86         "NTLMSSP_NEGOTIATE_VERSION",
87         "NTLMSSP_RESERVED4",
88         "NTLMSSP_NEGOTIATE_TARGET_INFO",
89         "NTLMSSP_REQUEST_NON_NT_SESSION_KEY",
90         "NTLMSSP_RESERVED5",
91         "NTLMSSP_NEGOTIATE_IDENTIFY",
92         "NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY",
93         "NTLMSSP_RESERVED6",
94         "NTLMSSP_TARGET_TYPE_SERVER",
95         "NTLMSSP_TARGET_TYPE_DOMAIN",
96         "NTLMSSP_NEGOTIATE_ALWAYS_SIGN",
97         "NTLMSSP_RESERVED7",
98         "NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED",
99         "NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED",
100         "NTLMSSP_NEGOTIATE_ANONYMOUS",
101         "NTLMSSP_RESERVED8",
102         "NTLMSSP_NEGOTIATE_NTLM",
103         "NTLMSSP_RESERVED9",
104         "NTLMSSP_NEGOTIATE_LM_KEY",
105         "NTLMSSP_NEGOTIATE_DATAGRAM",
106         "NTLMSSP_NEGOTIATE_SEAL",
107         "NTLMSSP_NEGOTIATE_SIGN",
108         "NTLMSSP_RESERVED10",
109         "NTLMSSP_REQUEST_TARGET",
110         "NTLMSSP_NEGOTIATE_OEM",
111         "NTLMSSP_NEGOTIATE_UNICODE"
112 };
113
114 static const char* const AV_PAIRS_STRINGS[] =
115 {
116         "MsvAvEOL",
117         "MsvAvNbComputerName",
118         "MsvAvNbDomainName",
119         "MsvAvDnsComputerName",
120         "MsvAvDnsDomainName",
121         "MsvAvDnsTreeName",
122         "MsvAvFlags",
123         "MsvAvTimestamp",
124         "MsvAvRestrictions",
125         "MsvAvTargetName",
126         "MsvChannelBindings"
127 };
128
129 /**
130  * Set NTLMSSP username.
131  * @param ntlmssp
132  * @param username username
133  */
134
135 void ntlmssp_set_username(NTLMSSP* ntlmssp, char* username)
136 {
137         freerdp_blob_free(&ntlmssp->username);
138
139         if (username != NULL)
140         {
141                 ntlmssp->username.data = freerdp_uniconv_out(ntlmssp->uniconv, username, (size_t*) &(ntlmssp->username.length));
142         }
143 }
144
145 /**
146  * Set NTLMSSP domain name.
147  * @param ntlmssp
148  * @param domain domain name
149  */
150
151 void ntlmssp_set_domain(NTLMSSP* ntlmssp, char* domain)
152 {
153         freerdp_blob_free(&ntlmssp->domain);
154
155         if (domain != NULL)
156         {
157                 ntlmssp->domain.data = freerdp_uniconv_out(ntlmssp->uniconv, domain, (size_t*) &(ntlmssp->domain.length));
158         }
159 }
160
161 /**
162  * Set NTLMSSP password.
163  * @param ntlmssp
164  * @param password password
165  */
166
167 void ntlmssp_set_password(NTLMSSP* ntlmssp, char* password)
168 {
169         freerdp_blob_free(&ntlmssp->password);
170
171         if (password != NULL)
172         {
173                 ntlmssp->password.data = freerdp_uniconv_out(ntlmssp->uniconv, password, (size_t*) &(ntlmssp->password.length));
174         }
175 }
176
177 /**
178  * Set NTLMSSP workstation.
179  * @param ntlmssp
180  * @param workstation workstation
181  */
182
183 void ntlmssp_set_workstation(NTLMSSP* ntlmssp, char* workstation)
184 {
185         freerdp_blob_free(&ntlmssp->workstation);
186
187         if (workstation != NULL)
188         {
189                 ntlmssp->workstation.data = freerdp_uniconv_out(ntlmssp->uniconv, workstation, (size_t*) &(ntlmssp->workstation.length));
190         }
191 }
192
193 /**
194  * Generate client challenge (8-byte nonce).
195  * @param ntlmssp
196  */
197
198 void ntlmssp_generate_client_challenge(NTLMSSP* ntlmssp)
199 {
200         /* ClientChallenge in computation of LMv2 and NTLMv2 responses */
201         crypto_nonce(ntlmssp->client_challenge, 8);
202 }
203
204 /**
205  * Generate KeyExchangeKey (the 128-bit SessionBaseKey).\n
206  * @msdn{cc236710}
207  * @param ntlmssp
208  */
209
210 void ntlmssp_generate_key_exchange_key(NTLMSSP* ntlmssp)
211 {
212         /* In NTLMv2, KeyExchangeKey is the 128-bit SessionBaseKey */
213         memcpy(ntlmssp->key_exchange_key, ntlmssp->session_base_key, 16);
214 }
215
216 /**
217  * Generate RandomSessionKey (16-byte nonce).
218  * @param ntlmssp
219  */
220
221 void ntlmssp_generate_random_session_key(NTLMSSP* ntlmssp)
222 {
223         crypto_nonce(ntlmssp->random_session_key, 16);
224 }
225
226 /**
227  * Generate ExportedSessionKey (the RandomSessionKey, exported)
228  * @param ntlmssp
229  */
230
231 void ntlmssp_generate_exported_session_key(NTLMSSP* ntlmssp)
232 {
233         memcpy(ntlmssp->exported_session_key, ntlmssp->random_session_key, 16);
234 }
235
236 /**
237  * Encrypt RandomSessionKey (RC4-encrypted RandomSessionKey, using KeyExchangeKey as the key).
238  * @param ntlmssp
239  */
240
241 void ntlmssp_encrypt_random_session_key(NTLMSSP* ntlmssp)
242 {
243         /* In NTLMv2, EncryptedRandomSessionKey is the ExportedSessionKey RC4-encrypted with the KeyExchangeKey */
244         credssp_rc4k(ntlmssp->key_exchange_key, 16, ntlmssp->random_session_key, ntlmssp->encrypted_random_session_key);
245 }
246
247 /**
248  * Generate timestamp for AUTHENTICATE_MESSAGE.
249  * @param ntlmssp
250  */
251
252 void ntlmssp_generate_timestamp(NTLMSSP* ntlmssp)
253 {
254         credssp_current_time(ntlmssp->timestamp);
255
256         if (ntlmssp->ntlm_v2)
257         {
258                 if (ntlmssp->av_pairs->Timestamp.length == 8)
259                 {
260                         memcpy(ntlmssp->av_pairs->Timestamp.value, ntlmssp->timestamp, 8);
261                         return;
262                 }
263         }
264         else
265         {
266                 if (ntlmssp->av_pairs->Timestamp.length != 8)
267                 {
268                         ntlmssp->av_pairs->Timestamp.length = 8;
269                         ntlmssp->av_pairs->Timestamp.value = xmalloc(ntlmssp->av_pairs->Timestamp.length);
270                 }
271                 memcpy(ntlmssp->av_pairs->Timestamp.value, ntlmssp->timestamp, 8);
272         }
273 }
274
275 /**
276  * Generate signing key.\n
277  * @msdn{cc236711}
278  * @param exported_session_key ExportedSessionKey
279  * @param sign_magic Sign magic string
280  * @param signing_key Destination signing key
281  */
282
283 void ntlmssp_generate_signing_key(uint8* exported_session_key, rdpBlob* sign_magic, uint8* signing_key)
284 {
285         int length;
286         uint8* value;
287         CryptoMd5 md5;
288
289         length = 16 + sign_magic->length;
290         value = (uint8*) xmalloc(length);
291
292         /* Concatenate ExportedSessionKey with sign magic */
293         memcpy(value, exported_session_key, 16);
294         memcpy(&value[16], sign_magic->data, sign_magic->length);
295
296         md5 = crypto_md5_init();
297         crypto_md5_update(md5, value, length);
298         crypto_md5_final(md5, signing_key);
299
300         xfree(value);
301 }
302
303 /**
304  * Generate client signing key (ClientSigningKey).\n
305  * @msdn{cc236711}
306  * @param ntlmssp
307  */
308
309 void ntlmssp_generate_client_signing_key(NTLMSSP* ntlmssp)
310 {
311         rdpBlob sign_magic;
312         sign_magic.data = (void*) client_sign_magic;
313         sign_magic.length = sizeof(client_sign_magic);
314         ntlmssp_generate_signing_key(ntlmssp->exported_session_key, &sign_magic, ntlmssp->client_signing_key);
315 }
316
317 /**
318  * Generate server signing key (ServerSigningKey).\n
319  * @msdn{cc236711}
320  * @param ntlmssp
321  */
322
323 void ntlmssp_generate_server_signing_key(NTLMSSP* ntlmssp)
324 {
325         rdpBlob sign_magic;
326         sign_magic.data = (void*) server_sign_magic;
327         sign_magic.length = sizeof(server_sign_magic);
328         ntlmssp_generate_signing_key(ntlmssp->exported_session_key, &sign_magic, ntlmssp->server_signing_key);
329 }
330
331 /**
332  * Generate sealing key.\n
333  * @msdn{cc236712}
334  * @param exported_session_key ExportedSessionKey
335  * @param seal_magic Seal magic string
336  * @param sealing_key Destination sealing key
337  */
338
339 void ntlmssp_generate_sealing_key(uint8* exported_session_key, rdpBlob* seal_magic, uint8* sealing_key)
340 {
341         uint8* p;
342         CryptoMd5 md5;
343         rdpBlob blob;
344
345         freerdp_blob_alloc(&blob, 16 + seal_magic->length);
346         p = (uint8*) blob.data;
347
348         /* Concatenate ExportedSessionKey with seal magic */
349         memcpy(p, exported_session_key, 16);
350         memcpy(&p[16], seal_magic->data, seal_magic->length);
351
352         md5 = crypto_md5_init();
353         crypto_md5_update(md5, blob.data, blob.length);
354         crypto_md5_final(md5, sealing_key);
355
356         freerdp_blob_free(&blob);
357 }
358
359 /**
360  * Generate client sealing key (ClientSealingKey).\n
361  * @msdn{cc236712}
362  * @param ntlmssp
363  */
364
365 void ntlmssp_generate_client_sealing_key(NTLMSSP* ntlmssp)
366 {
367         rdpBlob seal_magic;
368         seal_magic.data = (void*) client_seal_magic;
369         seal_magic.length = sizeof(client_seal_magic);
370         ntlmssp_generate_signing_key(ntlmssp->exported_session_key, &seal_magic, ntlmssp->client_sealing_key);
371 }
372
373 /**
374  * Generate server sealing key (ServerSealingKey).\n
375  * @msdn{cc236712}
376  * @param ntlmssp
377  */
378
379 void ntlmssp_generate_server_sealing_key(NTLMSSP* ntlmssp)
380 {
381         rdpBlob seal_magic;
382         seal_magic.data = (void*) server_seal_magic;
383         seal_magic.length = sizeof(server_seal_magic);
384         ntlmssp_generate_signing_key(ntlmssp->exported_session_key, &seal_magic, ntlmssp->server_sealing_key);
385 }
386
387 /**
388  * Initialize RC4 stream cipher states for sealing.
389  * @param ntlmssp
390  */
391
392 void ntlmssp_init_rc4_seal_states(NTLMSSP* ntlmssp)
393 {
394         ntlmssp->send_rc4_seal = crypto_rc4_init(ntlmssp->client_sealing_key, 16);
395         ntlmssp->recv_rc4_seal = crypto_rc4_init(ntlmssp->server_sealing_key, 16);
396 }
397
398 /**
399  * Get bit from a byte buffer using a bit offset.
400  * @param buffer byte buffer
401  * @param bit bit offset
402  * @return bit value
403  */
404
405 static int get_bit(char* buffer, int bit)
406 {
407         return (buffer[(bit - (bit % 8)) / 8] >> (7 - bit % 8) & 1);
408 }
409
410 /**
411  * Set bit in a byte buffer using a bit offset.
412  * @param buffer byte buffer
413  * @param bit bit offset
414  * @param value bit value
415  */
416
417 static void set_bit(char* buffer, int bit, int value)
418 {
419         buffer[(bit - (bit % 8)) / 8] |= value << (7 - bit % 8);
420 }
421
422 static void ntlmssp_compute_des_key(char* text, char* des_key)
423 {
424         int i, j;
425         int bit;
426         int nbits;
427
428         /* Convert the 7 bytes into a bit stream, and insert a parity-bit (odd parity) after every seven bits. */
429
430         memset(des_key, '\0', 8);
431
432         for (i = 0; i < 8; i++)
433         {
434                 nbits = 0;
435
436                 for (j = 0; j < 7; j++)
437                 {
438                         /* copy 7 bits, and count the number of bits that are set */
439
440                         bit = get_bit(text, i*7 + j);
441                         set_bit(des_key, i*7 + i + j, bit);
442                         nbits += bit;
443                 }
444
445                 /* insert parity bit (odd parity) */
446
447                 if (nbits % 2 == 0)
448                         set_bit(des_key, i*7 + i + j, 1);
449         }
450 }
451
452 void ntlmssp_compute_lm_hash(char* password, char* hash)
453 {
454         int i;
455         int maxlen;
456         char text[14];
457         char des_key1[8];
458         char des_key2[8];
459         des_key_schedule ks;
460
461         /* LM("password") = E52CAC67419A9A224A3B108F3FA6CB6D */
462
463         maxlen = (strlen(password) < 14) ? strlen(password) : 14;
464
465         /* convert to uppercase */
466         for (i = 0; i < maxlen; i++)
467         {
468                 if ((password[i] >= 'a') && (password[i] <= 'z'))
469                         text[i] = password[i] - 32;
470                 else
471                         text[i] = password[i];
472         }
473
474         /* pad with nulls up to 14 bytes */
475         for (i = maxlen; i < 14; i++)
476                 text[i] = '\0';
477
478         ntlmssp_compute_des_key(text, des_key1);
479         ntlmssp_compute_des_key(&text[7], des_key2);
480
481         DES_set_key((const_DES_cblock*)des_key1, &ks);
482         DES_ecb_encrypt((const_DES_cblock*) lm_magic, (DES_cblock*)hash, &ks, DES_ENCRYPT);
483
484         DES_set_key((const_DES_cblock*)des_key2, &ks);
485         DES_ecb_encrypt((const_DES_cblock*) lm_magic, (DES_cblock*)&hash[8], &ks, DES_ENCRYPT);
486 }
487
488 void ntlmssp_compute_ntlm_hash(rdpBlob* password, char* hash)
489 {
490         /* NTLMv1("password") = 8846F7EAEE8FB117AD06BDD830B7586C */
491
492         MD4_CTX md4_ctx;
493
494         /* Password needs to be in unicode */
495
496         /* Apply the MD4 digest algorithm on the password in unicode, the result is the NTLM hash */
497
498         MD4_Init(&md4_ctx);
499         MD4_Update(&md4_ctx, password->data, password->length);
500         MD4_Final((void*) hash, &md4_ctx);
501 }
502
503 void ntlmssp_compute_ntlm_v2_hash(NTLMSSP* ntlmssp, char* hash)
504 {
505         char* p;
506         rdpBlob blob;
507         char ntlm_hash[16];
508
509         freerdp_blob_alloc(&blob, ntlmssp->username.length + ntlmssp->domain.length);
510         p = (char*) blob.data;
511
512         /* First, compute the NTLMv1 hash of the password */
513         ntlmssp_compute_ntlm_hash(&ntlmssp->password, ntlm_hash);
514
515         /* Concatenate(Uppercase(username),domain)*/
516         memcpy(p, ntlmssp->username.data, ntlmssp->username.length);
517         freerdp_uniconv_uppercase(ntlmssp->uniconv, p, ntlmssp->username.length / 2);
518
519         memcpy(&p[ntlmssp->username.length], ntlmssp->domain.data, ntlmssp->domain.length);
520
521         /* Compute the HMAC-MD5 hash of the above value using the NTLMv1 hash as the key, the result is the NTLMv2 hash */
522         HMAC(EVP_md5(), (void*) ntlm_hash, 16, blob.data, blob.length, (void*) hash, NULL);
523
524         freerdp_blob_free(&blob);
525 }
526
527 void ntlmssp_compute_lm_response(char* password, char* challenge, char* response)
528 {
529         char hash[21];
530         char des_key1[8];
531         char des_key2[8];
532         char des_key3[8];
533         des_key_schedule ks;
534
535         /* A LM hash is 16-bytes long, but the LM response uses a LM hash null-padded to 21 bytes */
536         memset(hash, '\0', 21);
537         ntlmssp_compute_lm_hash(password, hash);
538
539         /* Each 7-byte third of the 21-byte null-padded LM hash is used to create a DES key */
540         ntlmssp_compute_des_key(hash, des_key1);
541         ntlmssp_compute_des_key(&hash[7], des_key2);
542         ntlmssp_compute_des_key(&hash[14], des_key3);
543
544         /* Encrypt the LM challenge with each key, and concatenate the result. This is the LM response (24 bytes) */
545         DES_set_key((const_DES_cblock*)des_key1, &ks);
546         DES_ecb_encrypt((const_DES_cblock*)challenge, (DES_cblock*)response, &ks, DES_ENCRYPT);
547
548         DES_set_key((const_DES_cblock*)des_key2, &ks);
549         DES_ecb_encrypt((const_DES_cblock*)challenge, (DES_cblock*)&response[8], &ks, DES_ENCRYPT);
550
551         DES_set_key((const_DES_cblock*)des_key3, &ks);
552         DES_ecb_encrypt((const_DES_cblock*)challenge, (DES_cblock*)&response[16], &ks, DES_ENCRYPT);
553 }
554
555 void ntlmssp_compute_lm_v2_response(NTLMSSP* ntlmssp)
556 {
557         char *response;
558         char value[16];
559         char ntlm_v2_hash[16];
560
561         /* Compute the NTLMv2 hash */
562         ntlmssp_compute_ntlm_v2_hash(ntlmssp, ntlm_v2_hash);
563
564         /* Concatenate the server and client challenges */
565         memcpy(value, ntlmssp->server_challenge, 8);
566         memcpy(&value[8], ntlmssp->client_challenge, 8);
567
568         freerdp_blob_alloc(&ntlmssp->lm_challenge_response, 24);
569         response = (char*) ntlmssp->lm_challenge_response.data;
570
571         /* Compute the HMAC-MD5 hash of the resulting value using the NTLMv2 hash as the key */
572         HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, (void*) value, 16, (void*) response, NULL);
573
574         /* Concatenate the resulting HMAC-MD5 hash and the client challenge, giving us the LMv2 response (24 bytes) */
575         memcpy(&response[16], ntlmssp->client_challenge, 8);
576 }
577
578 /**
579  * Compute NTLMv2 Response.\n
580  * NTLMv2_RESPONSE @msdn{cc236653}\n
581  * NTLMv2 Authentication @msdn{cc236700}
582  * @param ntlmssp
583  */
584
585 void ntlmssp_compute_ntlm_v2_response(NTLMSSP* ntlmssp)
586 {
587         uint8* blob;
588         uint8 ntlm_v2_hash[16];
589         uint8 nt_proof_str[16];
590         rdpBlob ntlm_v2_temp;
591         rdpBlob ntlm_v2_temp_chal;
592
593         freerdp_blob_alloc(&ntlm_v2_temp, ntlmssp->target_info.length + 28);
594
595         memset(ntlm_v2_temp.data, '\0', ntlm_v2_temp.length);
596         blob = (uint8*) ntlm_v2_temp.data;
597
598         /* Compute the NTLMv2 hash */
599         ntlmssp_compute_ntlm_v2_hash(ntlmssp, (char*) ntlm_v2_hash);
600
601 #ifdef WITH_DEBUG_NLA
602         printf("Password (length = %d)\n", ntlmssp->password.length);
603         freerdp_hexdump(ntlmssp->password.data, ntlmssp->password.length);
604         printf("\n");
605
606         printf("Username (length = %d)\n", ntlmssp->username.length);
607         freerdp_hexdump(ntlmssp->username.data, ntlmssp->username.length);
608         printf("\n");
609
610         printf("Domain (length = %d)\n", ntlmssp->domain.length);
611         freerdp_hexdump(ntlmssp->domain.data, ntlmssp->domain.length);
612         printf("\n");
613
614         printf("Workstation (length = %d)\n", ntlmssp->workstation.length);
615         freerdp_hexdump(ntlmssp->workstation.data, ntlmssp->workstation.length);
616         printf("\n");
617
618         printf("NTOWFv2, NTLMv2 Hash\n");
619         freerdp_hexdump(ntlm_v2_hash, 16);
620         printf("\n");
621 #endif
622
623         /* Construct temp */
624         blob[0] = 1; /* RespType (1 byte) */
625         blob[1] = 1; /* HighRespType (1 byte) */
626         /* Reserved1 (2 bytes) */
627         /* Reserved2 (4 bytes) */
628         memcpy(&blob[8], ntlmssp->av_pairs->Timestamp.value, 8); /* Timestamp (8 bytes) */
629         memcpy(&blob[16], ntlmssp->client_challenge, 8); /* ClientChallenge (8 bytes) */
630         /* Reserved3 (4 bytes) */
631         memcpy(&blob[28], ntlmssp->target_info.data, ntlmssp->target_info.length);
632
633 #ifdef WITH_DEBUG_NLA
634         printf("NTLMv2 Response Temp Blob\n");
635         freerdp_hexdump(ntlm_v2_temp.data, ntlm_v2_temp.length);
636         printf("\n");
637 #endif
638
639         /* Concatenate server challenge with temp */
640         freerdp_blob_alloc(&ntlm_v2_temp_chal, ntlm_v2_temp.length + 8);
641         blob = (uint8*) ntlm_v2_temp_chal.data;
642         memcpy(blob, ntlmssp->server_challenge, 8);
643         memcpy(&blob[8], ntlm_v2_temp.data, ntlm_v2_temp.length);
644
645         HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, (void*) ntlm_v2_temp_chal.data,
646                 ntlm_v2_temp_chal.length, (void*) nt_proof_str, NULL);
647
648         /* NtChallengeResponse, Concatenate NTProofStr with temp */
649         freerdp_blob_alloc(&ntlmssp->nt_challenge_response, ntlm_v2_temp.length + 16);
650         blob = (uint8*) ntlmssp->nt_challenge_response.data;
651         memcpy(blob, nt_proof_str, 16);
652         memcpy(&blob[16], ntlm_v2_temp.data, ntlm_v2_temp.length);
653
654         /* Compute SessionBaseKey, the HMAC-MD5 hash of NTProofStr using the NTLMv2 hash as the key */
655         HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16,
656                 (void*) nt_proof_str, 16, (void*) ntlmssp->session_base_key, NULL);
657
658         freerdp_blob_free(&ntlm_v2_temp);
659         freerdp_blob_free(&ntlm_v2_temp_chal);
660 }
661
662 /**
663  * Input NegotiateFlags, a 4-byte bit map.
664  * @param s
665  * @param flags
666  */
667
668 void ntlmssp_input_negotiate_flags(STREAM* s, uint32* flags)
669 {
670         *flags = 0;
671         stream_read_uint32(s, *flags);
672 }
673
674 /**
675  * Output NegotiateFlags, a 4-byte bit map.
676  * @param s
677  * @param flags
678  */
679
680 void ntlmssp_output_negotiate_flags(STREAM* s, uint32 flags)
681 {
682         stream_write_uint32(s, flags);
683 }
684
685 void ntlmssp_print_negotiate_flags(uint32 flags)
686 {
687         int i;
688         const char* str;
689
690         printf("negotiateFlags \"0x%08X\"{\n", flags);
691
692         for (i = 31; i >= 0; i--)
693         {
694                 if ((flags >> i) & 1)
695                 {
696                         str = NTLMSSP_NEGOTIATE_STRINGS[(31 - i)];
697                         printf("\t%s (%d),\n", str, (31 - i));
698                 }
699         }
700
701         printf("}\n");
702 }
703
704 /**
705  * Output Restriction_Encoding.\n
706  * Restriction_Encoding @msdn{cc236647}
707  * @param ntlmssp
708  */
709
710 static void ntlmssp_output_restriction_encoding(NTLMSSP* ntlmssp)
711 {
712         AV_PAIR *restrictions = &ntlmssp->av_pairs->Restrictions;
713         STREAM* s = stream_new(0);
714
715         uint8 machineID[32] =
716                 "\x3A\x15\x8E\xA6\x75\x82\xD8\xF7\x3E\x06\xFA\x7A\xB4\xDF\xFD\x43"
717                 "\x84\x6C\x02\x3A\xFD\x5A\x94\xFE\xCF\x97\x0F\x3D\x19\x2C\x38\x20";
718
719         restrictions->value = xmalloc(48);
720         restrictions->length = 48;
721
722         s->data = restrictions->value;
723         s->size = restrictions->length;
724         s->p = s->data;
725
726         stream_write_uint32(s, 48); /* Size */
727         stream_write_zero(s, 4); /* Z4 (set to zero) */
728
729         /* IntegrityLevel (bit 31 set to 1) */
730         stream_write_uint8(s, 1);
731         stream_write_zero(s, 3);
732
733         stream_write_uint32(s, 0x00002000); /* SubjectIntegrityLevel */
734         stream_write(s, machineID, 32); /* MachineID */
735
736         xfree(s);
737 }
738
739 /**
740  * Output TargetName.\n
741  * @param ntlmssp
742  */
743
744 void ntlmssp_output_target_name(NTLMSSP* ntlmssp)
745 {
746         STREAM* s = stream_new(0);
747         AV_PAIR* target_name = &ntlmssp->av_pairs->TargetName;
748
749         /*
750          * TODO: No idea what should be set here (observed MsvAvTargetName = MsvAvDnsComputerName or
751          * MsvAvTargetName should be the name of the service be accessed after authentication)
752          * here used: "TERMSRV/192.168.0.123" in unicode (Dmitrij Jasnov)
753          */
754         uint8 name[42] =
755                         "\x54\x00\x45\x00\x52\x00\x4d\x00\x53\x00\x52\x00\x56\x00\x2f\x00\x31\x00\x39\x00\x32"
756                         "\x00\x2e\x00\x31\x00\x36\x00\x38\x00\x2e\x00\x30\x00\x2e\x00\x31\x00\x32\x00\x33\x00";
757
758         target_name->length = 42;
759         target_name->value = (uint8*) xmalloc(target_name->length);
760
761         s->data = target_name->value;
762         s->size = target_name->length;
763         s->p = s->data;
764
765         stream_write(s, name, target_name->length);
766
767         xfree(s);
768 }
769
770 /**
771  * Output ChannelBindings.\n
772  * @param ntlmssp
773  */
774
775 void ntlmssp_output_channel_bindings(NTLMSSP* ntlmssp)
776 {
777         STREAM* s = stream_new(0);
778         AV_PAIR* channel_bindings = &ntlmssp->av_pairs->ChannelBindings;
779
780         channel_bindings->value = (uint8*) xmalloc(48);
781         channel_bindings->length = 16;
782
783         s->data = channel_bindings->value;
784         s->size = channel_bindings->length;
785         s->p = s->data;
786
787         stream_write_zero(s, 16); /* an all-zero value of the hash is used to indicate absence of channel bindings */
788
789         xfree(s);
790 }
791
792 /**
793  * Populate array of AV_PAIRs.\n
794  * AV_PAIR @msdn{cc236646}
795  * @param ntlmssp
796  */
797
798 void ntlmssp_populate_av_pairs(NTLMSSP* ntlmssp)
799 {
800         STREAM* s;
801         rdpBlob target_info;
802         AV_PAIRS *av_pairs = ntlmssp->av_pairs;
803
804         /* MsvAvFlags */
805         av_pairs->Flags = 0x00000002; /* Indicates the present of a Message Integrity Check (MIC) */
806
807         /* Restriction_Encoding */
808         ntlmssp_output_restriction_encoding(ntlmssp);
809
810         /* TargetName */
811         ntlmssp_output_target_name(ntlmssp);
812
813         /* ChannelBindings */
814         ntlmssp_output_channel_bindings(ntlmssp);
815
816         s = stream_new(0);
817         s->data = xmalloc(ntlmssp->target_info.length + 512);
818         s->p = s->data;
819
820         ntlmssp_output_av_pairs(ntlmssp, s);
821         freerdp_blob_alloc(&target_info, s->p - s->data);
822         memcpy(target_info.data, s->data, target_info.length);
823
824         ntlmssp->target_info.data = target_info.data;
825         ntlmssp->target_info.length = target_info.length;
826 }
827
828 /**
829  * Input array of AV_PAIRs.\n
830  * AV_PAIR @msdn{cc236646}
831  * @param ntlmssp
832  * @param s
833  */
834
835 void ntlmssp_input_av_pairs(NTLMSSP* ntlmssp, STREAM* s)
836 {
837         AV_ID AvId;
838         uint16 AvLen;
839         uint8* value;
840         AV_PAIRS* av_pairs = ntlmssp->av_pairs;
841
842 #ifdef WITH_DEBUG_NLA
843         printf("AV_PAIRS = {\n");
844 #endif
845
846         do
847         {
848                 value = NULL;
849                 stream_read_uint16(s, AvId);
850                 stream_read_uint16(s, AvLen);
851
852                 if (AvLen > 0)
853                 {
854                         if (AvId != MsvAvFlags)
855                         {
856                                 value = xmalloc(AvLen);
857                                 stream_read(s, value, AvLen);
858                         }
859                         else
860                         {
861                                 stream_read_uint32(s, av_pairs->Flags);
862                         }
863                 }
864
865                 switch (AvId)
866                 {
867                         case MsvAvNbComputerName:
868                                 av_pairs->NbComputerName.length = AvLen;
869                                 av_pairs->NbComputerName.value = value;
870                                 break;
871
872                         case MsvAvNbDomainName:
873                                 av_pairs->NbDomainName.length = AvLen;
874                                 av_pairs->NbDomainName.value = value;
875                                 break;
876
877                         case MsvAvDnsComputerName:
878                                 av_pairs->DnsComputerName.length = AvLen;
879                                 av_pairs->DnsComputerName.value = value;
880                                 break;
881
882                         case MsvAvDnsDomainName:
883                                 av_pairs->DnsDomainName.length = AvLen;
884                                 av_pairs->DnsDomainName.value = value;
885                                 break;
886
887                         case MsvAvDnsTreeName:
888                                 av_pairs->DnsTreeName.length = AvLen;
889                                 av_pairs->DnsTreeName.value = value;
890                                 break;
891
892                         case MsvAvTimestamp:
893                                 av_pairs->Timestamp.length = AvLen;
894                                 av_pairs->Timestamp.value = value;
895                                 break;
896
897                         case MsvAvRestrictions:
898                                 av_pairs->Restrictions.length = AvLen;
899                                 av_pairs->Restrictions.value = value;
900                                 break;
901
902                         case MsvAvTargetName:
903                                 av_pairs->TargetName.length = AvLen;
904                                 av_pairs->TargetName.value = value;
905                                 break;
906
907                         case MsvChannelBindings:
908                                 av_pairs->ChannelBindings.length = AvLen;
909                                 av_pairs->ChannelBindings.value = value;
910                                 break;
911
912                         default:
913                                 if (value != NULL)
914                                         xfree(value);
915                                 break;
916                 }
917
918 #ifdef WITH_DEBUG_NLA
919                 if (AvId < 10)
920                         printf("\tAvId: %s, AvLen: %d\n", AV_PAIRS_STRINGS[AvId], AvLen);
921                 else
922                         printf("\tAvId: %s, AvLen: %d\n", "Unknown", AvLen);
923
924                 freerdp_hexdump(value, AvLen);
925 #endif
926         }
927         while (AvId != MsvAvEOL);
928
929 #ifdef WITH_DEBUG_NLA
930         printf("}\n");
931 #endif
932 }
933
934 /**
935  * Output array of AV_PAIRs.\n
936  * AV_PAIR @msdn{cc236646}
937  * @param ntlmssp
938  * @param s
939  */
940
941 void ntlmssp_output_av_pairs(NTLMSSP* ntlmssp, STREAM* s)
942 {
943         AV_PAIRS* av_pairs = ntlmssp->av_pairs;
944         
945         if (av_pairs->NbDomainName.length > 0)
946         {
947                 stream_write_uint16(s, MsvAvNbDomainName); /* AvId */
948                 stream_write_uint16(s, av_pairs->NbDomainName.length); /* AvLen */
949                 stream_write(s, av_pairs->NbDomainName.value, av_pairs->NbDomainName.length); /* Value */
950         }
951
952         if (av_pairs->NbComputerName.length > 0)
953         {
954                 stream_write_uint16(s, MsvAvNbComputerName); /* AvId */
955                 stream_write_uint16(s, av_pairs->NbComputerName.length); /* AvLen */
956                 stream_write(s, av_pairs->NbComputerName.value, av_pairs->NbComputerName.length); /* Value */
957         }
958
959         if (av_pairs->DnsDomainName.length > 0)
960         {
961                 stream_write_uint16(s, MsvAvDnsDomainName); /* AvId */
962                 stream_write_uint16(s, av_pairs->DnsDomainName.length); /* AvLen */
963                 stream_write(s, av_pairs->DnsDomainName.value, av_pairs->DnsDomainName.length); /* Value */
964         }
965
966         if (av_pairs->DnsComputerName.length > 0)
967         {
968                 stream_write_uint16(s, MsvAvDnsComputerName); /* AvId */
969                 stream_write_uint16(s, av_pairs->DnsComputerName.length); /* AvLen */
970                 stream_write(s, av_pairs->DnsComputerName.value, av_pairs->DnsComputerName.length); /* Value */
971         }
972
973         if (av_pairs->DnsTreeName.length > 0)
974         {
975                 stream_write_uint16(s, MsvAvDnsTreeName); /* AvId */
976                 stream_write_uint16(s, av_pairs->DnsTreeName.length); /* AvLen */
977                 stream_write(s, av_pairs->DnsTreeName.value, av_pairs->DnsTreeName.length); /* Value */
978         }
979
980         if (av_pairs->Timestamp.length > 0)
981         {
982                 stream_write_uint16(s, MsvAvTimestamp); /* AvId */
983                 stream_write_uint16(s, av_pairs->Timestamp.length); /* AvLen */
984                 stream_write(s, av_pairs->Timestamp.value, av_pairs->Timestamp.length); /* Value */
985         }
986
987         if (av_pairs->Flags > 0)
988         {
989                 stream_write_uint16(s, MsvAvFlags); /* AvId */
990                 stream_write_uint16(s, 4); /* AvLen */
991                 stream_write_uint32(s, av_pairs->Flags); /* Value */
992         }
993
994         if (av_pairs->Restrictions.length > 0)
995         {
996                 stream_write_uint16(s, MsvAvRestrictions); /* AvId */
997                 stream_write_uint16(s, av_pairs->Restrictions.length); /* AvLen */
998                 stream_write(s, av_pairs->Restrictions.value, av_pairs->Restrictions.length); /* Value */
999         }
1000
1001         if (av_pairs->ChannelBindings.length > 0)
1002         {
1003                 stream_write_uint16(s, MsvChannelBindings); /* AvId */
1004                 stream_write_uint16(s, av_pairs->ChannelBindings.length); /* AvLen */
1005                 stream_write(s, av_pairs->ChannelBindings.value, av_pairs->ChannelBindings.length); /* Value */
1006         }
1007
1008         if (av_pairs->TargetName.length > 0)
1009         {
1010                 stream_write_uint16(s, MsvAvTargetName); /* AvId */
1011                 stream_write_uint16(s, av_pairs->TargetName.length); /* AvLen */
1012                 stream_write(s, av_pairs->TargetName.value, av_pairs->TargetName.length); /* Value */
1013         }
1014
1015         /* This indicates the end of the AV_PAIR array */
1016         stream_write_uint16(s, MsvAvEOL); /* AvId */
1017         stream_write_uint16(s, 0); /* AvLen */
1018
1019         if (ntlmssp->ntlm_v2)
1020         {
1021                 stream_write_zero(s, 8);
1022         }
1023 }
1024
1025 /**
1026  * Print array of AV_PAIRs.\n
1027  * AV_PAIR @msdn{cc236646}
1028  * @param ntlmssp
1029  * @param s
1030  */
1031
1032 void ntlmssp_print_av_pairs(NTLMSSP* ntlmssp)
1033 {
1034         AV_PAIRS* av_pairs = ntlmssp->av_pairs;
1035
1036         printf("AV_PAIRS = {\n");
1037
1038         if (av_pairs->NbDomainName.length > 0)
1039         {
1040                 printf("\tAvId: MsvAvNbDomainName AvLen: %d\n", av_pairs->NbDomainName.length);
1041                 freerdp_hexdump(av_pairs->NbDomainName.value, av_pairs->NbDomainName.length);
1042         }
1043
1044         if (av_pairs->NbComputerName.length > 0)
1045         {
1046                 printf("\tAvId: MsvAvNbComputerName AvLen: %d\n", av_pairs->NbComputerName.length);
1047                 freerdp_hexdump(av_pairs->NbComputerName.value, av_pairs->NbComputerName.length);
1048         }
1049
1050         if (av_pairs->DnsDomainName.length > 0)
1051         {
1052                 printf("\tAvId: MsvAvDnsDomainName AvLen: %d\n", av_pairs->DnsDomainName.length);
1053                 freerdp_hexdump(av_pairs->DnsDomainName.value, av_pairs->DnsDomainName.length);
1054         }
1055
1056         if (av_pairs->DnsComputerName.length > 0)
1057         {
1058                 printf("\tAvId: MsvAvDnsComputerName AvLen: %d\n", av_pairs->DnsComputerName.length);
1059                 freerdp_hexdump(av_pairs->DnsComputerName.value, av_pairs->DnsComputerName.length);
1060         }
1061
1062         if (av_pairs->DnsTreeName.length > 0)
1063         {
1064                 printf("\tAvId: MsvAvDnsTreeName AvLen: %d\n", av_pairs->DnsTreeName.length);
1065                 freerdp_hexdump(av_pairs->DnsTreeName.value, av_pairs->DnsTreeName.length);
1066         }
1067
1068         if (av_pairs->Timestamp.length > 0)
1069         {
1070                 printf("\tAvId: MsvAvTimestamp AvLen: %d\n", av_pairs->Timestamp.length);
1071                 freerdp_hexdump(av_pairs->Timestamp.value, av_pairs->Timestamp.length);
1072         }
1073
1074         if (av_pairs->Flags > 0)
1075         {
1076                 printf("\tAvId: MsvAvFlags AvLen: %d\n", 4);
1077                 printf("0x%08X\n", av_pairs->Flags);
1078         }
1079
1080         if (av_pairs->Restrictions.length > 0)
1081         {
1082                 printf("\tAvId: MsvAvRestrictions AvLen: %d\n", av_pairs->Restrictions.length);
1083                 freerdp_hexdump(av_pairs->Restrictions.value, av_pairs->Restrictions.length);
1084         }
1085
1086         if (av_pairs->ChannelBindings.length > 0)
1087         {
1088                 printf("\tAvId: MsvChannelBindings AvLen: %d\n", av_pairs->ChannelBindings.length);
1089                 freerdp_hexdump(av_pairs->ChannelBindings.value, av_pairs->ChannelBindings.length);
1090         }
1091
1092         if (av_pairs->TargetName.length > 0)
1093         {
1094                 printf("\tAvId: MsvAvTargetName AvLen: %d\n", av_pairs->TargetName.length);
1095                 freerdp_hexdump(av_pairs->TargetName.value, av_pairs->TargetName.length);
1096         }
1097
1098         printf("}\n");
1099 }
1100
1101 /**
1102  * Free array of AV_PAIRs.\n
1103  * AV_PAIR @msdn{cc236646}
1104  * @param ntlmssp
1105  */
1106
1107 void ntlmssp_free_av_pairs(NTLMSSP* ntlmssp)
1108 {
1109         AV_PAIRS *av_pairs = ntlmssp->av_pairs;
1110         
1111         if (av_pairs != NULL)
1112         {
1113                 if (av_pairs->NbComputerName.value != NULL)
1114                         xfree(av_pairs->NbComputerName.value);
1115                 if (av_pairs->NbDomainName.value != NULL)
1116                         xfree(av_pairs->NbDomainName.value);
1117                 if (av_pairs->DnsComputerName.value != NULL)
1118                         xfree(av_pairs->DnsComputerName.value);
1119                 if (av_pairs->DnsDomainName.value != NULL)
1120                         xfree(av_pairs->DnsDomainName.value);
1121                 if (av_pairs->DnsTreeName.value != NULL)
1122                         xfree(av_pairs->DnsTreeName.value);
1123                 if (av_pairs->Timestamp.value != NULL)
1124                         xfree(av_pairs->Timestamp.value);
1125                 if (av_pairs->Restrictions.value != NULL)
1126                         xfree(av_pairs->Restrictions.value);
1127                 if (av_pairs->TargetName.value != NULL)
1128                         xfree(av_pairs->TargetName.value);
1129                 if (av_pairs->ChannelBindings.value != NULL)
1130                         xfree(av_pairs->ChannelBindings.value);
1131
1132                 xfree(av_pairs);
1133         }
1134
1135         ntlmssp->av_pairs = NULL;
1136 }
1137
1138 /**
1139  * Output VERSION structure.\n
1140  * VERSION @msdn{cc236654}
1141  * @param s
1142  */
1143
1144 static void ntlmssp_output_version(STREAM* s)
1145 {
1146         /* The following version information was observed with Windows 7 */
1147
1148         stream_write_uint8(s, WINDOWS_MAJOR_VERSION_6); /* ProductMajorVersion (1 byte) */
1149         stream_write_uint8(s, WINDOWS_MINOR_VERSION_1); /* ProductMinorVersion (1 byte) */
1150         stream_write_uint16(s, 7600); /* ProductBuild (2 bytes) */
1151         stream_write_zero(s, 3); /* Reserved (3 bytes) */
1152         stream_write_uint8(s, NTLMSSP_REVISION_W2K3); /* NTLMRevisionCurrent (1 byte) */
1153 }
1154
1155 void ntlmssp_compute_message_integrity_check(NTLMSSP* ntlmssp)
1156 {
1157         HMAC_CTX hmac_ctx;
1158
1159         /* 
1160          * Compute the HMAC-MD5 hash of ConcatenationOf(NEGOTIATE_MESSAGE,
1161          * CHALLENGE_MESSAGE, AUTHENTICATE_MESSAGE) using the ExportedSessionKey
1162          */
1163
1164         HMAC_CTX_init(&hmac_ctx);
1165         HMAC_Init_ex(&hmac_ctx, ntlmssp->exported_session_key, 16, EVP_md5(), NULL);
1166         HMAC_Update(&hmac_ctx, ntlmssp->negotiate_message.data, ntlmssp->negotiate_message.length);
1167         HMAC_Update(&hmac_ctx, ntlmssp->challenge_message.data, ntlmssp->challenge_message.length);
1168         HMAC_Update(&hmac_ctx, ntlmssp->authenticate_message.data, ntlmssp->authenticate_message.length);
1169         HMAC_Final(&hmac_ctx, ntlmssp->message_integrity_check, NULL);
1170 }
1171
1172 /**
1173  * Encrypt and sign message using NTLMSSP.\n
1174  * GSS_WrapEx() @msdn{cc236718}\n
1175  * EncryptMessage() @msdn{aa375378}
1176  * @param ntlmssp
1177  * @param[in] msg message to encrypt
1178  * @param[out] encrypted_msg encrypted message
1179  * @param[out] signature destination signature
1180  */
1181
1182 void ntlmssp_encrypt_message(NTLMSSP* ntlmssp, rdpBlob* msg, rdpBlob* encrypted_msg, uint8* signature)
1183 {
1184         HMAC_CTX hmac_ctx;
1185         uint8 digest[16];
1186         uint8 checksum[8];
1187         uint32 version = 1;
1188
1189         /* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,msg) using the client signing key */
1190         HMAC_CTX_init(&hmac_ctx);
1191         HMAC_Init_ex(&hmac_ctx, ntlmssp->client_signing_key, 16, EVP_md5(), NULL);
1192         HMAC_Update(&hmac_ctx, (void*) &ntlmssp->send_seq_num, 4);
1193         HMAC_Update(&hmac_ctx, msg->data, msg->length);
1194         HMAC_Final(&hmac_ctx, digest, NULL);
1195
1196         /* Allocate space for encrypted message */
1197         freerdp_blob_alloc(encrypted_msg, msg->length);
1198
1199         /* Encrypt message using with RC4 */
1200         crypto_rc4(ntlmssp->send_rc4_seal, msg->length, msg->data, encrypted_msg->data);
1201
1202         /* RC4-encrypt first 8 bytes of digest */
1203         crypto_rc4(ntlmssp->send_rc4_seal, 8, digest, checksum);
1204
1205         /* Concatenate version, ciphertext and sequence number to build signature */
1206         memcpy(signature, (void*) &version, 4);
1207         memcpy(&signature[4], (void*) checksum, 8);
1208         memcpy(&signature[12], (void*) &(ntlmssp->send_seq_num), 4);
1209
1210         HMAC_CTX_cleanup(&hmac_ctx);
1211
1212         ntlmssp->send_seq_num++;
1213 }
1214
1215 /**
1216  * Decrypt message and verify signature using NTLMSSP.\n
1217  * GSS_UnwrapEx() @msdn{cc236703}\n
1218  * DecryptMessage() @msdn{aa375211}
1219  * @param ntlmssp
1220  * @param[in] encrypted_msg encrypted message
1221  * @param[out] msg decrypted message
1222  * @param[in] signature signature
1223  * @return
1224  */
1225
1226 int ntlmssp_decrypt_message(NTLMSSP* ntlmssp, rdpBlob* encrypted_msg, rdpBlob* msg, uint8* signature)
1227 {
1228         HMAC_CTX hmac_ctx;
1229         uint8 digest[16];
1230         uint8 checksum[8];
1231         uint32 version = 1;
1232         uint8 expected_signature[16];
1233
1234         /* Allocate space for encrypted message */
1235         freerdp_blob_alloc(msg, encrypted_msg->length);
1236
1237         /* Encrypt message using with RC4 */
1238         crypto_rc4(ntlmssp->recv_rc4_seal, encrypted_msg->length, encrypted_msg->data, msg->data);
1239
1240         /* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,msg) using the client signing key */
1241         HMAC_CTX_init(&hmac_ctx);
1242         HMAC_Init_ex(&hmac_ctx, ntlmssp->server_signing_key, 16, EVP_md5(), NULL);
1243         HMAC_Update(&hmac_ctx, (void*) &ntlmssp->recv_seq_num, 4);
1244         HMAC_Update(&hmac_ctx, msg->data, msg->length);
1245         HMAC_Final(&hmac_ctx, digest, NULL);
1246
1247         /* RC4-encrypt first 8 bytes of digest */
1248         crypto_rc4(ntlmssp->recv_rc4_seal, 8, digest, checksum);
1249
1250         /* Concatenate version, ciphertext and sequence number to build signature */
1251         memcpy(expected_signature, (void*) &version, 4);
1252         memcpy(&expected_signature[4], (void*) checksum, 8);
1253         memcpy(&expected_signature[12], (void*) &(ntlmssp->recv_seq_num), 4);
1254
1255         if (memcmp(signature, expected_signature, 16) != 0)
1256         {
1257                 /* signature verification failed! */
1258                 printf("signature verification failed, something nasty is going on!\n");
1259                 return 0;
1260         }
1261
1262         HMAC_CTX_cleanup(&hmac_ctx);
1263
1264         ntlmssp->recv_seq_num++;
1265         return 1;
1266 }
1267
1268 /**
1269  * Send NTLMSSP NEGOTIATE_MESSAGE.\n
1270  * NEGOTIATE_MESSAGE @msdn{cc236641}
1271  * @param ntlmssp
1272  * @param s
1273  */
1274
1275 void ntlmssp_send_negotiate_message(NTLMSSP* ntlmssp, STREAM* s)
1276 {
1277         int length;
1278         uint32 negotiateFlags = 0;
1279
1280         stream_write(s, ntlm_signature, 8); /* Signature (8 bytes) */
1281         stream_write_uint32(s, 1); /* MessageType */
1282
1283         if (ntlmssp->ntlm_v2)
1284         {
1285                 DEBUG_NLA("Negotiating NTLMv2");
1286                 /* observed: B7 82 08 E2 (0xE20882B7) (Dmitrij Jasnov) */
1287                 negotiateFlags |= NTLMSSP_NEGOTIATE_56;
1288                 negotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
1289                 negotiateFlags |= NTLMSSP_NEGOTIATE_128;
1290                 negotiateFlags |= NTLMSSP_NEGOTIATE_VERSION;
1291                 negotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
1292                 negotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
1293                 negotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
1294                 negotiateFlags |= NTLMSSP_NEGOTIATE_LM_KEY;
1295                 negotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
1296                 negotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
1297                 negotiateFlags |= NTLMSSP_REQUEST_TARGET;
1298                 negotiateFlags |= NTLMSSP_NEGOTIATE_OEM;
1299                 negotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
1300         }
1301         else
1302         {
1303                 negotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
1304                 negotiateFlags |= NTLMSSP_NEGOTIATE_128;
1305                 negotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
1306                 negotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
1307                 negotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
1308                 negotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
1309                 negotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
1310                 negotiateFlags |= NTLMSSP_REQUEST_TARGET;
1311                 negotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
1312         }
1313
1314         ntlmssp_output_negotiate_flags(s, negotiateFlags); /* NegotiateFlags (4 bytes) */
1315
1316 #ifdef WITH_DEBUG_NLA
1317         ntlmssp_print_negotiate_flags(negotiateFlags);
1318 #endif
1319
1320         /* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */
1321
1322         /* DomainNameFields (8 bytes) */
1323         stream_write_uint16(s, 0); /* DomainNameLen */
1324         stream_write_uint16(s, 0); /* DomainNameMaxLen */
1325         stream_write_uint32(s, 0); /* DomainNameBufferOffset */
1326
1327         /* only set if NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED is set */
1328
1329         /* WorkstationFields (8 bytes) */
1330         stream_write_uint16(s, 0); /* WorkstationLen */
1331         stream_write_uint16(s, 0); /* WorkstationMaxLen */
1332         stream_write_uint32(s, 0); /* WorkstationBufferOffset */
1333
1334         if (negotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
1335         {
1336                 /* Only present if NTLMSSP_NEGOTIATE_VERSION is set */
1337                 ntlmssp_output_version(s);
1338
1339 #ifdef WITH_DEBUG_NLA
1340                 printf("Version (length = 8)\n");
1341                 freerdp_hexdump((s->p - 8), 8);
1342                 printf("\n");
1343 #endif
1344         }
1345
1346         length = s->p - s->data;
1347         freerdp_blob_alloc(&ntlmssp->negotiate_message, length);
1348         memcpy(ntlmssp->negotiate_message.data, s->data, length);
1349
1350 #ifdef WITH_DEBUG_NLA
1351         printf("NEGOTIATE_MESSAGE (length = %d)\n", length);
1352         freerdp_hexdump(s->data, length);
1353         printf("\n");
1354 #endif
1355
1356         ntlmssp->state = NTLMSSP_STATE_CHALLENGE;
1357 }
1358
1359 /**
1360  * Receive NTLMSSP CHALLENGE_MESSAGE.\n
1361  * CHALLENGE_MESSAGE @msdn{cc236642}
1362  * @param ntlmssp
1363  * @param s
1364  */
1365
1366 void ntlmssp_recv_challenge_message(NTLMSSP* ntlmssp, STREAM* s)
1367 {
1368         uint8* p;
1369         int length;
1370         uint8* start_offset;
1371         uint8* payload_offset;
1372         uint16 targetNameLen;
1373         uint16 targetNameMaxLen;
1374         uint32 targetNameBufferOffset;
1375         uint16 targetInfoLen;
1376         uint16 targetInfoMaxLen;
1377         uint32 targetInfoBufferOffset;
1378
1379         start_offset = s->p - 12;
1380
1381         /* TargetNameFields (8 bytes) */
1382         stream_read_uint16(s, targetNameLen); /* TargetNameLen (2 bytes) */
1383         stream_read_uint16(s, targetNameMaxLen); /* TargetNameMaxLen (2 bytes) */
1384         stream_read_uint32(s, targetNameBufferOffset); /* TargetNameBufferOffset (4 bytes) */
1385
1386         ntlmssp_input_negotiate_flags(s, &(ntlmssp->negotiate_flags)); /* NegotiateFlags (4 bytes) */
1387
1388 #ifdef WITH_DEBUG_NLA
1389         ntlmssp_print_negotiate_flags(ntlmssp->negotiate_flags);
1390 #endif
1391
1392         stream_read(s, ntlmssp->server_challenge, 8); /* ServerChallenge (8 bytes) */
1393         stream_seek(s, 8); /* Reserved (8 bytes), should be ignored */
1394
1395         /* TargetInfoFields (8 bytes) */
1396         stream_read_uint16(s, targetInfoLen); /* TargetInfoLen (2 bytes) */
1397         stream_read_uint16(s, targetInfoMaxLen); /* TargetInfoMaxLen (2 bytes) */
1398         stream_read_uint32(s, targetInfoBufferOffset); /* TargetInfoBufferOffset (4 bytes) */
1399
1400         /* only present if NTLMSSP_NEGOTIATE_VERSION is set */
1401
1402         if (ntlmssp->negotiate_flags & NTLMSSP_NEGOTIATE_VERSION)
1403         {
1404                 stream_seek(s, 8); /* Version (8 bytes), can be ignored */
1405         }
1406
1407         /* Payload (variable) */
1408         payload_offset = s->p;
1409
1410         if (targetNameLen > 0)
1411         {
1412                 p = start_offset + targetNameBufferOffset;
1413                 freerdp_blob_alloc(&ntlmssp->target_name, targetNameLen);
1414                 memcpy(ntlmssp->target_name.data, p, targetNameLen);
1415
1416 #ifdef WITH_DEBUG_NLA
1417                 printf("targetName (length = %d, offset = %d)\n", targetNameLen, targetNameBufferOffset);
1418                 freerdp_hexdump(ntlmssp->target_name.data, ntlmssp->target_name.length);
1419                 printf("\n");
1420 #endif
1421         }
1422
1423         if (targetInfoLen > 0)
1424         {
1425                 p = start_offset + targetInfoBufferOffset;
1426                 freerdp_blob_alloc(&ntlmssp->target_info, targetInfoLen);
1427                 memcpy(ntlmssp->target_info.data, p, targetInfoLen);
1428
1429 #ifdef WITH_DEBUG_NLA
1430                 printf("targetInfo (length = %d, offset = %d)\n", targetInfoLen, targetInfoBufferOffset);
1431                 freerdp_hexdump(ntlmssp->target_info.data, ntlmssp->target_info.length);
1432                 printf("\n");
1433 #endif
1434
1435                 if (ntlmssp->ntlm_v2)
1436                 {
1437                         s->p = p;
1438                         ntlmssp_input_av_pairs(ntlmssp, s);
1439                 }
1440         }
1441
1442         length = (payload_offset - start_offset) + targetNameLen + targetInfoLen;
1443
1444         freerdp_blob_alloc(&ntlmssp->challenge_message, length);
1445         memcpy(ntlmssp->challenge_message.data, start_offset, length);
1446
1447 #ifdef WITH_DEBUG_NLA
1448         printf("CHALLENGE_MESSAGE (length = %d)\n", length);
1449         freerdp_hexdump(start_offset, length);
1450         printf("\n");
1451 #endif
1452
1453         /* AV_PAIRs */
1454         if (ntlmssp->ntlm_v2)
1455                 ntlmssp_populate_av_pairs(ntlmssp);
1456
1457         /* Timestamp */
1458         ntlmssp_generate_timestamp(ntlmssp);
1459
1460         /* LmChallengeResponse */
1461         ntlmssp_compute_lm_v2_response(ntlmssp);
1462
1463         if (ntlmssp->ntlm_v2)
1464                 memset(ntlmssp->lm_challenge_response.data, '\0', 24);
1465
1466         /* NtChallengeResponse */
1467         ntlmssp_compute_ntlm_v2_response(ntlmssp);
1468
1469         /* KeyExchangeKey */
1470         ntlmssp_generate_key_exchange_key(ntlmssp);
1471
1472         /* EncryptedRandomSessionKey */
1473         ntlmssp_encrypt_random_session_key(ntlmssp);
1474
1475         /* Generate signing keys */
1476         ntlmssp_generate_client_signing_key(ntlmssp);
1477         ntlmssp_generate_server_signing_key(ntlmssp);
1478
1479         /* Generate sealing keys */
1480         ntlmssp_generate_client_sealing_key(ntlmssp);
1481         ntlmssp_generate_server_sealing_key(ntlmssp);
1482
1483         /* Initialize RC4 seal state using client sealing key */
1484         ntlmssp_init_rc4_seal_states(ntlmssp);
1485
1486 #ifdef WITH_DEBUG_NLA
1487         printf("ClientChallenge\n");
1488         freerdp_hexdump(ntlmssp->client_challenge, 8);
1489         printf("\n");
1490
1491         printf("ServerChallenge\n");
1492         freerdp_hexdump(ntlmssp->server_challenge, 8);
1493         printf("\n");
1494
1495         printf("SessionBaseKey\n");
1496         freerdp_hexdump(ntlmssp->session_base_key, 16);
1497         printf("\n");
1498
1499         printf("KeyExchangeKey\n");
1500         freerdp_hexdump(ntlmssp->key_exchange_key, 16);
1501         printf("\n");
1502
1503         printf("ExportedSessionKey\n");
1504         freerdp_hexdump(ntlmssp->exported_session_key, 16);
1505         printf("\n");
1506
1507         printf("RandomSessionKey\n");
1508         freerdp_hexdump(ntlmssp->random_session_key, 16);
1509         printf("\n");
1510
1511         printf("ClientSignKey\n");
1512         freerdp_hexdump(ntlmssp->client_signing_key, 16);
1513         printf("\n");
1514
1515         printf("ClientSealingKey\n");
1516         freerdp_hexdump(ntlmssp->client_sealing_key, 16);
1517         printf("\n");
1518
1519         printf("Timestamp\n");
1520         freerdp_hexdump(ntlmssp->timestamp, 8);
1521         printf("\n");
1522 #endif
1523
1524         ntlmssp->state = NTLMSSP_STATE_AUTHENTICATE;
1525 }
1526
1527 /**
1528  * Send NTLMSSP AUTHENTICATE_MESSAGE.\n
1529  * AUTHENTICATE_MESSAGE @msdn{cc236643}
1530  * @param ntlmssp
1531  * @param s
1532  */
1533
1534 void ntlmssp_send_authenticate_message(NTLMSSP* ntlmssp, STREAM* s)
1535 {
1536         int length;
1537         uint32 negotiateFlags = 0;
1538         uint8* mic_offset = NULL;
1539
1540         uint16 DomainNameLen;
1541         uint16 UserNameLen;
1542         uint16 WorkstationLen;
1543         uint16 LmChallengeResponseLen;
1544         uint16 NtChallengeResponseLen;
1545         uint16 EncryptedRandomSessionKeyLen;
1546
1547         uint32 PayloadBufferOffset;
1548         uint32 DomainNameBufferOffset;
1549         uint32 UserNameBufferOffset;
1550         uint32 WorkstationBufferOffset;
1551         uint32 LmChallengeResponseBufferOffset;
1552         uint32 NtChallengeResponseBufferOffset;
1553         uint32 EncryptedRandomSessionKeyBufferOffset;
1554
1555         uint8* UserNameBuffer;
1556         uint8* DomainNameBuffer;
1557         uint8* WorkstationBuffer;
1558         uint8* EncryptedRandomSessionKeyBuffer;
1559
1560         WorkstationLen = ntlmssp->workstation.length;
1561         WorkstationBuffer = ntlmssp->workstation.data;
1562
1563         if (ntlmssp->ntlm_v2 < 1)
1564                 WorkstationLen = 0;
1565
1566         DomainNameLen = ntlmssp->domain.length;
1567         DomainNameBuffer = ntlmssp->domain.data;
1568
1569         UserNameLen = ntlmssp->username.length;
1570         UserNameBuffer = ntlmssp->username.data;
1571
1572         LmChallengeResponseLen = ntlmssp->lm_challenge_response.length;
1573         NtChallengeResponseLen = ntlmssp->nt_challenge_response.length;
1574
1575         EncryptedRandomSessionKeyLen = 16;
1576         EncryptedRandomSessionKeyBuffer = ntlmssp->encrypted_random_session_key;
1577
1578         if (ntlmssp->ntlm_v2)
1579         {
1580                 /* observed: 35 82 88 e2 (0xE2888235) */
1581                 negotiateFlags |= NTLMSSP_NEGOTIATE_56;
1582                 negotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
1583                 negotiateFlags |= NTLMSSP_NEGOTIATE_128;
1584                 negotiateFlags |= NTLMSSP_NEGOTIATE_VERSION;
1585                 negotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO;
1586                 negotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
1587                 negotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
1588                 negotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
1589                 negotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
1590                 negotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
1591                 negotiateFlags |= NTLMSSP_REQUEST_TARGET;
1592                 negotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
1593         }
1594         else
1595         {
1596                 negotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
1597                 negotiateFlags |= NTLMSSP_NEGOTIATE_128;
1598                 negotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
1599                 negotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
1600                 negotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
1601                 negotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
1602                 negotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
1603                 negotiateFlags |= NTLMSSP_REQUEST_TARGET;
1604                 negotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
1605         }
1606
1607         if (ntlmssp->ntlm_v2)
1608                 PayloadBufferOffset = 80; /* starting buffer offset */
1609         else
1610                 PayloadBufferOffset = 64; /* starting buffer offset */
1611
1612         if (negotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
1613                 PayloadBufferOffset += 8;
1614
1615         DomainNameBufferOffset = PayloadBufferOffset;
1616         UserNameBufferOffset = DomainNameBufferOffset + DomainNameLen;
1617         WorkstationBufferOffset = UserNameBufferOffset + UserNameLen;
1618         LmChallengeResponseBufferOffset = WorkstationBufferOffset + WorkstationLen;
1619         NtChallengeResponseBufferOffset = LmChallengeResponseBufferOffset + LmChallengeResponseLen;
1620         EncryptedRandomSessionKeyBufferOffset = NtChallengeResponseBufferOffset + NtChallengeResponseLen;
1621
1622         stream_write(s, ntlm_signature, 8); /* Signature (8 bytes) */
1623         stream_write_uint32(s, 3); /* MessageType */
1624
1625         /* LmChallengeResponseFields (8 bytes) */
1626         stream_write_uint16(s, LmChallengeResponseLen); /* LmChallengeResponseLen */
1627         stream_write_uint16(s, LmChallengeResponseLen); /* LmChallengeResponseMaxLen */
1628         stream_write_uint32(s, LmChallengeResponseBufferOffset); /* LmChallengeResponseBufferOffset */
1629
1630         /* NtChallengeResponseFields (8 bytes) */
1631         stream_write_uint16(s, NtChallengeResponseLen); /* NtChallengeResponseLen */
1632         stream_write_uint16(s, NtChallengeResponseLen); /* NtChallengeResponseMaxLen */
1633         stream_write_uint32(s, NtChallengeResponseBufferOffset); /* NtChallengeResponseBufferOffset */
1634
1635         /* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */
1636
1637         /* DomainNameFields (8 bytes) */
1638         stream_write_uint16(s, DomainNameLen); /* DomainNameLen */
1639         stream_write_uint16(s, DomainNameLen); /* DomainNameMaxLen */
1640         stream_write_uint32(s, DomainNameBufferOffset); /* DomainNameBufferOffset */
1641
1642         /* UserNameFields (8 bytes) */
1643         stream_write_uint16(s, UserNameLen); /* UserNameLen */
1644         stream_write_uint16(s, UserNameLen); /* UserNameMaxLen */
1645         stream_write_uint32(s, UserNameBufferOffset); /* UserNameBufferOffset */
1646
1647         /* only set if NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED is set */
1648
1649         /* WorkstationFields (8 bytes) */
1650         stream_write_uint16(s, WorkstationLen); /* WorkstationLen */
1651         stream_write_uint16(s, WorkstationLen); /* WorkstationMaxLen */
1652         stream_write_uint32(s, WorkstationBufferOffset); /* WorkstationBufferOffset */
1653
1654         /* EncryptedRandomSessionKeyFields (8 bytes) */
1655         stream_write_uint16(s, EncryptedRandomSessionKeyLen); /* EncryptedRandomSessionKeyLen */
1656         stream_write_uint16(s, EncryptedRandomSessionKeyLen); /* EncryptedRandomSessionKeyMaxLen */
1657         stream_write_uint32(s, EncryptedRandomSessionKeyBufferOffset); /* EncryptedRandomSessionKeyBufferOffset */
1658
1659         ntlmssp_output_negotiate_flags(s, negotiateFlags); /* NegotiateFlags (4 bytes) */
1660
1661 #ifdef WITH_DEBUG_NLA
1662         ntlmssp_print_negotiate_flags(negotiateFlags);
1663 #endif
1664         
1665         if (negotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
1666         {
1667                 /* Only present if NTLMSSP_NEGOTIATE_VERSION is set */
1668                 ntlmssp_output_version(s);
1669
1670 #ifdef WITH_DEBUG_NLA
1671                 printf("Version (length = 8)\n");
1672                 freerdp_hexdump((s->p - 8), 8);
1673                 printf("\n");
1674 #endif
1675         }
1676
1677         if (ntlmssp->ntlm_v2)
1678         {
1679                 /* Message Integrity Check */
1680                 mic_offset = s->p;
1681                 stream_write_zero(s, 16);
1682         }
1683
1684         /* DomainName */
1685         if (DomainNameLen > 0)
1686         {
1687                 stream_write(s, DomainNameBuffer, DomainNameLen);
1688 #ifdef WITH_DEBUG_NLA
1689                 printf("DomainName (length = %d, offset = %d)\n", DomainNameLen, DomainNameBufferOffset);
1690                 freerdp_hexdump(DomainNameBuffer, DomainNameLen);
1691                 printf("\n");
1692 #endif
1693         }
1694
1695         /* UserName */
1696         stream_write(s, UserNameBuffer, UserNameLen);
1697
1698 #ifdef WITH_DEBUG_NLA
1699         printf("UserName (length = %d, offset = %d)\n", UserNameLen, UserNameBufferOffset);
1700         freerdp_hexdump(UserNameBuffer, UserNameLen);
1701         printf("\n");
1702 #endif
1703
1704         /* Workstation */
1705         if (WorkstationLen > 0)
1706         {
1707                 stream_write(s, WorkstationBuffer, WorkstationLen);
1708 #ifdef WITH_DEBUG_NLA
1709                 printf("Workstation (length = %d, offset = %d)\n", WorkstationLen, WorkstationBufferOffset);
1710                 freerdp_hexdump(WorkstationBuffer, WorkstationLen);
1711                 printf("\n");
1712 #endif
1713         }
1714
1715         /* LmChallengeResponse */
1716         stream_write(s, ntlmssp->lm_challenge_response.data, LmChallengeResponseLen);
1717
1718 #ifdef WITH_DEBUG_NLA
1719         printf("LmChallengeResponse (length = %d, offset = %d)\n", LmChallengeResponseLen, LmChallengeResponseBufferOffset);
1720         freerdp_hexdump(ntlmssp->lm_challenge_response.data, LmChallengeResponseLen);
1721         printf("\n");
1722 #endif
1723
1724         /* NtChallengeResponse */
1725         stream_write(s, ntlmssp->nt_challenge_response.data, NtChallengeResponseLen);
1726
1727 #ifdef WITH_DEBUG_NLA
1728         if (ntlmssp->ntlm_v2)
1729         {
1730                 ntlmssp_print_av_pairs(ntlmssp);
1731
1732                 printf("targetInfo (length = %d)\n", ntlmssp->target_info.length);
1733                 freerdp_hexdump(ntlmssp->target_info.data, ntlmssp->target_info.length);
1734                 printf("\n");
1735         }
1736 #endif
1737
1738 #ifdef WITH_DEBUG_NLA
1739         printf("NtChallengeResponse (length = %d, offset = %d)\n", NtChallengeResponseLen, NtChallengeResponseBufferOffset);
1740         freerdp_hexdump(ntlmssp->nt_challenge_response.data, NtChallengeResponseLen);
1741         printf("\n");
1742 #endif
1743
1744         /* EncryptedRandomSessionKey */
1745         stream_write(s, EncryptedRandomSessionKeyBuffer, EncryptedRandomSessionKeyLen);
1746
1747 #ifdef WITH_DEBUG_NLA
1748         printf("EncryptedRandomSessionKey (length = %d, offset = %d)\n", EncryptedRandomSessionKeyLen, EncryptedRandomSessionKeyBufferOffset);
1749         freerdp_hexdump(EncryptedRandomSessionKeyBuffer, EncryptedRandomSessionKeyLen);
1750         printf("\n");
1751 #endif
1752
1753         length = s->p - s->data;
1754         freerdp_blob_alloc(&ntlmssp->authenticate_message, length);
1755         memcpy(ntlmssp->authenticate_message.data, s->data, length);
1756
1757         if (ntlmssp->ntlm_v2)
1758         {
1759                 /* Message Integrity Check */
1760                 ntlmssp_compute_message_integrity_check(ntlmssp);
1761                 
1762                 s->p = mic_offset;
1763                 stream_write(s, ntlmssp->message_integrity_check, 16);
1764                 s->p = s->data + length;
1765
1766 #ifdef WITH_DEBUG_NLA
1767                 printf("MessageIntegrityCheck (length = 16)\n");
1768                 freerdp_hexdump(mic_offset, 16);
1769                 printf("\n");
1770 #endif
1771         }
1772
1773 #ifdef WITH_DEBUG_NLA
1774         printf("AUTHENTICATE_MESSAGE (length = %d)\n", length);
1775         freerdp_hexdump(s->data, length);
1776         printf("\n");
1777 #endif
1778
1779         ntlmssp->state = NTLMSSP_STATE_FINAL;
1780 }
1781
1782 /**
1783  * Send NTLMSSP message.
1784  * @param ntlmssp
1785  * @param s
1786  * @return
1787  */
1788
1789 int ntlmssp_send(NTLMSSP* ntlmssp, STREAM* s)
1790 {
1791         if (ntlmssp->state == NTLMSSP_STATE_INITIAL)
1792                 ntlmssp->state = NTLMSSP_STATE_NEGOTIATE;
1793
1794         if (ntlmssp->state == NTLMSSP_STATE_NEGOTIATE)
1795                 ntlmssp_send_negotiate_message(ntlmssp, s);
1796         else if (ntlmssp->state == NTLMSSP_STATE_AUTHENTICATE)
1797                 ntlmssp_send_authenticate_message(ntlmssp, s);
1798
1799         return (ntlmssp->state == NTLMSSP_STATE_FINAL) ? 0 : 1;
1800 }
1801
1802 /**
1803  * Receive NTLMSSP message.
1804  * @param ntlmssp
1805  * @param s
1806  * @return
1807  */
1808
1809 int ntlmssp_recv(NTLMSSP* ntlmssp, STREAM* s)
1810 {
1811         char signature[8]; /* Signature, "NTLMSSP" */
1812         uint32 messageType; /* MessageType */
1813
1814         stream_read(s, signature, 8);
1815         stream_read_uint32(s, messageType);
1816
1817         if (messageType == 2 && ntlmssp->state == NTLMSSP_STATE_CHALLENGE)
1818                 ntlmssp_recv_challenge_message(ntlmssp, s);
1819
1820         return 1;
1821 }
1822
1823 /**
1824  * Create new NTLMSSP state machine instance.
1825  * @return
1826  */
1827
1828 NTLMSSP* ntlmssp_new()
1829 {
1830         NTLMSSP* ntlmssp = (NTLMSSP*) xmalloc(sizeof(NTLMSSP));
1831
1832         if (ntlmssp != NULL)
1833         {
1834                 memset(ntlmssp, '\0', sizeof(NTLMSSP));
1835                 ntlmssp->av_pairs = (AV_PAIRS*) xmalloc(sizeof(AV_PAIRS));
1836                 memset(ntlmssp->av_pairs, 0, sizeof(AV_PAIRS));
1837                 ntlmssp_init(ntlmssp);
1838         }
1839
1840         return ntlmssp;
1841 }
1842
1843 /**
1844  * Initialize NTLMSSP state machine.
1845  * @param ntlmssp
1846  */
1847
1848 void ntlmssp_init(NTLMSSP* ntlmssp)
1849 {
1850         ntlmssp->state = NTLMSSP_STATE_INITIAL;
1851         ntlmssp->uniconv = freerdp_uniconv_new();
1852 }
1853
1854 /**
1855  * Finalize NTLMSSP state machine.
1856  * @param ntlmssp
1857  */
1858
1859 void ntlmssp_uninit(NTLMSSP* ntlmssp)
1860 {
1861         freerdp_blob_free(&ntlmssp->username);
1862         freerdp_blob_free(&ntlmssp->password);
1863         freerdp_blob_free(&ntlmssp->domain);
1864
1865         freerdp_blob_free(&ntlmssp->spn);
1866         freerdp_blob_free(&ntlmssp->workstation);
1867         freerdp_blob_free(&ntlmssp->target_info);
1868         freerdp_blob_free(&ntlmssp->target_name);
1869
1870         freerdp_blob_free(&ntlmssp->negotiate_message);
1871         freerdp_blob_free(&ntlmssp->challenge_message);
1872         freerdp_blob_free(&ntlmssp->authenticate_message);
1873
1874         freerdp_blob_free(&ntlmssp->lm_challenge_response);
1875         freerdp_blob_free(&ntlmssp->nt_challenge_response);
1876
1877         ntlmssp_free_av_pairs(ntlmssp);
1878         freerdp_uniconv_free(ntlmssp->uniconv);
1879
1880         ntlmssp->state = NTLMSSP_STATE_FINAL;
1881 }
1882
1883 /**
1884  * Free NTLMSSP state machine.
1885  * @param ntlmssp
1886  */
1887
1888 void ntlmssp_free(NTLMSSP* ntlmssp)
1889 {
1890         ntlmssp_uninit(ntlmssp);
1891
1892         if (ntlmssp->send_rc4_seal)
1893                 crypto_rc4_free(ntlmssp->send_rc4_seal);
1894         if (ntlmssp->recv_rc4_seal)
1895                 crypto_rc4_free(ntlmssp->recv_rc4_seal);
1896         xfree(ntlmssp);
1897 }