diff --git a/libfreerdp/core/nla.c b/libfreerdp/core/nla.c index f9f93f3d9..65b6a1d41 100644 --- a/libfreerdp/core/nla.c +++ b/libfreerdp/core/nla.c @@ -939,6 +939,37 @@ static BOOL nla_setup_kerberos(rdpNla* nla) return TRUE; } +/** + * Initialize SSPI credential attributes + * @param nla + */ + +static BOOL nla_client_init_cred_handle(rdpNla* nla) +{ + SEC_WINPR_KERBEROS_SETTINGS* kerbSettings; + + WINPR_ASSERT(nla); + kerbSettings = nla->kerberosSettings; + WINPR_ASSERT(kerbSettings); + WINPR_ASSERT(nla->table->SetCredentialsAttributes); + + if (kerbSettings->kdcUrl) + { +#ifdef UNICODE + SecPkgCredentials_KdcUrlW secAttr = { NULL }; + ConvertToUnicode(CP_UTF8, 0, kerbSettings->kdcUrl, -1, &secAttr.KdcUrl, 0); + nla->table->SetCredentialsAttributesW(&nla->credentials, SECPKG_CRED_ATTR_KDC_URL, (void*) &secAttr, sizeof(secAttr)); + free(secAttr.KdcUrl); +#else + SecPkgCredentials_KdcUrlA secAttr = { NULL }; + secAttr.KdcUrl = kerbSettings->kdcUrl; + nla->table->SetCredentialsAttributesA(&nla->credentials, SECPKG_CRED_ATTR_KDC_URL, (void*) &secAttr, sizeof(secAttr)); +#endif + } + + return TRUE; +} + /** * Initialize NTLM/Kerberos SSP authentication module (client). * @param credssp @@ -1020,6 +1051,8 @@ static int nla_client_init(rdpNla* nla) return -1; } + nla_client_init_cred_handle(nla); + nla->haveContext = FALSE; nla->haveInputBuffer = FALSE; nla->havePubKeyAuth = FALSE; diff --git a/winpr/libwinpr/sspi/Negotiate/negotiate.c b/winpr/libwinpr/sspi/Negotiate/negotiate.c index 4d5fd379b..08fa82313 100644 --- a/winpr/libwinpr/sspi/Negotiate/negotiate.c +++ b/winpr/libwinpr/sspi/Negotiate/negotiate.c @@ -1206,14 +1206,56 @@ static SECURITY_STATUS SEC_ENTRY negotiate_SetCredentialsAttributesW(PCredHandle ULONG ulAttribute, void* pBuffer, ULONG cbBuffer) { - return SEC_E_UNSUPPORTED_FUNCTION; + MechCred* creds; + + creds = sspi_SecureHandleGetLowerPointer(phCredential); + + if (!creds) + return SEC_E_INVALID_HANDLE; + + for (size_t i = 0; i < MECH_COUNT; i++) + { + MechCred* cred = &creds[i]; + + if (!cred->valid) + continue; + + WINPR_ASSERT(cred->mech); + WINPR_ASSERT(cred->mech->pkg); + WINPR_ASSERT(cred->mech->pkg->table); + WINPR_ASSERT(cred->mech->pkg->table_w->SetCredentialsAttributesW); + cred->mech->pkg->table_w->SetCredentialsAttributesW(&cred->cred, ulAttribute, pBuffer, cbBuffer); + } + + return SEC_E_OK; } static SECURITY_STATUS SEC_ENTRY negotiate_SetCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer) { - return SEC_E_UNSUPPORTED_FUNCTION; + MechCred* creds; + + creds = sspi_SecureHandleGetLowerPointer(phCredential); + + if (!creds) + return SEC_E_INVALID_HANDLE; + + for (size_t i = 0; i < MECH_COUNT; i++) + { + MechCred* cred = &creds[i]; + + if (!cred->valid) + continue; + + WINPR_ASSERT(cred->mech); + WINPR_ASSERT(cred->mech->pkg); + WINPR_ASSERT(cred->mech->pkg->table); + WINPR_ASSERT(cred->mech->pkg->table->SetCredentialsAttributesA); + cred->mech->pkg->table->SetCredentialsAttributesA(&cred->cred, ulAttribute, pBuffer, cbBuffer); + } + + return SEC_E_OK; } static SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW( diff --git a/winpr/libwinpr/sspi/sspi_export.c b/winpr/libwinpr/sspi/sspi_export.c index 5f327aab1..b4cb8eb86 100644 --- a/winpr/libwinpr/sspi/sspi_export.c +++ b/winpr/libwinpr/sspi/sspi_export.c @@ -283,6 +283,24 @@ SSPI_EXPORT SECURITY_STATUS SEC_ENTRY SetContextAttributesA(void* phContext, ULO return sspi_SetContextAttributesA(phContext, ulAttribute, pBuffer, cbBuffer); } +extern SECURITY_STATUS SEC_ENTRY sspi_SetCredentialsAttributesW(void*, ULONG, void*, ULONG); + +static SECURITY_STATUS SEC_ENTRY SetCredentialsAttributesW(void* phCredential, + ULONG ulAttribute, void* pBuffer, + ULONG cbBuffer) +{ + return sspi_SetCredentialsAttributesW(phCredential, ulAttribute, pBuffer, cbBuffer); +} + +extern SECURITY_STATUS SEC_ENTRY sspi_SetCredentialsAttributesA(void*, ULONG, void*, ULONG); + +static SECURITY_STATUS SEC_ENTRY SetCredentialsAttributesA(void* phCredential, + ULONG ulAttribute, void* pBuffer, + ULONG cbBuffer) +{ + return sspi_SetCredentialsAttributesA(phCredential, ulAttribute, pBuffer, cbBuffer); +} + extern SECURITY_STATUS SEC_ENTRY sspi_RevertSecurityContext(void*); SSPI_EXPORT SECURITY_STATUS SEC_ENTRY RevertSecurityContext(void* phContext) diff --git a/winpr/libwinpr/sspi/sspi_winpr.c b/winpr/libwinpr/sspi/sspi_winpr.c index 2f68365b8..fc8814c3f 100644 --- a/winpr/libwinpr/sspi/sspi_winpr.c +++ b/winpr/libwinpr/sspi/sspi_winpr.c @@ -1070,6 +1070,74 @@ static SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle p return status; } +static SECURITY_STATUS SEC_ENTRY winpr_SetCredentialsAttributesW(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer, + ULONG cbBuffer) +{ + SEC_WCHAR* Name; + SECURITY_STATUS status; + const SecurityFunctionTableW* table; + Name = (SEC_WCHAR*)sspi_SecureHandleGetUpperPointer(phCredential); + + if (!Name) + return SEC_E_SECPKG_NOT_FOUND; + + table = sspi_GetSecurityFunctionTableWByNameW(Name); + + if (!table) + return SEC_E_SECPKG_NOT_FOUND; + + if (!table->SetCredentialsAttributesW) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); + return SEC_E_UNSUPPORTED_FUNCTION; + } + + status = table->SetCredentialsAttributesW(phCredential, ulAttribute, pBuffer, cbBuffer); + + if (IsSecurityStatusError(status)) + { + WLog_WARN(TAG, "SetCredentialsAttributesW status %s [0x%08" PRIX32 "]", + GetSecurityStatusString(status), status); + } + + return status; +} + +static SECURITY_STATUS SEC_ENTRY winpr_SetCredentialsAttributesA(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer, + ULONG cbBuffer) +{ + char* Name; + SECURITY_STATUS status; + const SecurityFunctionTableA* table; + Name = (char*)sspi_SecureHandleGetUpperPointer(phCredential); + + if (!Name) + return SEC_E_SECPKG_NOT_FOUND; + + table = sspi_GetSecurityFunctionTableAByNameA(Name); + + if (!table) + return SEC_E_SECPKG_NOT_FOUND; + + if (!table->SetCredentialsAttributesA) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); + return SEC_E_UNSUPPORTED_FUNCTION; + } + + status = table->SetCredentialsAttributesA(phCredential, ulAttribute, pBuffer, cbBuffer); + + if (IsSecurityStatusError(status)) + { + WLog_WARN(TAG, "SetCredentialsAttributesA status %s [0x%08" PRIX32 "]", + GetSecurityStatusString(status), status); + } + + return status; +} + /* Context Management */ static SECURITY_STATUS SEC_ENTRY @@ -1658,7 +1726,7 @@ static SECURITY_STATUS SEC_ENTRY winpr_VerifySignature(PCtxtHandle phContext, } static SecurityFunctionTableA winpr_SecurityFunctionTableA = { - 1, /* dwVersion */ + 3, /* dwVersion */ winpr_EnumerateSecurityPackagesA, /* EnumerateSecurityPackages */ winpr_QueryCredentialsAttributesA, /* QueryCredentialsAttributes */ winpr_AcquireCredentialsHandleA, /* AcquireCredentialsHandle */ @@ -1686,10 +1754,11 @@ static SecurityFunctionTableA winpr_SecurityFunctionTableA = { winpr_EncryptMessage, /* EncryptMessage */ winpr_DecryptMessage, /* DecryptMessage */ winpr_SetContextAttributesA, /* SetContextAttributes */ + winpr_SetCredentialsAttributesA, /* SetCredentialsAttributes */ }; static SecurityFunctionTableW winpr_SecurityFunctionTableW = { - 1, /* dwVersion */ + 3, /* dwVersion */ winpr_EnumerateSecurityPackagesW, /* EnumerateSecurityPackages */ winpr_QueryCredentialsAttributesW, /* QueryCredentialsAttributes */ winpr_AcquireCredentialsHandleW, /* AcquireCredentialsHandle */ @@ -1717,4 +1786,5 @@ static SecurityFunctionTableW winpr_SecurityFunctionTableW = { winpr_EncryptMessage, /* EncryptMessage */ winpr_DecryptMessage, /* DecryptMessage */ winpr_SetContextAttributesW, /* SetContextAttributes */ + winpr_SetCredentialsAttributesW, /* SetCredentialsAttributes */ };