#include #include #include #include #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 ); }