Merge pull request #12171 from jadahl/wip/ntlm-kerberos-package-info

Add support for querying SECPKG_ATTR_PACKAGE_INFO to NTLM and Kerberos
This commit is contained in:
akallabeth
2026-01-25 17:04:48 +01:00
committed by GitHub
8 changed files with 98 additions and 2 deletions

View File

@@ -767,6 +767,17 @@ owned by rdpRdp */
FREERDP_API SECURITY_STATUS freerdp_nla_QueryContextAttributes(rdpContext* context,
DWORD ulAttr, PVOID pBuffer);
/** Calls FreeContextbuffer on the SSPI context associated with the NLA part of the RDP context
*
* \param context the RDP context
* \param pBuffer an opaque pointer to free
* \returns a SECURITY_STATUS indicating if the operation completed successfully
* \since version 3.22.0
*
* Supported buffers are ones retrieved from SECPKG_ATTR_PACKAGE_INFO.
*/
FREERDP_API SECURITY_STATUS freerdp_nla_FreeContextBuffer(rdpContext* context, PVOID pBuffer);
FREERDP_API void clearChannelError(rdpContext* context);
FREERDP_API HANDLE getChannelErrorEventHandle(rdpContext* context);
FREERDP_API UINT getChannelError(const rdpContext* context);

View File

