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  INT32 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,
1565  WINPR_ASSERTING_INT_CAST(
1566  WinPrAsn1_INTEGER, freerdp_settings_get_uint32(settings, FreeRDP_KeySpec))))
1567  goto out;
1568 
1569  for (size_t i = 0; i < ARRAYSIZE(cspData_fields); i++)
1570  {
1571  size_t len = 0;
1572 
1573  octet_string.data = (BYTE*)freerdp_settings_get_string_as_utf16(
1574  settings, (FreeRDP_Settings_Keys_String)cspData_fields[i].setting_id, &len);
1575  octet_string.len = len * sizeof(WCHAR);
1576  if (octet_string.len)
1577  {
1578  const BOOL res2 = WinPrAsn1EncContextualOctetString(enc, cspData_fields[i].tag,
1579  &octet_string) > 0;
1580  free(octet_string.data);
1581  if (!res2)
1582  goto out;
1583  }
1584  }
1585 
1586  /* End cspData */
1587  if (!WinPrAsn1EncEndContainer(enc))
1588  goto out;
1589 
1590  /* End TSSmartCardCreds */
1591  if (!WinPrAsn1EncEndContainer(enc))
1592  goto out;
1593  break;
1594  }
1595  case TSCREDS_USER_PASSWD:
1596  {
1597  WinPrAsn1_OctetString username = { 0 };
1598  WinPrAsn1_OctetString domain = { 0 };
1599  WinPrAsn1_OctetString password = { 0 };
1600 
1601  /* TSPasswordCreds */
1602  if (!WinPrAsn1EncSeqContainer(enc))
1603  goto out;
1604 
1605  if (!settings->DisableCredentialsDelegation && nla->identity)
1606  {
1607  username.len = nla->identity->UserLength * sizeof(WCHAR);
1608  username.data = (BYTE*)nla->identity->User;
1609 
1610  domain.len = nla->identity->DomainLength * sizeof(WCHAR);
1611  domain.data = (BYTE*)nla->identity->Domain;
1612 
1613  password.len = nla->identity->PasswordLength * sizeof(WCHAR);
1614  password.data = (BYTE*)nla->identity->Password;
1615  }
1616 
1617  if (WinPrAsn1EncContextualOctetString(enc, 0, &domain) == 0)
1618  goto out;
1619  if (WinPrAsn1EncContextualOctetString(enc, 1, &username) == 0)
1620  goto out;
1621  if (WinPrAsn1EncContextualOctetString(enc, 2, &password) == 0)
1622  goto out;
1623 
1624  /* End TSPasswordCreds */
1625  if (!WinPrAsn1EncEndContainer(enc))
1626  goto out;
1627  break;
1628  }
1629  case TSCREDS_REMOTEGUARD:
1630  /* TSRemoteGuardCreds */
1631  if (!WinPrAsn1EncSeqContainer(enc))
1632  goto out;
1633 
1634  /* logonCred [0] TSRemoteGuardPackageCred, */
1635  if (!WinPrAsn1EncContextualSeqContainer(enc, 0))
1636  goto out;
1637 
1638  if (!nla_write_TSRemoteGuardKerbCred(nla, enc) || !WinPrAsn1EncEndContainer(enc))
1639  goto out;
1640 
1641  /* supplementalCreds [1] SEQUENCE OF TSRemoteGuardPackageCred OPTIONAL,
1642  *
1643  * no NTLM supplemental creds for now
1644  *
1645  */
1646  if (!WinPrAsn1EncContextualSeqContainer(enc, 1) || !WinPrAsn1EncEndContainer(enc))
1647  goto out;
1648 
1649  /* End TSRemoteGuardCreds */
1650  if (!WinPrAsn1EncEndContainer(enc))
1651  goto out;
1652  break;
1653  default:
1654  goto out;
1655  }
1656 
1657  /* End credentials | End TSCredentials */
1658  if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
1659  goto out;
1660 
1661  if (!WinPrAsn1EncStreamSize(enc, &length))
1662  goto out;
1663 
1664  if (!nla_sec_buffer_alloc(&nla->tsCredentials, length))
1665  {
1666  WLog_ERR(TAG, "sspi_SecBufferAlloc failed!");
1667  goto out;
1668  }
1669 
1670  Stream_StaticInit(&s, (BYTE*)nla->tsCredentials.pvBuffer, length);
1671 
1672  ret = WinPrAsn1EncToStream(enc, &s);
1673 
1674 out:
1675  WinPrAsn1Encoder_Free(&enc);
1676  return ret;
1677 }
1678 
1679 static BOOL nla_encrypt_ts_credentials(rdpNla* nla)
1680 {
1681  WINPR_ASSERT(nla);
1682 
1683  if (!nla_encode_ts_credentials(nla))
1684  return FALSE;
1685 
1686  sspi_SecBufferFree(&nla->authInfo);
1687  if (!credssp_auth_encrypt(nla->auth, &nla->tsCredentials, &nla->authInfo, NULL,
1688  nla->sendSeqNum++))
1689  return FALSE;
1690 
1691  return TRUE;
1692 }
1693 
1694 static BOOL nla_decrypt_ts_credentials(rdpNla* nla)
1695 {
1696  WINPR_ASSERT(nla);
1697 
1698  if (nla->authInfo.cbBuffer < 1)
1699  {
1700  WLog_ERR(TAG, "nla_decrypt_ts_credentials missing authInfo buffer");
1701  return FALSE;
1702  }
1703 
1704  sspi_SecBufferFree(&nla->tsCredentials);
1705  if (!credssp_auth_decrypt(nla->auth, &nla->authInfo, &nla->tsCredentials, nla->recvSeqNum++))
1706  return FALSE;
1707 
1708  if (!nla_read_ts_credentials(nla, &nla->tsCredentials))
1709  return FALSE;
1710 
1711  return TRUE;
1712 }
1713 
1714 static BOOL nla_write_octet_string(WinPrAsn1Encoder* enc, const SecBuffer* buffer,
1715  WinPrAsn1_tagId tagId, const char* msg)
1716 {
1717  BOOL res = FALSE;
1718 
1719  WINPR_ASSERT(enc);
1720  WINPR_ASSERT(buffer);
1721  WINPR_ASSERT(msg);
1722 
1723  if (buffer->cbBuffer > 0)
1724  {
1725  size_t rc = 0;
1726  WinPrAsn1_OctetString octet_string = { 0 };
1727 
1728  WLog_DBG(TAG, " ----->> %s", msg);
1729  octet_string.data = buffer->pvBuffer;
1730  octet_string.len = buffer->cbBuffer;
1731  rc = WinPrAsn1EncContextualOctetString(enc, tagId, &octet_string);
1732  if (rc != 0)
1733  res = TRUE;
1734  }
1735 
1736  return res;
1737 }
1738 
1739 static BOOL nla_write_octet_string_free(WinPrAsn1Encoder* enc, SecBuffer* buffer,
1740  WinPrAsn1_tagId tagId, const char* msg)
1741 {
1742  const BOOL rc = nla_write_octet_string(enc, buffer, tagId, msg);
1743  sspi_SecBufferFree(buffer);
1744  return rc;
1745 }
1746 
1755 BOOL nla_send(rdpNla* nla)
1756 {
1757  BOOL rc = FALSE;
1758  wStream* s = NULL;
1759  size_t length = 0;
1760  WinPrAsn1Encoder* enc = NULL;
1761 
1762  WINPR_ASSERT(nla);
1763 
1764  enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1765  if (!enc)
1766  return FALSE;
1767 
1768  /* TSRequest */
1769  WLog_DBG(TAG, "----->> sending...");
1770  if (!WinPrAsn1EncSeqContainer(enc))
1771  goto fail;
1772 
1773  /* version [0] INTEGER */
1774  WLog_DBG(TAG, " ----->> protocol version %" PRIu32, nla->version);
1775  if (!WinPrAsn1EncContextualInteger(enc, 0,
1776  WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->version)))
1777  goto fail;
1778 
1779  /* negoTokens [1] SEQUENCE OF SEQUENCE */
1780  if (nla_get_state(nla) <= NLA_STATE_NEGO_TOKEN && credssp_auth_have_output_token(nla->auth))
1781  {
1782  const SecBuffer* buffer = credssp_auth_get_output_buffer(nla->auth);
1783 
1784  if (!WinPrAsn1EncContextualSeqContainer(enc, 1) || !WinPrAsn1EncSeqContainer(enc))
1785  goto fail;
1786 
1787  /* negoToken [0] OCTET STRING */
1788  if (!nla_write_octet_string(enc, buffer, 0, "negoToken"))
1789  goto fail;
1790 
1791  /* End negoTokens (SEQUENCE OF SEQUENCE) */
1792  if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
1793  goto fail;
1794  }
1795 
1796  /* authInfo [2] OCTET STRING */
1797  if (nla->authInfo.cbBuffer > 0)
1798  {
1799  if (!nla_write_octet_string_free(enc, &nla->authInfo, 2, "auth info"))
1800  goto fail;
1801  }
1802 
1803  /* pubKeyAuth [3] OCTET STRING */
1804  if (nla->pubKeyAuth.cbBuffer > 0)
1805  {
1806  if (!nla_write_octet_string_free(enc, &nla->pubKeyAuth, 3, "public key auth"))
1807  goto fail;
1808  }
1809 
1810  /* errorCode [4] INTEGER */
1811  if (nla->errorCode && nla->peerVersion >= 3 && nla->peerVersion != 5)
1812  {
1813  WLog_DBG(TAG, " ----->> error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
1814  nla->errorCode);
1815  if (!WinPrAsn1EncContextualInteger(
1816  enc, 4, WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->errorCode)))
1817  goto fail;
1818  }
1819 
1820  /* clientNonce [5] OCTET STRING */
1821  if (!nla->server && nla->ClientNonce.cbBuffer > 0)
1822  {
1823  if (!nla_write_octet_string(enc, &nla->ClientNonce, 5, "client nonce"))
1824  goto fail;
1825  }
1826 
1827  /* End TSRequest */
1828  if (!WinPrAsn1EncEndContainer(enc))
1829  goto fail;
1830 
1831  if (!WinPrAsn1EncStreamSize(enc, &length))
1832  goto fail;
1833 
1834  s = Stream_New(NULL, length);
1835  if (!s)
1836  goto fail;
1837 
1838  if (!WinPrAsn1EncToStream(enc, s))
1839  goto fail;
1840 
1841  WLog_DBG(TAG, "[%" PRIuz " bytes]", length);
1842  if (transport_write(nla->transport, s) < 0)
1843  goto fail;
1844  rc = TRUE;
1845 
1846 fail:
1847  Stream_Free(s, TRUE);
1848  WinPrAsn1Encoder_Free(&enc);
1849  return rc;
1850 }
1851 
1852 static int nla_decode_ts_request(rdpNla* nla, wStream* s)
1853 {
1854  WinPrAsn1Decoder dec = { 0 };
1855  WinPrAsn1Decoder dec2 = { 0 };
1856  BOOL error = FALSE;
1857  WinPrAsn1_tagId tag = { 0 };
1858  WinPrAsn1_INTEGER val = { 0 };
1859  UINT32 version = 0;
1860 
1861  WINPR_ASSERT(nla);
1862  WINPR_ASSERT(s);
1863 
1864  WinPrAsn1Decoder_Init(&dec, WINPR_ASN1_DER, s);
1865 
1866  WLog_DBG(TAG, "<<----- receiving...");
1867 
1868  /* TSRequest */
1869  const size_t offset = WinPrAsn1DecReadSequence(&dec, &dec2);
1870  if (offset == 0)
1871  return -1;
1872  dec = dec2;
1873 
1874  /* version [0] INTEGER */
1875  if (WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &val) == 0)
1876  return -1;
1877 
1878  if (!Stream_SafeSeek(s, offset))
1879  return -1;
1880 
1881  version = (UINT)val;
1882  WLog_DBG(TAG, " <<----- protocol version %" PRIu32, version);
1883 
1884  if (nla->peerVersion == 0)
1885  nla->peerVersion = version;
1886 
1887  /* if the peer suddenly changed its version - kick it */
1888  if (nla->peerVersion != version)
1889  {
1890  WLog_ERR(TAG, "CredSSP peer changed protocol version from %" PRIu32 " to %" PRIu32,
1891  nla->peerVersion, version);
1892  return -1;
1893  }
1894 
1895  while (WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2) != 0)
1896  {
1897  WinPrAsn1Decoder dec3 = { 0 };
1898  WinPrAsn1_OctetString octet_string = { 0 };
1899 
1900  switch (tag)
1901  {
1902  case 1:
1903  WLog_DBG(TAG, " <<----- nego token");
1904  /* negoTokens [1] SEQUENCE OF SEQUENCE */
1905  if ((WinPrAsn1DecReadSequence(&dec2, &dec3) == 0) ||
1906  (WinPrAsn1DecReadSequence(&dec3, &dec2) == 0))
1907  return -1;
1908  /* negoToken [0] OCTET STRING */
1909  if ((WinPrAsn1DecReadContextualOctetString(&dec2, 0, &error, &octet_string,
1910  FALSE) == 0) &&
1911  error)
1912  return -1;
1913  if (!nla_sec_buffer_alloc_from_data(&nla->negoToken, octet_string.data, 0,
1914  octet_string.len))
1915  return -1;
1916  break;
1917  case 2:
1918  WLog_DBG(TAG, " <<----- auth info");
1919  /* authInfo [2] OCTET STRING */
1920  if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
1921  return -1;
1922  if (!nla_sec_buffer_alloc_from_data(&nla->authInfo, octet_string.data, 0,
1923  octet_string.len))
1924  return -1;
1925  break;
1926  case 3:
1927  WLog_DBG(TAG, " <<----- public key auth");
1928  /* pubKeyAuth [3] OCTET STRING */
1929  if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
1930  return -1;
1931  if (!nla_sec_buffer_alloc_from_data(&nla->pubKeyAuth, octet_string.data, 0,
1932  octet_string.len))
1933  return -1;
1934  break;
1935  case 4:
1936  /* errorCode [4] INTEGER */
1937  if (WinPrAsn1DecReadInteger(&dec2, &val) == 0)
1938  return -1;
1939  nla->errorCode = val;
1940  WLog_DBG(TAG, " <<----- error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
1941  nla->errorCode);
1942  break;
1943  case 5:
1944  WLog_DBG(TAG, " <<----- client nonce");
1945  /* clientNonce [5] OCTET STRING */
1946  if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
1947  return -1;
1948  if (!nla_sec_buffer_alloc_from_data(&nla->ClientNonce, octet_string.data, 0,
1949  octet_string.len))
1950  return -1;
1951  break;
1952  default:
1953  return -1;
1954  }
1955  }
1956 
1957  return 1;
1958 }
1959 
1960 int nla_recv_pdu(rdpNla* nla, wStream* s)
1961 {
1962  WINPR_ASSERT(nla);
1963  WINPR_ASSERT(s);
1964 
1965  if (nla_get_state(nla) == NLA_STATE_EARLY_USER_AUTH)
1966  {
1967  UINT32 code = 0;
1968  Stream_Read_UINT32(s, code);
1969  if (code != AUTHZ_SUCCESS)
1970  {
1971  WLog_DBG(TAG, "Early User Auth active: FAILURE code 0x%08" PRIX32 "", code);
1972  code = FREERDP_ERROR_AUTHENTICATION_FAILED;
1973  freerdp_set_last_error_log(nla->rdpcontext, code);
1974  return -1;
1975  }
1976  else
1977  WLog_DBG(TAG, "Early User Auth active: SUCCESS");
1978  }
1979  else
1980  {
1981  if (nla_decode_ts_request(nla, s) < 1)
1982  return -1;
1983 
1984  if (nla->errorCode)
1985  {
1986  UINT32 code = 0;
1987 
1988  switch (nla->errorCode)
1989  {
1990  case STATUS_PASSWORD_MUST_CHANGE:
1991  code = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE;
1992  break;
1993 
1994  case STATUS_PASSWORD_EXPIRED:
1995  code = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
1996  break;
1997 
1998  case STATUS_ACCOUNT_DISABLED:
1999  code = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED;
2000  break;
2001 
2002  case STATUS_LOGON_FAILURE:
2003  code = FREERDP_ERROR_CONNECT_LOGON_FAILURE;
2004  break;
2005 
2006  case STATUS_WRONG_PASSWORD:
2007  code = FREERDP_ERROR_CONNECT_WRONG_PASSWORD;
2008  break;
2009 
2010  case STATUS_ACCESS_DENIED:
2011  code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
2012  break;
2013 
2014  case STATUS_ACCOUNT_RESTRICTION:
2015  code = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION;
2016  break;
2017 
2018  case STATUS_ACCOUNT_LOCKED_OUT:
2019  code = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT;
2020  break;
2021 
2022  case STATUS_ACCOUNT_EXPIRED:
2023  code = FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED;
2024  break;
2025 
2026  case STATUS_LOGON_TYPE_NOT_GRANTED:
2027  code = FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED;
2028  break;
2029 
2030  default:
2031  WLog_ERR(TAG, "SPNEGO failed with NTSTATUS: %s [0x%08" PRIX32 "]",
2032  NtStatus2Tag(nla->errorCode), nla->errorCode);
2033  code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2034  break;
2035  }
2036 
2037  freerdp_set_last_error_log(nla->rdpcontext, code);
2038  return -1;
2039  }
2040  }
2041 
2042  return nla_client_recv(nla);
2043 }
2044 
2045 int nla_server_recv(rdpNla* nla)
2046 {
2047  int status = -1;
2048 
2049  WINPR_ASSERT(nla);
2050 
2051  wStream* s = nla_server_recv_stream(nla);
2052  if (!s)
2053  goto fail;
2054  status = nla_decode_ts_request(nla, s);
2055 
2056 fail:
2057  Stream_Free(s, TRUE);
2058  return status;
2059 }
2060 
2070 rdpNla* nla_new(rdpContext* context, rdpTransport* transport)
2071 {
2072  WINPR_ASSERT(transport);
2073  WINPR_ASSERT(context);
2074 
2075  rdpSettings* settings = context->settings;
2076  WINPR_ASSERT(settings);
2077 
2078  rdpNla* nla = (rdpNla*)calloc(1, sizeof(rdpNla));
2079 
2080  if (!nla)
2081  return NULL;
2082 
2083  nla->rdpcontext = context;
2084  nla->server = settings->ServerMode;
2085  nla->transport = transport;
2086  nla->sendSeqNum = 0;
2087  nla->recvSeqNum = 0;
2088  nla->version = 6;
2089  nla->earlyUserAuth = FALSE;
2090 
2091  nla->identity = calloc(1, sizeof(SEC_WINNT_AUTH_IDENTITY));
2092  if (!nla->identity)
2093  goto cleanup;
2094 
2095  nla->auth = credssp_auth_new(context);
2096  if (!nla->auth)
2097  goto cleanup;
2098 
2099  /* init to 0 or we end up freeing a bad pointer if the alloc fails */
2100  if (!nla_sec_buffer_alloc(&nla->ClientNonce, NonceLength))
2101  goto cleanup;
2102 
2103  /* generate random 32-byte nonce */
2104  if (winpr_RAND(nla->ClientNonce.pvBuffer, NonceLength) < 0)
2105  goto cleanup;
2106 
2107  return nla;
2108 cleanup:
2109  WINPR_PRAGMA_DIAG_PUSH
2110  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2111  nla_free(nla);
2112  WINPR_PRAGMA_DIAG_POP
2113  return NULL;
2114 }
2115 
2121 void nla_free(rdpNla* nla)
2122 {
2123  if (!nla)
2124  return;
2125 
2126  smartcardCertInfo_Free(nla->smartcardCert);
2127  nla_buffer_free(nla);
2128  sspi_SecBufferFree(&nla->tsCredentials);
2129  credssp_auth_free(nla->auth);
2130 
2131  sspi_FreeAuthIdentity(nla->identity);
2132  free(nla->pkinitArgs);
2133  free(nla->identity);
2134  free(nla);
2135 }
2136 
2137 SEC_WINNT_AUTH_IDENTITY* nla_get_identity(rdpNla* nla)
2138 {
2139  if (!nla)
2140  return NULL;
2141 
2142  return nla->identity;
2143 }
2144 
2145 NLA_STATE nla_get_state(rdpNla* nla)
2146 {
2147  if (!nla)
2148  return NLA_STATE_FINAL;
2149 
2150  return nla->state;
2151 }
2152 
2153 BOOL nla_set_state(rdpNla* nla, NLA_STATE state)
2154 {
2155  if (!nla)
2156  return FALSE;
2157 
2158  WLog_DBG(TAG, "-- %s\t--> %s", nla_get_state_str(nla->state), nla_get_state_str(state));
2159  nla->state = state;
2160  return TRUE;
2161 }
2162 
2163 BOOL nla_set_service_principal(rdpNla* nla, const char* service, const char* hostname)
2164 {
2165  if (!credssp_auth_set_spn(nla->auth, service, hostname))
2166  return FALSE;
2167  return TRUE;
2168 }
2169 
2170 BOOL nla_impersonate(rdpNla* nla)
2171 {
2172  return credssp_auth_impersonate(nla->auth);
2173 }
2174 
2175 BOOL nla_revert_to_self(rdpNla* nla)
2176 {
2177  return credssp_auth_revert_to_self(nla->auth);
2178 }
2179 
2180 const char* nla_get_state_str(NLA_STATE state)
2181 {
2182  switch (state)
2183  {
2184  case NLA_STATE_INITIAL:
2185  return "NLA_STATE_INITIAL";
2186  case NLA_STATE_NEGO_TOKEN:
2187  return "NLA_STATE_NEGO_TOKEN";
2188  case NLA_STATE_PUB_KEY_AUTH:
2189  return "NLA_STATE_PUB_KEY_AUTH";
2190  case NLA_STATE_AUTH_INFO:
2191  return "NLA_STATE_AUTH_INFO";
2192  case NLA_STATE_POST_NEGO:
2193  return "NLA_STATE_POST_NEGO";
2194  case NLA_STATE_EARLY_USER_AUTH:
2195  return "NLA_STATE_EARLY_USER_AUTH";
2196  case NLA_STATE_FINAL:
2197  return "NLA_STATE_FINAL";
2198  default:
2199  return "UNKNOWN";
2200  }
2201 }
2202 
2203 DWORD nla_get_error(rdpNla* nla)
2204 {
2205  if (!nla)
2206  return ERROR_INTERNAL_ERROR;
2207  return (UINT32)nla->errorCode;
2208 }
2209 
2210 INT32 nla_get_sspi_error(rdpNla* nla)
2211 {
2212  WINPR_ASSERT(nla);
2213  return credssp_auth_sspi_error(nla->auth);
2214 }
2215 
2216 BOOL nla_encrypt(rdpNla* nla, const SecBuffer* inBuffer, SecBuffer* outBuffer)
2217 {
2218  WINPR_ASSERT(nla);
2219  WINPR_ASSERT(inBuffer);
2220  WINPR_ASSERT(outBuffer);
2221  return credssp_auth_encrypt(nla->auth, inBuffer, outBuffer, NULL, nla->sendSeqNum++);
2222 }
2223 
2224 BOOL nla_decrypt(rdpNla* nla, const SecBuffer* inBuffer, SecBuffer* outBuffer)
2225 {
2226  WINPR_ASSERT(nla);
2227  WINPR_ASSERT(inBuffer);
2228  WINPR_ASSERT(outBuffer);
2229  return credssp_auth_decrypt(nla->auth, inBuffer, outBuffer, nla->recvSeqNum++);
2230 }
2231 
2232 SECURITY_STATUS nla_QueryContextAttributes(rdpNla* nla, DWORD ulAttr, PVOID pBuffer)
2233 {
2234  WINPR_ASSERT(nla);
2235 
2236  SecurityFunctionTable* table = NULL;
2237  CtxtHandle context = { 0 };
2238  credssp_auth_tableAndContext(nla->auth, &table, &context);
2239 
2240  return table->QueryContextAttributes(&context, ulAttr, pBuffer);
2241 }
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.