You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1609 lines
45 KiB
1609 lines
45 KiB
/*++
|
|
|
|
Copyright (c) 1997-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
efscert.cxx
|
|
|
|
Abstract:
|
|
|
|
EFS Certificate management code
|
|
|
|
Author:
|
|
|
|
Robert Reichel (RobertRe) July 4, 1997
|
|
Robert Gu (RobertG) Dec. 4, 1997
|
|
|
|
Environment:
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <lsapch.hxx>
|
|
|
|
extern "C" {
|
|
#include <nt.h>
|
|
#include <ntdef.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <wincrypt.h>
|
|
#include <efsstruc.h>
|
|
#include "lsasrvp.h"
|
|
#include "debug.h"
|
|
#include "efssrv.hxx"
|
|
#include "userkey.h"
|
|
}
|
|
|
|
//#define ProfilingEfs
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// /
|
|
// /
|
|
// Helper Functions /
|
|
// /
|
|
// /
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
PCCERT_CONTEXT
|
|
GetCertContextFromCertHash(
|
|
IN PBYTE pbHash,
|
|
IN DWORD cbHash,
|
|
IN DWORD dwFlags,
|
|
IN DWORD dwOpen
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Finds the cert with the passed cert hash in the user's MY store
|
|
and returns a context pointer.
|
|
|
|
Arguments:
|
|
|
|
pbHash - Supplies a pointer to the hash to be matched.
|
|
|
|
cbHash - Supplies the length in bytes of the passed hash.
|
|
|
|
dwFlags - Supplies flags to CertOpenStore
|
|
|
|
dwOpen - 0 if not in the file open path
|
|
|
|
Return Value:
|
|
|
|
Returns a pointer to a certificate context, or NULL.
|
|
The returned context must be freed via CertFreeCertificateContext()
|
|
|
|
--*/
|
|
|
|
{
|
|
CRYPT_HASH_BLOB hashBlob;
|
|
BOOL OidFound;
|
|
PCCERT_CONTEXT pCertContext = NULL;
|
|
DWORD rc = ERROR_SUCCESS;
|
|
|
|
//HCERTSTORE hStore = CertOpenSystemStoreW( NULL, L"MY");
|
|
|
|
#ifdef ProfilingEfs
|
|
|
|
LARGE_INTEGER StartTime;
|
|
LARGE_INTEGER StopTime;
|
|
|
|
|
|
NtQuerySystemTime(&StartTime);
|
|
#endif
|
|
|
|
HCERTSTORE hStore = CertOpenStore(
|
|
CERT_STORE_PROV_SYSTEM_REGISTRY_W,
|
|
0, // dwEncodingType
|
|
0, // hCryptProv,
|
|
dwFlags,
|
|
L"My"
|
|
);
|
|
|
|
#ifdef ProfilingEfs
|
|
|
|
NtQuerySystemTime(&StopTime);
|
|
DbgPrint("OpenStore:%lu\tHashHead:%lu\n", (ULONG)(StopTime.QuadPart - StartTime.QuadPart)/1000, *((PULONG)pbHash));
|
|
#endif
|
|
|
|
if (hStore != NULL) {
|
|
|
|
//
|
|
// Find our cert via the hash
|
|
//
|
|
|
|
hashBlob.cbData = cbHash;
|
|
hashBlob.pbData = pbHash;
|
|
|
|
pCertContext = CertFindCertificateInStore( hStore,
|
|
CRYPT_ASN_ENCODING,
|
|
0,
|
|
CERT_FIND_HASH,
|
|
&hashBlob,
|
|
NULL
|
|
);
|
|
//
|
|
// Let's make sure we have the right EFS OID
|
|
//
|
|
|
|
if (pCertContext) {
|
|
rc = EfsFindCertOid(
|
|
szOID_KP_EFS,
|
|
pCertContext,
|
|
&OidFound
|
|
);
|
|
|
|
if ((ERROR_SUCCESS != rc) || !OidFound) {
|
|
|
|
if (dwOpen) {
|
|
|
|
//
|
|
// Let's try recovery cert
|
|
//
|
|
|
|
rc = EfsFindCertOid(
|
|
szOID_EFS_RECOVERY,
|
|
pCertContext,
|
|
&OidFound
|
|
);
|
|
}
|
|
|
|
|
|
if ((ERROR_SUCCESS != rc) || !OidFound) {
|
|
//
|
|
// Could not get the EFS OID. Same as not finding the cert.
|
|
//
|
|
|
|
CertFreeCertificateContext(pCertContext);
|
|
pCertContext = NULL;
|
|
if ((rc != ERROR_SUCCESS) && (rc != CERTSRV_E_KEY_LENGTH)){
|
|
rc = CERT_E_WRONG_USAGE;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
rc = GetLastError();
|
|
}
|
|
|
|
CertCloseStore( hStore, 0 );
|
|
}
|
|
|
|
if (rc != ERROR_SUCCESS) {
|
|
SetLastError(rc);
|
|
}
|
|
return( pCertContext );
|
|
}
|
|
|
|
|
|
LPWSTR
|
|
EfspGetCertDisplayInformation(
|
|
IN PCCERT_CONTEXT pCertContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns the display string from the passed certificate context.
|
|
|
|
Arguments:
|
|
|
|
pCertContext - Supplies a pointer to an open certificate context.
|
|
|
|
Return Value:
|
|
|
|
On success, pointer to display string. Caller must call
|
|
LsapFreeLsaHeap() to free.
|
|
|
|
NULL on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD rc;
|
|
LPWSTR UserDispName = NULL;
|
|
|
|
rc = EfsGetCertNameFromCertContext(
|
|
pCertContext,
|
|
&UserDispName
|
|
);
|
|
|
|
if (rc == ERROR_SUCCESS) {
|
|
return UserDispName;
|
|
} else {
|
|
SetLastError(rc);
|
|
return NULL;
|
|
}
|
|
|
|
}
|
|
|
|
PBYTE
|
|
GetCertHashFromCertContext(
|
|
IN PCCERT_CONTEXT pCertContext,
|
|
OUT PDWORD pcbHash
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Helper routine, takes a cert context and extracts the hash.
|
|
|
|
Arguments:
|
|
|
|
pCertContext - Supplies the cert context.
|
|
|
|
pcbHash - Returns the length in bytes of the returned hash.
|
|
|
|
Return Value:
|
|
|
|
Returns a pointer to a hash block allocated out of heap memory,
|
|
or NULL if either the attempt to get the hash failed or the attempt
|
|
to allocate memory failed.
|
|
|
|
Call GetLastError() for more details in case of failure.
|
|
|
|
--*/
|
|
{
|
|
PBYTE pbHash = NULL;
|
|
*pcbHash = 0;
|
|
|
|
if (CertGetCertificateContextProperty(
|
|
pCertContext,
|
|
CERT_HASH_PROP_ID,
|
|
NULL,
|
|
pcbHash
|
|
)) {
|
|
|
|
pbHash = (PBYTE)LsapAllocateLsaHeap( *pcbHash );
|
|
|
|
if (pbHash != NULL) {
|
|
|
|
if (!CertGetCertificateContextProperty(
|
|
pCertContext,
|
|
CERT_HASH_PROP_ID,
|
|
pbHash,
|
|
pcbHash
|
|
)) {
|
|
|
|
LsapFreeLsaHeap( pbHash );
|
|
pbHash = NULL;
|
|
*pcbHash = 0;
|
|
}
|
|
|
|
} else {
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
}
|
|
}
|
|
|
|
return( pbHash );
|
|
}
|
|
|
|
PCERT_PUBLIC_KEY_INFO
|
|
ExportPublicKeyInfo(
|
|
IN HCRYPTPROV hProv,
|
|
IN DWORD dwKeySpec,
|
|
IN DWORD dwCertEncodingType,
|
|
IN OUT DWORD *pcbInfo
|
|
)
|
|
{
|
|
PCERT_PUBLIC_KEY_INFO pPubKeyInfo = NULL;
|
|
|
|
if ( CryptExportPublicKeyInfo(
|
|
hProv,
|
|
dwKeySpec,
|
|
dwCertEncodingType,
|
|
NULL,
|
|
pcbInfo)) {
|
|
|
|
pPubKeyInfo = (PCERT_PUBLIC_KEY_INFO) LsapAllocateLsaHeap(*pcbInfo);
|
|
|
|
if (pPubKeyInfo) {
|
|
|
|
if (!CryptExportPublicKeyInfo( hProv,
|
|
dwKeySpec,
|
|
dwCertEncodingType,
|
|
pPubKeyInfo,
|
|
pcbInfo)) {
|
|
|
|
LsapFreeLsaHeap( pPubKeyInfo );
|
|
pPubKeyInfo = NULL;
|
|
*pcbInfo = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ( pPubKeyInfo );
|
|
}
|
|
|
|
BOOL
|
|
EncodeAndAlloc(
|
|
DWORD dwEncodingType,
|
|
LPCSTR lpszStructType,
|
|
const void * pvStructInfo,
|
|
PBYTE * pbEncoded,
|
|
PDWORD pcbEncoded
|
|
)
|
|
{
|
|
BOOL b = FALSE;
|
|
|
|
if (CryptEncodeObject(
|
|
dwEncodingType,
|
|
lpszStructType,
|
|
pvStructInfo,
|
|
NULL,
|
|
pcbEncoded )) {
|
|
|
|
*pbEncoded = (PBYTE)LsapAllocateLsaHeap( *pcbEncoded );
|
|
|
|
if (*pbEncoded) {
|
|
|
|
if (CryptEncodeObject(
|
|
dwEncodingType,
|
|
lpszStructType,
|
|
pvStructInfo,
|
|
*pbEncoded,
|
|
pcbEncoded )) {
|
|
|
|
b = TRUE;
|
|
|
|
} else {
|
|
|
|
LsapFreeLsaHeap( *pbEncoded );
|
|
*pbEncoded = NULL;
|
|
}
|
|
|
|
} else {
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
}
|
|
}
|
|
|
|
return( b );
|
|
}
|
|
|
|
DWORD
|
|
EfsMakeCertNames(
|
|
IN PEFS_USER_INFO pEfsUserInfo,
|
|
OUT LPWSTR *DispInfo,
|
|
OUT LPWSTR *SubjectName,
|
|
OUT LPWSTR *UPNName
|
|
)
|
|
{
|
|
DWORD rc = ERROR_SUCCESS;
|
|
|
|
*DispInfo = NULL;
|
|
*UPNName = NULL;
|
|
|
|
if (pEfsUserInfo->bDomainAccount) {
|
|
|
|
//
|
|
// Domain Account
|
|
//
|
|
|
|
HRESULT hr;
|
|
HANDLE hDS = NULL;
|
|
DS_NAME_RESULT* UserName = NULL;
|
|
|
|
hr = DsBind(NULL, NULL, &hDS);
|
|
if (hr == NO_ERROR) {
|
|
|
|
rc = DsCrackNames(
|
|
hDS,
|
|
DS_NAME_NO_FLAGS,
|
|
DS_SID_OR_SID_HISTORY_NAME,
|
|
DS_USER_PRINCIPAL_NAME,
|
|
1,
|
|
&(pEfsUserInfo->lpUserSid),
|
|
&UserName
|
|
);
|
|
|
|
if (ERROR_SUCCESS == rc) {
|
|
|
|
if (UserName->rItems[0].status == DS_NAME_NO_ERROR) {
|
|
|
|
*UPNName = (LPWSTR) LsapAllocateLsaHeap((wcslen(UserName->rItems[0].pName) + 1) * sizeof (WCHAR));
|
|
*DispInfo = (LPWSTR) LsapAllocateLsaHeap(
|
|
(wcslen(UserName->rItems[0].pName) +
|
|
wcslen(pEfsUserInfo->lpUserName) +
|
|
3) * sizeof (WCHAR));
|
|
*SubjectName = (LPWSTR) LsapAllocateLsaHeap((wcslen(pEfsUserInfo->lpUserName)+4) * sizeof (WCHAR));
|
|
|
|
if (*UPNName && *DispInfo && *SubjectName ){
|
|
wcscpy(*UPNName, UserName->rItems[0].pName);
|
|
wcscpy(*DispInfo, pEfsUserInfo->lpUserName);
|
|
wcscat(*DispInfo, L"(");
|
|
wcscat(*DispInfo, *UPNName);
|
|
wcscat(*DispInfo, L")");
|
|
wcscpy(*SubjectName, L"CN=");
|
|
wcscat(*SubjectName, pEfsUserInfo->lpUserName);
|
|
} else {
|
|
|
|
if (*UPNName) {
|
|
LsapFreeLsaHeap( *UPNName );
|
|
*UPNName = NULL;
|
|
}
|
|
if (*DispInfo) {
|
|
LsapFreeLsaHeap( *DispInfo );
|
|
*DispInfo = NULL;
|
|
}
|
|
if (*SubjectName) {
|
|
LsapFreeLsaHeap( *SubjectName );
|
|
*SubjectName = NULL;
|
|
}
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if (UserName){
|
|
DsFreeNameResult(UserName);
|
|
UserName = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
DsUnBindW( &hDS );
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if (NULL == *UPNName) {
|
|
|
|
//
|
|
// If Local Account, let the UPNNmae be User@Computer. DispInfo be User(User@Computer).
|
|
// Else let the UPNName be User@Domain. DispInfo be User(User@Domain)
|
|
//
|
|
|
|
*UPNName = (LPWSTR) LsapAllocateLsaHeap(
|
|
(wcslen(pEfsUserInfo->lpUserName) +
|
|
wcslen(pEfsUserInfo->lpDomainName) +
|
|
2) * sizeof (WCHAR));
|
|
*DispInfo = (LPWSTR) LsapAllocateLsaHeap(
|
|
(wcslen(pEfsUserInfo->lpDomainName) +
|
|
wcslen(pEfsUserInfo->lpUserName) * 2 +
|
|
4) * sizeof (WCHAR));
|
|
*SubjectName = (LPWSTR) LsapAllocateLsaHeap(
|
|
(wcslen(pEfsUserInfo->lpUserName)+
|
|
4) * sizeof (WCHAR));
|
|
|
|
if (*UPNName && *DispInfo && *SubjectName){
|
|
wcscpy(*UPNName, pEfsUserInfo->lpUserName);
|
|
wcscat(*UPNName, L"@");
|
|
wcscat(*UPNName, pEfsUserInfo->lpDomainName);
|
|
wcscpy(*DispInfo, pEfsUserInfo->lpUserName);
|
|
wcscat(*DispInfo, L"(");
|
|
wcscat(*DispInfo, *UPNName);
|
|
wcscat(*DispInfo, L")");
|
|
wcscpy(*SubjectName, L"CN=");
|
|
wcscat(*SubjectName, pEfsUserInfo->lpUserName);
|
|
} else {
|
|
|
|
if (*UPNName) {
|
|
LsapFreeLsaHeap( *UPNName );
|
|
*UPNName = NULL;
|
|
}
|
|
if (*DispInfo) {
|
|
LsapFreeLsaHeap( *DispInfo );
|
|
*DispInfo = NULL;
|
|
}
|
|
if (*SubjectName) {
|
|
LsapFreeLsaHeap( *SubjectName );
|
|
*SubjectName = NULL;
|
|
}
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
EfsFindCertOid(
|
|
IN LPSTR pEfsCertOid,
|
|
IN PCCERT_CONTEXT pCertContext,
|
|
OUT BOOL *OidFound
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine takes a cert context and an Efs Oid. It will check if the cert has the Efs Oid or not.
|
|
|
|
Arguments:
|
|
|
|
pEfsCertOid - Efs Oid to be searched for.
|
|
|
|
pCertContext - The cert to be searched for.
|
|
|
|
OidFound - The result. TRUE if the oid is found.
|
|
|
|
Return Value:
|
|
|
|
Win32 Error code.
|
|
|
|
--*/
|
|
{
|
|
BOOL bRet;
|
|
PCERT_ENHKEY_USAGE pUsage;
|
|
DWORD pcbUsage = 0;
|
|
DWORD rc = ERROR_SUCCESS;
|
|
DWORD ii;
|
|
DWORD KeyLength;
|
|
|
|
*OidFound = FALSE;
|
|
|
|
//
|
|
// Let's check the key length first
|
|
//
|
|
|
|
KeyLength = CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &(pCertContext->pCertInfo->SubjectPublicKeyInfo));
|
|
if (!KeyLength) {
|
|
return GetLastError();
|
|
}
|
|
|
|
if (KeyLength < (RSA1024BIT_KEY >> 17)) {
|
|
|
|
//
|
|
// Key length too short ( 512 ), We actually don't generate less than 1024.
|
|
//
|
|
|
|
return CERTSRV_E_KEY_LENGTH;
|
|
}
|
|
|
|
bRet = CertGetEnhancedKeyUsage(
|
|
pCertContext,
|
|
0,
|
|
NULL,
|
|
&pcbUsage
|
|
);
|
|
|
|
if (bRet) {
|
|
|
|
SafeAllocaAllocate(pUsage, pcbUsage);
|
|
|
|
if (pUsage) {
|
|
bRet = CertGetEnhancedKeyUsage(
|
|
pCertContext,
|
|
0,
|
|
pUsage,
|
|
&pcbUsage
|
|
);
|
|
if (bRet){
|
|
for (ii=0; ii<pUsage->cUsageIdentifier;ii++) {
|
|
if (!strcmp(pUsage->rgpszUsageIdentifier[ii], pEfsCertOid)){
|
|
|
|
//
|
|
// We found the OID
|
|
//
|
|
*OidFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
rc = GetLastError();
|
|
}
|
|
|
|
SafeAllocaFree(pUsage);
|
|
|
|
} else {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
} else {
|
|
rc = GetLastError();
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
LONG
|
|
EfsTimeExp(
|
|
IN LPFILETIME CertExpTime
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine takes a time to see if it has passed.
|
|
|
|
Arguments:
|
|
|
|
CertExpTime - time to be checked
|
|
|
|
|
|
Return Value:
|
|
|
|
Non zero if passed.
|
|
|
|
--*/
|
|
|
|
{
|
|
SYSTEMTIME SystemTime;
|
|
FILETIME FileTime;
|
|
|
|
|
|
GetSystemTime(&SystemTime);
|
|
SystemTimeToFileTime(&SystemTime, &FileTime);
|
|
|
|
if (CompareFileTime(&FileTime, CertExpTime) <= 0)
|
|
return 0;
|
|
else
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
DWORD
|
|
GetKeyInfoFromCertHash(
|
|
IN OUT PEFS_USER_INFO pEfsUserInfo,
|
|
IN PBYTE pbHash,
|
|
IN DWORD cbHash,
|
|
OUT HCRYPTKEY * hKey OPTIONAL,
|
|
OUT HCRYPTPROV * hProv OPTIONAL,
|
|
OUT LPWSTR * ContainerName OPTIONAL,
|
|
OUT LPWSTR * ProviderName OPTIONAL,
|
|
OUT LPWSTR * DisplayInformation OPTIONAL,
|
|
OUT PBOOLEAN pbIsValid OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine takes a certificate hash and extracts from it information
|
|
about the key it represents. If the key information from this
|
|
cert does not exist in the current context, it will return an error.
|
|
|
|
Arguments:
|
|
|
|
pEfsUserInfo - User Information
|
|
|
|
pbHash - Takes a pointer to the certificate hash.
|
|
|
|
cbHash - The length in bytes of the certificate hash.
|
|
|
|
hKey - Returns the handle to the key corresponding to this
|
|
certificate. Must be passed of hProv is passed.
|
|
|
|
hProv - Returns the handle to the context corresponding to this
|
|
certificate. Must be passed of hKey is passed.
|
|
|
|
ContainerName - Returns a string with the name of the container of the
|
|
key in this certificate.
|
|
|
|
ProviderName - Returns a string with the name of the provider of the
|
|
key in this certificate.
|
|
|
|
DisplayInformation - Returns the display information for the certificate.
|
|
|
|
pbIsValid - If present, causes the cert to be validity checked and the
|
|
results returned.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - The passed certificate is in the current user's MY
|
|
store and the key it represents is in his context.
|
|
|
|
!ERROR_SUCCESS - Either the certificate could not be found in the
|
|
user's MY store, or the key in the certificate could not be
|
|
instantiated.
|
|
|
|
--*/
|
|
|
|
{
|
|
PCCERT_CONTEXT pCertContext;
|
|
IN PBYTE pbLocalHash = NULL;
|
|
IN DWORD cbLocalHash = 0;
|
|
|
|
//
|
|
// Don't trust CryptoAPI to set last error properly,
|
|
// keep track of success and failure on our own.
|
|
//
|
|
|
|
BOOLEAN b = TRUE;
|
|
BOOLEAN CreateCache = FALSE;
|
|
BOOLEAN LocalCertValidated = FALSE;
|
|
BOOLEAN DataNotCached = TRUE;
|
|
DWORD rc = ERROR_SUCCESS;
|
|
DWORD rc2 = ERROR_SUCCESS;
|
|
|
|
HCRYPTKEY hLocalKey = NULL;
|
|
HCRYPTPROV hLocalProv = NULL;
|
|
LPWSTR LocalContainerName = NULL;
|
|
LPWSTR LocalProviderName = NULL;
|
|
LPWSTR LocalDisplayInformation = NULL;
|
|
|
|
//
|
|
// Output parameters
|
|
//
|
|
|
|
if (ARGUMENT_PRESENT(ContainerName)) {
|
|
*ContainerName = NULL;
|
|
}
|
|
|
|
if (ARGUMENT_PRESENT(ProviderName)) {
|
|
*ProviderName = NULL;
|
|
}
|
|
|
|
if (ARGUMENT_PRESENT(DisplayInformation)) {
|
|
*DisplayInformation = NULL;
|
|
}
|
|
|
|
if (ARGUMENT_PRESENT(hProv)) {
|
|
*hProv = NULL;
|
|
}
|
|
|
|
if (ARGUMENT_PRESENT(hKey)) {
|
|
*hKey = NULL;
|
|
}
|
|
|
|
if (ARGUMENT_PRESENT( pbIsValid )){
|
|
*pbIsValid = FALSE;
|
|
}
|
|
|
|
//
|
|
// Check if a cache node is available
|
|
//
|
|
|
|
if (!pEfsUserInfo->UserCacheStop) {
|
|
if (pEfsUserInfo->pUserCache) {
|
|
|
|
//
|
|
// The user has a cache, check if the Hash matches
|
|
//
|
|
|
|
if ( pEfsUserInfo->pUserCache->cbHash == cbHash ) {
|
|
|
|
if(RtlEqualMemory( pEfsUserInfo->pUserCache->pbHash, pbHash, cbHash)){
|
|
|
|
//
|
|
// Cache is valid. Use the cache
|
|
//
|
|
|
|
|
|
if (ARGUMENT_PRESENT( pbIsValid )){
|
|
*pbIsValid = (pEfsUserInfo->pUserCache->CertValidated == CERT_VALIDATED);
|
|
}
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
//
|
|
// User might use an old key, do not put in the cache.
|
|
//
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
CreateCache = TRUE;
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// Well, cert is not in the cache. The profile could be not loaded. Let's try to load the profile.
|
|
// If the profile is already loaded, it will return success without calling LoadUserProfile().
|
|
// We don't need to unload here. It will be unload at the very outside.
|
|
//
|
|
|
|
if (!EfspLoadUserProfile( pEfsUserInfo, TRUE )){
|
|
|
|
//
|
|
// Profile Load Failure
|
|
//
|
|
|
|
return GetLastError();
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Find our cert via the hash
|
|
//
|
|
|
|
pCertContext = GetCertContextFromCertHash(
|
|
pbHash,
|
|
cbHash,
|
|
CERT_SYSTEM_STORE_CURRENT_USER,
|
|
ARGUMENT_PRESENT( pbIsValid )? 0:1
|
|
);
|
|
|
|
|
|
if (pCertContext != NULL) {
|
|
|
|
pbLocalHash = pbHash;
|
|
cbLocalHash = cbHash;
|
|
|
|
//
|
|
// Let's check if the cert points to a new cert or not. If it is, the current reg value
|
|
// will be changed.
|
|
//
|
|
PCCERT_CONTEXT pNewCertContext = NULL;
|
|
|
|
|
|
if (ARGUMENT_PRESENT( pbIsValid ) || pEfsUserInfo->pUserCache == NULL) {
|
|
|
|
//
|
|
// Create path or the first open
|
|
//
|
|
|
|
rc = EfsTryRenewCert(
|
|
pEfsUserInfo,
|
|
pCertContext,
|
|
&pNewCertContext
|
|
);
|
|
|
|
if (ERROR_SUCCESS == rc) {
|
|
|
|
if (ARGUMENT_PRESENT( pbIsValid )) {
|
|
|
|
//
|
|
// Not an open path. Let's switch the certificate
|
|
//
|
|
|
|
pbLocalHash = GetCertHashFromCertContext(
|
|
pNewCertContext,
|
|
&cbLocalHash
|
|
);
|
|
if (pbLocalHash) {
|
|
|
|
CertFreeCertificateContext( pCertContext );
|
|
pCertContext = pNewCertContext;
|
|
pNewCertContext = NULL;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Forget about the new cert
|
|
//
|
|
|
|
pbLocalHash = pbHash;
|
|
cbLocalHash = cbHash;
|
|
CertFreeCertificateContext( pNewCertContext );
|
|
pNewCertContext = NULL;
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// Let's create the new cache for the new cert.
|
|
//
|
|
|
|
EfsCreateNewCache(pEfsUserInfo, pNewCertContext);
|
|
CertFreeCertificateContext( pNewCertContext );
|
|
pNewCertContext = NULL;
|
|
CreateCache = FALSE;
|
|
|
|
}
|
|
} else {
|
|
|
|
rc = ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
PCRYPT_KEY_PROV_INFO pCryptKeyProvInfo = GetKeyProvInfo( pCertContext );
|
|
|
|
if (pCryptKeyProvInfo != NULL) {
|
|
|
|
//
|
|
// Copy out the container name and provider name if requested.
|
|
//
|
|
|
|
|
|
if (pCryptKeyProvInfo->pwszContainerName) {
|
|
LocalContainerName = (LPWSTR)LsapAllocateLsaHeap( wcslen(pCryptKeyProvInfo->pwszContainerName) * sizeof( WCHAR ) + sizeof( UNICODE_NULL ));
|
|
if (LocalContainerName != NULL) {
|
|
wcscpy( LocalContainerName, pCryptKeyProvInfo->pwszContainerName );
|
|
} else {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
b = FALSE;
|
|
}
|
|
}
|
|
if (b && pCryptKeyProvInfo->pwszProvName) {
|
|
LocalProviderName = (LPWSTR)LsapAllocateLsaHeap( wcslen(pCryptKeyProvInfo->pwszProvName) * sizeof( WCHAR ) + sizeof( UNICODE_NULL ));
|
|
if (LocalProviderName != NULL) {
|
|
wcscpy( LocalProviderName, pCryptKeyProvInfo->pwszProvName );
|
|
}
|
|
else {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
b = FALSE;
|
|
}
|
|
}
|
|
if (!(LocalDisplayInformation = EfspGetCertDisplayInformation( pCertContext ))) {
|
|
|
|
//
|
|
// At least for now, we do not accept Cert without display name
|
|
//
|
|
|
|
rc = GetLastError();
|
|
b = FALSE;
|
|
}
|
|
|
|
//
|
|
// Get the key information
|
|
//
|
|
|
|
if (b) {
|
|
|
|
#ifdef ProfilingEfs
|
|
|
|
LARGE_INTEGER StartTime;
|
|
LARGE_INTEGER StopTime;
|
|
|
|
|
|
NtQuerySystemTime(&StartTime);
|
|
#endif
|
|
if (CryptAcquireContext( &hLocalProv, pCryptKeyProvInfo->pwszContainerName, pCryptKeyProvInfo->pwszProvName, PROV_RSA_FULL, CRYPT_SILENT)) {
|
|
|
|
#ifdef ProfilingEfs
|
|
NtQuerySystemTime(&StopTime);
|
|
DbgPrint("CryptAcquireContext:%lu\tSessionID:%lu\tHashHead:%lu\n", (ULONG)(StopTime.QuadPart - StartTime.QuadPart)/1000, pEfsUserInfo->AuthId.LowPart, *((ULONG *)pbHash));
|
|
#endif
|
|
if (!CryptGetUserKey(hLocalProv, AT_KEYEXCHANGE, &hLocalKey)) {
|
|
|
|
rc = GetLastError();
|
|
b = FALSE;
|
|
}
|
|
|
|
} else {
|
|
|
|
rc = GetLastError();
|
|
if (pEfsUserInfo->NonKerberos && (ERROR_OUTOFMEMORY != rc)) {
|
|
|
|
EfsLogEntry(
|
|
EVENTLOG_ERROR_TYPE,
|
|
0,
|
|
EFS_NTLM_ERROR,
|
|
0,
|
|
sizeof(DWORD),
|
|
NULL,
|
|
&rc
|
|
);
|
|
|
|
rc = ERROR_BAD_LOGON_SESSION_STATE;
|
|
}
|
|
b = FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
if (b) {
|
|
|
|
if ( ARGUMENT_PRESENT( pbIsValid ) || CreateCache ) {
|
|
|
|
//
|
|
// Do cert validity checking. Check time and usage.
|
|
//
|
|
|
|
if ( CertVerifyTimeValidity(
|
|
NULL,
|
|
pCertContext->pCertInfo
|
|
)){
|
|
|
|
rc2 = CERT_E_EXPIRED;
|
|
|
|
//b = FALSE;
|
|
|
|
} else {
|
|
|
|
LocalCertValidated = TRUE;
|
|
|
|
}
|
|
|
|
|
|
if (ARGUMENT_PRESENT( pbIsValid )) {
|
|
|
|
//
|
|
// We need the validation info.
|
|
//
|
|
|
|
*pbIsValid = LocalCertValidated;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( CreateCache ) {
|
|
|
|
DWORD certFlag;
|
|
|
|
//
|
|
// To determine if we can put the data in cache.
|
|
//
|
|
|
|
if (CurrentHashOK(pEfsUserInfo, pbLocalHash, cbLocalHash, &certFlag)) {
|
|
|
|
//
|
|
// This pbHash is in the user's key or has been put in. Let's create the cache node.
|
|
//
|
|
|
|
PUSER_CACHE pCacheNode;
|
|
PBYTE pbWkHash;
|
|
DWORD ImpersonationError = 0;
|
|
|
|
if ( 0 == (certFlag & CERTSTOREIDMASK) ) {
|
|
|
|
DWORD sevRc;
|
|
|
|
//
|
|
// The cert is not in the LM Trusted or Other store. Upgrade system from Win2K, or Beta 1 Whistler.
|
|
//
|
|
|
|
if (ERROR_SUCCESS == (sevRc = EfsAddCertToCertStore(pCertContext, OTHERPEOPLE, &ImpersonationError))) {
|
|
EfsMarkCertAddedToStore(pEfsUserInfo, CERTINLMOTHERSTORE);
|
|
} else {
|
|
if (ImpersonationError) {
|
|
|
|
//
|
|
// Got in trouble. We could not impersonate back.
|
|
//
|
|
|
|
ASSERT(FALSE);
|
|
rc = sevRc;
|
|
b = FALSE;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (!ImpersonationError) {
|
|
|
|
PSID pUserID = NULL;
|
|
ULONG SidLength = 0;
|
|
|
|
pCacheNode = (PUSER_CACHE) LsapAllocateLsaHeap(sizeof(USER_CACHE));
|
|
|
|
pbWkHash = (PBYTE) LsapAllocateLsaHeap(cbLocalHash);
|
|
|
|
if (pEfsUserInfo->InterActiveUser != USER_INTERACTIVE) {
|
|
|
|
SidLength = RtlLengthSid(pEfsUserInfo->pTokenUser->User.Sid);
|
|
pUserID = (PSID) LsapAllocateLsaHeap(SidLength);
|
|
|
|
}
|
|
|
|
if (pCacheNode && pbWkHash && ((SidLength == 0) || (pUserID))) {
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
memset( pCacheNode, 0, sizeof( USER_CACHE ));
|
|
RtlCopyMemory(pbWkHash, pbLocalHash, cbLocalHash);
|
|
|
|
if (pUserID) {
|
|
|
|
Status = RtlCopySid(
|
|
SidLength,
|
|
pUserID,
|
|
pEfsUserInfo->pTokenUser->User.Sid
|
|
);
|
|
}
|
|
|
|
if (NT_SUCCESS( Status ) && NT_SUCCESS( NtQuerySystemTime(&(pCacheNode->TimeStamp)))){
|
|
|
|
if (EfspInitUserCacheNode(
|
|
pCacheNode,
|
|
pUserID,
|
|
pbWkHash,
|
|
cbLocalHash,
|
|
LocalContainerName,
|
|
LocalProviderName,
|
|
LocalDisplayInformation,
|
|
&(pCertContext->pCertInfo->NotAfter),
|
|
hLocalKey,
|
|
hLocalProv,
|
|
pUserID? NULL: &(pEfsUserInfo->AuthId),
|
|
LocalCertValidated? CERT_VALIDATED:CERT_VALIDATION_FAILED
|
|
)){
|
|
|
|
//
|
|
// Cache node created and ready for use. Do not delete or close the info
|
|
// we just got.
|
|
//
|
|
|
|
LocalContainerName = NULL;
|
|
LocalProviderName = NULL;
|
|
LocalDisplayInformation = NULL;
|
|
hLocalKey = NULL;
|
|
hLocalProv = NULL;
|
|
pEfsUserInfo->pUserCache = pCacheNode;
|
|
|
|
DataNotCached = FALSE;
|
|
rc = ERROR_SUCCESS;
|
|
b = TRUE; // We can have a non-validated cache node for the use of open file
|
|
|
|
} else {
|
|
|
|
LsapFreeLsaHeap(pCacheNode);
|
|
LsapFreeLsaHeap(pbWkHash);
|
|
pbWkHash = NULL;
|
|
pCacheNode = NULL;
|
|
if (pUserID) {
|
|
LsapFreeLsaHeap(pUserID);
|
|
pUserID = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
LsapFreeLsaHeap(pCacheNode);
|
|
LsapFreeLsaHeap(pbWkHash);
|
|
pbWkHash = NULL;
|
|
pCacheNode = NULL;
|
|
if (pUserID) {
|
|
LsapFreeLsaHeap(pUserID);
|
|
pUserID = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
if (pCacheNode) {
|
|
LsapFreeLsaHeap(pCacheNode);
|
|
pCacheNode = NULL;
|
|
}
|
|
if (pbWkHash) {
|
|
LsapFreeLsaHeap(pbWkHash);
|
|
pbWkHash = NULL;
|
|
}
|
|
if (pUserID) {
|
|
LsapFreeLsaHeap(pUserID);
|
|
pUserID = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (DataNotCached && b) {
|
|
|
|
//
|
|
// We need to returned the data to outside
|
|
//
|
|
|
|
|
|
if (ARGUMENT_PRESENT(ContainerName)) {
|
|
|
|
*ContainerName = LocalContainerName;
|
|
LocalContainerName = NULL;
|
|
|
|
} else {
|
|
|
|
LsapFreeLsaHeap( LocalContainerName );
|
|
LocalContainerName = NULL;
|
|
|
|
}
|
|
|
|
if (ARGUMENT_PRESENT(ProviderName)) {
|
|
*ProviderName = LocalProviderName;
|
|
LocalProviderName = NULL;
|
|
} else {
|
|
|
|
LsapFreeLsaHeap( LocalProviderName );
|
|
LocalProviderName = NULL;
|
|
|
|
}
|
|
|
|
if (ARGUMENT_PRESENT(DisplayInformation)) {
|
|
*DisplayInformation = LocalDisplayInformation;
|
|
LocalDisplayInformation = NULL;
|
|
} else {
|
|
|
|
LsapFreeLsaHeap( LocalDisplayInformation );
|
|
LocalDisplayInformation = NULL;
|
|
|
|
}
|
|
|
|
if (ARGUMENT_PRESENT(hKey)) {
|
|
*hKey = hLocalKey;
|
|
hLocalKey = NULL;
|
|
|
|
}
|
|
|
|
if (ARGUMENT_PRESENT(hProv)) {
|
|
*hProv = hLocalProv;
|
|
hLocalProv = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LsapFreeLsaHeap( pCryptKeyProvInfo );
|
|
if (pbLocalHash && (pbLocalHash != pbHash)) {
|
|
LsapFreeLsaHeap( pbLocalHash );
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
rc = GetLastError();
|
|
b = FALSE;
|
|
}
|
|
|
|
if (pCertContext) {
|
|
|
|
CertFreeCertificateContext( pCertContext );
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
rc = GetLastError();
|
|
b = FALSE;
|
|
}
|
|
|
|
if (!b) {
|
|
|
|
ASSERT( rc != ERROR_SUCCESS );
|
|
|
|
//
|
|
// Something failed, cleanup the stuff we were going to return
|
|
//
|
|
|
|
if ( LocalContainerName) {
|
|
LsapFreeLsaHeap( LocalContainerName );
|
|
}
|
|
|
|
if (LocalProviderName) {
|
|
LsapFreeLsaHeap( LocalProviderName );
|
|
}
|
|
|
|
if (LocalDisplayInformation) {
|
|
LsapFreeLsaHeap( LocalDisplayInformation );
|
|
}
|
|
|
|
if (hLocalKey) {
|
|
CryptDestroyKey( hLocalKey );
|
|
}
|
|
|
|
if (hLocalProv) {
|
|
CryptReleaseContext( hLocalProv, 0 );
|
|
}
|
|
}
|
|
|
|
if (ARGUMENT_PRESENT( pbIsValid ) && !LocalCertValidated ) {
|
|
if (rc == ERROR_SUCCESS) {
|
|
rc = rc2;
|
|
}
|
|
}
|
|
|
|
return( rc );
|
|
}
|
|
|
|
|
|
PCRYPT_KEY_PROV_INFO
|
|
GetKeyProvInfo(
|
|
PCCERT_CONTEXT pCertContext
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will extract the Key Provider Information from
|
|
the passed certificate context.
|
|
|
|
Arguments:
|
|
|
|
pCertContext - Supplies a pointer to a certificate context.
|
|
|
|
Return Value:
|
|
|
|
Returns a pointer to a PCRYPT_KEY_PROV_INFO structure on success,
|
|
otherwise returns NULL, which usually means that the certificate
|
|
did not have the context property we were looking for (meaning
|
|
that it probably isn't an EFS certificate).
|
|
--*/
|
|
|
|
{
|
|
|
|
DWORD cbData = 0;
|
|
BOOL b;
|
|
PCRYPT_KEY_PROV_INFO pCryptKeyProvInfo = NULL;
|
|
|
|
b = CertGetCertificateContextProperty(
|
|
pCertContext,
|
|
CERT_KEY_PROV_INFO_PROP_ID,
|
|
NULL,
|
|
&cbData
|
|
);
|
|
|
|
if (b) {
|
|
|
|
pCryptKeyProvInfo = (PCRYPT_KEY_PROV_INFO)LsapAllocateLsaHeap( cbData );
|
|
|
|
if (pCryptKeyProvInfo != NULL) {
|
|
|
|
b = CertGetCertificateContextProperty(
|
|
pCertContext,
|
|
CERT_KEY_PROV_INFO_PROP_ID,
|
|
pCryptKeyProvInfo,
|
|
&cbData
|
|
);
|
|
|
|
if (!b) {
|
|
|
|
LsapFreeLsaHeap( pCryptKeyProvInfo );
|
|
pCryptKeyProvInfo = NULL;
|
|
}
|
|
|
|
} else {
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
}
|
|
}
|
|
|
|
return ( pCryptKeyProvInfo );
|
|
}
|
|
|
|
|
|
DWORD
|
|
EfsCreateNewCache(
|
|
IN OUT PEFS_USER_INFO pEfsUserInfo,
|
|
IN PCCERT_CONTEXT pCertContext
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will create a cache node.
|
|
|
|
Arguments:
|
|
|
|
pEfsUserInfo - User Information
|
|
|
|
pCertContext - Supplies a pointer to a certificate context.
|
|
|
|
Return Value:
|
|
|
|
Returns Win32 error code.
|
|
--*/
|
|
|
|
{
|
|
|
|
PBYTE pbHash;
|
|
DWORD cbHash;
|
|
HCRYPTKEY hLocalKey = NULL;
|
|
HCRYPTPROV hLocalProv = NULL;
|
|
DWORD rc = ERROR_SUCCESS;
|
|
LPWSTR LocalContainerName = NULL;
|
|
LPWSTR LocalProviderName = NULL;
|
|
LPWSTR LocalDisplayInformation = NULL;
|
|
PUSER_CACHE pCacheNode;
|
|
PCRYPT_KEY_PROV_INFO pCryptKeyProvInfo = GetKeyProvInfo( pCertContext );
|
|
|
|
if (pCryptKeyProvInfo != NULL) {
|
|
|
|
//
|
|
// Copy out the container name and provider name if requested.
|
|
//
|
|
|
|
|
|
if (pCryptKeyProvInfo->pwszContainerName) {
|
|
LocalContainerName = (LPWSTR)LsapAllocateLsaHeap( wcslen(pCryptKeyProvInfo->pwszContainerName) * sizeof( WCHAR ) + sizeof( UNICODE_NULL ));
|
|
if (LocalContainerName != NULL) {
|
|
wcscpy( LocalContainerName, pCryptKeyProvInfo->pwszContainerName );
|
|
} else {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
if ((ERROR_SUCCESS == rc) && pCryptKeyProvInfo->pwszProvName) {
|
|
LocalProviderName = (LPWSTR)LsapAllocateLsaHeap( wcslen(pCryptKeyProvInfo->pwszProvName) * sizeof( WCHAR ) + sizeof( UNICODE_NULL ));
|
|
if (LocalProviderName != NULL) {
|
|
wcscpy( LocalProviderName, pCryptKeyProvInfo->pwszProvName );
|
|
}
|
|
else {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
if ((ERROR_SUCCESS == rc) && !(LocalDisplayInformation = EfspGetCertDisplayInformation( pCertContext ))) {
|
|
|
|
//
|
|
// At least for now, we do not accept Cert without display name
|
|
//
|
|
|
|
rc = GetLastError();
|
|
}
|
|
|
|
//
|
|
// Get the key information
|
|
//
|
|
|
|
if (ERROR_SUCCESS == rc) {
|
|
|
|
if (CryptAcquireContext( &hLocalProv, pCryptKeyProvInfo->pwszContainerName, pCryptKeyProvInfo->pwszProvName, PROV_RSA_FULL, CRYPT_SILENT)) {
|
|
|
|
if (!CryptGetUserKey(hLocalProv, AT_KEYEXCHANGE, &hLocalKey)) {
|
|
|
|
rc = GetLastError();
|
|
}
|
|
|
|
} else {
|
|
|
|
rc = GetLastError();
|
|
}
|
|
|
|
}
|
|
|
|
if (ERROR_SUCCESS == rc) {
|
|
|
|
DWORD ImpersonationError = 0;
|
|
DWORD sevRc;
|
|
|
|
//
|
|
// The cert may not be in the LM Trusted or OtherPeople store.
|
|
//
|
|
|
|
if (ERROR_SUCCESS == (sevRc = EfsAddCertToCertStore(pCertContext, OTHERPEOPLE, &ImpersonationError))) {
|
|
EfsMarkCertAddedToStore(pEfsUserInfo, CERTINLMOTHERSTORE);
|
|
} else {
|
|
if (ImpersonationError) {
|
|
|
|
//
|
|
// Got in trouble. We could not impersonate back.
|
|
//
|
|
|
|
ASSERT(FALSE);
|
|
rc = sevRc;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if (!ImpersonationError) {
|
|
|
|
PSID pUserID = NULL;
|
|
ULONG SidLength = 0;
|
|
|
|
pCacheNode = (PUSER_CACHE) LsapAllocateLsaHeap(sizeof(USER_CACHE));
|
|
|
|
pbHash = GetCertHashFromCertContext(
|
|
pCertContext,
|
|
&cbHash
|
|
);
|
|
|
|
if (pEfsUserInfo->InterActiveUser != USER_INTERACTIVE) {
|
|
|
|
SidLength = RtlLengthSid(pEfsUserInfo->pTokenUser->User.Sid);
|
|
pUserID = (PSID) LsapAllocateLsaHeap(SidLength);
|
|
|
|
}
|
|
|
|
if (pCacheNode && pbHash && ((SidLength == 0) || (pUserID))) {
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
memset( pCacheNode, 0, sizeof( USER_CACHE ));
|
|
|
|
if (pUserID) {
|
|
|
|
Status = RtlCopySid(
|
|
SidLength,
|
|
pUserID,
|
|
pEfsUserInfo->pTokenUser->User.Sid
|
|
);
|
|
}
|
|
|
|
if (NT_SUCCESS( Status ) && NT_SUCCESS( Status = NtQuerySystemTime(&(pCacheNode->TimeStamp)))){
|
|
|
|
if (EfspInitUserCacheNode(
|
|
pCacheNode,
|
|
pUserID,
|
|
pbHash,
|
|
cbHash,
|
|
LocalContainerName,
|
|
LocalProviderName,
|
|
LocalDisplayInformation,
|
|
&(pCertContext->pCertInfo->NotAfter),
|
|
hLocalKey,
|
|
hLocalProv,
|
|
pUserID? NULL: &(pEfsUserInfo->AuthId),
|
|
CERT_VALIDATED
|
|
)){
|
|
|
|
//
|
|
// Cache node created and ready for use. Do not delete or close the info
|
|
// we just got.
|
|
//
|
|
|
|
LocalContainerName = NULL;
|
|
LocalProviderName = NULL;
|
|
LocalDisplayInformation = NULL;
|
|
hLocalKey = NULL;
|
|
hLocalProv = NULL;
|
|
pEfsUserInfo->pUserCache = pCacheNode;
|
|
pCacheNode = NULL;
|
|
|
|
} else {
|
|
|
|
rc = GetLastError();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
rc = RtlNtStatusToDosError( Status );
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
}
|
|
|
|
if (ERROR_SUCCESS != rc) {
|
|
|
|
if (pCacheNode) {
|
|
LsapFreeLsaHeap(pCacheNode);
|
|
pCacheNode = NULL;
|
|
}
|
|
if (pbHash) {
|
|
LsapFreeLsaHeap(pbHash);
|
|
pbHash = NULL;
|
|
}
|
|
if (pUserID) {
|
|
LsapFreeLsaHeap(pUserID);
|
|
pUserID = NULL;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (ERROR_SUCCESS != rc) {
|
|
|
|
|
|
if (LocalContainerName) {
|
|
|
|
LsapFreeLsaHeap(LocalContainerName);
|
|
|
|
}
|
|
|
|
if (LocalProviderName) {
|
|
|
|
LsapFreeLsaHeap(LocalProviderName);
|
|
|
|
}
|
|
|
|
if (LocalDisplayInformation) {
|
|
|
|
LsapFreeLsaHeap(LocalDisplayInformation);
|
|
|
|
}
|
|
|
|
if (hLocalKey) {
|
|
CryptDestroyKey( hLocalKey );
|
|
}
|
|
|
|
if (hLocalProv) {
|
|
CryptReleaseContext( hLocalProv, 0 );
|
|
}
|
|
|
|
}
|
|
|
|
LsapFreeLsaHeap( pCryptKeyProvInfo );
|
|
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|