FreeRDP
nla.c
1 
25 #include <freerdp/config.h>
26 
27 #include "settings.h"
28 
29 #include <time.h>
30 #include <ctype.h>
31 
32 #include <freerdp/log.h>
33 #include <freerdp/build-config.h>
34 
35 #include <winpr/crt.h>
36 #include <winpr/assert.h>
37 #include <winpr/sam.h>
38 #include <winpr/sspi.h>
39 #include <winpr/print.h>
40 #include <winpr/tchar.h>
41 #include <winpr/ncrypt.h>
42 #include <winpr/cred.h>
43 #include <winpr/debug.h>
44 #include <winpr/asn1.h>
45 #include <winpr/secapi.h>
46 
47 #include "../crypto/tls.h"
48 #include "nego.h"
49 #include "rdp.h"
50 #include "nla.h"
51 #include "utils.h"
52 #include "credssp_auth.h"
53 #include <freerdp/utils/smartcardlogon.h>
54 
55 #define TAG FREERDP_TAG("core.nla")
56 
57 // #define SERVER_KEY "Software\\" FREERDP_VENDOR_STRING "\\" FREERDP_PRODUCT_STRING "\\Server"
58 
59 #define NLA_AUTH_PKG NEGO_SSP_NAME
60 
61 typedef enum
62 {
63  AUTHZ_SUCCESS = 0x00000000,
64  AUTHZ_ACCESS_DENIED = 0x00000005,
65 } AUTHZ_RESULT;
66 
110 struct rdp_nla
111 {
112  BOOL server;
113  NLA_STATE state;
114  ULONG sendSeqNum;
115  ULONG recvSeqNum;
116  rdpContext* rdpcontext;
117  rdpTransport* transport;
118  UINT32 version;
119  UINT32 peerVersion;
120  UINT32 errorCode;
121 
122  /* Lifetime of buffer nla_new -> nla_free */
123  SecBuffer ClientNonce; /* Depending on protocol version a random nonce or a value read from the
124  server. */
125 
126  SecBuffer negoToken;
127  SecBuffer pubKeyAuth;
128  SecBuffer authInfo;
129  SecBuffer PublicKey;
130  SecBuffer tsCredentials;
131 
132  SEC_WINNT_AUTH_IDENTITY* identity;
133 
134  rdpCredsspAuth* auth;
135  char* pkinitArgs;
136  SmartcardCertInfo* smartcardCert;
137  BYTE certSha1[20];
138  BOOL earlyUserAuth;
139 };
140 
141 static BOOL nla_send(rdpNla* nla);
142 static int nla_server_recv(rdpNla* nla);
143 static BOOL nla_encrypt_public_key_echo(rdpNla* nla);
144 static BOOL nla_encrypt_public_key_hash(rdpNla* nla);
145 static BOOL nla_decrypt_public_key_echo(rdpNla* nla);
146 static BOOL nla_decrypt_public_key_hash(rdpNla* nla);
147 static BOOL nla_encrypt_ts_credentials(rdpNla* nla);
148 static BOOL nla_decrypt_ts_credentials(rdpNla* nla);
149 
150 void nla_set_early_user_auth(rdpNla* nla, BOOL earlyUserAuth)
151 {
152  WINPR_ASSERT(nla);
153  WLog_DBG(TAG, "Early User Auth active: %s", earlyUserAuth ? "true" : "false");
154  nla->earlyUserAuth = earlyUserAuth;
155 }
156 
157 static void nla_buffer_free(rdpNla* nla)
158 {
159  WINPR_ASSERT(nla);
160  sspi_SecBufferFree(&nla->pubKeyAuth);
161  sspi_SecBufferFree(&nla->authInfo);
162  sspi_SecBufferFree(&nla->negoToken);
163  sspi_SecBufferFree(&nla->ClientNonce);
164  sspi_SecBufferFree(&nla->PublicKey);
165 }
166 
167 static BOOL nla_Digest_Update_From_SecBuffer(WINPR_DIGEST_CTX* ctx, const SecBuffer* buffer)
168 {
169  if (!buffer)
170  return FALSE;
171  return winpr_Digest_Update(ctx, buffer->pvBuffer, buffer->cbBuffer);
172 }
173 
174 static BOOL nla_sec_buffer_alloc(SecBuffer* buffer, size_t size)
175 {
176  WINPR_ASSERT(buffer);
177  sspi_SecBufferFree(buffer);
178  if (size > UINT32_MAX)
179  return FALSE;
180  if (!sspi_SecBufferAlloc(buffer, (ULONG)size))
181  return FALSE;
182 
183  WINPR_ASSERT(buffer);
184  buffer->BufferType = SECBUFFER_TOKEN;
185  return TRUE;
186 }
187 
188 static BOOL nla_sec_buffer_alloc_from_data(SecBuffer* buffer, const BYTE* data, size_t offset,
189  size_t size)
190 {
191  if (!nla_sec_buffer_alloc(buffer, offset + size))
192  return FALSE;
193 
194  WINPR_ASSERT(buffer);
195  BYTE* pb = buffer->pvBuffer;
196  memcpy(&pb[offset], data, size);
197  return TRUE;
198 }
199 
200 /* CredSSP Client-To-Server Binding Hash\0 */
201 static const BYTE ClientServerHashMagic[] = { 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20,
202  0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x2D, 0x54,
203  0x6F, 0x2D, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
204  0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67,
205  0x20, 0x48, 0x61, 0x73, 0x68, 0x00 };
206 
207 /* CredSSP Server-To-Client Binding Hash\0 */
208 static const BYTE ServerClientHashMagic[] = { 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20,
209  0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2D, 0x54,
210  0x6F, 0x2D, 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74,
211  0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67,
212  0x20, 0x48, 0x61, 0x73, 0x68, 0x00 };
213 
214 static const UINT32 NonceLength = 32;
215 
216 static BOOL nla_adjust_settings_from_smartcard(rdpNla* nla)
217 {
218  BOOL ret = FALSE;
219 
220  WINPR_ASSERT(nla);
221  WINPR_ASSERT(nla->rdpcontext);
222 
223  rdpSettings* settings = nla->rdpcontext->settings;
224  WINPR_ASSERT(settings);
225 
226  if (!settings->SmartcardLogon)
227  return TRUE;
228 
229  smartcardCertInfo_Free(nla->smartcardCert);
230 
231  if (!smartcard_getCert(nla->rdpcontext, &nla->smartcardCert, FALSE))
232  {
233  WLog_ERR(TAG, "unable to get smartcard certificate for logon");
234  return FALSE;
235  }
236 
237  if (!settings->CspName)
238  {
239  if (nla->smartcardCert->csp && !freerdp_settings_set_string_from_utf16(
240  settings, FreeRDP_CspName, nla->smartcardCert->csp))
241  {
242  WLog_ERR(TAG, "unable to set CSP name");
243  goto out;
244  }
245  if (!settings->CspName &&
246  !freerdp_settings_set_string(settings, FreeRDP_CspName, MS_SCARD_PROV_A))
247  {
248  WLog_ERR(TAG, "unable to set CSP name");
249  goto out;
250  }
251  }
252 
253  if (!settings->ReaderName && nla->smartcardCert->reader)
254  {
255  if (!freerdp_settings_set_string_from_utf16(settings, FreeRDP_ReaderName,
256  nla->smartcardCert->reader))
257  {
258  WLog_ERR(TAG, "unable to copy reader name");
259  goto out;
260  }
261  }
262 
263  if (!settings->ContainerName && nla->smartcardCert->containerName)
264  {
265  if (!freerdp_settings_set_string_from_utf16(settings, FreeRDP_ContainerName,
266  nla->smartcardCert->containerName))
267  {
268  WLog_ERR(TAG, "unable to copy container name");
269  goto out;
270  }
271  }
272 
273  memcpy(nla->certSha1, nla->smartcardCert->sha1Hash, sizeof(nla->certSha1));
274 
275  if (nla->smartcardCert->pkinitArgs)
276  {
277  nla->pkinitArgs = _strdup(nla->smartcardCert->pkinitArgs);
278  if (!nla->pkinitArgs)
279  {
280  WLog_ERR(TAG, "unable to copy pkinitArgs");
281  goto out;
282  }
283  }
284 
285  ret = TRUE;
286 out:
287  return ret;
288 }
289 
290 static BOOL nla_client_setup_identity(rdpNla* nla)
291 {
292  BOOL PromptPassword = FALSE;
293 
294  WINPR_ASSERT(nla);
295  WINPR_ASSERT(nla->rdpcontext);
296 
297  rdpSettings* settings = nla->rdpcontext->settings;
298  WINPR_ASSERT(settings);
299 
300  freerdp* instance = nla->rdpcontext->instance;
301  WINPR_ASSERT(instance);
302 
303  /* */
304  if ((utils_str_is_empty(settings->Username) ||
305  (utils_str_is_empty(settings->Password) &&
306  utils_str_is_empty((const char*)settings->RedirectionPassword))))
307  {
308  PromptPassword = TRUE;
309  }
310 
311  if (PromptPassword && !utils_str_is_empty(settings->Username))
312  {
313  WINPR_SAM* sam = SamOpen(NULL, TRUE);
314  if (sam)
315  {
316  const UINT32 userLength = (UINT32)strnlen(settings->Username, INT32_MAX);
317  WINPR_SAM_ENTRY* entry = SamLookupUserA(
318  sam, settings->Username, userLength + 1 /* ensure '\0' is checked too */, NULL, 0);
319  if (entry)
320  {
325  PromptPassword = FALSE;
326  SamFreeEntry(sam, entry);
327  }
328 
329  SamClose(sam);
330  }
331  }
332 
333  if (PromptPassword)
334  {
335  if (settings->RestrictedAdminModeRequired)
336  {
337  if ((settings->PasswordHash) && (strlen(settings->PasswordHash) > 0))
338  PromptPassword = FALSE;
339  }
340 
341  if (settings->RemoteCredentialGuard)
342  PromptPassword = FALSE;
343  }
344 
345  BOOL smartCardLogonWasDisabled = !settings->SmartcardLogon;
346  if (PromptPassword)
347  {
348  switch (utils_authenticate(instance, AUTH_NLA, TRUE))
349  {
350  case AUTH_SKIP:
351  case AUTH_SUCCESS:
352  break;
353  case AUTH_CANCELLED:
354  freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
355  return FALSE;
356  case AUTH_NO_CREDENTIALS:
357  WLog_INFO(TAG, "No credentials provided - using NULL identity");
358  break;
359  default:
360  return FALSE;
361  }
362  }
363 
364  if (!settings->Username)
365  {
366  sspi_FreeAuthIdentity(nla->identity);
367  nla->identity = NULL;
368  }
369  else if (settings->SmartcardLogon)
370  {
371  if (smartCardLogonWasDisabled)
372  {
373  if (!nla_adjust_settings_from_smartcard(nla))
374  return FALSE;
375  }
376 
377  if (!identity_set_from_smartcard_hash(nla->identity, settings, FreeRDP_Username,
378  FreeRDP_Domain, FreeRDP_Password, nla->certSha1,
379  sizeof(nla->certSha1)))
380  return FALSE;
381  }
382  else
383  {
384  BOOL usePassword = TRUE;
385 
386  if (settings->RedirectionPassword && (settings->RedirectionPasswordLength > 0))
387  {
388  if (!identity_set_from_settings_with_pwd(
389  nla->identity, settings, FreeRDP_Username, FreeRDP_Domain,
390  (const WCHAR*)settings->RedirectionPassword,
391  settings->RedirectionPasswordLength / sizeof(WCHAR)))
392  return FALSE;
393 
394  usePassword = FALSE;
395  }
396 
397  if (settings->RestrictedAdminModeRequired)
398  {
399  if (settings->PasswordHash && strlen(settings->PasswordHash) == 32)
400  {
401  if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
402  FreeRDP_Domain, FreeRDP_PasswordHash))
403  return FALSE;
404 
410  nla->identity->PasswordLength += LB_PASSWORD_MAX_LENGTH;
411  usePassword = FALSE;
412  }
413  }
414 
415  if (usePassword)
416  {
417  if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
418  FreeRDP_Domain, FreeRDP_Password))
419  return FALSE;
420  }
421  }
422 
423  return TRUE;
424 }
425 
426 static int nla_client_init(rdpNla* nla)
427 {
428  WINPR_ASSERT(nla);
429  WINPR_ASSERT(nla->rdpcontext);
430 
431  rdpSettings* settings = nla->rdpcontext->settings;
432  WINPR_ASSERT(settings);
433 
434  nla_set_state(nla, NLA_STATE_INITIAL);
435 
436  if (!nla_adjust_settings_from_smartcard(nla))
437  return -1;
438 
439  if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG, NULL))
440  return -1;
441 
442  if (!nla_client_setup_identity(nla))
443  return -1;
444 
445  const char* hostname = freerdp_settings_get_server_name(settings);
446 
447  if (!credssp_auth_setup_client(nla->auth, "TERMSRV", hostname, nla->identity, nla->pkinitArgs))
448  return -1;
449 
450  const BYTE* data = NULL;
451  DWORD length = 0;
452  if (!transport_get_public_key(nla->transport, &data, &length))
453  {
454  WLog_ERR(TAG, "Failed to get public key");
455  return -1;
456  }
457 
458  if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
459  {
460  WLog_ERR(TAG, "Failed to allocate sspi secBuffer");
461  return -1;
462  }
463 
464  return 1;
465 }
466 
467 int nla_client_begin(rdpNla* nla)
468 {
469  WINPR_ASSERT(nla);
470 
471  if (nla_client_init(nla) < 1)
472  return -1;
473 
474  if (nla_get_state(nla) != NLA_STATE_INITIAL)
475  return -1;
476 
477  /*
478  * from tspkg.dll: 0x00000132
479  * ISC_REQ_MUTUAL_AUTH
480  * ISC_REQ_CONFIDENTIALITY
481  * ISC_REQ_USE_SESSION_KEY
482  * ISC_REQ_ALLOCATE_MEMORY
483  */
484  credssp_auth_set_flags(nla->auth, ISC_REQ_MUTUAL_AUTH | ISC_REQ_CONFIDENTIALITY);
485 
486  const int rc = credssp_auth_authenticate(nla->auth);
487 
488  switch (rc)
489  {
490  case 0:
491  if (!nla_send(nla))
492  return -1;
493  nla_set_state(nla, NLA_STATE_NEGO_TOKEN);
494  break;
495  case 1:
496  if (credssp_auth_have_output_token(nla->auth))
497  {
498  if (!nla_send(nla))
499  return -1;
500  }
501  nla_set_state(nla, NLA_STATE_FINAL);
502  break;
503  default:
504  switch (credssp_auth_sspi_error(nla->auth))
505  {
506  case SEC_E_LOGON_DENIED:
507  case SEC_E_NO_CREDENTIALS:
508  freerdp_set_last_error_log(nla->rdpcontext,
509  FREERDP_ERROR_CONNECT_LOGON_FAILURE);
510  break;
511  default:
512  break;
513  }
514  return -1;
515  }
516 
517  return 1;
518 }
519 
520 static int nla_client_recv_nego_token(rdpNla* nla)
521 {
522  credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
523  const int rc = credssp_auth_authenticate(nla->auth);
524 
525  switch (rc)
526  {
527  case 0:
528  if (!nla_send(nla))
529  return -1;
530  break;
531  case 1: /* completed */
532  {
533  int res = -1;
534  if (nla->peerVersion < 5)
535  res = nla_encrypt_public_key_echo(nla);
536  else
537  res = nla_encrypt_public_key_hash(nla);
538 
539  if (!res)
540  return -1;
541 
542  if (!nla_send(nla))
543  return -1;
544 
545  nla_set_state(nla, NLA_STATE_PUB_KEY_AUTH);
546  }
547  break;
548 
549  default:
550  return -1;
551  }
552 
553  return 1;
554 }
555 
556 static int nla_client_recv_pub_key_auth(rdpNla* nla)
557 {
558  BOOL rc = FALSE;
559 
560  WINPR_ASSERT(nla);
561 
562  /* Verify Server Public Key Echo */
563  if (nla->peerVersion < 5)
564  rc = nla_decrypt_public_key_echo(nla);
565  else
566  rc = nla_decrypt_public_key_hash(nla);
567 
568  sspi_SecBufferFree(&nla->pubKeyAuth);
569 
570  if (!rc)
571  return -1;
572 
573  /* Send encrypted credentials */
574  rc = nla_encrypt_ts_credentials(nla);
575  if (!rc)
576  return -1;
577 
578  if (!nla_send(nla))
579  return -1;
580 
581  if (nla->earlyUserAuth)
582  {
583  transport_set_early_user_auth_mode(nla->transport, TRUE);
584  nla_set_state(nla, NLA_STATE_EARLY_USER_AUTH);
585  }
586  else
587  nla_set_state(nla, NLA_STATE_AUTH_INFO);
588  return 1;
589 }
590 
591 static int nla_client_recv_early_user_auth(rdpNla* nla)
592 {
593  WINPR_ASSERT(nla);
594 
595  transport_set_early_user_auth_mode(nla->transport, FALSE);
596  nla_set_state(nla, NLA_STATE_AUTH_INFO);
597  return 1;
598 }
599 
600 static int nla_client_recv(rdpNla* nla)
601 {
602  WINPR_ASSERT(nla);
603 
604  switch (nla_get_state(nla))
605  {
606  case NLA_STATE_NEGO_TOKEN:
607  return nla_client_recv_nego_token(nla);
608 
609  case NLA_STATE_PUB_KEY_AUTH:
610  return nla_client_recv_pub_key_auth(nla);
611 
612  case NLA_STATE_EARLY_USER_AUTH:
613  return nla_client_recv_early_user_auth(nla);
614 
615  case NLA_STATE_FINAL:
616  default:
617  WLog_ERR(TAG, "NLA in invalid client receive state %s",
618  nla_get_state_str(nla_get_state(nla)));
619  return -1;
620  }
621 }
622 
623 static int nla_client_authenticate(rdpNla* nla)
624 {
625  int rc = -1;
626 
627  WINPR_ASSERT(nla);
628 
629  wStream* s = Stream_New(NULL, 4096);
630 
631  if (!s)
632  {
633  WLog_ERR(TAG, "Stream_New failed!");
634  return -1;
635  }
636 
637  if (nla_client_begin(nla) < 1)
638  goto fail;
639 
640  while (nla_get_state(nla) < NLA_STATE_AUTH_INFO)
641  {
642  Stream_SetPosition(s, 0);
643  const int status = transport_read_pdu(nla->transport, s);
644 
645  if (status < 0)
646  {
647  WLog_ERR(TAG, "nla_client_authenticate failure");
648  goto fail;
649  }
650 
651  const int status2 = nla_recv_pdu(nla, s);
652 
653  if (status2 < 0)
654  goto fail;
655  }
656 
657  rc = 1;
658 fail:
659  Stream_Free(s, TRUE);
660  return rc;
661 }
662 
667 static int nla_server_init(rdpNla* nla)
668 {
669  WINPR_ASSERT(nla);
670 
671  const BYTE* data = NULL;
672  DWORD length = 0;
673  if (!transport_get_public_key(nla->transport, &data, &length))
674  {
675  WLog_ERR(TAG, "Failed to get public key");
676  return -1;
677  }
678 
679  if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
680  {
681  WLog_ERR(TAG, "Failed to allocate SecBuffer for public key");
682  return -1;
683  }
684 
685  if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG, NULL))
686  return -1;
687 
688  if (!credssp_auth_setup_server(nla->auth))
689  return -1;
690 
691  nla_set_state(nla, NLA_STATE_INITIAL);
692  return 1;
693 }
694 
695 static wStream* nla_server_recv_stream(rdpNla* nla)
696 {
697  wStream* s = NULL;
698  int status = -1;
699 
700  WINPR_ASSERT(nla);
701 
702  s = Stream_New(NULL, 4096);
703 
704  if (!s)
705  goto fail;
706 
707  status = transport_read_pdu(nla->transport, s);
708 
709 fail:
710  if (status < 0)
711  {
712  WLog_ERR(TAG, "nla_recv() error: %d", status);
713  Stream_Free(s, TRUE);
714  return NULL;
715  }
716 
717  return s;
718 }
719 
720 static BOOL nla_server_recv_credentials(rdpNla* nla)
721 {
722  WINPR_ASSERT(nla);
723 
724  if (nla_server_recv(nla) < 0)
725  return FALSE;
726 
727  if (!nla_decrypt_ts_credentials(nla))
728  return FALSE;
729 
730  if (!nla_impersonate(nla))
731  return FALSE;
732 
733  if (!nla_revert_to_self(nla))
734  return FALSE;
735 
736  return TRUE;
737 }
738 
746 static int nla_server_authenticate(rdpNla* nla)
747 {
748  int ret = -1;
749 
750  WINPR_ASSERT(nla);
751 
752  if (nla_server_init(nla) < 1)
753  goto fail;
754 
755  /*
756  * from tspkg.dll: 0x00000112
757  * ASC_REQ_MUTUAL_AUTH
758  * ASC_REQ_CONFIDENTIALITY
759  * ASC_REQ_ALLOCATE_MEMORY
760  */
761  credssp_auth_set_flags(nla->auth, ASC_REQ_MUTUAL_AUTH | ASC_REQ_CONFIDENTIALITY |
762  ASC_REQ_CONNECTION | ASC_REQ_USE_SESSION_KEY |
763  ASC_REQ_SEQUENCE_DETECT | ASC_REQ_EXTENDED_ERROR);
764 
765  /* Client is starting, here es the state machine:
766  *
767  * -- NLA_STATE_INITIAL --> NLA_STATE_INITIAL
768  * ----->> sending...
769  * ----->> protocol version 6
770  * ----->> nego token
771  * ----->> client nonce
772  * <<----- receiving...
773  * <<----- protocol version 6
774  * <<----- nego token
775  * ----->> sending...
776  * ----->> protocol version 6
777  * ----->> nego token
778  * ----->> public key auth
779  * ----->> client nonce
780  * -- NLA_STATE_NEGO_TOKEN --> NLA_STATE_PUB_KEY_AUTH
781  * <<----- receiving...
782  * <<----- protocol version 6
783  * <<----- public key info
784  * ----->> sending...
785  * ----->> protocol version 6
786  * ----->> auth info
787  * ----->> client nonce
788  * -- NLA_STATE_PUB_KEY_AUTH --> NLA_STATE
789  */
790 
791  while (TRUE)
792  {
793  int res = -1;
794 
795  if (nla_server_recv(nla) < 0)
796  goto fail;
797 
798  WLog_DBG(TAG, "Receiving Authentication Token");
799  credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
800 
801  res = credssp_auth_authenticate(nla->auth);
802 
803  if (res == -1)
804  {
805  /* Special handling of these specific error codes as NTSTATUS_FROM_WIN32
806  unfortunately does not map directly to the corresponding NTSTATUS values
807  */
808  switch (GetLastError())
809  {
810  case ERROR_PASSWORD_MUST_CHANGE:
811  nla->errorCode = STATUS_PASSWORD_MUST_CHANGE;
812  break;
813 
814  case ERROR_PASSWORD_EXPIRED:
815  nla->errorCode = STATUS_PASSWORD_EXPIRED;
816  break;
817 
818  case ERROR_ACCOUNT_DISABLED:
819  nla->errorCode = STATUS_ACCOUNT_DISABLED;
820  break;
821 
822  default:
823  nla->errorCode = NTSTATUS_FROM_WIN32(GetLastError());
824  break;
825  }
826 
827  (void)nla_send(nla);
828  /* Access Denied */
829  goto fail;
830  }
831 
832  if (res == 1)
833  {
834  /* Process final part of the nego token exchange */
835  if (credssp_auth_have_output_token(nla->auth))
836  {
837  if (!nla_send(nla))
838  goto fail;
839 
840  if (nla_server_recv(nla) < 0)
841  goto fail;
842 
843  WLog_DBG(TAG, "Receiving pubkey Token");
844  }
845 
846  if (nla->peerVersion < 5)
847  res = nla_decrypt_public_key_echo(nla);
848  else
849  res = nla_decrypt_public_key_hash(nla);
850 
851  if (!res)
852  goto fail;
853 
854  /* Clear nego token buffer or we will send it again to the client */
855  sspi_SecBufferFree(&nla->negoToken);
856 
857  if (nla->peerVersion < 5)
858  res = nla_encrypt_public_key_echo(nla);
859  else
860  res = nla_encrypt_public_key_hash(nla);
861 
862  if (!res)
863  goto fail;
864  }
865 
866  /* send authentication token */
867  WLog_DBG(TAG, "Sending Authentication Token");
868 
869  if (!nla_send(nla))
870  goto fail;
871 
872  if (res == 1)
873  {
874  ret = 1;
875  break;
876  }
877  }
878 
879  /* Receive encrypted credentials */
880  if (!nla_server_recv_credentials(nla))
881  ret = -1;
882 
883 fail:
884  nla_buffer_free(nla);
885  return ret;
886 }
887 
895 int nla_authenticate(rdpNla* nla)
896 {
897  WINPR_ASSERT(nla);
898 
899  if (nla->server)
900  return nla_server_authenticate(nla);
901  else
902  return nla_client_authenticate(nla);
903 }
904 
905 static void ap_integer_increment_le(BYTE* number, size_t size)
906 {
907  WINPR_ASSERT(number || (size == 0));
908 
909  for (size_t index = 0; index < size; index++)
910  {
911  if (number[index] < 0xFF)
912  {
913  number[index]++;
914  break;
915  }
916  else
917  {
918  number[index] = 0;
919  continue;
920  }
921  }
922 }
923 
924 static void ap_integer_decrement_le(BYTE* number, size_t size)
925 {
926  WINPR_ASSERT(number || (size == 0));
927 
928  for (size_t index = 0; index < size; index++)
929  {
930  if (number[index] > 0)
931  {
932  number[index]--;
933  break;
934  }
935  else
936  {
937  number[index] = 0xFF;
938  continue;
939  }
940  }
941 }
942 
943 BOOL nla_encrypt_public_key_echo(rdpNla* nla)
944 {
945  BOOL status = FALSE;
946 
947  WINPR_ASSERT(nla);
948 
949  sspi_SecBufferFree(&nla->pubKeyAuth);
950  if (nla->server)
951  {
952  SecBuffer buf = { 0 };
953  if (!sspi_SecBufferAlloc(&buf, nla->PublicKey.cbBuffer))
954  return FALSE;
955  ap_integer_increment_le(buf.pvBuffer, buf.cbBuffer);
956  status = credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth, NULL, nla->sendSeqNum++);
957  sspi_SecBufferFree(&buf);
958  }
959  else
960  {
961  status = credssp_auth_encrypt(nla->auth, &nla->PublicKey, &nla->pubKeyAuth, NULL,
962  nla->sendSeqNum++);
963  }
964 
965  return status;
966 }
967 
968 BOOL nla_encrypt_public_key_hash(rdpNla* nla)
969 {
970  BOOL status = FALSE;
971  WINPR_DIGEST_CTX* sha256 = NULL;
972  SecBuffer buf = { 0 };
973 
974  WINPR_ASSERT(nla);
975 
976  const BYTE* hashMagic = nla->server ? ServerClientHashMagic : ClientServerHashMagic;
977  const size_t hashSize =
978  nla->server ? sizeof(ServerClientHashMagic) : sizeof(ClientServerHashMagic);
979 
980  if (!sspi_SecBufferAlloc(&buf, WINPR_SHA256_DIGEST_LENGTH))
981  return FALSE;
982 
983  /* generate SHA256 of following data: ClientServerHashMagic, Nonce, SubjectPublicKey */
984  if (!(sha256 = winpr_Digest_New()))
985  goto out;
986 
987  if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
988  goto out;
989 
990  /* include trailing \0 from hashMagic */
991  if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
992  goto out;
993 
994  if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
995  goto out;
996 
997  /* SubjectPublicKey */
998  if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
999  goto out;
1000 
1001  if (!winpr_Digest_Final(sha256, buf.pvBuffer, WINPR_SHA256_DIGEST_LENGTH))
1002  goto out;
1003 
1004  sspi_SecBufferFree(&nla->pubKeyAuth);
1005  if (!credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth, NULL, nla->sendSeqNum++))
1006  goto out;
1007 
1008  status = TRUE;
1009 
1010 out:
1011  winpr_Digest_Free(sha256);
1012  sspi_SecBufferFree(&buf);
1013  return status;
1014 }
1015 
1016 BOOL nla_decrypt_public_key_echo(rdpNla* nla)
1017 {
1018  BOOL status = FALSE;
1019  SecBuffer public_key = { 0 };
1020 
1021  if (!nla)
1022  goto fail;
1023 
1024  if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &public_key, nla->recvSeqNum++))
1025  return FALSE;
1026 
1027  if (!nla->server)
1028  {
1029  /* server echos the public key +1 */
1030  ap_integer_decrement_le(public_key.pvBuffer, public_key.cbBuffer);
1031  }
1032 
1033  if (public_key.cbBuffer != nla->PublicKey.cbBuffer ||
1034  memcmp(public_key.pvBuffer, nla->PublicKey.pvBuffer, public_key.cbBuffer) != 0)
1035  {
1036  WLog_ERR(TAG, "Could not verify server's public key echo");
1037 #if defined(WITH_DEBUG_NLA)
1038  WLog_ERR(TAG, "Expected (length = %" PRIu32 "):", nla->PublicKey.cbBuffer);
1039  winpr_HexDump(TAG, WLOG_ERROR, nla->PublicKey.pvBuffer, nla->PublicKey.cbBuffer);
1040  WLog_ERR(TAG, "Actual (length = %" PRIu32 "):", public_key.cbBuffer);
1041  winpr_HexDump(TAG, WLOG_ERROR, public_key.pvBuffer, public_key.cbBuffer);
1042 #endif
1043  /* DO NOT SEND CREDENTIALS! */
1044  goto fail;
1045  }
1046 
1047  status = TRUE;
1048 fail:
1049  sspi_SecBufferFree(&public_key);
1050  return status;
1051 }
1052 
1053 BOOL nla_decrypt_public_key_hash(rdpNla* nla)
1054 {
1055  WINPR_DIGEST_CTX* sha256 = NULL;
1056  BYTE serverClientHash[WINPR_SHA256_DIGEST_LENGTH] = { 0 };
1057  BOOL status = FALSE;
1058 
1059  WINPR_ASSERT(nla);
1060 
1061  const BYTE* hashMagic = nla->server ? ClientServerHashMagic : ServerClientHashMagic;
1062  const size_t hashSize =
1063  nla->server ? sizeof(ClientServerHashMagic) : sizeof(ServerClientHashMagic);
1064  SecBuffer hash = { 0 };
1065 
1066  if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &hash, nla->recvSeqNum++))
1067  return FALSE;
1068 
1069  /* generate SHA256 of following data: ServerClientHashMagic, Nonce, SubjectPublicKey */
1070  if (!(sha256 = winpr_Digest_New()))
1071  goto fail;
1072 
1073  if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1074  goto fail;
1075 
1076  /* include trailing \0 from hashMagic */
1077  if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1078  goto fail;
1079 
1080  if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1081  goto fail;
1082 
1083  /* SubjectPublicKey */
1084  if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1085  goto fail;
1086 
1087  if (!winpr_Digest_Final(sha256, serverClientHash, sizeof(serverClientHash)))
1088  goto fail;
1089 
1090  /* verify hash */
1091  if (hash.cbBuffer != WINPR_SHA256_DIGEST_LENGTH ||
1092  memcmp(serverClientHash, hash.pvBuffer, WINPR_SHA256_DIGEST_LENGTH) != 0)
1093  {
1094  WLog_ERR(TAG, "Could not verify server's hash");
1095  /* DO NOT SEND CREDENTIALS! */
1096  goto fail;
1097  }
1098 
1099  status = TRUE;
1100 fail:
1101  winpr_Digest_Free(sha256);
1102  sspi_SecBufferFree(&hash);
1103  return status;
1104 }
1105 
1106 static BOOL set_creds_octetstring_to_settings(WinPrAsn1Decoder* dec, WinPrAsn1_tagId tagId,
1107  BOOL optional, FreeRDP_Settings_Keys_String settingId,
1108  rdpSettings* settings)
1109 {
1110  if (optional)
1111  {
1112  WinPrAsn1_tagId itemTag = 0;
1113  if (!WinPrAsn1DecPeekTag(dec, &itemTag) || (itemTag != tagId))
1114  return TRUE;
1115  }
1116 
1117  BOOL error = FALSE;
1118  WinPrAsn1_OctetString value;
1119  /* note: not checking "error" value, as the not present optional item case is handled above
1120  * if the function fails it's because of a real error not because the item is not present
1121  */
1122  if (!WinPrAsn1DecReadContextualOctetString(dec, tagId, &error, &value, FALSE))
1123  return FALSE;
1124 
1125  return freerdp_settings_set_string_from_utf16N(settings, settingId, (const WCHAR*)value.data,
1126  value.len / sizeof(WCHAR));
1127 }
1128 
1129 static BOOL nla_read_TSCspDataDetail(WinPrAsn1Decoder* dec, rdpSettings* settings)
1130 {
1131  BOOL error = FALSE;
1132 
1133  /* keySpec [0] INTEGER */
1134  WinPrAsn1_INTEGER keyspec = 0;
1135  if (!WinPrAsn1DecReadContextualInteger(dec, 0, &error, &keyspec))
1136  return FALSE;
1137  settings->KeySpec = (UINT32)keyspec;
1138 
1139  /* cardName [1] OCTET STRING OPTIONAL */
1140  if (!set_creds_octetstring_to_settings(dec, 1, TRUE, FreeRDP_CardName, settings))
1141  return FALSE;
1142 
1143  /* readerName [2] OCTET STRING OPTIONAL */
1144  if (!set_creds_octetstring_to_settings(dec, 2, TRUE, FreeRDP_ReaderName, settings))
1145  return FALSE;
1146 
1147  /* containerName [3] OCTET STRING OPTIONAL */
1148  if (!set_creds_octetstring_to_settings(dec, 3, TRUE, FreeRDP_ContainerName, settings))
1149  return FALSE;
1150 
1151  /* cspName [4] OCTET STRING OPTIONAL */
1152  return set_creds_octetstring_to_settings(dec, 4, TRUE, FreeRDP_CspName, settings);
1153 }
1154 
1155 static BOOL nla_read_KERB_TICKET_LOGON(rdpNla* nla, wStream* s, KERB_TICKET_LOGON* ticket)
1156 {
1157  WINPR_ASSERT(nla);
1158 
1159  if (!ticket)
1160  return FALSE;
1161 
1162  /* mysterious extra 16 bytes before TGS/TGT content */
1163  if (!Stream_CheckAndLogRequiredLength(TAG, s, 16 + 16))
1164  return FALSE;
1165 
1166  Stream_Read_UINT32(s, ticket->MessageType);
1167  Stream_Read_UINT32(s, ticket->Flags);
1168  Stream_Read_UINT32(s, ticket->ServiceTicketLength);
1169  Stream_Read_UINT32(s, ticket->TicketGrantingTicketLength);
1170 
1171  if (ticket->MessageType != KerbTicketLogon)
1172  {
1173  WLog_ERR(TAG, "Not a KerbTicketLogon");
1174  return FALSE;
1175  }
1176 
1177  if (!Stream_CheckAndLogRequiredLength(
1178  TAG, s, 16ull + ticket->ServiceTicketLength + ticket->TicketGrantingTicketLength))
1179  return FALSE;
1180 
1181  /* mysterious 16 bytes in the way, maybe they would need to be interpreted... */
1182  Stream_Seek(s, 16);
1183 
1184  /*WLog_INFO(TAG, "TGS");
1185  winpr_HexDump(TAG, WLOG_DEBUG, Stream_PointerAs(s, const BYTE), ticket->ServiceTicketLength);*/
1186  ticket->ServiceTicket = Stream_PointerAs(s, UCHAR);
1187  Stream_Seek(s, ticket->ServiceTicketLength);
1188 
1189  /*WLog_INFO(TAG, "TGT");
1190  winpr_HexDump(TAG, WLOG_DEBUG, Stream_PointerAs(s, const BYTE),
1191  ticket->TicketGrantingTicketLength);*/
1192  ticket->TicketGrantingTicket = Stream_PointerAs(s, UCHAR);
1193  return TRUE;
1194 }
1195 
1197 typedef enum
1198 {
1199  RCG_TYPE_NONE,
1200  RCG_TYPE_KERB,
1201  RCG_TYPE_NTLM
1202 } RemoteGuardPackageCredType;
1203 
1204 static BOOL nla_read_TSRemoteGuardPackageCred(rdpNla* nla, WinPrAsn1Decoder* dec,
1205  RemoteGuardPackageCredType* credsType,
1206  wStream* payload)
1207 {
1208  WinPrAsn1_OctetString packageName = { 0 };
1209  WinPrAsn1_OctetString credBuffer = { 0 };
1210  BOOL error = FALSE;
1211  char packageNameStr[100] = { 0 };
1212 
1213  WINPR_ASSERT(nla);
1214  WINPR_ASSERT(dec);
1215  WINPR_ASSERT(credsType);
1216  WINPR_ASSERT(payload);
1217 
1218  *credsType = RCG_TYPE_NONE;
1219 
1220  /* packageName [0] OCTET STRING */
1221  if (!WinPrAsn1DecReadContextualOctetString(dec, 0, &error, &packageName, FALSE) || error)
1222  return FALSE;
1223 
1224  ConvertMszWCharNToUtf8((WCHAR*)packageName.data, packageName.len / sizeof(WCHAR),
1225  packageNameStr, sizeof(packageNameStr));
1226  WLog_DBG(TAG, "TSRemoteGuardPackageCred(%s)", packageNameStr);
1227 
1228  /* credBuffer [1] OCTET STRING, */
1229  if (!WinPrAsn1DecReadContextualOctetString(dec, 1, &error, &credBuffer, FALSE) || error)
1230  return FALSE;
1231 
1232  if (_stricmp(packageNameStr, "Kerberos") == 0)
1233  {
1234  *credsType = RCG_TYPE_KERB;
1235  }
1236  else if (_stricmp(packageNameStr, "NTLM") == 0)
1237  {
1238  *credsType = RCG_TYPE_NTLM;
1239  }
1240  else
1241  {
1242  WLog_INFO(TAG, "TSRemoteGuardPackageCred package %s not handled", packageNameStr);
1243  return FALSE;
1244  }
1245 
1246  Stream_StaticInit(payload, credBuffer.data, credBuffer.len);
1247  return TRUE;
1248 }
1249 
1251 typedef enum
1252 {
1253  TSCREDS_INVALID = 0,
1254  TSCREDS_USER_PASSWD = 1,
1255  TSCREDS_SMARTCARD = 2,
1256  TSCREDS_REMOTEGUARD = 6
1257 } TsCredentialsType;
1258 
1259 static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data)
1260 {
1261  WinPrAsn1Decoder dec = { 0 };
1262  WinPrAsn1Decoder dec2 = { 0 };
1263  WinPrAsn1_OctetString credentials = { 0 };
1264  BOOL error = FALSE;
1265  WinPrAsn1_INTEGER credType = -1;
1266  BOOL ret = TRUE;
1267 
1268  WINPR_ASSERT(nla);
1269  WINPR_ASSERT(data);
1270 
1271  WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, (BYTE*)data->pvBuffer, data->cbBuffer);
1272 
1273  /* TSCredentials */
1274  if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1275  return FALSE;
1276  dec = dec2;
1277 
1278  /* credType [0] INTEGER */
1279  if (!WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &credType))
1280  return FALSE;
1281 
1282  /* credentials [1] OCTET STRING */
1283  if (!WinPrAsn1DecReadContextualOctetString(&dec, 1, &error, &credentials, FALSE))
1284  return FALSE;
1285 
1286  WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, credentials.data, credentials.len);
1287 
1288  rdpSettings* settings = nla->rdpcontext->settings;
1289  if (nego_get_remoteCredentialGuard(nla->rdpcontext->rdp->nego) &&
1290  credType != TSCREDS_REMOTEGUARD)
1291  {
1292  WLog_ERR(TAG, "connecting with RCG but it's not TSRemoteGuard credentials");
1293  return FALSE;
1294  }
1295 
1296  switch (credType)
1297  {
1298  case TSCREDS_USER_PASSWD:
1299  {
1300  /* TSPasswordCreds */
1301  if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1302  return FALSE;
1303  dec = dec2;
1304 
1305  /* domainName [0] OCTET STRING */
1306  if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Domain, settings))
1307  return FALSE;
1308 
1309  /* userName [1] OCTET STRING */
1310  if (!set_creds_octetstring_to_settings(&dec, 1, FALSE, FreeRDP_Username, settings))
1311  return FALSE;
1312 
1313  /* password [2] OCTET STRING */
1314  return set_creds_octetstring_to_settings(&dec, 2, FALSE, FreeRDP_Password, settings);
1315  }
1316  case TSCREDS_SMARTCARD:
1317  {
1318  /* TSSmartCardCreds */
1319  if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1320  return FALSE;
1321  dec = dec2;
1322 
1323  /* pin [0] OCTET STRING, */
1324  if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Password, settings))
1325  return FALSE;
1326  settings->PasswordIsSmartcardPin = TRUE;
1327 
1328  /* cspData [1] TSCspDataDetail */
1329  WinPrAsn1Decoder cspDetails = { 0 };
1330  if (!WinPrAsn1DecReadContextualSequence(&dec, 1, &error, &cspDetails) && error)
1331  return FALSE;
1332  if (!nla_read_TSCspDataDetail(&cspDetails, settings))
1333  return FALSE;
1334 
1335  /* userHint [2] OCTET STRING OPTIONAL */
1336  if (!set_creds_octetstring_to_settings(&dec, 2, TRUE, FreeRDP_Username, settings))
1337  return FALSE;
1338 
1339  /* domainHint [3] OCTET STRING OPTIONAL */
1340  return set_creds_octetstring_to_settings(&dec, 3, TRUE, FreeRDP_Domain, settings);
1341  }
1342  case TSCREDS_REMOTEGUARD:
1343  {
1344  /* TSRemoteGuardCreds */
1345  if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1346  return FALSE;
1347 
1348  /* logonCred[0] TSRemoteGuardPackageCred */
1349  KERB_TICKET_LOGON kerbLogon = { 0 };
1350  WinPrAsn1Decoder logonCredsSeq = { 0 };
1351  if (!WinPrAsn1DecReadContextualSequence(&dec2, 0, &error, &logonCredsSeq) || error)
1352  return FALSE;
1353 
1354  RemoteGuardPackageCredType logonCredsType = RCG_TYPE_NONE;
1355  wStream logonPayload = { 0 };
1356  if (!nla_read_TSRemoteGuardPackageCred(nla, &logonCredsSeq, &logonCredsType,
1357  &logonPayload))
1358  return FALSE;
1359  if (logonCredsType != RCG_TYPE_KERB)
1360  {
1361  WLog_ERR(TAG, "logonCred must be some Kerberos creds");
1362  return FALSE;
1363  }
1364 
1365  if (!nla_read_KERB_TICKET_LOGON(nla, &logonPayload, &kerbLogon))
1366  {
1367  WLog_ERR(TAG, "invalid KERB_TICKET_LOGON");
1368  return FALSE;
1369  }
1370 
1371  /* supplementalCreds [1] SEQUENCE OF TSRemoteGuardPackageCred OPTIONAL, */
1372  MSV1_0_SUPPLEMENTAL_CREDENTIAL* suppCreds = NULL;
1373  WinPrAsn1Decoder suppCredsSeq = { 0 };
1374 
1375  if (WinPrAsn1DecReadContextualSequence(&dec2, 1, &error, &suppCredsSeq))
1376  {
1377  WinPrAsn1Decoder ntlmCredsSeq = { 0 };
1378  if (!WinPrAsn1DecReadSequence(&suppCredsSeq, &ntlmCredsSeq))
1379  return FALSE;
1380 
1381  RemoteGuardPackageCredType suppCredsType = { 0 };
1382  wStream ntlmPayload = { 0 };
1383  if (!nla_read_TSRemoteGuardPackageCred(nla, &ntlmCredsSeq, &suppCredsType,
1384  &ntlmPayload))
1385  return FALSE;
1386 
1387  if (suppCredsType != RCG_TYPE_NTLM)
1388  {
1389  WLog_ERR(TAG, "supplementalCreds must be some NTLM creds");
1390  return FALSE;
1391  }
1392 
1393  /* TODO: suppCreds = &ntlmCreds; and parse NTLM creds */
1394  }
1395  else if (error)
1396  {
1397  WLog_ERR(TAG, "invalid supplementalCreds");
1398  return FALSE;
1399  }
1400 
1401  freerdp_peer* peer = nla->rdpcontext->peer;
1402  ret = IFCALLRESULT(TRUE, peer->RemoteCredentials, peer, &kerbLogon, suppCreds);
1403  break;
1404  }
1405  default:
1406  WLog_DBG(TAG, "TSCredentials type " PRIu32 " not supported for now", credType);
1407  ret = FALSE;
1408  break;
1409  }
1410 
1411  return ret;
1412 }
1413 
1414 static BOOL nla_write_KERB_TICKET_LOGON(wStream* s, const KERB_TICKET_LOGON* ticket)
1415 {
1416  WINPR_ASSERT(ticket);
1417 
1418  if (!Stream_EnsureRemainingCapacity(s, (4ULL * 4) + 16ULL + ticket->ServiceTicketLength +
1419  ticket->TicketGrantingTicketLength))
1420  return FALSE;
1421 
1422  Stream_Write_UINT32(s, KerbTicketLogon);
1423  Stream_Write_UINT32(s, ticket->Flags);
1424  Stream_Write_UINT32(s, ticket->ServiceTicketLength);
1425  Stream_Write_UINT32(s, ticket->TicketGrantingTicketLength);
1426 
1427  Stream_Write_UINT64(s, 0x20); /* offset of TGS in the packet */
1428  Stream_Write_UINT64(s, 0x20 + ticket->ServiceTicketLength); /* offset of TGT in packet */
1429 
1430  Stream_Write(s, ticket->ServiceTicket, ticket->ServiceTicketLength);
1431  Stream_Write(s, ticket->TicketGrantingTicket, ticket->TicketGrantingTicketLength);
1432  return TRUE;
1433 }
1434 
1435 static BOOL nla_get_KERB_TICKET_LOGON(rdpNla* nla, KERB_TICKET_LOGON* logonTicket)
1436 {
1437  WINPR_ASSERT(nla);
1438  WINPR_ASSERT(logonTicket);
1439 
1440  SecurityFunctionTable* table = NULL;
1441  CtxtHandle context = { 0 };
1442  credssp_auth_tableAndContext(nla->auth, &table, &context);
1443  return table->QueryContextAttributes(&context, SECPKG_CRED_ATTR_TICKET_LOGON, logonTicket) ==
1444  SEC_E_OK;
1445 }
1446 
1447 static BOOL nla_write_TSRemoteGuardKerbCred(rdpNla* nla, WinPrAsn1Encoder* enc)
1448 {
1449  BOOL ret = FALSE;
1450  wStream* s = NULL;
1451  char kerberos[] = { 'K', '\0', 'e', '\0', 'r', '\0', 'b', '\0',
1452  'e', '\0', 'r', '\0', 'o', '\0', 's', '\0' };
1453  WinPrAsn1_OctetString packageName = { sizeof(kerberos), (BYTE*)kerberos };
1454  WinPrAsn1_OctetString credBuffer;
1455  KERB_TICKET_LOGON logonTicket;
1456 
1457  logonTicket.ServiceTicket = NULL;
1458  logonTicket.TicketGrantingTicket = NULL;
1459 
1460  /* packageName [0] OCTET STRING */
1461  if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1462  goto out;
1463 
1464  /* credBuffer [1] OCTET STRING */
1465  if (!nla_get_KERB_TICKET_LOGON(nla, &logonTicket))
1466  goto out;
1467 
1468  s = Stream_New(NULL, 2000);
1469  if (!s)
1470  goto out;
1471 
1472  if (!nla_write_KERB_TICKET_LOGON(s, &logonTicket))
1473  goto out;
1474 
1475  credBuffer.len = Stream_GetPosition(s);
1476  credBuffer.data = Stream_Buffer(s);
1477  ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1478 
1479 out:
1480  free(logonTicket.ServiceTicket);
1481  free(logonTicket.TicketGrantingTicket);
1482  Stream_Free(s, TRUE);
1483  return ret;
1484 }
1485 
1493 static BOOL nla_encode_ts_credentials(rdpNla* nla)
1494 {
1495  BOOL ret = FALSE;
1496  WinPrAsn1Encoder* enc = NULL;
1497  size_t length = 0;
1498  wStream s = { 0 };
1499  TsCredentialsType credType = TSCREDS_INVALID;
1500 
1501  WINPR_ASSERT(nla);
1502  WINPR_ASSERT(nla->rdpcontext);
1503 
1504  rdpSettings* settings = nla->rdpcontext->settings;
1505  WINPR_ASSERT(settings);
1506 
1507  if (settings->RemoteCredentialGuard)
1508  credType = TSCREDS_REMOTEGUARD;
1509  else if (settings->SmartcardLogon)
1510  credType = TSCREDS_SMARTCARD;
1511  else
1512  credType = TSCREDS_USER_PASSWD;
1513 
1514  enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1515  if (!enc)
1516  return FALSE;
1517 
1518  /* TSCredentials */
1519  if (!WinPrAsn1EncSeqContainer(enc))
1520  goto out;
1521 
1522  /* credType [0] INTEGER */
1523  if (!WinPrAsn1EncContextualInteger(enc, 0, (WinPrAsn1_INTEGER)credType))
1524  goto out;
1525 
1526  /* credentials [1] OCTET STRING */
1527  if (!WinPrAsn1EncContextualOctetStringContainer(enc, 1))
1528  goto out;
1529 
1530  switch (credType)
1531  {
1532  case TSCREDS_SMARTCARD:
1533  {
1534  struct
1535  {
1536  WinPrAsn1_tagId tag;
1537  size_t setting_id;
1538  } cspData_fields[] = { { 1, FreeRDP_CardName },
1539  { 2, FreeRDP_ReaderName },
1540  { 3, FreeRDP_ContainerName },
1541  { 4, FreeRDP_CspName } };
1542  WinPrAsn1_OctetString octet_string = { 0 };
1543 
1544  /* TSSmartCardCreds */
1545  if (!WinPrAsn1EncSeqContainer(enc))
1546  goto out;
1547 
1548  /* pin [0] OCTET STRING */
1549  size_t ss = 0;
1550  octet_string.data =
1551  (BYTE*)freerdp_settings_get_string_as_utf16(settings, FreeRDP_Password, &ss);
1552  octet_string.len = ss * sizeof(WCHAR);
1553  const BOOL res = WinPrAsn1EncContextualOctetString(enc, 0, &octet_string) > 0;
1554  free(octet_string.data);
1555  if (!res)
1556  goto out;
1557 
1558  /* cspData [1] SEQUENCE */
1559  if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1560  goto out;
1561 
1562  /* keySpec [0] INTEGER */
1563  if (!WinPrAsn1EncContextualInteger(
1564  enc, 0, freerdp_settings_get_uint32(settings, FreeRDP_KeySpec)))
1565  goto out;
1566 
1567  for (size_t i = 0; i < ARRAYSIZE(cspData_fields); i++)
1568  {
1569  size_t len = 0;
1570 
1571  octet_string.data = (BYTE*)freerdp_settings_get_string_as_utf16(
1572  settings, (FreeRDP_Settings_Keys_String)cspData_fields[i].setting_id, &len);
1573  octet_string.len = len * sizeof(WCHAR);
1574  if (octet_string.len)
1575  {
1576  const BOOL res2 = WinPrAsn1EncContextualOctetString(enc, cspData_fields[i].tag,
1577  &octet_string) > 0;
1578  free(octet_string.data);
1579  if (!res2)
1580  goto out;
1581  }
1582  }
1583 
1584  /* End cspData */
1585  if (!WinPrAsn1EncEndContainer(enc))
1586  goto out;
1587 
1588  /* End TSSmartCardCreds */
1589  if (!WinPrAsn1EncEndContainer(enc))
1590  goto out;
1591  break;
1592  }
1593  case TSCREDS_USER_PASSWD:
1594  {
1595  WinPrAsn1_OctetString username = { 0 };
1596  WinPrAsn1_OctetString domain = { 0 };
1597  WinPrAsn1_OctetString password = { 0 };
1598 
1599  /* TSPasswordCreds */
1600  if (!WinPrAsn1EncSeqContainer(enc))
1601  goto out;
1602 
1603  if (!settings->DisableCredentialsDelegation && nla->identity)
1604  {
1605  username.len = nla->identity->UserLength * sizeof(WCHAR);
1606  username.data = (BYTE*)nla->identity->User;
1607 
1608  domain.len = nla->identity->DomainLength * sizeof(WCHAR);
1609  domain.data = (BYTE*)nla->identity->Domain;
1610 
1611  password.len = nla->identity->PasswordLength * sizeof(WCHAR);
1612  password.data = (BYTE*)nla->identity->Password;
1613  }
1614 
1615  if (WinPrAsn1EncContextualOctetString(enc, 0, &domain) == 0)
1616  goto out;
1617  if (WinPrAsn1EncContextualOctetString(enc, 1, &username) == 0)
1618  goto out;
1619  if (WinPrAsn1EncContextualOctetString(enc, 2, &password) == 0)
1620  goto out;
1621 
1622  /* End TSPasswordCreds */
1623  if (!WinPrAsn1EncEndContainer(enc))
1624  goto out;
1625  break;
1626  }
1627  case TSCREDS_REMOTEGUARD:
1628  /* TSRemoteGuardCreds */
1629  if (!WinPrAsn1EncSeqContainer(enc))
1630  goto out;
1631 
1632  /* logonCred [0] TSRemoteGuardPackageCred, */
1633  if (!WinPrAsn1EncContextualSeqContainer(enc, 0))
1634  goto out;
1635 
1636  if (!nla_write_TSRemoteGuardKerbCred(nla, enc) || !WinPrAsn1EncEndContainer(enc))
1637  goto out;
1638 
1639  /* supplementalCreds [1] SEQUENCE OF TSRemoteGuardPackageCred OPTIONAL,
1640  *
1641  * no NTLM supplemental creds for now
1642  *
1643  */
1644  if (!WinPrAsn1EncContextualSeqContainer(enc, 1) || !WinPrAsn1EncEndContainer(enc))
1645  goto out;
1646 
1647  /* End TSRemoteGuardCreds */
1648  if (!WinPrAsn1EncEndContainer(enc))
1649  goto out;
1650  break;
1651  default:
1652  goto out;
1653  }
1654 
1655  /* End credentials | End TSCredentials */
1656  if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
1657  goto out;
1658 
1659  if (!WinPrAsn1EncStreamSize(enc, &length))
1660  goto out;
1661 
1662  if (!nla_sec_buffer_alloc(&nla->tsCredentials, length))
1663  {
1664  WLog_ERR(TAG, "sspi_SecBufferAlloc failed!");
1665  goto out;
1666  }
1667 
1668  Stream_StaticInit(&s, (BYTE*)nla->tsCredentials.pvBuffer, length);
1669 
1670  ret = WinPrAsn1EncToStream(enc, &s);
1671 
1672 out:
1673  WinPrAsn1Encoder_Free(&enc);
1674  return ret;
1675 }
1676 
1677 static BOOL nla_encrypt_ts_credentials(rdpNla* nla)
1678 {
1679  WINPR_ASSERT(nla);
1680 
1681  if (!nla_encode_ts_credentials(nla))
1682  return FALSE;
1683 
1684  sspi_SecBufferFree(&nla->authInfo);
1685  if (!credssp_auth_encrypt(nla->auth, &nla->tsCredentials, &nla->authInfo, NULL,
1686  nla->sendSeqNum++))
1687  return FALSE;
1688 
1689  return TRUE;
1690 }
1691 
1692 static BOOL nla_decrypt_ts_credentials(rdpNla* nla)
1693 {
1694  WINPR_ASSERT(nla);
1695 
1696  if (nla->authInfo.cbBuffer < 1)
1697  {
1698  WLog_ERR(TAG, "nla_decrypt_ts_credentials missing authInfo buffer");
1699  return FALSE;
1700  }
1701 
1702  sspi_SecBufferFree(&nla->tsCredentials);
1703  if (!credssp_auth_decrypt(nla->auth, &nla->authInfo, &nla->tsCredentials, nla->recvSeqNum++))
1704  return FALSE;
1705 
1706  if (!nla_read_ts_credentials(nla, &nla->tsCredentials))
1707  return FALSE;
1708 
1709  return TRUE;
1710 }
1711 
1712 static BOOL nla_write_octet_string(WinPrAsn1Encoder* enc, const SecBuffer* buffer,
1713  WinPrAsn1_tagId tagId, const char* msg)
1714 {
1715  BOOL res = FALSE;
1716 
1717  WINPR_ASSERT(enc);
1718  WINPR_ASSERT(buffer);
1719  WINPR_ASSERT(msg);
1720 
1721  if (buffer->cbBuffer > 0)
1722  {
1723  size_t rc = 0;
1724  WinPrAsn1_OctetString octet_string = { 0 };
1725 
1726  WLog_DBG(TAG, " ----->> %s", msg);
1727  octet_string.data = buffer->pvBuffer;
1728  octet_string.len = buffer->cbBuffer;
1729  rc = WinPrAsn1EncContextualOctetString(enc, tagId, &octet_string);
1730  if (rc != 0)
1731  res = TRUE;
1732  }
1733 
1734  return res;
1735 }
1736 
1737 static BOOL nla_write_octet_string_free(WinPrAsn1Encoder* enc, SecBuffer* buffer,
1738  WinPrAsn1_tagId tagId, const char* msg)
1739 {
1740  const BOOL rc = nla_write_octet_string(enc, buffer, tagId, msg);
1741  sspi_SecBufferFree(buffer);
1742  return rc;
1743 }
1744 
1753 BOOL nla_send(rdpNla* nla)
1754 {
1755  BOOL rc = FALSE;
1756  wStream* s = NULL;
1757  size_t length = 0;
1758  WinPrAsn1Encoder* enc = NULL;
1759 
1760  WINPR_ASSERT(nla);
1761 
1762  enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1763  if (!enc)
1764  return FALSE;
1765 
1766  /* TSRequest */
1767  WLog_DBG(TAG, "----->> sending...");
1768  if (!WinPrAsn1EncSeqContainer(enc))
1769  goto fail;
1770 
1771  /* version [0] INTEGER */
1772  WLog_DBG(TAG, " ----->> protocol version %" PRIu32, nla->version);
1773  if (!WinPrAsn1EncContextualInteger(enc, 0, nla->version))
1774  goto fail;
1775 
1776  /* negoTokens [1] SEQUENCE OF SEQUENCE */
1777  if (nla_get_state(nla) <= NLA_STATE_NEGO_TOKEN && credssp_auth_have_output_token(nla->auth))
1778  {
1779  const SecBuffer* buffer = credssp_auth_get_output_buffer(nla->auth);
1780 
1781  if (!WinPrAsn1EncContextualSeqContainer(enc, 1) || !WinPrAsn1EncSeqContainer(enc))
1782  goto fail;
1783 
1784  /* negoToken [0] OCTET STRING */
1785  if (!nla_write_octet_string(enc, buffer, 0, "negoToken"))
1786  goto fail;
1787 
1788  /* End negoTokens (SEQUENCE OF SEQUENCE) */
1789  if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
1790  goto fail;
1791  }
1792 
1793  /* authInfo [2] OCTET STRING */
1794  if (nla->authInfo.cbBuffer > 0)
1795  {
1796  if (!nla_write_octet_string_free(enc, &nla->authInfo, 2, "auth info"))
1797  goto fail;
1798  }
1799 
1800  /* pubKeyAuth [3] OCTET STRING */
1801  if (nla->pubKeyAuth.cbBuffer > 0)
1802  {
1803  if (!nla_write_octet_string_free(enc, &nla->pubKeyAuth, 3, "public key auth"))
1804  goto fail;
1805  }
1806 
1807  /* errorCode [4] INTEGER */
1808  if (nla->errorCode && nla->peerVersion >= 3 && nla->peerVersion != 5)
1809  {
1810  WLog_DBG(TAG, " ----->> error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
1811  nla->errorCode);
1812  if (!WinPrAsn1EncContextualInteger(enc, 4, nla->errorCode))
1813  goto fail;
1814  }
1815 
1816  /* clientNonce [5] OCTET STRING */
1817  if (!nla->server && nla->ClientNonce.cbBuffer > 0)
1818  {
1819  if (!nla_write_octet_string(enc, &nla->ClientNonce, 5, "client nonce"))
1820  goto fail;
1821  }
1822 
1823  /* End TSRequest */
1824  if (!WinPrAsn1EncEndContainer(enc))
1825  goto fail;
1826 
1827  if (!WinPrAsn1EncStreamSize(enc, &length))
1828  goto fail;
1829 
1830  s = Stream_New(NULL, length);
1831  if (!s)
1832  goto fail;
1833 
1834  if (!WinPrAsn1EncToStream(enc, s))
1835  goto fail;
1836 
1837  WLog_DBG(TAG, "[%" PRIuz " bytes]", length);
1838  if (transport_write(nla->transport, s) < 0)
1839  goto fail;
1840  rc = TRUE;
1841 
1842 fail:
1843  Stream_Free(s, TRUE);
1844  WinPrAsn1Encoder_Free(&enc);
1845  return rc;
1846 }
1847 
1848 static int nla_decode_ts_request(rdpNla* nla, wStream* s)
1849 {
1850  WinPrAsn1Decoder dec = { 0 };
1851  WinPrAsn1Decoder dec2 = { 0 };
1852  BOOL error = FALSE;
1853  WinPrAsn1_tagId tag = { 0 };
1854  WinPrAsn1_INTEGER val = { 0 };
1855  UINT32 version = 0;
1856 
1857  WINPR_ASSERT(nla);
1858  WINPR_ASSERT(s);
1859 
1860  WinPrAsn1Decoder_Init(&dec, WINPR_ASN1_DER, s);
1861 
1862  WLog_DBG(TAG, "<<----- receiving...");
1863 
1864  /* TSRequest */
1865  const size_t offset = WinPrAsn1DecReadSequence(&dec, &dec2);
1866  if (offset == 0)
1867  return -1;
1868  dec = dec2;
1869 
1870  /* version [0] INTEGER */
1871  if (WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &val) == 0)
1872  return -1;
1873 
1874  if (!Stream_SafeSeek(s, offset))
1875  return -1;
1876 
1877  version = (UINT)val;
1878  WLog_DBG(TAG, " <<----- protocol version %" PRIu32, version);
1879 
1880  if (nla->peerVersion == 0)
1881  nla->peerVersion = version;
1882 
1883  /* if the peer suddenly changed its version - kick it */
1884  if (nla->peerVersion != version)
1885  {
1886  WLog_ERR(TAG, "CredSSP peer changed protocol version from %" PRIu32 " to %" PRIu32,
1887  nla->peerVersion, version);
1888  return -1;
1889  }
1890 
1891  while (WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2) != 0)
1892  {
1893  WinPrAsn1Decoder dec3 = { 0 };
1894  WinPrAsn1_OctetString octet_string = { 0 };
1895 
1896  switch (tag)
1897  {
1898  case 1:
1899  WLog_DBG(TAG, " <<----- nego token");
1900  /* negoTokens [1] SEQUENCE OF SEQUENCE */
1901  if ((WinPrAsn1DecReadSequence(&dec2, &dec3) == 0) ||
1902  (WinPrAsn1DecReadSequence(&dec3, &dec2) == 0))
1903  return -1;
1904  /* negoToken [0] OCTET STRING */
1905  if ((WinPrAsn1DecReadContextualOctetString(&dec2, 0, &error, &octet_string,
1906  FALSE) == 0) &&
1907  error)
1908  return -1;
1909  if (!nla_sec_buffer_alloc_from_data(&nla->negoToken, octet_string.data, 0,
1910  octet_string.len))
1911  return -1;
1912  break;
1913  case 2:
1914  WLog_DBG(TAG, " <<----- auth info");
1915  /* authInfo [2] OCTET STRING */
1916  if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
1917  return -1;
1918  if (!nla_sec_buffer_alloc_from_data(&nla->authInfo, octet_string.data, 0,
1919  octet_string.len))
1920  return -1;
1921  break;
1922  case 3:
1923  WLog_DBG(TAG, " <<----- public key auth");
1924  /* pubKeyAuth [3] OCTET STRING */
1925  if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
1926  return -1;
1927  if (!nla_sec_buffer_alloc_from_data(&nla->pubKeyAuth, octet_string.data, 0,
1928  octet_string.len))
1929  return -1;
1930  break;
1931  case 4:
1932  /* errorCode [4] INTEGER */
1933  if (WinPrAsn1DecReadInteger(&dec2, &val) == 0)
1934  return -1;
1935  nla->errorCode = (UINT)val;
1936  WLog_DBG(TAG, " <<----- error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
1937  nla->errorCode);
1938  break;
1939  case 5:
1940  WLog_DBG(TAG, " <<----- client nonce");
1941  /* clientNonce [5] OCTET STRING */
1942  if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
1943  return -1;
1944  if (!nla_sec_buffer_alloc_from_data(&nla->ClientNonce, octet_string.data, 0,
1945  octet_string.len))
1946  return -1;
1947  break;
1948  default:
1949  return -1;
1950  }
1951  }
1952 
1953  return 1;
1954 }
1955 
1956 int nla_recv_pdu(rdpNla* nla, wStream* s)
1957 {
1958  WINPR_ASSERT(nla);
1959  WINPR_ASSERT(s);
1960 
1961  if (nla_get_state(nla) == NLA_STATE_EARLY_USER_AUTH)
1962  {
1963  UINT32 code = 0;
1964  Stream_Read_UINT32(s, code);
1965  if (code != AUTHZ_SUCCESS)
1966  {
1967  WLog_DBG(TAG, "Early User Auth active: FAILURE code 0x%08" PRIX32 "", code);
1968  code = FREERDP_ERROR_AUTHENTICATION_FAILED;
1969  freerdp_set_last_error_log(nla->rdpcontext, code);
1970  return -1;
1971  }
1972  else
1973  WLog_DBG(TAG, "Early User Auth active: SUCCESS");
1974  }
1975  else
1976  {
1977  if (nla_decode_ts_request(nla, s) < 1)
1978  return -1;
1979 
1980  if (nla->errorCode)
1981  {
1982  UINT32 code = 0;
1983 
1984  switch (nla->errorCode)
1985  {
1986  case STATUS_PASSWORD_MUST_CHANGE:
1987  code = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE;
1988  break;
1989 
1990  case STATUS_PASSWORD_EXPIRED:
1991  code = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
1992  break;
1993 
1994  case STATUS_ACCOUNT_DISABLED:
1995  code = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED;
1996  break;
1997 
1998  case STATUS_LOGON_FAILURE:
1999  code = FREERDP_ERROR_CONNECT_LOGON_FAILURE;
2000  break;
2001 
2002  case STATUS_WRONG_PASSWORD:
2003  code = FREERDP_ERROR_CONNECT_WRONG_PASSWORD;
2004  break;
2005 
2006  case STATUS_ACCESS_DENIED:
2007  code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
2008  break;
2009 
2010  case STATUS_ACCOUNT_RESTRICTION:
2011  code = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION;
2012  break;
2013 
2014  case STATUS_ACCOUNT_LOCKED_OUT:
2015  code = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT;
2016  break;
2017 
2018  case STATUS_ACCOUNT_EXPIRED:
2019  code = FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED;
2020  break;
2021 
2022  case STATUS_LOGON_TYPE_NOT_GRANTED:
2023  code = FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED;
2024  break;
2025 
2026  default:
2027  WLog_ERR(TAG, "SPNEGO failed with NTSTATUS: %s [0x%08" PRIX32 "]",
2028  NtStatus2Tag(nla->errorCode), nla->errorCode);
2029  code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2030  break;
2031  }
2032 
2033  freerdp_set_last_error_log(nla->rdpcontext, code);
2034  return -1;
2035  }
2036  }
2037 
2038  return nla_client_recv(nla);
2039 }
2040 
2041 int nla_server_recv(rdpNla* nla)
2042 {
2043  int status = -1;
2044 
2045  WINPR_ASSERT(nla);
2046 
2047  wStream* s = nla_server_recv_stream(nla);
2048  if (!s)
2049  goto fail;
2050  status = nla_decode_ts_request(nla, s);
2051 
2052 fail:
2053  Stream_Free(s, TRUE);
2054  return status;
2055 }
2056 
2066 rdpNla* nla_new(rdpContext* context, rdpTransport* transport)
2067 {
2068  WINPR_ASSERT(transport);
2069  WINPR_ASSERT(context);
2070 
2071  rdpSettings* settings = context->settings;
2072  WINPR_ASSERT(settings);
2073 
2074  rdpNla* nla = (rdpNla*)calloc(1, sizeof(rdpNla));
2075 
2076  if (!nla)
2077  return NULL;
2078 
2079  nla->rdpcontext = context;
2080  nla->server = settings->ServerMode;
2081  nla->transport = transport;
2082  nla->sendSeqNum = 0;
2083  nla->recvSeqNum = 0;
2084  nla->version = 6;
2085  nla->earlyUserAuth = FALSE;
2086 
2087  nla->identity = calloc(1, sizeof(SEC_WINNT_AUTH_IDENTITY));
2088  if (!nla->identity)
2089  goto cleanup;
2090 
2091  nla->auth = credssp_auth_new(context);
2092  if (!nla->auth)
2093  goto cleanup;
2094 
2095  /* init to 0 or we end up freeing a bad pointer if the alloc fails */
2096  if (!nla_sec_buffer_alloc(&nla->ClientNonce, NonceLength))
2097  goto cleanup;
2098 
2099  /* generate random 32-byte nonce */
2100  if (winpr_RAND(nla->ClientNonce.pvBuffer, NonceLength) < 0)
2101  goto cleanup;
2102 
2103  return nla;
2104 cleanup:
2105  WINPR_PRAGMA_DIAG_PUSH
2106  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2107  nla_free(nla);
2108  WINPR_PRAGMA_DIAG_POP
2109  return NULL;
2110 }
2111 
2117 void nla_free(rdpNla* nla)
2118 {
2119  if (!nla)
2120  return;
2121 
2122  smartcardCertInfo_Free(nla->smartcardCert);
2123  nla_buffer_free(nla);
2124  sspi_SecBufferFree(&nla->tsCredentials);
2125  credssp_auth_free(nla->auth);
2126 
2127  sspi_FreeAuthIdentity(nla->identity);
2128  free(nla->pkinitArgs);
2129  free(nla->identity);
2130  free(nla);
2131 }
2132 
2133 SEC_WINNT_AUTH_IDENTITY* nla_get_identity(rdpNla* nla)
2134 {
2135  if (!nla)
2136  return NULL;
2137 
2138  return nla->identity;
2139 }
2140 
2141 NLA_STATE nla_get_state(rdpNla* nla)
2142 {
2143  if (!nla)
2144  return NLA_STATE_FINAL;
2145 
2146  return nla->state;
2147 }
2148 
2149 BOOL nla_set_state(rdpNla* nla, NLA_STATE state)
2150 {
2151  if (!nla)
2152  return FALSE;
2153 
2154  WLog_DBG(TAG, "-- %s\t--> %s", nla_get_state_str(nla->state), nla_get_state_str(state));
2155  nla->state = state;
2156  return TRUE;
2157 }
2158 
2159 BOOL nla_set_service_principal(rdpNla* nla, const char* service, const char* hostname)
2160 {
2161  if (!credssp_auth_set_spn(nla->auth, service, hostname))
2162  return FALSE;
2163  return TRUE;
2164 }
2165 
2166 BOOL nla_impersonate(rdpNla* nla)
2167 {
2168  return credssp_auth_impersonate(nla->auth);
2169 }
2170 
2171 BOOL nla_revert_to_self(rdpNla* nla)
2172 {
2173  return credssp_auth_revert_to_self(nla->auth);
2174 }
2175 
2176 const char* nla_get_state_str(NLA_STATE state)
2177 {
2178  switch (state)
2179  {
2180  case NLA_STATE_INITIAL:
2181  return "NLA_STATE_INITIAL";
2182  case NLA_STATE_NEGO_TOKEN:
2183  return "NLA_STATE_NEGO_TOKEN";
2184  case NLA_STATE_PUB_KEY_AUTH:
2185  return "NLA_STATE_PUB_KEY_AUTH";
2186  case NLA_STATE_AUTH_INFO:
2187  return "NLA_STATE_AUTH_INFO";
2188  case NLA_STATE_POST_NEGO:
2189  return "NLA_STATE_POST_NEGO";
2190  case NLA_STATE_EARLY_USER_AUTH:
2191  return "NLA_STATE_EARLY_USER_AUTH";
2192  case NLA_STATE_FINAL:
2193  return "NLA_STATE_FINAL";
2194  default:
2195  return "UNKNOWN";
2196  }
2197 }
2198 
2199 DWORD nla_get_error(rdpNla* nla)
2200 {
2201  if (!nla)
2202  return ERROR_INTERNAL_ERROR;
2203  return nla->errorCode;
2204 }
2205 
2206 UINT32 nla_get_sspi_error(rdpNla* nla)
2207 {
2208  WINPR_ASSERT(nla);
2209  return credssp_auth_sspi_error(nla->auth);
2210 }
2211 
2212 BOOL nla_encrypt(rdpNla* nla, const SecBuffer* inBuffer, SecBuffer* outBuffer)
2213 {
2214  WINPR_ASSERT(nla);
2215  WINPR_ASSERT(inBuffer);
2216  WINPR_ASSERT(outBuffer);
2217  return credssp_auth_encrypt(nla->auth, inBuffer, outBuffer, NULL, nla->sendSeqNum++);
2218 }
2219 
2220 BOOL nla_decrypt(rdpNla* nla, const SecBuffer* inBuffer, SecBuffer* outBuffer)
2221 {
2222  WINPR_ASSERT(nla);
2223  WINPR_ASSERT(inBuffer);
2224  WINPR_ASSERT(outBuffer);
2225  return credssp_auth_decrypt(nla->auth, inBuffer, outBuffer, nla->recvSeqNum++);
2226 }
2227 
2228 SECURITY_STATUS nla_QueryContextAttributes(rdpNla* nla, DWORD ulAttr, PVOID pBuffer)
2229 {
2230  WINPR_ASSERT(nla);
2231 
2232  SecurityFunctionTable* table = NULL;
2233  CtxtHandle context = { 0 };
2234  credssp_auth_tableAndContext(nla->auth, &table, &context);
2235 
2236  return table->QueryContextAttributes(&context, ulAttr, pBuffer);
2237 }
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *param)
Sets a string settings value. The param is copied.
FREERDP_API BOOL freerdp_settings_set_string_from_utf16N(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const WCHAR *param, size_t length)
Sets a string settings value. The param is converted to UTF-8 and the copy stored.
FREERDP_API const char * freerdp_settings_get_server_name(const rdpSettings *settings)
A helper function to return the correct server name.
FREERDP_API WCHAR * freerdp_settings_get_string_as_utf16(const rdpSettings *settings, FreeRDP_Settings_Keys_String id, size_t *pCharLen)
Return an allocated UTF16 string.
FREERDP_API BOOL freerdp_settings_set_string_from_utf16(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const WCHAR *param)
Sets a string settings value. The param is converted to UTF-8 and the copy stored.