From b1c4cb493faab181e913beb5faa1606b8c757a92 Mon Sep 17 00:00:00 2001 From: fifthdegree Date: Sun, 23 Apr 2023 18:38:24 -0400 Subject: [PATCH] Set KDC URL in a way compatible with Windows --- libfreerdp/core/credssp_auth.c | 43 +++++++++++++++++-------- winpr/include/winpr/sspi.h | 23 ------------- winpr/libwinpr/sspi/Kerberos/kerberos.c | 40 +++++++++++------------ 3 files changed, 48 insertions(+), 58 deletions(-) diff --git a/libfreerdp/core/credssp_auth.c b/libfreerdp/core/credssp_auth.c index eb6ead0cc..59838ba0e 100644 --- a/libfreerdp/core/credssp_auth.c +++ b/libfreerdp/core/credssp_auth.c @@ -199,36 +199,53 @@ static BOOL credssp_auth_client_init_cred_attributes(rdpCredsspAuth* auth) if (auth->kerberosSettings.kdcUrl) { SECURITY_STATUS status = ERROR_INTERNAL_ERROR; + SecPkgCredentials_KdcProxySettingsW* secAttr = NULL; + SSIZE_T str_size = 0; + ULONG buffer_size = 0; -#ifdef UNICODE - SecPkgCredentials_KdcUrlW secAttr = { NULL }; - secAttr.KdcUrl = ConvertUtf8ToWCharAlloc(auth->kerberosSettings.kdcUrl, NULL); + str_size = ConvertUtf8ToWChar(auth->kerberosSettings.kdcUrl, NULL, 0); + if (str_size <= 0) + return FALSE; + str_size++; - if (!secAttr.KdcUrl) + buffer_size = sizeof(SecPkgCredentials_KdcProxySettingsW) + str_size * sizeof(WCHAR); + secAttr = calloc(1, buffer_size); + if (!secAttr) return FALSE; + secAttr->Version = KDC_PROXY_SETTINGS_V1; + secAttr->ProxyServerLength = str_size * sizeof(WCHAR); + secAttr->ProxyServerOffset = sizeof(SecPkgCredentials_KdcProxySettingsW); + + if (ConvertUtf8ToWChar(auth->kerberosSettings.kdcUrl, (WCHAR*)(secAttr + 1), str_size) <= 0) + { + free(secAttr); + return FALSE; + } + +#ifdef UNICODE if (auth->table->SetCredentialsAttributesW) - status = auth->table->SetCredentialsAttributesW( - &auth->credentials, SECPKG_CRED_ATTR_KDC_URL, (void*)&secAttr, sizeof(secAttr)); + status = auth->table->SetCredentialsAttributesW(&auth->credentials, + SECPKG_CRED_ATTR_KDC_PROXY_SETTINGS, + (void*)secAttr, buffer_size); else status = SEC_E_UNSUPPORTED_FUNCTION; - - free(secAttr.KdcUrl); #else - SecPkgCredentials_KdcUrlA secAttr = { NULL }; - secAttr.KdcUrl = auth->kerberosSettings.kdcUrl; - if (auth->table->SetCredentialsAttributesA) - status = auth->table->SetCredentialsAttributesA( - &auth->credentials, SECPKG_CRED_ATTR_KDC_URL, (void*)&secAttr, sizeof(secAttr)); + status = auth->table->SetCredentialsAttributesA(&auth->credentials, + SECPKG_CRED_ATTR_KDC_PROXY_SETTINGS, + (void*)secAttr, buffer_size); else status = SEC_E_UNSUPPORTED_FUNCTION; #endif + if (status != SEC_E_OK) { WLog_WARN(TAG, "Explicit Kerberos KDC URL (%s) injection is not supported", auth->kerberosSettings.kdcUrl); } + + free(secAttr); } return TRUE; diff --git a/winpr/include/winpr/sspi.h b/winpr/include/winpr/sspi.h index f05cb22a3..27b545894 100644 --- a/winpr/include/winpr/sspi.h +++ b/winpr/include/winpr/sspi.h @@ -1324,29 +1324,6 @@ extern "C" /* Custom API */ -/* Extended SECPKG_CRED_ATTR IDs begin at 500 */ -#define SECPKG_CRED_ATTR_KDC_URL 501 - - typedef struct - { - SEC_CHAR* KdcUrl; - } SecPkgCredentials_KdcUrlA; - typedef SecPkgCredentials_KdcUrlA* PSecPkgCredentials_KdcUrlA; - - typedef struct - { - SEC_WCHAR* KdcUrl; - } SecPkgCredentials_KdcUrlW; - typedef SecPkgCredentials_KdcUrlW* PSecPkgCredentials_KdcUrlW; - -#ifdef UNICODE -#define SecPkgCredentials_KdcUrl SecPkgCredentials_KdcUrlW -#define PSecPkgCredentials_KdcUrl PSecPkgCredentials_KdcUrlW -#else -#define SecPkgCredentials_KdcUrl SecPkgCredentials_KdcUrlA -#define PSecPkgCredentials_KdcUrl PSecPkgCredentials_KdcUrlA -#endif - /* Extended SECPKG_ATTR IDs begin at 1000 */ #define SECPKG_ATTR_AUTH_IDENTITY 1001 #define SECPKG_ATTR_AUTH_PASSWORD 1002 diff --git a/winpr/libwinpr/sspi/Kerberos/kerberos.c b/winpr/libwinpr/sspi/Kerberos/kerberos.c index 194d94dab..d4407abab 100644 --- a/winpr/libwinpr/sspi/Kerberos/kerberos.c +++ b/winpr/libwinpr/sspi/Kerberos/kerberos.c @@ -1360,39 +1360,35 @@ static SECURITY_STATUS SEC_ENTRY kerberos_SetCredentialsAttributesX(PCredHandle if (!pBuffer) return SEC_E_INSUFFICIENT_MEMORY; - if (ulAttribute == SECPKG_CRED_ATTR_KDC_URL) + if (ulAttribute == SECPKG_CRED_ATTR_KDC_PROXY_SETTINGS) { + SecPkgCredentials_KdcProxySettingsW* kdc_settings = pBuffer; + + /* Sanity checks */ + if (cbBuffer < sizeof(SecPkgCredentials_KdcProxySettingsW) || + kdc_settings->Version != KDC_PROXY_SETTINGS_V1 || + kdc_settings->ProxyServerOffset < sizeof(SecPkgCredentials_KdcProxySettingsW) || + cbBuffer < sizeof(SecPkgCredentials_KdcProxySettingsW) + + kdc_settings->ProxyServerOffset + kdc_settings->ProxyServerLength) + return SEC_E_INVALID_TOKEN; + if (credentials->kdc_url) { free(credentials->kdc_url); credentials->kdc_url = NULL; } - if (unicode) + if (kdc_settings->ProxyServerLength > 0) { - SEC_WCHAR* KdcUrl = ((SecPkgCredentials_KdcUrlW*)pBuffer)->KdcUrl; + WCHAR* proxy = (WCHAR*)((BYTE*)pBuffer + kdc_settings->ProxyServerOffset); - if (KdcUrl) - { - credentials->kdc_url = ConvertWCharToUtf8Alloc(KdcUrl, NULL); - if (!credentials->kdc_url) - return SEC_E_INSUFFICIENT_MEMORY; - } - } - else - { - SEC_CHAR* KdcUrl = ((SecPkgCredentials_KdcUrlA*)pBuffer)->KdcUrl; - - if (KdcUrl) - { - credentials->kdc_url = _strdup(KdcUrl); - - if (!credentials->kdc_url) - return SEC_E_INSUFFICIENT_MEMORY; - } + credentials->kdc_url = ConvertWCharNToUtf8Alloc( + proxy, kdc_settings->ProxyServerLength / sizeof(WCHAR), NULL); + if (!credentials->kdc_url) + return SEC_E_INSUFFICIENT_MEMORY; } - return SEC_E_UNSUPPORTED_FUNCTION; + return SEC_E_OK; } return SEC_E_UNSUPPORTED_FUNCTION;