271 lines
7.9 KiB
C
271 lines
7.9 KiB
C
|
#include <windows.h>
|
||
|
#include <wincrypt.h>
|
||
|
#include <autoenr.h>
|
||
|
#include <cryptui.h>
|
||
|
|
||
|
#define MY_TEST_REG_ENTRY "Software\\Microsoft\\Cryptography\\AutoEnroll"
|
||
|
#define PST_EVENT_INIT "PS_SERVICE_STARTED"
|
||
|
|
||
|
|
||
|
/*BOOL SmallTest(DWORD dw)
|
||
|
{
|
||
|
HKEY hRegKey = 0;
|
||
|
DWORD dwDisposition;
|
||
|
BOOL fRet = FALSE;
|
||
|
|
||
|
if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, MY_TEST_REG_ENTRY,
|
||
|
0, NULL, REG_OPTION_NON_VOLATILE,
|
||
|
KEY_ALL_ACCESS, NULL, &hRegKey,
|
||
|
&dwDisposition))
|
||
|
goto Ret;
|
||
|
|
||
|
if (ERROR_SUCCESS != RegSetValueEx(hRegKey, "AutoEnrollTest", 0,
|
||
|
REG_BINARY, (BYTE*)&dw, sizeof(dw)))
|
||
|
goto Ret;
|
||
|
|
||
|
fRet = TRUE;
|
||
|
Ret:
|
||
|
if (hRegKey)
|
||
|
RegCloseKey(hRegKey);
|
||
|
SetLastError(dw);
|
||
|
return fRet;
|
||
|
}*/
|
||
|
|
||
|
void AutoEnrollErrorLogging(DWORD dwErr)
|
||
|
{
|
||
|
return;
|
||
|
// UNDONE - log the error along with some useful message
|
||
|
//SmallTest(dwErr);
|
||
|
}
|
||
|
|
||
|
#define FAST_BUFF_LEN 256
|
||
|
|
||
|
|
||
|
|
||
|
BOOL EnrollForACert(
|
||
|
IN BOOL fMachineEnrollment,
|
||
|
IN BOOL fRenewalRequired,
|
||
|
IN PAUTO_ENROLL_INFO pInfo
|
||
|
)
|
||
|
{
|
||
|
CRYPTUI_WIZ_CERT_REQUEST_INFO CertRequestInfo;
|
||
|
CRYPTUI_WIZ_CERT_REQUEST_PVK_NEW NewKeyInfo;
|
||
|
CRYPTUI_WIZ_CERT_TYPE CertType;
|
||
|
CRYPT_KEY_PROV_INFO ProviderInfo;
|
||
|
PCCERT_CONTEXT pCertContext = NULL;
|
||
|
PCCERT_CONTEXT pCert = NULL;
|
||
|
DWORD dwCAStatus;
|
||
|
DWORD dwAcquireFlags = 0;
|
||
|
LPWSTR pwszProvName = NULL;
|
||
|
WCHAR rgwszMachineName[MAX_COMPUTERNAME_LENGTH + 1];
|
||
|
DWORD cMachineName = MAX_COMPUTERNAME_LENGTH + 1;
|
||
|
CRYPT_DATA_BLOB CryptData;
|
||
|
DWORD dwErr = 0;
|
||
|
BOOL fRet = FALSE;
|
||
|
|
||
|
memset(&CertRequestInfo, 0, sizeof(CertRequestInfo));
|
||
|
memset(&NewKeyInfo, 0, sizeof(NewKeyInfo));
|
||
|
memset(&ProviderInfo, 0, sizeof(ProviderInfo));
|
||
|
memset(&rgwszMachineName, 0, sizeof(rgwszMachineName));
|
||
|
memset(&CryptData, 0, sizeof(CryptData));
|
||
|
memset(&CertType, 0, sizeof(CertType));
|
||
|
|
||
|
if (fMachineEnrollment)
|
||
|
{
|
||
|
dwAcquireFlags = CRYPT_MACHINE_KEYSET;
|
||
|
if (0 == GetComputerNameW(rgwszMachineName,
|
||
|
&cMachineName))
|
||
|
{
|
||
|
goto Ret;
|
||
|
}
|
||
|
CertRequestInfo.pwszMachineName = rgwszMachineName;
|
||
|
}
|
||
|
|
||
|
// set up the provider info
|
||
|
ProviderInfo.dwProvType = pInfo->dwProvType;
|
||
|
|
||
|
ProviderInfo.pwszProvName = NULL; // The wizard will choose one based
|
||
|
// on the cert type
|
||
|
|
||
|
// set the acquire context flags
|
||
|
// UNDONE - need to add silent flag
|
||
|
ProviderInfo.dwFlags = dwAcquireFlags;
|
||
|
|
||
|
// set the key specification
|
||
|
ProviderInfo.dwKeySpec = pInfo->dwKeySpec;
|
||
|
|
||
|
// set up the new key info
|
||
|
NewKeyInfo.dwSize = sizeof(NewKeyInfo);
|
||
|
NewKeyInfo.pKeyProvInfo = &ProviderInfo;
|
||
|
// set the flags to be passed when calling CryptGenKey
|
||
|
NewKeyInfo.dwGenKeyFlags = pInfo->dwGenKeyFlags;
|
||
|
|
||
|
// set the request info
|
||
|
CertRequestInfo.dwSize = sizeof(CertRequestInfo);
|
||
|
|
||
|
// UNDONE - if cert exists then check if expired (if so do renewal)
|
||
|
if (pInfo->fRenewal)
|
||
|
{
|
||
|
CertRequestInfo.dwPurpose = CRYPTUI_WIZ_CERT_RENEW;
|
||
|
CertRequestInfo.pRenewCertContext = pInfo->pOldCert;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CertRequestInfo.dwPurpose = CRYPTUI_WIZ_CERT_ENROLL;
|
||
|
CertRequestInfo.pRenewCertContext = NULL;
|
||
|
}
|
||
|
|
||
|
// UNDONE - for now always gen a new key, later may allow using existing key
|
||
|
// for things like renewal
|
||
|
CertRequestInfo.dwPvkChoice = CRYPTUI_WIZ_CERT_REQUEST_PVK_CHOICE_NEW;
|
||
|
CertRequestInfo.pPvkNew = &NewKeyInfo;
|
||
|
|
||
|
// destination cert store is the MY store (!!!! hard coded !!!!)
|
||
|
CertRequestInfo.pwszDesStore = L"MY";
|
||
|
|
||
|
// set algorithm for hashing
|
||
|
CertRequestInfo.pszHashAlg = NULL;
|
||
|
|
||
|
// set the cert type
|
||
|
CertRequestInfo.dwCertChoice = CRYPTUI_WIZ_CERT_REQUEST_CERT_TYPE;
|
||
|
CertType.dwSize = sizeof(CertType);
|
||
|
CertType.cCertType = 1;
|
||
|
CertType.rgwszCertType = &pInfo->pwszCertType;
|
||
|
CertRequestInfo.pCertType = &CertType;
|
||
|
|
||
|
// set the requested cert extensions
|
||
|
CertRequestInfo.pCertRequestExtensions = &pInfo->CertExtensions;
|
||
|
|
||
|
// set post option
|
||
|
CertRequestInfo.dwPostOption = 0;
|
||
|
|
||
|
// set the Cert Server machine and authority
|
||
|
CertRequestInfo.pwszCALocation = pInfo->pwszCAMachine;
|
||
|
CertRequestInfo.pwszCAName = pInfo->pwszCAAuthority;
|
||
|
|
||
|
// certify and create a key at the same time
|
||
|
if (!CryptUIWizCertRequest(CRYPTUI_WIZ_NO_UI, 0, NULL,
|
||
|
&CertRequestInfo, &pCertContext,
|
||
|
&dwCAStatus))
|
||
|
{
|
||
|
AutoEnrollErrorLogging(GetLastError());
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
if (CRYPTUI_WIZ_CERT_REQUEST_STATUS_SUCCEEDED == dwCAStatus)
|
||
|
{
|
||
|
BYTE aHash[20];
|
||
|
CRYPT_HASH_BLOB blobHash;
|
||
|
|
||
|
blobHash.pbData = aHash;
|
||
|
blobHash.cbData = sizeof(aHash);
|
||
|
CryptData.cbData = (wcslen(pInfo->pwszAutoEnrollmentID) + 1) * sizeof(WCHAR);
|
||
|
CryptData.pbData = (BYTE*)pInfo->pwszAutoEnrollmentID;
|
||
|
|
||
|
// We need to get the real certificate of the store, as the one
|
||
|
// passed back is self contained.
|
||
|
if(!CertGetCertificateContextProperty(pCertContext,
|
||
|
CERT_SHA1_HASH_PROP_ID,
|
||
|
blobHash.pbData,
|
||
|
&blobHash.cbData))
|
||
|
{
|
||
|
AutoEnrollErrorLogging(GetLastError());
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
pCert = CertFindCertificateInStore(pInfo->hMYStore,
|
||
|
pCertContext->dwCertEncodingType,
|
||
|
0,
|
||
|
CERT_FIND_SHA1_HASH,
|
||
|
&blobHash,
|
||
|
NULL);
|
||
|
if(pCert == NULL)
|
||
|
{
|
||
|
AutoEnrollErrorLogging(GetLastError());
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// place the auto enrollment property on the cert
|
||
|
if (!CertSetCertificateContextProperty(pCert,
|
||
|
CERT_AUTO_ENROLL_PROP_ID, 0, &CryptData))
|
||
|
{
|
||
|
AutoEnrollErrorLogging(GetLastError());
|
||
|
goto Ret;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// UNDONE - request did not return cert so take appropriate action
|
||
|
// else
|
||
|
// {
|
||
|
// goto Ret;
|
||
|
// }
|
||
|
|
||
|
fRet = TRUE;
|
||
|
Ret:
|
||
|
if (pCertContext)
|
||
|
CertFreeCertificateContext(pCertContext);
|
||
|
|
||
|
if (pCert)
|
||
|
CertFreeCertificateContext(pCert);
|
||
|
|
||
|
if (pwszProvName)
|
||
|
LocalFree(pwszProvName);
|
||
|
|
||
|
return fRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ProvAutoEnrollment
|
||
|
//
|
||
|
// Synopsis: Entry point for the default MS auto enrollment client provider.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// fMachineEnrollment - TRUE if machine is enrolling, FALSE if user
|
||
|
//
|
||
|
// pInfo - information needed to enroll (see AUTO_ENROLL_INFO struct
|
||
|
// in autoenrl.h)
|
||
|
//
|
||
|
// History: 01-12-98 jeffspel Created
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
BOOL ProvAutoEnrollment(
|
||
|
IN BOOL fMachineEnrollment,
|
||
|
IN PAUTO_ENROLL_INFO pInfo
|
||
|
)
|
||
|
{
|
||
|
BOOL fRenewalRequired = FALSE;
|
||
|
BOOL fRet = FALSE;
|
||
|
|
||
|
|
||
|
// enroll for a cert
|
||
|
if (!EnrollForACert(fMachineEnrollment, fRenewalRequired, pInfo))
|
||
|
goto Ret;
|
||
|
|
||
|
fRet = TRUE;
|
||
|
Ret:
|
||
|
return fRet;
|
||
|
}
|
||
|
|
||
|
BOOLEAN
|
||
|
DllInitialize(
|
||
|
IN PVOID hmod,
|
||
|
IN ULONG Reason,
|
||
|
IN PCONTEXT Context
|
||
|
)
|
||
|
{
|
||
|
|
||
|
return( TRUE );
|
||
|
|
||
|
}
|