24#include <freerdp/config.h>
26#include <freerdp/build-config.h>
27#include <freerdp/peer.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\\%s\\Server"
49 AUTH_STATE_IN_PROGRESS,
53struct 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;
76static 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";
93static BOOL parseKerberosDeltat(
const char* value, INT32* dest,
const char* message);
94static BOOL credssp_auth_setup_identity(rdpCredsspAuth* auth);
95static SecurityFunctionTable* auth_resolve_sspi_table(
const rdpSettings* settings);
97#define log_status(status, level, ...) \
98 log_status_((status), (level), __FILE__, __func__, __LINE__, __VA_ARGS__)
100WINPR_ATTR_FORMAT_ARG(6, 7)
101static BOOL log_status_(SECURITY_STATUS status, DWORD level, const
char* file, const
char* fkt,
102 size_t line, WINPR_FORMAT_ARG const
char* what, ...)
104 static wLog* log =
nullptr;
108 if (WLog_IsLevelActive(log, level))
110 char fwhat[128] = WINPR_C_ARRAY_INIT;
111 va_list ap = WINPR_C_ARRAY_INIT;
113 (void)vsnprintf(fwhat,
sizeof(fwhat) - 1, what, ap);
116 WLog_PrintTextMessage(log, level, line, file, fkt,
"%s status %s [0x%08" PRIx32
"]", fwhat,
117 GetSecurityStatusString(status),
118 WINPR_CXX_COMPAT_CAST(uint32_t, status));
124static BOOL credssp_auth_update_name_cache(rdpCredsspAuth* auth, TCHAR* name)
128 free(auth->pkgNameA);
129 auth->pkgNameA =
nullptr;
132 auth->pkgNameA = ConvertWCharToUtf8Alloc(name,
nullptr);
134 auth->pkgNameA = _strdup(name);
138rdpCredsspAuth* credssp_auth_new(
const rdpContext* context)
140 WINPR_ASSERT(context);
141 rdpCredsspAuth* auth = calloc(1,
sizeof(rdpCredsspAuth));
144 auth->rdp_ctx = context;
152 WINPR_ASSERT(auth->rdp_ctx);
154 const rdpSettings* settings = auth->rdp_ctx->settings;
155 WINPR_ASSERT(settings);
157 if (!credssp_auth_update_name_cache(auth, pkg_name))
160 auth->table = auth_resolve_sspi_table(settings);
163 WLog_ERR(TAG,
"Unable to initialize sspi table");
168 WINPR_ASSERT(auth->table->QuerySecurityPackageInfo);
169 const SECURITY_STATUS status = auth->table->QuerySecurityPackageInfo(pkg_name, &auth->info);
170 if (status != SEC_E_OK)
171 return log_status(status, WLOG_ERROR,
"QuerySecurityPackageInfo (%s)",
172 credssp_auth_pkg_name(auth));
174 if (!credssp_auth_update_name_cache(auth, auth->info->Name))
177 WLog_DBG(TAG,
"Using package: %s (cbMaxToken: %u bytes)", credssp_auth_pkg_name(auth),
178 auth->info->cbMaxToken);
181 if (!credssp_auth_setup_identity(auth))
184 auth->bindings = bindings;
189static BOOL credssp_auth_setup_auth_data(rdpCredsspAuth* auth,
190 const SEC_WINNT_AUTH_IDENTITY* identity,
193 WINPR_ASSERT(pAuthData);
197 identityEx->Version = SEC_WINNT_AUTH_IDENTITY_VERSION;
198 identityEx->Length =
sizeof(SEC_WINNT_AUTH_IDENTITY_EX);
199 identityEx->User = identity->User;
200 identityEx->UserLength = identity->UserLength;
201 identityEx->Domain = identity->Domain;
202 identityEx->DomainLength = identity->DomainLength;
203 identityEx->Password = identity->Password;
204 identityEx->PasswordLength = identity->PasswordLength;
205 identityEx->Flags = identity->Flags;
206 identityEx->Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
207 identityEx->Flags |= SEC_WINNT_AUTH_IDENTITY_EXTENDED;
209 if (auth->package_list)
211 const size_t len = _wcslen(auth->package_list);
212 if (len > UINT32_MAX)
215 identityEx->PackageList = (UINT16*)auth->package_list;
216 identityEx->PackageListLength = (UINT32)len;
219 pAuthData->ntlmSettings = &auth->ntlmSettings;
220 pAuthData->kerberosSettings = &auth->kerberosSettings;
225static BOOL credssp_auth_client_init_cred_attributes(rdpCredsspAuth* auth)
229 if (!utils_str_is_empty(auth->kerberosSettings.kdcUrl))
231 SECURITY_STATUS status = ERROR_INTERNAL_ERROR;
232 SSIZE_T str_size = 0;
234 str_size = ConvertUtf8ToWChar(auth->kerberosSettings.kdcUrl,
nullptr, 0);
235 if ((str_size <= 0) || (str_size >= UINT16_MAX / 2))
239 const size_t buffer_size =
241 if (buffer_size > UINT32_MAX)
247 secAttr->Version = KDC_PROXY_SETTINGS_V1;
248 secAttr->ProxyServerLength = (UINT16)((
size_t)str_size *
sizeof(WCHAR));
251 if (ConvertUtf8ToWChar(auth->kerberosSettings.kdcUrl, (WCHAR*)(secAttr + 1),
252 (
size_t)str_size) <= 0)
259 if (auth->table->SetCredentialsAttributesW)
260 status = auth->table->SetCredentialsAttributesW(&auth->credentials,
261 SECPKG_CRED_ATTR_KDC_PROXY_SETTINGS,
262 (
void*)secAttr, (UINT32)buffer_size);
264 status = SEC_E_UNSUPPORTED_FUNCTION;
266 if (auth->table->SetCredentialsAttributesA)
267 status = auth->table->SetCredentialsAttributesA(&auth->credentials,
268 SECPKG_CRED_ATTR_KDC_PROXY_SETTINGS,
269 (
void*)secAttr, (UINT32)buffer_size);
271 status = SEC_E_UNSUPPORTED_FUNCTION;
274 if (status != SEC_E_OK)
276 WLog_WARN(TAG,
"Explicit Kerberos KDC URL (%s) injection is not supported",
277 auth->kerberosSettings.kdcUrl);
286BOOL credssp_auth_setup_client(rdpCredsspAuth* auth,
const char* target_service,
287 const char* target_hostname,
const SEC_WINNT_AUTH_IDENTITY* identity,
290 void* pAuthData =
nullptr;
294 WINPR_ASSERT(auth->table);
295 WINPR_ASSERT(auth->info);
297 WINPR_ASSERT(auth->state == AUTH_STATE_INITIAL);
300 if (!credssp_auth_set_spn(auth, target_service, target_hostname))
305 credssp_auth_setup_auth_data(auth, identity, &winprAuthData);
309 auth->kerberosSettings.pkinitX509Identity = _strdup(pkinit);
310 if (!auth->kerberosSettings.pkinitX509Identity)
312 WLog_ERR(TAG,
"unable to copy pkinitArgs");
317 pAuthData = (
void*)&winprAuthData;
320 WINPR_ASSERT(auth->table->AcquireCredentialsHandle);
321 const SECURITY_STATUS status = auth->table->AcquireCredentialsHandle(
322 nullptr, auth->info->Name, SECPKG_CRED_OUTBOUND,
nullptr, pAuthData,
nullptr,
nullptr,
323 &auth->credentials,
nullptr);
325 if (status != SEC_E_OK)
326 return log_status(status, WLOG_ERROR,
"AcquireCredentialsHandleA");
328 if (!credssp_auth_client_init_cred_attributes(auth))
330 WLog_ERR(TAG,
"Fatal error setting credential attributes");
334 auth->state = AUTH_STATE_CREDS;
335 WLog_DBG(TAG,
"Acquired client credentials");
340BOOL credssp_auth_setup_server(rdpCredsspAuth* auth)
342 void* pAuthData =
nullptr;
346 WINPR_ASSERT(auth->table);
348 WINPR_ASSERT(auth->state == AUTH_STATE_INITIAL);
350 if (auth->ntlmSettings.samFile || auth->ntlmSettings.hashCallback ||
351 auth->kerberosSettings.keytab)
353 credssp_auth_setup_auth_data(auth, &auth->identity, &winprAuthData);
354 pAuthData = &winprAuthData;
357 WINPR_ASSERT(auth->table->AcquireCredentialsHandle);
358 const SECURITY_STATUS status = auth->table->AcquireCredentialsHandle(
359 nullptr, auth->info->Name, SECPKG_CRED_INBOUND,
nullptr, pAuthData,
nullptr,
nullptr,
360 &auth->credentials,
nullptr);
361 if (status != SEC_E_OK)
362 return log_status(status, WLOG_ERROR,
"AcquireCredentialsHandleA");
364 auth->state = AUTH_STATE_CREDS;
365 WLog_DBG(TAG,
"Acquired server credentials");
372void credssp_auth_set_flags(rdpCredsspAuth* auth, ULONG flags)
416int credssp_auth_authenticate(rdpCredsspAuth* auth)
418 SECURITY_STATUS status = ERROR_INTERNAL_ERROR;
419 SecBuffer input_buffers[2] = WINPR_C_ARRAY_INIT;
420 SecBufferDesc input_buffer_desc = { SECBUFFER_VERSION, 1, input_buffers };
424 WINPR_ASSERT(auth->table);
426 SecBufferDesc output_buffer_desc = { SECBUFFER_VERSION, 1, &auth->output_buffer };
430 case AUTH_STATE_CREDS:
431 case AUTH_STATE_IN_PROGRESS:
433 case AUTH_STATE_INITIAL:
434 case AUTH_STATE_FINAL:
435 WLog_ERR(TAG,
"context in invalid state!");
443 context = &auth->context;
444 if (!auth->context.dwLower && !auth->context.dwUpper)
447 input_buffers[0] = auth->input_buffer;
451 input_buffer_desc.cBuffers = 2;
453 input_buffers[1].BufferType = SECBUFFER_CHANNEL_BINDINGS;
454 input_buffers[1].cbBuffer = auth->bindings->BindingsLength;
455 input_buffers[1].pvBuffer = auth->bindings->Bindings;
459 sspi_SecBufferFree(&auth->output_buffer);
460 auth->output_buffer.BufferType = SECBUFFER_TOKEN;
461 if (!sspi_SecBufferAlloc(&auth->output_buffer, auth->info->cbMaxToken))
466 WINPR_ASSERT(auth->table->AcceptSecurityContext);
467 status = auth->table->AcceptSecurityContext(
468 &auth->credentials, context, &input_buffer_desc, auth->flags, SECURITY_NATIVE_DREP,
469 &auth->context, &output_buffer_desc, &auth->flags,
nullptr);
473 WINPR_ASSERT(auth->table->InitializeSecurityContext);
474 status = auth->table->InitializeSecurityContext(
475 &auth->credentials, context, auth->spn, auth->flags, 0, SECURITY_NATIVE_DREP,
476 &input_buffer_desc, 0, &auth->context, &output_buffer_desc, &auth->flags,
nullptr);
479 if (status == SEC_E_OK)
481 WLog_DBG(TAG,
"Authentication complete (output token size: %" PRIu32
" bytes)",
482 auth->output_buffer.cbBuffer);
483 auth->state = AUTH_STATE_FINAL;
487 WINPR_ASSERT(auth->table->QueryContextAttributes);
489 auth->table->QueryContextAttributes(&auth->context, SECPKG_ATTR_SIZES, &auth->sizes);
490 (void)log_status(status, WLOG_DEBUG,
"QueryContextAttributes");
491 WLog_DBG(TAG,
"Context sizes: cbMaxSignature=%" PRIu32
", cbSecurityTrailer=%" PRIu32
"",
492 auth->sizes.cbMaxSignature, auth->sizes.cbSecurityTrailer);
496 else if (status == SEC_I_CONTINUE_NEEDED)
498 WLog_DBG(TAG,
"Authentication in progress... (output token size: %" PRIu32
")",
499 auth->output_buffer.cbBuffer);
500 auth->state = AUTH_STATE_IN_PROGRESS;
505 (void)log_status(status, WLOG_ERROR,
506 auth->server ?
"AcceptSecurityContext" :
"InitializeSecurityContext");
507 auth->sspi_error = status;
513BOOL credssp_auth_encrypt(rdpCredsspAuth* auth,
const SecBuffer* plaintext,
SecBuffer* ciphertext,
514 size_t* signature_length, ULONG sequence)
516 SECURITY_STATUS status = ERROR_INTERNAL_ERROR;
517 SecBuffer buffers[2] = WINPR_C_ARRAY_INIT;
518 SecBufferDesc buffer_desc = { SECBUFFER_VERSION, 2, buffers };
521 WINPR_ASSERT(auth && auth->table);
522 WINPR_ASSERT(plaintext);
523 WINPR_ASSERT(ciphertext);
527 case AUTH_STATE_INITIAL:
528 WLog_ERR(TAG,
"Invalid state %s", credssp_auth_state_string(auth));
535 buf = calloc(1, plaintext->cbBuffer + auth->sizes.cbSecurityTrailer);
539 buffers[0].BufferType = SECBUFFER_TOKEN;
540 buffers[0].cbBuffer = auth->sizes.cbSecurityTrailer;
541 buffers[0].pvBuffer = buf;
543 buffers[1].BufferType = SECBUFFER_DATA;
544 if (plaintext->BufferType & SECBUFFER_READONLY)
545 buffers[1].BufferType |= SECBUFFER_READONLY;
546 buffers[1].pvBuffer = buf + auth->sizes.cbSecurityTrailer;
547 buffers[1].cbBuffer = plaintext->cbBuffer;
548 CopyMemory(buffers[1].pvBuffer, plaintext->pvBuffer, plaintext->cbBuffer);
550 WINPR_ASSERT(auth->table->EncryptMessage);
551 status = auth->table->EncryptMessage(&auth->context, 0, &buffer_desc, sequence);
552 if (status != SEC_E_OK)
555 return log_status(status, WLOG_ERROR,
"EncryptMessage");
558 if (buffers[0].cbBuffer < auth->sizes.cbSecurityTrailer)
561 MoveMemory(((BYTE*)buffers[0].pvBuffer) + buffers[0].cbBuffer, buffers[1].pvBuffer,
562 buffers[1].cbBuffer);
564 auth->sizes.cbSecurityTrailer = buffers[0].cbBuffer;
567 ciphertext->cbBuffer = buffers[0].cbBuffer + buffers[1].cbBuffer;
568 ciphertext->pvBuffer = buf;
570 if (signature_length)
571 *signature_length = buffers[0].cbBuffer;
577BOOL credssp_auth_decrypt(rdpCredsspAuth* auth,
const SecBuffer* ciphertext,
SecBuffer* plaintext,
581 SecBufferDesc buffer_desc = { SECBUFFER_VERSION, 2, buffers };
584 WINPR_ASSERT(auth && auth->table);
585 WINPR_ASSERT(ciphertext);
586 WINPR_ASSERT(plaintext);
590 case AUTH_STATE_INITIAL:
591 WLog_ERR(TAG,
"Invalid state %s", credssp_auth_state_string(auth));
598 if (ciphertext->cbBuffer < auth->sizes.cbSecurityTrailer)
600 WLog_ERR(TAG,
"Encrypted message buffer too small");
606 buffers[0].BufferType = SECBUFFER_TOKEN;
607 buffers[0].pvBuffer = ciphertext->pvBuffer;
608 buffers[0].cbBuffer = auth->sizes.cbSecurityTrailer;
610 buffers[1].BufferType = SECBUFFER_DATA;
611 if (!sspi_SecBufferAlloc(&buffers[1], ciphertext->cbBuffer - auth->sizes.cbSecurityTrailer))
613 CopyMemory(buffers[1].pvBuffer, (BYTE*)ciphertext->pvBuffer + auth->sizes.cbSecurityTrailer,
614 buffers[1].cbBuffer);
616 WINPR_ASSERT(auth->table->DecryptMessage);
617 const SECURITY_STATUS status =
618 auth->table->DecryptMessage(&auth->context, &buffer_desc, sequence, &fqop);
619 if (status != SEC_E_OK)
621 WLog_ERR(TAG,
"DecryptMessage failed with %s [0x%08" PRIx32
"]",
622 GetSecurityStatusString(status), WINPR_CXX_COMPAT_CAST(uint32_t, status));
623 sspi_SecBufferFree(&buffers[1]);
627 *plaintext = buffers[1];
632BOOL credssp_auth_impersonate(rdpCredsspAuth* auth)
634 WINPR_ASSERT(auth && auth->table);
636 WINPR_ASSERT(auth->table->ImpersonateSecurityContext);
637 const SECURITY_STATUS status = auth->table->ImpersonateSecurityContext(&auth->context);
639 if (status != SEC_E_OK)
641 WLog_ERR(TAG,
"ImpersonateSecurityContext failed with %s [0x%08" PRIx32
"]",
642 GetSecurityStatusString(status), WINPR_CXX_COMPAT_CAST(uint32_t, status));
649BOOL credssp_auth_revert_to_self(rdpCredsspAuth* auth)
651 WINPR_ASSERT(auth && auth->table);
653 WINPR_ASSERT(auth->table->RevertSecurityContext);
654 const SECURITY_STATUS status = auth->table->RevertSecurityContext(&auth->context);
656 if (status != SEC_E_OK)
658 WLog_ERR(TAG,
"RevertSecurityContext failed with %s [0x%08" PRIx32
"]",
659 GetSecurityStatusString(status), WINPR_CXX_COMPAT_CAST(uint32_t, status));
666void credssp_auth_take_input_buffer(rdpCredsspAuth* auth,
SecBuffer* buffer)
669 WINPR_ASSERT(buffer);
671 sspi_SecBufferFree(&auth->input_buffer);
673 auth->input_buffer = *buffer;
674 auth->input_buffer.BufferType = SECBUFFER_TOKEN;
681const SecBuffer* credssp_auth_get_output_buffer(
const rdpCredsspAuth* auth)
684 return &auth->output_buffer;
687BOOL credssp_auth_have_output_token(rdpCredsspAuth* auth)
690 return (auth->output_buffer.cbBuffer != 0);
693BOOL credssp_auth_is_complete(
const rdpCredsspAuth* auth)
696 return auth->state == AUTH_STATE_FINAL;
699size_t credssp_auth_trailer_size(
const rdpCredsspAuth* auth)
702 return auth->sizes.cbSecurityTrailer;
705const char* credssp_auth_pkg_name(
const rdpCredsspAuth* auth)
707 WINPR_ASSERT(auth && auth->info);
708 return auth->pkgNameA;
711INT32 credssp_auth_sspi_error(
const rdpCredsspAuth* auth)
714 return auth->sspi_error;
717void credssp_auth_tableAndContext(rdpCredsspAuth* auth, SecurityFunctionTable** ptable,
721 WINPR_ASSERT(ptable);
722 WINPR_ASSERT(pcontext);
724 *ptable = auth->table;
725 *pcontext = auth->context;
728void credssp_auth_free(rdpCredsspAuth* auth)
740 case AUTH_STATE_IN_PROGRESS:
741 case AUTH_STATE_FINAL:
742 WINPR_ASSERT(auth->table->DeleteSecurityContext);
743 auth->table->DeleteSecurityContext(&auth->context);
746 case AUTH_STATE_CREDS:
747 WINPR_ASSERT(auth->table->FreeCredentialsHandle);
748 auth->table->FreeCredentialsHandle(&auth->credentials);
750 case AUTH_STATE_INITIAL:
757 WINPR_ASSERT(auth->table->FreeContextBuffer);
758 auth->table->FreeContextBuffer(auth->info);
762 sspi_FreeAuthIdentity(&auth->identity);
764 krb_settings = &auth->kerberosSettings;
765 ntlm_settings = &auth->ntlmSettings;
767 free(krb_settings->kdcUrl);
768 free(krb_settings->cache);
769 free(krb_settings->keytab);
770 free(krb_settings->armorCache);
771 free(krb_settings->pkinitX509Anchors);
772 free(krb_settings->pkinitX509Identity);
773 free(ntlm_settings->samFile);
775 free(auth->package_list);
777 sspi_SecBufferFree(&auth->input_buffer);
778 sspi_SecBufferFree(&auth->output_buffer);
779 credssp_auth_update_name_cache(auth,
nullptr);
783static void auth_get_sspi_module_from_reg(
char** sspi_module)
789 WINPR_ASSERT(sspi_module);
790 *sspi_module =
nullptr;
792 char* key = freerdp_getApplicatonDetailsRegKey(SERVER_KEY);
796 const LONG rc = RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
799 if (rc != ERROR_SUCCESS)
802 if (RegQueryValueExA(hKey,
"SspiModule",
nullptr, &dwType,
nullptr, &dwSize) != ERROR_SUCCESS)
808 char*
module = (LPSTR)calloc(dwSize + sizeof(CHAR), sizeof(char));
815 if (RegQueryValueExA(hKey,
"SspiModule",
nullptr, &dwType, (BYTE*)module, &dwSize) !=
824 *sspi_module =
module;
827static SecurityFunctionTable* auth_resolve_sspi_table(
const rdpSettings* settings)
829 char* sspi_module =
nullptr;
831 WINPR_ASSERT(settings);
833 if (settings->ServerMode)
834 auth_get_sspi_module_from_reg(&sspi_module);
836 if (sspi_module || settings->SspiModule)
838 const char* module_name = sspi_module ? sspi_module : settings->SspiModule;
840 const char* proc_name =
"InitSecurityInterfaceW";
842 const char* proc_name =
"InitSecurityInterfaceA";
845 HMODULE hSSPI = LoadLibraryX(module_name);
849 WLog_ERR(TAG,
"Failed to load SSPI module: %s", module_name);
854 WLog_INFO(TAG,
"Using SSPI Module: %s", module_name);
856 INIT_SECURITY_INTERFACE InitSecurityInterface_ptr =
857 GetProcAddressAs(hSSPI, proc_name, INIT_SECURITY_INTERFACE);
858 if (!InitSecurityInterface_ptr)
860 WLog_ERR(TAG,
"Failed to load SSPI module: %s, no function %s", module_name, proc_name);
865 return InitSecurityInterface_ptr();
868 return InitSecurityInterfaceEx(0);
871static BOOL credssp_auth_setup_identity(rdpCredsspAuth* auth)
873 const rdpSettings* settings =
nullptr;
876 freerdp_peer* peer =
nullptr;
879 WINPR_ASSERT(auth->rdp_ctx);
881 peer = auth->rdp_ctx->peer;
882 settings = auth->rdp_ctx->settings;
883 WINPR_ASSERT(settings);
885 krb_settings = &auth->kerberosSettings;
886 ntlm_settings = &auth->ntlmSettings;
888 if (settings->KerberosLifeTime)
889 parseKerberosDeltat(settings->KerberosLifeTime, &krb_settings->lifeTime,
"lifetime");
890 if (settings->KerberosStartTime)
891 parseKerberosDeltat(settings->KerberosStartTime, &krb_settings->startTime,
"starttime");
892 if (settings->KerberosRenewableLifeTime)
893 parseKerberosDeltat(settings->KerberosRenewableLifeTime, &krb_settings->renewLifeTime,
896 if (settings->KerberosKdcUrl)
898 krb_settings->kdcUrl = _strdup(settings->KerberosKdcUrl);
899 if (!krb_settings->kdcUrl)
901 WLog_ERR(TAG,
"unable to copy kdcUrl");
906 if (settings->KerberosCache)
908 krb_settings->cache = _strdup(settings->KerberosCache);
909 if (!krb_settings->cache)
911 WLog_ERR(TAG,
"unable to copy cache name");
916 if (settings->KerberosKeytab)
918 krb_settings->keytab = _strdup(settings->KerberosKeytab);
919 if (!krb_settings->keytab)
921 WLog_ERR(TAG,
"unable to copy keytab name");
926 if (settings->KerberosArmor)
928 krb_settings->armorCache = _strdup(settings->KerberosArmor);
929 if (!krb_settings->armorCache)
931 WLog_ERR(TAG,
"unable to copy armorCache");
936 if (settings->PkinitAnchors)
938 krb_settings->pkinitX509Anchors = _strdup(settings->PkinitAnchors);
939 if (!krb_settings->pkinitX509Anchors)
941 WLog_ERR(TAG,
"unable to copy pkinitX509Anchors");
946 if (settings->NtlmSamFile)
948 ntlm_settings->samFile = _strdup(settings->NtlmSamFile);
949 if (!ntlm_settings->samFile)
951 WLog_ERR(TAG,
"unable to copy samFile");
956 if (peer && peer->SspiNtlmHashCallback)
958 ntlm_settings->hashCallback = peer->SspiNtlmHashCallback;
959 ntlm_settings->hashCallbackArg = peer;
962 if (settings->AuthenticationPackageList)
964 auth->package_list = ConvertUtf8ToWCharAlloc(settings->AuthenticationPackageList,
nullptr);
965 if (!auth->package_list)
969 auth->identity.Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
970 auth->identity.Flags |= SEC_WINNT_AUTH_IDENTITY_EXTENDED;
975BOOL credssp_auth_set_spn(rdpCredsspAuth* auth,
const char* service,
const char* hostname)
986 spn = _strdup(hostname);
989 length = strlen(service) + strlen(hostname) + 2;
990 spn = calloc(length + 1,
sizeof(
char));
994 (void)sprintf_s(spn, length,
"%s/%s", service, hostname);
1000 auth->spn = ConvertUtf8ToWCharAlloc(spn,
nullptr);
1009static const char* parseInt(
const char* v, INT32* r)
1014 if (!*v || !((*v >=
'0') && (*v <=
'9')))
1017 for (; *v && (*v >=
'0') && (*v <=
'9'); v++)
1019 *r = (*r * 10) + (*v -
'0');
1025static BOOL parseKerberosDeltat(
const char* value, INT32* dest,
const char* message)
1028 const char* ptr =
nullptr;
1030 WINPR_ASSERT(value);
1032 WINPR_ASSERT(message);
1039 ptr = strchr(value,
':');
1044 value = parseInt(value, &v);
1045 if (!value || *value !=
':')
1047 WLog_ERR(TAG,
"Invalid value for %s", message);
1053 value = parseInt(value + 1, &v);
1054 if (!value || (*value != 0 && *value !=
':') || (v > 60))
1056 WLog_ERR(TAG,
"Invalid value for %s", message);
1064 value = parseInt(value + 1, &v);
1065 if (!value || (*value != 0) || (v > 60))
1067 WLog_ERR(TAG,
"Invalid value for %s", message);
1076 value = parseInt(value, &v);
1079 WLog_ERR(TAG,
"Invalid value for %s", message);
1083 if (!*value || isspace(*value))
1115 WLog_ERR(TAG,
"invalid value for unit %c when parsing %s", *value, message);
1119 if ((maxValue > 0) && (v > maxValue))
1121 WLog_ERR(TAG,
"invalid value for unit %c when parsing %s", *value, message);
1125 *dest += (v * factor);
1130 value = parseInt(value, &v);
1131 if (!value || !*value)
1133 WLog_ERR(TAG,
"Invalid value for %s", message);