d2d78da03ef304198470b5433a21ac104115802e
[platform/upstream/freerdp.git] / libfreerdp / core / nla.c
1 /**
2  * WinPR: Windows Portable Runtime
3  * Network Level Authentication (NLA)
4  *
5  * Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  * Copyright 2015 Thincast Technologies GmbH
7  * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *               http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <time.h>
27
28 #ifndef _WIN32
29 #include <unistd.h>
30 #endif
31
32 #include <freerdp/log.h>
33 #include <freerdp/crypto/tls.h>
34
35 #include <winpr/crt.h>
36 #include <winpr/sspi.h>
37 #include <winpr/print.h>
38 #include <winpr/tchar.h>
39 #include <winpr/dsparse.h>
40 #include <winpr/library.h>
41 #include <winpr/registry.h>
42
43 #include "nla.h"
44
45 #define TAG FREERDP_TAG("core.nla")
46
47 /**
48  * TSRequest ::= SEQUENCE {
49  *      version    [0] INTEGER,
50  *      negoTokens [1] NegoData OPTIONAL,
51  *      authInfo   [2] OCTET STRING OPTIONAL,
52  *      pubKeyAuth [3] OCTET STRING OPTIONAL
53  * }
54  *
55  * NegoData ::= SEQUENCE OF NegoDataItem
56  *
57  * NegoDataItem ::= SEQUENCE {
58  *      negoToken [0] OCTET STRING
59  * }
60  *
61  * TSCredentials ::= SEQUENCE {
62  *      credType    [0] INTEGER,
63  *      credentials [1] OCTET STRING
64  * }
65  *
66  * TSPasswordCreds ::= SEQUENCE {
67  *      domainName  [0] OCTET STRING,
68  *      userName    [1] OCTET STRING,
69  *      password    [2] OCTET STRING
70  * }
71  *
72  * TSSmartCardCreds ::= SEQUENCE {
73  *      pin        [0] OCTET STRING,
74  *      cspData    [1] TSCspDataDetail,
75  *      userHint   [2] OCTET STRING OPTIONAL,
76  *      domainHint [3] OCTET STRING OPTIONAL
77  * }
78  *
79  * TSCspDataDetail ::= SEQUENCE {
80  *      keySpec       [0] INTEGER,
81  *      cardName      [1] OCTET STRING OPTIONAL,
82  *      readerName    [2] OCTET STRING OPTIONAL,
83  *      containerName [3] OCTET STRING OPTIONAL,
84  *      cspName       [4] OCTET STRING OPTIONAL
85  * }
86  *
87  */
88
89 #define NLA_PKG_NAME    NEGOSSP_NAME
90
91 #define TERMSRV_SPN_PREFIX      "TERMSRV/"
92
93 BOOL nla_send(rdpNla* nla);
94 int nla_recv(rdpNla* nla);
95 void nla_buffer_print(rdpNla* nla);
96 void nla_buffer_free(rdpNla* nla);
97 SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla);
98 SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla);
99 SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla);
100 SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla);
101
102 #define ber_sizeof_sequence_octet_string(length) ber_sizeof_contextual_tag(ber_sizeof_octet_string(length)) + ber_sizeof_octet_string(length)
103 #define ber_write_sequence_octet_string(stream, context, value, length) ber_write_contextual_tag(stream, context, ber_sizeof_octet_string(length), TRUE) + ber_write_octet_string(stream, value, length)
104
105 /**
106  * Initialize NTLMSSP authentication module (client).
107  * @param credssp
108  */
109
110 int nla_client_init(rdpNla* nla)
111 {
112         char* spn;
113         int length;
114         rdpTls* tls = NULL;
115         BOOL PromptPassword = FALSE;
116         freerdp* instance = nla->instance;
117         rdpSettings* settings = nla->settings;
118
119         nla->state = NLA_STATE_INITIAL;
120
121         if (settings->RestrictedAdminModeRequired)
122                 settings->DisableCredentialsDelegation = TRUE;
123
124         if ((!settings->Password) || (!settings->Username)
125                         || (!strlen(settings->Password)) || (!strlen(settings->Username)))
126         {
127                 PromptPassword = TRUE;
128         }
129
130 #ifndef _WIN32
131         if (PromptPassword)
132         {
133                 if (settings->RestrictedAdminModeRequired)
134                 {
135                         if ((settings->PasswordHash) && (strlen(settings->PasswordHash) > 0))
136                                 PromptPassword = FALSE;
137                 }
138         }
139 #endif
140
141         if (PromptPassword)
142         {
143                 if (instance->Authenticate)
144                 {
145                         BOOL proceed = instance->Authenticate(instance,
146                                                 &settings->Username, &settings->Password, &settings->Domain);
147
148                         if (!proceed)
149                         {
150                                 freerdp_set_last_error(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
151                                 return 0;
152                         }
153                 }
154         }
155
156         sspi_SetAuthIdentity(&(nla->identity), settings->Username, settings->Domain, settings->Password);
157
158 #ifndef _WIN32
159         {
160                 SEC_WINNT_AUTH_IDENTITY* identity = &(nla->identity);
161
162                 if (settings->RestrictedAdminModeRequired)
163                 {
164                         if (settings->PasswordHash)
165                         {
166                                 if (strlen(settings->PasswordHash) == 32)
167                                 {
168                                         free(identity->Password);
169
170                                         identity->PasswordLength = ConvertToUnicode(CP_UTF8, 0,
171                                                         settings->PasswordHash, -1, &identity->Password, 0) - 1;
172                                         /**
173                                          * Multiply password hash length by 64 to obtain a length exceeding
174                                          * the maximum (256) and use it this for hash identification in WinPR.
175                                          */
176                                         identity->PasswordLength = 32 * 64; /* 2048 */
177                                 }
178                         }
179                 }
180         }
181 #endif
182
183         tls = nla->transport->tls;
184
185         if (!tls)
186         {
187                 WLog_ERR(TAG, "Unknown NLA transport layer");
188                 return -1;
189         }
190
191         if (!sspi_SecBufferAlloc(&nla->PublicKey, tls->PublicKeyLength))
192         {
193                 WLog_ERR(TAG, "Failed to allocate sspic secBuffer");
194                 return -1;
195         }
196         CopyMemory(nla->PublicKey.pvBuffer, tls->PublicKey, tls->PublicKeyLength);
197         length = sizeof(TERMSRV_SPN_PREFIX) + strlen(settings->ServerHostname);
198
199         spn = (SEC_CHAR*) malloc(length + 1);
200
201         if (!spn)
202                 return -1;
203
204         sprintf(spn, "%s%s", TERMSRV_SPN_PREFIX, settings->ServerHostname);
205
206 #ifdef UNICODE
207         nla->ServicePrincipalName = NULL;
208         ConvertToUnicode(CP_UTF8, 0, spn, -1, &nla->ServicePrincipalName, 0);
209         free(spn);
210 #else
211         nla->ServicePrincipalName = spn;
212 #endif
213
214         nla->table = InitSecurityInterfaceEx(SSPI_INTERFACE_WINPR);
215         nla->status = nla->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &nla->pPackageInfo);
216
217         if (nla->status != SEC_E_OK)
218         {
219                 WLog_ERR(TAG, "QuerySecurityPackageInfo status: 0x%08X", nla->status);
220                 return -1;
221         }
222
223         nla->cbMaxToken = nla->pPackageInfo->cbMaxToken;
224         nla->status = nla->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME,
225                          SECPKG_CRED_OUTBOUND, NULL, &nla->identity, NULL, NULL, &nla->credentials, &nla->expiration);
226
227         if (nla->status != SEC_E_OK)
228         {
229                 WLog_ERR(TAG, "AcquireCredentialsHandle status: 0x%08X", nla->status);
230                 return -1;
231         }
232
233         nla->haveContext = FALSE;
234         nla->haveInputBuffer = FALSE;
235         nla->havePubKeyAuth = FALSE;
236         ZeroMemory(&nla->inputBuffer, sizeof(SecBuffer));
237         ZeroMemory(&nla->outputBuffer, sizeof(SecBuffer));
238         ZeroMemory(&nla->ContextSizes, sizeof(SecPkgContext_Sizes));
239
240         /*
241          * from tspkg.dll: 0x00000132
242          * ISC_REQ_MUTUAL_AUTH
243          * ISC_REQ_CONFIDENTIALITY
244          * ISC_REQ_USE_SESSION_KEY
245          * ISC_REQ_ALLOCATE_MEMORY
246          */
247         nla->fContextReq = ISC_REQ_MUTUAL_AUTH | ISC_REQ_CONFIDENTIALITY | ISC_REQ_USE_SESSION_KEY;
248
249         return 1;
250 }
251
252 int nla_client_begin(rdpNla* nla)
253 {
254         if (nla_client_init(nla) < 1)
255                 return -1;
256
257         if (nla->state != NLA_STATE_INITIAL)
258                 return -1;
259
260         nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
261         nla->outputBufferDesc.cBuffers = 1;
262         nla->outputBufferDesc.pBuffers = &nla->outputBuffer;
263         nla->outputBuffer.BufferType = SECBUFFER_TOKEN;
264         nla->outputBuffer.cbBuffer = nla->cbMaxToken;
265         nla->outputBuffer.pvBuffer = malloc(nla->outputBuffer.cbBuffer);
266
267         if (!nla->outputBuffer.pvBuffer)
268                 return -1;
269
270         nla->status = nla->table->InitializeSecurityContext(&nla->credentials,
271                         NULL, nla->ServicePrincipalName, nla->fContextReq, 0,
272                         SECURITY_NATIVE_DREP, NULL, 0, &nla->context,
273                         &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);
274
275         if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
276         {
277                 if (nla->table->CompleteAuthToken)
278                         nla->table->CompleteAuthToken(&nla->context, &nla->outputBufferDesc);
279
280                 if (nla->status == SEC_I_COMPLETE_NEEDED)
281                         nla->status = SEC_E_OK;
282                 else if (nla->status == SEC_I_COMPLETE_AND_CONTINUE)
283                         nla->status = SEC_I_CONTINUE_NEEDED;
284         }
285
286         if (nla->status != SEC_I_CONTINUE_NEEDED)
287                 return -1;
288
289         if (nla->outputBuffer.cbBuffer < 1)
290                 return -1;
291
292         nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
293         nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;
294
295         WLog_DBG(TAG, "Sending Authentication Token");
296         winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer);
297
298         if (!nla_send(nla))
299         {
300                 nla_buffer_free(nla);
301                 return -1;
302         }
303
304         nla_buffer_free(nla);
305
306         nla->state = NLA_STATE_NEGO_TOKEN;
307
308         return 1;
309 }
310
311 int nla_client_recv(rdpNla* nla)
312 {
313         int status = -1;
314
315         if (nla->state == NLA_STATE_NEGO_TOKEN)
316         {
317                 nla->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
318                 nla->inputBufferDesc.cBuffers = 1;
319                 nla->inputBufferDesc.pBuffers = &nla->inputBuffer;
320                 nla->inputBuffer.BufferType = SECBUFFER_TOKEN;
321                 nla->inputBuffer.pvBuffer = nla->negoToken.pvBuffer;
322                 nla->inputBuffer.cbBuffer = nla->negoToken.cbBuffer;
323
324                 nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
325                 nla->outputBufferDesc.cBuffers = 1;
326                 nla->outputBufferDesc.pBuffers = &nla->outputBuffer;
327                 nla->outputBuffer.BufferType = SECBUFFER_TOKEN;
328                 nla->outputBuffer.cbBuffer = nla->cbMaxToken;
329                 nla->outputBuffer.pvBuffer = malloc(nla->outputBuffer.cbBuffer);
330
331                 if (!nla->outputBuffer.pvBuffer)
332                         return -1;
333
334                 nla->status = nla->table->InitializeSecurityContext(&nla->credentials,
335                                 &nla->context, nla->ServicePrincipalName, nla->fContextReq, 0,
336                                 SECURITY_NATIVE_DREP, &nla->inputBufferDesc,
337                                 0, &nla->context, &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);
338
339                 free(nla->inputBuffer.pvBuffer);
340                 nla->inputBuffer.pvBuffer = NULL;
341
342                 if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
343                 {
344                         if (nla->table->CompleteAuthToken)
345                                 nla->table->CompleteAuthToken(&nla->context, &nla->outputBufferDesc);
346
347                         if (nla->status == SEC_I_COMPLETE_NEEDED)
348                                 nla->status = SEC_E_OK;
349                         else if (nla->status == SEC_I_COMPLETE_AND_CONTINUE)
350                                 nla->status = SEC_I_CONTINUE_NEEDED;
351                 }
352
353                 if (nla->status == SEC_E_OK)
354                 {
355                         nla->havePubKeyAuth = TRUE;
356
357                         if (nla->table->QueryContextAttributes(&nla->context, SECPKG_ATTR_SIZES, &nla->ContextSizes) != SEC_E_OK)
358                         {
359                                 WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES failure");
360                                 return -1;
361                         }
362
363                         nla_encrypt_public_key_echo(nla);
364                 }
365
366                 if (nla->outputBuffer.cbBuffer < 1)
367                         return -1;
368
369                 nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
370                 nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;
371
372                 WLog_DBG(TAG, "Sending Authentication Token");
373                 winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer);
374
375                 if (!nla_send(nla))
376                 {
377                         nla_buffer_free(nla);
378                         return -1;
379                 }
380                 nla_buffer_free(nla);
381
382                 nla->state = NLA_STATE_PUB_KEY_AUTH;
383                 status = 1;
384         }
385         else if (nla->state == NLA_STATE_PUB_KEY_AUTH)
386         {
387                 /* Verify Server Public Key Echo */
388                 nla->status = nla_decrypt_public_key_echo(nla);
389                 nla_buffer_free(nla);
390
391                 if (nla->status != SEC_E_OK)
392                 {
393                         WLog_ERR(TAG, "Could not verify public key echo!");
394                         return -1;
395                 }
396
397                 /* Send encrypted credentials */
398                 nla->status = nla_encrypt_ts_credentials(nla);
399
400                 if (nla->status != SEC_E_OK)
401                 {
402                         WLog_ERR(TAG, "nla_encrypt_ts_credentials status: 0x%08X", nla->status);
403                         return -1;
404                 }
405
406                 if (!nla_send(nla))
407                 {
408                         nla_buffer_free(nla);
409                         return -1;
410                 }
411                 nla_buffer_free(nla);
412
413                 nla->table->FreeCredentialsHandle(&nla->credentials);
414                 nla->table->FreeContextBuffer(nla->pPackageInfo);
415
416                 nla->state = NLA_STATE_AUTH_INFO;
417                 status = 1;
418         }
419
420         return status;
421 }
422
423 int nla_client_authenticate(rdpNla* nla)
424 {
425         wStream* s;
426         int status;
427
428         s = Stream_New(NULL, 4096);
429
430         if (!s)
431         {
432                 WLog_ERR(TAG, "Stream_New failed!");
433                 return -1;
434         }
435
436         if (nla_client_begin(nla) < 1)
437                 return -1;
438
439         while (nla->state < NLA_STATE_AUTH_INFO)
440         {
441                 Stream_SetPosition(s, 0);
442
443                 status = transport_read_pdu(nla->transport, s);
444
445                 if (status < 0)
446                 {
447                         WLog_ERR(TAG, "nla_client_authenticate failure");
448                         Stream_Free(s, TRUE);
449                         return -1;
450                 }
451
452                 status = nla_recv_pdu(nla, s);
453
454                 if (status < 0)
455                         return -1;
456         }
457
458         Stream_Free(s, TRUE);
459
460         return 1;
461 }
462
463 /**
464  * Initialize NTLMSSP authentication module (server).
465  * @param credssp
466  */
467
468 int nla_server_init(rdpNla* nla)
469 {
470         rdpTls* tls = nla->transport->tls;
471
472         if (!sspi_SecBufferAlloc(&nla->PublicKey, tls->PublicKeyLength))
473         {
474                 WLog_ERR(TAG, "Failed to allocate SecBuffer for public key");
475                 return -1;
476         }
477         CopyMemory(nla->PublicKey.pvBuffer, tls->PublicKey, tls->PublicKeyLength);
478
479         if (nla->SspiModule)
480         {
481                 HMODULE hSSPI;
482                 INIT_SECURITY_INTERFACE pInitSecurityInterface;
483
484                 hSSPI = LoadLibrary(nla->SspiModule);
485
486                 if (!hSSPI)
487                 {
488                         WLog_ERR(TAG, "Failed to load SSPI module: %s", nla->SspiModule);
489                         return -1;
490                 }
491
492 #ifdef UNICODE
493                 pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceW");
494 #else
495                 pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceA");
496 #endif
497                 nla->table = pInitSecurityInterface();
498         }
499         else
500         {
501                 nla->table = InitSecurityInterfaceEx(0);
502         }
503
504         nla->status = nla->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &nla->pPackageInfo);
505
506         if (nla->status != SEC_E_OK)
507         {
508                 WLog_ERR(TAG, "QuerySecurityPackageInfo status: 0x%08X", nla->status);
509                 return -1;
510         }
511
512         nla->cbMaxToken = nla->pPackageInfo->cbMaxToken;
513         nla->status = nla->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME,
514                          SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &nla->credentials, &nla->expiration);
515
516         if (nla->status != SEC_E_OK)
517         {
518                 WLog_ERR(TAG, "AcquireCredentialsHandle status: 0x%08X", nla->status);
519                 return -1;
520         }
521
522         nla->haveContext = FALSE;
523         nla->haveInputBuffer = FALSE;
524         nla->havePubKeyAuth = FALSE;
525         ZeroMemory(&nla->inputBuffer, sizeof(SecBuffer));
526         ZeroMemory(&nla->outputBuffer, sizeof(SecBuffer));
527         ZeroMemory(&nla->inputBufferDesc, sizeof(SecBufferDesc));
528         ZeroMemory(&nla->outputBufferDesc, sizeof(SecBufferDesc));
529         ZeroMemory(&nla->ContextSizes, sizeof(SecPkgContext_Sizes));
530
531         /*
532          * from tspkg.dll: 0x00000112
533          * ASC_REQ_MUTUAL_AUTH
534          * ASC_REQ_CONFIDENTIALITY
535          * ASC_REQ_ALLOCATE_MEMORY
536          */
537         nla->fContextReq = 0;
538         nla->fContextReq |= ASC_REQ_MUTUAL_AUTH;
539         nla->fContextReq |= ASC_REQ_CONFIDENTIALITY;
540         nla->fContextReq |= ASC_REQ_CONNECTION;
541         nla->fContextReq |= ASC_REQ_USE_SESSION_KEY;
542         nla->fContextReq |= ASC_REQ_REPLAY_DETECT;
543         nla->fContextReq |= ASC_REQ_SEQUENCE_DETECT;
544         nla->fContextReq |= ASC_REQ_EXTENDED_ERROR;
545
546         return 1;
547 }
548
549 /**
550  * Authenticate with client using CredSSP (server).
551  * @param credssp
552  * @return 1 if authentication is successful
553  */
554
555 int nla_server_authenticate(rdpNla* nla)
556 {
557         if (nla_server_init(nla) < 1)
558                 return -1;
559
560         while (TRUE)
561         {
562                 /* receive authentication token */
563                 nla->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
564                 nla->inputBufferDesc.cBuffers = 1;
565                 nla->inputBufferDesc.pBuffers = &nla->inputBuffer;
566                 nla->inputBuffer.BufferType = SECBUFFER_TOKEN;
567
568                 if (nla_recv(nla) < 0)
569                         return -1;
570
571                 WLog_DBG(TAG, "Receiving Authentication Token");
572                 nla_buffer_print(nla);
573
574                 nla->inputBuffer.pvBuffer = nla->negoToken.pvBuffer;
575                 nla->inputBuffer.cbBuffer = nla->negoToken.cbBuffer;
576
577                 if (nla->negoToken.cbBuffer < 1)
578                 {
579                         WLog_ERR(TAG, "CredSSP: invalid negoToken!");
580                         return -1;
581                 }
582
583                 nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
584                 nla->outputBufferDesc.cBuffers = 1;
585                 nla->outputBufferDesc.pBuffers = &nla->outputBuffer;
586                 nla->outputBuffer.BufferType = SECBUFFER_TOKEN;
587                 nla->outputBuffer.cbBuffer = nla->cbMaxToken;
588                 nla->outputBuffer.pvBuffer = malloc(nla->outputBuffer.cbBuffer);
589
590                 if (!nla->outputBuffer.pvBuffer)
591                         return -1;
592
593                 nla->status = nla->table->AcceptSecurityContext(&nla->credentials,
594                                 nla-> haveContext? &nla->context: NULL,
595                                  &nla->inputBufferDesc, nla->fContextReq, SECURITY_NATIVE_DREP, &nla->context,
596                                  &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);
597
598                 nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
599                 nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;
600
601                 if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
602                 {
603                         if (nla->table->CompleteAuthToken)
604                                 nla->table->CompleteAuthToken(&nla->context, &nla->outputBufferDesc);
605
606                         if (nla->status == SEC_I_COMPLETE_NEEDED)
607                                 nla->status = SEC_E_OK;
608                         else if (nla->status == SEC_I_COMPLETE_AND_CONTINUE)
609                                 nla->status = SEC_I_CONTINUE_NEEDED;
610                 }
611
612                 if (nla->status == SEC_E_OK)
613                 {
614                         nla->havePubKeyAuth = TRUE;
615
616                         if (nla->table->QueryContextAttributes(&nla->context, SECPKG_ATTR_SIZES, &nla->ContextSizes) != SEC_E_OK)
617                         {
618                                 WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES failure");
619                                 return -1;
620                         }
621
622                         if (nla_decrypt_public_key_echo(nla) != SEC_E_OK)
623                         {
624                                 WLog_ERR(TAG, "Error: could not verify client's public key echo");
625                                 return -1;
626                         }
627
628                         sspi_SecBufferFree(&nla->negoToken);
629                         nla->negoToken.pvBuffer = NULL;
630                         nla->negoToken.cbBuffer = 0;
631                         nla_encrypt_public_key_echo(nla);
632                 }
633
634                 if ((nla->status != SEC_E_OK) && (nla->status != SEC_I_CONTINUE_NEEDED))
635                 {
636                         WLog_ERR(TAG, "AcceptSecurityContext status: 0x%08X", nla->status);
637                         return -1; /* Access Denied */
638                 }
639
640                 /* send authentication token */
641
642                 WLog_DBG(TAG, "Sending Authentication Token");
643                 nla_buffer_print(nla);
644
645                 if (!nla_send(nla))
646                 {
647                         nla_buffer_free(nla);
648                         return -1;
649                 }
650                 nla_buffer_free(nla);
651
652                 if (nla->status != SEC_I_CONTINUE_NEEDED)
653                         break;
654
655                 nla->haveContext = TRUE;
656         }
657
658         /* Receive encrypted credentials */
659
660         if (nla_recv(nla) < 0)
661                 return -1;
662
663         if (nla_decrypt_ts_credentials(nla) != SEC_E_OK)
664         {
665                 WLog_ERR(TAG, "Could not decrypt TSCredentials status: 0x%08X", nla->status);
666                 return -1;
667         }
668
669         if (nla->status != SEC_E_OK)
670         {
671                 WLog_ERR(TAG, "AcceptSecurityContext status: 0x%08X", nla->status);
672                 return -1;
673         }
674
675         nla->status = nla->table->ImpersonateSecurityContext(&nla->context);
676
677         if (nla->status != SEC_E_OK)
678         {
679                 WLog_ERR(TAG, "ImpersonateSecurityContext status: 0x%08X", nla->status);
680                 return -1;
681         }
682         else
683         {
684                 nla->status = nla->table->RevertSecurityContext(&nla->context);
685
686                 if (nla->status != SEC_E_OK)
687                 {
688                         WLog_ERR(TAG, "RevertSecurityContext status: 0x%08X", nla->status);
689                         return -1;
690                 }
691         }
692
693         nla->table->FreeContextBuffer(nla->pPackageInfo);
694
695         return 1;
696 }
697
698 /**
699  * Authenticate using CredSSP.
700  * @param credssp
701  * @return 1 if authentication is successful
702  */
703
704 int nla_authenticate(rdpNla* nla)
705 {
706         if (nla->server)
707                 return nla_server_authenticate(nla);
708         else
709                 return nla_client_authenticate(nla);
710 }
711
712 void ap_integer_increment_le(BYTE* number, int size)
713 {
714         int index;
715
716         for (index = 0; index < size; index++)
717         {
718                 if (number[index] < 0xFF)
719                 {
720                         number[index]++;
721                         break;
722                 }
723                 else
724                 {
725                         number[index] = 0;
726                         continue;
727                 }
728         }
729 }
730
731 void ap_integer_decrement_le(BYTE* number, int size)
732 {
733         int index;
734
735         for (index = 0; index < size; index++)
736         {
737                 if (number[index] > 0)
738                 {
739                         number[index]--;
740                         break;
741                 }
742                 else
743                 {
744                         number[index] = 0xFF;
745                         continue;
746                 }
747         }
748 }
749
750 SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla)
751 {
752         SecBuffer Buffers[2];
753         SecBufferDesc Message;
754         SECURITY_STATUS status;
755         int public_key_length;
756
757         public_key_length = nla->PublicKey.cbBuffer;
758         if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, nla->ContextSizes.cbMaxSignature + public_key_length))
759                 return SEC_E_INSUFFICIENT_MEMORY;
760         Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
761         Buffers[1].BufferType = SECBUFFER_DATA; /* TLS Public Key */
762         Buffers[0].cbBuffer = nla->ContextSizes.cbMaxSignature;
763         Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer;
764         Buffers[1].cbBuffer = public_key_length;
765         Buffers[1].pvBuffer = ((BYTE*) nla->pubKeyAuth.pvBuffer) + nla->ContextSizes.cbMaxSignature;
766         CopyMemory(Buffers[1].pvBuffer, nla->PublicKey.pvBuffer, Buffers[1].cbBuffer);
767
768         if (nla->server)
769         {
770                 /* server echos the public key +1 */
771                 ap_integer_increment_le((BYTE*) Buffers[1].pvBuffer, Buffers[1].cbBuffer);
772         }
773
774         Message.cBuffers = 2;
775         Message.ulVersion = SECBUFFER_VERSION;
776         Message.pBuffers = (PSecBuffer) &Buffers;
777         status = nla->table->EncryptMessage(&nla->context, 0, &Message, nla->sendSeqNum++);
778
779         if (status != SEC_E_OK)
780         {
781                 WLog_ERR(TAG, "EncryptMessage status: 0x%08X", status);
782                 return status;
783         }
784
785         return status;
786 }
787
788 SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla)
789 {
790         int length;
791         BYTE* buffer;
792         ULONG pfQOP = 0;
793         BYTE* public_key1;
794         BYTE* public_key2;
795         int public_key_length;
796         SecBuffer Buffers[2];
797         SecBufferDesc Message;
798         SECURITY_STATUS status;
799
800         if ((nla->PublicKey.cbBuffer + nla->ContextSizes.cbMaxSignature) != nla->pubKeyAuth.cbBuffer)
801         {
802                 WLog_ERR(TAG, "unexpected pubKeyAuth buffer size: %d", (int) nla->pubKeyAuth.cbBuffer);
803                 return SEC_E_INVALID_TOKEN;
804         }
805
806         length = nla->pubKeyAuth.cbBuffer;
807         buffer = (BYTE*) malloc(length);
808
809         if (!buffer)
810                 return SEC_E_INSUFFICIENT_MEMORY;
811
812         CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length);
813         public_key_length = nla->PublicKey.cbBuffer;
814         Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
815         Buffers[1].BufferType = SECBUFFER_DATA; /* Encrypted TLS Public Key */
816         Buffers[0].cbBuffer = nla->ContextSizes.cbMaxSignature;
817         Buffers[0].pvBuffer = buffer;
818         Buffers[1].cbBuffer = length - nla->ContextSizes.cbMaxSignature;
819         Buffers[1].pvBuffer = buffer + nla->ContextSizes.cbMaxSignature;
820         Message.cBuffers = 2;
821         Message.ulVersion = SECBUFFER_VERSION;
822         Message.pBuffers = (PSecBuffer) &Buffers;
823         status = nla->table->DecryptMessage(&nla->context, &Message, nla->recvSeqNum++, &pfQOP);
824
825         if (status != SEC_E_OK)
826         {
827                 WLog_ERR(TAG, "DecryptMessage failure: 0x%08X", status);
828                 return status;
829         }
830
831         public_key1 = (BYTE*) nla->PublicKey.pvBuffer;
832         public_key2 = (BYTE*) Buffers[1].pvBuffer;
833
834         if (!nla->server)
835         {
836                 /* server echos the public key +1 */
837                 ap_integer_decrement_le(public_key2, public_key_length);
838         }
839
840         if (memcmp(public_key1, public_key2, public_key_length) != 0)
841         {
842                 WLog_ERR(TAG, "Could not verify server's public key echo");
843                 WLog_ERR(TAG, "Expected (length = %d):", public_key_length);
844                 winpr_HexDump(TAG, WLOG_ERROR, public_key1, public_key_length);
845                 WLog_ERR(TAG, "Actual (length = %d):", public_key_length);
846                 winpr_HexDump(TAG, WLOG_ERROR, public_key2, public_key_length);
847                 return SEC_E_MESSAGE_ALTERED; /* DO NOT SEND CREDENTIALS! */
848         }
849
850         free(buffer);
851         return SEC_E_OK;
852 }
853
854 int nla_sizeof_ts_password_creds(rdpNla* nla)
855 {
856         int length = 0;
857         length += ber_sizeof_sequence_octet_string(nla->identity.DomainLength * 2);
858         length += ber_sizeof_sequence_octet_string(nla->identity.UserLength * 2);
859         length += ber_sizeof_sequence_octet_string(nla->identity.PasswordLength * 2);
860         return length;
861 }
862
863 void nla_read_ts_password_creds(rdpNla* nla, wStream* s)
864 {
865         int length;
866
867         /* TSPasswordCreds (SEQUENCE) */
868         ber_read_sequence_tag(s, &length);
869
870         /* [0] domainName (OCTET STRING) */
871         ber_read_contextual_tag(s, 0, &length, TRUE);
872         ber_read_octet_string_tag(s, &length);
873         nla->identity.DomainLength = (UINT32) length;
874         nla->identity.Domain = (UINT16*) malloc(length);
875         CopyMemory(nla->identity.Domain, Stream_Pointer(s), nla->identity.DomainLength);
876         Stream_Seek(s, nla->identity.DomainLength);
877         nla->identity.DomainLength /= 2;
878
879         /* [1] userName (OCTET STRING) */
880         ber_read_contextual_tag(s, 1, &length, TRUE);
881         ber_read_octet_string_tag(s, &length);
882         nla->identity.UserLength = (UINT32) length;
883         nla->identity.User = (UINT16*) malloc(length);
884         CopyMemory(nla->identity.User, Stream_Pointer(s), nla->identity.UserLength);
885         Stream_Seek(s, nla->identity.UserLength);
886         nla->identity.UserLength /= 2;
887
888         /* [2] password (OCTET STRING) */
889         ber_read_contextual_tag(s, 2, &length, TRUE);
890         ber_read_octet_string_tag(s, &length);
891         nla->identity.PasswordLength = (UINT32) length;
892         nla->identity.Password = (UINT16*) malloc(length);
893         CopyMemory(nla->identity.Password, Stream_Pointer(s), nla->identity.PasswordLength);
894         Stream_Seek(s, nla->identity.PasswordLength);
895         nla->identity.PasswordLength /= 2;
896         nla->identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
897 }
898
899 int nla_write_ts_password_creds(rdpNla* nla, wStream* s)
900 {
901         int size = 0;
902         int innerSize = nla_sizeof_ts_password_creds(nla);
903         /* TSPasswordCreds (SEQUENCE) */
904         size += ber_write_sequence_tag(s, innerSize);
905         /* [0] domainName (OCTET STRING) */
906         size += ber_write_sequence_octet_string(s, 0, (BYTE*) nla->identity.Domain, nla->identity.DomainLength * 2);
907         /* [1] userName (OCTET STRING) */
908         size += ber_write_sequence_octet_string(s, 1, (BYTE*) nla->identity.User, nla->identity.UserLength * 2);
909         /* [2] password (OCTET STRING) */
910         size += ber_write_sequence_octet_string(s, 2, (BYTE*) nla->identity.Password, nla->identity.PasswordLength * 2);
911         return size;
912 }
913
914 int nla_sizeof_ts_credentials(rdpNla* nla)
915 {
916         int size = 0;
917         size += ber_sizeof_integer(1);
918         size += ber_sizeof_contextual_tag(ber_sizeof_integer(1));
919         size += ber_sizeof_sequence_octet_string(ber_sizeof_sequence(nla_sizeof_ts_password_creds(nla)));
920         return size;
921 }
922
923 BOOL nla_read_ts_credentials(rdpNla* nla, PSecBuffer ts_credentials)
924 {
925         wStream* s;
926         int length;
927         int ts_password_creds_length;
928
929         s = Stream_New(ts_credentials->pvBuffer, ts_credentials->cbBuffer);
930
931         if (!s)
932         {
933                 WLog_ERR(TAG, "Stream_New failed!");
934                 return FALSE;
935         }
936
937
938         /* TSCredentials (SEQUENCE) */
939         ber_read_sequence_tag(s, &length);
940
941         /* [0] credType (INTEGER) */
942         ber_read_contextual_tag(s, 0, &length, TRUE);
943         ber_read_integer(s, NULL);
944
945         /* [1] credentials (OCTET STRING) */
946         ber_read_contextual_tag(s, 1, &length, TRUE);
947         ber_read_octet_string_tag(s, &ts_password_creds_length);
948
949         nla_read_ts_password_creds(nla, s);
950
951         Stream_Free(s, FALSE);
952         return TRUE;
953 }
954
955 int nla_write_ts_credentials(rdpNla* nla, wStream* s)
956 {
957         int size = 0;
958         int passwordSize;
959         int innerSize = nla_sizeof_ts_credentials(nla);
960
961         /* TSCredentials (SEQUENCE) */
962         size += ber_write_sequence_tag(s, innerSize);
963
964         /* [0] credType (INTEGER) */
965         size += ber_write_contextual_tag(s, 0, ber_sizeof_integer(1), TRUE);
966         size += ber_write_integer(s, 1);
967
968         /* [1] credentials (OCTET STRING) */
969         passwordSize = ber_sizeof_sequence(nla_sizeof_ts_password_creds(nla));
970         size += ber_write_contextual_tag(s, 1, ber_sizeof_octet_string(passwordSize), TRUE);
971         size += ber_write_octet_string_tag(s, passwordSize);
972         size += nla_write_ts_password_creds(nla, s);
973
974         return size;
975 }
976
977 /**
978  * Encode TSCredentials structure.
979  * @param credssp
980  */
981
982 BOOL nla_encode_ts_credentials(rdpNla* nla)
983 {
984         wStream* s;
985         int length;
986         int DomainLength;
987         int UserLength;
988         int PasswordLength;
989
990         DomainLength = nla->identity.DomainLength;
991         UserLength = nla->identity.UserLength;
992         PasswordLength = nla->identity.PasswordLength;
993
994         if (nla->settings->DisableCredentialsDelegation)
995         {
996                 nla->identity.DomainLength = 0;
997                 nla->identity.UserLength = 0;
998                 nla->identity.PasswordLength = 0;
999         }
1000
1001         length = ber_sizeof_sequence(nla_sizeof_ts_credentials(nla));
1002         if (!sspi_SecBufferAlloc(&nla->tsCredentials, length))
1003         {
1004                 WLog_ERR(TAG, "sspi_SecBufferAlloc failed!");
1005                 return FALSE;
1006         }
1007         s = Stream_New((BYTE*) nla->tsCredentials.pvBuffer, length);
1008
1009         if (!s)
1010         {
1011                 sspi_SecBufferFree(&nla->tsCredentials);
1012                 WLog_ERR(TAG, "Stream_New failed!");
1013                 return FALSE;
1014         }
1015
1016         nla_write_ts_credentials(nla, s);
1017
1018         if (nla->settings->DisableCredentialsDelegation)
1019         {
1020                 nla->identity.DomainLength = DomainLength;
1021                 nla->identity.UserLength = UserLength;
1022                 nla->identity.PasswordLength = PasswordLength;
1023         }
1024
1025         Stream_Free(s, FALSE);
1026         return TRUE;
1027 }
1028
1029 SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla)
1030 {
1031         SecBuffer Buffers[2];
1032         SecBufferDesc Message;
1033         SECURITY_STATUS status;
1034
1035         if (!nla_encode_ts_credentials(nla))
1036                 return SEC_E_INSUFFICIENT_MEMORY;
1037
1038         if (!sspi_SecBufferAlloc(&nla->authInfo, nla->ContextSizes.cbMaxSignature + nla->tsCredentials.cbBuffer))
1039                 return SEC_E_INSUFFICIENT_MEMORY;
1040         Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
1041         Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
1042         Buffers[0].cbBuffer = nla->ContextSizes.cbMaxSignature;
1043         Buffers[0].pvBuffer = nla->authInfo.pvBuffer;
1044         ZeroMemory(Buffers[0].pvBuffer, Buffers[0].cbBuffer);
1045         Buffers[1].cbBuffer = nla->tsCredentials.cbBuffer;
1046         Buffers[1].pvBuffer = &((BYTE*) nla->authInfo.pvBuffer)[Buffers[0].cbBuffer];
1047         CopyMemory(Buffers[1].pvBuffer, nla->tsCredentials.pvBuffer, Buffers[1].cbBuffer);
1048
1049         Message.cBuffers = 2;
1050         Message.ulVersion = SECBUFFER_VERSION;
1051         Message.pBuffers = (PSecBuffer) &Buffers;
1052
1053         status = nla->table->EncryptMessage(&nla->context, 0, &Message, nla->sendSeqNum++);
1054
1055         if (status != SEC_E_OK)
1056                 return status;
1057
1058         return SEC_E_OK;
1059 }
1060
1061 SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla)
1062 {
1063         int length;
1064         BYTE* buffer;
1065         ULONG pfQOP;
1066         SecBuffer Buffers[2];
1067         SecBufferDesc Message;
1068         SECURITY_STATUS status;
1069         Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
1070         Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
1071
1072         if (nla->authInfo.cbBuffer < 1)
1073         {
1074                 WLog_ERR(TAG, "nla_decrypt_ts_credentials missing authInfo buffer");
1075                 return SEC_E_INVALID_TOKEN;
1076         }
1077
1078         length = nla->authInfo.cbBuffer;
1079         buffer = (BYTE*) malloc(length);
1080
1081         if (!buffer)
1082                 return SEC_E_INSUFFICIENT_MEMORY;
1083
1084         CopyMemory(buffer, nla->authInfo.pvBuffer, length);
1085         Buffers[0].cbBuffer = nla->ContextSizes.cbMaxSignature;
1086         Buffers[0].pvBuffer = buffer;
1087         Buffers[1].cbBuffer = length - nla->ContextSizes.cbMaxSignature;
1088         Buffers[1].pvBuffer = &buffer[nla->ContextSizes.cbMaxSignature];
1089         Message.cBuffers = 2;
1090         Message.ulVersion = SECBUFFER_VERSION;
1091         Message.pBuffers = (PSecBuffer) &Buffers;
1092         status = nla->table->DecryptMessage(&nla->context, &Message, nla->recvSeqNum++, &pfQOP);
1093
1094         if (status != SEC_E_OK)
1095                 return status;
1096
1097         if(!nla_read_ts_credentials(nla, &Buffers[1]))
1098         {
1099                 free(buffer);
1100                 return SEC_E_INSUFFICIENT_MEMORY;
1101         }
1102         free(buffer);
1103
1104         return SEC_E_OK;
1105 }
1106
1107 int nla_sizeof_nego_token(int length)
1108 {
1109         length = ber_sizeof_octet_string(length);
1110         length += ber_sizeof_contextual_tag(length);
1111         return length;
1112 }
1113
1114 int nla_sizeof_nego_tokens(int length)
1115 {
1116         length = nla_sizeof_nego_token(length);
1117         length += ber_sizeof_sequence_tag(length);
1118         length += ber_sizeof_sequence_tag(length);
1119         length += ber_sizeof_contextual_tag(length);
1120         return length;
1121 }
1122
1123 int nla_sizeof_pub_key_auth(int length)
1124 {
1125         length = ber_sizeof_octet_string(length);
1126         length += ber_sizeof_contextual_tag(length);
1127         return length;
1128 }
1129
1130 int nla_sizeof_auth_info(int length)
1131 {
1132         length = ber_sizeof_octet_string(length);
1133         length += ber_sizeof_contextual_tag(length);
1134         return length;
1135 }
1136
1137 int nla_sizeof_ts_request(int length)
1138 {
1139         length += ber_sizeof_integer(2);
1140         length += ber_sizeof_contextual_tag(3);
1141         return length;
1142 }
1143
1144 /**
1145  * Send CredSSP message.
1146  * @param credssp
1147  */
1148
1149 BOOL nla_send(rdpNla* nla)
1150 {
1151         wStream* s;
1152         int length;
1153         int ts_request_length;
1154         int nego_tokens_length;
1155         int pub_key_auth_length;
1156         int auth_info_length;
1157
1158         nego_tokens_length = (nla->negoToken.cbBuffer > 0) ? nla_sizeof_nego_tokens(nla->negoToken.cbBuffer) : 0;
1159         pub_key_auth_length = (nla->pubKeyAuth.cbBuffer > 0) ? nla_sizeof_pub_key_auth(nla->pubKeyAuth.cbBuffer) : 0;
1160         auth_info_length = (nla->authInfo.cbBuffer > 0) ? nla_sizeof_auth_info(nla->authInfo.cbBuffer) : 0;
1161         length = nego_tokens_length + pub_key_auth_length + auth_info_length;
1162         ts_request_length = nla_sizeof_ts_request(length);
1163
1164         s = Stream_New(NULL, ber_sizeof_sequence(ts_request_length));
1165
1166         if (!s)
1167         {
1168                 WLog_ERR(TAG, "Stream_New failed!");
1169                 return FALSE;
1170         }
1171
1172
1173         /* TSRequest */
1174         ber_write_sequence_tag(s, ts_request_length); /* SEQUENCE */
1175         /* [0] version */
1176         ber_write_contextual_tag(s, 0, 3, TRUE);
1177         ber_write_integer(s, 2); /* INTEGER */
1178
1179         /* [1] negoTokens (NegoData) */
1180         if (nego_tokens_length > 0)
1181         {
1182                 length = nego_tokens_length;
1183                 length -= ber_write_contextual_tag(s, 1, ber_sizeof_sequence(ber_sizeof_sequence(ber_sizeof_sequence_octet_string(nla->negoToken.cbBuffer))), TRUE); /* NegoData */
1184                 length -= ber_write_sequence_tag(s, ber_sizeof_sequence(ber_sizeof_sequence_octet_string(nla->negoToken.cbBuffer))); /* SEQUENCE OF NegoDataItem */
1185                 length -= ber_write_sequence_tag(s, ber_sizeof_sequence_octet_string(nla->negoToken.cbBuffer)); /* NegoDataItem */
1186                 length -= ber_write_sequence_octet_string(s, 0, (BYTE*) nla->negoToken.pvBuffer, nla->negoToken.cbBuffer);  /* OCTET STRING */
1187         }
1188
1189         /* [2] authInfo (OCTET STRING) */
1190         if (auth_info_length > 0)
1191         {
1192                 length = auth_info_length;
1193                 length -= ber_write_sequence_octet_string(s, 2, nla->authInfo.pvBuffer, nla->authInfo.cbBuffer);
1194         }
1195
1196         /* [3] pubKeyAuth (OCTET STRING) */
1197         if (pub_key_auth_length > 0)
1198         {
1199                 length = pub_key_auth_length;
1200                 length -= ber_write_sequence_octet_string(s, 3, nla->pubKeyAuth.pvBuffer, nla->pubKeyAuth.cbBuffer);
1201         }
1202
1203         Stream_SealLength(s);
1204         transport_write(nla->transport, s);
1205         Stream_Free(s, TRUE);
1206         return TRUE;
1207 }
1208
1209 int nla_decode_ts_request(rdpNla* nla, wStream* s)
1210 {
1211         int length;
1212         UINT32 version;
1213
1214         /* TSRequest */
1215         if (!ber_read_sequence_tag(s, &length) ||
1216                         !ber_read_contextual_tag(s, 0, &length, TRUE) ||
1217                         !ber_read_integer(s, &version))
1218         {
1219                 Stream_Free(s, TRUE);
1220                 return -1;
1221         }
1222
1223         /* [1] negoTokens (NegoData) */
1224         if (ber_read_contextual_tag(s, 1, &length, TRUE) != FALSE)
1225         {
1226                 if (!ber_read_sequence_tag(s, &length) || /* SEQUENCE OF NegoDataItem */
1227                                 !ber_read_sequence_tag(s, &length) || /* NegoDataItem */
1228                                 !ber_read_contextual_tag(s, 0, &length, TRUE) || /* [0] negoToken */
1229                                 !ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
1230                                 ((int) Stream_GetRemainingLength(s)) < length)
1231                 {
1232                         Stream_Free(s, TRUE);
1233                         return -1;
1234                 }
1235
1236                 if (!sspi_SecBufferAlloc(&nla->negoToken, length))
1237                 {
1238                         Stream_Free(s, TRUE);
1239                         return -1;
1240                 }
1241                 Stream_Read(s, nla->negoToken.pvBuffer, length);
1242                 nla->negoToken.cbBuffer = length;
1243         }
1244
1245         /* [2] authInfo (OCTET STRING) */
1246         if (ber_read_contextual_tag(s, 2, &length, TRUE) != FALSE)
1247         {
1248                 if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
1249                                 ((int) Stream_GetRemainingLength(s)) < length)
1250                 {
1251                         Stream_Free(s, TRUE);
1252                         return -1;
1253                 }
1254
1255                 if (!sspi_SecBufferAlloc(&nla->authInfo, length))
1256                 {
1257                         Stream_Free(s, TRUE);
1258                         return -1;
1259                 }
1260                 Stream_Read(s, nla->authInfo.pvBuffer, length);
1261                 nla->authInfo.cbBuffer = length;
1262         }
1263
1264         /* [3] pubKeyAuth (OCTET STRING) */
1265         if (ber_read_contextual_tag(s, 3, &length, TRUE) != FALSE)
1266         {
1267                 if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
1268                                 ((int) Stream_GetRemainingLength(s)) < length)
1269                 {
1270                         Stream_Free(s, TRUE);
1271                         return -1;
1272                 }
1273
1274                 if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, length))
1275                 {
1276                         Stream_Free(s, TRUE);
1277                         return -1;
1278                 }
1279                 Stream_Read(s, nla->pubKeyAuth.pvBuffer, length);
1280                 nla->pubKeyAuth.cbBuffer = length;
1281         }
1282
1283         return 1;
1284 }
1285
1286 int nla_recv_pdu(rdpNla* nla, wStream* s)
1287 {
1288         if (nla_decode_ts_request(nla, s) < 1)
1289                 return -1;
1290
1291         if (nla_client_recv(nla) < 1)
1292                 return -1;
1293
1294         return 1;
1295 }
1296
1297 int nla_recv(rdpNla* nla)
1298 {
1299         wStream* s;
1300         int status;
1301
1302         s = Stream_New(NULL, 4096);
1303
1304         if (!s)
1305         {
1306                 WLog_ERR(TAG, "Stream_New failed!");
1307                 return -1;
1308         }
1309
1310         status = transport_read_pdu(nla->transport, s);
1311
1312         if (status < 0)
1313         {
1314                 WLog_ERR(TAG, "nla_recv() error: %d", status);
1315                 Stream_Free(s, TRUE);
1316                 return -1;
1317         }
1318
1319         if (nla_decode_ts_request(nla, s) < 1)
1320                 return -1;
1321
1322         Stream_Free(s, TRUE);
1323         return 1;
1324 }
1325
1326 void nla_buffer_print(rdpNla* nla)
1327 {
1328         if (nla->negoToken.cbBuffer > 0)
1329         {
1330                 WLog_DBG(TAG, "NLA.negoToken (length = %d):", (int) nla->negoToken.cbBuffer);
1331                 winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer);
1332         }
1333
1334         if (nla->pubKeyAuth.cbBuffer > 0)
1335         {
1336                 WLog_DBG(TAG, "NLA.pubKeyAuth (length = %d):", (int) nla->pubKeyAuth.cbBuffer);
1337                 winpr_HexDump(TAG, WLOG_DEBUG, nla->pubKeyAuth.pvBuffer, nla->pubKeyAuth.cbBuffer);
1338         }
1339
1340         if (nla->authInfo.cbBuffer > 0)
1341         {
1342                 WLog_DBG(TAG, "NLA.authInfo (length = %d):", (int) nla->authInfo.cbBuffer);
1343                 winpr_HexDump(TAG, WLOG_DEBUG, nla->authInfo.pvBuffer, nla->authInfo.cbBuffer);
1344         }
1345 }
1346
1347 void nla_buffer_free(rdpNla* nla)
1348 {
1349         sspi_SecBufferFree(&nla->negoToken);
1350         sspi_SecBufferFree(&nla->pubKeyAuth);
1351         sspi_SecBufferFree(&nla->authInfo);
1352 }
1353
1354 LPTSTR nla_make_spn(const char* ServiceClass, const char* hostname)
1355 {
1356         DWORD status;
1357         DWORD SpnLength;
1358         LPTSTR hostnameX = NULL;
1359         LPTSTR ServiceClassX = NULL;
1360         LPTSTR ServicePrincipalName = NULL;
1361 #ifdef UNICODE
1362         ConvertToUnicode(CP_UTF8, 0, hostname, -1, &hostnameX, 0);
1363         ConvertToUnicode(CP_UTF8, 0, ServiceClass, -1, &ServiceClassX, 0);
1364 #else
1365         hostnameX = _strdup(hostname);
1366         ServiceClassX = _strdup(ServiceClass);
1367 #endif
1368
1369         if (!ServiceClass)
1370         {
1371                 ServicePrincipalName = (LPTSTR) _tcsdup(hostnameX);
1372                 free(ServiceClassX);
1373                 free(hostnameX);
1374                 return ServicePrincipalName;
1375         }
1376
1377         SpnLength = 0;
1378         status = DsMakeSpn(ServiceClassX, hostnameX, NULL, 0, NULL, &SpnLength, NULL);
1379
1380         if (status != ERROR_BUFFER_OVERFLOW)
1381         {
1382                 free(ServiceClassX);
1383                 free(hostnameX);
1384                 return NULL;
1385         }
1386
1387         ServicePrincipalName = (LPTSTR) malloc(SpnLength * sizeof(TCHAR));
1388
1389         if (!ServicePrincipalName)
1390                 return NULL;
1391
1392         status = DsMakeSpn(ServiceClassX, hostnameX, NULL, 0, NULL, &SpnLength, ServicePrincipalName);
1393
1394         if (status != ERROR_SUCCESS)
1395         {
1396                 free(ServicePrincipalName);
1397                 free(ServiceClassX);
1398                 free(hostnameX);
1399                 return NULL;
1400         }
1401
1402         free(ServiceClassX);
1403         free(hostnameX);
1404         return ServicePrincipalName;
1405 }
1406
1407 /**
1408  * Create new CredSSP state machine.
1409  * @param transport
1410  * @return new CredSSP state machine.
1411  */
1412
1413 rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* settings)
1414 {
1415         rdpNla* nla = (rdpNla*) calloc(1, sizeof(rdpNla));
1416
1417         if (nla)
1418         {
1419                 HKEY hKey;
1420                 LONG status;
1421                 DWORD dwType;
1422                 DWORD dwSize;
1423                 nla->instance = instance;
1424                 nla->settings = settings;
1425                 nla->server = settings->ServerMode;
1426                 nla->transport = transport;
1427                 nla->sendSeqNum = 0;
1428                 nla->recvSeqNum = 0;
1429                 ZeroMemory(&nla->negoToken, sizeof(SecBuffer));
1430                 ZeroMemory(&nla->pubKeyAuth, sizeof(SecBuffer));
1431                 ZeroMemory(&nla->authInfo, sizeof(SecBuffer));
1432                 SecInvalidateHandle(&nla->context);
1433
1434                 if (nla->server)
1435                 {
1436                         status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"),
1437                                                                   0, KEY_READ | KEY_WOW64_64KEY, &hKey);
1438
1439                         if (status == ERROR_SUCCESS)
1440                         {
1441                                 status = RegQueryValueEx(hKey, _T("SspiModule"), NULL, &dwType, NULL, &dwSize);
1442
1443                                 if (status == ERROR_SUCCESS)
1444                                 {
1445                                         nla->SspiModule = (LPTSTR) malloc(dwSize + sizeof(TCHAR));
1446                                         status = RegQueryValueEx(hKey, _T("SspiModule"), NULL, &dwType,
1447                                                                                          (BYTE*) nla->SspiModule, &dwSize);
1448
1449                                         if (status == ERROR_SUCCESS)
1450                                         {
1451                                                 WLog_INFO(TAG, "Using SSPI Module: %s", nla->SspiModule);
1452                                                 RegCloseKey(hKey);
1453                                         }
1454                                 }
1455                         }
1456                 }
1457         }
1458
1459         return nla;
1460 }
1461
1462 /**
1463  * Free CredSSP state machine.
1464  * @param credssp
1465  */
1466
1467 void nla_free(rdpNla* nla)
1468 {
1469         if (!nla)
1470                 return;
1471
1472         if (nla->table)
1473                 nla->table->DeleteSecurityContext(&nla->context);
1474
1475         sspi_SecBufferFree(&nla->PublicKey);
1476         sspi_SecBufferFree(&nla->tsCredentials);
1477
1478         free(nla->ServicePrincipalName);
1479         free(nla->identity.User);
1480         free(nla->identity.Domain);
1481         free(nla->identity.Password);
1482
1483         free(nla);
1484 }