2423 lines
66 KiB
C
2423 lines
66 KiB
C
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1995.
|
|
//
|
|
// File: ctxtattr.c
|
|
//
|
|
// Contents: QueryContextAttribute and related functions.
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 09-30-97 jbanes Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "sslp.h"
|
|
#include <ssl2msg.h>
|
|
#include <ssl3msg.h>
|
|
#include <pct1msg.h>
|
|
#include <tls1key.h>
|
|
#include <mapper.h>
|
|
#include <lsasecpk.h>
|
|
|
|
typedef struct {
|
|
DWORD dwProtoId;
|
|
LPCTSTR szProto;
|
|
DWORD dwMajor;
|
|
DWORD dwMinor;
|
|
} PROTO_ID;
|
|
|
|
const PROTO_ID rgProts[] = {
|
|
{ SP_PROT_SSL2_CLIENT, TEXT("SSL"), 2, 0 },
|
|
{ SP_PROT_SSL2_SERVER, TEXT("SSL"), 2, 0 },
|
|
{ SP_PROT_PCT1_CLIENT, TEXT("PCT"), 1, 0 },
|
|
{ SP_PROT_PCT1_SERVER, TEXT("PCT"), 1, 0 },
|
|
{ SP_PROT_SSL3_CLIENT, TEXT("SSL"), 3, 0 },
|
|
{ SP_PROT_SSL3_SERVER, TEXT("SSL"), 3, 0 },
|
|
{ SP_PROT_TLS1_CLIENT, TEXT("TLS"), 1, 0 },
|
|
{ SP_PROT_TLS1_SERVER, TEXT("TLS"), 1, 0 }
|
|
};
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryAccessToken
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_ACCESS_TOKEN context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_AccessToken
|
|
// {
|
|
// void SEC_FAR * AccessToken;
|
|
// } SecPkgContext_AccessToken, SEC_FAR * PSecPkgContext_AccessToken;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryAccessToken(
|
|
PSPContext pContext,
|
|
PSecPkgContext_AccessToken pAccessToken)
|
|
{
|
|
PSessCacheItem pZombie;
|
|
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_ACCESS_TOKEN)\n"));
|
|
|
|
pZombie = pContext->RipeZombie;
|
|
|
|
if(pZombie == NULL ||
|
|
pZombie->hLocator == 0)
|
|
{
|
|
if(pZombie->LocatorStatus)
|
|
{
|
|
return(SP_LOG_RESULT(pZombie->LocatorStatus));
|
|
}
|
|
else
|
|
{
|
|
return(SP_LOG_RESULT(SEC_E_NO_IMPERSONATION));
|
|
}
|
|
}
|
|
|
|
pAccessToken->AccessToken = (VOID *)pZombie->hLocator;
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryAuthority
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_AUTHORITY context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_AuthorityW
|
|
// {
|
|
// SEC_WCHAR SEC_FAR * sAuthorityName;
|
|
// } SecPkgContext_AuthorityW, * PSecPkgContext_AuthorityW;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryAuthority(
|
|
LSA_SEC_HANDLE ContextHandle,
|
|
PVOID Buffer)
|
|
{
|
|
SecPkgContext_Authority Authority;
|
|
DWORD Size;
|
|
PSPContext pContext;
|
|
SECURITY_STATUS Status;
|
|
PVOID pvClient = NULL;
|
|
|
|
CERT_CONTEXT * pCert;
|
|
DWORD cchIssuer;
|
|
DWORD cbIssuer;
|
|
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_AUTHORITY)\n"));
|
|
|
|
pContext = (PSPContext)ContextHandle;
|
|
Size = sizeof( SecPkgContext_Authority );
|
|
|
|
//
|
|
// Obtain data from Schannel.
|
|
//
|
|
|
|
pCert = pContext->RipeZombie->pRemoteCert;
|
|
if(NULL == pCert)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|
|
|
|
if(pCert->pCertInfo->Issuer.cbData == 0 ||
|
|
pCert->pCertInfo->Issuer.pbData == NULL)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|
|
|
|
if(0 >= (cchIssuer = CertNameToStr(pCert->dwCertEncodingType,
|
|
&pCert->pCertInfo->Issuer,
|
|
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
|
|
NULL,
|
|
0)))
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|
|
cbIssuer = (cchIssuer + 1) * sizeof(TCHAR);
|
|
|
|
Authority.sAuthorityName = SPExternalAlloc(cbIssuer);
|
|
if(Authority.sAuthorityName == NULL)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
|
|
}
|
|
|
|
if(0 >= CertNameToStr(pCert->dwCertEncodingType,
|
|
&pCert->pCertInfo->Issuer,
|
|
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
|
|
Authority.sAuthorityName,
|
|
cchIssuer))
|
|
{
|
|
SPExternalFree(Authority.sAuthorityName);
|
|
return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|
|
|
|
|
|
//
|
|
// Copy buffers to client memory.
|
|
//
|
|
|
|
Status = LsaTable->AllocateClientBuffer(
|
|
NULL,
|
|
cbIssuer,
|
|
&pvClient);
|
|
if(FAILED(Status))
|
|
{
|
|
SPExternalFree(Authority.sAuthorityName);
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
Status = LsaTable->CopyToClientBuffer(
|
|
NULL,
|
|
cbIssuer,
|
|
pvClient,
|
|
Authority.sAuthorityName);
|
|
if(FAILED(Status))
|
|
{
|
|
SPExternalFree(Authority.sAuthorityName);
|
|
LsaTable->FreeClientBuffer(NULL, pvClient);
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
SPExternalFree(Authority.sAuthorityName);
|
|
|
|
Authority.sAuthorityName = pvClient;
|
|
|
|
|
|
//
|
|
// Copy structure back to client memory.
|
|
//
|
|
|
|
Status = LsaTable->CopyToClientBuffer( NULL,
|
|
Size,
|
|
Buffer,
|
|
&Authority );
|
|
if(FAILED(Status))
|
|
{
|
|
LsaTable->FreeClientBuffer(NULL, pvClient);
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryConnectionInfo
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_CONNECTION_INFO context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_ConnectionInfo
|
|
// {
|
|
// DWORD dwProtocol;
|
|
// ALG_ID aiCipher;
|
|
// DWORD dwCipherStrength;
|
|
// ALG_ID aiHash;
|
|
// DWORD dwHashStrength;
|
|
// ALG_ID aiExch;
|
|
// DWORD dwExchStrength;
|
|
// } SecPkgContext_ConnectionInfo;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryConnectionInfo(
|
|
PSPContext pContext,
|
|
SecPkgContext_ConnectionInfo *pConnectionInfo)
|
|
{
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_CONNECTION_INFO)\n"));
|
|
|
|
if (NULL == pContext->pCipherInfo ||
|
|
NULL == pContext->pHashInfo ||
|
|
NULL == pContext->pKeyExchInfo)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|
|
|
|
ZeroMemory(pConnectionInfo, sizeof(SecPkgContext_ConnectionInfo));
|
|
|
|
pConnectionInfo->dwProtocol = pContext->RipeZombie->fProtocol;
|
|
if(pContext->pCipherInfo->aiCipher != CALG_NULLCIPHER)
|
|
{
|
|
pConnectionInfo->aiCipher = pContext->pCipherInfo->aiCipher;
|
|
pConnectionInfo->dwCipherStrength = pContext->pCipherInfo->dwStrength;
|
|
}
|
|
pConnectionInfo->aiHash = pContext->pHashInfo->aiHash;
|
|
pConnectionInfo->dwHashStrength = pContext->pHashInfo->cbCheckSum * 8;
|
|
pConnectionInfo->aiExch = pContext->pKeyExchInfo->aiExch;
|
|
pConnectionInfo->dwExchStrength = pContext->RipeZombie->dwExchStrength;
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryIssuerList
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_ISSUER_LIST context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_IssuerListInfo
|
|
// {
|
|
// DWORD cbIssuerList;
|
|
// PBYTE pIssuerList;
|
|
// } SecPkgContext_IssuerListInfo;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryIssuerList(
|
|
LSA_SEC_HANDLE ContextHandle,
|
|
PVOID Buffer)
|
|
{
|
|
SecPkgContext_IssuerListInfo IssuerList;
|
|
DWORD Size;
|
|
PSPContext pContext;
|
|
SECURITY_STATUS Status;
|
|
PVOID pvClient = NULL;
|
|
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_ISSUER_LIST)\n"));
|
|
|
|
pContext = (PSPContext)ContextHandle;
|
|
Size = sizeof( SecPkgContext_IssuerListInfo );
|
|
|
|
//
|
|
// Obtain data from Schannel.
|
|
//
|
|
|
|
// The issuer list is returned in the SSL3 wire format, which
|
|
// consists of a bunch of issuer names, each prepended
|
|
// with a two byte size (in big endian). Additionally, the list
|
|
// is also prepended with a two byte list size (also in big
|
|
// endian).
|
|
IssuerList.cbIssuerList = pContext->cbIssuerList;
|
|
IssuerList.pIssuerList = pContext->pbIssuerList;
|
|
|
|
|
|
//
|
|
// Copy buffers to client memory.
|
|
//
|
|
|
|
if(IssuerList.cbIssuerList && IssuerList.pIssuerList)
|
|
{
|
|
Status = LsaTable->AllocateClientBuffer(
|
|
NULL,
|
|
IssuerList.cbIssuerList,
|
|
&pvClient);
|
|
if(FAILED(Status))
|
|
{
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
Status = LsaTable->CopyToClientBuffer(
|
|
NULL,
|
|
IssuerList.cbIssuerList,
|
|
pvClient,
|
|
IssuerList.pIssuerList);
|
|
if(FAILED(Status))
|
|
{
|
|
LsaTable->FreeClientBuffer(NULL, pvClient);
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
IssuerList.pIssuerList = pvClient;
|
|
}
|
|
|
|
|
|
//
|
|
// Copy structure back to client memory.
|
|
//
|
|
|
|
Status = LsaTable->CopyToClientBuffer( NULL,
|
|
Size,
|
|
Buffer,
|
|
&IssuerList );
|
|
if(FAILED(Status))
|
|
{
|
|
LsaTable->FreeClientBuffer(NULL, pvClient);
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryIssuerListEx
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_ISSUER_LIST_EX context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_IssuerListInfoEx
|
|
// {
|
|
// PCERT_NAME_BLOB aIssuers;
|
|
// DWORD cIssuers;
|
|
// } SecPkgContext_IssuerListInfoEx;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryIssuerListEx(
|
|
LSA_SEC_HANDLE ContextHandle,
|
|
PVOID Buffer)
|
|
{
|
|
SecPkgContext_IssuerListInfoEx IssuerListEx;
|
|
DWORD Size;
|
|
PSPContext pContext;
|
|
SECURITY_STATUS Status;
|
|
PVOID pvClient = NULL;
|
|
DWORD cIssuers;
|
|
|
|
PBYTE pbIssuerList;
|
|
DWORD cbIssuerList;
|
|
PBYTE pbIssuer;
|
|
DWORD cbIssuer;
|
|
PBYTE pbClientIssuer;
|
|
PCERT_NAME_BLOB paIssuerBlobs;
|
|
DWORD cbIssuerBlobs;
|
|
DWORD i;
|
|
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_ISSUER_LIST_EX)\n"));
|
|
|
|
pContext = (PSPContext)ContextHandle;
|
|
Size = sizeof( SecPkgContext_IssuerListInfoEx );
|
|
|
|
//
|
|
// Obtain data from Schannel.
|
|
//
|
|
|
|
IssuerListEx.cIssuers = 0;
|
|
IssuerListEx.aIssuers = NULL;
|
|
|
|
if(pContext->pbIssuerList && pContext->cbIssuerList > 2)
|
|
{
|
|
pbIssuerList = pContext->pbIssuerList + 2;
|
|
cbIssuerList = pContext->cbIssuerList - 2;
|
|
|
|
// Count issuers.
|
|
cIssuers = 0;
|
|
pbIssuer = pbIssuerList;
|
|
while(pbIssuer + 1 < pbIssuerList + cbIssuerList)
|
|
{
|
|
cbIssuer = COMBINEBYTES(pbIssuer[0], pbIssuer[1]);
|
|
pbIssuer += 2 + cbIssuer;
|
|
cIssuers++;
|
|
}
|
|
|
|
// Allocate memory for list of blobs.
|
|
cbIssuerBlobs = cIssuers * sizeof(CERT_NAME_BLOB);
|
|
paIssuerBlobs = SPExternalAlloc(cbIssuerBlobs);
|
|
if(paIssuerBlobs == NULL)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
|
|
}
|
|
|
|
// Allocate memory for issuer list.
|
|
Status = LsaTable->AllocateClientBuffer(
|
|
NULL,
|
|
cbIssuerBlobs + cbIssuerList,
|
|
&pvClient);
|
|
if(FAILED(Status))
|
|
{
|
|
SPExternalFree(paIssuerBlobs);
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
// Copy the raw issuer list into client memory.
|
|
Status = LsaTable->CopyToClientBuffer(
|
|
NULL,
|
|
cbIssuerList,
|
|
(PBYTE)pvClient + cbIssuerBlobs,
|
|
pbIssuerList );
|
|
if(FAILED(Status))
|
|
{
|
|
SPExternalFree(paIssuerBlobs);
|
|
LsaTable->FreeClientBuffer(NULL, pvClient);
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
// Build the issuer blob list.
|
|
pbIssuer = pbIssuerList;
|
|
pbClientIssuer = (PBYTE)pvClient + cbIssuerBlobs;
|
|
|
|
for(i = 0; i < cIssuers; i++)
|
|
{
|
|
paIssuerBlobs[i].pbData = pbClientIssuer + 2;
|
|
paIssuerBlobs[i].cbData = COMBINEBYTES(pbIssuer[0], pbIssuer[1]);
|
|
|
|
pbIssuer += 2 + paIssuerBlobs[i].cbData;
|
|
pbClientIssuer += 2 + paIssuerBlobs[i].cbData;
|
|
}
|
|
|
|
// Copy the blob list into client memory.
|
|
Status = LsaTable->CopyToClientBuffer(
|
|
NULL,
|
|
cbIssuerBlobs,
|
|
pvClient,
|
|
paIssuerBlobs );
|
|
if(FAILED(Status))
|
|
{
|
|
SPExternalFree(paIssuerBlobs);
|
|
LsaTable->FreeClientBuffer(NULL, pvClient);
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
SPExternalFree(paIssuerBlobs);
|
|
|
|
IssuerListEx.cIssuers = cIssuers;
|
|
IssuerListEx.aIssuers = pvClient;
|
|
}
|
|
|
|
|
|
//
|
|
// Copy structure back to client memory.
|
|
//
|
|
|
|
Status = LsaTable->CopyToClientBuffer( NULL,
|
|
Size,
|
|
Buffer,
|
|
&IssuerListEx );
|
|
if(FAILED(Status))
|
|
{
|
|
if(pvClient) LsaTable->FreeClientBuffer(NULL, pvClient);
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryKeyInfo
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_KEY_INFO context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_KeyInfoW
|
|
// {
|
|
// SEC_WCHAR SEC_FAR * sSignatureAlgorithmName;
|
|
// SEC_WCHAR SEC_FAR * sEncryptAlgorithmName;
|
|
// unsigned long KeySize;
|
|
// unsigned long SignatureAlgorithm;
|
|
// unsigned long EncryptAlgorithm;
|
|
// } SecPkgContext_KeyInfoW;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryKeyInfo(
|
|
PSPContext pContext,
|
|
PVOID Buffer)
|
|
{
|
|
SecPkgContext_KeyInfo *pKeyInfo;
|
|
DWORD cchSigName;
|
|
DWORD cbSigName;
|
|
DWORD cchCipherName;
|
|
DWORD cbCipherName;
|
|
|
|
UNICODE_STRING UniString;
|
|
ANSI_STRING AnsiString;
|
|
|
|
DWORD Status;
|
|
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_KEY_INFO)\n"));
|
|
|
|
if (NULL == pContext->pCipherInfo ||
|
|
NULL == pContext->pHashInfo ||
|
|
NULL == pContext->pKeyExchInfo)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|
|
if (NULL == pContext->pCipherInfo->szName)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
|
|
}
|
|
|
|
|
|
pKeyInfo = (SecPkgContext_KeyInfo *)Buffer;
|
|
|
|
ZeroMemory(pKeyInfo, sizeof(*pKeyInfo));
|
|
|
|
pKeyInfo->KeySize = pContext->pCipherInfo->dwStrength;
|
|
pKeyInfo->EncryptAlgorithm = pContext->pCipherInfo->aiCipher;
|
|
pKeyInfo->SignatureAlgorithm = 0;
|
|
|
|
|
|
cchSigName = strlen(pContext->pKeyExchInfo->szName);
|
|
cbSigName = (cchSigName + 1) * sizeof(WCHAR);
|
|
pKeyInfo->sSignatureAlgorithmName = LocalAlloc(LPTR, cbSigName);
|
|
if(pKeyInfo->sSignatureAlgorithmName == NULL)
|
|
{
|
|
Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
|
|
goto done;
|
|
}
|
|
|
|
RtlInitAnsiString(&AnsiString,
|
|
pContext->pKeyExchInfo->szName);
|
|
|
|
UniString.Length = 0;
|
|
UniString.MaximumLength = (USHORT)cbSigName;
|
|
UniString.Buffer = pKeyInfo->sSignatureAlgorithmName;
|
|
|
|
RtlAnsiStringToUnicodeString(&UniString,
|
|
&AnsiString,
|
|
FALSE);
|
|
|
|
|
|
cchCipherName = strlen(pContext->pCipherInfo->szName);
|
|
cbCipherName = (cchCipherName + 1) * sizeof(WCHAR);
|
|
pKeyInfo->sEncryptAlgorithmName = LocalAlloc(LPTR, cbCipherName);
|
|
if(pKeyInfo->sEncryptAlgorithmName == NULL)
|
|
{
|
|
Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
|
|
goto done;
|
|
}
|
|
|
|
RtlInitAnsiString(&AnsiString,
|
|
pContext->pCipherInfo->szName);
|
|
|
|
UniString.Length = 0;
|
|
UniString.MaximumLength = (USHORT)cbCipherName;
|
|
UniString.Buffer = pKeyInfo->sEncryptAlgorithmName;
|
|
|
|
RtlAnsiStringToUnicodeString(&UniString,
|
|
&AnsiString,
|
|
FALSE);
|
|
|
|
Status = PCT_ERR_OK;
|
|
|
|
done:
|
|
|
|
if(Status != PCT_ERR_OK)
|
|
{
|
|
if(pKeyInfo->sSignatureAlgorithmName)
|
|
{
|
|
LocalFree(pKeyInfo->sSignatureAlgorithmName);
|
|
pKeyInfo->sSignatureAlgorithmName = NULL;
|
|
}
|
|
if(pKeyInfo->sEncryptAlgorithmName)
|
|
{
|
|
LocalFree(pKeyInfo->sEncryptAlgorithmName);
|
|
pKeyInfo->sEncryptAlgorithmName = NULL;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryLifespan
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_LIFESPAN context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_Lifespan
|
|
// {
|
|
// TimeStamp tsStart;
|
|
// TimeStamp tsExpiry;
|
|
// } SecPkgContext_Lifespan;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryLifespan(
|
|
PSPContext pContext,
|
|
SecPkgContext_Lifespan *pLifespan)
|
|
{
|
|
PCCERT_CONTEXT pCertContext;
|
|
NTSTATUS Status;
|
|
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_LIFESPAN)\n"));
|
|
|
|
if(pContext->RipeZombie->pbServerCertificate)
|
|
{
|
|
Status = DeserializeCertContext(&pCertContext,
|
|
pContext->RipeZombie->pbServerCertificate,
|
|
pContext->RipeZombie->cbServerCertificate);
|
|
if(Status != PCT_ERR_OK)
|
|
{
|
|
SP_LOG_RESULT(Status);
|
|
return SEC_E_INSUFFICIENT_MEMORY;
|
|
}
|
|
|
|
pLifespan->tsStart.QuadPart = *((LONGLONG *)&pCertContext->pCertInfo->NotBefore);
|
|
pLifespan->tsExpiry.QuadPart = *((LONGLONG *)&pCertContext->pCertInfo->NotAfter);
|
|
|
|
CertFreeCertificateContext(pCertContext);
|
|
}
|
|
else
|
|
{
|
|
pLifespan->tsStart.QuadPart = 0;
|
|
pLifespan->tsExpiry.QuadPart = MAXTIMEQUADPART;
|
|
}
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryLocalCertContext
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_LOCAL_CERT_CONTEXT
|
|
// context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains a pointer to a CERT_CONTEXT
|
|
// structure.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryLocalCertContext(
|
|
LSA_SEC_HANDLE ContextHandle,
|
|
PVOID Buffer)
|
|
{
|
|
DWORD Size;
|
|
PSPContext pContext;
|
|
SECURITY_STATUS Status;
|
|
PVOID pvClient = NULL;
|
|
|
|
PCCERT_CONTEXT pCertContext = NULL;
|
|
SecBuffer Input;
|
|
SecBuffer Output;
|
|
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_LOCAL_CERT_CONTEXT)\n"));
|
|
|
|
pContext = (PSPContext)ContextHandle;
|
|
Size = sizeof( PCCERT_CONTEXT );
|
|
|
|
//
|
|
// Obtain data from Schannel.
|
|
//
|
|
|
|
if(pContext->dwProtocol & SP_PROT_CLIENTS)
|
|
{
|
|
pCertContext = pContext->RipeZombie->pClientCert;
|
|
}
|
|
else
|
|
{
|
|
pCertContext = pContext->RipeZombie->pActiveServerCred->pCert;
|
|
}
|
|
|
|
|
|
//
|
|
// Copy buffers to client memory.
|
|
//
|
|
|
|
if(pCertContext)
|
|
{
|
|
// Serialize the certificate context, as well as the associated
|
|
// certificate store.
|
|
Status = SerializeCertContext(pCertContext,
|
|
NULL,
|
|
&Input.cbBuffer);
|
|
if(FAILED(Status))
|
|
{
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
Input.pvBuffer = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, Input.cbBuffer);
|
|
if(Input.pvBuffer == NULL)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
|
|
}
|
|
Status = SerializeCertContext(pCertContext,
|
|
Input.pvBuffer,
|
|
&Input.cbBuffer);
|
|
if(FAILED(Status))
|
|
{
|
|
LocalFree(Input.pvBuffer);
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
// Call back into the user process in order to replicate the
|
|
// certificate context and store over there.
|
|
Input.BufferType = SECBUFFER_DATA;
|
|
|
|
Status = PerformApplicationCallback(SCH_DOWNLOAD_CERT_CALLBACK,
|
|
0,
|
|
0,
|
|
&Input,
|
|
&Output,
|
|
TRUE);
|
|
LocalFree(Input.pvBuffer);
|
|
if(FAILED(Status))
|
|
{
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
pCertContext = *(PCCERT_CONTEXT *)(Output.pvBuffer);
|
|
SPExternalFree(Output.pvBuffer);
|
|
}
|
|
|
|
//
|
|
// Copy structure back to client memory.
|
|
//
|
|
|
|
if(pCertContext)
|
|
{
|
|
Status = LsaTable->CopyToClientBuffer( NULL,
|
|
Size,
|
|
Buffer,
|
|
(PVOID)&pCertContext );
|
|
if(FAILED(Status))
|
|
{
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_NO_CREDENTIALS);
|
|
}
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryRemoteCertContext
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_REMOTE_CERT_CONTEXT
|
|
// context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains a pointer to a CERT_CONTEXT
|
|
// structure.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryRemoteCertContext(
|
|
PSPContext pContext,
|
|
PVOID Buffer)
|
|
{
|
|
PCCERT_CONTEXT pCertContext;
|
|
SP_STATUS pctRet;
|
|
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_REMOTE_CERT_CONTEXT)\n"));
|
|
|
|
if(pContext->RipeZombie->pbServerCertificate)
|
|
{
|
|
pctRet = DeserializeCertContext(&pCertContext,
|
|
pContext->RipeZombie->pbServerCertificate,
|
|
pContext->RipeZombie->cbServerCertificate);
|
|
if(pctRet != PCT_ERR_OK)
|
|
{
|
|
return SP_LOG_RESULT(pctRet);
|
|
}
|
|
|
|
*(PCCERT_CONTEXT *)Buffer = pCertContext;
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
else
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_NO_CREDENTIALS);
|
|
}
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryLocalCred
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_LOCAL_CRED context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_LocalCredentialInfo
|
|
// {
|
|
// DWORD cbCertificateChain;
|
|
// PBYTE pbCertificateChain;
|
|
// DWORD cCertificates;
|
|
// DWORD fFlags;
|
|
// DWORD dwBits;
|
|
// } SecPkgContext_LocalCredentialInfo;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryLocalCred(
|
|
LSA_SEC_HANDLE ContextHandle,
|
|
PVOID Buffer)
|
|
{
|
|
SecPkgContext_LocalCredentialInfo CredInfo;
|
|
DWORD Size;
|
|
PSPContext pContext;
|
|
SECURITY_STATUS Status;
|
|
PVOID pvClient = NULL;
|
|
SP_STATUS pctRet;
|
|
|
|
PCCERT_CONTEXT pCert = NULL;
|
|
PUBLICKEY * pKey = NULL;
|
|
DWORD fVerified = FALSE;
|
|
RSAPUBKEY * pk = NULL;
|
|
PSPCredential pCred;
|
|
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_LOCAL_CRED)\n"));
|
|
|
|
pContext = (PSPContext)ContextHandle;
|
|
Size = sizeof( SecPkgContext_LocalCredentialInfo );
|
|
|
|
//
|
|
// Obtain data from Schannel.
|
|
//
|
|
|
|
ZeroMemory(&CredInfo, Size);
|
|
|
|
if(pContext->dwProtocol & SP_PROT_CLIENTS)
|
|
{
|
|
pCred = pContext->pActiveClientCred;
|
|
}
|
|
else
|
|
{
|
|
pCred = pContext->RipeZombie->pActiveServerCred;
|
|
}
|
|
if(pCred)
|
|
{
|
|
pCert = pCred->pCert;
|
|
pKey = pCred->pPublicKey;
|
|
}
|
|
|
|
if(pCert)
|
|
{
|
|
CredInfo.fFlags |= LCRED_CRED_EXISTS;
|
|
|
|
CredInfo.pbCertificateChain = pCert->pbCertEncoded;
|
|
CredInfo.cbCertificateChain = pCert->cbCertEncoded;
|
|
CredInfo.cCertificates = 1;
|
|
|
|
// Compute number of bits in the certificate's public key.
|
|
CredInfo.dwBits = 0;
|
|
pk = (RSAPUBKEY *)((pKey->pPublic) + 1);
|
|
if(pk)
|
|
{
|
|
CredInfo.dwBits = pk->bitlen;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Copy buffers to client memory.
|
|
//
|
|
|
|
if(CredInfo.pbCertificateChain)
|
|
{
|
|
Status = LsaTable->AllocateClientBuffer(
|
|
NULL,
|
|
CredInfo.cbCertificateChain,
|
|
&pvClient);
|
|
if(FAILED(Status))
|
|
{
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
Status = LsaTable->CopyToClientBuffer(
|
|
NULL,
|
|
CredInfo.cbCertificateChain,
|
|
pvClient,
|
|
CredInfo.pbCertificateChain);
|
|
if(FAILED(Status))
|
|
{
|
|
LsaTable->FreeClientBuffer(NULL, pvClient);
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
CredInfo.pbCertificateChain = pvClient;
|
|
}
|
|
|
|
//
|
|
// Copy structure back to client memory.
|
|
//
|
|
|
|
Status = LsaTable->CopyToClientBuffer( NULL,
|
|
Size,
|
|
Buffer,
|
|
&CredInfo );
|
|
if(FAILED(Status))
|
|
{
|
|
LsaTable->FreeClientBuffer(NULL, pvClient);
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryRemoteCred
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_REMOTE_CRED context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_LocalCredentialInfo
|
|
// {
|
|
// DWORD cbCertificateChain;
|
|
// PBYTE pbCertificateChain;
|
|
// DWORD cCertificates;
|
|
// DWORD fFlags;
|
|
// DWORD dwBits;
|
|
// } SecPkgContext_LocalCredentialInfo;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryRemoteCred(
|
|
PSPContext pContext,
|
|
PVOID Buffer)
|
|
{
|
|
SecPkgContext_LocalCredentialInfo *pCredInfo;
|
|
PCCERT_CONTEXT pCertContext = NULL;
|
|
PUBLICKEY * pKey = NULL;
|
|
RSAPUBKEY * pk = NULL;
|
|
SP_STATUS pctRet;
|
|
PBYTE pbCert;
|
|
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_REMOTE_CRED)\n"));
|
|
|
|
pCredInfo = (SecPkgContext_LocalCredentialInfo *)Buffer;
|
|
|
|
ZeroMemory(pCredInfo, sizeof(*pCredInfo));
|
|
|
|
if(pContext->RipeZombie->pbServerCertificate)
|
|
{
|
|
pctRet = DeserializeCertContext(&pCertContext,
|
|
pContext->RipeZombie->pbServerCertificate,
|
|
pContext->RipeZombie->cbServerCertificate);
|
|
if(pctRet != PCT_ERR_OK)
|
|
{
|
|
return SP_LOG_RESULT(pctRet);
|
|
}
|
|
}
|
|
|
|
if(pCertContext)
|
|
{
|
|
pbCert = LocalAlloc(LPTR, pCertContext->cbCertEncoded);
|
|
if(pbCert == NULL)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
|
|
}
|
|
memcpy(pbCert, pCertContext->pbCertEncoded, pCertContext->cbCertEncoded);
|
|
|
|
pCredInfo->fFlags |= LCRED_CRED_EXISTS;
|
|
|
|
pCredInfo->pbCertificateChain = pbCert;
|
|
pCredInfo->cbCertificateChain = pCertContext->cbCertEncoded;
|
|
pCredInfo->cCertificates = 1;
|
|
pCredInfo->dwBits = 0;
|
|
|
|
// Compute number of bits in the certificate's public key.
|
|
pctRet = SPPublicKeyFromCert(pCertContext, &pKey, NULL);
|
|
if(pctRet == PCT_ERR_OK)
|
|
{
|
|
pk = (RSAPUBKEY *)((pKey->pPublic) + 1);
|
|
if(pk)
|
|
{
|
|
pCredInfo->dwBits = pk->bitlen;
|
|
}
|
|
|
|
SPExternalFree(pKey);
|
|
}
|
|
|
|
CertFreeCertificateContext(pCertContext);
|
|
}
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryNames
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_NAMES context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_NamesW
|
|
// {
|
|
// SEC_WCHAR SEC_FAR * sUserName;
|
|
// } SecPkgContext_NamesW;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryNames(
|
|
PSPContext pContext,
|
|
SecPkgContext_Names *pNames)
|
|
{
|
|
SECURITY_STATUS Status;
|
|
PCCERT_CONTEXT pCert = NULL;
|
|
DWORD cchSubject;
|
|
DWORD cbSubject;
|
|
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_NAMES)\n"));
|
|
|
|
//
|
|
// Obtain data from Schannel.
|
|
//
|
|
|
|
if(pContext->RipeZombie->pbServerCertificate == NULL)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|
|
|
|
Status = DeserializeCertContext(&pCert,
|
|
pContext->RipeZombie->pbServerCertificate,
|
|
pContext->RipeZombie->cbServerCertificate);
|
|
if(Status != PCT_ERR_OK)
|
|
{
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
//
|
|
// Build name string.
|
|
//
|
|
|
|
if(0 >= (cchSubject = CertNameToStr(pCert->dwCertEncodingType,
|
|
&pCert->pCertInfo->Subject,
|
|
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
|
|
NULL,
|
|
0)))
|
|
{
|
|
CertFreeCertificateContext(pCert);
|
|
return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|
|
cbSubject = (cchSubject + 1) * sizeof(TCHAR);
|
|
|
|
pNames->sUserName = LocalAlloc(LPTR, cbSubject);
|
|
if(pNames->sUserName == NULL)
|
|
{
|
|
CertFreeCertificateContext(pCert);
|
|
return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
|
|
}
|
|
|
|
if(0 >= CertNameToStr(pCert->dwCertEncodingType,
|
|
&pCert->pCertInfo->Subject,
|
|
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
|
|
pNames->sUserName,
|
|
cchSubject))
|
|
{
|
|
CertFreeCertificateContext(pCert);
|
|
LocalFree(pNames->sUserName);
|
|
return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|
|
|
|
CertFreeCertificateContext(pCert);
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryPackageInfo
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_PACKAGE_INFO context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_PackageInfoW
|
|
// {
|
|
// PSecPkgInfoW PackageInfo;
|
|
// } SecPkgContext_PackageInfoW, SEC_FAR * PSecPkgContext_PackageInfoW;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryPackageInfo(
|
|
PSPContext pContext,
|
|
PVOID Buffer)
|
|
{
|
|
PSecPkgContext_PackageInfoW pPackageInfo;
|
|
SecPkgInfoW Info;
|
|
DWORD cbName;
|
|
DWORD cbComment;
|
|
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_PACKAGE_INFO)\n"));
|
|
|
|
SpSslGetInfo(&Info);
|
|
|
|
pPackageInfo = (PSecPkgContext_PackageInfoW)Buffer;
|
|
|
|
cbName = (lstrlen(Info.Name) + 1) * sizeof(WCHAR);
|
|
cbComment = (lstrlen(Info.Comment) + 1) * sizeof(WCHAR);
|
|
|
|
pPackageInfo->PackageInfo = LocalAlloc(LPTR, sizeof(SecPkgInfo) + cbName + cbComment);
|
|
|
|
if(pPackageInfo->PackageInfo == NULL)
|
|
{
|
|
return SP_LOG_RESULT(STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
pPackageInfo->PackageInfo->wVersion = Info.wVersion;
|
|
pPackageInfo->PackageInfo->wRPCID = Info.wRPCID;
|
|
pPackageInfo->PackageInfo->fCapabilities = Info.fCapabilities;
|
|
pPackageInfo->PackageInfo->cbMaxToken = Info.cbMaxToken;
|
|
|
|
pPackageInfo->PackageInfo->Name = (LPWSTR)(pPackageInfo->PackageInfo + 1);
|
|
pPackageInfo->PackageInfo->Comment = (LPWSTR)((PBYTE)pPackageInfo->PackageInfo->Name + cbName);
|
|
|
|
lstrcpy(
|
|
pPackageInfo->PackageInfo->Name,
|
|
Info.Name);
|
|
|
|
lstrcpy(
|
|
pPackageInfo->PackageInfo->Comment,
|
|
Info.Comment);
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryProtoInfo
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_PROTO_INFO context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_ProtoInfoW
|
|
// {
|
|
// SEC_WCHAR SEC_FAR * sProtocolName;
|
|
// unsigned long majorVersion;
|
|
// unsigned long minorVersion;
|
|
// } SecPkgContext_ProtoInfoW;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryProtoInfo(
|
|
PSPContext pContext,
|
|
PVOID Buffer)
|
|
{
|
|
SecPkgContext_ProtoInfo *pProtoInfo;
|
|
DWORD index;
|
|
DWORD cbName;
|
|
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_PROTO_INFO)\n"));
|
|
|
|
pProtoInfo = (SecPkgContext_ProtoInfo *)Buffer;
|
|
|
|
for(index = 0;
|
|
index < sizeof(rgProts) / sizeof(PROTO_ID);
|
|
index += 1)
|
|
{
|
|
if(pContext->RipeZombie->fProtocol == rgProts[index].dwProtoId)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if(index >= sizeof(rgProts) / sizeof(PROTO_ID))
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|
|
|
|
cbName = (lstrlen(rgProts[index].szProto) + 1) * sizeof(WCHAR);
|
|
|
|
pProtoInfo->sProtocolName = LocalAlloc(LPTR, cbName);
|
|
if(pProtoInfo->sProtocolName == NULL)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
|
|
}
|
|
lstrcpy(pProtoInfo->sProtocolName, rgProts[index].szProto);
|
|
|
|
pProtoInfo->majorVersion = rgProts[index].dwMajor;
|
|
pProtoInfo->minorVersion = rgProts[index].dwMinor;
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQuerySizes
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_SIZES context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_Sizes
|
|
// {
|
|
// unsigned long cbMaxToken;
|
|
// unsigned long cbMaxSignature;
|
|
// unsigned long cbBlockSize;
|
|
// unsigned long cbSecurityTrailer;
|
|
// } SecPkgContext_Sizes;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQuerySizes(
|
|
PSPContext pContext,
|
|
SecPkgContext_Sizes *pSizes)
|
|
{
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_SIZES)\n"));
|
|
|
|
if (NULL == pContext->pCipherInfo ||
|
|
NULL == pContext->pHashInfo)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INVALID_HANDLE);
|
|
}
|
|
|
|
switch(pContext->RipeZombie->fProtocol)
|
|
{
|
|
case SP_PROT_SSL2_CLIENT:
|
|
case SP_PROT_SSL2_SERVER:
|
|
pSizes->cbMaxToken = SSL2_MAX_MESSAGE_LENGTH;
|
|
pSizes->cbSecurityTrailer = 2 + pContext->pHashInfo->cbCheckSum;
|
|
if(pContext->pCipherInfo->dwBlockSize > 1)
|
|
{
|
|
pSizes->cbSecurityTrailer += 1 + pContext->pCipherInfo->dwBlockSize; // 3 byte header
|
|
}
|
|
break;
|
|
|
|
case SP_PROT_PCT1_CLIENT:
|
|
case SP_PROT_PCT1_SERVER:
|
|
pSizes->cbMaxToken = PCT1_MAX_MESSAGE_LENGTH;
|
|
pSizes->cbSecurityTrailer = 2 + pContext->pHashInfo->cbCheckSum;
|
|
if(pContext->pCipherInfo->dwBlockSize > 1)
|
|
{
|
|
pSizes->cbSecurityTrailer += 1 + pContext->pCipherInfo->dwBlockSize; // 3 byte header
|
|
}
|
|
break;
|
|
|
|
case SP_PROT_SSL3_CLIENT:
|
|
case SP_PROT_SSL3_SERVER:
|
|
case SP_PROT_TLS1_CLIENT:
|
|
case SP_PROT_TLS1_SERVER:
|
|
pSizes->cbMaxToken = SSL3_MAX_MESSAGE_LENGTH;
|
|
pSizes->cbSecurityTrailer = 5 + pContext->pHashInfo->cbCheckSum;
|
|
if(pContext->pCipherInfo->dwBlockSize > 1)
|
|
{
|
|
pSizes->cbSecurityTrailer += pContext->pCipherInfo->dwBlockSize;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
pSizes->cbMaxToken = SSL3_MAX_MESSAGE_LENGTH;
|
|
pSizes->cbSecurityTrailer = 0;
|
|
}
|
|
|
|
pSizes->cbMaxSignature = pContext->pHashInfo->cbCheckSum;
|
|
pSizes->cbBlockSize = pContext->pCipherInfo->dwBlockSize;
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryStreamSizes
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_STREAM_SIZES context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_StreamSizes
|
|
// {
|
|
// unsigned long cbHeader;
|
|
// unsigned long cbTrailer;
|
|
// unsigned long cbMaximumMessage;
|
|
// unsigned long cBuffers;
|
|
// unsigned long cbBlockSize;
|
|
// } SecPkgContext_StreamSizes;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryStreamSizes(
|
|
PSPContext pContext,
|
|
SecPkgContext_StreamSizes *pStreamSizes)
|
|
{
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_STREAM_SIZES)\n"));
|
|
|
|
if (NULL == pContext->pCipherInfo ||
|
|
NULL == pContext->pHashInfo)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INVALID_HANDLE);
|
|
}
|
|
|
|
switch(pContext->RipeZombie->fProtocol)
|
|
{
|
|
case SP_PROT_SSL2_CLIENT:
|
|
case SP_PROT_SSL2_SERVER:
|
|
pStreamSizes->cbMaximumMessage = SSL2_MAX_MESSAGE_LENGTH;
|
|
pStreamSizes->cbHeader = 2 + pContext->pHashInfo->cbCheckSum;
|
|
pStreamSizes->cbTrailer = 0;
|
|
if(pContext->pCipherInfo->dwBlockSize > 1)
|
|
{
|
|
pStreamSizes->cbHeader += 1; // 3 byte header
|
|
pStreamSizes->cbTrailer += pContext->pCipherInfo->dwBlockSize;
|
|
}
|
|
break;
|
|
|
|
case SP_PROT_PCT1_CLIENT:
|
|
case SP_PROT_PCT1_SERVER:
|
|
pStreamSizes->cbMaximumMessage = PCT1_MAX_MESSAGE_LENGTH;
|
|
pStreamSizes->cbHeader = 2;
|
|
pStreamSizes->cbTrailer = pContext->pHashInfo->cbCheckSum;
|
|
if(pContext->pCipherInfo->dwBlockSize > 1)
|
|
{
|
|
pStreamSizes->cbHeader += 1; // 3 byte header
|
|
pStreamSizes->cbTrailer += pContext->pCipherInfo->dwBlockSize;
|
|
}
|
|
break;
|
|
|
|
case SP_PROT_TLS1_CLIENT:
|
|
case SP_PROT_TLS1_SERVER:
|
|
case SP_PROT_SSL3_CLIENT:
|
|
case SP_PROT_SSL3_SERVER:
|
|
pStreamSizes->cbMaximumMessage = SSL3_MAX_MESSAGE_LENGTH;
|
|
pStreamSizes->cbHeader = 5;
|
|
pStreamSizes->cbTrailer = pContext->pHashInfo->cbCheckSum;
|
|
if(pContext->pCipherInfo->dwBlockSize > 1)
|
|
{
|
|
pStreamSizes->cbTrailer += pContext->pCipherInfo->dwBlockSize;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
pStreamSizes->cbMaximumMessage = SSL3_MAX_MESSAGE_LENGTH;
|
|
pStreamSizes->cbHeader = 0;
|
|
pStreamSizes->cbTrailer = 0;
|
|
}
|
|
|
|
pStreamSizes->cbBlockSize = pContext->pCipherInfo->dwBlockSize;
|
|
|
|
pStreamSizes->cBuffers = 4;
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryEapKeyBlock
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_EAP_KEY_BLOCK context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_EapKeyBlock
|
|
// {
|
|
// BYTE rgbKeys[128];
|
|
// BYTE rgbIVs[64];
|
|
// } SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryEapKeyBlock(
|
|
LSA_SEC_HANDLE ContextHandle,
|
|
PVOID Buffer)
|
|
{
|
|
SecPkgContext_EapKeyBlock KeyBlock;
|
|
DWORD Size;
|
|
PSPContext pContext;
|
|
SECURITY_STATUS Status;
|
|
|
|
HCRYPTHASH hHash;
|
|
CRYPT_DATA_BLOB Data;
|
|
UCHAR rgbRandom[CB_SSL3_RANDOM + CB_SSL3_RANDOM];
|
|
DWORD cbRandom;
|
|
DWORD cbData;
|
|
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_EAP_KEY_BLOCK)\n"));
|
|
|
|
pContext = (PSPContext)ContextHandle;
|
|
Size = sizeof( SecPkgContext_EapKeyBlock );
|
|
|
|
//
|
|
// Obtain data from Schannel.
|
|
//
|
|
|
|
if(!(pContext->RipeZombie->fProtocol & SP_PROT_TLS1))
|
|
{
|
|
// This attribute is defined for TLS only.
|
|
return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|
|
|
|
if(!pContext->RipeZombie->hMasterKey)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INVALID_HANDLE);
|
|
}
|
|
|
|
// Build random buffer.
|
|
CopyMemory(rgbRandom, pContext->rgbS3CRandom, CB_SSL3_RANDOM);
|
|
CopyMemory(rgbRandom + CB_SSL3_RANDOM, pContext->rgbS3SRandom, CB_SSL3_RANDOM);
|
|
cbRandom = CB_SSL3_RANDOM + CB_SSL3_RANDOM;
|
|
|
|
// rgbKeys = PRF(master_secret, "client EAP encryption", client_random + server_random);
|
|
|
|
// Compute the PRF
|
|
if(!CryptCreateHash(pContext->RipeZombie->hMasterProv,
|
|
CALG_TLS1PRF,
|
|
pContext->RipeZombie->hMasterKey,
|
|
0,
|
|
&hHash))
|
|
{
|
|
SP_LOG_RESULT(GetLastError());
|
|
return SEC_E_INTERNAL_ERROR;
|
|
}
|
|
|
|
Data.pbData = TLS1_LABEL_EAP_KEYS;
|
|
Data.cbData = CB_TLS1_LABEL_EAP_KEYS;
|
|
if(!CryptSetHashParam(hHash,
|
|
HP_TLS1PRF_LABEL,
|
|
(PBYTE)&Data,
|
|
0))
|
|
{
|
|
SP_LOG_RESULT(GetLastError());
|
|
CryptDestroyHash(hHash);
|
|
return SEC_E_INTERNAL_ERROR;
|
|
}
|
|
|
|
Data.pbData = rgbRandom;
|
|
Data.cbData = cbRandom;
|
|
if(!CryptSetHashParam(hHash,
|
|
HP_TLS1PRF_SEED,
|
|
(PBYTE)&Data,
|
|
0))
|
|
{
|
|
SP_LOG_RESULT(GetLastError());
|
|
CryptDestroyHash(hHash);
|
|
return SEC_E_INTERNAL_ERROR;
|
|
}
|
|
|
|
cbData = sizeof(KeyBlock.rgbKeys);
|
|
if(!CryptGetHashParam(hHash,
|
|
HP_HASHVAL,
|
|
KeyBlock.rgbKeys,
|
|
&cbData,
|
|
0))
|
|
{
|
|
SP_LOG_RESULT(GetLastError());
|
|
CryptDestroyHash(hHash);
|
|
return SEC_E_INTERNAL_ERROR;
|
|
}
|
|
SP_ASSERT(cbData == sizeof(KeyBlock.rgbKeys));
|
|
|
|
CryptDestroyHash(hHash);
|
|
|
|
|
|
// IVs = PRF("", "client EAP encryption", client_random + server_random)
|
|
|
|
if(!PRF(NULL, 0,
|
|
TLS1_LABEL_EAP_KEYS, CB_TLS1_LABEL_EAP_KEYS,
|
|
rgbRandom, sizeof(rgbRandom),
|
|
KeyBlock.rgbIVs, sizeof(KeyBlock.rgbIVs)))
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
|
|
}
|
|
|
|
//
|
|
// Copy structure back to client memory.
|
|
//
|
|
|
|
Status = LsaTable->CopyToClientBuffer( NULL,
|
|
Size,
|
|
Buffer,
|
|
&KeyBlock );
|
|
if(FAILED(Status))
|
|
{
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryMappedCredProp
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_MAPPED_CRED_PROP context
|
|
// attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_MappedCredProp
|
|
// {
|
|
// DWORD dwProperty;
|
|
// PBYTE pbBuffer;
|
|
// } SecPkgContext_MappedCredProp;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryMappedCredAttr(
|
|
PSPContext pContext,
|
|
PVOID Buffer)
|
|
{
|
|
SecPkgContext_MappedCredAttr *pMappedCredAttr;
|
|
HMAPPER *phMapper;
|
|
DWORD cbBuffer;
|
|
SECURITY_STATUS Status;
|
|
|
|
pMappedCredAttr = (SecPkgContext_MappedCredAttr *)Buffer;
|
|
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_MAPPED_CRED_ATTR %d)\n", pMappedCredAttr->dwAttribute));
|
|
|
|
if(pContext->RipeZombie == NULL)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INVALID_HANDLE);
|
|
}
|
|
|
|
phMapper = pContext->RipeZombie->phMapper;
|
|
if(phMapper == NULL)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INVALID_HANDLE);
|
|
}
|
|
|
|
if(phMapper->m_dwFlags & SCH_FLAG_SYSTEM_MAPPER)
|
|
{
|
|
// System mapper.
|
|
return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|
|
else
|
|
{
|
|
// Application mapper.
|
|
Status = phMapper->m_vtable->QueryMappedCredentialAttributes(
|
|
phMapper,
|
|
pContext->RipeZombie->hLocator,
|
|
pMappedCredAttr->dwAttribute,
|
|
NULL,
|
|
&cbBuffer);
|
|
if(FAILED(Status))
|
|
{
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
|
|
pMappedCredAttr->pvBuffer = LocalAlloc(LPTR, cbBuffer);
|
|
if(pMappedCredAttr->pvBuffer == NULL)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
|
|
}
|
|
|
|
Status = phMapper->m_vtable->QueryMappedCredentialAttributes(
|
|
phMapper,
|
|
pContext->RipeZombie->hLocator,
|
|
pMappedCredAttr->dwAttribute,
|
|
pMappedCredAttr->pvBuffer,
|
|
&cbBuffer);
|
|
if(FAILED(Status))
|
|
{
|
|
LocalFree(pMappedCredAttr->pvBuffer);
|
|
return SP_LOG_RESULT(Status);
|
|
}
|
|
}
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryApplicationData
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_APP_DATA context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_SessionAppData
|
|
// {
|
|
// DWORD dwFlags;
|
|
// DWORD cbAppData;
|
|
// PBYTE pbAppData;
|
|
// } SecPkgContext_SessionAppData, *PSecPkgContext_SessionAppData;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQueryApplicationData(
|
|
LSA_SEC_HANDLE ContextHandle,
|
|
PVOID Buffer)
|
|
{
|
|
SecPkgContext_SessionAppData AppData;
|
|
PBYTE pbAppData = NULL;
|
|
DWORD cbAppData = 0;
|
|
PSPContext pContext;
|
|
SECURITY_STATUS Status;
|
|
PVOID pvClient = NULL;
|
|
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_APP_DATA)\n"));
|
|
|
|
pContext = (PSPContext)ContextHandle;
|
|
|
|
if(pContext == NULL || pContext->RipeZombie == NULL)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INVALID_HANDLE);
|
|
}
|
|
|
|
//
|
|
// Get application data from cache.
|
|
//
|
|
|
|
Status = GetCacheAppData(pContext->RipeZombie, &pbAppData, &cbAppData);
|
|
|
|
if(FAILED(Status))
|
|
{
|
|
SP_LOG_RESULT(Status);
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Allocate memory for application data in application process.
|
|
//
|
|
|
|
if(pbAppData != NULL)
|
|
{
|
|
Status = LsaTable->AllocateClientBuffer(
|
|
NULL,
|
|
cbAppData,
|
|
&pvClient);
|
|
if(FAILED(Status))
|
|
{
|
|
SP_LOG_RESULT(Status);
|
|
goto cleanup;
|
|
}
|
|
|
|
Status = LsaTable->CopyToClientBuffer(
|
|
NULL,
|
|
cbAppData,
|
|
pvClient,
|
|
pbAppData);
|
|
if(FAILED(Status))
|
|
{
|
|
SP_LOG_RESULT(Status);
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Build output structure.
|
|
//
|
|
|
|
ZeroMemory(&AppData, sizeof(AppData));
|
|
|
|
AppData.cbAppData = cbAppData;
|
|
AppData.pbAppData = pvClient;
|
|
|
|
|
|
//
|
|
// Copy output structure back to client memory.
|
|
//
|
|
|
|
Status = LsaTable->CopyToClientBuffer( NULL,
|
|
sizeof(SecPkgContext_SessionAppData),
|
|
Buffer,
|
|
&AppData);
|
|
if(FAILED(Status))
|
|
{
|
|
SP_LOG_RESULT(Status);
|
|
goto cleanup;
|
|
}
|
|
|
|
// Operation has succeeded, so consume this buffer.
|
|
pvClient = NULL;
|
|
|
|
|
|
cleanup:
|
|
|
|
if(pvClient)
|
|
{
|
|
LsaTable->FreeClientBuffer(NULL, pvClient);
|
|
}
|
|
|
|
if(pbAppData)
|
|
{
|
|
SPExternalFree(pbAppData);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQuerySessionInfo
|
|
//
|
|
// Synopsis: Retrieves the SECPKG_ATTR_SESSION_INFO context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer returned contains the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_SessionInfo
|
|
// {
|
|
// DWORD dwFlags;
|
|
// DWORD cbSessionId;
|
|
// BYTE rgbSessionId[32];
|
|
// } SecPkgContext_SessionInfo, *PSecPkgContext_SessionInfo;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SpQuerySessionInfo(
|
|
PSPContext pContext,
|
|
SecPkgContext_SessionInfo *pSessionInfo)
|
|
{
|
|
DebugLog((DEB_TRACE, "QueryContextAttributes(SECPKG_ATTR_SESSION_INFO)\n"));
|
|
|
|
if (NULL == pContext->RipeZombie)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INVALID_HANDLE);
|
|
}
|
|
|
|
ZeroMemory(pSessionInfo, sizeof(SecPkgContext_SessionInfo));
|
|
|
|
if(!(pContext->Flags & CONTEXT_FLAG_FULL_HANDSHAKE))
|
|
{
|
|
pSessionInfo->dwFlags = SSL_SESSION_RECONNECT;
|
|
}
|
|
|
|
pSessionInfo->cbSessionId = pContext->RipeZombie->cbSessionID;
|
|
|
|
memcpy(pSessionInfo->rgbSessionId, pContext->RipeZombie->SessionID, pContext->RipeZombie->cbSessionID);
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpQueryContextAttributes
|
|
//
|
|
// Synopsis: Querys attributes of the specified context
|
|
//
|
|
// Effects:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The following attributes are supported by the Schannel
|
|
// package:
|
|
//
|
|
// SECPKG_ATTR_AUTHORITY
|
|
// SECPKG_ATTR_CONNECTION_INFO
|
|
// SECPKG_ATTR_ISSUER_LIST
|
|
// SECPKG_ATTR_ISSUER_LIST_EX
|
|
// SECPKG_ATTR_KEY_INFO
|
|
// SECPKG_ATTR_LIFESPAN
|
|
// SECPKG_ATTR_LOCAL_CERT_CONTEXT
|
|
// SECPKG_ATTR_LOCAL_CRED
|
|
// SECPKG_ATTR_NAMES
|
|
// SECPKG_ATTR_PROTO_INFO
|
|
// SECPKG_ATTR_REMOTE_CERT_CONTEXT
|
|
// SECPKG_ATTR_REMOTE_CRED
|
|
// SECPKG_ATTR_SIZES
|
|
// SECPKG_ATTR_STREAM_SIZES
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SECURITY_STATUS
|
|
SEC_ENTRY
|
|
SpLsaQueryContextAttributes(
|
|
LSA_SEC_HANDLE Context,
|
|
ULONG Attribute,
|
|
PVOID Buffer)
|
|
{
|
|
SECURITY_STATUS Status;
|
|
PSPContext pContext;
|
|
|
|
pContext = (PSPContext)Context;
|
|
|
|
switch(Attribute)
|
|
{
|
|
case SECPKG_ATTR_AUTHORITY :
|
|
Status = SpQueryAuthority(Context, Buffer);
|
|
break;
|
|
|
|
case SECPKG_ATTR_ISSUER_LIST :
|
|
Status = SpQueryIssuerList(Context, Buffer);
|
|
break;
|
|
|
|
case SECPKG_ATTR_ISSUER_LIST_EX:
|
|
Status = SpQueryIssuerListEx(Context, Buffer);
|
|
break;
|
|
|
|
// case SECPKG_ATTR_KEY_INFO :
|
|
// Status = SpQueryKeyInfo(Context, Buffer);
|
|
// break;
|
|
|
|
// case SECPKG_ATTR_LIFESPAN :
|
|
// Status = SpQueryLifespan(Context, Buffer);
|
|
// break;
|
|
|
|
case SECPKG_ATTR_LOCAL_CERT_CONTEXT:
|
|
Status = SpQueryLocalCertContext(Context, Buffer);
|
|
break;
|
|
|
|
case SECPKG_ATTR_LOCAL_CRED:
|
|
Status = SpQueryLocalCred(Context, Buffer);
|
|
break;
|
|
|
|
// case SECPKG_ATTR_NAMES :
|
|
// Status = SpQueryNames(Context, Buffer);
|
|
// break;
|
|
|
|
// case SECPKG_ATTR_PROTO_INFO:
|
|
// Status = SpQueryProtoInfo(Context, Buffer);
|
|
// break;
|
|
|
|
// case SECPKG_ATTR_REMOTE_CERT_CONTEXT:
|
|
// Status = SpQueryCertContext(Context, Buffer, FALSE);
|
|
// break;
|
|
|
|
// case SECPKG_ATTR_REMOTE_CRED:
|
|
// Status = SpQueryRemoteCred(Context, Buffer);
|
|
// break;
|
|
|
|
// case SECPKG_ATTR_SIZES:
|
|
// Status = SpQuerySizes(Context, Buffer);
|
|
// break;
|
|
|
|
// case SECPKG_ATTR_STREAM_SIZES:
|
|
// Status = SpQueryStreamSizes(Context, Buffer);
|
|
// break;
|
|
|
|
case SECPKG_ATTR_EAP_KEY_BLOCK:
|
|
Status = SpQueryEapKeyBlock(Context, Buffer);
|
|
break;
|
|
|
|
// case SECPKG_ATTR_MAPPED_CRED_ATTR:
|
|
// Status = SpQueryMappedCredAttr(Context, Buffer);
|
|
// break;
|
|
|
|
case SECPKG_ATTR_APP_DATA:
|
|
Status = SpQueryApplicationData(Context, Buffer);
|
|
break;
|
|
|
|
default:
|
|
DebugLog((DEB_ERROR, "QueryContextAttributes(unsupported function %d)\n", Attribute));
|
|
|
|
return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpUserQueryContextAttributes
|
|
//
|
|
// Synopsis: User mode QueryContextAttribute.
|
|
//
|
|
// Effects:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
NTSTATUS NTAPI
|
|
SpUserQueryContextAttributes(
|
|
IN LSA_SEC_HANDLE ContextHandle,
|
|
IN ULONG ContextAttribute,
|
|
IN OUT PVOID pBuffer
|
|
)
|
|
{
|
|
PSSL_USER_CONTEXT Context;
|
|
PSPContext pContext;
|
|
SECURITY_STATUS Status;
|
|
|
|
Context = SslFindUserContext( ContextHandle );
|
|
|
|
if(Context == NULL)
|
|
{
|
|
return(SEC_E_INVALID_HANDLE);
|
|
}
|
|
|
|
pContext = Context->pContext;
|
|
if(!pContext)
|
|
{
|
|
return(SEC_E_INVALID_HANDLE);
|
|
}
|
|
|
|
switch(ContextAttribute)
|
|
{
|
|
case SECPKG_ATTR_CONNECTION_INFO:
|
|
Status = SpQueryConnectionInfo(pContext, pBuffer);
|
|
break;
|
|
|
|
case SECPKG_ATTR_KEY_INFO:
|
|
Status = SpQueryKeyInfo(pContext, pBuffer);
|
|
break;
|
|
|
|
case SECPKG_ATTR_LIFESPAN:
|
|
Status = SpQueryLifespan(pContext, pBuffer);
|
|
break;
|
|
|
|
case SECPKG_ATTR_NAMES :
|
|
Status = SpQueryNames(pContext, pBuffer);
|
|
break;
|
|
|
|
case SECPKG_ATTR_PACKAGE_INFO:
|
|
Status = SpQueryPackageInfo(pContext, pBuffer);
|
|
break;
|
|
|
|
case SECPKG_ATTR_PROTO_INFO:
|
|
Status = SpQueryProtoInfo(pContext, pBuffer);
|
|
break;
|
|
|
|
case SECPKG_ATTR_REMOTE_CERT_CONTEXT:
|
|
Status = SpQueryRemoteCertContext(pContext, pBuffer);
|
|
break;
|
|
|
|
case SECPKG_ATTR_REMOTE_CRED:
|
|
Status = SpQueryRemoteCred(pContext, pBuffer);
|
|
break;
|
|
|
|
case SECPKG_ATTR_SIZES:
|
|
Status = SpQuerySizes(pContext, pBuffer);
|
|
break;
|
|
|
|
case SECPKG_ATTR_STREAM_SIZES:
|
|
Status = SpQueryStreamSizes(pContext, pBuffer);
|
|
break;
|
|
|
|
case SECPKG_ATTR_MAPPED_CRED_ATTR:
|
|
Status = SpQueryMappedCredAttr(pContext, pBuffer);
|
|
break;
|
|
|
|
case SECPKG_ATTR_ACCESS_TOKEN:
|
|
Status = SpQueryAccessToken(pContext, pBuffer);
|
|
break;
|
|
|
|
case SECPKG_ATTR_SESSION_INFO:
|
|
Status = SpQuerySessionInfo(pContext, pBuffer);
|
|
break;
|
|
|
|
default:
|
|
DebugLog((DEB_ERROR, "QueryContextAttributes(unsupported function %d)\n", ContextAttribute));
|
|
|
|
return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpSetUseValidatedProp
|
|
//
|
|
// Synopsis: Sets the SECPKG_ATTR_USE_VALIDATED context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer must contain a DWORD indicating whether the
|
|
// credential currently associated with the context has been
|
|
// validated for use.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
NTSTATUS
|
|
SpSetUseValidatedProp(
|
|
IN PSPContext pContext,
|
|
IN PVOID Buffer,
|
|
IN ULONG BufferSize)
|
|
{
|
|
DWORD dwUseValidated;
|
|
NTSTATUS Status;
|
|
|
|
DebugLog((DEB_TRACE, "SetContextAttributes(SECPKG_ATTR_USE_VALIDATED)\n"));
|
|
|
|
if(BufferSize < sizeof(DWORD))
|
|
{
|
|
Status = SP_LOG_RESULT(STATUS_INVALID_PARAMETER);
|
|
goto cleanup;
|
|
}
|
|
|
|
Status = LsaTable->CopyFromClientBuffer( NULL,
|
|
sizeof(DWORD),
|
|
&dwUseValidated,
|
|
Buffer );
|
|
if(FAILED(Status))
|
|
{
|
|
SP_LOG_RESULT(Status);
|
|
goto cleanup;
|
|
}
|
|
|
|
DebugLog((DEB_TRACE, "Use validated:%d\n", dwUseValidated));
|
|
|
|
if(pContext->RipeZombie == NULL)
|
|
{
|
|
Status = SP_LOG_RESULT(STATUS_INVALID_PARAMETER);
|
|
goto cleanup;
|
|
}
|
|
|
|
if(dwUseValidated)
|
|
{
|
|
pContext->RipeZombie->dwFlags |= SP_CACHE_FLAG_USE_VALIDATED;
|
|
}
|
|
else
|
|
{
|
|
pContext->RipeZombie->dwFlags &= ~SP_CACHE_FLAG_USE_VALIDATED;
|
|
}
|
|
|
|
cleanup:
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpSetCredentialNameProp
|
|
//
|
|
// Synopsis: Sets the SECPKG_ATTR_CREDENTIAL_NAME context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer must contain the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_CredentialNameW
|
|
// {
|
|
// unsigned long CredentialType;
|
|
// SEC_WCHAR SEC_FAR *sCredentialName;
|
|
// } SecPkgContext_CredentialNameW, SEC_FAR * PSecPkgContext_CredentialNameW;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
NTSTATUS
|
|
SpSetCredentialNameProp(
|
|
IN PSPContext pContext,
|
|
IN PVOID Buffer,
|
|
IN ULONG BufferSize)
|
|
{
|
|
PSecPkgContext_CredentialNameW pCredentialName = NULL;
|
|
DWORD_PTR Offset;
|
|
NTSTATUS Status;
|
|
|
|
DebugLog((DEB_TRACE, "SetContextAttributes(SECPKG_ATTR_CREDENTIAL_NAME)\n"));
|
|
|
|
//
|
|
// Marshal over the credential name from the client address space.
|
|
//
|
|
|
|
if(BufferSize < sizeof(SecPkgContext_CredentialNameW))
|
|
{
|
|
Status = SP_LOG_RESULT(STATUS_INVALID_PARAMETER);
|
|
goto cleanup;
|
|
}
|
|
|
|
pCredentialName = SPExternalAlloc(BufferSize + sizeof(WCHAR));
|
|
|
|
if(pCredentialName == NULL)
|
|
{
|
|
Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
|
|
goto cleanup;
|
|
}
|
|
|
|
Status = LsaTable->CopyFromClientBuffer( NULL,
|
|
BufferSize,
|
|
pCredentialName,
|
|
Buffer );
|
|
if(FAILED(Status))
|
|
{
|
|
SP_LOG_RESULT(Status);
|
|
goto cleanup;
|
|
}
|
|
|
|
if(pCredentialName->CredentialType != CRED_TYPE_DOMAIN_CERTIFICATE)
|
|
{
|
|
DebugLog((DEB_ERROR, "Unexpected credential type %d\n", pCredentialName->CredentialType));
|
|
Status = SEC_E_UNKNOWN_CREDENTIALS;
|
|
}
|
|
|
|
if((PVOID)pCredentialName->sCredentialName < Buffer ||
|
|
(PBYTE)pCredentialName->sCredentialName >= (PBYTE)Buffer + BufferSize)
|
|
{
|
|
Status = SP_LOG_RESULT(STATUS_INVALID_PARAMETER);
|
|
goto cleanup;
|
|
}
|
|
Offset = (PBYTE)pCredentialName->sCredentialName - (PBYTE)Buffer;
|
|
|
|
pCredentialName->sCredentialName = (LPWSTR)((PBYTE)pCredentialName + Offset);
|
|
|
|
DebugLog((DEB_TRACE, "Set client credential to '%ls'.\n", pCredentialName->sCredentialName));
|
|
|
|
|
|
//
|
|
// Associate the specified credential with the current context.
|
|
//
|
|
|
|
pContext->pszCredentialName = SPExternalAlloc((lstrlenW(pCredentialName->sCredentialName) + 1) * sizeof(WCHAR));
|
|
if(pContext->pszCredentialName == NULL)
|
|
{
|
|
Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
|
|
goto cleanup;
|
|
}
|
|
lstrcpyW(pContext->pszCredentialName, pCredentialName->sCredentialName);
|
|
|
|
|
|
Status = QueryCredentialManagerForCert(pContext,
|
|
pCredentialName->sCredentialName);
|
|
|
|
if(FAILED(Status))
|
|
{
|
|
SP_LOG_RESULT(Status);
|
|
goto cleanup;
|
|
}
|
|
|
|
DebugLog((DEB_TRACE, "Credential assigned to context successfully.\n"));
|
|
|
|
|
|
cleanup:
|
|
if(pCredentialName)
|
|
{
|
|
SPExternalFree(pCredentialName);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpSetApplicationData
|
|
//
|
|
// Synopsis: Sets the SECPKG_ATTR_APP_DATA context attribute.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: The buffer must contain the following structure:
|
|
//
|
|
// typedef struct _SecPkgContext_SessionAppData
|
|
// {
|
|
// DWORD dwFlags;
|
|
// DWORD cbAppData;
|
|
// PBYTE pbAppData;
|
|
// } SecPkgContext_SessionAppData, *PSecPkgContext_SessionAppData;
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
NTSTATUS
|
|
SpSetApplicationData(
|
|
IN PSPContext pContext,
|
|
IN PVOID Buffer,
|
|
IN ULONG BufferSize)
|
|
{
|
|
SecPkgContext_SessionAppData AppData;
|
|
PBYTE pbAppData = NULL;
|
|
NTSTATUS Status;
|
|
|
|
DebugLog((DEB_TRACE, "SetContextAttributes(SECPKG_ATTR_APP_DATA)\n"));
|
|
|
|
if(pContext->RipeZombie == NULL)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INVALID_HANDLE);
|
|
}
|
|
|
|
|
|
//
|
|
// Marshal over the input structure from the client address space.
|
|
//
|
|
|
|
if(BufferSize < sizeof(SecPkgContext_SessionAppData))
|
|
{
|
|
Status = SP_LOG_RESULT(STATUS_INVALID_PARAMETER);
|
|
goto cleanup;
|
|
}
|
|
|
|
Status = LsaTable->CopyFromClientBuffer( NULL,
|
|
sizeof(SecPkgContext_SessionAppData),
|
|
&AppData,
|
|
Buffer );
|
|
if(FAILED(Status))
|
|
{
|
|
SP_LOG_RESULT(Status);
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Marshal over the application data from the client address space.
|
|
//
|
|
|
|
// Limit application data size to 64k.
|
|
if(AppData.cbAppData > 0x10000)
|
|
{
|
|
Status = SP_LOG_RESULT(STATUS_INVALID_PARAMETER);
|
|
goto cleanup;
|
|
}
|
|
|
|
if(AppData.cbAppData == 0 || AppData.pbAppData == NULL)
|
|
{
|
|
Status = SP_LOG_RESULT(STATUS_INVALID_PARAMETER);
|
|
goto cleanup;
|
|
}
|
|
|
|
pbAppData = SPExternalAlloc(AppData.cbAppData);
|
|
|
|
if(pbAppData == NULL)
|
|
{
|
|
Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
|
|
goto cleanup;
|
|
}
|
|
|
|
Status = LsaTable->CopyFromClientBuffer( NULL,
|
|
AppData.cbAppData,
|
|
pbAppData,
|
|
AppData.pbAppData );
|
|
if(FAILED(Status))
|
|
{
|
|
SP_LOG_RESULT(Status);
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Assign application data to cache entry.
|
|
//
|
|
|
|
Status = SetCacheAppData(pContext->RipeZombie,
|
|
pbAppData,
|
|
AppData.cbAppData);
|
|
|
|
if(!FAILED(Status))
|
|
{
|
|
// The operation succeeded, so consume the application data.
|
|
pbAppData = NULL;
|
|
}
|
|
|
|
|
|
cleanup:
|
|
if(pbAppData)
|
|
{
|
|
SPExternalFree(pbAppData);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
SpSetContextAttributes(
|
|
IN LSA_SEC_HANDLE ContextHandle,
|
|
IN ULONG ContextAttribute,
|
|
IN PVOID Buffer,
|
|
IN ULONG BufferSize)
|
|
{
|
|
NTSTATUS Status;
|
|
PSPContext pContext;
|
|
|
|
pContext = (PSPContext)ContextHandle;
|
|
|
|
switch(ContextAttribute)
|
|
{
|
|
case SECPKG_ATTR_USE_VALIDATED:
|
|
DebugLog((DEB_TRACE, "SetContextAttributes(SECPKG_ATTR_USE_VALIDATED)\n"));
|
|
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case SECPKG_ATTR_CREDENTIAL_NAME:
|
|
Status = SpSetCredentialNameProp(pContext, Buffer, BufferSize);
|
|
break;
|
|
|
|
case SECPKG_ATTR_TARGET_INFORMATION:
|
|
DebugLog((DEB_TRACE, "SetContextAttributes(SECPKG_ATTR_TARGET_INFORMATION)\n"));
|
|
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case SECPKG_ATTR_APP_DATA:
|
|
Status = SpSetApplicationData(pContext, Buffer, BufferSize);
|
|
break;
|
|
|
|
default:
|
|
DebugLog((DEB_ERROR, "SetContextAttributes(unsupported function %d)\n", ContextAttribute));
|
|
|
|
Status = SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|