|
|
//+---------------------------------------------------------------------------
//
// Microsoft Widows
// Copyright (C) Microsoft Corporation, 1992 - 1997.
//
// File: defcreds.c
//
// Contents: Routines for acquiring default credentials.
//
// Classes:
//
// Functions:
//
// History: 12-05-97 jbanes Created.
//
//----------------------------------------------------------------------------
#include <spbase.h>
#include <softpub.h>
void GetImplementationType( PCCERT_CONTEXT pCertContext, PDWORD pdwImpType);
NTSTATUS AssignNewClientCredential( PSPContext pContext, PCCERT_CONTEXT pCertContext, BOOL fPromptNow) { PSPCredential pCred = NULL; NTSTATUS Status; BOOL fEventLogged; LSA_SCHANNEL_SUB_CRED SubCred;
//
// Does this certificate have an acceptable public key type?
//
{ BOOL fFound; DWORD dwKeyType; DWORD i;
fFound = FALSE; dwKeyType = MapOidToCertType(pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
for(i = 0; i < pContext->cSsl3ClientCertTypes; i++) { if(pContext->Ssl3ClientCertTypes[i] == dwKeyType) { fFound = TRUE; break; } } if(!fFound) { // Don't use this certificate.
Status = SP_LOG_RESULT(PCT_INT_UNKNOWN_CREDENTIAL); goto cleanup; } }
//
// Build a credential structure for the certificate.
//
pCred = SPExternalAlloc(sizeof(SPCredential)); if(pCred == NULL) { Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY); goto cleanup; }
memset(&SubCred, 0, sizeof(SubCred));
SubCred.pCert = pCertContext;
Status = SPCreateCred(pContext->dwProtocol, &SubCred, pCred, &fEventLogged); if(Status != PCT_ERR_OK) { goto cleanup; }
//
// Release the existing credential, if one exists.
//
if(pContext->RipeZombie->pClientCred) { SPDeleteCred(pContext->RipeZombie->pClientCred, TRUE); pContext->RipeZombie->pClientCred = NULL; }
//
// Assign the credential to the cache element.
//
pContext->RipeZombie->pClientCred = pCred; pContext->pActiveClientCred = pCred;
if(fPromptNow == FALSE) { pContext->RipeZombie->dwFlags |= SP_CACHE_FLAG_USE_VALIDATED; }
Status = PCT_ERR_OK;
cleanup:
if(pCred && Status != PCT_ERR_OK) { SPDeleteCred(pCred, TRUE); }
return Status; }
NTSTATUS QueryCredentialManagerForCert( PSPContext pContext, LPWSTR pszTarget) { PCCERT_CONTEXT pCertContext = NULL; LUID LogonId; PENCRYPTED_CREDENTIALW pCredential = NULL; BOOL fImpersonating = FALSE; CRYPT_HASH_BLOB HashBlob; NTSTATUS Status; HCERTSTORE hStore = 0; PCERT_CREDENTIAL_INFO pCertInfo = NULL; CRED_MARSHAL_TYPE CredType;
//
// Obtain client logon id.
//
Status = SslGetClientLogonId(&LogonId);
if(!NT_SUCCESS(Status)) { SP_LOG_RESULT(Status); goto cleanup; }
fImpersonating = SslImpersonateClient();
//
// Query the credential manager for a certificate.
//
Status = LsaTable->CrediRead(&LogonId, CREDP_FLAGS_IN_PROCESS, pszTarget, CRED_TYPE_DOMAIN_CERTIFICATE, 0, &pCredential); if(!NT_SUCCESS(Status)) { if(Status == STATUS_NOT_FOUND) { DebugLog((DEB_WARN, "No certificate found in credential manager.\n")); } else { SP_LOG_RESULT(Status); } goto cleanup; }
//
// Extract the certificate thumbprint and (optional) PIN.
//
if(!CredIsMarshaledCredentialW(pCredential->Cred.UserName)) { Status = SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS); goto cleanup; }
if(!CredUnmarshalCredentialW(pCredential->Cred.UserName, &CredType, &pCertInfo)) { Status = SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS); goto cleanup; } if(CredType != CertCredential) { Status = SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS); goto cleanup; }
//
// Look up the certificate in the MY certificate store.
//
hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, X509_ASN_ENCODING, 0, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, L"MY"); if(!hStore) { SP_LOG_RESULT(GetLastError()); Status = SEC_E_NO_CREDENTIALS; goto cleanup; }
HashBlob.cbData = sizeof(pCertInfo->rgbHashOfCert); HashBlob.pbData = pCertInfo->rgbHashOfCert;
pCertContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING, 0, CERT_FIND_HASH, &HashBlob, NULL); if(pCertContext == NULL) { DebugLog((DEB_ERROR, "Certificate designated by credential manager was not found in certificate store (0x%x).\n", GetLastError())); Status = SEC_E_NO_CREDENTIALS; goto cleanup; }
//
// Attempt to add this certificate context to the current credential.
//
Status = AssignNewClientCredential(pContext, pCertContext, pCredential->Cred.Flags & CRED_FLAGS_PROMPT_NOW); if(!NT_SUCCESS(Status)) { SP_LOG_RESULT(Status); goto cleanup; }
Status = STATUS_SUCCESS;
cleanup:
if(pCertContext) { CertFreeCertificateContext(pCertContext); }
if(hStore) { CertCloseStore(hStore, 0); }
if(pCredential) { LsaTable->FreeLsaHeap(pCredential); }
if(pCertInfo) { CredFree(pCertInfo); }
if(fImpersonating) { RevertToSelf(); }
return Status; }
DWORD IsThreadLocalSystem( BOOL *pfIsLocalSystem) { DWORD Status; HANDLE hToken = 0; UCHAR InfoBuffer[1024]; DWORD dwInfoBufferSize = sizeof(InfoBuffer); PTOKEN_USER SlowBuffer = NULL; PTOKEN_USER pTokenUser = (PTOKEN_USER)InfoBuffer; PSID psidLocalSystem = NULL; PSID psidNetworkService = NULL; SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
*pfIsLocalSystem = FALSE;
//
// Get SID of calling thread.
//
if(!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken)) { Status = GetLastError(); goto cleanup; }
if(!GetTokenInformation(hToken, TokenUser, pTokenUser, dwInfoBufferSize, &dwInfoBufferSize)) { //
// if fast buffer wasn't big enough, allocate enough storage
// and try again.
//
Status = GetLastError(); if(Status != ERROR_INSUFFICIENT_BUFFER) { goto cleanup; }
SlowBuffer = (PTOKEN_USER)LocalAlloc(LPTR, dwInfoBufferSize); if(NULL == SlowBuffer) { Status = ERROR_NOT_ENOUGH_MEMORY; goto cleanup; }
pTokenUser = SlowBuffer; if(!GetTokenInformation(hToken, TokenUser, pTokenUser, dwInfoBufferSize, &dwInfoBufferSize)) { Status = GetLastError(); goto cleanup; } }
//
// Check for local system.
//
if(!AllocateAndInitializeSid(&siaNtAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &psidLocalSystem)) { Status = GetLastError(); goto cleanup; }
if (EqualSid(psidLocalSystem, pTokenUser->User.Sid)) { DebugLog((DEB_TRACE, "Client is using the LOCAL SYSTEM account.\n")); *pfIsLocalSystem = TRUE; Status = ERROR_SUCCESS; goto cleanup; }
//
// Check for network service.
//
if(!AllocateAndInitializeSid(&siaNtAuthority, 1, SECURITY_NETWORK_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0, &psidNetworkService)) { Status = GetLastError(); goto cleanup; }
if (EqualSid(psidNetworkService, pTokenUser->User.Sid)) { DebugLog((DEB_TRACE, "Client is using the NETWORK SERVICE account.\n")); *pfIsLocalSystem = TRUE; Status = ERROR_SUCCESS; goto cleanup; }
Status = ERROR_SUCCESS;
cleanup:
if(NULL != SlowBuffer) { LocalFree(SlowBuffer); }
if(NULL != psidLocalSystem) { FreeSid(psidLocalSystem); } if(NULL != psidNetworkService) { FreeSid(psidNetworkService); }
if(NULL != hToken) { CloseHandle(hToken); }
return Status; }
NTSTATUS FindClientCertificate( PSPContext pContext, HCERTSTORE hMyStore, CERT_CHAIN_FIND_BY_ISSUER_PARA *pFindByIssuerPara, BOOL fSkipExpiredCerts, BOOL fSoftwareCspOnly) { PCCERT_CHAIN_CONTEXT pChainContext = NULL; HTTPSPolicyCallbackData polHttps; CERT_CHAIN_POLICY_PARA PolicyPara; CERT_CHAIN_POLICY_STATUS PolicyStatus; PCCERT_CONTEXT pCertContext; NTSTATUS Status; ULONG j;
pChainContext = NULL;
while(TRUE) { // Find a certificate chain.
pChainContext = CertFindChainInStore(hMyStore, X509_ASN_ENCODING, 0, CERT_CHAIN_FIND_BY_ISSUER, pFindByIssuerPara, pChainContext); if(pChainContext == NULL) { break; }
// Make sure that every certificate in the chain either has the
// client auth EKU or it has no EKUs at all.
{ PCERT_SIMPLE_CHAIN pSimpleChain; PCCERT_CONTEXT pCurrentCert; BOOL fIsAllowed = FALSE;
pSimpleChain = pChainContext->rgpChain[0];
for(j = 0; j < pSimpleChain->cElement; j++) { pCurrentCert = pSimpleChain->rgpElement[j]->pCertContext;
Status = SPCheckKeyUsage(pCurrentCert, szOID_PKIX_KP_CLIENT_AUTH, TRUE, &fIsAllowed); if(Status != SEC_E_OK || !fIsAllowed) { fIsAllowed = FALSE; break; } } if(!fIsAllowed) { // skip this certificate chain.
continue; } }
// Set up validate chain structures.
ZeroMemory(&polHttps, sizeof(HTTPSPolicyCallbackData)); polHttps.cbStruct = sizeof(HTTPSPolicyCallbackData); polHttps.dwAuthType = AUTHTYPE_CLIENT; polHttps.fdwChecks = 0; polHttps.pwszServerName = NULL;
ZeroMemory(&PolicyStatus, sizeof(PolicyStatus)); PolicyStatus.cbSize = sizeof(PolicyStatus);
ZeroMemory(&PolicyPara, sizeof(PolicyPara)); PolicyPara.cbSize = sizeof(PolicyPara); PolicyPara.pvExtraPolicyPara= &polHttps;
PolicyPara.dwFlags = CERT_CHAIN_POLICY_IGNORE_WRONG_USAGE_FLAG | CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG; if(!fSkipExpiredCerts) { PolicyPara.dwFlags |= CERT_CHAIN_POLICY_IGNORE_ALL_NOT_TIME_VALID_FLAGS; }
// Validate chain
if(!CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL, pChainContext, &PolicyPara, &PolicyStatus)) { DebugLog((DEB_WARN,"Error 0x%x returned by CertVerifyCertificateChainPolicy!\n", GetLastError())); continue; } Status = MapWinTrustError(PolicyStatus.dwError, 0, 0); if(Status) { // Certificate did not validate, move on to the next one.
DebugLog((DEB_WARN, "Client certificate failed validation with 0x%x\n", Status)); continue; }
// Get pointer to leaf certificate context.
if(pChainContext->cChain == 0 || pChainContext->rgpChain[0] == NULL) { Status = SP_LOG_RESULT(SEC_E_INTERNAL_ERROR); goto cleanup; } if(pChainContext->rgpChain[0]->cElement == 0 || pChainContext->rgpChain[0]->rgpElement == NULL) { Status = SP_LOG_RESULT(SEC_E_INTERNAL_ERROR); goto cleanup; } pCertContext = pChainContext->rgpChain[0]->rgpElement[0]->pCertContext;
//
// Is the private key stored in a software CSP?
//
if(fSoftwareCspOnly) { DWORD dwImpType;
GetImplementationType(pCertContext, &dwImpType);
if(dwImpType != CRYPT_IMPL_SOFTWARE) { // Skip this certificate
continue; } }
//
// Assign the certificate to the current context.
//
Status = AssignNewClientCredential(pContext, pCertContext, FALSE); if(NT_SUCCESS(Status)) { // Success! Our work here is done.
goto cleanup; } }
// No suitable client credential was found.
Status = SP_LOG_RESULT(SEC_E_INCOMPLETE_CREDENTIALS);
cleanup:
if(pChainContext) { CertFreeCertificateChain(pChainContext); }
return Status; }
NTSTATUS AcquireDefaultClientCredential( PSPContext pContext, BOOL fCredManagerOnly) { CERT_CHAIN_FIND_BY_ISSUER_PARA FindByIssuerPara; CERT_NAME_BLOB * prgIssuers = NULL; DWORD cIssuers = 0; HCERTSTORE hStore = 0; NTSTATUS Status; BOOL fImpersonating = FALSE; BOOL fLocalSystem = FALSE; ULONG i;
DebugLog((DEB_TRACE,"AcquireDefaultClientCredential\n"));
//
// Is the application running under local system?
//
fImpersonating = SslImpersonateClient();
if(fImpersonating) { Status = IsThreadLocalSystem(&fLocalSystem); if(Status) { DebugLog((DEB_WARN, "IsThreadLocalSystem returned error 0x%x.\n", Status)); }
RevertToSelf(); fImpersonating = FALSE; }
//
// Ask the credential manager to select a certificate for us.
//
Status = QueryCredentialManagerForCert( pContext, pContext->pszTarget);
if(NT_SUCCESS(Status)) { DebugLog((DEB_TRACE, "Credential manager found a certificate for us.\n")); goto cleanup; }
if(fCredManagerOnly) { // No suitable client credential was found.
Status = SP_LOG_RESULT(SEC_I_INCOMPLETE_CREDENTIALS); goto cleanup; }
//
// Get list of trusted issuers as a list of CERT_NAME_BLOBs.
//
if(pContext->pbIssuerList && pContext->cbIssuerList > 2) { PBYTE pbIssuerList = pContext->pbIssuerList + 2; DWORD cbIssuerList = pContext->cbIssuerList - 2; PBYTE pbIssuer;
// Count issuers.
cIssuers = 0; pbIssuer = pbIssuerList; while(pbIssuer + 1 < pbIssuerList + cbIssuerList) { pbIssuer += 2 + COMBINEBYTES(pbIssuer[0], pbIssuer[1]); cIssuers++; }
// Allocate memory for list of blobs.
prgIssuers = SPExternalAlloc(cIssuers * sizeof(CERT_NAME_BLOB)); if(prgIssuers == NULL) { Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY); goto cleanup; }
// Build the issuer blob list.
pbIssuer = pbIssuerList; for(i = 0; i < cIssuers; i++) { prgIssuers[i].pbData = pbIssuer + 2; prgIssuers[i].cbData = COMBINEBYTES(pbIssuer[0], pbIssuer[1]);
pbIssuer += 2 + prgIssuers[i].cbData; } }
//
// Enumerate the certificates in the MY store, looking for a suitable
// client certificate.
//
fImpersonating = SslImpersonateClient();
if(fLocalSystem) { hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, X509_ASN_ENCODING, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG | CERT_STORE_OPEN_EXISTING_FLAG, L"MY"); } else { hStore = CertOpenSystemStore(0, "MY"); }
if(!hStore) { SP_LOG_RESULT(GetLastError()); Status = SEC_E_INTERNAL_ERROR; goto cleanup; }
ZeroMemory(&FindByIssuerPara, sizeof(FindByIssuerPara)); FindByIssuerPara.cbSize = sizeof(FindByIssuerPara); FindByIssuerPara.pszUsageIdentifier = szOID_PKIX_KP_CLIENT_AUTH; FindByIssuerPara.dwKeySpec = 0; FindByIssuerPara.cIssuer = cIssuers; FindByIssuerPara.rgIssuer = prgIssuers;
//
// Attempt to find a suitable certificate.
//
Status = FindClientCertificate(pContext, hStore, &FindByIssuerPara, TRUE, // skip expired certs
TRUE); // software CSPs only
if(NT_SUCCESS(Status)) { // Success! Our work here is done.
goto cleanup; }
Status = FindClientCertificate(pContext, hStore, &FindByIssuerPara, TRUE, // skip expired certs
FALSE); // software CSPs only
if(NT_SUCCESS(Status)) { // Success! Our work here is done.
goto cleanup; }
Status = FindClientCertificate(pContext, hStore, &FindByIssuerPara, FALSE, // skip expired certs
TRUE); // software CSPs only
if(NT_SUCCESS(Status)) { // Success! Our work here is done.
goto cleanup; }
Status = FindClientCertificate(pContext, hStore, &FindByIssuerPara, FALSE, // skip expired certs
FALSE); // software CSPs only
if(NT_SUCCESS(Status)) { // Success! Our work here is done.
goto cleanup; }
// No suitable client credential was found.
Status = SP_LOG_RESULT(SEC_I_INCOMPLETE_CREDENTIALS);
cleanup:
if(hStore) { CertCloseStore(hStore, 0); }
if(fImpersonating) { RevertToSelf(); }
if(prgIssuers) { SPExternalFree(prgIssuers); }
DebugLog((DEB_TRACE,"AcquireDefaultClientCredential returned 0x%x\n", Status));
return Status; }
NTSTATUS FindDefaultMachineCred( PSPCredentialGroup *ppCred, DWORD dwProtocol) { HTTPSPolicyCallbackData polHttps; CERT_CHAIN_POLICY_PARA PolicyPara; CERT_CHAIN_POLICY_STATUS PolicyStatus; CERT_CHAIN_PARA ChainPara; PCCERT_CHAIN_CONTEXT pChainContext = NULL; PCCERT_CONTEXT pCertContext = NULL; LSA_SCHANNEL_CRED SchannelCred; LSA_SCHANNEL_SUB_CRED SubCred; HCERTSTORE hStore = 0;
#define SERVER_USAGE_COUNT 3
LPSTR rgszUsages[SERVER_USAGE_COUNT] = { szOID_PKIX_KP_SERVER_AUTH, szOID_SERVER_GATED_CRYPTO, szOID_SGC_NETSCAPE };
LPWSTR pwszMachineName = NULL; DWORD cchMachineName; SP_STATUS Status; DWORD i;
// Get the machine name
cchMachineName = 0; if(!GetComputerNameExW(ComputerNameDnsFullyQualified, NULL, &cchMachineName)) { if(GetLastError() != ERROR_MORE_DATA) { DebugLog((DEB_ERROR,"Failed to get computer name size: 0x%x\n",GetLastError())); Status = SP_LOG_RESULT(SEC_E_WRONG_PRINCIPAL); goto cleanup; } } pwszMachineName = SPExternalAlloc(cchMachineName * sizeof(WCHAR)); if(pwszMachineName == NULL) { Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY); goto cleanup; } if(!GetComputerNameExW(ComputerNameDnsFullyQualified, pwszMachineName, &cchMachineName)) { DebugLog((DEB_ERROR,"Failed to get computer name: 0x%x\n",GetLastError())); Status = SP_LOG_RESULT(SEC_E_WRONG_PRINCIPAL); goto cleanup; }
// Remove the trailing "." if any. This can happen in the stand-alone
// server case.
cchMachineName = lstrlenW(pwszMachineName); if(cchMachineName > 0 && pwszMachineName[cchMachineName - 1] == L'.') { pwszMachineName[cchMachineName - 1] = L'\0'; }
DebugLog((DEB_TRACE,"Computer name: %ls\n",pwszMachineName));
// Open the system MY store.
hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, X509_ASN_ENCODING, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG | CERT_STORE_OPEN_EXISTING_FLAG, L"MY"); if(hStore == NULL) { SP_LOG_RESULT(GetLastError()); Status = SEC_E_NO_CREDENTIALS; goto cleanup; }
//
// Enumerate the certificates in the MY store, looking for a suitable
// server certificate. Do this twice, the first time looking for the
// perfect certificate, and if this fails then look again, this time
// being a little less picky.
//
for(i = 0; i < 2; i++) { pCertContext = NULL;
while(TRUE) { // Get leaf certificate in the MY store.
pCertContext = CertEnumCertificatesInStore(hStore, pCertContext); if(pCertContext == NULL) { // No more certificates.
break; }
//
// Build a certificate chain from the leaf certificate.
//
ZeroMemory(&ChainPara, sizeof(ChainPara)); ChainPara.cbSize = sizeof(ChainPara); ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; ChainPara.RequestedUsage.Usage.cUsageIdentifier = SERVER_USAGE_COUNT; ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = rgszUsages;
if(!CertGetCertificateChain( NULL, pCertContext, NULL, 0, &ChainPara, CERT_CHAIN_REVOCATION_CHECK_END_CERT, NULL, &pChainContext)) { DebugLog((DEB_WARN, "Error 0x%x returned by CertGetCertificateChain!\n", GetLastError())); continue; }
// Set up validate chain structures.
ZeroMemory(&polHttps, sizeof(HTTPSPolicyCallbackData)); polHttps.cbStruct = sizeof(HTTPSPolicyCallbackData); polHttps.dwAuthType = AUTHTYPE_SERVER; polHttps.fdwChecks = 0; polHttps.pwszServerName = pwszMachineName;
ZeroMemory(&PolicyStatus, sizeof(PolicyStatus)); PolicyStatus.cbSize = sizeof(PolicyStatus);
ZeroMemory(&PolicyPara, sizeof(PolicyPara)); PolicyPara.cbSize = sizeof(PolicyPara); PolicyPara.pvExtraPolicyPara= &polHttps; if(i == 0) { // Look for the perfect certificate.
PolicyPara.dwFlags = 0; } else { // Ignore expiration.
PolicyPara.dwFlags = CERT_CHAIN_POLICY_IGNORE_ALL_NOT_TIME_VALID_FLAGS; }
// Validate chain
if(!CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL, pChainContext, &PolicyPara, &PolicyStatus)) { SP_LOG_RESULT(GetLastError()); CertFreeCertificateChain(pChainContext); continue; } Status = MapWinTrustError(PolicyStatus.dwError, 0, CRED_FLAG_IGNORE_NO_REVOCATION_CHECK | CRED_FLAG_IGNORE_REVOCATION_OFFLINE); if(Status) { // Certificate did not validate, move on to the next one.
DebugLog((DEB_WARN, "Machine certificate failed validation with 0x%x\n", Status)); CertFreeCertificateChain(pChainContext); continue; }
CertFreeCertificateChain(pChainContext);
// Build an schannel credential.
ZeroMemory(&SchannelCred, sizeof(SchannelCred));
SchannelCred.dwVersion = SCHANNEL_CRED_VERSION; SchannelCred.cSubCreds = 1; SchannelCred.paSubCred = &SubCred;
ZeroMemory(&SubCred, sizeof(SubCred));
SubCred.pCert = pCertContext;
Status = SPCreateCredential(ppCred, dwProtocol, &SchannelCred); if(Status != PCT_ERR_OK) { // Don't use this certificate.
continue; }
// We have a winner!
DebugLog((DEB_TRACE, "Machine certificate automatically acquired\n")); Status = PCT_ERR_OK; goto cleanup; } }
// No suitable machine credential was found.
Status = SP_LOG_RESULT(SEC_E_NO_CREDENTIALS);
cleanup:
if(Status != PCT_ERR_OK) { LogNoDefaultServerCredEvent(); }
if(pwszMachineName) { SPExternalFree(pwszMachineName); }
if(pCertContext) { CertFreeCertificateContext(pCertContext); }
if(hStore) { CertCloseStore(hStore, 0); }
return Status; }
void GetImplementationType( PCCERT_CONTEXT pCertContext, PDWORD pdwImpType) { PCRYPT_KEY_PROV_INFO pProvInfo = NULL; HCRYPTPROV hProv = 0; DWORD cbSize; DWORD dwImpType;
*pdwImpType = CRYPT_IMPL_UNKNOWN;
if(!CertGetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, NULL, &cbSize)) { goto cleanup; }
pProvInfo = SPExternalAlloc(cbSize); if(pProvInfo == NULL) { goto cleanup; }
if(!CertGetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, pProvInfo, &cbSize)) { goto cleanup; }
// HACKHACK - clear the smart-card specific flag.
pProvInfo->dwFlags &= ~CERT_SET_KEY_CONTEXT_PROP_ID;
if(!CryptAcquireContextW(&hProv, pProvInfo->pwszContainerName, pProvInfo->pwszProvName, pProvInfo->dwProvType, pProvInfo->dwFlags | CRYPT_SILENT)) { goto cleanup; }
cbSize = sizeof(dwImpType); if(!CryptGetProvParam(hProv, PP_IMPTYPE, (PBYTE)&dwImpType, &cbSize, 0)) { goto cleanup; }
*pdwImpType = dwImpType;
cleanup:
if(pProvInfo) { SPExternalFree(pProvInfo); }
if(hProv) { CryptReleaseContext(hProv, 0); } }
|