24 #include <freerdp/config.h>
26 #include <freerdp/build-config.h>
27 #include <freerdp/peer.h>
29 #include <winpr/crt.h>
30 #include <winpr/wtypes.h>
31 #include <winpr/assert.h>
32 #include <winpr/library.h>
33 #include <winpr/registry.h>
34 #include <winpr/sspi.h>
36 #include <freerdp/log.h>
39 #include "credssp_auth.h"
41 #define TAG FREERDP_TAG("core.auth")
43 #define SERVER_KEY "Software\\" FREERDP_VENDOR_STRING "\\" FREERDP_PRODUCT_STRING "\\Server"
49 AUTH_STATE_IN_PROGRESS,
53 struct rdp_credssp_auth
55 const rdpContext* rdp_ctx;
56 SecurityFunctionTable* table;
58 SEC_WINNT_AUTH_IDENTITY identity;
71 SECURITY_STATUS sspi_error;
72 enum AUTH_STATE state;
76 static const char* credssp_auth_state_string(
const rdpCredsspAuth* auth)
81 case AUTH_STATE_INITIAL:
82 return "AUTH_STATE_INITIAL";
83 case AUTH_STATE_CREDS:
84 return "AUTH_STATE_CREDS";
85 case AUTH_STATE_IN_PROGRESS:
86 return "AUTH_STATE_IN_PROGRESS";
87 case AUTH_STATE_FINAL:
88 return "AUTH_STATE_FINAL";
90 return "AUTH_STATE_UNKNOWN";
93 static BOOL parseKerberosDeltat(
const char* value, INT32* dest,
const char* message);
94 static BOOL credssp_auth_setup_identity(rdpCredsspAuth* auth);
95 static SecurityFunctionTable* auth_resolve_sspi_table(
const rdpSettings* settings);
97 static BOOL credssp_auth_update_name_cache(rdpCredsspAuth* auth, TCHAR* name)
101 free(auth->pkgNameA);
102 auth->pkgNameA = NULL;
105 auth->pkgNameA = ConvertWCharToUtf8Alloc(name, NULL);
107 auth->pkgNameA = _strdup(name);
111 rdpCredsspAuth* credssp_auth_new(
const rdpContext* rdp_ctx)
113 rdpCredsspAuth* auth = calloc(1,
sizeof(rdpCredsspAuth));
116 auth->rdp_ctx = rdp_ctx;
124 WINPR_ASSERT(auth->rdp_ctx);
126 const rdpSettings* settings = auth->rdp_ctx->settings;
127 WINPR_ASSERT(settings);
129 if (!credssp_auth_update_name_cache(auth, pkg_name))
132 auth->table = auth_resolve_sspi_table(settings);
135 WLog_ERR(TAG,
"Unable to initialize sspi table");
140 WINPR_ASSERT(auth->table->QuerySecurityPackageInfo);
141 const SECURITY_STATUS status = auth->table->QuerySecurityPackageInfo(pkg_name, &auth->info);
142 if (status != SEC_E_OK)
144 WLog_ERR(TAG,
"QuerySecurityPackageInfo (%s) failed with %s [0x%08X]",
145 credssp_auth_pkg_name(auth), GetSecurityStatusString(status), status);
149 if (!credssp_auth_update_name_cache(auth, auth->info->Name))
152 WLog_DBG(TAG,
"Using package: %s (cbMaxToken: %u bytes)", credssp_auth_pkg_name(auth),
153 auth->info->cbMaxToken);
156 if (!credssp_auth_setup_identity(auth))
159 auth->bindings = bindings;
164 static BOOL credssp_auth_setup_auth_data(rdpCredsspAuth* auth,
165 const SEC_WINNT_AUTH_IDENTITY* identity,
168 WINPR_ASSERT(pAuthData);
172 identityEx->Version = SEC_WINNT_AUTH_IDENTITY_VERSION;
173 identityEx->Length =
sizeof(SEC_WINNT_AUTH_IDENTITY_EX);
174 identityEx->User = identity->User;
175 identityEx->UserLength = identity->UserLength;
176 identityEx->Domain = identity->Domain;
177 identityEx->DomainLength = identity->DomainLength;
178 identityEx->Password = identity->Password;
179 identityEx->PasswordLength = identity->PasswordLength;
180 identityEx->Flags = identity->Flags;
181 identityEx->Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
182 identityEx->Flags |= SEC_WINNT_AUTH_IDENTITY_EXTENDED;
184 if (auth->package_list)
186 const size_t len = _wcslen(auth->package_list);
187 if (len > UINT32_MAX)
190 identityEx->PackageList = (UINT16*)auth->package_list;
191 identityEx->PackageListLength = (UINT32)len;
194 pAuthData->ntlmSettings = &auth->ntlmSettings;
195 pAuthData->kerberosSettings = &auth->kerberosSettings;
200 static BOOL credssp_auth_client_init_cred_attributes(rdpCredsspAuth* auth)
204 if (!utils_str_is_empty(auth->kerberosSettings.kdcUrl))
206 SECURITY_STATUS status = ERROR_INTERNAL_ERROR;
207 SSIZE_T str_size = 0;
209 str_size = ConvertUtf8ToWChar(auth->kerberosSettings.kdcUrl, NULL, 0);
210 if ((str_size <= 0) || (str_size <= UINT16_MAX / 2))
214 const size_t buffer_size =
216 if (buffer_size > UINT32_MAX)
222 secAttr->Version = KDC_PROXY_SETTINGS_V1;
223 secAttr->ProxyServerLength = (UINT16)((
size_t)str_size *
sizeof(WCHAR));
226 if (ConvertUtf8ToWChar(auth->kerberosSettings.kdcUrl, (WCHAR*)(secAttr + 1),
227 (
size_t)str_size) <= 0)
234 if (auth->table->SetCredentialsAttributesW)
235 status = auth->table->SetCredentialsAttributesW(&auth->credentials,
236 SECPKG_CRED_ATTR_KDC_PROXY_SETTINGS,
237 (
void*)secAttr, (UINT32)buffer_size);
239 status = SEC_E_UNSUPPORTED_FUNCTION;
241 if (auth->table->SetCredentialsAttributesA)
242 status = auth->table->SetCredentialsAttributesA(&auth->credentials,
243 SECPKG_CRED_ATTR_KDC_PROXY_SETTINGS,
244 (
void*)secAttr, (UINT32)buffer_size);
246 status = SEC_E_UNSUPPORTED_FUNCTION;
249 if (status != SEC_E_OK)
251 WLog_WARN(TAG,
"Explicit Kerberos KDC URL (%s) injection is not supported",
252 auth->kerberosSettings.kdcUrl);
261 BOOL credssp_auth_setup_client(rdpCredsspAuth* auth,
const char* target_service,
262 const char* target_hostname,
const SEC_WINNT_AUTH_IDENTITY* identity,
265 void* pAuthData = NULL;
269 WINPR_ASSERT(auth->table);
270 WINPR_ASSERT(auth->info);
272 WINPR_ASSERT(auth->state == AUTH_STATE_INITIAL);
275 if (!credssp_auth_set_spn(auth, target_service, target_hostname))
280 credssp_auth_setup_auth_data(auth, identity, &winprAuthData);
284 auth->kerberosSettings.pkinitX509Identity = _strdup(pkinit);
285 if (!auth->kerberosSettings.pkinitX509Identity)
287 WLog_ERR(TAG,
"unable to copy pkinitArgs");
292 pAuthData = (
void*)&winprAuthData;
295 WINPR_ASSERT(auth->table->AcquireCredentialsHandle);
296 const SECURITY_STATUS status =
297 auth->table->AcquireCredentialsHandle(NULL, auth->info->Name, SECPKG_CRED_OUTBOUND, NULL,
298 pAuthData, NULL, NULL, &auth->credentials, NULL);
300 if (status != SEC_E_OK)
302 WLog_ERR(TAG,
"AcquireCredentialsHandleA failed with %s [0x%08X]",
303 GetSecurityStatusString(status), status);
307 if (!credssp_auth_client_init_cred_attributes(auth))
309 WLog_ERR(TAG,
"Fatal error setting credential attributes");
313 auth->state = AUTH_STATE_CREDS;
314 WLog_DBG(TAG,
"Acquired client credentials");
319 BOOL credssp_auth_setup_server(rdpCredsspAuth* auth)
321 void* pAuthData = NULL;
325 WINPR_ASSERT(auth->table);
327 WINPR_ASSERT(auth->state == AUTH_STATE_INITIAL);
329 if (auth->ntlmSettings.samFile || auth->ntlmSettings.hashCallback ||
330 auth->kerberosSettings.keytab)
332 credssp_auth_setup_auth_data(auth, &auth->identity, &winprAuthData);
333 pAuthData = &winprAuthData;
336 WINPR_ASSERT(auth->table->AcquireCredentialsHandle);
337 const SECURITY_STATUS status =
338 auth->table->AcquireCredentialsHandle(NULL, auth->info->Name, SECPKG_CRED_INBOUND, NULL,
339 pAuthData, NULL, NULL, &auth->credentials, NULL);
340 if (status != SEC_E_OK)
342 WLog_ERR(TAG,
"AcquireCredentialsHandleA failed with %s [0x%08X]",
343 GetSecurityStatusString(status), status);
347 auth->state = AUTH_STATE_CREDS;
348 WLog_DBG(TAG,
"Acquired server credentials");
355 void credssp_auth_set_flags(rdpCredsspAuth* auth, ULONG flags)
399 int credssp_auth_authenticate(rdpCredsspAuth* auth)
401 SECURITY_STATUS status = ERROR_INTERNAL_ERROR;
403 SecBufferDesc input_buffer_desc = { SECBUFFER_VERSION, 1, input_buffers };
407 WINPR_ASSERT(auth->table);
409 SecBufferDesc output_buffer_desc = { SECBUFFER_VERSION, 1, &auth->output_buffer };
413 case AUTH_STATE_CREDS:
414 case AUTH_STATE_IN_PROGRESS:
416 case AUTH_STATE_INITIAL:
417 case AUTH_STATE_FINAL:
418 WLog_ERR(TAG,
"context in invalid state!");
426 context = &auth->context;
427 if (!auth->context.dwLower && !auth->context.dwUpper)
430 input_buffers[0] = auth->input_buffer;
434 input_buffer_desc.cBuffers = 2;
436 input_buffers[1].BufferType = SECBUFFER_CHANNEL_BINDINGS;
437 input_buffers[1].cbBuffer = auth->bindings->BindingsLength;
438 input_buffers[1].pvBuffer = auth->bindings->Bindings;
442 sspi_SecBufferFree(&auth->output_buffer);
443 auth->output_buffer.BufferType = SECBUFFER_TOKEN;
444 if (!sspi_SecBufferAlloc(&auth->output_buffer, auth->info->cbMaxToken))
449 WINPR_ASSERT(auth->table->AcceptSecurityContext);
450 status = auth->table->AcceptSecurityContext(
451 &auth->credentials, context, &input_buffer_desc, auth->flags, SECURITY_NATIVE_DREP,
452 &auth->context, &output_buffer_desc, &auth->flags, NULL);
456 WINPR_ASSERT(auth->table->InitializeSecurityContext);
457 status = auth->table->InitializeSecurityContext(
458 &auth->credentials, context, auth->spn, auth->flags, 0, SECURITY_NATIVE_DREP,
459 &input_buffer_desc, 0, &auth->context, &output_buffer_desc, &auth->flags, NULL);
462 if (status == SEC_E_OK)
464 WLog_DBG(TAG,
"Authentication complete (output token size: %" PRIu32
" bytes)",
465 auth->output_buffer.cbBuffer);
466 auth->state = AUTH_STATE_FINAL;
470 WINPR_ASSERT(auth->table->QueryContextAttributes);
472 auth->table->QueryContextAttributes(&auth->context, SECPKG_ATTR_SIZES, &auth->sizes);
473 WLog_DBG(TAG,
"QueryContextAttributes returned %s [0x%08" PRIx32
"]",
474 GetSecurityStatusString(status), status);
475 WLog_DBG(TAG,
"Context sizes: cbMaxSignature=%d, cbSecurityTrailer=%d",
476 auth->sizes.cbMaxSignature, auth->sizes.cbSecurityTrailer);
480 else if (status == SEC_I_CONTINUE_NEEDED)
482 WLog_DBG(TAG,
"Authentication in progress... (output token size: %" PRIu32
")",
483 auth->output_buffer.cbBuffer);
484 auth->state = AUTH_STATE_IN_PROGRESS;
489 WLog_ERR(TAG,
"%s failed with %s [0x%08X]",
490 auth->server ?
"AcceptSecurityContext" :
"InitializeSecurityContext",
491 GetSecurityStatusString(status), status);
492 auth->sspi_error = status;
498 BOOL credssp_auth_encrypt(rdpCredsspAuth* auth,
const SecBuffer* plaintext,
SecBuffer* ciphertext,
499 size_t* signature_length, ULONG sequence)
501 SECURITY_STATUS status = ERROR_INTERNAL_ERROR;
503 SecBufferDesc buffer_desc = { SECBUFFER_VERSION, 2, buffers };
506 WINPR_ASSERT(auth && auth->table);
507 WINPR_ASSERT(plaintext);
508 WINPR_ASSERT(ciphertext);
512 case AUTH_STATE_INITIAL:
513 WLog_ERR(TAG,
"Invalid state %s", credssp_auth_state_string(auth));
520 buf = calloc(1, plaintext->cbBuffer + auth->sizes.cbSecurityTrailer);
524 buffers[0].BufferType = SECBUFFER_TOKEN;
525 buffers[0].cbBuffer = auth->sizes.cbSecurityTrailer;
526 buffers[0].pvBuffer = buf;
528 buffers[1].BufferType = SECBUFFER_DATA;
529 if (plaintext->BufferType & SECBUFFER_READONLY)
530 buffers[1].BufferType |= SECBUFFER_READONLY;
531 buffers[1].pvBuffer = buf + auth->sizes.cbSecurityTrailer;
532 buffers[1].cbBuffer = plaintext->cbBuffer;
533 CopyMemory(buffers[1].pvBuffer, plaintext->pvBuffer, plaintext->cbBuffer);
535 WINPR_ASSERT(auth->table->EncryptMessage);
536 status = auth->table->EncryptMessage(&auth->context, 0, &buffer_desc, sequence);
537 if (status != SEC_E_OK)
539 WLog_ERR(TAG,
"EncryptMessage failed with %s [0x%08X]", GetSecurityStatusString(status),
545 if (buffers[0].cbBuffer < auth->sizes.cbSecurityTrailer)
548 MoveMemory(((BYTE*)buffers[0].pvBuffer) + buffers[0].cbBuffer, buffers[1].pvBuffer,
549 buffers[1].cbBuffer);
551 auth->sizes.cbSecurityTrailer = buffers[0].cbBuffer;
554 ciphertext->cbBuffer = buffers[0].cbBuffer + buffers[1].cbBuffer;
555 ciphertext->pvBuffer = buf;
557 if (signature_length)
558 *signature_length = buffers[0].cbBuffer;
564 BOOL credssp_auth_decrypt(rdpCredsspAuth* auth,
const SecBuffer* ciphertext,
SecBuffer* plaintext,
568 SecBufferDesc buffer_desc = { SECBUFFER_VERSION, 2, buffers };
571 WINPR_ASSERT(auth && auth->table);
572 WINPR_ASSERT(ciphertext);
573 WINPR_ASSERT(plaintext);
577 case AUTH_STATE_INITIAL:
578 WLog_ERR(TAG,
"Invalid state %s", credssp_auth_state_string(auth));
585 if (ciphertext->cbBuffer < auth->sizes.cbSecurityTrailer)
587 WLog_ERR(TAG,
"Encrypted message buffer too small");
593 buffers[0].BufferType = SECBUFFER_TOKEN;
594 buffers[0].pvBuffer = ciphertext->pvBuffer;
595 buffers[0].cbBuffer = auth->sizes.cbSecurityTrailer;
597 buffers[1].BufferType = SECBUFFER_DATA;
598 if (!sspi_SecBufferAlloc(&buffers[1], ciphertext->cbBuffer - auth->sizes.cbSecurityTrailer))
600 CopyMemory(buffers[1].pvBuffer, (BYTE*)ciphertext->pvBuffer + auth->sizes.cbSecurityTrailer,
601 buffers[1].cbBuffer);
603 WINPR_ASSERT(auth->table->DecryptMessage);
604 const SECURITY_STATUS status =
605 auth->table->DecryptMessage(&auth->context, &buffer_desc, sequence, &fqop);
606 if (status != SEC_E_OK)
608 WLog_ERR(TAG,
"DecryptMessage failed with %s [0x%08X]", GetSecurityStatusString(status),
610 sspi_SecBufferFree(&buffers[1]);
614 *plaintext = buffers[1];
619 BOOL credssp_auth_impersonate(rdpCredsspAuth* auth)
621 WINPR_ASSERT(auth && auth->table);
623 WINPR_ASSERT(auth->table->ImpersonateSecurityContext);
624 const SECURITY_STATUS status = auth->table->ImpersonateSecurityContext(&auth->context);
626 if (status != SEC_E_OK)
628 WLog_ERR(TAG,
"ImpersonateSecurityContext failed with %s [0x%08X]",
629 GetSecurityStatusString(status), status);
636 BOOL credssp_auth_revert_to_self(rdpCredsspAuth* auth)
638 WINPR_ASSERT(auth && auth->table);
640 WINPR_ASSERT(auth->table->RevertSecurityContext);
641 const SECURITY_STATUS status = auth->table->RevertSecurityContext(&auth->context);
643 if (status != SEC_E_OK)
645 WLog_ERR(TAG,
"RevertSecurityContext failed with %s [0x%08X]",
646 GetSecurityStatusString(status), status);
653 void credssp_auth_take_input_buffer(rdpCredsspAuth* auth,
SecBuffer* buffer)
656 WINPR_ASSERT(buffer);
658 sspi_SecBufferFree(&auth->input_buffer);
660 auth->input_buffer = *buffer;
661 auth->input_buffer.BufferType = SECBUFFER_TOKEN;
668 const SecBuffer* credssp_auth_get_output_buffer(rdpCredsspAuth* auth)
671 return &auth->output_buffer;
674 BOOL credssp_auth_have_output_token(rdpCredsspAuth* auth)
677 return auth->output_buffer.cbBuffer ? TRUE : FALSE;
680 BOOL credssp_auth_is_complete(rdpCredsspAuth* auth)
683 return auth->state == AUTH_STATE_FINAL;
686 size_t credssp_auth_trailer_size(rdpCredsspAuth* auth)
689 return auth->sizes.cbSecurityTrailer;
692 const char* credssp_auth_pkg_name(rdpCredsspAuth* auth)
694 WINPR_ASSERT(auth && auth->info);
695 return auth->pkgNameA;
698 UINT32 credssp_auth_sspi_error(rdpCredsspAuth* auth)
701 return (UINT32)auth->sspi_error;
704 void credssp_auth_tableAndContext(rdpCredsspAuth* auth, SecurityFunctionTable** ptable,
708 WINPR_ASSERT(ptable);
709 WINPR_ASSERT(pcontext);
711 *ptable = auth->table;
712 *pcontext = auth->context;
715 void credssp_auth_free(rdpCredsspAuth* auth)
727 case AUTH_STATE_IN_PROGRESS:
728 case AUTH_STATE_FINAL:
729 WINPR_ASSERT(auth->table->DeleteSecurityContext);
730 auth->table->DeleteSecurityContext(&auth->context);
733 case AUTH_STATE_CREDS:
734 WINPR_ASSERT(auth->table->FreeCredentialsHandle);
735 auth->table->FreeCredentialsHandle(&auth->credentials);
737 case AUTH_STATE_INITIAL:
744 WINPR_ASSERT(auth->table->FreeContextBuffer);
745 auth->table->FreeContextBuffer(auth->info);
749 sspi_FreeAuthIdentity(&auth->identity);
751 krb_settings = &auth->kerberosSettings;
752 ntlm_settings = &auth->ntlmSettings;
754 free(krb_settings->kdcUrl);
755 free(krb_settings->cache);
756 free(krb_settings->keytab);
757 free(krb_settings->armorCache);
758 free(krb_settings->pkinitX509Anchors);
759 free(krb_settings->pkinitX509Identity);
760 free(ntlm_settings->samFile);
762 free(auth->package_list);
764 sspi_SecBufferFree(&auth->input_buffer);
765 sspi_SecBufferFree(&auth->output_buffer);
766 credssp_auth_update_name_cache(auth, NULL);
770 static void auth_get_sspi_module_from_reg(
char** sspi_module)
776 WINPR_ASSERT(sspi_module);
779 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, SERVER_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey) !=
783 if (RegQueryValueExA(hKey,
"SspiModule", NULL, &dwType, NULL, &dwSize) != ERROR_SUCCESS)
789 char* module = (LPSTR)calloc(dwSize +
sizeof(CHAR),
sizeof(char));
796 if (RegQueryValueExA(hKey,
"SspiModule", NULL, &dwType, (BYTE*)module, &dwSize) !=
805 *sspi_module = module;
808 static SecurityFunctionTable* auth_resolve_sspi_table(
const rdpSettings* settings)
810 char* sspi_module = NULL;
812 WINPR_ASSERT(settings);
814 if (settings->ServerMode)
815 auth_get_sspi_module_from_reg(&sspi_module);
817 if (sspi_module || settings->SspiModule)
819 const char* module_name = sspi_module ? sspi_module : settings->SspiModule;
821 const char* proc_name =
"InitSecurityInterfaceW";
823 const char* proc_name =
"InitSecurityInterfaceA";
826 HMODULE hSSPI = LoadLibraryX(module_name);
830 WLog_ERR(TAG,
"Failed to load SSPI module: %s", module_name);
835 WLog_INFO(TAG,
"Using SSPI Module: %s", module_name);
837 INIT_SECURITY_INTERFACE InitSecurityInterface_ptr =
838 GetProcAddressAs(hSSPI, proc_name, INIT_SECURITY_INTERFACE);
839 if (!InitSecurityInterface_ptr)
841 WLog_ERR(TAG,
"Failed to load SSPI module: %s, no function %s", module_name, proc_name);
846 return InitSecurityInterface_ptr();
849 return InitSecurityInterfaceEx(0);
852 static BOOL credssp_auth_setup_identity(rdpCredsspAuth* auth)
854 const rdpSettings* settings = NULL;
857 freerdp_peer* peer = NULL;
860 WINPR_ASSERT(auth->rdp_ctx);
862 peer = auth->rdp_ctx->peer;
863 settings = auth->rdp_ctx->settings;
864 WINPR_ASSERT(settings);
866 krb_settings = &auth->kerberosSettings;
867 ntlm_settings = &auth->ntlmSettings;
869 if (settings->KerberosLifeTime)
870 parseKerberosDeltat(settings->KerberosLifeTime, &krb_settings->lifeTime,
"lifetime");
871 if (settings->KerberosStartTime)
872 parseKerberosDeltat(settings->KerberosStartTime, &krb_settings->startTime,
"starttime");
873 if (settings->KerberosRenewableLifeTime)
874 parseKerberosDeltat(settings->KerberosRenewableLifeTime, &krb_settings->renewLifeTime,
877 if (settings->KerberosKdcUrl)
879 krb_settings->kdcUrl = _strdup(settings->KerberosKdcUrl);
880 if (!krb_settings->kdcUrl)
882 WLog_ERR(TAG,
"unable to copy kdcUrl");
887 if (settings->KerberosCache)
889 krb_settings->cache = _strdup(settings->KerberosCache);
890 if (!krb_settings->cache)
892 WLog_ERR(TAG,
"unable to copy cache name");
897 if (settings->KerberosKeytab)
899 krb_settings->keytab = _strdup(settings->KerberosKeytab);
900 if (!krb_settings->keytab)
902 WLog_ERR(TAG,
"unable to copy keytab name");
907 if (settings->KerberosArmor)
909 krb_settings->armorCache = _strdup(settings->KerberosArmor);
910 if (!krb_settings->armorCache)
912 WLog_ERR(TAG,
"unable to copy armorCache");
917 if (settings->PkinitAnchors)
919 krb_settings->pkinitX509Anchors = _strdup(settings->PkinitAnchors);
920 if (!krb_settings->pkinitX509Anchors)
922 WLog_ERR(TAG,
"unable to copy pkinitX509Anchors");
927 if (settings->NtlmSamFile)
929 ntlm_settings->samFile = _strdup(settings->NtlmSamFile);
930 if (!ntlm_settings->samFile)
932 WLog_ERR(TAG,
"unable to copy samFile");
937 if (peer && peer->SspiNtlmHashCallback)
939 ntlm_settings->hashCallback = peer->SspiNtlmHashCallback;
940 ntlm_settings->hashCallbackArg = peer;
943 if (settings->AuthenticationPackageList)
945 auth->package_list = ConvertUtf8ToWCharAlloc(settings->AuthenticationPackageList, NULL);
946 if (!auth->package_list)
950 auth->identity.Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
951 auth->identity.Flags |= SEC_WINNT_AUTH_IDENTITY_EXTENDED;
956 BOOL credssp_auth_set_spn(rdpCredsspAuth* auth,
const char* service,
const char* hostname)
967 spn = _strdup(hostname);
970 length = strlen(service) + strlen(hostname) + 2;
971 spn = calloc(length + 1,
sizeof(
char));
975 (void)sprintf_s(spn, length,
"%s/%s", service, hostname);
981 auth->spn = ConvertUtf8ToWCharAlloc(spn, NULL);
990 static const char* parseInt(
const char* v, INT32* r)
995 if (!*v || !((*v >=
'0') && (*v <=
'9')))
998 for (; *v && (*v >=
'0') && (*v <=
'9'); v++)
1000 *r = (*r * 10) + (*v -
'0');
1006 static BOOL parseKerberosDeltat(
const char* value, INT32* dest,
const char* message)
1009 const char* ptr = NULL;
1011 WINPR_ASSERT(value);
1013 WINPR_ASSERT(message);
1020 ptr = strchr(value,
':');
1025 value = parseInt(value, &v);
1026 if (!value || *value !=
':')
1028 WLog_ERR(TAG,
"Invalid value for %s", message);
1034 value = parseInt(value + 1, &v);
1035 if (!value || (*value != 0 && *value !=
':') || (v > 60))
1037 WLog_ERR(TAG,
"Invalid value for %s", message);
1045 value = parseInt(value + 1, &v);
1046 if (!value || (*value != 0) || (v > 60))
1048 WLog_ERR(TAG,
"Invalid value for %s", message);
1057 value = parseInt(value, &v);
1060 WLog_ERR(TAG,
"Invalid value for %s", message);
1064 if (!*value || isspace(*value))
1096 WLog_ERR(TAG,
"invalid value for unit %c when parsing %s", *value, message);
1100 if ((maxValue > 0) && (v > maxValue))
1102 WLog_ERR(TAG,
"invalid value for unit %c when parsing %s", *value, message);
1106 *dest += (v * factor);
1111 value = parseInt(value, &v);
1112 if (!value || !*value)
1114 WLog_ERR(TAG,
"Invalid value for %s", message);