@@ -1349,6 +1349,20 @@ SECURITY_STATUS freerdp_nla_QueryContextAttributes(rdpContext* context, DWORD ul
return nla_QueryContextAttributes(nla, ulAttr, pBuffer);
}
SECURITY_STATUS freerdp_nla_FreeContextBuffer(rdpContext* context, PVOID pBuffer)
{
WINPR_ASSERT(context);
WINPR_ASSERT(context->rdp);
rdpNla* nla = context->rdp->nla;
if (!nla)
nla = transport_get_nla(context->rdp->transport);
WINPR_ASSERT(nla);
return nla_FreeContextBuffer(nla, pBuffer);
}
HANDLE getChannelErrorEventHandle(rdpContext* context)
{
WINPR_ASSERT(context);

View File

@@ -2455,3 +2455,14 @@ SECURITY_STATUS nla_QueryContextAttributes(rdpNla* nla, DWORD ulAttr, PVOID pBuf
return table->QueryContextAttributes(&context, ulAttr, pBuffer);
}
SECURITY_STATUS nla_FreeContextBuffer(rdpNla* nla, PVOID pBuffer)
{
WINPR_ASSERT(nla);
SecurityFunctionTable* table = NULL;
CtxtHandle context = { 0 };
credssp_auth_tableAndContext(nla->auth, &table, &context);
return table->FreeContextBuffer(pBuffer);
}

View File

@@ -78,5 +78,6 @@ FREERDP_LOCAL void nla_set_early_user_auth(rdpNla* nla, BOOL earlyUserAuth);
FREERDP_LOCAL BOOL nla_encrypt(rdpNla* nla, const SecBuffer* inBuffer, SecBuffer* outBuffer);
FREERDP_LOCAL BOOL nla_decrypt(rdpNla* nla, const SecBuffer* inBuffer, SecBuffer* outBuffer);
FREERDP_LOCAL SECURITY_STATUS nla_QueryContextAttributes(rdpNla* nla, DWORD ulAttr, PVOID pBuffer);
FREERDP_LOCAL SECURITY_STATUS nla_FreeContextBuffer(rdpNla* nla, PVOID pBuffer);
#endif /* FREERDP_LIB_CORE_NLA_H */

View File

@@ -1781,6 +1781,33 @@ fail:
return krb5_error_to_SECURITY_STATUS(rv);
}
static SECURITY_STATUS kerberos_ATTR_PACKAGE_INFO(KRB_CONTEXT* context,
KRB_CREDENTIALS* credentials,
SecPkgContext_PackageInfo* PackageInfo)
{
size_t size = sizeof(SecPkgInfoA);
SecPkgInfoA* pPackageInfo =
(SecPkgInfoA*)sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size);
if (!pPackageInfo)
return SEC_E_INSUFFICIENT_MEMORY;
pPackageInfo->fCapabilities = KERBEROS_SecPkgInfoA.fCapabilities;
pPackageInfo->wVersion = KERBEROS_SecPkgInfoA.wVersion;
pPackageInfo->wRPCID = KERBEROS_SecPkgInfoA.wRPCID;
pPackageInfo->cbMaxToken = KERBEROS_SecPkgInfoA.cbMaxToken;
pPackageInfo->Name = _strdup(KERBEROS_SecPkgInfoA.Name);
pPackageInfo->Comment = _strdup(KERBEROS_SecPkgInfoA.Comment);
if (!pPackageInfo->Name || !pPackageInfo->Comment)
{
sspi_ContextBufferFree(pPackageInfo);
return SEC_E_INSUFFICIENT_MEMORY;
}
PackageInfo->PackageInfo = pPackageInfo;
return SEC_E_OK;
}
static SECURITY_STATUS kerberos_ATTR_TICKET_LOGON(KRB_CONTEXT* context,
KRB_CREDENTIALS* credentials,
KERB_TICKET_LOGON* ticketLogon)
@@ -1883,6 +1910,10 @@ static SECURITY_STATUS SEC_ENTRY kerberos_QueryContextAttributesA(PCtxtHandle ph
return kerberos_ATTR_AUTH_IDENTITY(context, credentials,
(SecPkgContext_AuthIdentity*)pBuffer);
case SECPKG_ATTR_PACKAGE_INFO:
return kerberos_ATTR_PACKAGE_INFO(context, credentials,
(SecPkgContext_PackageInfo*)pBuffer);
case SECPKG_CRED_ATTR_TICKET_LOGON:
return kerberos_ATTR_TICKET_LOGON(context, credentials, (KERB_TICKET_LOGON*)pBuffer);

View File

@@ -897,6 +897,31 @@ static SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phCont
{
return ntlm_computeMicValue(context, (SecBuffer*)pBuffer);
}
else if (ulAttribute == SECPKG_ATTR_PACKAGE_INFO)
{
SecPkgContext_PackageInfo* PackageInfo = (SecPkgContext_PackageInfo*)pBuffer;
size_t size = sizeof(SecPkgInfoA);
SecPkgInfoA* pPackageInfo =
(SecPkgInfoA*)sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size);
if (!pPackageInfo)
return SEC_E_INSUFFICIENT_MEMORY;
pPackageInfo->fCapabilities = NTLM_SecPkgInfoA.fCapabilities;
pPackageInfo->wVersion = NTLM_SecPkgInfoA.wVersion;
pPackageInfo->wRPCID = NTLM_SecPkgInfoA.wRPCID;
pPackageInfo->cbMaxToken = NTLM_SecPkgInfoA.cbMaxToken;
pPackageInfo->Name = _strdup(NTLM_SecPkgInfoA.Name);
pPackageInfo->Comment = _strdup(NTLM_SecPkgInfoA.Comment);
if (!pPackageInfo->Name || !pPackageInfo->Comment)
{
sspi_ContextBufferFree(pPackageInfo);
return SEC_E_INSUFFICIENT_MEMORY;
}
PackageInfo->PackageInfo = pPackageInfo;
return SEC_E_OK;
}
WLog_ERR(TAG, "TODO: Implement ulAttribute=0x%08" PRIx32, ulAttribute);
return SEC_E_UNSUPPORTED_FUNCTION;

View File

@@ -147,7 +147,7 @@ static void sspi_ContextBufferAllocTableFree(void)
ContextBufferAllocTable.entries = NULL;
}
static void* sspi_ContextBufferAlloc(UINT32 allocatorIndex, size_t size)
void* sspi_ContextBufferAlloc(UINT32 allocatorIndex, size_t size)
{
void* contextBuffer = NULL;
@@ -1050,7 +1050,7 @@ static const SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameA(const
static void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer);
static void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer);
static void sspi_ContextBufferFree(void* contextBuffer)
void sspi_ContextBufferFree(void* contextBuffer)
{
UINT32 allocatorIndex = 0;

View File

@@ -25,4 +25,7 @@
SecurityFunctionTableW* SEC_ENTRY winpr_InitSecurityInterfaceW(void);
SecurityFunctionTableA* SEC_ENTRY winpr_InitSecurityInterfaceA(void);
void* sspi_ContextBufferAlloc(UINT32 allocatorIndex, size_t size);
void sspi_ContextBufferFree(void* contextBuffer);
#endif /* WINPR_SSPI_WINPR_H */