Source code of Windows XP (NT5)
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.

8967 lines
264 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 2000
  6. //
  7. // File: autoenro.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include <windows.h>
  11. #include <winuser.h>
  12. #include <wincrypt.h>
  13. #include <cryptui.h>
  14. #include <lmcons.h>
  15. #include <lmapibuf.h>
  16. #include <dsgetdc.h>
  17. #include <oleauto.h>
  18. #define SECURITY_WIN32
  19. #include <rpc.h>
  20. #include <security.h>
  21. #include <winldap.h>
  22. #include <dsrole.h>
  23. #include <shobjidl.h>
  24. #include <shellapi.h>
  25. #include <commctrl.h>
  26. #include <winscard.h>
  27. #include <Rpcdce.h>
  28. #include <certca.h>
  29. #include <certsrv.h>
  30. #include <autoenr.h>
  31. #include <autoenro.h>
  32. #include <autolog.h>
  33. #include <resource.h>
  34. #include <xenroll.h>
  35. //*******************************************************************************
  36. //
  37. //
  38. // Global Defines and Data Structures
  39. //
  40. //
  41. //*******************************************************************************
  42. HINSTANCE g_hmodThisDll = NULL; // Handle to this DLL itself.
  43. #if DBG
  44. DWORD g_AutoenrollDebugLevel = AE_ERROR; //| AE_WARNING | AE_INFO | AE_TRACE;
  45. #endif
  46. //when we look at supersede relationship, we based on the following order
  47. DWORD g_rgdwSupersedeOrder[]={CERT_REQUEST_STATUS_OBTAINED,
  48. CERT_REQUEST_STATUS_ACTIVE,
  49. CERT_REQUEST_STATUS_PENDING,
  50. CERT_REQUEST_STATUS_SUPERSEDE_ACTIVE};
  51. DWORD g_dwSupersedeOrder=sizeof(g_rgdwSupersedeOrder)/sizeof(g_rgdwSupersedeOrder[0]);
  52. //the list of certificate store to update
  53. AE_STORE_INFO g_rgStoreInfo[]={
  54. L"ROOT", L"ldap://%s/CN=Certification Authorities,CN=Public Key Services,CN=Services,%s?cACertificate?one?objectCategory=certificationAuthority",
  55. L"NTAuth", L"ldap://%s/CN=Public Key Services,CN=Services,%s?cACertificate?one?cn=NTAuthCertificates",
  56. L"CA", L"ldap://%s/CN=AIA,CN=Public Key Services,CN=Services,%s?crossCertificatePair,cACertificate?one?objectCategory=certificationAuthority"
  57. };
  58. DWORD g_dwStoreInfo=sizeof(g_rgStoreInfo)/sizeof(g_rgStoreInfo[0]);
  59. typedef IEnroll4 * (WINAPI *PFNPIEnroll4GetNoCOM)();
  60. static WCHAR * s_wszLocation = L"CN=Public Key Services,CN=Services,";
  61. //Enhanced key usage for DS email replication
  62. #ifndef CT_FLAG_REMOVE_INVALID_CERTIFICATE_FROM_PERSONAL_STORE
  63. #define CT_FLAG_REMOVE_INVALID_CERTIFICATE_FROM_PERSONAL_STORE 0x00000400
  64. #endif
  65. //*******************************************************************************
  66. //
  67. //
  68. // Implementation of IQueryContinue for use autoenrollment notification
  69. //
  70. //
  71. //*******************************************************************************
  72. //--------------------------------------------------------------------------
  73. // CQueryContinue
  74. //--------------------------------------------------------------------------
  75. CQueryContinue::CQueryContinue()
  76. {
  77. m_cRef=1;
  78. m_pIUserNotification=NULL;
  79. m_hTimer=NULL;
  80. }
  81. //--------------------------------------------------------------------------
  82. // ~CQueryContinue
  83. //--------------------------------------------------------------------------
  84. CQueryContinue::~CQueryContinue()
  85. {
  86. }
  87. //--------------------------------------------------------------------------
  88. // CQueryContinue
  89. //--------------------------------------------------------------------------
  90. HRESULT CQueryContinue::QueryInterface(REFIID riid, void **ppv)
  91. {
  92. if(IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IQueryContinue))
  93. {
  94. *ppv=(LPVOID)this;
  95. AddRef();
  96. return S_OK;
  97. }
  98. return E_NOINTERFACE;
  99. }
  100. //--------------------------------------------------------------------------
  101. // AddRef
  102. //--------------------------------------------------------------------------
  103. STDMETHODIMP_(ULONG) CQueryContinue::AddRef()
  104. {
  105. return InterlockedIncrement(&m_cRef);
  106. }
  107. //--------------------------------------------------------------------------
  108. // Release
  109. //--------------------------------------------------------------------------
  110. STDMETHODIMP_(ULONG) CQueryContinue::Release()
  111. {
  112. if (InterlockedDecrement(&m_cRef))
  113. return m_cRef;
  114. delete this;
  115. return 0;
  116. }
  117. //--------------------------------------------------------------------------
  118. // CQueryContinue
  119. //--------------------------------------------------------------------------
  120. HRESULT CQueryContinue::QueryContinue()
  121. {
  122. //disable the balloon
  123. if(m_pIUserNotification)
  124. m_pIUserNotification->SetBalloonInfo(NULL, NULL, NIIF_INFO);
  125. //wait for the timer to be activated
  126. if(m_hTimer)
  127. {
  128. if(WAIT_OBJECT_0 == WaitForSingleObject(m_hTimer, 0))
  129. return S_FALSE;
  130. }
  131. return S_OK;
  132. }
  133. //--------------------------------------------------------------------------
  134. // DoBalloon()
  135. //--------------------------------------------------------------------------
  136. HRESULT CQueryContinue::DoBalloon()
  137. {
  138. HRESULT hr=E_FAIL;
  139. WCHAR wszTitle[MAX_DN_SIZE];
  140. WCHAR wszText[MAX_DN_SIZE];
  141. HICON hIcon=NULL;
  142. LARGE_INTEGER DueTime;
  143. if(S_OK != (hr=CoCreateInstance(CLSID_UserNotification,
  144. NULL,
  145. CLSCTX_ALL,
  146. IID_IUserNotification,
  147. (void **)&m_pIUserNotification)))
  148. goto Ret;
  149. if(NULL==m_pIUserNotification)
  150. {
  151. hr=E_FAIL;
  152. goto Ret;
  153. }
  154. //create a waitable timer with default security setting
  155. m_hTimer=CreateWaitableTimer(NULL, TRUE, NULL);
  156. if(NULL==m_hTimer)
  157. {
  158. hr=E_FAIL;
  159. goto Ret;
  160. }
  161. //set the timer
  162. DueTime.QuadPart = Int32x32To64(-10000, AUTO_ENROLLMENT_BALLOON_LENGTH * 1000);
  163. if(!SetWaitableTimer(m_hTimer, &DueTime, 0, NULL, 0, FALSE))
  164. {
  165. hr=E_FAIL;
  166. goto Ret;
  167. }
  168. if(S_OK != (hr=m_pIUserNotification->SetBalloonRetry(AUTO_ENROLLMENT_SHOW_TIME * 1000,
  169. AUTO_ENROLLMENT_INTERVAL * 1000,
  170. AUTO_ENROLLMENT_RETRIAL)))
  171. goto Ret;
  172. if((!LoadStringW(g_hmodThisDll,IDS_ICON_TIP, wszText, MAX_DN_SIZE)) ||
  173. (NULL==(hIcon=LoadIcon(g_hmodThisDll, MAKEINTRESOURCE(IDI_AUTOENROLL_ICON)))))
  174. {
  175. hr=E_FAIL;
  176. goto Ret;
  177. }
  178. if(S_OK != (hr=m_pIUserNotification->SetIconInfo(hIcon, wszText)))
  179. goto Ret;
  180. if((!LoadStringW(g_hmodThisDll,IDS_BALLOON_TITLE, wszTitle, MAX_DN_SIZE)) ||
  181. (!LoadStringW(g_hmodThisDll,IDS_BALLOON_TEXT, wszText, MAX_DN_SIZE)))
  182. {
  183. hr=E_FAIL;
  184. goto Ret;
  185. }
  186. if(S_OK !=(hr=m_pIUserNotification->SetBalloonInfo(wszTitle, wszText, NIIF_INFO)))
  187. goto Ret;
  188. //user did not click on the icon or we time out
  189. hr= m_pIUserNotification->Show(this, AUTO_ENROLLMENT_QUERY_INTERVAL * 1000);
  190. Ret:
  191. if(m_hTimer)
  192. {
  193. CloseHandle(m_hTimer);
  194. m_hTimer=NULL;
  195. }
  196. if(m_pIUserNotification)
  197. {
  198. m_pIUserNotification->Release();
  199. m_pIUserNotification=NULL;
  200. }
  201. return hr;
  202. }
  203. //*******************************************************************************
  204. //
  205. //
  206. // Functions for autoenrollment
  207. //
  208. //
  209. //*******************************************************************************
  210. //--------------------------------------------------------------------------
  211. //
  212. // Name: FindCertificateInOtherStore
  213. //
  214. //--------------------------------------------------------------------------
  215. PCCERT_CONTEXT FindCertificateInOtherStore(
  216. IN HCERTSTORE hOtherStore,
  217. IN PCCERT_CONTEXT pCert
  218. )
  219. {
  220. BYTE rgbHash[SHA1_HASH_LENGTH];
  221. CRYPT_DATA_BLOB HashBlob;
  222. HashBlob.pbData = rgbHash;
  223. HashBlob.cbData = SHA1_HASH_LENGTH;
  224. if (!CertGetCertificateContextProperty(
  225. pCert,
  226. CERT_SHA1_HASH_PROP_ID,
  227. rgbHash,
  228. &HashBlob.cbData
  229. ) || SHA1_HASH_LENGTH != HashBlob.cbData)
  230. return NULL;
  231. return CertFindCertificateInStore(
  232. hOtherStore,
  233. ENCODING_TYPE, // dwCertEncodingType
  234. 0, // dwFindFlags
  235. CERT_FIND_SHA1_HASH,
  236. (const void *) &HashBlob,
  237. NULL //pPrevCertContext
  238. );
  239. }
  240. //--------------------------------------------------------------------------
  241. //
  242. // AEUpdateCertificateStore
  243. //
  244. // Description: This function enumerates all of the certificate in the DS based
  245. // LdapPath, and moves them into the corresponding local machine store.
  246. //
  247. //--------------------------------------------------------------------------
  248. HRESULT WINAPI AEUpdateCertificateStore(LDAP *pld,
  249. LPWSTR pwszConfig,
  250. LPWSTR pwszDCName,
  251. LPWSTR pwszStoreName,
  252. LPWSTR pwszLdapPath)
  253. {
  254. HRESULT hr = S_OK;
  255. PCCERT_CONTEXT pContext = NULL,
  256. pOtherCert = NULL;
  257. LPWSTR pwszLdapStore = NULL;
  258. HCERTSTORE hEnterpriseStore = NULL,
  259. hLocalStore = NULL;
  260. if((NULL==pld) || (NULL==pwszConfig) || (NULL==pwszDCName) || (NULL==pwszStoreName) || (NULL==pwszLdapPath))
  261. {
  262. hr = E_INVALIDARG;
  263. goto error;
  264. }
  265. pwszLdapStore = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*(wcslen(pwszConfig)+wcslen(pwszDCName)+wcslen(pwszLdapPath)));
  266. if(pwszLdapStore == NULL)
  267. {
  268. hr = E_OUTOFMEMORY;
  269. goto error;
  270. }
  271. wsprintf(pwszLdapStore,
  272. pwszLdapPath,
  273. pwszDCName,
  274. pwszConfig);
  275. hLocalStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_REGISTRY_W,
  276. 0,
  277. 0,
  278. CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE,
  279. pwszStoreName);
  280. if(hLocalStore == NULL)
  281. {
  282. hr = HRESULT_FROM_WIN32(GetLastError());
  283. AE_DEBUG((AE_ERROR, L"Unable to open ROOT store (%lx)\n\r", hr));
  284. goto error;
  285. }
  286. hEnterpriseStore = CertOpenStore(CERT_STORE_PROV_LDAP,
  287. 0,
  288. 0,
  289. CERT_STORE_READONLY_FLAG | CERT_LDAP_STORE_SIGN_FLAG |
  290. CERT_LDAP_STORE_AREC_EXCLUSIVE_FLAG,
  291. pwszLdapStore);
  292. if(hEnterpriseStore == NULL)
  293. {
  294. DWORD err = GetLastError();
  295. if((err == ERROR_FILE_NOT_FOUND))
  296. {
  297. // There was no store, so there are no certs
  298. hr = S_OK;
  299. goto error;
  300. }
  301. hr = HRESULT_FROM_WIN32(err);
  302. AE_DEBUG((AE_ERROR, L"Unable to open ROOT store (%lx)\n\r", hr));
  303. goto error;
  304. }
  305. while(pContext = CertEnumCertificatesInStore(hEnterpriseStore, pContext))
  306. {
  307. if (pOtherCert = FindCertificateInOtherStore(hLocalStore, pContext)) {
  308. CertFreeCertificateContext(pOtherCert);
  309. }
  310. else
  311. {
  312. CertAddCertificateContextToStore(hLocalStore,
  313. pContext,
  314. CERT_STORE_ADD_ALWAYS,
  315. NULL);
  316. }
  317. }
  318. while(pContext = CertEnumCertificatesInStore(hLocalStore, pContext))
  319. {
  320. if (pOtherCert = FindCertificateInOtherStore(hEnterpriseStore, pContext)) {
  321. CertFreeCertificateContext(pOtherCert);
  322. }
  323. else
  324. {
  325. CertDeleteCertificateFromStore(CertDuplicateCertificateContext(pContext));
  326. }
  327. }
  328. error:
  329. if(hr != S_OK)
  330. {
  331. AELogAutoEnrollmentEvent(
  332. STATUS_SEVERITY_ERROR, //this event will always be logged
  333. TRUE,
  334. hr,
  335. EVENT_FAIL_DOWNLOAD_CERT,
  336. TRUE,
  337. NULL,
  338. 3,
  339. pwszStoreName,
  340. pwszConfig,
  341. pwszLdapPath);
  342. }
  343. if(pwszLdapStore)
  344. {
  345. LocalFree(pwszLdapStore);
  346. }
  347. if(hEnterpriseStore)
  348. {
  349. CertCloseStore(hEnterpriseStore,0);
  350. }
  351. if(hLocalStore)
  352. {
  353. CertCloseStore(hLocalStore,0);
  354. }
  355. return hr;
  356. }
  357. //--------------------------------------------------------------------------
  358. //
  359. // AENeedToUpdateDSCache
  360. //
  361. //--------------------------------------------------------------------------
  362. BOOL AENeedToUpdateDSCache(LDAP *pld, LPWSTR pwszDCInvocationID, LPWSTR pwszConfig, AE_DS_INFO *pAEDSInfo)
  363. {
  364. BOOL fNeedToUpdate=TRUE;
  365. DWORD dwRegObject=0;
  366. ULARGE_INTEGER maxRegUSN;
  367. ULARGE_INTEGER maxDsUSN;
  368. DWORD dwType=0;
  369. DWORD dwSize=0;
  370. DWORD dwDisp=0;
  371. struct l_timeval timeout;
  372. LPWSTR rgwszAttrs[] = {AUTO_ENROLLMENT_USN_ATTR, NULL};
  373. LDAPMessage *Entry=NULL;
  374. LPWSTR *awszValue = NULL;
  375. HKEY hDSKey=NULL;
  376. HKEY hDCKey=NULL;
  377. LDAPMessage *SearchResult = NULL;
  378. LPWSTR pwszContainer=NULL;
  379. if((NULL==pld) || (NULL==pwszDCInvocationID) || (NULL==pwszConfig) || (NULL==pAEDSInfo))
  380. goto error;
  381. //init
  382. memset(pAEDSInfo, 0, sizeof(AE_DS_INFO));
  383. //compute the # of objects and maxUSN from the directory
  384. pwszContainer=(LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * (1 + wcslen(pwszConfig) + wcslen(s_wszLocation)));
  385. if(NULL == pwszContainer)
  386. goto error;
  387. wcscpy(pwszContainer, s_wszLocation);
  388. wcscat(pwszContainer, pwszConfig);
  389. timeout.tv_sec = 300;
  390. timeout.tv_usec = 0;
  391. if(LDAP_SUCCESS != ldap_search_stW(
  392. pld,
  393. pwszContainer,
  394. LDAP_SCOPE_SUBTREE,
  395. L"(objectCategory=certificationAuthority)",
  396. rgwszAttrs,
  397. 0,
  398. &timeout,
  399. &SearchResult))
  400. goto error;
  401. //get the # of objects
  402. pAEDSInfo->dwObjects = ldap_count_entries(pld, SearchResult);
  403. for(Entry = ldap_first_entry(pld, SearchResult); Entry != NULL; Entry = ldap_next_entry(pld, Entry))
  404. {
  405. awszValue = ldap_get_values(pld, Entry, AUTO_ENROLLMENT_USN_ATTR);
  406. if(NULL==awszValue)
  407. goto error;
  408. if(NULL==awszValue[0])
  409. goto error;
  410. maxDsUSN.QuadPart=0;
  411. maxDsUSN.QuadPart=_wtoi64(awszValue[0]);
  412. //if any error happens, maxDsUSN will be 0.
  413. if(0 == maxDsUSN.QuadPart)
  414. goto error;
  415. if((pAEDSInfo->maxUSN).QuadPart < maxDsUSN.QuadPart)
  416. (pAEDSInfo->maxUSN).QuadPart = maxDsUSN.QuadPart;
  417. ldap_value_free(awszValue);
  418. awszValue=NULL;
  419. }
  420. //signal that we have retrieved correct data from the directory
  421. pAEDSInfo->fValidData=TRUE;
  422. //find if we have cached any information about the DC of interest
  423. if(ERROR_SUCCESS != RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  424. AUTO_ENROLLMENT_DS_KEY,
  425. 0,
  426. TEXT(""),
  427. REG_OPTION_NON_VOLATILE,
  428. KEY_ALL_ACCESS,
  429. NULL,
  430. &hDSKey,
  431. &dwDisp))
  432. goto error;
  433. if(ERROR_SUCCESS != RegOpenKeyEx(
  434. hDSKey,
  435. pwszDCInvocationID,
  436. 0,
  437. KEY_ALL_ACCESS,
  438. &hDCKey))
  439. goto error;
  440. dwSize=sizeof(dwRegObject);
  441. if(ERROR_SUCCESS != RegQueryValueEx(
  442. hDCKey,
  443. AUTO_ENROLLMENT_DS_OBJECT,
  444. NULL,
  445. &dwType,
  446. (PBYTE)(&dwRegObject),
  447. &dwSize))
  448. goto error;
  449. if(REG_DWORD != dwType)
  450. goto error;
  451. dwSize=sizeof(maxRegUSN);
  452. if(ERROR_SUCCESS != RegQueryValueEx(
  453. hDCKey,
  454. AUTO_ENROLLMENT_DS_USN,
  455. NULL,
  456. &dwType,
  457. (PBYTE)(&(maxRegUSN)),
  458. &dwSize))
  459. goto error;
  460. if(REG_BINARY != dwType)
  461. goto error;
  462. //compare the registry data with the data from directory
  463. if(dwRegObject != (pAEDSInfo->dwObjects))
  464. goto error;
  465. if(maxRegUSN.QuadPart != ((pAEDSInfo->maxUSN).QuadPart))
  466. goto error;
  467. fNeedToUpdate=FALSE;
  468. error:
  469. if(awszValue)
  470. ldap_value_free(awszValue);
  471. if(pwszContainer)
  472. LocalFree(pwszContainer);
  473. if(hDCKey)
  474. RegCloseKey(hDCKey);
  475. if(hDSKey)
  476. RegCloseKey(hDSKey);
  477. if(SearchResult)
  478. ldap_msgfree(SearchResult);
  479. //remove the temporary data
  480. if(pAEDSInfo)
  481. {
  482. if(FALSE == fNeedToUpdate)
  483. memset(pAEDSInfo, 0, sizeof(AE_DS_INFO));
  484. }
  485. return fNeedToUpdate;
  486. }
  487. //--------------------------------------------------------------------------
  488. //
  489. // AEUpdateDSCache
  490. //
  491. //--------------------------------------------------------------------------
  492. BOOL AEUpdateDSCache(LPWSTR pwszDCInvocationID, AE_DS_INFO *pAEDSInfo)
  493. {
  494. BOOL fResult=FALSE;
  495. DWORD dwDisp=0;
  496. HKEY hDSKey=NULL;
  497. HKEY hDCKey=NULL;
  498. if((NULL==pwszDCInvocationID) || (NULL==pAEDSInfo))
  499. goto error;
  500. if(ERROR_SUCCESS != RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  501. AUTO_ENROLLMENT_DS_KEY,
  502. 0,
  503. TEXT(""),
  504. REG_OPTION_NON_VOLATILE,
  505. KEY_ALL_ACCESS,
  506. NULL,
  507. &hDSKey,
  508. &dwDisp))
  509. goto error;
  510. //create the key named by the DC
  511. if(ERROR_SUCCESS != RegCreateKeyEx(hDSKey,
  512. pwszDCInvocationID,
  513. 0,
  514. TEXT(""),
  515. REG_OPTION_NON_VOLATILE,
  516. KEY_ALL_ACCESS,
  517. NULL,
  518. &hDCKey,
  519. &dwDisp))
  520. goto error;
  521. //set the # of objects value
  522. if(ERROR_SUCCESS != RegSetValueEx(hDCKey,
  523. AUTO_ENROLLMENT_DS_OBJECT,
  524. NULL,
  525. REG_DWORD,
  526. (PBYTE)&(pAEDSInfo->dwObjects),
  527. sizeof(pAEDSInfo->dwObjects)))
  528. goto error;
  529. //set the max uSN value
  530. if(ERROR_SUCCESS != RegSetValueEx(hDCKey,
  531. AUTO_ENROLLMENT_DS_USN,
  532. NULL,
  533. REG_BINARY,
  534. (PBYTE)&(pAEDSInfo->maxUSN),
  535. sizeof(pAEDSInfo->maxUSN)))
  536. goto error;
  537. fResult=TRUE;
  538. error:
  539. if(hDCKey)
  540. RegCloseKey(hDCKey);
  541. if(hDSKey)
  542. RegCloseKey(hDSKey);
  543. return fResult;
  544. }
  545. //--------------------------------------------------------------------------
  546. //
  547. // AERetrieveInvocationID
  548. //
  549. //--------------------------------------------------------------------------
  550. BOOL AERetrieveInvocationID(LDAP *pld, LPWSTR *ppwszID)
  551. {
  552. BOOL fResult=FALSE;
  553. struct l_timeval timeout;
  554. LPWSTR rgwszDSAttrs[] = {L"dsServiceName", NULL};
  555. LPWSTR rgwszIDAttr[] = {L"invocationId", NULL};
  556. LDAPMessage *Entry=NULL;
  557. LPWSTR *awszValues = NULL;
  558. LDAPMessage *SearchResults = NULL;
  559. struct berval **apUUID = NULL;
  560. LDAPMessage *SearchIDResult = NULL;
  561. BYTE *pbUUID=NULL;
  562. if((NULL==pld) || (NULL==ppwszID))
  563. goto error;
  564. *ppwszID=NULL;
  565. //retrieve the dsSerivceName attribute
  566. timeout.tv_sec = 300;
  567. timeout.tv_usec = 0;
  568. if(LDAP_SUCCESS != ldap_search_stW(
  569. pld,
  570. NULL, //NULL DN for dsServiceName
  571. LDAP_SCOPE_BASE,
  572. L"(objectCategory=*)",
  573. rgwszDSAttrs,
  574. 0,
  575. &timeout,
  576. &SearchResults))
  577. goto error;
  578. Entry = ldap_first_entry(pld, SearchResults);
  579. if(NULL == Entry)
  580. goto error;
  581. awszValues = ldap_get_values(pld, Entry, rgwszDSAttrs[0]);
  582. if(NULL==awszValues)
  583. goto error;
  584. if(NULL==awszValues[0])
  585. goto error;
  586. //retrieve the invocationId attribute
  587. timeout.tv_sec = 300;
  588. timeout.tv_usec = 0;
  589. if(LDAP_SUCCESS != ldap_search_stW(
  590. pld,
  591. awszValues[0],
  592. LDAP_SCOPE_BASE,
  593. L"(objectCategory=*)",
  594. rgwszIDAttr,
  595. 0,
  596. &timeout,
  597. &SearchIDResult))
  598. goto error;
  599. Entry = ldap_first_entry(pld, SearchIDResult);
  600. if(NULL == Entry)
  601. goto error;
  602. apUUID = ldap_get_values_len(pld, Entry, rgwszIDAttr[0]);
  603. if(NULL == apUUID)
  604. goto error;
  605. if(NULL == (*apUUID))
  606. goto error;
  607. pbUUID = (BYTE *)LocalAlloc(LPTR, (*apUUID)->bv_len);
  608. if(NULL == (pbUUID))
  609. goto error;
  610. memcpy(pbUUID, (*apUUID)->bv_val, (*apUUID)->bv_len);
  611. if(RPC_S_OK != UuidToStringW((UUID *)pbUUID, ppwszID))
  612. goto error;
  613. fResult=TRUE;
  614. error:
  615. if(pbUUID)
  616. LocalFree(pbUUID);
  617. if(apUUID)
  618. ldap_value_free_len(apUUID);
  619. if(SearchIDResult)
  620. ldap_msgfree(SearchIDResult);
  621. if(awszValues)
  622. ldap_value_free(awszValues);
  623. if(SearchResults)
  624. ldap_msgfree(SearchResults);
  625. return fResult;
  626. }
  627. //--------------------------------------------------------------------------
  628. //
  629. // AEDownloadStore
  630. //
  631. //--------------------------------------------------------------------------
  632. BOOL WINAPI AEDownloadStore(LDAP *pld, LPWSTR pwszDCName)
  633. {
  634. BOOL fResult = TRUE;
  635. DWORD dwIndex = 0;
  636. AE_DS_INFO AEDSInfo;
  637. LPWSTR wszConfig = NULL;
  638. LPWSTR pwszDCInvocationID = NULL;
  639. memset(&AEDSInfo, 0, sizeof(AEDSInfo));
  640. if(S_OK != AEGetConfigDN(pld, &wszConfig))
  641. {
  642. fResult=FALSE;
  643. goto error;
  644. }
  645. //get the pwszDCInvocationID. NULL means AENeedToUpdateDSCache will return TRUE
  646. AERetrieveInvocationID(pld, &pwszDCInvocationID);
  647. if(AENeedToUpdateDSCache(pld, pwszDCInvocationID, wszConfig, &AEDSInfo))
  648. {
  649. for(dwIndex =0; dwIndex < g_dwStoreInfo; dwIndex++)
  650. {
  651. fResult = fResult && (S_OK == AEUpdateCertificateStore(
  652. pld,
  653. wszConfig,
  654. pwszDCName,
  655. g_rgStoreInfo[dwIndex].pwszStoreName,
  656. g_rgStoreInfo[dwIndex].pwszLdapPath));
  657. }
  658. //only update the new DS cached information if we have a successful download
  659. if((fResult) && (TRUE == AEDSInfo.fValidData) && (pwszDCInvocationID))
  660. AEUpdateDSCache(pwszDCInvocationID, &AEDSInfo);
  661. }
  662. error:
  663. if(pwszDCInvocationID)
  664. RpcStringFreeW(&pwszDCInvocationID);
  665. if(wszConfig)
  666. {
  667. LocalFree(wszConfig);
  668. }
  669. return fResult;
  670. }
  671. //--------------------------------------------------------------------------
  672. //
  673. // AESetWakeUpFlag
  674. //
  675. // We set the flag to tell winlogon if autoenrollment should be waken up
  676. // during each policy check
  677. //
  678. //--------------------------------------------------------------------------
  679. BOOL WINAPI AESetWakeUpFlag(BOOL fMachine, BOOL fWakeUp)
  680. {
  681. BOOL fResult = FALSE;
  682. DWORD dwDisp = 0;
  683. DWORD dwFlags = 0;
  684. HKEY hAEKey = NULL;
  685. if(ERROR_SUCCESS != RegCreateKeyEx(
  686. fMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
  687. AUTO_ENROLLMENT_FLAG_KEY,
  688. 0,
  689. L"",
  690. REG_OPTION_NON_VOLATILE,
  691. KEY_ALL_ACCESS,
  692. NULL,
  693. &hAEKey,
  694. &dwDisp))
  695. goto Ret;
  696. if(fWakeUp)
  697. dwFlags = AUTO_ENROLLMENT_WAKE_UP_REQUIRED;
  698. if(ERROR_SUCCESS != RegSetValueEx(
  699. hAEKey,
  700. AUTO_ENROLLMENT_FLAG,
  701. 0,
  702. REG_DWORD,
  703. (PBYTE)&dwFlags,
  704. sizeof(dwFlags)))
  705. goto Ret;
  706. fResult=TRUE;
  707. Ret:
  708. if(hAEKey)
  709. RegCloseKey(hAEKey);
  710. return fResult;
  711. }
  712. //--------------------------------------------------------------------------
  713. //
  714. // AESetWakeUpTimer
  715. //
  716. // Set the timer to wake us up in 8 hrs
  717. //
  718. //--------------------------------------------------------------------------
  719. BOOL WINAPI AESetWakeUpTimer(BOOL fMachine, LARGE_INTEGER *pPreTime, LARGE_INTEGER *pPostTime)
  720. {
  721. HRESULT hr;
  722. HKEY hKey;
  723. HKEY hCurrent;
  724. DWORD dwType, dwSize, dwResult;
  725. LONG lTimeout;
  726. LARGE_INTEGER DueTime;
  727. WCHAR * wszTimerName;
  728. LARGE_INTEGER EnrollmentTime;
  729. // must be cleaned up
  730. HANDLE hTimer=NULL;
  731. // Build a timer event to ping us in about 8 hours if we don't get notified sooner.
  732. lTimeout=AE_DEFAULT_REFRESH_RATE;
  733. // Query for the refresh timer value
  734. if (ERROR_SUCCESS==RegOpenKeyEx((fMachine?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER), SYSTEM_POLICIES_KEY, 0, KEY_READ, &hKey)) {
  735. dwSize=sizeof(lTimeout);
  736. RegQueryValueEx(hKey, TEXT("AutoEnrollmentRefreshTime"), NULL, &dwType, (LPBYTE) &lTimeout, &dwSize);
  737. RegCloseKey(hKey);
  738. }
  739. // Limit the timeout to once every 240 hours (10 days)
  740. if (lTimeout>=240) {
  741. lTimeout=240;
  742. } else if (lTimeout<0) {
  743. lTimeout=0;
  744. }
  745. // Convert hours to milliseconds
  746. lTimeout=lTimeout*60*60*1000;
  747. // Special case 0 milliseconds to be 7 seconds
  748. if (lTimeout==0) {
  749. lTimeout=7000;
  750. }
  751. // convert to 10^-7s. not yet negative values are relative
  752. DueTime.QuadPart=Int32x32To64(-10000, lTimeout);
  753. // if user has hold on the UI for too long and the cycle passed the 8 hours.
  754. // we set the time for 1 hour
  755. EnrollmentTime.QuadPart=pPostTime->QuadPart - pPreTime->QuadPart;
  756. if(EnrollmentTime.QuadPart > 0)
  757. {
  758. if((-(DueTime.QuadPart)) > EnrollmentTime.QuadPart)
  759. {
  760. DueTime.QuadPart = DueTime.QuadPart + EnrollmentTime.QuadPart;
  761. }
  762. else
  763. {
  764. // Convert hours to milliseconds
  765. lTimeout=AE_DEFAULT_POSTPONE*60*60*1000;
  766. DueTime.QuadPart = Int32x32To64(-10000, lTimeout);
  767. }
  768. }
  769. // find the timer
  770. if (fMachine) {
  771. wszTimerName=L"Global\\" MACHINE_AUTOENROLLMENT_TIMER_NAME;
  772. } else {
  773. wszTimerName=USER_AUTOENROLLMENT_TIMER_NAME;
  774. }
  775. hTimer=OpenWaitableTimer(TIMER_MODIFY_STATE, false, wszTimerName);
  776. if (NULL==hTimer) {
  777. hr=HRESULT_FROM_WIN32(GetLastError());
  778. AE_DEBUG((AE_ERROR, L"OpenWaitableTimer(%s) failed with 0x%08X.\n", wszTimerName, hr));
  779. goto error;
  780. }
  781. // set the timer
  782. if (!SetWaitableTimer (hTimer, &DueTime, 0, NULL, 0, FALSE)) {
  783. hr=HRESULT_FROM_WIN32(GetLastError());
  784. AE_DEBUG((AE_ERROR, L"SetWaitableTimer failed with 0x%08X.\n", hr));
  785. goto error;
  786. }
  787. AE_DEBUG((AE_INFO, L"Set wakeup timer.\n"));
  788. hr=S_OK;
  789. error:
  790. if (NULL!=hTimer) {
  791. CloseHandle(hTimer);
  792. }
  793. return (S_OK==hr);
  794. }
  795. //--------------------------------------------------------------------------
  796. //
  797. // AEGetPendingRequestProperty
  798. //
  799. //--------------------------------------------------------------------------
  800. BOOL AEGetPendingRequestProperty(IEnroll4 *pIEnroll4,
  801. DWORD dwIndex,
  802. DWORD dwProp,
  803. LPVOID pProp)
  804. {
  805. CRYPT_DATA_BLOB *pBlob=NULL;
  806. BOOL fResult=FALSE;
  807. if((NULL==pIEnroll4) || (NULL==pProp))
  808. return FALSE;
  809. switch(dwProp)
  810. {
  811. case XEPR_REQUESTID:
  812. case XEPR_DATE:
  813. case XEPR_VERSION:
  814. fResult = (S_OK == pIEnroll4->enumPendingRequestWStr(dwIndex, dwProp, pProp));
  815. break;
  816. case XEPR_CANAME:
  817. case XEPR_CAFRIENDLYNAME:
  818. case XEPR_CADNS:
  819. case XEPR_V1TEMPLATENAME:
  820. case XEPR_V2TEMPLATEOID:
  821. case XEPR_HASH:
  822. pBlob=(CRYPT_DATA_BLOB *)pProp;
  823. pBlob->cbData=0;
  824. pBlob->pbData=NULL;
  825. if(S_OK != pIEnroll4->enumPendingRequestWStr(dwIndex, dwProp, pProp))
  826. goto Ret;
  827. if(0 == pBlob->cbData)
  828. goto Ret;
  829. pBlob->pbData=(BYTE *)LocalAlloc(LPTR, pBlob->cbData);
  830. if(NULL == pBlob->pbData)
  831. goto Ret;
  832. fResult = (S_OK == pIEnroll4->enumPendingRequestWStr(dwIndex, dwProp, pProp));
  833. break;
  834. default:
  835. break;
  836. }
  837. Ret:
  838. if(FALSE==fResult)
  839. {
  840. if(pBlob)
  841. {
  842. if(pBlob->pbData)
  843. LocalFree(pBlob->pbData);
  844. memset(pBlob, 0, sizeof(CRYPT_DATA_BLOB));
  845. }
  846. }
  847. return fResult;
  848. }
  849. //--------------------------------------------------------------------------
  850. //
  851. // AERetrieveRequestProperty
  852. //
  853. //--------------------------------------------------------------------------
  854. BOOL AERetrieveRequestProperty(IEnroll4 *pIEnroll4,
  855. DWORD dwIndex,
  856. DWORD *pdwCount,
  857. DWORD *pdwMax,
  858. CRYPT_DATA_BLOB **prgblobHash)
  859. {
  860. BOOL fResult=FALSE;
  861. CRYPT_DATA_BLOB *pblobHash=NULL;
  862. if((NULL==pIEnroll4) || (NULL==pdwCount) || (NULL==pdwMax) || (NULL==prgblobHash) ||
  863. (NULL==*prgblobHash))
  864. goto Ret;
  865. //need to alloc more memory
  866. if((*pdwCount) >= (*pdwMax))
  867. {
  868. pblobHash=*prgblobHash;
  869. *prgblobHash=(CRYPT_DATA_BLOB *)LocalAlloc(LPTR,
  870. ((*pdwMax) + PENDING_ALLOC_SIZE) * sizeof(CRYPT_DATA_BLOB));
  871. if(NULL==(*prgblobHash))
  872. {
  873. *prgblobHash=pblobHash;
  874. pblobHash=NULL;
  875. goto Ret;
  876. }
  877. memset(*prgblobHash, 0, ((*pdwMax) + PENDING_ALLOC_SIZE) * sizeof(CRYPT_DATA_BLOB));
  878. //copy the old memmory
  879. memcpy(*prgblobHash, pblobHash, (*pdwMax) * sizeof(CRYPT_DATA_BLOB));
  880. *pdwMax=(*pdwMax) + PENDING_ALLOC_SIZE;
  881. }
  882. if(!AEGetPendingRequestProperty(pIEnroll4, dwIndex, XEPR_HASH,
  883. &((*prgblobHash)[*pdwCount])))
  884. goto Ret;
  885. (*pdwCount)=(*pdwCount) + 1;
  886. fResult=TRUE;
  887. Ret:
  888. if(pblobHash)
  889. LocalFree(pblobHash);
  890. return fResult;
  891. }
  892. //--------------------------------------------------------------------------
  893. //
  894. // AERemovePendingRequest
  895. //
  896. //--------------------------------------------------------------------------
  897. BOOL AERemovePendingRequest(IEnroll4 *pIEnroll4,
  898. DWORD dwCount,
  899. CRYPT_DATA_BLOB *rgblobHash)
  900. {
  901. DWORD dwIndex=0;
  902. BOOL fResult=TRUE;
  903. if((NULL==pIEnroll4) || (NULL==rgblobHash))
  904. return FALSE;
  905. for(dwIndex=0; dwIndex < dwCount; dwIndex++)
  906. {
  907. if(S_OK != (pIEnroll4->removePendingRequestWStr(rgblobHash[dwIndex])))
  908. fResult=FALSE;
  909. }
  910. return fResult;
  911. }
  912. //--------------------------------------------------------------------------
  913. //
  914. // AEFreePendingRequests
  915. //
  916. //--------------------------------------------------------------------------
  917. BOOL AEFreePendingRequests(DWORD dwCount, CRYPT_DATA_BLOB *rgblobHash)
  918. {
  919. DWORD dwIndex=0;
  920. if(rgblobHash)
  921. {
  922. for(dwIndex=0; dwIndex < dwCount; dwIndex++)
  923. {
  924. if(rgblobHash[dwIndex].pbData)
  925. LocalFree(rgblobHash[dwIndex].pbData);
  926. }
  927. LocalFree(rgblobHash);
  928. }
  929. return TRUE;
  930. }
  931. //--------------------------------------------------------------------------
  932. //
  933. // AEValidVersionCert
  934. //
  935. // Verify the certificate returned from CA has the latest version info.
  936. // If so, copy the certificate to the hIssuedStore for potentical publishing
  937. //
  938. //--------------------------------------------------------------------------
  939. BOOL AEValidVersionCert(AE_CERTTYPE_INFO *pCertType, IEnroll4 *pIEnroll4, CRYPT_DATA_BLOB *pBlobPKCS7)
  940. {
  941. BOOL fValid=FALSE;
  942. PCCERT_CONTEXT pCertContext=NULL;
  943. AE_TEMPLATE_INFO AETemplateInfo;
  944. memset(&AETemplateInfo, 0, sizeof(AE_TEMPLATE_INFO));
  945. if((NULL==pCertType) || (NULL==pIEnroll4) || (NULL==pBlobPKCS7))
  946. goto Ret;
  947. if(NULL==(pBlobPKCS7->pbData))
  948. goto Ret;
  949. if(S_OK != pIEnroll4->getCertContextFromResponseBlob(pBlobPKCS7, &pCertContext))
  950. goto Ret;
  951. if(!AERetrieveTemplateInfo(pCertContext, &AETemplateInfo))
  952. goto Ret;
  953. if(AETemplateInfo.pwszOid)
  954. {
  955. if(AETemplateInfo.dwVersion >= (pCertType->dwVersion))
  956. fValid=TRUE;
  957. }
  958. else
  959. {
  960. //V1 template
  961. if(NULL == AETemplateInfo.pwszName)
  962. goto Ret;
  963. fValid=TRUE;
  964. }
  965. if(pCertContext && (TRUE == fValid))
  966. {
  967. CertAddCertificateContextToStore(pCertType->hIssuedStore,
  968. pCertContext,
  969. CERT_STORE_ADD_USE_EXISTING,
  970. NULL);
  971. }
  972. Ret:
  973. if(pCertContext)
  974. CertFreeCertificateContext(pCertContext);
  975. AEFreeTemplateInfo(&AETemplateInfo);
  976. return fValid;
  977. }
  978. //--------------------------------------------------------------------------
  979. //
  980. // AECopyPendingBlob
  981. //
  982. // Copy the issued PKCS7 and request hash.
  983. //
  984. //--------------------------------------------------------------------------
  985. BOOL AECopyPendingBlob(CRYPT_DATA_BLOB *pBlobPKCS7,
  986. IEnroll4 *pIEnroll4,
  987. DWORD dwXenrollIndex,
  988. AE_CERTTYPE_INFO *pCertType)
  989. {
  990. BOOL fResult=FALSE;
  991. DWORD dwIndex=0;
  992. AE_PEND_INFO *pPendInfo=NULL;
  993. if((NULL==pBlobPKCS7)||(NULL==pIEnroll4)||(NULL==pCertType))
  994. goto Ret;
  995. if(NULL==(pBlobPKCS7->pbData))
  996. goto Ret;
  997. dwIndex=pCertType->dwPendCount;
  998. //increase the memory array
  999. if(0 != dwIndex)
  1000. {
  1001. pPendInfo=pCertType->rgPendInfo;
  1002. pCertType->rgPendInfo=(AE_PEND_INFO *)LocalAlloc(LPTR,
  1003. (dwIndex + 1) * sizeof(AE_PEND_INFO));
  1004. if(NULL==(pCertType->rgPendInfo))
  1005. {
  1006. pCertType->rgPendInfo=pPendInfo;
  1007. pPendInfo=NULL;
  1008. goto Ret;
  1009. }
  1010. memset(pCertType->rgPendInfo, 0, (dwIndex + 1) * sizeof(AE_PEND_INFO));
  1011. //copy the old memmory
  1012. memcpy(pCertType->rgPendInfo, pPendInfo, (dwIndex) * sizeof(AE_PEND_INFO));
  1013. }
  1014. else
  1015. {
  1016. pCertType->rgPendInfo=(AE_PEND_INFO *)LocalAlloc(LPTR, sizeof(AE_PEND_INFO));
  1017. if(NULL==(pCertType->rgPendInfo))
  1018. goto Ret;
  1019. memset(pCertType->rgPendInfo, 0, sizeof(AE_PEND_INFO));
  1020. }
  1021. //copy the issued PKCS7 blob
  1022. (pCertType->rgPendInfo)[dwIndex].blobPKCS7.pbData=(BYTE *)LocalAlloc(
  1023. LPTR,
  1024. pBlobPKCS7->cbData);
  1025. if(NULL == ((pCertType->rgPendInfo)[dwIndex].blobPKCS7.pbData))
  1026. goto Ret;
  1027. memcpy((pCertType->rgPendInfo)[dwIndex].blobPKCS7.pbData,
  1028. pBlobPKCS7->pbData,
  1029. pBlobPKCS7->cbData);
  1030. (pCertType->rgPendInfo)[dwIndex].blobPKCS7.cbData=pBlobPKCS7->cbData;
  1031. //copy the hash of the request
  1032. if(!AEGetPendingRequestProperty(pIEnroll4, dwXenrollIndex, XEPR_HASH,
  1033. &((pCertType->rgPendInfo)[dwIndex].blobHash)))
  1034. {
  1035. LocalFree((pCertType->rgPendInfo)[dwIndex].blobPKCS7.pbData);
  1036. (pCertType->rgPendInfo)[dwIndex].blobPKCS7.pbData=NULL;
  1037. (pCertType->rgPendInfo)[dwIndex].blobPKCS7.cbData=0;
  1038. goto Ret;
  1039. }
  1040. (pCertType->dwPendCount)++;
  1041. fResult=TRUE;
  1042. Ret:
  1043. if(pPendInfo)
  1044. LocalFree(pPendInfo);
  1045. return fResult;
  1046. }
  1047. //--------------------------------------------------------------------------
  1048. //
  1049. // AEProcessUIPendingRequest
  1050. //
  1051. // In this function, we install the issued pending certificate request
  1052. // that will require UI.
  1053. //
  1054. //--------------------------------------------------------------------------
  1055. BOOL WINAPI AEProcessUIPendingRequest(AE_GENERAL_INFO *pAE_General_Info)
  1056. {
  1057. DWORD dwIndex=0;
  1058. DWORD dwPendIndex=0;
  1059. AE_CERTTYPE_INFO *pCertTypeInfo=pAE_General_Info->rgCertTypeInfo;
  1060. AE_CERTTYPE_INFO *pCertType=NULL;
  1061. BOOL fInit=FALSE;
  1062. PFNPIEnroll4GetNoCOM pfnPIEnroll4GetNoCOM=NULL;
  1063. HMODULE hXenroll=NULL;
  1064. HRESULT hr=E_FAIL;
  1065. IEnroll4 *pIEnroll4=NULL;
  1066. if(NULL==pAE_General_Info)
  1067. goto Ret;
  1068. //has to be in the UI mode
  1069. if(FALSE == pAE_General_Info->fUIProcess)
  1070. goto Ret;
  1071. if(NULL==pCertTypeInfo)
  1072. goto Ret;
  1073. hXenroll=pAE_General_Info->hXenroll;
  1074. if(NULL==hXenroll)
  1075. goto Ret;
  1076. if(NULL==(pfnPIEnroll4GetNoCOM=(PFNPIEnroll4GetNoCOM)GetProcAddress(
  1077. hXenroll,
  1078. "PIEnroll4GetNoCOM")))
  1079. goto Ret;
  1080. if(FAILED(CoInitialize(NULL)))
  1081. goto Ret;
  1082. fInit=TRUE;
  1083. if(NULL==(pIEnroll4=pfnPIEnroll4GetNoCOM()))
  1084. goto Ret;
  1085. //Set the request store flag based on fMachine
  1086. if(pAE_General_Info->fMachine)
  1087. {
  1088. if(S_OK != pIEnroll4->put_RequestStoreFlags(CERT_SYSTEM_STORE_LOCAL_MACHINE))
  1089. goto Ret;
  1090. }
  1091. else
  1092. {
  1093. if(S_OK != pIEnroll4->put_RequestStoreFlags(CERT_SYSTEM_STORE_CURRENT_USER))
  1094. goto Ret;
  1095. }
  1096. //initialize the enumerator
  1097. if(S_OK != pIEnroll4->enumPendingRequestWStr(XEPR_ENUM_FIRST, 0, NULL))
  1098. goto Ret;
  1099. for(dwIndex=0; dwIndex < pAE_General_Info->dwCertType; dwIndex++)
  1100. {
  1101. pCertType = &(pCertTypeInfo[dwIndex]);
  1102. if(pCertType->dwPendCount)
  1103. {
  1104. for(dwPendIndex=0; dwPendIndex < pCertType->dwPendCount; dwPendIndex++)
  1105. {
  1106. //check if cancel button is clicked
  1107. if(AECancelled(pAE_General_Info->hCancelEvent))
  1108. break;
  1109. //report the current enrollment action
  1110. AEUIProgressReport(TRUE, pCertType, pAE_General_Info->hwndDlg, pAE_General_Info->hCancelEvent);
  1111. //install the certificate
  1112. if(S_OK == (hr = pIEnroll4->acceptResponseBlob(
  1113. &((pCertType->rgPendInfo)[dwPendIndex].blobPKCS7))))
  1114. {
  1115. //mark the status to obtained if required
  1116. //this is a valid certificate
  1117. if(AEValidVersionCert(pCertType, pIEnroll4, &((pCertType->rgPendInfo)[dwPendIndex].blobPKCS7)))
  1118. pCertType->dwStatus = CERT_REQUEST_STATUS_OBTAINED;
  1119. //the certificate is successfully issued and installed
  1120. //remove the request from the request store
  1121. pIEnroll4->removePendingRequestWStr((pCertType->rgPendInfo)[dwPendIndex].blobHash);
  1122. AELogAutoEnrollmentEvent(
  1123. pAE_General_Info->dwLogLevel,
  1124. FALSE,
  1125. S_OK,
  1126. EVENT_PENDING_INSTALLED,
  1127. pAE_General_Info->fMachine,
  1128. pAE_General_Info->hToken,
  1129. 1,
  1130. pCertType->awszDisplay[0]);
  1131. }
  1132. else
  1133. {
  1134. //doing this for summary page
  1135. if((SCARD_E_CANCELLED != hr) && (SCARD_W_CANCELLED_BY_USER != hr))
  1136. pCertType->idsSummary=IDS_SUMMARY_INSTALL;
  1137. AELogAutoEnrollmentEvent(
  1138. pAE_General_Info->dwLogLevel,
  1139. TRUE,
  1140. hr,
  1141. EVENT_PENDING_FAILED,
  1142. pAE_General_Info->fMachine,
  1143. pAE_General_Info->hToken,
  1144. 1,
  1145. pCertType->awszDisplay[0]);
  1146. }
  1147. //advance progress
  1148. AEUIProgressAdvance(pAE_General_Info);
  1149. }
  1150. }
  1151. }
  1152. Ret:
  1153. if(pIEnroll4)
  1154. pIEnroll4->Release();
  1155. if(fInit)
  1156. CoUninitialize();
  1157. return TRUE;
  1158. }
  1159. //--------------------------------------------------------------------------
  1160. //
  1161. // AEProcessPendingRequest -- UIless call.
  1162. //
  1163. // In this function, we check each pending requests in the request store.
  1164. // We install the certificate is the request has been issued by the CA, and
  1165. // mark the certificate type status to obtained if the certificate is issued
  1166. // and of correct version
  1167. //
  1168. // We remove any requests that are stale based on the # of days defined
  1169. // in the registry. If no value is defined in the registry, use
  1170. // AE_PENDING_REQUEST_ACTIVE_PERIOD (60 days).
  1171. //
  1172. // Also, if there is no more pending requests active in the request store,
  1173. // we set the registry value to indicate that winlogon should not wake us up.
  1174. //
  1175. //--------------------------------------------------------------------------
  1176. BOOL WINAPI AEProcessPendingRequest(AE_GENERAL_INFO *pAE_General_Info)
  1177. {
  1178. DWORD dwRequestID=0;
  1179. LONG dwDisposition=0;
  1180. DWORD dwIndex=0;
  1181. DWORD dwCount=0;
  1182. DWORD dwMax=PENDING_ALLOC_SIZE;
  1183. AE_CERTTYPE_INFO *pCertType=NULL;
  1184. PFNPIEnroll4GetNoCOM pfnPIEnroll4GetNoCOM=NULL;
  1185. BOOL fInit=FALSE;
  1186. AE_TEMPLATE_INFO AETemplateInfo;
  1187. CRYPT_DATA_BLOB blobPKCS7;
  1188. HMODULE hXenroll=NULL;
  1189. VARIANT varCMC;
  1190. HRESULT hr=E_FAIL;
  1191. IEnroll4 *pIEnroll4=NULL;
  1192. ICertRequest2 *pICertRequest=NULL;
  1193. BSTR bstrCert=NULL;
  1194. LPWSTR pwszCAConfig=NULL;
  1195. BSTR bstrConfig=NULL;
  1196. CRYPT_DATA_BLOB *rgblobHash=NULL;
  1197. CRYPT_DATA_BLOB blobCAName;
  1198. CRYPT_DATA_BLOB blobCALocation;
  1199. CRYPT_DATA_BLOB blobName;
  1200. if(NULL==pAE_General_Info)
  1201. goto Ret;
  1202. //init the dwUIPendCount to 0
  1203. pAE_General_Info->dwUIPendCount=0;
  1204. //has to be in the UIless mode
  1205. if(TRUE == pAE_General_Info->fUIProcess)
  1206. goto Ret;
  1207. hXenroll=pAE_General_Info->hXenroll;
  1208. if(NULL==hXenroll)
  1209. goto Ret;
  1210. if(NULL==(pfnPIEnroll4GetNoCOM=(PFNPIEnroll4GetNoCOM)GetProcAddress(
  1211. hXenroll,
  1212. "PIEnroll4GetNoCOM")))
  1213. goto Ret;
  1214. if(FAILED(CoInitialize(NULL)))
  1215. goto Ret;
  1216. fInit=TRUE;
  1217. if(NULL==(pIEnroll4=pfnPIEnroll4GetNoCOM()))
  1218. goto Ret;
  1219. if(S_OK != CoCreateInstance(CLSID_CCertRequest,
  1220. NULL,
  1221. CLSCTX_INPROC_SERVER,
  1222. IID_ICertRequest2,
  1223. (void **)&pICertRequest))
  1224. goto Ret;
  1225. //Set the request store flag based on fMachine
  1226. if(pAE_General_Info->fMachine)
  1227. {
  1228. if(S_OK != pIEnroll4->put_RequestStoreFlags(CERT_SYSTEM_STORE_LOCAL_MACHINE))
  1229. goto Ret;
  1230. }
  1231. else
  1232. {
  1233. if(S_OK != pIEnroll4->put_RequestStoreFlags(CERT_SYSTEM_STORE_CURRENT_USER))
  1234. goto Ret;
  1235. }
  1236. memset(&blobCAName, 0, sizeof(blobCAName));
  1237. memset(&blobCALocation, 0, sizeof(blobCALocation));
  1238. memset(&blobName, 0, sizeof(blobName));
  1239. memset(&AETemplateInfo, 0, sizeof(AETemplateInfo));
  1240. rgblobHash=(CRYPT_DATA_BLOB *)LocalAlloc(LPTR, dwMax * sizeof(CRYPT_DATA_BLOB));
  1241. if(NULL==rgblobHash)
  1242. goto Ret;
  1243. memset(rgblobHash, 0, dwMax * sizeof(CRYPT_DATA_BLOB));
  1244. //initialize the enumerator
  1245. if(S_OK != pIEnroll4->enumPendingRequestWStr(XEPR_ENUM_FIRST, 0, NULL))
  1246. goto Ret;
  1247. //initlialize the variant
  1248. VariantInit(&varCMC);
  1249. while(AEGetPendingRequestProperty(
  1250. pIEnroll4,
  1251. dwIndex,
  1252. XEPR_REQUESTID,
  1253. &dwRequestID))
  1254. {
  1255. //query the status of the requests to the CA
  1256. if(!AEGetPendingRequestProperty(
  1257. pIEnroll4,
  1258. dwIndex,
  1259. XEPR_CANAME,
  1260. &blobCAName))
  1261. goto Next;
  1262. if(!AEGetPendingRequestProperty(
  1263. pIEnroll4,
  1264. dwIndex,
  1265. XEPR_CADNS,
  1266. &blobCALocation))
  1267. goto Next;
  1268. //build the config string
  1269. pwszCAConfig=(LPWSTR)LocalAlloc(LPTR,
  1270. sizeof(WCHAR) * (wcslen((LPWSTR)(blobCALocation.pbData)) + wcslen((LPWSTR)(blobCAName.pbData)) + wcslen(L"\\") + 1));
  1271. if(NULL==pwszCAConfig)
  1272. goto Next;
  1273. wcscpy(pwszCAConfig, (LPWSTR)(blobCALocation.pbData));
  1274. wcscat(pwszCAConfig, L"\\");
  1275. wcscat(pwszCAConfig, (LPWSTR)(blobCAName.pbData));
  1276. //conver to bstr
  1277. bstrConfig=SysAllocString(pwszCAConfig);
  1278. if(NULL==bstrConfig)
  1279. goto Next;
  1280. //find the template information
  1281. //get the version and the template name of the request
  1282. if(AEGetPendingRequestProperty(pIEnroll4, dwIndex, XEPR_V2TEMPLATEOID, &blobName))
  1283. {
  1284. AETemplateInfo.pwszOid=(LPWSTR)blobName.pbData;
  1285. }
  1286. else
  1287. {
  1288. if(!AEGetPendingRequestProperty(pIEnroll4, dwIndex, XEPR_V1TEMPLATENAME, &blobName))
  1289. goto Next;
  1290. AETemplateInfo.pwszName=(LPWSTR)blobName.pbData;
  1291. }
  1292. //find the template
  1293. if(NULL==(pCertType=AEFindTemplateInRequestTree(
  1294. &AETemplateInfo, pAE_General_Info)))
  1295. goto Next;
  1296. if(S_OK != pICertRequest->RetrievePending(
  1297. dwRequestID,
  1298. bstrConfig,
  1299. &dwDisposition))
  1300. goto Next;
  1301. switch(dwDisposition)
  1302. {
  1303. case CR_DISP_ISSUED:
  1304. if(S_OK != pICertRequest->GetFullResponseProperty(
  1305. FR_PROP_FULLRESPONSE, 0, PROPTYPE_BINARY, CR_OUT_BINARY,
  1306. &varCMC))
  1307. {
  1308. goto Next;
  1309. }
  1310. // Check to make sure we've gotten a BSTR back:
  1311. if (VT_BSTR != varCMC.vt)
  1312. {
  1313. goto Next;
  1314. }
  1315. bstrCert = varCMC.bstrVal;
  1316. // Marshal the cert into a CRYPT_DATA_BLOB:
  1317. blobPKCS7.cbData = (DWORD)SysStringByteLen(bstrCert);
  1318. blobPKCS7.pbData = (BYTE *)bstrCert;
  1319. // we will keep the PKCS7 blob for installation
  1320. if(CT_FLAG_USER_INTERACTION_REQUIRED & (pCertType->dwEnrollmentFlag))
  1321. {
  1322. //signal that we should pop up the UI balloon
  1323. (pAE_General_Info->dwUIPendCount)++;
  1324. //copy the PKCS7 blob from the cert server
  1325. AECopyPendingBlob(&blobPKCS7,
  1326. pIEnroll4,
  1327. dwIndex,
  1328. pCertType);
  1329. }
  1330. else
  1331. {
  1332. //install the certificate
  1333. if(S_OK != (hr = pIEnroll4->acceptResponseBlob(&blobPKCS7)))
  1334. {
  1335. AELogAutoEnrollmentEvent(
  1336. pAE_General_Info->dwLogLevel,
  1337. TRUE,
  1338. hr,
  1339. EVENT_PENDING_FAILED,
  1340. pAE_General_Info->fMachine,
  1341. pAE_General_Info->hToken,
  1342. 1,
  1343. pCertType->awszDisplay[0]);
  1344. goto Next;
  1345. }
  1346. //mark the status to obtained if required
  1347. //this is a valid certificate
  1348. if(AEValidVersionCert(pCertType, pIEnroll4, &blobPKCS7))
  1349. pCertType->dwStatus = CERT_REQUEST_STATUS_OBTAINED;
  1350. //the certificate is successfully issued and installed
  1351. //remove the request from the request store
  1352. AERetrieveRequestProperty(pIEnroll4, dwIndex, &dwCount, &dwMax, &rgblobHash);
  1353. }
  1354. AELogAutoEnrollmentEvent(
  1355. pAE_General_Info->dwLogLevel,
  1356. FALSE,
  1357. S_OK,
  1358. EVENT_PENDING_ISSUED,
  1359. pAE_General_Info->fMachine,
  1360. pAE_General_Info->hToken,
  1361. 2,
  1362. pCertType->awszDisplay[0],
  1363. pwszCAConfig);
  1364. break;
  1365. case CR_DISP_UNDER_SUBMISSION:
  1366. AELogAutoEnrollmentEvent(
  1367. pAE_General_Info->dwLogLevel,
  1368. FALSE,
  1369. S_OK,
  1370. EVENT_PENDING_PEND,
  1371. pAE_General_Info->fMachine,
  1372. pAE_General_Info->hToken,
  1373. 2,
  1374. pCertType->awszDisplay[0],
  1375. pwszCAConfig);
  1376. break;
  1377. case CR_DISP_INCOMPLETE:
  1378. case CR_DISP_ERROR:
  1379. case CR_DISP_DENIED:
  1380. case CR_DISP_ISSUED_OUT_OF_BAND: //we consider it a failure in this case
  1381. case CR_DISP_REVOKED:
  1382. default:
  1383. //requests failed. remove the request from the request store
  1384. AERetrieveRequestProperty(pIEnroll4, dwIndex, &dwCount, &dwMax, &rgblobHash);
  1385. if(S_OK == pICertRequest->GetLastStatus(&hr))
  1386. {
  1387. AELogAutoEnrollmentEvent(
  1388. pAE_General_Info->dwLogLevel,
  1389. TRUE,
  1390. hr,
  1391. EVENT_PENDING_DENIED,
  1392. pAE_General_Info->fMachine,
  1393. pAE_General_Info->hToken,
  1394. 2,
  1395. pwszCAConfig,
  1396. pCertType->awszDisplay[0]);
  1397. }
  1398. break;
  1399. }
  1400. Next:
  1401. if(pwszCAConfig)
  1402. LocalFree(pwszCAConfig);
  1403. pwszCAConfig=NULL;
  1404. if(bstrConfig)
  1405. SysFreeString(bstrConfig);
  1406. bstrConfig=NULL;
  1407. if(bstrCert)
  1408. SysFreeString(bstrCert);
  1409. bstrCert=NULL;
  1410. if(blobCAName.pbData)
  1411. LocalFree(blobCAName.pbData);
  1412. memset(&blobCAName, 0, sizeof(blobCAName));
  1413. if(blobCALocation.pbData)
  1414. LocalFree(blobCALocation.pbData);
  1415. memset(&blobCALocation, 0, sizeof(blobCALocation));
  1416. if(blobName.pbData)
  1417. LocalFree(blobName.pbData);
  1418. memset(&blobName, 0, sizeof(blobName));
  1419. memset(&AETemplateInfo, 0, sizeof(AETemplateInfo));
  1420. VariantInit(&varCMC);
  1421. dwIndex++;
  1422. }
  1423. //remove the requests based the hash
  1424. AERemovePendingRequest(pIEnroll4, dwCount, rgblobHash);
  1425. Ret:
  1426. AEFreePendingRequests(dwCount, rgblobHash);
  1427. if(pICertRequest)
  1428. pICertRequest->Release();
  1429. if(pIEnroll4)
  1430. pIEnroll4->Release();
  1431. if(fInit)
  1432. CoUninitialize();
  1433. return TRUE;
  1434. }
  1435. //--------------------------------------------------------------------------
  1436. //
  1437. // AEIsLocalSystem
  1438. //
  1439. //--------------------------------------------------------------------------
  1440. BOOL
  1441. AEIsLocalSystem(BOOL *pfIsLocalSystem)
  1442. {
  1443. HANDLE hToken = 0;
  1444. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  1445. BOOL fRet = FALSE;
  1446. BOOL fRevertToSelf = FALSE;
  1447. PSID psidLocalSystem = NULL;
  1448. *pfIsLocalSystem = FALSE;
  1449. if (!OpenThreadToken(
  1450. GetCurrentThread(),
  1451. TOKEN_QUERY,
  1452. TRUE,
  1453. &hToken))
  1454. {
  1455. if (ERROR_NO_TOKEN != GetLastError())
  1456. goto Ret;
  1457. //we need to impersonateself and get the thread token again
  1458. if(!ImpersonateSelf(SecurityImpersonation))
  1459. goto Ret;
  1460. fRevertToSelf = TRUE;
  1461. if (!OpenThreadToken(
  1462. GetCurrentThread(),
  1463. TOKEN_QUERY,
  1464. TRUE,
  1465. &hToken))
  1466. goto Ret;
  1467. }
  1468. //build the well known local system SID (s-1-5-18)
  1469. if (!AllocateAndInitializeSid(
  1470. &siaNtAuthority,
  1471. 1,
  1472. SECURITY_LOCAL_SYSTEM_RID,
  1473. 0, 0, 0, 0, 0, 0, 0,
  1474. &psidLocalSystem
  1475. ))
  1476. goto Ret;
  1477. fRet = CheckTokenMembership(
  1478. hToken,
  1479. psidLocalSystem,
  1480. pfIsLocalSystem);
  1481. Ret:
  1482. if(fRevertToSelf)
  1483. RevertToSelf();
  1484. if(psidLocalSystem)
  1485. FreeSid(psidLocalSystem);
  1486. if (hToken)
  1487. CloseHandle(hToken);
  1488. return fRet;
  1489. }
  1490. //--------------------------------------------------------------------------
  1491. //
  1492. // AEInSafeBoot
  1493. //
  1494. // copied from the service controller code
  1495. //--------------------------------------------------------------------------
  1496. BOOL WINAPI AEInSafeBoot()
  1497. {
  1498. DWORD dwSafeBoot = 0;
  1499. DWORD cbSafeBoot = sizeof(dwSafeBoot);
  1500. DWORD dwType = 0;
  1501. HKEY hKeySafeBoot = NULL;
  1502. if(ERROR_SUCCESS == RegOpenKeyW(
  1503. HKEY_LOCAL_MACHINE,
  1504. L"system\\currentcontrolset\\control\\safeboot\\option",
  1505. &hKeySafeBoot))
  1506. {
  1507. // we did in fact boot under safeboot control
  1508. if(ERROR_SUCCESS != RegQueryValueExW(
  1509. hKeySafeBoot,
  1510. L"OptionValue",
  1511. NULL,
  1512. &dwType,
  1513. (LPBYTE)&dwSafeBoot,
  1514. &cbSafeBoot))
  1515. {
  1516. dwSafeBoot = 0;
  1517. }
  1518. if(hKeySafeBoot)
  1519. RegCloseKey(hKeySafeBoot);
  1520. }
  1521. return (0 != dwSafeBoot);
  1522. }
  1523. //--------------------------------------------------------------------------
  1524. //
  1525. // AEIsDomainMember
  1526. //
  1527. //--------------------------------------------------------------------------
  1528. BOOL WINAPI AEIsDomainMember()
  1529. {
  1530. DWORD dwErr;
  1531. BOOL bIsDomainMember=FALSE;
  1532. // must be cleaned up
  1533. DSROLE_PRIMARY_DOMAIN_INFO_BASIC * pDomInfo=NULL;
  1534. dwErr=DsRoleGetPrimaryDomainInformation(NULL, DsRolePrimaryDomainInfoBasic, (BYTE **)&pDomInfo);
  1535. if (ERROR_SUCCESS==dwErr) {
  1536. if (DsRole_RoleStandaloneWorkstation!=pDomInfo->MachineRole
  1537. && DsRole_RoleStandaloneServer!=pDomInfo->MachineRole) {
  1538. bIsDomainMember=TRUE;
  1539. }
  1540. }
  1541. if (NULL!=pDomInfo) {
  1542. DsRoleFreeMemory(pDomInfo);
  1543. }
  1544. return bIsDomainMember;
  1545. }
  1546. //-----------------------------------------------------------------------
  1547. //
  1548. // AEGetPolicyFlag
  1549. //
  1550. //-----------------------------------------------------------------------
  1551. BOOL AEGetPolicyFlag(BOOL fMachine, DWORD *pdwPolicy)
  1552. {
  1553. DWORD dwPolicy = 0;
  1554. DWORD cbPolicy = sizeof(dwPolicy);
  1555. DWORD dwType = 0;
  1556. HKEY hKey = NULL;
  1557. if(ERROR_SUCCESS == RegOpenKeyW(
  1558. fMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
  1559. AUTO_ENROLLMENT_KEY,
  1560. &hKey))
  1561. {
  1562. if(ERROR_SUCCESS != RegQueryValueExW(
  1563. hKey,
  1564. AUTO_ENROLLMENT_POLICY,
  1565. NULL,
  1566. &dwType,
  1567. (LPBYTE)&dwPolicy,
  1568. &cbPolicy))
  1569. {
  1570. dwPolicy = 0;
  1571. }
  1572. if(hKey)
  1573. RegCloseKey(hKey);
  1574. }
  1575. *pdwPolicy=dwPolicy;
  1576. return TRUE;
  1577. }
  1578. //-----------------------------------------------------------------------
  1579. //
  1580. // AERetrieveLogLevel
  1581. //
  1582. //-----------------------------------------------------------------------
  1583. BOOL AERetrieveLogLevel(BOOL fMachine, DWORD *pdwLogLevel)
  1584. {
  1585. DWORD dwLogLevel = STATUS_SEVERITY_ERROR; //we default to highest logging level
  1586. DWORD cbLogLevel = sizeof(dwLogLevel);
  1587. DWORD dwType = 0;
  1588. HKEY hKey = NULL;
  1589. if(ERROR_SUCCESS == RegOpenKeyW(
  1590. fMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
  1591. AUTO_ENROLLMENT_EVENT_LEVEL_KEY,
  1592. &hKey))
  1593. {
  1594. if(ERROR_SUCCESS != RegQueryValueExW(
  1595. hKey,
  1596. AUTO_ENROLLMENT_EVENT_LEVEL,
  1597. NULL,
  1598. &dwType,
  1599. (LPBYTE)&dwLogLevel,
  1600. &cbLogLevel))
  1601. {
  1602. dwLogLevel = STATUS_SEVERITY_ERROR;
  1603. }
  1604. if(hKey)
  1605. RegCloseKey(hKey);
  1606. }
  1607. *pdwLogLevel=dwLogLevel;
  1608. return TRUE;
  1609. }
  1610. //-----------------------------------------------------------------------
  1611. //
  1612. // AERetrieveTemplateInfo
  1613. //
  1614. //-----------------------------------------------------------------------
  1615. BOOL AERetrieveTemplateInfo(PCCERT_CONTEXT pCertCurrent,
  1616. AE_TEMPLATE_INFO *pTemplateInfo)
  1617. {
  1618. BOOL fResult = FALSE;
  1619. PCERT_EXTENSION pExt = NULL;
  1620. DWORD cbData=0;
  1621. CERT_NAME_VALUE *pbName = NULL;
  1622. CERT_TEMPLATE_EXT *pbTemplate = NULL;
  1623. if((NULL==pCertCurrent) || (NULL==pTemplateInfo))
  1624. goto Ret;
  1625. memset(pTemplateInfo, 0, sizeof(AE_TEMPLATE_INFO));
  1626. //try to find V2 template extension first
  1627. if(pExt = CertFindExtension(szOID_CERTIFICATE_TEMPLATE,
  1628. pCertCurrent->pCertInfo->cExtension,
  1629. pCertCurrent->pCertInfo->rgExtension))
  1630. {
  1631. if(!CryptDecodeObject(X509_ASN_ENCODING,
  1632. szOID_CERTIFICATE_TEMPLATE,
  1633. pExt->Value.pbData,
  1634. pExt->Value.cbData,
  1635. 0,
  1636. NULL,
  1637. &cbData))
  1638. goto Ret;
  1639. pbTemplate = (CERT_TEMPLATE_EXT *)LocalAlloc(LPTR, cbData);
  1640. if(NULL==pbTemplate)
  1641. goto Ret;
  1642. if(!CryptDecodeObject(X509_ASN_ENCODING,
  1643. szOID_CERTIFICATE_TEMPLATE,
  1644. pExt->Value.pbData,
  1645. pExt->Value.cbData,
  1646. 0,
  1647. pbTemplate,
  1648. &cbData))
  1649. goto Ret;
  1650. //copy the version
  1651. pTemplateInfo->dwVersion=pbTemplate->dwMajorVersion;
  1652. //copy the extension oid
  1653. if(NULL==pbTemplate->pszObjId)
  1654. goto Ret;
  1655. if(0 == (cbData = MultiByteToWideChar(CP_ACP,
  1656. 0,
  1657. pbTemplate->pszObjId,
  1658. -1,
  1659. NULL,
  1660. 0)))
  1661. goto Ret;
  1662. if(NULL==(pTemplateInfo->pwszOid=(LPWSTR)LocalAlloc(LPTR, cbData * sizeof(WCHAR))))
  1663. goto Ret;
  1664. if(0 == MultiByteToWideChar(CP_ACP,
  1665. 0,
  1666. pbTemplate->pszObjId,
  1667. -1,
  1668. pTemplateInfo->pwszOid,
  1669. cbData))
  1670. goto Ret;
  1671. }
  1672. else
  1673. {
  1674. //try V1 template extension
  1675. if(NULL == (pExt = CertFindExtension(
  1676. szOID_ENROLL_CERTTYPE_EXTENSION,
  1677. pCertCurrent->pCertInfo->cExtension,
  1678. pCertCurrent->pCertInfo->rgExtension)))
  1679. goto Ret;
  1680. if(!CryptDecodeObject(X509_ASN_ENCODING,
  1681. X509_UNICODE_ANY_STRING,
  1682. pExt->Value.pbData,
  1683. pExt->Value.cbData,
  1684. 0,
  1685. NULL,
  1686. &cbData))
  1687. goto Ret;
  1688. pbName = (CERT_NAME_VALUE *)LocalAlloc(LPTR, cbData);
  1689. if(NULL==pbName)
  1690. goto Ret;
  1691. if(!CryptDecodeObject(X509_ASN_ENCODING,
  1692. X509_UNICODE_ANY_STRING,
  1693. pExt->Value.pbData,
  1694. pExt->Value.cbData,
  1695. 0,
  1696. pbName,
  1697. &cbData))
  1698. goto Ret;
  1699. if(!AEAllocAndCopy((LPWSTR)(pbName->Value.pbData),
  1700. &(pTemplateInfo->pwszName)))
  1701. goto Ret;
  1702. }
  1703. fResult = TRUE;
  1704. Ret:
  1705. if(pbTemplate)
  1706. LocalFree(pbTemplate);
  1707. if(pbName)
  1708. LocalFree(pbName);
  1709. return fResult;
  1710. }
  1711. //-----------------------------------------------------------------------
  1712. //
  1713. // AEFreeTemplateInfo
  1714. //
  1715. //-----------------------------------------------------------------------
  1716. BOOL AEFreeTemplateInfo(AE_TEMPLATE_INFO *pAETemplateInfo)
  1717. {
  1718. if(pAETemplateInfo->pwszName)
  1719. LocalFree(pAETemplateInfo->pwszName);
  1720. if(pAETemplateInfo->pwszOid)
  1721. LocalFree(pAETemplateInfo->pwszOid);
  1722. memset(pAETemplateInfo, 0, sizeof(AE_TEMPLATE_INFO));
  1723. return TRUE;
  1724. }
  1725. //-----------------------------------------------------------------------
  1726. //
  1727. // AEFindTemplateInRequestTree
  1728. //
  1729. //-----------------------------------------------------------------------
  1730. AE_CERTTYPE_INFO *AEFindTemplateInRequestTree(AE_TEMPLATE_INFO *pTemplateInfo,
  1731. AE_GENERAL_INFO *pAE_General_Info)
  1732. {
  1733. DWORD dwIndex = 0;
  1734. AE_CERTTYPE_INFO *rgCertTypeInfo=NULL;
  1735. AE_CERTTYPE_INFO *pCertType=NULL;
  1736. if(NULL == (rgCertTypeInfo=pAE_General_Info->rgCertTypeInfo))
  1737. return NULL;
  1738. if( (NULL == pTemplateInfo->pwszName) && (NULL == pTemplateInfo->pwszOid))
  1739. return NULL;
  1740. for(dwIndex=0; dwIndex < pAE_General_Info->dwCertType; dwIndex++)
  1741. {
  1742. if(pTemplateInfo->pwszOid)
  1743. {
  1744. //we are guaranteed to have an OID if the schema is greater than or equal to 2
  1745. if(rgCertTypeInfo[dwIndex].dwSchemaVersion >= CERTTYPE_SCHEMA_VERSION_2)
  1746. {
  1747. if(0 == wcscmp(pTemplateInfo->pwszOid, (rgCertTypeInfo[dwIndex].awszOID)[0]))
  1748. {
  1749. pCertType = &(rgCertTypeInfo[dwIndex]);
  1750. break;
  1751. }
  1752. }
  1753. }
  1754. else
  1755. {
  1756. //we are guaranteed to have a name
  1757. if(0 == wcscmp(pTemplateInfo->pwszName, (rgCertTypeInfo[dwIndex].awszName)[0]))
  1758. {
  1759. pCertType = &(rgCertTypeInfo[dwIndex]);
  1760. break;
  1761. }
  1762. }
  1763. }
  1764. return pCertType;
  1765. }
  1766. //-----------------------------------------------------------------------
  1767. //
  1768. // AEIsLogonDCCertificate
  1769. //
  1770. //
  1771. //-----------------------------------------------------------------------
  1772. BOOL AEIsLogonDCCertificate(PCCERT_CONTEXT pCertContext)
  1773. {
  1774. BOOL fDCCert=FALSE;
  1775. PCERT_EXTENSION pExt = NULL;
  1776. DWORD cbData = 0;
  1777. DWORD dwIndex = 0;
  1778. BOOL fFound = FALSE;
  1779. CERT_ENHKEY_USAGE *pbKeyUsage=NULL;
  1780. AE_TEMPLATE_INFO AETemplateInfo;
  1781. memset(&AETemplateInfo, 0, sizeof(AE_TEMPLATE_INFO));
  1782. if(NULL==pCertContext)
  1783. return FALSE;
  1784. if(!AERetrieveTemplateInfo(pCertContext, &AETemplateInfo))
  1785. goto Ret;
  1786. if(AETemplateInfo.pwszName)
  1787. {
  1788. //this is a V1 template. Search for the hard coded DC template name
  1789. if(0 == _wcsicmp(wszCERTTYPE_DC, AETemplateInfo.pwszName))
  1790. fDCCert=TRUE;
  1791. }
  1792. else
  1793. {
  1794. //this is a V2 template. Search for the smart card logon OID
  1795. if(NULL==(pExt=CertFindExtension(szOID_ENHANCED_KEY_USAGE,
  1796. pCertContext->pCertInfo->cExtension,
  1797. pCertContext->pCertInfo->rgExtension)))
  1798. goto Ret;
  1799. if(!CryptDecodeObject(X509_ASN_ENCODING,
  1800. szOID_ENHANCED_KEY_USAGE,
  1801. pExt->Value.pbData,
  1802. pExt->Value.cbData,
  1803. 0,
  1804. NULL,
  1805. &cbData))
  1806. goto Ret;
  1807. pbKeyUsage=(CERT_ENHKEY_USAGE *)LocalAlloc(LPTR, cbData);
  1808. if(NULL==pbKeyUsage)
  1809. goto Ret;
  1810. if(!CryptDecodeObject(X509_ASN_ENCODING,
  1811. szOID_ENHANCED_KEY_USAGE,
  1812. pExt->Value.pbData,
  1813. pExt->Value.cbData,
  1814. 0,
  1815. pbKeyUsage,
  1816. &cbData))
  1817. goto Ret;
  1818. for(dwIndex=0; dwIndex < pbKeyUsage->cUsageIdentifier; dwIndex++)
  1819. {
  1820. if(0==_stricmp(szOID_KP_SMARTCARD_LOGON,(pbKeyUsage->rgpszUsageIdentifier)[dwIndex]))
  1821. {
  1822. fDCCert=TRUE;
  1823. break;
  1824. }
  1825. }
  1826. }
  1827. Ret:
  1828. if(pbKeyUsage)
  1829. LocalFree(pbKeyUsage);
  1830. AEFreeTemplateInfo(&AETemplateInfo);
  1831. return fDCCert;
  1832. }
  1833. //-----------------------------------------------------------------------
  1834. //
  1835. // AEValidateCertificateInfo
  1836. //
  1837. // This function verifies if the certificate needs to be renewed or
  1838. // re-enrolled based on:
  1839. //
  1840. // 1. Presence of the private key
  1841. // 2. Chaining of the certificate
  1842. // 3. If the certificate is close to expiration
  1843. //
  1844. //-----------------------------------------------------------------------
  1845. BOOL AEValidateCertificateInfo(AE_GENERAL_INFO *pAE_General_Info,
  1846. AE_CERTTYPE_INFO *pCertType,
  1847. BOOL fCheckForPrivateKey,
  1848. PCCERT_CONTEXT pCertCurrent,
  1849. AE_CERT_INFO *pAECertInfo)
  1850. {
  1851. BOOL fResult = TRUE;
  1852. DWORD cbData = 0;
  1853. CERT_CHAIN_PARA ChainParams;
  1854. CERT_CHAIN_POLICY_PARA ChainPolicy;
  1855. CERT_CHAIN_POLICY_STATUS PolicyStatus;
  1856. LARGE_INTEGER ftTime;
  1857. HRESULT hrChainStatus = S_OK;
  1858. LARGE_INTEGER ftHalfLife;
  1859. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  1860. if((NULL==pCertCurrent) || (NULL==pAECertInfo) || (NULL==pAE_General_Info))
  1861. {
  1862. SetLastError(E_INVALIDARG);
  1863. fResult = FALSE;
  1864. goto Ret;
  1865. }
  1866. //assume the certificate is bad
  1867. pAECertInfo->fValid = FALSE;
  1868. pAECertInfo->fRenewal = FALSE;
  1869. //////////////////////////////////////////////////
  1870. //
  1871. //check for the private key information
  1872. //
  1873. //////////////////////////////////////////////////
  1874. if(fCheckForPrivateKey)
  1875. {
  1876. if(!CertGetCertificateContextProperty(
  1877. pCertCurrent,
  1878. CERT_KEY_PROV_INFO_PROP_ID,
  1879. NULL,
  1880. &cbData))
  1881. goto Ret;
  1882. }
  1883. /////////////////////////////////////////////////////////
  1884. //
  1885. //check for chaining, revoke status and expiration of the certificate
  1886. //
  1887. /////////////////////////////////////////////////////////
  1888. memset(&ChainParams, 0, sizeof(ChainParams));
  1889. ChainParams.cbSize = sizeof(ChainParams);
  1890. ChainParams.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
  1891. ChainParams.RequestedUsage.Usage.cUsageIdentifier = 0;
  1892. ChainParams.RequestedUsage.Usage.rgpszUsageIdentifier = NULL;
  1893. // Build a small time skew into the chain building in order to deal
  1894. // with servers that may skew slightly fast.
  1895. GetSystemTimeAsFileTime((LPFILETIME)&ftTime);
  1896. ftTime.QuadPart += Int32x32To64(FILETIME_TICKS_PER_SECOND, AE_DEFAULT_SKEW);
  1897. // Build a cert chain for the current status of the cert..
  1898. if(!CertGetCertificateChain(pAE_General_Info->fMachine?HCCE_LOCAL_MACHINE:HCCE_CURRENT_USER,
  1899. pCertCurrent,
  1900. (LPFILETIME)&ftTime,
  1901. NULL,
  1902. &ChainParams,
  1903. CERT_CHAIN_REVOCATION_CHECK_CHAIN,
  1904. NULL,
  1905. &pChainContext))
  1906. {
  1907. AE_DEBUG((AE_WARNING, L"Could not build certificate chain (%lx)\n\r", GetLastError()));
  1908. goto Ret;
  1909. }
  1910. //validate the certificate chain
  1911. //special case for domain controller certificate.
  1912. //it should not have any revocation error, even for status unknown case
  1913. //check against the base policy
  1914. memset(&ChainPolicy, 0, sizeof(ChainPolicy));
  1915. ChainPolicy.cbSize = sizeof(ChainPolicy);
  1916. ChainPolicy.dwFlags = 0; // ignore nothing
  1917. ChainPolicy.pvExtraPolicyPara = NULL;
  1918. memset(&PolicyStatus, 0, sizeof(PolicyStatus));
  1919. PolicyStatus.cbSize = sizeof(PolicyStatus);
  1920. PolicyStatus.dwError = 0;
  1921. PolicyStatus.lChainIndex = -1;
  1922. PolicyStatus.lElementIndex = -1;
  1923. PolicyStatus.pvExtraPolicyStatus = NULL;
  1924. if(!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE,
  1925. pChainContext,
  1926. &ChainPolicy,
  1927. &PolicyStatus))
  1928. {
  1929. AE_DEBUG((AE_WARNING, L"Base Chain Policy failed (%lx) - must get new cert\n\r", GetLastError()));
  1930. goto Ret;
  1931. }
  1932. hrChainStatus = PolicyStatus.dwError;
  1933. if((S_OK == hrChainStatus) ||
  1934. (CRYPT_E_NO_REVOCATION_CHECK == hrChainStatus) ||
  1935. (CRYPT_E_REVOCATION_OFFLINE == hrChainStatus))
  1936. {
  1937. // The cert is still currently acceptable by trust standards, so we can renew it
  1938. pAECertInfo->fRenewal = TRUE;
  1939. }
  1940. else
  1941. {
  1942. goto Ret;
  1943. }
  1944. if(pChainContext)
  1945. {
  1946. CertFreeCertificateChain(pChainContext);
  1947. pChainContext = NULL;
  1948. }
  1949. /////////////////////////////////////////////////////////////////////
  1950. //
  1951. // Check if the certificate is close to expire
  1952. //
  1953. ///////////////////////////////////////////////////////////////////////
  1954. if(NULL==pCertType)
  1955. goto Ret;
  1956. // Nudge the evaluation of the cert chain by the expiration
  1957. // offset so we know if is expired by that time in the future.
  1958. GetSystemTimeAsFileTime((LPFILETIME)&ftTime);
  1959. // Build the certificate chain for trust operations
  1960. memset(&ChainParams, 0, sizeof(ChainParams));
  1961. ChainParams.cbSize = sizeof(ChainParams);
  1962. ChainParams.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
  1963. ChainParams.RequestedUsage.Usage.cUsageIdentifier = 0;
  1964. ChainParams.RequestedUsage.Usage.rgpszUsageIdentifier = NULL;
  1965. //get the half lifetime of the certificate
  1966. ftHalfLife.QuadPart = (((LARGE_INTEGER UNALIGNED *)&(pCertCurrent->pCertInfo->NotAfter))->QuadPart -
  1967. ((LARGE_INTEGER UNALIGNED *)&(pCertCurrent->pCertInfo->NotBefore))->QuadPart)/2;
  1968. //check if the old cert is time nesting invalid
  1969. if(ftHalfLife.QuadPart < 0)
  1970. goto Ret;
  1971. //check if the offset was specified in a relative value
  1972. if(pCertType->ftExpirationOffset.QuadPart < 0)
  1973. {
  1974. if(ftHalfLife.QuadPart > (- pCertType->ftExpirationOffset.QuadPart))
  1975. {
  1976. ftTime.QuadPart -= pCertType->ftExpirationOffset.QuadPart;
  1977. }
  1978. else
  1979. {
  1980. ftTime.QuadPart += ftHalfLife.QuadPart;
  1981. }
  1982. }
  1983. else
  1984. {
  1985. //the offset was specified in an absolute value
  1986. if(0 < pCertType->ftExpirationOffset.QuadPart)
  1987. ftTime = pCertType->ftExpirationOffset;
  1988. else
  1989. //use the half time mark if the offset is 0
  1990. ftTime.QuadPart += ftHalfLife.QuadPart;
  1991. }
  1992. //check the certificate chain at a future time
  1993. if(!CertGetCertificateChain(pAE_General_Info->fMachine?HCCE_LOCAL_MACHINE:HCCE_CURRENT_USER,
  1994. pCertCurrent,
  1995. (LPFILETIME)&ftTime,
  1996. NULL, //no additional store
  1997. &ChainParams,
  1998. 0, //no revocation check
  1999. NULL, //Reserved
  2000. &pChainContext))
  2001. {
  2002. AE_DEBUG((AE_WARNING, L"Could not build certificate chain (%lx)\n\r", GetLastError()));
  2003. goto Ret;
  2004. }
  2005. // Verify expiration of the certificate
  2006. memset(&ChainPolicy, 0, sizeof(ChainPolicy));
  2007. ChainPolicy.cbSize = sizeof(ChainPolicy);
  2008. ChainPolicy.dwFlags = 0; // ignore nothing
  2009. ChainPolicy.pvExtraPolicyPara = NULL;
  2010. memset(&PolicyStatus, 0, sizeof(PolicyStatus));
  2011. PolicyStatus.cbSize = sizeof(PolicyStatus);
  2012. PolicyStatus.dwError = 0;
  2013. PolicyStatus.lChainIndex = -1;
  2014. PolicyStatus.lElementIndex = -1;
  2015. PolicyStatus.pvExtraPolicyStatus = NULL;
  2016. if(!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE,
  2017. pChainContext,
  2018. &ChainPolicy,
  2019. &PolicyStatus))
  2020. {
  2021. AE_DEBUG((AE_WARNING, L"Base Chain Policy failed (%lx) - must get new cert\n\r", GetLastError()));
  2022. goto Ret;
  2023. }
  2024. hrChainStatus = PolicyStatus.dwError;
  2025. if((S_OK != hrChainStatus) &&
  2026. (CRYPT_E_NO_REVOCATION_CHECK != hrChainStatus) &&
  2027. (CRYPT_E_REVOCATION_OFFLINE != hrChainStatus))
  2028. {
  2029. // The cert is close to expire. we must re-renewal
  2030. goto Ret;
  2031. }
  2032. //the certificate is good
  2033. pAECertInfo->fValid = TRUE;
  2034. fResult = TRUE;
  2035. Ret:
  2036. if(pChainContext)
  2037. CertFreeCertificateChain(pChainContext);
  2038. return fResult;
  2039. }
  2040. //-----------------------------------------------------------------------
  2041. //
  2042. // AESameOID
  2043. //
  2044. // Check if the two OIDs are the same
  2045. //-----------------------------------------------------------------------
  2046. BOOL AESameOID(LPWSTR pwszOID, LPSTR pszOID)
  2047. {
  2048. DWORD cbChar=0;
  2049. BOOL fSame=FALSE;
  2050. LPSTR pszNewOID=NULL;
  2051. if((NULL==pwszOID) || (NULL==pszOID))
  2052. return FALSE;
  2053. cbChar= WideCharToMultiByte(
  2054. CP_ACP, // codepage
  2055. 0, // dwFlags
  2056. pwszOID,
  2057. -1,
  2058. NULL,
  2059. 0,
  2060. NULL,
  2061. NULL);
  2062. if(0 == cbChar)
  2063. goto Ret;
  2064. if(NULL==(pszNewOID=(LPSTR)LocalAlloc(LPTR, cbChar)))
  2065. goto Ret;
  2066. cbChar= WideCharToMultiByte(
  2067. CP_ACP, // codepage
  2068. 0, // dwFlags
  2069. pwszOID,
  2070. -1,
  2071. pszNewOID,
  2072. cbChar,
  2073. NULL,
  2074. NULL);
  2075. if(0 == cbChar)
  2076. goto Ret;
  2077. if(0 == _stricmp(pszNewOID, pszOID))
  2078. fSame=TRUE;
  2079. Ret:
  2080. if(pszNewOID)
  2081. LocalFree(pszNewOID);
  2082. return fSame;
  2083. }
  2084. //-----------------------------------------------------------------------
  2085. //
  2086. // AEValidRAPolicyWithProperty
  2087. //
  2088. // Check if the certificate matches the RA signature requirement
  2089. // of the certificate type
  2090. //-----------------------------------------------------------------------
  2091. BOOL AEValidRAPolicyWithProperty(PCCERT_CONTEXT pCertContext,
  2092. LPWSTR *rgwszPolicy,
  2093. LPWSTR *rgwszAppPolicy)
  2094. {
  2095. PCERT_EXTENSION pExt = NULL;
  2096. DWORD cbData = 0;
  2097. DWORD dwIndex = 0;
  2098. DWORD dwFindIndex=0;
  2099. BOOL fFound = FALSE;
  2100. BOOL fValid = FALSE;
  2101. CERT_ENHKEY_USAGE *pbKeyUsage=NULL;
  2102. CERT_POLICIES_INFO *pbAppPolicy=NULL;
  2103. CERT_POLICIES_INFO *pbPolicy=NULL;
  2104. //find the EKUs
  2105. if(pExt=CertFindExtension(szOID_ENHANCED_KEY_USAGE,
  2106. pCertContext->pCertInfo->cExtension,
  2107. pCertContext->pCertInfo->rgExtension))
  2108. {
  2109. cbData=0;
  2110. if(!CryptDecodeObject(X509_ASN_ENCODING,
  2111. szOID_ENHANCED_KEY_USAGE,
  2112. pExt->Value.pbData,
  2113. pExt->Value.cbData,
  2114. 0,
  2115. NULL,
  2116. &cbData))
  2117. goto Ret;
  2118. pbKeyUsage=(CERT_ENHKEY_USAGE *)LocalAlloc(LPTR, cbData);
  2119. if(NULL==pbKeyUsage)
  2120. goto Ret;
  2121. if(!CryptDecodeObject(X509_ASN_ENCODING,
  2122. szOID_ENHANCED_KEY_USAGE,
  2123. pExt->Value.pbData,
  2124. pExt->Value.cbData,
  2125. 0,
  2126. pbKeyUsage,
  2127. &cbData))
  2128. goto Ret;
  2129. }
  2130. //get the cert issurance policy
  2131. if(pExt=CertFindExtension(szOID_CERT_POLICIES,
  2132. pCertContext->pCertInfo->cExtension,
  2133. pCertContext->pCertInfo->rgExtension))
  2134. {
  2135. cbData=0;
  2136. if(!CryptDecodeObject(X509_ASN_ENCODING,
  2137. szOID_CERT_POLICIES,
  2138. pExt->Value.pbData,
  2139. pExt->Value.cbData,
  2140. 0,
  2141. NULL,
  2142. &cbData))
  2143. goto Ret;
  2144. pbPolicy=(CERT_POLICIES_INFO *)LocalAlloc(LPTR, cbData);
  2145. if(NULL==pbPolicy)
  2146. goto Ret;
  2147. if(!CryptDecodeObject(X509_ASN_ENCODING,
  2148. szOID_CERT_POLICIES,
  2149. pExt->Value.pbData,
  2150. pExt->Value.cbData,
  2151. 0,
  2152. pbPolicy,
  2153. &cbData))
  2154. goto Ret;
  2155. }
  2156. //get the cert application policy
  2157. if(pExt=CertFindExtension(szOID_APPLICATION_CERT_POLICIES,
  2158. pCertContext->pCertInfo->cExtension,
  2159. pCertContext->pCertInfo->rgExtension))
  2160. {
  2161. cbData=0;
  2162. if(!CryptDecodeObject(X509_ASN_ENCODING,
  2163. szOID_CERT_POLICIES,
  2164. pExt->Value.pbData,
  2165. pExt->Value.cbData,
  2166. 0,
  2167. NULL,
  2168. &cbData))
  2169. goto Ret;
  2170. pbAppPolicy=(CERT_POLICIES_INFO *)LocalAlloc(LPTR, cbData);
  2171. if(NULL==pbAppPolicy)
  2172. goto Ret;
  2173. if(!CryptDecodeObject(X509_ASN_ENCODING,
  2174. szOID_CERT_POLICIES,
  2175. pExt->Value.pbData,
  2176. pExt->Value.cbData,
  2177. 0,
  2178. pbAppPolicy,
  2179. &cbData))
  2180. goto Ret;
  2181. }
  2182. if(rgwszPolicy)
  2183. {
  2184. if(rgwszPolicy[0])
  2185. {
  2186. if(NULL==pbPolicy)
  2187. goto Ret;
  2188. dwIndex=0;
  2189. while(rgwszPolicy[dwIndex])
  2190. {
  2191. fFound=FALSE;
  2192. for(dwFindIndex=0; dwFindIndex < pbPolicy->cPolicyInfo; dwFindIndex++)
  2193. {
  2194. if(AESameOID(rgwszPolicy[dwIndex], (pbPolicy->rgPolicyInfo)[dwFindIndex].pszPolicyIdentifier))
  2195. {
  2196. fFound=TRUE;
  2197. break;
  2198. }
  2199. }
  2200. if(FALSE == fFound)
  2201. goto Ret;
  2202. dwIndex++;
  2203. }
  2204. }
  2205. }
  2206. if(rgwszAppPolicy)
  2207. {
  2208. if(rgwszAppPolicy[0])
  2209. {
  2210. if((NULL==pbAppPolicy) && (NULL==pbKeyUsage))
  2211. goto Ret;
  2212. dwIndex=0;
  2213. while(rgwszAppPolicy[dwIndex])
  2214. {
  2215. fFound=FALSE;
  2216. if(pbAppPolicy)
  2217. {
  2218. for(dwFindIndex=0; dwFindIndex < pbAppPolicy->cPolicyInfo; dwFindIndex++)
  2219. {
  2220. if(AESameOID(rgwszAppPolicy[dwIndex], (pbAppPolicy->rgPolicyInfo)[dwFindIndex].pszPolicyIdentifier))
  2221. {
  2222. fFound=TRUE;
  2223. break;
  2224. }
  2225. }
  2226. }
  2227. if((FALSE == fFound) && (pbKeyUsage))
  2228. {
  2229. for(dwFindIndex=0; dwFindIndex < pbKeyUsage->cUsageIdentifier; dwFindIndex++)
  2230. {
  2231. if(AESameOID(rgwszAppPolicy[dwIndex],(pbKeyUsage->rgpszUsageIdentifier)[dwFindIndex]))
  2232. {
  2233. fFound=TRUE;
  2234. break;
  2235. }
  2236. }
  2237. }
  2238. if(FALSE == fFound)
  2239. goto Ret;
  2240. dwIndex++;
  2241. }
  2242. }
  2243. }
  2244. fValid=TRUE;
  2245. Ret:
  2246. if(pbKeyUsage)
  2247. LocalFree(pbKeyUsage);
  2248. if(pbPolicy)
  2249. LocalFree(pbPolicy);
  2250. if(pbAppPolicy)
  2251. LocalFree(pbAppPolicy);
  2252. return fValid;
  2253. }
  2254. //-----------------------------------------------------------------------
  2255. //
  2256. // AEValidRAPolicy
  2257. //
  2258. // Check if the certificate matches the RA signature requirement
  2259. // of the certificate type
  2260. //-----------------------------------------------------------------------
  2261. BOOL AEValidRAPolicy(PCCERT_CONTEXT pCertContext, AE_CERTTYPE_INFO *pCertType)
  2262. {
  2263. BOOL fValid=FALSE;
  2264. LPWSTR *rgwszPolicy=NULL;
  2265. LPWSTR *rgwszAppPolicy=NULL;
  2266. if((NULL==pCertType) || (NULL==pCertContext))
  2267. return FALSE;
  2268. //get the certificate type properties
  2269. CAGetCertTypePropertyEx(pCertType->hCertType,
  2270. CERTTYPE_PROP_RA_POLICY,
  2271. &rgwszPolicy);
  2272. CAGetCertTypePropertyEx(pCertType->hCertType,
  2273. CERTTYPE_PROP_RA_APPLICATION_POLICY,
  2274. &rgwszAppPolicy);
  2275. fValid = AEValidRAPolicyWithProperty(pCertContext, rgwszPolicy, rgwszAppPolicy);
  2276. if(rgwszPolicy)
  2277. CAFreeCertTypeProperty(pCertType->hCertType, rgwszPolicy);
  2278. if(rgwszAppPolicy)
  2279. CAFreeCertTypeProperty(pCertType->hCertType, rgwszAppPolicy);
  2280. return fValid;
  2281. }
  2282. //-----------------------------------------------------------------------
  2283. //
  2284. // AESomeCSPSupported
  2285. //
  2286. //-----------------------------------------------------------------------
  2287. BOOL AESomeCSPSupported(HCERTTYPE hCertType)
  2288. {
  2289. BOOL fResult=FALSE;
  2290. DWORD dwIndex=0;
  2291. DWORD dwCSPIndex=0;
  2292. DWORD dwProviderType=0;
  2293. DWORD cbSize=0;
  2294. LPWSTR *awszCSP=NULL;
  2295. LPWSTR pwszProviderName=NULL;
  2296. HCRYPTPROV hProv=NULL;
  2297. if(NULL==hCertType)
  2298. goto Ret;
  2299. //no CSPs means all CSPs are fine
  2300. if((S_OK != CAGetCertTypePropertyEx(
  2301. hCertType,
  2302. CERTTYPE_PROP_CSP_LIST,
  2303. &awszCSP)) || (NULL == awszCSP))
  2304. {
  2305. fResult=TRUE;
  2306. goto Ret;
  2307. }
  2308. //no CSP means all CSPs are fine
  2309. if(NULL == awszCSP[0])
  2310. {
  2311. fResult=TRUE;
  2312. goto Ret;
  2313. }
  2314. for(dwIndex=0; NULL != awszCSP[dwIndex]; dwIndex++)
  2315. {
  2316. for (dwCSPIndex = 0;
  2317. CryptEnumProvidersW(dwCSPIndex, 0, 0, &dwProviderType, NULL, &cbSize);
  2318. dwCSPIndex++)
  2319. {
  2320. pwszProviderName = (LPWSTR)LocalAlloc(LPTR, cbSize);
  2321. if(NULL == pwszProviderName)
  2322. goto Ret;
  2323. //get the provider name and type
  2324. if(!CryptEnumProvidersW(dwCSPIndex,
  2325. 0,
  2326. 0,
  2327. &dwProviderType,
  2328. pwszProviderName,
  2329. &cbSize))
  2330. goto Ret;
  2331. if(0 == _wcsicmp(pwszProviderName, awszCSP[dwIndex]))
  2332. {
  2333. //find the CSP. See if it is present in the box
  2334. if(CryptAcquireContextW(
  2335. &hProv,
  2336. NULL,
  2337. awszCSP[dwIndex],
  2338. dwProviderType,
  2339. CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
  2340. {
  2341. CryptReleaseContext(hProv, 0);
  2342. hProv=NULL;
  2343. fResult=TRUE;
  2344. break;
  2345. }
  2346. }
  2347. //keep the CSP enumeration
  2348. if(pwszProviderName)
  2349. LocalFree(pwszProviderName);
  2350. pwszProviderName=NULL;
  2351. cbSize=0;
  2352. dwProviderType=0;
  2353. }
  2354. //detect if a valid CSP if found
  2355. if(TRUE == fResult)
  2356. {
  2357. break;
  2358. }
  2359. cbSize=0;
  2360. dwProviderType=0;
  2361. }
  2362. Ret:
  2363. if(pwszProviderName)
  2364. LocalFree(pwszProviderName);
  2365. if(hProv)
  2366. CryptReleaseContext(hProv, 0);
  2367. if(awszCSP)
  2368. CAFreeCertTypeProperty(hCertType, awszCSP);
  2369. return fResult;
  2370. }
  2371. //-----------------------------------------------------------------------
  2372. //
  2373. // AESmartcardOnlyTemplate
  2374. //
  2375. //-----------------------------------------------------------------------
  2376. BOOL AESmartcardOnlyTemplate(HCERTTYPE hCertType)
  2377. {
  2378. BOOL fResult=FALSE;
  2379. DWORD dwIndex=0;
  2380. DWORD dwImpType=0;
  2381. DWORD cbData=0;
  2382. DWORD dwSCCount=0;
  2383. LPWSTR *awszCSP=NULL;
  2384. HCRYPTPROV hProv = NULL;
  2385. if(NULL==hCertType)
  2386. goto Ret;
  2387. if(S_OK != CAGetCertTypePropertyEx(
  2388. hCertType,
  2389. CERTTYPE_PROP_CSP_LIST,
  2390. &awszCSP))
  2391. goto Ret;
  2392. if(NULL==awszCSP)
  2393. goto Ret;
  2394. for(dwIndex=0; NULL != awszCSP[dwIndex]; dwIndex++)
  2395. {
  2396. dwImpType=0;
  2397. //all smart card CSPs are RSA_FULL.
  2398. if(CryptAcquireContextW(
  2399. &hProv,
  2400. NULL,
  2401. awszCSP[dwIndex],
  2402. PROV_RSA_FULL,
  2403. CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
  2404. {
  2405. cbData = sizeof(dwImpType);
  2406. if(CryptGetProvParam(hProv,
  2407. PP_IMPTYPE,
  2408. (BYTE *)(&dwImpType),
  2409. &cbData,
  2410. 0))
  2411. {
  2412. if((CRYPT_IMPL_REMOVABLE & dwImpType) && (CRYPT_IMPL_MIXED & dwImpType))
  2413. dwSCCount++;
  2414. }
  2415. CryptReleaseContext(hProv, 0);
  2416. hProv=NULL;
  2417. }
  2418. }
  2419. //smart card CSP only if all CSPs are for smart card only
  2420. if((0 != dwIndex) && (dwIndex==dwSCCount))
  2421. fResult=TRUE;
  2422. Ret:
  2423. if(hProv)
  2424. CryptReleaseContext(hProv, 0);
  2425. if(awszCSP)
  2426. CAFreeCertTypeProperty(hCertType, awszCSP);
  2427. return fResult;
  2428. }
  2429. //-----------------------------------------------------------------------
  2430. //
  2431. // AEUserProtectionForTemplate
  2432. //
  2433. //-----------------------------------------------------------------------
  2434. BOOL AEUserProtectionForTemplate(AE_GENERAL_INFO *pAE_General_Info, PCERT_CONTEXT pCertContext)
  2435. {
  2436. BOOL fUserProtection=FALSE;
  2437. AE_CERTTYPE_INFO *pCertType=NULL;
  2438. AE_TEMPLATE_INFO AETemplateInfo;
  2439. memset(&AETemplateInfo, 0, sizeof(AE_TEMPLATE_INFO));
  2440. if((NULL == pAE_General_Info) || (NULL == pCertContext))
  2441. goto Ret;
  2442. //get the template information for the certificate
  2443. if(!AERetrieveTemplateInfo(pCertContext, &AETemplateInfo))
  2444. goto Ret;
  2445. pCertType=AEFindTemplateInRequestTree(&AETemplateInfo, pAE_General_Info);
  2446. if(NULL==pCertType)
  2447. goto Ret;
  2448. if(CT_FLAG_STRONG_KEY_PROTECTION_REQUIRED & (pCertType->dwPrivateKeyFlag))
  2449. fUserProtection=TRUE;
  2450. Ret:
  2451. AEFreeTemplateInfo(&AETemplateInfo);
  2452. return fUserProtection;
  2453. }
  2454. //-----------------------------------------------------------------------
  2455. //
  2456. // AEUISetForTemplate
  2457. //
  2458. //-----------------------------------------------------------------------
  2459. BOOL AEUISetForTemplate(AE_GENERAL_INFO *pAE_General_Info, PCERT_CONTEXT pCertContext)
  2460. {
  2461. BOOL fUI=FALSE;
  2462. AE_CERTTYPE_INFO *pCertType=NULL;
  2463. AE_TEMPLATE_INFO AETemplateInfo;
  2464. memset(&AETemplateInfo, 0, sizeof(AE_TEMPLATE_INFO));
  2465. if((NULL == pAE_General_Info) || (NULL == pCertContext))
  2466. goto Ret;
  2467. //get the template information for the certificate
  2468. if(!AERetrieveTemplateInfo(pCertContext, &AETemplateInfo))
  2469. goto Ret;
  2470. pCertType=AEFindTemplateInRequestTree(&AETemplateInfo, pAE_General_Info);
  2471. if(NULL==pCertType)
  2472. goto Ret;
  2473. if(CT_FLAG_USER_INTERACTION_REQUIRED & (pCertType->dwEnrollmentFlag))
  2474. fUI=TRUE;
  2475. Ret:
  2476. AEFreeTemplateInfo(&AETemplateInfo);
  2477. return fUI;
  2478. }
  2479. //-----------------------------------------------------------------------
  2480. //
  2481. // AECanEnrollCertType
  2482. //
  2483. //-----------------------------------------------------------------------
  2484. BOOL AECanEnrollCertType(HANDLE hToken, AE_CERTTYPE_INFO *pCertType, AE_GENERAL_INFO *pAE_General_Info, BOOL *pfUserProtection)
  2485. {
  2486. DWORD dwValue = 0;
  2487. PCCERT_CONTEXT pCertCurrent=NULL;
  2488. AE_CERT_INFO AECertInfo;
  2489. memset(&AECertInfo, 0, sizeof(AE_CERT_INFO));
  2490. *pfUserProtection=FALSE;
  2491. //check enrollment ACL
  2492. if(S_OK != CACertTypeAccessCheckEx(
  2493. pCertType->hCertType,
  2494. hToken,
  2495. CERTTYPE_ACCESS_CHECK_ENROLL | CERTTYPE_ACCESS_CHECK_NO_MAPPING))
  2496. return FALSE;
  2497. //check the subject requirements
  2498. if(S_OK != CAGetCertTypeFlagsEx(
  2499. pCertType->hCertType,
  2500. CERTTYPE_SUBJECT_NAME_FLAG,
  2501. &dwValue))
  2502. return FALSE;
  2503. if((CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT & dwValue) ||
  2504. (CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT_ALT_NAME & dwValue))
  2505. return FALSE;
  2506. //check if we are doing smart card CSPs and there is no reader installed
  2507. if(FALSE == (pAE_General_Info->fSmartcardSystem))
  2508. {
  2509. if(AESmartcardOnlyTemplate(pCertType->hCertType))
  2510. return FALSE;
  2511. }
  2512. //check if all CSPs on the template is not supported
  2513. {
  2514. if(!AESomeCSPSupported(pCertType->hCertType))
  2515. return FALSE;
  2516. }
  2517. //we might not get the RA property for V1 template
  2518. dwValue = 0;
  2519. //check the RA support
  2520. if(S_OK != CAGetCertTypePropertyEx(
  2521. pCertType->hCertType,
  2522. CERTTYPE_PROP_RA_SIGNATURE,
  2523. &dwValue))
  2524. return TRUE;
  2525. if(0==dwValue)
  2526. return TRUE;
  2527. //self-template RA
  2528. if((CT_FLAG_PREVIOUS_APPROVAL_VALIDATE_REENROLLMENT & (pCertType->dwEnrollmentFlag)) &&
  2529. ((pCertType->fRenewal) && (pCertType->pOldCert))
  2530. )
  2531. {
  2532. //the request has to be RAed
  2533. pCertType->fNeedRA=TRUE;
  2534. return TRUE;
  2535. }
  2536. //autoenrollment only deal with one RA signature.
  2537. //it is sufficient for autoenrollment RA scenarios
  2538. if(1!=dwValue)
  2539. return FALSE;
  2540. //the certificate template requires one and only one RA signature
  2541. //cross-template RA
  2542. //enumerate all certificate in store
  2543. while(pCertCurrent = CertEnumCertificatesInStore(pAE_General_Info->hMyStore, pCertCurrent))
  2544. {
  2545. //check if we need to enroll/renewal for the certificate
  2546. AEValidateCertificateInfo(pAE_General_Info,
  2547. NULL,
  2548. TRUE, //valid private key
  2549. pCertCurrent,
  2550. &AECertInfo);
  2551. //the certificate is good enough for RA signature purpose
  2552. if(AECertInfo.fRenewal)
  2553. {
  2554. if(AEValidRAPolicy(pCertCurrent, pCertType))
  2555. {
  2556. if(AEUserProtectionForTemplate(pAE_General_Info, (PCERT_CONTEXT)pCertCurrent))
  2557. {
  2558. if(pAE_General_Info->fMachine)
  2559. {
  2560. *pfUserProtection=TRUE;
  2561. continue;
  2562. }
  2563. else
  2564. {
  2565. if(0==(CT_FLAG_USER_INTERACTION_REQUIRED & (pCertType->dwEnrollmentFlag)))
  2566. {
  2567. *pfUserProtection=TRUE;
  2568. continue;
  2569. }
  2570. }
  2571. }
  2572. pCertType->fRenewal=TRUE;
  2573. if(pCertType->pOldCert)
  2574. {
  2575. CertFreeCertificateContext(pCertType->pOldCert);
  2576. pCertType->pOldCert=NULL;
  2577. }
  2578. //we will free the certificate context later
  2579. pCertType->pOldCert=(PCERT_CONTEXT)pCertCurrent;
  2580. //we mark UI required if the RAing certificate template requires UI
  2581. if(AEUISetForTemplate(pAE_General_Info, pCertType->pOldCert))
  2582. pCertType->fUIActive=TRUE;
  2583. //we mark the requests has to be RAed.
  2584. pCertType->fNeedRA=TRUE;
  2585. //we mark that we are doing cross RAing.
  2586. pCertType->fCrossRA=TRUE;
  2587. *pfUserProtection=FALSE;
  2588. return TRUE;
  2589. }
  2590. }
  2591. memset(&AECertInfo, 0, sizeof(AE_CERT_INFO));
  2592. }
  2593. return FALSE;
  2594. }
  2595. //-----------------------------------------------------------------------
  2596. //
  2597. // AEMarkAutoenrollment
  2598. //
  2599. //-----------------------------------------------------------------------
  2600. BOOL AEMarkAutoenrollment(AE_GENERAL_INFO *pAE_General_Info)
  2601. {
  2602. DWORD dwIndex = 0;
  2603. for(dwIndex=0; dwIndex < pAE_General_Info->dwCertType; dwIndex++)
  2604. {
  2605. if(CT_FLAG_AUTO_ENROLLMENT & ((pAE_General_Info->rgCertTypeInfo)[dwIndex].dwEnrollmentFlag))
  2606. {
  2607. //check the autoenrollment ACL
  2608. if(S_OK != CACertTypeAccessCheckEx(
  2609. (pAE_General_Info->rgCertTypeInfo)[dwIndex].hCertType,
  2610. pAE_General_Info->hToken,
  2611. CERTTYPE_ACCESS_CHECK_AUTO_ENROLL | CERTTYPE_ACCESS_CHECK_NO_MAPPING))
  2612. continue;
  2613. //mark the template nees to be auto-enrolled
  2614. (pAE_General_Info->rgCertTypeInfo)[dwIndex].dwStatus=CERT_REQUEST_STATUS_ACTIVE;
  2615. (pAE_General_Info->rgCertTypeInfo)[dwIndex].fCheckMyStore=TRUE;
  2616. }
  2617. }
  2618. return TRUE;
  2619. }
  2620. //-----------------------------------------------------------------------
  2621. //
  2622. // IsACRSStoreEmpty
  2623. //
  2624. //
  2625. //-----------------------------------------------------------------------
  2626. BOOL IsACRSStoreEmpty(BOOL fMachine)
  2627. {
  2628. DWORD dwOpenStoreFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG;
  2629. LPSTR pszCTLUsageOID = NULL;
  2630. BOOL fEmpty = TRUE;
  2631. CERT_PHYSICAL_STORE_INFO PhysicalStoreInfo;
  2632. CTL_FIND_USAGE_PARA CTLFindUsage;
  2633. PCCTL_CONTEXT pCTLContext = NULL;
  2634. HCERTSTORE hStoreACRS=NULL;
  2635. memset(&PhysicalStoreInfo, 0, sizeof(PhysicalStoreInfo));
  2636. memset(&CTLFindUsage, 0, sizeof(CTLFindUsage));
  2637. // if the auto enrollment is for a user then we need to shut off inheritance
  2638. // from the local machine store so that we don't try and enroll for certs
  2639. // which are meant to be for the machine
  2640. if (FALSE == fMachine)
  2641. {
  2642. dwOpenStoreFlags = CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG;
  2643. PhysicalStoreInfo.cbSize = sizeof(PhysicalStoreInfo);
  2644. PhysicalStoreInfo.dwFlags = CERT_PHYSICAL_STORE_OPEN_DISABLE_FLAG;
  2645. if (!CertRegisterPhysicalStore(ACRS_STORE,
  2646. CERT_SYSTEM_STORE_CURRENT_USER,
  2647. CERT_PHYSICAL_STORE_LOCAL_MACHINE_NAME,
  2648. &PhysicalStoreInfo,
  2649. NULL))
  2650. {
  2651. AE_DEBUG((AE_ERROR, L"Could not register ACRS store: (%lx)\n\r", GetLastError()));
  2652. goto Ret;
  2653. }
  2654. }
  2655. // open the ACRS store and fine the CTL based on the auto enrollment usage
  2656. if (NULL == (hStoreACRS = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
  2657. ENCODING_TYPE,
  2658. NULL,
  2659. dwOpenStoreFlags,
  2660. ACRS_STORE)))
  2661. {
  2662. AE_DEBUG((AE_ERROR, L"Could not open ACRS store: (%lx)\n\r", GetLastError()));
  2663. goto Ret;
  2664. }
  2665. //find the template name specified in the CTLContext
  2666. CTLFindUsage.cbSize = sizeof(CTLFindUsage);
  2667. CTLFindUsage.SubjectUsage.cUsageIdentifier = 1;
  2668. pszCTLUsageOID = szOID_AUTO_ENROLL_CTL_USAGE;
  2669. CTLFindUsage.SubjectUsage.rgpszUsageIdentifier = &pszCTLUsageOID;
  2670. while(pCTLContext = CertFindCTLInStore(hStoreACRS,
  2671. X509_ASN_ENCODING,
  2672. CTL_FIND_SAME_USAGE_FLAG,
  2673. CTL_FIND_USAGE,
  2674. &CTLFindUsage,
  2675. pCTLContext))
  2676. {
  2677. fEmpty=FALSE;
  2678. break;
  2679. }
  2680. Ret:
  2681. if(pCTLContext)
  2682. CertFreeCTLContext(pCTLContext);
  2683. if(hStoreACRS)
  2684. CertCloseStore(hStoreACRS, 0);
  2685. return fEmpty;
  2686. }
  2687. //-----------------------------------------------------------------------
  2688. //
  2689. // AEMarkAEObject
  2690. //
  2691. // Mark the active status based on ACRS store
  2692. //
  2693. // INFORMATION:
  2694. // we do not honor the CA specified in the autoenrollment object anymore. All CAs
  2695. // in the enterprise should be treated equal; and once the CA is renewed, it certificate
  2696. // will be changed anyway.
  2697. //-----------------------------------------------------------------------
  2698. BOOL AEMarkAEObject(AE_GENERAL_INFO *pAE_General_Info)
  2699. {
  2700. DWORD dwOpenStoreFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG;
  2701. PCCTL_CONTEXT pCTLContext = NULL;
  2702. LPSTR pszCTLUsageOID = NULL;
  2703. LPWSTR wszCertTypeName = NULL;
  2704. AE_CERTTYPE_INFO *pCertType=NULL;
  2705. CERT_PHYSICAL_STORE_INFO PhysicalStoreInfo;
  2706. CTL_FIND_USAGE_PARA CTLFindUsage;
  2707. AE_TEMPLATE_INFO AETemplateInfo;
  2708. HCERTSTORE hStoreACRS=NULL;
  2709. memset(&PhysicalStoreInfo, 0, sizeof(PhysicalStoreInfo));
  2710. memset(&CTLFindUsage, 0, sizeof(CTLFindUsage));
  2711. memset(&AETemplateInfo, 0, sizeof(AETemplateInfo));
  2712. // if the auto enrollment is for a user then we need to shut off inheritance
  2713. // from the local machine store so that we don't try and enroll for certs
  2714. // which are meant to be for the machine
  2715. if (FALSE == (pAE_General_Info->fMachine))
  2716. {
  2717. dwOpenStoreFlags = CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG;
  2718. PhysicalStoreInfo.cbSize = sizeof(PhysicalStoreInfo);
  2719. PhysicalStoreInfo.dwFlags = CERT_PHYSICAL_STORE_OPEN_DISABLE_FLAG;
  2720. if (!CertRegisterPhysicalStore(ACRS_STORE,
  2721. CERT_SYSTEM_STORE_CURRENT_USER,
  2722. CERT_PHYSICAL_STORE_LOCAL_MACHINE_NAME,
  2723. &PhysicalStoreInfo,
  2724. NULL))
  2725. {
  2726. AE_DEBUG((AE_ERROR, L"Could not register ACRS store: (%lx)\n\r", GetLastError()));
  2727. goto Ret;
  2728. }
  2729. }
  2730. // open the ACRS store and fine the CTL based on the auto enrollment usage
  2731. if (NULL == (hStoreACRS = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
  2732. ENCODING_TYPE,
  2733. NULL,
  2734. dwOpenStoreFlags,
  2735. ACRS_STORE)))
  2736. {
  2737. AE_DEBUG((AE_ERROR, L"Could not open ACRS store: (%lx)\n\r", GetLastError()));
  2738. goto Ret;
  2739. }
  2740. //find the template name specified in the CTLContext
  2741. CTLFindUsage.cbSize = sizeof(CTLFindUsage);
  2742. CTLFindUsage.SubjectUsage.cUsageIdentifier = 1;
  2743. pszCTLUsageOID = szOID_AUTO_ENROLL_CTL_USAGE;
  2744. CTLFindUsage.SubjectUsage.rgpszUsageIdentifier = &pszCTLUsageOID;
  2745. while(pCTLContext = CertFindCTLInStore(hStoreACRS,
  2746. X509_ASN_ENCODING,
  2747. CTL_FIND_SAME_USAGE_FLAG,
  2748. CTL_FIND_USAGE,
  2749. &CTLFindUsage,
  2750. pCTLContext))
  2751. {
  2752. if(NULL== (pCTLContext->pCtlInfo->ListIdentifier.pbData))
  2753. continue;
  2754. wszCertTypeName = wcschr((LPWSTR)pCTLContext->pCtlInfo->ListIdentifier.pbData, L'|');
  2755. if(wszCertTypeName)
  2756. {
  2757. wszCertTypeName++;
  2758. }
  2759. else
  2760. {
  2761. wszCertTypeName = (LPWSTR)pCTLContext->pCtlInfo->ListIdentifier.pbData;
  2762. }
  2763. AETemplateInfo.pwszName = wszCertTypeName;
  2764. if(pCertType=AEFindTemplateInRequestTree(&AETemplateInfo, pAE_General_Info))
  2765. {
  2766. if(0 == pCertType->dwStatus)
  2767. {
  2768. //mark the template needs to be auto-enrolled
  2769. pCertType->dwStatus=CERT_REQUEST_STATUS_ACTIVE;
  2770. pCertType->fCheckMyStore=TRUE;
  2771. }
  2772. }
  2773. else
  2774. {
  2775. //log that the template is invalid
  2776. AELogAutoEnrollmentEvent(pAE_General_Info->dwLogLevel, FALSE, S_OK, EVENT_INVALID_ACRS_OBJECT,
  2777. pAE_General_Info->fMachine, pAE_General_Info->hToken, 1, wszCertTypeName);
  2778. }
  2779. }
  2780. Ret:
  2781. if(hStoreACRS)
  2782. CertCloseStore(hStoreACRS, 0);
  2783. return TRUE;
  2784. }
  2785. //-----------------------------------------------------------------------
  2786. //
  2787. // AEManageAndMarkMyStore
  2788. //
  2789. //-----------------------------------------------------------------------
  2790. BOOL AEManageAndMarkMyStore(AE_GENERAL_INFO *pAE_General_Info)
  2791. {
  2792. AE_CERT_INFO AECertInfo;
  2793. AE_CERTTYPE_INFO *pCertType=NULL;
  2794. BOOL fNeedToValidate=TRUE;
  2795. PCCERT_CONTEXT pCertCurrent = NULL;
  2796. DWORD cbData=0;
  2797. AE_TEMPLATE_INFO AETemplateInfo;
  2798. memset(&AECertInfo, 0, sizeof(AE_CERT_INFO));
  2799. memset(&AETemplateInfo, 0, sizeof(AE_TEMPLATE_INFO));
  2800. //enumerate all certificate in store
  2801. while(pCertCurrent = CertEnumCertificatesInStore(pAE_General_Info->hMyStore, pCertCurrent))
  2802. {
  2803. //only interested in certificate with template information
  2804. if(AERetrieveTemplateInfo(pCertCurrent, &AETemplateInfo))
  2805. {
  2806. if(pCertType=AEFindTemplateInRequestTree(
  2807. &AETemplateInfo, pAE_General_Info))
  2808. {
  2809. //if we are not supposed to check for my store, only search
  2810. //for template with ACTIVE status
  2811. if(0 == (AUTO_ENROLLMENT_ENABLE_MY_STORE_MANAGEMENT & (pAE_General_Info->dwPolicy)))
  2812. {
  2813. if(!(pCertType->fCheckMyStore))
  2814. goto Next;
  2815. }
  2816. //make sure the version of the certificate template is up to date
  2817. //we do not have version for V1 template
  2818. if(AETemplateInfo.pwszOid)
  2819. {
  2820. if(AETemplateInfo.dwVersion < pCertType->dwVersion)
  2821. {
  2822. AECertInfo.fValid=FALSE;
  2823. AECertInfo.fRenewal = FALSE;
  2824. //self-RA renewal
  2825. if(CT_FLAG_PREVIOUS_APPROVAL_VALIDATE_REENROLLMENT & pCertType->dwEnrollmentFlag)
  2826. {
  2827. if(CertGetCertificateContextProperty(
  2828. pCertCurrent,
  2829. CERT_KEY_PROV_INFO_PROP_ID,
  2830. NULL,
  2831. &cbData))
  2832. AECertInfo.fRenewal = TRUE;
  2833. }
  2834. fNeedToValidate=FALSE;
  2835. }
  2836. }
  2837. if(fNeedToValidate)
  2838. {
  2839. //check if we need to enroll/renewal for the certificate
  2840. AEValidateCertificateInfo(pAE_General_Info,
  2841. pCertType,
  2842. TRUE, //valid private key
  2843. pCertCurrent,
  2844. &AECertInfo);
  2845. }
  2846. if(AECertInfo.fValid)
  2847. {
  2848. //if the certificate is valid, mark as obtained. And copy the
  2849. //certificate to the obtained store. Keep the archive store.
  2850. pCertType->dwStatus = CERT_REQUEST_STATUS_OBTAINED;
  2851. CertAddCertificateContextToStore(
  2852. pCertType->hObtainedStore,
  2853. pCertCurrent,
  2854. CERT_STORE_ADD_ALWAYS,
  2855. NULL);
  2856. }
  2857. else
  2858. {
  2859. //the certificate is not valid
  2860. //mark the status to active if it is not obtained
  2861. if(CERT_REQUEST_STATUS_OBTAINED != pCertType->dwStatus)
  2862. {
  2863. pCertType->dwStatus = CERT_REQUEST_STATUS_ACTIVE;
  2864. if(AECertInfo.fRenewal)
  2865. {
  2866. //we only need to copy renewal information once
  2867. if(!pCertType->fRenewal)
  2868. {
  2869. pCertType->fRenewal=TRUE;
  2870. pCertType->pOldCert=(PCERT_CONTEXT)CertDuplicateCertificateContext(pCertCurrent);
  2871. }
  2872. }
  2873. }
  2874. //copy the certificate to the Archive certificate store
  2875. CertAddCertificateContextToStore(
  2876. pCertType->hArchiveStore,
  2877. pCertCurrent,
  2878. CERT_STORE_ADD_ALWAYS,
  2879. NULL);
  2880. }
  2881. }
  2882. else
  2883. {
  2884. //log that the template is invalid
  2885. AELogAutoEnrollmentEvent(
  2886. pAE_General_Info->dwLogLevel,
  2887. FALSE,
  2888. S_OK,
  2889. EVENT_INVALID_TEMPLATE_MY_STORE,
  2890. pAE_General_Info->fMachine,
  2891. pAE_General_Info->hToken,
  2892. 1,
  2893. AETemplateInfo.pwszName ? AETemplateInfo.pwszName : AETemplateInfo.pwszOid);
  2894. }
  2895. }
  2896. Next:
  2897. memset(&AECertInfo, 0, sizeof(AE_CERT_INFO));
  2898. AEFreeTemplateInfo(&AETemplateInfo);
  2899. fNeedToValidate=TRUE;
  2900. cbData=0;
  2901. }
  2902. return TRUE;
  2903. }
  2904. //-----------------------------------------------------------------------
  2905. //
  2906. // AEOpenUserDSStore
  2907. //
  2908. // INFORMATION: We could just open the "UserDS" store as if it is "My"
  2909. //
  2910. //-----------------------------------------------------------------------
  2911. HCERTSTORE AEOpenUserDSStore(AE_GENERAL_INFO *pAE_General_Info, DWORD dwOpenFlag)
  2912. {
  2913. LPWSTR pwszPath=L"ldap:///%s?userCertificate?base?objectCategory=user";
  2914. DWORD dwSize=0;
  2915. WCHAR wszDN[MAX_DN_SIZE];
  2916. LPWSTR pwszDN=NULL;
  2917. LPWSTR pwszStore=NULL;
  2918. HCERTSTORE hStore=NULL;
  2919. dwSize=MAX_DN_SIZE;
  2920. if(!GetUserNameExW(NameFullyQualifiedDN, wszDN, &dwSize))
  2921. {
  2922. if(dwSize > MAX_DN_SIZE)
  2923. {
  2924. pwszDN=(LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * dwSize);
  2925. if(NULL==pwszDN)
  2926. goto Ret;
  2927. if(!GetUserNameExW(NameFullyQualifiedDN, pwszDN, &dwSize))
  2928. goto Ret;
  2929. }
  2930. else
  2931. goto Ret;
  2932. }
  2933. pwszStore = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*(wcslen(pwszDN ? pwszDN : wszDN)+wcslen(pwszPath)+1));
  2934. if(pwszStore == NULL)
  2935. goto Ret;
  2936. wsprintf(pwszStore,
  2937. pwszPath,
  2938. pwszDN ? pwszDN : wszDN);
  2939. hStore = CertOpenStore(CERT_STORE_PROV_LDAP,
  2940. ENCODING_TYPE,
  2941. NULL,
  2942. dwOpenFlag,
  2943. pwszStore);
  2944. Ret:
  2945. if(pwszStore)
  2946. LocalFree(pwszStore);
  2947. if(pwszDN)
  2948. LocalFree(pwszDN);
  2949. return hStore;
  2950. }
  2951. //-----------------------------------------------------------------------
  2952. //
  2953. // AECheckUserDSStore
  2954. //
  2955. //-----------------------------------------------------------------------
  2956. BOOL AECheckUserDSStore(AE_GENERAL_INFO *pAE_General_Info)
  2957. {
  2958. PCCERT_CONTEXT pCertCurrent = NULL;
  2959. AE_CERTTYPE_INFO *pCertType=NULL;
  2960. BOOL fNeedToValidate=TRUE;
  2961. AE_CERT_INFO AECertInfo;
  2962. HCERTSTORE hUserDS = NULL;
  2963. AE_TEMPLATE_INFO AETemplateInfo;
  2964. memset(&AECertInfo, 0, sizeof(AE_CERT_INFO));
  2965. memset(&AETemplateInfo, 0, sizeof(AE_TEMPLATE_INFO));
  2966. pCertType=pAE_General_Info->rgCertTypeInfo;
  2967. if(NULL==pCertType)
  2968. goto Ret;
  2969. if(NULL== (hUserDS = AEOpenUserDSStore(pAE_General_Info, CERT_STORE_READONLY_FLAG)))
  2970. goto Ret;
  2971. pCertType = NULL;
  2972. while(pCertCurrent = CertEnumCertificatesInStore(hUserDS, pCertCurrent))
  2973. {
  2974. //only interested in certificate with template information
  2975. if(AERetrieveTemplateInfo(pCertCurrent, &AETemplateInfo))
  2976. {
  2977. if(pCertType=AEFindTemplateInRequestTree(
  2978. &AETemplateInfo, pAE_General_Info))
  2979. {
  2980. //if we are not supposed to check for UserDS store, only search
  2981. //for template with ACTIVE status
  2982. if(0 == (AUTO_ENROLLMENT_ENABLE_MY_STORE_MANAGEMENT & (pAE_General_Info->dwPolicy)))
  2983. {
  2984. if(!(pCertType->fCheckMyStore))
  2985. goto Next;
  2986. }
  2987. //make sure the version of the certificate template is up to date
  2988. //we do not have version for V1 template
  2989. if(AETemplateInfo.pwszOid)
  2990. {
  2991. if(AETemplateInfo.dwVersion < pCertType->dwVersion)
  2992. {
  2993. AECertInfo.fValid=FALSE;
  2994. AECertInfo.fRenewal=FALSE;
  2995. fNeedToValidate=FALSE;
  2996. }
  2997. }
  2998. if(fNeedToValidate)
  2999. {
  3000. //check if we need to enroll/renewal for the certificate
  3001. AEValidateCertificateInfo(pAE_General_Info,
  3002. pCertType,
  3003. FALSE, //does not valid private key
  3004. pCertCurrent,
  3005. &AECertInfo);
  3006. }
  3007. //we only interested in any valid certificate
  3008. if(AECertInfo.fValid)
  3009. {
  3010. if((CT_FLAG_AUTO_ENROLLMENT_CHECK_USER_DS_CERTIFICATE & (pCertType->dwEnrollmentFlag)) &&
  3011. (CERT_REQUEST_STATUS_OBTAINED != pCertType->dwStatus))
  3012. {
  3013. //mark the status as obtained.
  3014. pCertType->dwStatus = CERT_REQUEST_STATUS_OBTAINED;
  3015. }
  3016. CertAddCertificateContextToStore(
  3017. pCertType->hObtainedStore,
  3018. pCertCurrent,
  3019. CERT_STORE_ADD_USE_EXISTING,
  3020. NULL);
  3021. }
  3022. else
  3023. {
  3024. //copy the certificate to the Archive certificate store
  3025. CertAddCertificateContextToStore(
  3026. pCertType->hArchiveStore,
  3027. pCertCurrent,
  3028. CERT_STORE_ADD_USE_EXISTING,
  3029. NULL);
  3030. }
  3031. }
  3032. }
  3033. Next:
  3034. memset(&AECertInfo, 0, sizeof(AE_CERT_INFO));
  3035. AEFreeTemplateInfo(&AETemplateInfo);
  3036. fNeedToValidate=TRUE;
  3037. }
  3038. Ret:
  3039. if(hUserDS)
  3040. CertCloseStore(hUserDS, 0);
  3041. return TRUE;
  3042. }
  3043. //-----------------------------------------------------------------------
  3044. //
  3045. // AECheckPendingRequests
  3046. //
  3047. // If we have pending update-to-date certificate requests, no need
  3048. // to enroll/renew for duplicates.
  3049. //-----------------------------------------------------------------------
  3050. BOOL AECheckPendingRequests(AE_GENERAL_INFO *pAE_General_Info)
  3051. {
  3052. DWORD dwIndex=0;
  3053. DWORD dwVersion=0;
  3054. AE_CERTTYPE_INFO *pCertType=NULL;
  3055. BOOL fValid=FALSE;
  3056. DWORD dwCount=0;
  3057. DWORD dwMax=PENDING_ALLOC_SIZE;
  3058. PFNPIEnroll4GetNoCOM pfnPIEnroll4GetNoCOM=NULL;
  3059. FILETIME ftTime;
  3060. LARGE_INTEGER ftRequestTime;
  3061. AE_TEMPLATE_INFO AETemplateInfo;
  3062. IEnroll4 *pIEnroll4=NULL;
  3063. CRYPT_DATA_BLOB *rgblobHash=NULL;
  3064. CRYPT_DATA_BLOB blobName;
  3065. //init before any goto Ret
  3066. memset(&blobName, 0, sizeof(blobName));
  3067. memset(&AETemplateInfo, 0, sizeof(AETemplateInfo));
  3068. if(NULL==pAE_General_Info->hXenroll)
  3069. goto Ret;
  3070. if(NULL==(pfnPIEnroll4GetNoCOM=(PFNPIEnroll4GetNoCOM)GetProcAddress(
  3071. pAE_General_Info->hXenroll,
  3072. "PIEnroll4GetNoCOM")))
  3073. goto Ret;
  3074. if(NULL==(pIEnroll4=pfnPIEnroll4GetNoCOM()))
  3075. goto Ret;
  3076. GetSystemTimeAsFileTime(&ftTime);
  3077. if(pAE_General_Info->fMachine)
  3078. {
  3079. if(S_OK != pIEnroll4->put_RequestStoreFlags(CERT_SYSTEM_STORE_LOCAL_MACHINE))
  3080. goto Ret;
  3081. }
  3082. else
  3083. {
  3084. if(S_OK != pIEnroll4->put_RequestStoreFlags(CERT_SYSTEM_STORE_CURRENT_USER))
  3085. goto Ret;
  3086. }
  3087. //enumerate all the pending requests
  3088. rgblobHash=(CRYPT_DATA_BLOB *)LocalAlloc(LPTR, dwMax * sizeof(CRYPT_DATA_BLOB));
  3089. if(NULL==rgblobHash)
  3090. goto Ret;
  3091. memset(rgblobHash, 0, dwMax * sizeof(CRYPT_DATA_BLOB));
  3092. //initialize the enumerator
  3093. if(S_OK != pIEnroll4->enumPendingRequestWStr(XEPR_ENUM_FIRST, 0, NULL))
  3094. goto Ret;
  3095. while(AEGetPendingRequestProperty(
  3096. pIEnroll4,
  3097. dwIndex,
  3098. XEPR_DATE,
  3099. &ftRequestTime))
  3100. {
  3101. ftRequestTime.QuadPart += Int32x32To64(FILETIME_TICKS_PER_SECOND,
  3102. AE_PENDING_REQUEST_ACTIVE_PERIOD * 24 * 3600);
  3103. //remove the request if out of date
  3104. if(0 <= CompareFileTime(&ftTime, (LPFILETIME)&ftRequestTime))
  3105. {
  3106. AERetrieveRequestProperty(pIEnroll4, dwIndex, &dwCount, &dwMax, &rgblobHash);
  3107. }
  3108. else
  3109. {
  3110. //get the version and the template name of the request
  3111. if(AEGetPendingRequestProperty(pIEnroll4, dwIndex, XEPR_V2TEMPLATEOID, &blobName))
  3112. {
  3113. //this is a V2 template
  3114. if(!AEGetPendingRequestProperty(pIEnroll4, dwIndex, XEPR_VERSION, &dwVersion))
  3115. goto Next;
  3116. AETemplateInfo.pwszOid=(LPWSTR)blobName.pbData;
  3117. }
  3118. else
  3119. {
  3120. if(!AEGetPendingRequestProperty(pIEnroll4, dwIndex, XEPR_V1TEMPLATENAME, &blobName))
  3121. goto Next;
  3122. AETemplateInfo.pwszName=(LPWSTR)blobName.pbData;
  3123. }
  3124. //find the template
  3125. if(NULL==(pCertType=AEFindTemplateInRequestTree(
  3126. &AETemplateInfo, pAE_General_Info)))
  3127. goto Next;
  3128. if(AETemplateInfo.pwszName)
  3129. fValid=TRUE;
  3130. else
  3131. {
  3132. if(dwVersion >= pCertType->dwVersion)
  3133. fValid=TRUE;
  3134. }
  3135. if(fValid)
  3136. {
  3137. //this is a valid pending request
  3138. if(CERT_REQUEST_STATUS_OBTAINED != pCertType->dwStatus)
  3139. pCertType->dwStatus=CERT_REQUEST_STATUS_PENDING;
  3140. }
  3141. else
  3142. {
  3143. if(CERT_REQUEST_STATUS_OBTAINED == pCertType->dwStatus)
  3144. AERetrieveRequestProperty(pIEnroll4, dwIndex, &dwCount, &dwMax, &rgblobHash);
  3145. }
  3146. }
  3147. Next:
  3148. if(blobName.pbData)
  3149. LocalFree(blobName.pbData);
  3150. memset(&blobName, 0, sizeof(blobName));
  3151. memset(&AETemplateInfo, 0, sizeof(AETemplateInfo));
  3152. fValid=FALSE;
  3153. dwVersion=0;
  3154. dwIndex++;
  3155. }
  3156. //remove the requests based the hash
  3157. if(dwCount)
  3158. {
  3159. AERemovePendingRequest(pIEnroll4, dwCount, rgblobHash);
  3160. AELogAutoEnrollmentEvent(pAE_General_Info->dwLogLevel, FALSE, S_OK, EVENT_PENDING_INVALID, pAE_General_Info->fMachine, pAE_General_Info->hToken, 0);
  3161. }
  3162. Ret:
  3163. AEFreePendingRequests(dwCount, rgblobHash);
  3164. if(blobName.pbData)
  3165. LocalFree(blobName.pbData);
  3166. if(pIEnroll4)
  3167. pIEnroll4->Release();
  3168. return TRUE;
  3169. }
  3170. //-----------------------------------------------------------------------
  3171. //
  3172. // AECheckSupersedeRequest
  3173. //
  3174. //-----------------------------------------------------------------------
  3175. BOOL AECheckSupersedeRequest(DWORD dwCurIndex,
  3176. AE_CERTTYPE_INFO *pCurCertType,
  3177. AE_CERTTYPE_INFO *pSupersedingCertType,
  3178. AE_GENERAL_INFO *pAE_General_Info)
  3179. {
  3180. BOOL fFound=FALSE;
  3181. LPWSTR *awszSuperseding=NULL;
  3182. if(S_OK == CAGetCertTypePropertyEx(
  3183. pSupersedingCertType->hCertType,
  3184. CERTTYPE_PROP_SUPERSEDE,
  3185. &(awszSuperseding)))
  3186. {
  3187. if(awszSuperseding && awszSuperseding[0])
  3188. {
  3189. if(AEIfSupersede(pCurCertType->awszName[0], awszSuperseding, pAE_General_Info))
  3190. {
  3191. switch(pCurCertType->dwStatus)
  3192. {
  3193. case CERT_REQUEST_STATUS_ACTIVE:
  3194. case CERT_REQUEST_STATUS_SUPERSEDE_ACTIVE:
  3195. //remove the active status if it is superseded by an obtained certificate
  3196. if(CERT_REQUEST_STATUS_OBTAINED != pSupersedingCertType->dwStatus)
  3197. {
  3198. pCurCertType->dwStatus = CERT_REQUEST_STATUS_SUPERSEDE_ACTIVE;
  3199. pSupersedingCertType->prgActive[pSupersedingCertType->dwActive]=dwCurIndex;
  3200. (pSupersedingCertType->dwActive)++;
  3201. }
  3202. else
  3203. {
  3204. pCurCertType->dwStatus = 0;
  3205. }
  3206. case CERT_REQUEST_STATUS_PENDING:
  3207. AECopyCertStore(pCurCertType->hArchiveStore,
  3208. pSupersedingCertType->hArchiveStore);
  3209. break;
  3210. case CERT_REQUEST_STATUS_OBTAINED:
  3211. AECopyCertStore(pCurCertType->hObtainedStore,
  3212. pSupersedingCertType->hArchiveStore);
  3213. break;
  3214. default:
  3215. break;
  3216. }
  3217. //we consider that we find a valid superseding template only if the status
  3218. //is obtained. If the status is anyting else, we need to keep searching since
  3219. //enrollment/renewal requests might not be granted
  3220. if(CERT_REQUEST_STATUS_OBTAINED == pSupersedingCertType->dwStatus)
  3221. fFound=TRUE;
  3222. }
  3223. //clear the visited flag in AE_General_Info
  3224. AEClearVistedFlag(pAE_General_Info);
  3225. }
  3226. //free the property
  3227. if(awszSuperseding)
  3228. CAFreeCertTypeProperty(
  3229. pSupersedingCertType->hCertType,
  3230. awszSuperseding);
  3231. awszSuperseding=NULL;
  3232. }
  3233. return fFound;
  3234. }
  3235. //-----------------------------------------------------------------------
  3236. //
  3237. // AEIsCALonger
  3238. //
  3239. // For renewal, the CA's certificate has to live longer than the
  3240. // renewing certificate
  3241. //
  3242. //-----------------------------------------------------------------------
  3243. BOOL AEIsCALonger(HCAINFO hCAInfo, PCERT_CONTEXT pOldCert)
  3244. {
  3245. BOOL fCALonger=TRUE;
  3246. PCCERT_CONTEXT pCACert=NULL;
  3247. //we assume the CA is good unless we found something wrong
  3248. if((NULL == hCAInfo) || (NULL == pOldCert))
  3249. goto Ret;
  3250. if(S_OK != CAGetCACertificate(hCAInfo, &pCACert))
  3251. goto Ret;
  3252. if(NULL == pCACert)
  3253. goto Ret;
  3254. //CA cert's NotAfter should be longer than the issued certificate' NotAfger
  3255. if(1 == CompareFileTime(&(pCACert->pCertInfo->NotAfter), &(pOldCert->pCertInfo->NotAfter)))
  3256. goto Ret;
  3257. fCALonger=FALSE;
  3258. Ret:
  3259. if(pCACert)
  3260. CertFreeCertificateContext(pCACert);
  3261. return fCALonger;
  3262. }
  3263. //-----------------------------------------------------------------------
  3264. //
  3265. // AECanFindCAForCertType
  3266. //
  3267. // Check if there exists a CA that can issue the specified certificate
  3268. // template.
  3269. //
  3270. //-----------------------------------------------------------------------
  3271. BOOL AECanFindCAForCertType(AE_GENERAL_INFO *pAE_General_Info, AE_CERTTYPE_INFO *pCertType)
  3272. {
  3273. DWORD dwIndex=0;
  3274. BOOL fFound=FALSE;
  3275. AE_CA_INFO *prgCAInfo=pAE_General_Info->rgCAInfo;
  3276. BOOL fRenewal=FALSE;
  3277. //detect if we are performing an enrollment or renewal
  3278. if((pCertType->fRenewal) && (pCertType->pOldCert))
  3279. {
  3280. if((pCertType->fNeedRA) && (pCertType->fCrossRA))
  3281. fRenewal=FALSE;
  3282. else
  3283. fRenewal=TRUE;
  3284. }
  3285. else
  3286. fRenewal=FALSE;
  3287. if(prgCAInfo)
  3288. {
  3289. for(dwIndex=0; dwIndex < pAE_General_Info->dwCA; dwIndex++)
  3290. {
  3291. //make sure the CA supports the specific template
  3292. if(AEIsAnElement((pCertType->awszName)[0],
  3293. (prgCAInfo[dwIndex]).awszCertificateTemplate))
  3294. {
  3295. if(FALSE == fRenewal)
  3296. {
  3297. fFound=TRUE;
  3298. break;
  3299. }
  3300. else
  3301. {
  3302. if(AEIsCALonger(prgCAInfo[dwIndex].hCAInfo, pCertType->pOldCert))
  3303. {
  3304. fFound=TRUE;
  3305. break;
  3306. }
  3307. }
  3308. }
  3309. }
  3310. }
  3311. return fFound;
  3312. }
  3313. //-----------------------------------------------------------------------
  3314. //
  3315. // AEManageActiveTemplates
  3316. //
  3317. // We make sure that for all active templates, we can in deed enroll
  3318. // for it.
  3319. //
  3320. //-----------------------------------------------------------------------
  3321. BOOL AEManageActiveTemplates(AE_GENERAL_INFO *pAE_General_Info)
  3322. {
  3323. DWORD dwIndex=0;
  3324. AE_CERTTYPE_INFO *pCertTypeInfo=pAE_General_Info->rgCertTypeInfo;
  3325. AE_CERTTYPE_INFO *pCurCertType=NULL;
  3326. BOOL fCanEnrollCertType=FALSE;
  3327. BOOL fUserProtection=FALSE;
  3328. DWORD dwEventID=0;
  3329. if(pCertTypeInfo)
  3330. {
  3331. for(dwIndex=0; dwIndex < pAE_General_Info->dwCertType; dwIndex++)
  3332. {
  3333. pCurCertType = &(pCertTypeInfo[dwIndex]);
  3334. fCanEnrollCertType=FALSE;
  3335. fUserProtection=FALSE;
  3336. if(CERT_REQUEST_STATUS_PENDING == pCurCertType->dwStatus)
  3337. {
  3338. //check if UI is required
  3339. if(CT_FLAG_USER_INTERACTION_REQUIRED & (pCurCertType->dwEnrollmentFlag))
  3340. {
  3341. pCurCertType->fUIActive=TRUE;
  3342. if(pAE_General_Info->fMachine)
  3343. {
  3344. pCurCertType->dwStatus = 0;
  3345. //log that user does not have access right to the template
  3346. AELogAutoEnrollmentEvent(pAE_General_Info->dwLogLevel, FALSE, S_OK, EVENT_NO_ACCESS_ACRS_OBJECT,
  3347. pAE_General_Info->fMachine, pAE_General_Info->hToken, 1, (pCurCertType->awszDisplay)[0]);
  3348. }
  3349. }
  3350. continue;
  3351. }
  3352. if(CERT_REQUEST_STATUS_ACTIVE != pCurCertType->dwStatus)
  3353. continue;
  3354. //check if CRYPT_USER_PROTECTED is used for machine certificate template
  3355. if(CT_FLAG_STRONG_KEY_PROTECTION_REQUIRED & pCurCertType->dwPrivateKeyFlag)
  3356. {
  3357. if(pAE_General_Info->fMachine)
  3358. {
  3359. pCurCertType->dwStatus = 0;
  3360. //log that machine template should not require user password
  3361. AELogAutoEnrollmentEvent(pAE_General_Info->dwLogLevel, FALSE, S_OK, EVENT_NO_ACCESS_ACRS_OBJECT,
  3362. pAE_General_Info->fMachine, pAE_General_Info->hToken, 1, (pCurCertType->awszDisplay)[0]);
  3363. continue;
  3364. }
  3365. else
  3366. {
  3367. if(0 == (CT_FLAG_USER_INTERACTION_REQUIRED & (pCurCertType->dwEnrollmentFlag)))
  3368. {
  3369. pCurCertType->dwStatus = 0;
  3370. //log that user interaction is not set
  3371. AELogAutoEnrollmentEvent(pAE_General_Info->dwLogLevel, FALSE, S_OK, EVENT_NO_ACCESS_ACRS_OBJECT,
  3372. pAE_General_Info->fMachine, pAE_General_Info->hToken, 1, (pCurCertType->awszDisplay)[0]);
  3373. continue;
  3374. }
  3375. }
  3376. }
  3377. fCanEnrollCertType=AECanEnrollCertType(pAE_General_Info->hToken, pCurCertType, pAE_General_Info, &fUserProtection);
  3378. if((!fCanEnrollCertType) ||
  3379. (!AECanFindCAForCertType(pAE_General_Info, pCurCertType))
  3380. )
  3381. {
  3382. pCurCertType->dwStatus = 0;
  3383. //log that user does not have access right to the template
  3384. if(FALSE == fUserProtection)
  3385. {
  3386. dwEventID=EVENT_NO_ACCESS_ACRS_OBJECT;
  3387. }
  3388. else
  3389. {
  3390. if(pAE_General_Info->fMachine)
  3391. dwEventID=EVENT_NO_ACCESS_ACRS_OBJECT;
  3392. else
  3393. dwEventID=EVENT_NO_ACCESS_ACRS_OBJECT;
  3394. }
  3395. AELogAutoEnrollmentEvent(pAE_General_Info->dwLogLevel, FALSE, S_OK, dwEventID,
  3396. pAE_General_Info->fMachine, pAE_General_Info->hToken, 1, (pCurCertType->awszDisplay)[0]);
  3397. }
  3398. else
  3399. {
  3400. //check if UI is required
  3401. if(CT_FLAG_USER_INTERACTION_REQUIRED & (pCurCertType->dwEnrollmentFlag))
  3402. {
  3403. pCurCertType->fUIActive=TRUE;
  3404. if(pAE_General_Info->fMachine)
  3405. {
  3406. pCurCertType->dwStatus = 0;
  3407. //log that user does not have access right to the template
  3408. AELogAutoEnrollmentEvent(pAE_General_Info->dwLogLevel, FALSE, S_OK, EVENT_NO_ACCESS_ACRS_OBJECT,
  3409. pAE_General_Info->fMachine, pAE_General_Info->hToken, 1, (pCurCertType->awszDisplay)[0]);
  3410. }
  3411. }
  3412. }
  3413. }
  3414. }
  3415. return TRUE;
  3416. }
  3417. //-----------------------------------------------------------------------
  3418. //
  3419. // AEManageSupersedeRequests
  3420. // remove duplicated requests based on "Supersede" relationship
  3421. //
  3422. //
  3423. //-----------------------------------------------------------------------
  3424. BOOL AEManageSupersedeRequests(AE_GENERAL_INFO *pAE_General_Info)
  3425. {
  3426. DWORD dwIndex=0;
  3427. DWORD dwSuperseding=0;
  3428. DWORD dwOrder=0;
  3429. AE_CERTTYPE_INFO *pCertTypeInfo=pAE_General_Info->rgCertTypeInfo;
  3430. AE_CERTTYPE_INFO *pCurCertType=NULL;
  3431. AE_CERTTYPE_INFO *pSupersedingCertType=NULL;
  3432. BOOL fFound=FALSE;
  3433. if(pCertTypeInfo)
  3434. {
  3435. for(dwIndex=0; dwIndex < pAE_General_Info->dwCertType; dwIndex++)
  3436. {
  3437. pCurCertType = &(pCertTypeInfo[dwIndex]);
  3438. //we only consider templates with valid status
  3439. if(0 == pCurCertType->dwStatus)
  3440. continue;
  3441. fFound=FALSE;
  3442. for(dwOrder=0; dwOrder < g_dwSupersedeOrder; dwOrder++)
  3443. {
  3444. for(dwSuperseding=0; dwSuperseding < pAE_General_Info->dwCertType; dwSuperseding++)
  3445. {
  3446. //one can not be superseded by itself
  3447. if(dwIndex == dwSuperseding)
  3448. continue;
  3449. pSupersedingCertType = &(pCertTypeInfo[dwSuperseding]);
  3450. //we consider templates with obtained status first
  3451. if(g_rgdwSupersedeOrder[dwOrder] != pSupersedingCertType->dwStatus)
  3452. continue;
  3453. fFound = AECheckSupersedeRequest(dwIndex, pCurCertType, pSupersedingCertType, pAE_General_Info);
  3454. //we find a valid superseding template
  3455. if(fFound)
  3456. break;
  3457. }
  3458. //we find a valid superseding template
  3459. if(fFound)
  3460. break;
  3461. }
  3462. }
  3463. }
  3464. return TRUE;
  3465. }
  3466. //-----------------------------------------------------------------------
  3467. //
  3468. // AEDoOneEnrollment
  3469. //
  3470. //-----------------------------------------------------------------------
  3471. /*BOOL AEDoOneEnrollment(HWND hwndParent,
  3472. BOOL fUIProcess,
  3473. BOOL fMachine,
  3474. LPWSTR pwszMachineName,
  3475. AE_CERTTYPE_INFO *pCertType,
  3476. AE_CA_INFO *pCAInfo,
  3477. DWORD *pdwStatus)
  3478. {
  3479. BOOL fResult = FALSE;
  3480. CRYPTUI_WIZ_CERT_REQUEST_INFO CertRequestInfo;
  3481. CRYPTUI_WIZ_CERT_TYPE CertWizType;
  3482. CRYPTUI_WIZ_CERT_REQUEST_PVK_NEW CertPvkNew;
  3483. CRYPT_KEY_PROV_INFO KeyProvInfo;
  3484. memset(&CertRequestInfo, 0, sizeof(CRYPTUI_WIZ_CERT_REQUEST_INFO));
  3485. memset(&CertWizType, 0, sizeof(CRYPTUI_WIZ_CERT_TYPE));
  3486. memset(&CertPvkNew, 0, sizeof(CRYPTUI_WIZ_CERT_REQUEST_PVK_NEW));
  3487. memset(&KeyProvInfo, 0, sizeof(CRYPT_KEY_PROV_INFO));
  3488. CertRequestInfo.dwSize = sizeof(CRYPTUI_WIZ_CERT_REQUEST_INFO);
  3489. //enroll or renewal
  3490. if((pCertType->fRenewal) && (pCertType->pOldCert))
  3491. {
  3492. CertRequestInfo.dwPurpose = CRYPTUI_WIZ_CERT_RENEW;
  3493. CertRequestInfo.pRenewCertContext = pCertType->pOldCert;
  3494. }
  3495. else
  3496. CertRequestInfo.dwPurpose = CRYPTUI_WIZ_CERT_ENROLL;
  3497. //machine name
  3498. if(fMachine)
  3499. {
  3500. CertRequestInfo.pwszMachineName = pwszMachineName;
  3501. }
  3502. //private key information
  3503. CertRequestInfo.dwPvkChoice = CRYPTUI_WIZ_CERT_REQUEST_PVK_CHOICE_NEW;
  3504. CertRequestInfo.pPvkNew = &CertPvkNew;
  3505. CertPvkNew.dwSize = sizeof(CertPvkNew);
  3506. CertPvkNew.pKeyProvInfo = &KeyProvInfo;
  3507. CertPvkNew.dwGenKeyFlags = 0; //no need to specify the exportable flags
  3508. //SILENT is always set for machine
  3509. if(fMachine)
  3510. KeyProvInfo.dwFlags = CRYPT_MACHINE_KEYSET | CRYPT_SILENT;
  3511. else
  3512. {
  3513. if(fUIProcess)
  3514. KeyProvInfo.dwFlags = 0;
  3515. else
  3516. KeyProvInfo.dwFlags = CRYPT_SILENT;
  3517. }
  3518. //CA information
  3519. CertRequestInfo.pwszCALocation = pCAInfo->awszCADNS[0];
  3520. CertRequestInfo.pwszCAName = pCAInfo->awszCAName[0];
  3521. //enroll for the template
  3522. CertRequestInfo.dwCertChoice = CRYPTUI_WIZ_CERT_REQUEST_CERT_TYPE;
  3523. CertRequestInfo.pCertType = &CertWizType;
  3524. CertWizType.dwSize = sizeof(CertWizType);
  3525. CertWizType.cCertType = 1;
  3526. CertWizType.rgwszCertType = &(pCertType->awszName[0]);
  3527. //ISSUE: we need to call Duncanb's new no-DS look up API
  3528. //for faster performance
  3529. fResult = CryptUIWizCertRequest(CRYPTUI_WIZ_NO_UI_EXCEPT_CSP | CRYPTUI_WIZ_NO_INSTALL_ROOT,
  3530. hwndParent,
  3531. NULL,
  3532. &CertRequestInfo,
  3533. NULL, //pCertContext
  3534. pdwStatus);
  3535. return fResult;
  3536. } */
  3537. //-----------------------------------------------------------------------
  3538. //
  3539. // AECreateEnrollmentRequest
  3540. //
  3541. //
  3542. //-----------------------------------------------------------------------
  3543. BOOL AECreateEnrollmentRequest(
  3544. HWND hwndParent,
  3545. BOOL fUIProcess,
  3546. BOOL fMachine,
  3547. LPWSTR pwszMachineName,
  3548. AE_CERTTYPE_INFO *pCertType,
  3549. AE_CA_INFO *pCAInfo,
  3550. HANDLE *phRequest,
  3551. DWORD *pdwLastError)
  3552. {
  3553. BOOL fResult = FALSE;
  3554. CRYPTUI_WIZ_CREATE_CERT_REQUEST_INFO CreateRequestInfo;
  3555. CRYPTUI_WIZ_CERT_REQUEST_PVK_NEW CertPvkNew;
  3556. CRYPT_KEY_PROV_INFO KeyProvInfo;
  3557. DWORD dwFlags=CRYPTUI_WIZ_NO_UI_EXCEPT_CSP |
  3558. CRYPTUI_WIZ_NO_INSTALL_ROOT |
  3559. CRYPTUI_WIZ_ALLOW_ALL_TEMPLATES |
  3560. CRYPTUI_WIZ_ALLOW_ALL_CAS;
  3561. DWORD dwSize=0;
  3562. DWORD dwAcquireFlags=0;
  3563. BOOL fResetProv=FALSE;
  3564. CRYPT_KEY_PROV_INFO *pKeyProvInfo=NULL;
  3565. HANDLE hRequest=NULL;
  3566. memset(&CreateRequestInfo, 0, sizeof(CRYPTUI_WIZ_CREATE_CERT_REQUEST_INFO));
  3567. memset(&CertPvkNew, 0, sizeof(CRYPTUI_WIZ_CERT_REQUEST_PVK_NEW));
  3568. memset(&KeyProvInfo, 0, sizeof(CRYPT_KEY_PROV_INFO));
  3569. CreateRequestInfo.dwSize = sizeof(CreateRequestInfo);
  3570. //enroll or renewal
  3571. if((pCertType->fRenewal) && (pCertType->pOldCert))
  3572. {
  3573. CreateRequestInfo.dwPurpose = CRYPTUI_WIZ_CERT_RENEW;
  3574. CreateRequestInfo.pRenewCertContext = pCertType->pOldCert;
  3575. //we should not archive renewal certificate for cross template RA
  3576. if((pCertType->fNeedRA) && (pCertType->fCrossRA))
  3577. dwFlags |= CRYPTUI_WIZ_NO_ARCHIVE_RENEW_CERT;
  3578. //we should disalbe UI for machine or non-UI enrollment renew/RA certificate
  3579. if((TRUE == fMachine) || (FALSE == fUIProcess))
  3580. {
  3581. dwSize=0;
  3582. if(!CertGetCertificateContextProperty(pCertType->pOldCert,
  3583. CERT_KEY_PROV_INFO_PROP_ID,
  3584. NULL,
  3585. &dwSize))
  3586. goto error;
  3587. pKeyProvInfo=(CRYPT_KEY_PROV_INFO *)LocalAlloc(LPTR, dwSize);
  3588. if(NULL == pKeyProvInfo)
  3589. goto error;
  3590. if(!CertGetCertificateContextProperty(pCertType->pOldCert,
  3591. CERT_KEY_PROV_INFO_PROP_ID,
  3592. pKeyProvInfo,
  3593. &dwSize))
  3594. goto error;
  3595. dwAcquireFlags=pKeyProvInfo->dwFlags;
  3596. pKeyProvInfo->dwFlags |= CRYPT_SILENT;
  3597. //set the property
  3598. if(!CertSetCertificateContextProperty(pCertType->pOldCert,
  3599. CERT_KEY_PROV_INFO_PROP_ID,
  3600. CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG,
  3601. pKeyProvInfo))
  3602. goto error;
  3603. fResetProv=TRUE;
  3604. }
  3605. }
  3606. else
  3607. CreateRequestInfo.dwPurpose = CRYPTUI_WIZ_CERT_ENROLL;
  3608. //cert template information
  3609. CreateRequestInfo.hCertType = pCertType->hCertType;
  3610. //machine name
  3611. if(fMachine)
  3612. {
  3613. CreateRequestInfo.fMachineContext = TRUE;
  3614. }
  3615. //private key information
  3616. CreateRequestInfo.dwPvkChoice = CRYPTUI_WIZ_CERT_REQUEST_PVK_CHOICE_NEW;
  3617. CreateRequestInfo.pPvkNew = &CertPvkNew;
  3618. CertPvkNew.dwSize = sizeof(CertPvkNew);
  3619. CertPvkNew.pKeyProvInfo = &KeyProvInfo;
  3620. CertPvkNew.dwGenKeyFlags = 0; //no need to specify the exportable flags
  3621. //SILENT is always set for machine
  3622. if(fMachine)
  3623. KeyProvInfo.dwFlags = CRYPT_MACHINE_KEYSET | CRYPT_SILENT;
  3624. else
  3625. {
  3626. if(fUIProcess)
  3627. KeyProvInfo.dwFlags = 0;
  3628. else
  3629. KeyProvInfo.dwFlags = CRYPT_SILENT;
  3630. }
  3631. //CA information
  3632. CreateRequestInfo.pwszCALocation = pCAInfo->awszCADNS[0];
  3633. CreateRequestInfo.pwszCAName = pCAInfo->awszCAName[0];
  3634. if(!CryptUIWizCreateCertRequestNoDS(
  3635. dwFlags,
  3636. hwndParent,
  3637. &CreateRequestInfo,
  3638. &hRequest))
  3639. goto error;
  3640. if(NULL==hRequest)
  3641. goto error;
  3642. *phRequest=hRequest;
  3643. hRequest=NULL;
  3644. fResult = TRUE;
  3645. error:
  3646. //get the last error
  3647. if(FALSE == fResult)
  3648. {
  3649. *pdwLastError=GetLastError();
  3650. }
  3651. //reset the property
  3652. if(TRUE == fResetProv)
  3653. {
  3654. if((pKeyProvInfo) && (pCertType->pOldCert))
  3655. {
  3656. pKeyProvInfo->dwFlags = dwAcquireFlags;
  3657. //set the property
  3658. CertSetCertificateContextProperty(pCertType->pOldCert,
  3659. CERT_KEY_PROV_INFO_PROP_ID,
  3660. CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG,
  3661. pKeyProvInfo);
  3662. }
  3663. }
  3664. if(pKeyProvInfo)
  3665. LocalFree(pKeyProvInfo);
  3666. if(hRequest)
  3667. CryptUIWizFreeCertRequestNoDS(hRequest);
  3668. return fResult;
  3669. }
  3670. //-----------------------------------------------------------------------
  3671. //
  3672. // AECancelled
  3673. //
  3674. //-----------------------------------------------------------------------
  3675. BOOL AECancelled(HANDLE hCancelEvent)
  3676. {
  3677. if(NULL==hCancelEvent)
  3678. return FALSE;
  3679. //test if the event is signalled
  3680. if(WAIT_OBJECT_0 == WaitForSingleObject(hCancelEvent, 0))
  3681. return TRUE;
  3682. return FALSE;
  3683. }
  3684. //-----------------------------------------------------------------------
  3685. //
  3686. // AEDoEnrollment
  3687. //
  3688. // return TRUE is no need to do another renewal.
  3689. // *pdwStatus contain the real enrollment status.
  3690. //
  3691. //-----------------------------------------------------------------------
  3692. BOOL AEDoEnrollment(HWND hwndParent,
  3693. HANDLE hCancelEvent,
  3694. BOOL fUIProcess,
  3695. DWORD dwLogLevel,
  3696. HANDLE hToken,
  3697. BOOL fMachine,
  3698. LPWSTR pwszMachineName,
  3699. AE_CERTTYPE_INFO *pCertType,
  3700. DWORD dwCA,
  3701. AE_CA_INFO *rgCAInfo,
  3702. DWORD *pdwStatus)
  3703. {
  3704. BOOL fResult = FALSE;
  3705. DWORD dwIndex = 0;
  3706. DWORD dwCAIndex = 0;
  3707. BOOL fRenewal = FALSE;
  3708. DWORD dwEventID = 0;
  3709. BOOL fFoundCA = FALSE;
  3710. DWORD idsSummary = 0; //keep the last failure case
  3711. DWORD dwLastError = 0;
  3712. CRYPTUI_WIZ_QUERY_CERT_REQUEST_INFO QueryCertRequestInfo;
  3713. HANDLE hRequest=NULL;
  3714. PCCERT_CONTEXT pCertContext=NULL;
  3715. //init the out parameter
  3716. *pdwStatus = CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_ERROR;
  3717. //detect if we are performing an enrollment or renewal
  3718. if((pCertType->fRenewal) && (pCertType->pOldCert))
  3719. {
  3720. if((pCertType->fNeedRA) && (pCertType->fCrossRA))
  3721. fRenewal=FALSE;
  3722. else
  3723. fRenewal=TRUE;
  3724. }
  3725. else
  3726. fRenewal=FALSE;
  3727. //loop through all the CAs
  3728. for(dwIndex =0; dwIndex < dwCA; dwIndex++)
  3729. {
  3730. dwCAIndex = (dwIndex + pCertType->dwRandomCAIndex) % dwCA;
  3731. if(AECancelled(hCancelEvent))
  3732. {
  3733. //no need to renew any more
  3734. fResult=TRUE;
  3735. //log that autoenrollment is cancelled
  3736. AELogAutoEnrollmentEvent(dwLogLevel,
  3737. FALSE,
  3738. S_OK,
  3739. EVENT_AUTOENROLL_CANCELLED,
  3740. fMachine,
  3741. hToken,
  3742. 0);
  3743. break;
  3744. }
  3745. //make sure the CA supports the specific template
  3746. if(!AEIsAnElement((pCertType->awszName)[0],
  3747. rgCAInfo[dwCAIndex].awszCertificateTemplate))
  3748. continue;
  3749. //make sure the CA's validity period of more than the renewing certificate
  3750. if(TRUE == fRenewal)
  3751. {
  3752. if(!AEIsCALonger(rgCAInfo[dwCAIndex].hCAInfo, pCertType->pOldCert))
  3753. continue;
  3754. }
  3755. //enroll to the CA
  3756. *pdwStatus = CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_ERROR;
  3757. fFoundCA = TRUE;
  3758. //create a certificate request
  3759. if(NULL==hRequest)
  3760. {
  3761. if(!AECreateEnrollmentRequest(hwndParent, fUIProcess, fMachine, pwszMachineName, pCertType, &(rgCAInfo[dwCAIndex]), &hRequest, &dwLastError))
  3762. {
  3763. //check if user cancelled the enrollment. If so, no
  3764. //need to try another CA.
  3765. if((HRESULT_FROM_WIN32(ERROR_CANCELLED) == dwLastError) ||
  3766. (SCARD_W_CANCELLED_BY_USER == dwLastError))
  3767. {
  3768. //no need to renewal anymore
  3769. fResult = TRUE;
  3770. //log that autoenrollment is cancelled
  3771. AELogAutoEnrollmentEvent(dwLogLevel,
  3772. FALSE,
  3773. S_OK,
  3774. EVENT_AUTOENROLL_CANCELLED_TEMPLATE,
  3775. fMachine,
  3776. hToken,
  3777. 1,
  3778. pCertType->awszDisplay[0]);
  3779. break;
  3780. }
  3781. else
  3782. {
  3783. idsSummary=IDS_SUMMARY_REQUEST;
  3784. if(CT_FLAG_REQUIRE_PRIVATE_KEY_ARCHIVAL & pCertType->dwPrivateKeyFlag)
  3785. {
  3786. //we have a chance of success with another CA
  3787. if(hRequest)
  3788. {
  3789. CryptUIWizFreeCertRequestNoDS(hRequest);
  3790. hRequest=NULL;
  3791. }
  3792. continue;
  3793. }
  3794. else
  3795. {
  3796. //we have no hope to create a request successfully
  3797. //mark dwIndex to the dwCA so that we will log an event at the end of the loop
  3798. dwIndex=dwCA;
  3799. break;
  3800. }
  3801. }
  3802. }
  3803. }
  3804. //check the cancel again because significant time can pass during
  3805. //request creation
  3806. if(AECancelled(hCancelEvent))
  3807. {
  3808. //no need to renew any more
  3809. fResult=TRUE;
  3810. //log that autoenrollment is cancelled
  3811. AELogAutoEnrollmentEvent(dwLogLevel,
  3812. FALSE,
  3813. S_OK,
  3814. EVENT_AUTOENROLL_CANCELLED,
  3815. fMachine,
  3816. hToken,
  3817. 0);
  3818. break;
  3819. }
  3820. if(CryptUIWizSubmitCertRequestNoDS(
  3821. hRequest,
  3822. hwndParent,
  3823. rgCAInfo[dwCAIndex].awszCAName[0],
  3824. rgCAInfo[dwCAIndex].awszCADNS[0],
  3825. pdwStatus,
  3826. &pCertContext))
  3827. {
  3828. //no need to try another CA if the request is successful or pending
  3829. if((CRYPTUI_WIZ_CERT_REQUEST_STATUS_SUCCEEDED == (*pdwStatus)) ||
  3830. (CRYPTUI_WIZ_CERT_REQUEST_STATUS_UNDER_SUBMISSION == (*pdwStatus))
  3831. )
  3832. {
  3833. //no need to renewal anymore
  3834. fResult = TRUE;
  3835. if(CRYPTUI_WIZ_CERT_REQUEST_STATUS_SUCCEEDED == (*pdwStatus))
  3836. {
  3837. //we copy the certificate to publishing
  3838. if(pCertContext)
  3839. {
  3840. CertAddCertificateContextToStore(pCertType->hIssuedStore,
  3841. pCertContext,
  3842. CERT_STORE_ADD_USE_EXISTING,
  3843. NULL);
  3844. CertFreeCertificateContext(pCertContext);
  3845. pCertContext=NULL;
  3846. }
  3847. dwEventID=fRenewal ? EVENT_RENEWAL_SUCCESS_ONCE : EVENT_ENROLL_SUCCESS_ONCE;
  3848. }
  3849. else
  3850. {
  3851. dwEventID=fRenewal ? EVENT_RENEWAL_PENDING_ONCE : EVENT_ENROLL_PENDING_ONCE;
  3852. }
  3853. //log the enrollment sucess or pending event
  3854. AELogAutoEnrollmentEvent(dwLogLevel,
  3855. FALSE,
  3856. S_OK,
  3857. dwEventID,
  3858. fMachine,
  3859. hToken,
  3860. 3,
  3861. pCertType->awszDisplay[0],
  3862. rgCAInfo[dwCAIndex].awszCADisplay[0],
  3863. rgCAInfo[dwCAIndex].awszCADNS[0]);
  3864. //log if the private key is re-used
  3865. memset(&QueryCertRequestInfo, 0, sizeof(QueryCertRequestInfo));
  3866. QueryCertRequestInfo.dwSize=sizeof(QueryCertRequestInfo);
  3867. if(CryptUIWizQueryCertRequestNoDS(hRequest,
  3868. &QueryCertRequestInfo))
  3869. {
  3870. if(CRYPTUI_WIZ_QUERY_CERT_REQUEST_STATUS_CREATE_REUSED_PRIVATE_KEY &
  3871. (QueryCertRequestInfo.dwStatus))
  3872. {
  3873. AELogAutoEnrollmentEvent(dwLogLevel,
  3874. FALSE,
  3875. S_OK,
  3876. EVENT_PRIVATE_KEY_REUSED,
  3877. fMachine,
  3878. hToken,
  3879. 1,
  3880. pCertType->awszDisplay[0]);
  3881. }
  3882. }
  3883. break;
  3884. }
  3885. }
  3886. //get the last error
  3887. dwLastError=GetLastError();
  3888. idsSummary=IDS_SUMMARY_CA;
  3889. //log the one enrollment warning
  3890. AELogAutoEnrollmentEvent(dwLogLevel,
  3891. TRUE,
  3892. HRESULT_FROM_WIN32(dwLastError),
  3893. fRenewal ? EVENT_RENEWAL_FAIL_ONCE : EVENT_ENROLL_FAIL_ONCE,
  3894. fMachine,
  3895. hToken,
  3896. 3,
  3897. pCertType->awszDisplay[0],
  3898. rgCAInfo[dwCAIndex].awszCADisplay[0],
  3899. rgCAInfo[dwCAIndex].awszCADNS[0]);
  3900. //we should recreate the request for key archival
  3901. if(CT_FLAG_REQUIRE_PRIVATE_KEY_ARCHIVAL & pCertType->dwPrivateKeyFlag)
  3902. {
  3903. if(hRequest)
  3904. {
  3905. CryptUIWizFreeCertRequestNoDS(hRequest);
  3906. hRequest=NULL;
  3907. }
  3908. }
  3909. }
  3910. //log all enrollments error
  3911. //the loop will exit only if CANCEL, or SUCCEED, or we run out of CAs to try or
  3912. //the request can not be created
  3913. if(dwIndex == dwCA)
  3914. {
  3915. //we either run out of CAs to try or the request can not be created
  3916. if(0 != idsSummary)
  3917. pCertType->idsSummary=idsSummary;
  3918. if(fFoundCA)
  3919. {
  3920. dwEventID = fRenewal ? EVENT_RENEWAL_FAIL : EVENT_ENROLL_FAIL;
  3921. }
  3922. else
  3923. {
  3924. //if there is no CA, no need to try re-enrollment
  3925. if(fRenewal)
  3926. pCertType->fRenewal=FALSE;
  3927. dwEventID = fRenewal ? EVENT_RENEWAL_NO_CA_FAIL : EVENT_ENROLL_NO_CA_FAIL;
  3928. }
  3929. AELogAutoEnrollmentEvent(dwLogLevel,
  3930. fFoundCA ? TRUE : FALSE,
  3931. HRESULT_FROM_WIN32(dwLastError),
  3932. dwEventID,
  3933. fMachine,
  3934. hToken,
  3935. 1,
  3936. pCertType->awszDisplay[0]);
  3937. }
  3938. if(hRequest)
  3939. CryptUIWizFreeCertRequestNoDS(hRequest);
  3940. return fResult;
  3941. }
  3942. //-----------------------------------------------------------------------
  3943. //
  3944. // AEEnrollmentCertificates
  3945. //
  3946. //-----------------------------------------------------------------------
  3947. BOOL AEEnrollmentCertificates(AE_GENERAL_INFO *pAE_General_Info, DWORD dwEnrollStatus)
  3948. {
  3949. AE_CERTTYPE_INFO *rgCertTypeInfo = NULL;
  3950. DWORD dwIndex =0 ;
  3951. DWORD dwStatus= 0;
  3952. DWORD dwRandom = 0;
  3953. HCRYPTPROV hProv = NULL;
  3954. rgCertTypeInfo = pAE_General_Info->rgCertTypeInfo;
  3955. if(NULL == rgCertTypeInfo)
  3956. return FALSE;
  3957. if((0 == pAE_General_Info->dwCA) || (NULL==pAE_General_Info->rgCAInfo))
  3958. return FALSE;
  3959. if(!CryptAcquireContextW(&hProv,
  3960. NULL,
  3961. MS_DEF_PROV_W,
  3962. PROV_RSA_FULL,
  3963. CRYPT_VERIFYCONTEXT))
  3964. hProv=NULL;
  3965. //going through all the active requests
  3966. for(dwIndex=0; dwIndex < pAE_General_Info->dwCertType; dwIndex++)
  3967. {
  3968. //we enroll/renew for templates that are active
  3969. if(dwEnrollStatus != rgCertTypeInfo[dwIndex].dwStatus)
  3970. continue;
  3971. if(pAE_General_Info->fUIProcess != rgCertTypeInfo[dwIndex].fUIActive)
  3972. continue;
  3973. //select a random CA index to balance the load
  3974. if((hProv) && (CryptGenRandom(hProv, sizeof(dwRandom), (BYTE *)(&dwRandom))))
  3975. {
  3976. rgCertTypeInfo[dwIndex].dwRandomCAIndex = dwRandom % (pAE_General_Info->dwCA);
  3977. }
  3978. else
  3979. rgCertTypeInfo[dwIndex].dwRandomCAIndex = 0;
  3980. //enroll
  3981. dwStatus=0;
  3982. //report progress
  3983. if(pAE_General_Info->fUIProcess)
  3984. {
  3985. //continue if user choose CANCEL in view RA dialogue
  3986. if(!AEUIProgressReport(FALSE, &(rgCertTypeInfo[dwIndex]),pAE_General_Info->hwndDlg, pAE_General_Info->hCancelEvent))
  3987. {
  3988. AEUIProgressAdvance(pAE_General_Info);
  3989. continue;
  3990. }
  3991. }
  3992. if(AEDoEnrollment( pAE_General_Info->hwndDlg ? pAE_General_Info->hwndDlg : pAE_General_Info->hwndParent,
  3993. pAE_General_Info->hCancelEvent,
  3994. pAE_General_Info->fUIProcess,
  3995. pAE_General_Info->dwLogLevel,
  3996. pAE_General_Info->hToken,
  3997. pAE_General_Info->fMachine,
  3998. pAE_General_Info->wszMachineName,
  3999. &(rgCertTypeInfo[dwIndex]),
  4000. pAE_General_Info->dwCA,
  4001. pAE_General_Info->rgCAInfo,
  4002. &dwStatus))
  4003. {
  4004. //mark the status
  4005. if(CRYPTUI_WIZ_CERT_REQUEST_STATUS_SUCCEEDED == dwStatus)
  4006. rgCertTypeInfo[dwIndex].dwStatus=CERT_REQUEST_STATUS_OBTAINED;
  4007. }
  4008. else
  4009. {
  4010. //if renewal failed, we try to re-enrollment if no RA is required
  4011. if((rgCertTypeInfo[dwIndex].fRenewal) && (FALSE == (rgCertTypeInfo[dwIndex].fNeedRA)))
  4012. {
  4013. rgCertTypeInfo[dwIndex].fRenewal=FALSE;
  4014. dwStatus=0;
  4015. if(AEDoEnrollment( pAE_General_Info->hwndDlg ? pAE_General_Info->hwndDlg : pAE_General_Info->hwndParent,
  4016. pAE_General_Info->hCancelEvent,
  4017. pAE_General_Info->fUIProcess,
  4018. pAE_General_Info->dwLogLevel,
  4019. pAE_General_Info->hToken,
  4020. pAE_General_Info->fMachine,
  4021. pAE_General_Info->wszMachineName,
  4022. &(rgCertTypeInfo[dwIndex]),
  4023. pAE_General_Info->dwCA,
  4024. pAE_General_Info->rgCAInfo,
  4025. &dwStatus))
  4026. {
  4027. //mark the status
  4028. if(CRYPTUI_WIZ_CERT_REQUEST_STATUS_SUCCEEDED == dwStatus)
  4029. rgCertTypeInfo[dwIndex].dwStatus=CERT_REQUEST_STATUS_OBTAINED;
  4030. }
  4031. }
  4032. }
  4033. //advance progress
  4034. if(pAE_General_Info->fUIProcess)
  4035. {
  4036. AEUIProgressAdvance(pAE_General_Info);
  4037. }
  4038. }
  4039. if(hProv)
  4040. CryptReleaseContext(hProv, 0);
  4041. return TRUE;
  4042. }
  4043. //-----------------------------------------------------------------------
  4044. //
  4045. // AEIsDeletableCert
  4046. // Decide if we should archive or delete the certificate
  4047. //
  4048. //-----------------------------------------------------------------------
  4049. BOOL AEIsDeletableCert(PCCERT_CONTEXT pCertContext, AE_GENERAL_INFO *pAE_General_Info)
  4050. {
  4051. AE_CERTTYPE_INFO *pCertType=NULL;
  4052. BOOL fDelete=FALSE;
  4053. AE_TEMPLATE_INFO AETemplateInfo;
  4054. memset(&AETemplateInfo, 0, sizeof(AE_TEMPLATE_INFO));
  4055. //only interested in certificate with template information
  4056. if(!AERetrieveTemplateInfo(pCertContext, &AETemplateInfo))
  4057. goto Ret;
  4058. pCertType=AEFindTemplateInRequestTree(&AETemplateInfo, pAE_General_Info);
  4059. if(NULL==pCertType)
  4060. goto Ret;
  4061. if(CT_FLAG_REMOVE_INVALID_CERTIFICATE_FROM_PERSONAL_STORE & (pCertType->dwEnrollmentFlag))
  4062. fDelete=TRUE;
  4063. else
  4064. fDelete=FALSE;
  4065. Ret:
  4066. AEFreeTemplateInfo(&AETemplateInfo);
  4067. return fDelete;
  4068. }
  4069. //-----------------------------------------------------------------------
  4070. //
  4071. // AEArchiveObsoleteCertificates
  4072. // archive old certificate after the enrollment/renewal
  4073. //
  4074. // clean up the hUserDS store (delete the expired or revoked certificate)
  4075. //-----------------------------------------------------------------------
  4076. BOOL AEArchiveObsoleteCertificates(AE_GENERAL_INFO *pAE_General_Info)
  4077. {
  4078. AE_CERTTYPE_INFO *rgCertTypeInfo = NULL;
  4079. DWORD dwIndex = 0;
  4080. CRYPT_DATA_BLOB Archived;
  4081. BOOL fArchived = FALSE;
  4082. AE_CERT_INFO AECertInfo;
  4083. BOOL fRepublish=FALSE;
  4084. BYTE rgbHash[SHA1_HASH_LENGTH];
  4085. CRYPT_HASH_BLOB blobHash;
  4086. BOOL fHash=FALSE;
  4087. HCERTSTORE hUserDS = NULL;
  4088. PCCERT_CONTEXT pCertContext = NULL;
  4089. PCCERT_CONTEXT pMyContext = NULL;
  4090. PCCERT_CONTEXT pDSContext = NULL;
  4091. PCCERT_CONTEXT pIssuedContext = NULL;
  4092. rgCertTypeInfo = pAE_General_Info->rgCertTypeInfo;
  4093. if(NULL == rgCertTypeInfo)
  4094. return FALSE;
  4095. memset(&Archived, 0, sizeof(CRYPT_DATA_BLOB));
  4096. memset(&AECertInfo, 0, sizeof(AE_CERT_INFO));
  4097. //open the UserDS store
  4098. if(!(pAE_General_Info->fMachine))
  4099. {
  4100. hUserDS = AEOpenUserDSStore(pAE_General_Info, 0);
  4101. }
  4102. for(dwIndex=0; dwIndex < pAE_General_Info->dwCertType; dwIndex++)
  4103. {
  4104. fHash=FALSE;
  4105. fRepublish=FALSE;
  4106. if(CERT_REQUEST_STATUS_OBTAINED == rgCertTypeInfo[dwIndex].dwStatus)
  4107. {
  4108. //get the hash of newly enrolled certificate
  4109. blobHash.cbData=SHA1_HASH_LENGTH;
  4110. blobHash.pbData=rgbHash;
  4111. if(rgCertTypeInfo[dwIndex].hIssuedStore)
  4112. {
  4113. if(pIssuedContext = CertEnumCertificatesInStore(
  4114. rgCertTypeInfo[dwIndex].hIssuedStore, NULL))
  4115. {
  4116. if(CryptHashCertificate(
  4117. NULL,
  4118. 0,
  4119. X509_ASN_ENCODING,
  4120. pIssuedContext->pbCertEncoded,
  4121. pIssuedContext->cbCertEncoded,
  4122. blobHash.pbData,
  4123. &(blobHash.cbData)))
  4124. {
  4125. fHash=TRUE;
  4126. }
  4127. }
  4128. //free the cert context
  4129. if(pIssuedContext)
  4130. {
  4131. CertFreeCertificateContext(pIssuedContext);
  4132. pIssuedContext = NULL;
  4133. }
  4134. }
  4135. while(pCertContext = CertEnumCertificatesInStore(
  4136. rgCertTypeInfo[dwIndex].hArchiveStore, pCertContext))
  4137. {
  4138. //archive or delete the certificate from my store
  4139. pMyContext = FindCertificateInOtherStore(
  4140. pAE_General_Info->hMyStore,
  4141. pCertContext);
  4142. if(pMyContext)
  4143. {
  4144. //set the Hash of the newly enrolled certificate
  4145. if(fHash)
  4146. {
  4147. CertSetCertificateContextProperty(
  4148. pMyContext,
  4149. CERT_RENEWAL_PROP_ID,
  4150. 0,
  4151. &blobHash);
  4152. }
  4153. if(AEIsDeletableCert(pMyContext, pAE_General_Info))
  4154. {
  4155. CertDeleteCertificateFromStore(CertDuplicateCertificateContext(pMyContext));
  4156. }
  4157. else
  4158. {
  4159. // We force an archive on the old cert and close it.
  4160. CertSetCertificateContextProperty(pMyContext,
  4161. CERT_ARCHIVED_PROP_ID,
  4162. 0,
  4163. &Archived);
  4164. fArchived=TRUE;
  4165. }
  4166. CertFreeCertificateContext(pMyContext);
  4167. pMyContext = NULL;
  4168. }
  4169. //check the DS store. remove the certificates from DS store
  4170. if(hUserDS)
  4171. {
  4172. if(pMyContext = FindCertificateInOtherStore(
  4173. hUserDS,
  4174. pCertContext))
  4175. {
  4176. CertDeleteCertificateFromStore(pMyContext);
  4177. pMyContext = NULL;
  4178. fRepublish=TRUE;
  4179. }
  4180. }
  4181. }
  4182. }
  4183. }
  4184. //now we are done with archiving, we clean up user DS store
  4185. if(AUTO_ENROLLMENT_ENABLE_MY_STORE_MANAGEMENT & (pAE_General_Info->dwPolicy))
  4186. {
  4187. if(hUserDS)
  4188. {
  4189. while(pDSContext = CertEnumCertificatesInStore(hUserDS, pDSContext))
  4190. {
  4191. AEValidateCertificateInfo(pAE_General_Info,
  4192. NULL, //do not evaluate soon to expire
  4193. FALSE, //do not valid private key
  4194. pDSContext,
  4195. &AECertInfo);
  4196. if(FALSE == AECertInfo.fRenewal)
  4197. {
  4198. CertDeleteCertificateFromStore(CertDuplicateCertificateContext(pDSContext));
  4199. fRepublish=TRUE;
  4200. }
  4201. memset(&AECertInfo, 0, sizeof(AE_CERT_INFO));
  4202. }
  4203. }
  4204. }
  4205. //we have to republish the certificates as we have rewritten the user DS store
  4206. //CA might has just published to the location
  4207. if(fRepublish)
  4208. {
  4209. if(hUserDS)
  4210. {
  4211. for(dwIndex=0; dwIndex < pAE_General_Info->dwCertType; dwIndex++)
  4212. {
  4213. if(CERT_REQUEST_STATUS_OBTAINED == rgCertTypeInfo[dwIndex].dwStatus)
  4214. {
  4215. if((rgCertTypeInfo[dwIndex].hIssuedStore) &&
  4216. (CT_FLAG_PUBLISH_TO_DS & rgCertTypeInfo[dwIndex].dwEnrollmentFlag)
  4217. )
  4218. {
  4219. pCertContext=NULL;
  4220. while(pCertContext = CertEnumCertificatesInStore(
  4221. rgCertTypeInfo[dwIndex].hIssuedStore, pCertContext))
  4222. {
  4223. CertAddCertificateContextToStore(hUserDS,
  4224. pCertContext,
  4225. CERT_STORE_ADD_USE_EXISTING,
  4226. NULL);
  4227. }
  4228. }
  4229. }
  4230. }
  4231. }
  4232. }
  4233. //report the event if archival has happened
  4234. if(fArchived)
  4235. AELogAutoEnrollmentEvent(pAE_General_Info->dwLogLevel, FALSE, S_OK, EVENT_ARCHIVE_CERT,
  4236. pAE_General_Info->fMachine, pAE_General_Info->hToken, 0);
  4237. if(hUserDS)
  4238. CertCloseStore(hUserDS, 0);
  4239. return TRUE;
  4240. }
  4241. //-----------------------------------------------------------------------
  4242. //
  4243. // AERemoveSupersedeActive
  4244. // Remove supersedeActive flag after any successful the enrollment/renewal
  4245. //
  4246. //-----------------------------------------------------------------------
  4247. BOOL AERemoveSupersedeActive(AE_GENERAL_INFO *pAE_General_Info)
  4248. {
  4249. AE_CERTTYPE_INFO *rgCertTypeInfo = NULL;
  4250. DWORD dwIndex = 0;
  4251. DWORD dwActiveIndex = 0;
  4252. DWORD dwMarkIndex = 0;
  4253. rgCertTypeInfo = pAE_General_Info->rgCertTypeInfo;
  4254. if(NULL == rgCertTypeInfo)
  4255. return FALSE;
  4256. for(dwIndex=0; dwIndex < pAE_General_Info->dwCertType; dwIndex++)
  4257. {
  4258. if(CERT_REQUEST_STATUS_OBTAINED == rgCertTypeInfo[dwIndex].dwStatus)
  4259. {
  4260. for(dwActiveIndex=0; dwActiveIndex < rgCertTypeInfo[dwIndex].dwActive; dwActiveIndex++)
  4261. {
  4262. dwMarkIndex = rgCertTypeInfo[dwIndex].prgActive[dwActiveIndex];
  4263. rgCertTypeInfo[dwMarkIndex].dwStatus=CERT_REQUEST_STATUS_OBTAINED;
  4264. }
  4265. }
  4266. }
  4267. return TRUE;
  4268. }
  4269. //-----------------------------------------------------------------------
  4270. //
  4271. // AEEnrollmentWalker
  4272. //
  4273. // This functin performs enrollment tasks
  4274. //
  4275. //
  4276. //-----------------------------------------------------------------------
  4277. BOOL AEEnrollmentWalker(AE_GENERAL_INFO *pAE_General_Info)
  4278. {
  4279. BOOL fResult = FALSE;
  4280. //we need to set the range for the progress bar in the
  4281. //UI case
  4282. if((pAE_General_Info->fUIProcess) && (pAE_General_Info->hwndDlg))
  4283. {
  4284. //set the range
  4285. if(0 != (pAE_General_Info->dwUIEnrollCount))
  4286. {
  4287. SendMessage(GetDlgItem(pAE_General_Info->hwndDlg, IDC_ENROLL_PROGRESS),
  4288. PBM_SETRANGE,
  4289. 0,
  4290. MAKELPARAM(0, ((pAE_General_Info->dwUIEnrollCount) & (0xFFFF)))
  4291. );
  4292. SendMessage(GetDlgItem(pAE_General_Info->hwndDlg, IDC_ENROLL_PROGRESS),
  4293. PBM_SETSTEP,
  4294. (WPARAM)1,
  4295. 0);
  4296. SendMessage(GetDlgItem(pAE_General_Info->hwndDlg, IDC_ENROLL_PROGRESS),
  4297. PBM_SETPOS,
  4298. (WPARAM)0,
  4299. 0);
  4300. }
  4301. }
  4302. //retrieve the pending request. Mark the status to obtained if the
  4303. //certificate is issued and of the correct version
  4304. if(AUTO_ENROLLMENT_ENABLE_PENDING_FETCH & (pAE_General_Info->dwPolicy))
  4305. {
  4306. if(FALSE == pAE_General_Info->fUIProcess)
  4307. {
  4308. if(!AEProcessPendingRequest(pAE_General_Info))
  4309. goto Ret;
  4310. }
  4311. else
  4312. {
  4313. if(!AEProcessUIPendingRequest(pAE_General_Info))
  4314. goto Ret;
  4315. }
  4316. }
  4317. //remove duplicated requests based on "Supersede" relationship
  4318. //supress active templates that are superseded by other templates
  4319. if(!AEManageSupersedeRequests(pAE_General_Info))
  4320. goto Ret;
  4321. //do enrollment/renewal
  4322. if(!AEEnrollmentCertificates(pAE_General_Info, CERT_REQUEST_STATUS_ACTIVE))
  4323. goto Ret;
  4324. //We try to get the superseded templates if supserseding templates failed.
  4325. //Only for machine for the case of two V2 DC templates.
  4326. if(TRUE == pAE_General_Info->fMachine)
  4327. {
  4328. //remove supersedeActive based on the obtained flag
  4329. if(!AERemoveSupersedeActive(pAE_General_Info))
  4330. goto Ret;
  4331. //do enrollment/renewal again since we migh fail to get superseding templates
  4332. if(!AEEnrollmentCertificates(pAE_General_Info, CERT_REQUEST_STATUS_SUPERSEDE_ACTIVE))
  4333. goto Ret;
  4334. }
  4335. fResult = TRUE;
  4336. Ret:
  4337. return fResult;
  4338. }
  4339. //-----------------------------------------------------------------------------
  4340. //
  4341. // AEUIProgressAdvance
  4342. //
  4343. // Increase the progress bar by one step
  4344. //-----------------------------------------------------------------------------
  4345. BOOL AEUIProgressAdvance(AE_GENERAL_INFO *pAE_General_Info)
  4346. {
  4347. BOOL fResult=FALSE;
  4348. if(NULL==pAE_General_Info)
  4349. goto Ret;
  4350. if(NULL==(pAE_General_Info->hwndDlg))
  4351. goto Ret;
  4352. //check if CANCEL button is clicked
  4353. if(AECancelled(pAE_General_Info->hCancelEvent))
  4354. {
  4355. fResult=TRUE;
  4356. goto Ret;
  4357. }
  4358. //advance the progress bar
  4359. SendMessage(GetDlgItem(pAE_General_Info->hwndDlg, IDC_ENROLL_PROGRESS),
  4360. PBM_STEPIT,
  4361. 0,
  4362. 0);
  4363. fResult=TRUE;
  4364. Ret:
  4365. return fResult;
  4366. }
  4367. //-----------------------------------------------------------------------------
  4368. //
  4369. // AEUIGetNameFromCert
  4370. //
  4371. // Retrieve a unique string to identify the certificate.
  4372. //-----------------------------------------------------------------------------
  4373. BOOL AEUIGetNameFromCert(PCCERT_CONTEXT pCertContext, LPWSTR *ppwszRACert)
  4374. {
  4375. BOOL fResult=FALSE;
  4376. DWORD dwChar=0;
  4377. DWORD cbOID=0;
  4378. PCCRYPT_OID_INFO pOIDInfo=NULL;
  4379. LPWSTR pwszRACert=NULL;
  4380. AE_TEMPLATE_INFO TemplateInfo;
  4381. LPSTR szOID=NULL;
  4382. if((NULL==pCertContext) || (NULL==ppwszRACert))
  4383. goto Ret;
  4384. *ppwszRACert=NULL;
  4385. memset(&TemplateInfo, 0, sizeof(TemplateInfo));
  4386. //get the template name first
  4387. if(!AERetrieveTemplateInfo(pCertContext, &TemplateInfo))
  4388. goto Ret;
  4389. if(TemplateInfo.pwszName)
  4390. {
  4391. pwszRACert=(LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * (wcslen(TemplateInfo.pwszName) + 1));
  4392. if(NULL == pwszRACert)
  4393. goto Ret;
  4394. wcscpy(pwszRACert, TemplateInfo.pwszName);
  4395. }
  4396. else
  4397. {
  4398. if(NULL==(TemplateInfo.pwszOid))
  4399. goto Ret;
  4400. //find the OID
  4401. if(0 == (cbOID = WideCharToMultiByte(CP_ACP,
  4402. 0,
  4403. TemplateInfo.pwszOid,
  4404. -1,
  4405. NULL,
  4406. 0,
  4407. NULL,
  4408. NULL)))
  4409. goto Ret;
  4410. szOID=(LPSTR)LocalAlloc(LPTR, cbOID);
  4411. if(NULL==szOID)
  4412. goto Ret;
  4413. if(0 == WideCharToMultiByte(CP_ACP,
  4414. 0,
  4415. TemplateInfo.pwszOid,
  4416. -1,
  4417. szOID,
  4418. cbOID,
  4419. NULL,
  4420. NULL))
  4421. goto Ret;
  4422. pOIDInfo=CryptFindOIDInfo(
  4423. CRYPT_OID_INFO_OID_KEY,
  4424. szOID,
  4425. CRYPT_TEMPLATE_OID_GROUP_ID);
  4426. if(pOIDInfo)
  4427. {
  4428. if(pOIDInfo->pwszName)
  4429. {
  4430. pwszRACert=(LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * (wcslen(pOIDInfo->pwszName) + 1));
  4431. if(NULL== pwszRACert)
  4432. goto Ret;
  4433. wcscpy(pwszRACert, pOIDInfo->pwszName);
  4434. }
  4435. }
  4436. }
  4437. //if template name does not exist. Get the subject name for now
  4438. /* if(NULL==pwszRACert)
  4439. {
  4440. if(0 == (dwChar=CertGetNameStringW(
  4441. pCertContext,
  4442. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  4443. 0,
  4444. NULL,
  4445. NULL,
  4446. 0)))
  4447. goto Ret;
  4448. pwszRACert=(LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * (dwChar));
  4449. if(NULL== pwszRACert)
  4450. goto Ret;
  4451. if(0 == (dwChar=CertGetNameStringW(
  4452. pCertContext,
  4453. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  4454. 0,
  4455. NULL,
  4456. pwszRACert,
  4457. dwChar)))
  4458. goto Ret;
  4459. } */
  4460. *ppwszRACert = pwszRACert;
  4461. pwszRACert=NULL;
  4462. fResult=TRUE;
  4463. Ret:
  4464. if(pwszRACert)
  4465. LocalFree(pwszRACert);
  4466. if(szOID)
  4467. LocalFree(szOID);
  4468. AEFreeTemplateInfo(&TemplateInfo);
  4469. return fResult;
  4470. }
  4471. //-----------------------------------------------------------------------------
  4472. //
  4473. // AEGetRACertInfo
  4474. //
  4475. //-----------------------------------------------------------------------------
  4476. BOOL AEGetRACertInfo(PCERT_CONTEXT pRAContext,
  4477. LPWSTR pwszRATemplate,
  4478. LPWSTR *ppwszRACertInfo)
  4479. {
  4480. BOOL fResult=FALSE;
  4481. UINT idsMessage=0;
  4482. DWORD dwSize=0;
  4483. LPWSTR pwszIssuer=NULL;
  4484. if(NULL==pRAContext)
  4485. goto Ret;
  4486. if(pwszRATemplate)
  4487. idsMessage=IDS_VIEW_RA_INFO;
  4488. else
  4489. idsMessage=IDS_VIEW_RA_INFO_GENERAL;
  4490. //the cert has to have an issuer
  4491. if(0 == (dwSize=CertNameToStrW(
  4492. ENCODING_TYPE,
  4493. &(pRAContext->pCertInfo->Issuer),
  4494. CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
  4495. NULL,
  4496. 0)))
  4497. goto Ret;
  4498. pwszIssuer=(LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * dwSize);
  4499. if(NULL==pwszIssuer)
  4500. goto Ret;
  4501. if(0 == CertNameToStrW(
  4502. ENCODING_TYPE,
  4503. &(pRAContext->pCertInfo->Issuer),
  4504. CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
  4505. pwszIssuer,
  4506. dwSize))
  4507. goto Ret;
  4508. if(!FormatMessageUnicode(
  4509. ppwszRACertInfo,
  4510. idsMessage,
  4511. pwszIssuer,
  4512. pwszRATemplate))
  4513. goto Ret;
  4514. fResult=TRUE;
  4515. Ret:
  4516. if(pwszIssuer)
  4517. LocalFree(pwszIssuer);
  4518. return fResult;
  4519. }
  4520. //-----------------------------------------------------------------------------
  4521. //
  4522. // WinProc for the view RA certificate dialogue
  4523. //
  4524. //-----------------------------------------------------------------------------
  4525. INT_PTR CALLBACK AEViewRADlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  4526. {
  4527. BOOL fPropertyChanged = FALSE;
  4528. AE_VIEW_RA_INFO *pAEViewRAInfo = NULL;
  4529. CRYPTUI_VIEWCERTIFICATE_STRUCT CertViewStruct;
  4530. LPWSTR pwszRACertInfo=NULL;
  4531. switch (msg)
  4532. {
  4533. case WM_INITDIALOG:
  4534. pAEViewRAInfo=(AE_VIEW_RA_INFO *)lParam;
  4535. if(NULL==pAEViewRAInfo)
  4536. break;
  4537. SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pAEViewRAInfo);
  4538. //display the RA template and issuer dynamically
  4539. if(AEGetRACertInfo(pAEViewRAInfo->pRAContext,
  4540. pAEViewRAInfo->pwszRATemplate,
  4541. &pwszRACertInfo))
  4542. {
  4543. SetDlgItemTextW(hwndDlg, IDC_EDIT3, pwszRACertInfo);
  4544. LocalFree((HLOCAL)pwszRACertInfo);
  4545. }
  4546. return TRUE;
  4547. break;
  4548. case WM_NOTIFY:
  4549. break;
  4550. case WM_CLOSE:
  4551. EndDialog(hwndDlg, IDC_BUTTON3);
  4552. return TRUE;
  4553. break;
  4554. case WM_COMMAND:
  4555. switch (LOWORD(wParam))
  4556. {
  4557. //view certificate
  4558. case IDC_BUTTON1:
  4559. if(NULL==(pAEViewRAInfo=(AE_VIEW_RA_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
  4560. break;
  4561. if(NULL==pAEViewRAInfo->pRAContext)
  4562. break;
  4563. //show the certificate
  4564. memset(&CertViewStruct, 0, sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT));
  4565. CertViewStruct.dwSize=sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT);
  4566. CertViewStruct.hwndParent=hwndDlg;
  4567. CertViewStruct.dwFlags=CRYPTUI_DISABLE_EDITPROPERTIES;
  4568. CertViewStruct.pCertContext=pAEViewRAInfo->pRAContext;
  4569. fPropertyChanged=FALSE;
  4570. CryptUIDlgViewCertificate(&CertViewStruct, &fPropertyChanged);
  4571. return TRUE;
  4572. //OK
  4573. case IDC_BUTTON2:
  4574. EndDialog(hwndDlg, IDC_BUTTON2);
  4575. return TRUE;
  4576. }
  4577. break;
  4578. default:
  4579. return FALSE;
  4580. }
  4581. return FALSE;
  4582. }
  4583. //-----------------------------------------------------------------------------
  4584. //
  4585. // AEUIProgressReport
  4586. //
  4587. // Report the current enrollment action. Return FALSE if no progress status
  4588. // can be reported.
  4589. //-----------------------------------------------------------------------------
  4590. BOOL AEUIProgressReport(BOOL fPending, AE_CERTTYPE_INFO *pCertType, HWND hwndDlg, HANDLE hCancelEvent)
  4591. {
  4592. BOOL fResult=FALSE;
  4593. UINT idsMessage=0;
  4594. INT_PTR ret=0;
  4595. AE_VIEW_RA_INFO AEViewRAInfo;
  4596. LPWSTR *awszFriendlyName=NULL;
  4597. LPWSTR pwszRACert=NULL;
  4598. LPWSTR pwszReport=NULL;
  4599. memset(&AEViewRAInfo, 0, sizeof(AE_VIEW_RA_INFO));
  4600. if((NULL==pCertType) || (NULL==hwndDlg))
  4601. goto Ret;
  4602. if(NULL==(pCertType->hCertType))
  4603. goto Ret;
  4604. if(AECancelled(hCancelEvent))
  4605. {
  4606. fResult=TRUE;
  4607. goto Ret;
  4608. }
  4609. if(fPending)
  4610. idsMessage=IDS_REPORT_PENDING;
  4611. else
  4612. {
  4613. if((pCertType->fRenewal) && (pCertType->pOldCert))
  4614. {
  4615. if(pCertType->fNeedRA)
  4616. {
  4617. if(FALSE == (pCertType->fCrossRA))
  4618. idsMessage=IDS_REPORT_RENEW;
  4619. else
  4620. idsMessage=IDS_REPORT_ENROLL_RA;
  4621. }
  4622. else
  4623. idsMessage=IDS_REPORT_RENEW;
  4624. }
  4625. else
  4626. idsMessage=IDS_REPORT_ENROLL;
  4627. }
  4628. //retrieve the template's friendly name
  4629. if(S_OK != CAGetCertTypePropertyEx(
  4630. pCertType->hCertType,
  4631. CERTTYPE_PROP_FRIENDLY_NAME,
  4632. &awszFriendlyName))
  4633. goto Ret;
  4634. if(NULL==awszFriendlyName)
  4635. goto Ret;
  4636. if(NULL==(awszFriendlyName[0]))
  4637. goto Ret;
  4638. //retrieve the RA certificate's template name
  4639. if(IDS_REPORT_ENROLL_RA == idsMessage)
  4640. {
  4641. if(!AEUIGetNameFromCert(pCertType->pOldCert, &pwszRACert))
  4642. {
  4643. pwszRACert=NULL;
  4644. }
  4645. }
  4646. if(!FormatMessageUnicode(&pwszReport, idsMessage, awszFriendlyName[0]))
  4647. goto Ret;
  4648. if(0 == SetDlgItemTextW(hwndDlg, IDC_EDIT2, pwszReport))
  4649. goto Ret;
  4650. //we will give user an opportunity to view the RA certificate before we go on
  4651. //format the view message
  4652. if(IDS_REPORT_ENROLL_RA != idsMessage)
  4653. {
  4654. //no need to do anything more
  4655. fResult=TRUE;
  4656. goto Ret;
  4657. }
  4658. AEViewRAInfo.pRAContext=pCertType->pOldCert;
  4659. AEViewRAInfo.pwszRATemplate=pwszRACert;
  4660. //ask user if he/she wants to view the RA certificate
  4661. ret=DialogBoxParam(g_hmodThisDll,
  4662. (LPCWSTR)MAKEINTRESOURCE(IDD_VIEW_RA_CERTIFICATE_DLG),
  4663. hwndDlg,
  4664. AEViewRADlgProc,
  4665. (LPARAM)(&AEViewRAInfo));
  4666. fResult=TRUE;
  4667. Ret:
  4668. if(pwszRACert)
  4669. LocalFree(pwszRACert);
  4670. if(awszFriendlyName)
  4671. CAFreeCertTypeProperty(pCertType->hCertType, awszFriendlyName);
  4672. if(pwszReport)
  4673. LocalFree((HLOCAL) pwszReport);
  4674. return fResult;
  4675. }
  4676. //-----------------------------------------------------------------------------
  4677. //
  4678. // the call back function to compare summary column
  4679. //
  4680. //-----------------------------------------------------------------------------
  4681. int CALLBACK CompareSummary(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  4682. {
  4683. AE_CERTTYPE_INFO *pCertTypeOne=NULL;
  4684. AE_CERTTYPE_INFO *pCertTypeTwo=NULL;
  4685. DWORD dwColumn=0;
  4686. int iCompare=0;
  4687. LPWSTR pwszOne=NULL;
  4688. LPWSTR pwszTwo=NULL;
  4689. pCertTypeOne=(AE_CERTTYPE_INFO *)lParam1;
  4690. pCertTypeTwo=(AE_CERTTYPE_INFO *)lParam2;
  4691. dwColumn=(DWORD)lParamSort;
  4692. if((NULL==pCertTypeOne) || (NULL==pCertTypeTwo))
  4693. goto Ret;
  4694. switch(dwColumn & 0x0000FFFF)
  4695. {
  4696. case AE_SUMMARY_COLUMN_TYPE:
  4697. //we should use wcsicoll instead of wcsicmp since wcsicoll use the
  4698. //lexicographic order of current code page.
  4699. iCompare=CompareStringW(LOCALE_USER_DEFAULT,
  4700. NORM_IGNORECASE,
  4701. pCertTypeOne->awszDisplay[0],
  4702. -1,
  4703. pCertTypeTwo->awszDisplay[0],
  4704. -1);
  4705. break;
  4706. case AE_SUMMARY_COLUMN_REASON:
  4707. pwszOne=(LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * (MAX_DN_SIZE));
  4708. pwszTwo=(LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * (MAX_DN_SIZE));
  4709. if((NULL==pwszOne) || (NULL==pwszTwo))
  4710. goto Ret;
  4711. if(0 == LoadStringW(g_hmodThisDll,
  4712. pCertTypeOne->idsSummary,
  4713. pwszOne,
  4714. MAX_DN_SIZE))
  4715. goto Ret;
  4716. if(0 == LoadStringW(g_hmodThisDll,
  4717. pCertTypeTwo->idsSummary,
  4718. pwszTwo,
  4719. MAX_DN_SIZE))
  4720. goto Ret;
  4721. //we should use wcsicoll instead of wcsicmp since wcsicoll use the
  4722. //lexicographic order of current code page.
  4723. iCompare=CompareStringW(LOCALE_USER_DEFAULT,
  4724. NORM_IGNORECASE,
  4725. pwszOne,
  4726. -1,
  4727. pwszTwo,
  4728. -1);
  4729. break;
  4730. default:
  4731. goto Ret;
  4732. break;
  4733. }
  4734. switch(iCompare)
  4735. {
  4736. case CSTR_LESS_THAN:
  4737. iCompare=-1;
  4738. break;
  4739. case CSTR_EQUAL:
  4740. iCompare=0;
  4741. break;
  4742. case CSTR_GREATER_THAN:
  4743. iCompare=1;
  4744. break;
  4745. default:
  4746. goto Ret;
  4747. break;
  4748. }
  4749. if(dwColumn & SORT_COLUMN_DESCEND)
  4750. iCompare = 0-iCompare;
  4751. Ret:
  4752. if(pwszOne)
  4753. LocalFree(pwszOne);
  4754. if(pwszTwo)
  4755. LocalFree(pwszTwo);
  4756. return iCompare;
  4757. }
  4758. //-----------------------------------------------------------------------------
  4759. //
  4760. // AEDisplaySummaryInfo
  4761. //
  4762. //-----------------------------------------------------------------------------
  4763. BOOL AEDisplaySummaryInfo(HWND hWndListView, AE_GENERAL_INFO *pAE_General_Info)
  4764. {
  4765. BOOL fResult=FALSE;
  4766. AE_CERTTYPE_INFO *rgCertTypeInfo = NULL;
  4767. DWORD dwIndex =0;
  4768. DWORD dwItem=0;
  4769. LV_ITEMW lvItem;
  4770. WCHAR wszReason[MAX_DN_SIZE];
  4771. AE_CERTTYPE_INFO *pCertType=NULL;
  4772. if((NULL==hWndListView) || (NULL==pAE_General_Info))
  4773. goto Ret;
  4774. rgCertTypeInfo = pAE_General_Info->rgCertTypeInfo;
  4775. if(NULL == rgCertTypeInfo)
  4776. goto Ret;
  4777. // set up the fields in the list view item struct that don't change from item to item
  4778. lvItem.mask = LVIF_TEXT | LVIF_PARAM;
  4779. lvItem.state = 0;
  4780. lvItem.stateMask = 0;
  4781. lvItem.iItem=0;
  4782. lvItem.iSubItem=0;
  4783. lvItem.iImage = 0;
  4784. lvItem.lParam = NULL;
  4785. for(dwIndex=0; dwIndex < pAE_General_Info->dwCertType; dwIndex++)
  4786. {
  4787. if((TRUE == rgCertTypeInfo[dwIndex].fUIActive) && (0 != rgCertTypeInfo[dwIndex].idsSummary))
  4788. {
  4789. if(0 != LoadStringW(g_hmodThisDll,
  4790. rgCertTypeInfo[dwIndex].idsSummary,
  4791. wszReason,
  4792. MAX_DN_SIZE))
  4793. {
  4794. lvItem.iItem=dwItem;
  4795. lvItem.iSubItem=0;
  4796. dwItem++;
  4797. pCertType=&(rgCertTypeInfo[dwIndex]);
  4798. lvItem.lParam = (LPARAM)(pCertType);
  4799. //template name
  4800. lvItem.pszText=rgCertTypeInfo[dwIndex].awszDisplay[0];
  4801. ListView_InsertItem(hWndListView, &lvItem);
  4802. //reason
  4803. lvItem.iSubItem++;
  4804. ListView_SetItemText(hWndListView, lvItem.iItem, lvItem.iSubItem, wszReason);
  4805. }
  4806. }
  4807. }
  4808. fResult=TRUE;
  4809. Ret:
  4810. return fResult;
  4811. }
  4812. //-----------------------------------------------------------------------------
  4813. //
  4814. // WinProc for the summary page
  4815. //
  4816. //-----------------------------------------------------------------------------
  4817. INT_PTR CALLBACK AESummaryDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  4818. {
  4819. AE_GENERAL_INFO *pAE_General_Info=NULL;
  4820. HWND hWndListView=NULL;
  4821. UINT rgIDS[]={IDS_COLUMN_TYPE,
  4822. IDS_COLUMN_REASON};
  4823. DWORD dwIndex=0;
  4824. DWORD dwCount=0;
  4825. LV_COLUMNW lvC;
  4826. WCHAR wszText[AE_SUMMARY_COLUMN_SIZE];
  4827. NM_LISTVIEW *pnmv=NULL;
  4828. DWORD dwSortParam=0;
  4829. static DWORD rgdwSortParam[]=
  4830. {AE_SUMMARY_COLUMN_TYPE | SORT_COLUMN_ASCEND,
  4831. AE_SUMMARY_COLUMN_REASON | SORT_COLUMN_DESCEND};
  4832. switch (msg)
  4833. {
  4834. case WM_INITDIALOG:
  4835. pAE_General_Info=(AE_GENERAL_INFO *)lParam;
  4836. if(NULL==pAE_General_Info)
  4837. break;
  4838. SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pAE_General_Info);
  4839. //init the list view control
  4840. //add the colums to the list view
  4841. hWndListView = GetDlgItem(hwndDlg, IDC_LIST2);
  4842. if(NULL==hWndListView)
  4843. break;
  4844. dwCount=sizeof(rgIDS)/sizeof(rgIDS[0]);
  4845. //set up the common info for the column
  4846. memset(&lvC, 0, sizeof(LV_COLUMNW));
  4847. lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  4848. lvC.fmt = LVCFMT_LEFT; // Left-align the column.
  4849. lvC.cx = 150; // Width of the column, in pixels.
  4850. lvC.iSubItem=0;
  4851. lvC.pszText = wszText; // The text for the column.
  4852. //insert the column one at a time
  4853. for(dwIndex=0; dwIndex < dwCount; dwIndex++)
  4854. {
  4855. //get the column header
  4856. wszText[0]=L'\0';
  4857. if(0 != LoadStringW(g_hmodThisDll, rgIDS[dwIndex], wszText, AE_SUMMARY_COLUMN_SIZE))
  4858. {
  4859. ListView_InsertColumn(hWndListView, dwIndex, &lvC);
  4860. }
  4861. }
  4862. // set the style in the list view so that it highlights an entire line
  4863. SendMessage(hWndListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
  4864. AEDisplaySummaryInfo(hWndListView, pAE_General_Info);
  4865. //autosize the columns
  4866. for(dwIndex=0; dwIndex < dwCount; dwIndex++)
  4867. {
  4868. ListView_SetColumnWidth(hWndListView, dwIndex, LVSCW_AUTOSIZE);
  4869. }
  4870. //sort 1st column of the list view
  4871. dwSortParam=rgdwSortParam[0];
  4872. SendDlgItemMessage(hwndDlg,
  4873. IDC_LIST2,
  4874. LVM_SORTITEMS,
  4875. (WPARAM) (LPARAM) dwSortParam,
  4876. (LPARAM) (PFNLVCOMPARE)CompareSummary);
  4877. return TRUE;
  4878. break;
  4879. case WM_NOTIFY:
  4880. switch (((NMHDR FAR *) lParam)->code)
  4881. {
  4882. //the column has been changed
  4883. case LVN_COLUMNCLICK:
  4884. pnmv = (NM_LISTVIEW *) lParam;
  4885. dwSortParam=0;
  4886. //get the column number
  4887. switch(pnmv->iSubItem)
  4888. {
  4889. case 0:
  4890. case 1:
  4891. dwSortParam=rgdwSortParam[pnmv->iSubItem];
  4892. break;
  4893. default:
  4894. dwSortParam=0;
  4895. break;
  4896. }
  4897. if(0!=dwSortParam)
  4898. {
  4899. //remember to flip the ascend ording
  4900. if(dwSortParam & SORT_COLUMN_ASCEND)
  4901. {
  4902. dwSortParam &= 0x0000FFFF;
  4903. dwSortParam |= SORT_COLUMN_DESCEND;
  4904. }
  4905. else
  4906. {
  4907. if(dwSortParam & SORT_COLUMN_DESCEND)
  4908. {
  4909. dwSortParam &= 0x0000FFFF;
  4910. dwSortParam |= SORT_COLUMN_ASCEND;
  4911. }
  4912. }
  4913. //sort the column
  4914. SendDlgItemMessage(hwndDlg,
  4915. IDC_LIST2,
  4916. LVM_SORTITEMS,
  4917. (WPARAM) (LPARAM) dwSortParam,
  4918. (LPARAM) (PFNLVCOMPARE)CompareSummary);
  4919. rgdwSortParam[pnmv->iSubItem]=dwSortParam;
  4920. }
  4921. break;
  4922. }
  4923. break;
  4924. case WM_CLOSE:
  4925. EndDialog(hwndDlg, IDC_BUTTON1);
  4926. return TRUE;
  4927. break;
  4928. case WM_COMMAND:
  4929. switch (LOWORD(wParam))
  4930. {
  4931. case IDC_BUTTON1:
  4932. EndDialog(hwndDlg, IDC_BUTTON1);
  4933. return TRUE;
  4934. }
  4935. break;
  4936. default:
  4937. return FALSE;
  4938. }
  4939. return FALSE;
  4940. }
  4941. //-----------------------------------------------------------------------------
  4942. //
  4943. // AEDisplaySummaryPage
  4944. //
  4945. //-----------------------------------------------------------------------------
  4946. BOOL AEDisplaySummaryPage(AE_GENERAL_INFO *pAE_General_Info)
  4947. {
  4948. BOOL fResult=FALSE;
  4949. DWORD dwIndex=0;
  4950. BOOL fSummary=FALSE;
  4951. AE_CERTTYPE_INFO *rgCertTypeInfo=NULL;
  4952. AE_CERTTYPE_INFO *pCertType=NULL;
  4953. //decide if there is need to show the summary page.
  4954. //Checking for idsSummary for each template
  4955. if(NULL == pAE_General_Info)
  4956. goto Ret;
  4957. if(NULL == (rgCertTypeInfo=pAE_General_Info->rgCertTypeInfo))
  4958. goto Ret;
  4959. for(dwIndex=0; dwIndex < pAE_General_Info->dwCertType; dwIndex++)
  4960. {
  4961. if((TRUE == rgCertTypeInfo[dwIndex].fUIActive) && (0 != rgCertTypeInfo[dwIndex].idsSummary))
  4962. {
  4963. fSummary=TRUE;
  4964. break;
  4965. }
  4966. }
  4967. //show the summary dialogue
  4968. if(TRUE == fSummary)
  4969. {
  4970. if(pAE_General_Info->hwndDlg)
  4971. {
  4972. DialogBoxParam(g_hmodThisDll,
  4973. (LPCWSTR)MAKEINTRESOURCE(IDD_USER_SUMMARY_DLG),
  4974. pAE_General_Info->hwndDlg,
  4975. AESummaryDlgProc,
  4976. (LPARAM)(pAE_General_Info));
  4977. }
  4978. }
  4979. fResult=TRUE;
  4980. Ret:
  4981. return fResult;
  4982. }
  4983. //-----------------------------------------------------------------------------
  4984. // WinProc for the autoenrollment progress window
  4985. //
  4986. //-----------------------------------------------------------------------------
  4987. INT_PTR CALLBACK progressDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  4988. {
  4989. AE_GENERAL_INFO *pAE_General_Info = NULL;
  4990. switch (msg)
  4991. {
  4992. case WM_INITDIALOG:
  4993. pAE_General_Info=(AE_GENERAL_INFO *)lParam;
  4994. //copy the hwndDlg to the enrollment thread
  4995. pAE_General_Info->hwndDlg=hwndDlg;
  4996. //start the interacive enrollment thread
  4997. if(1 != ResumeThread(pAE_General_Info->hThread))
  4998. {
  4999. pAE_General_Info->hwndDlg=NULL;
  5000. //we have to end the dialogue
  5001. EndDialog(hwndDlg, IDC_BUTTON1);
  5002. return TRUE;
  5003. }
  5004. SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pAE_General_Info);
  5005. return TRUE;
  5006. break;
  5007. case WM_NOTIFY:
  5008. break;
  5009. case WM_CLOSE:
  5010. if(NULL==(pAE_General_Info=(AE_GENERAL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
  5011. break;
  5012. //disable the cancel button
  5013. EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON1), FALSE);
  5014. //signal the cancel event
  5015. if(pAE_General_Info->hCancelEvent)
  5016. SetEvent(pAE_General_Info->hCancelEvent);
  5017. //close the dialogue if the enrollment work is completed
  5018. if(WAIT_OBJECT_0 == WaitForSingleObject(pAE_General_Info->hCompleteEvent, 0))
  5019. {
  5020. EndDialog(hwndDlg, IDC_BUTTON1);
  5021. }
  5022. return TRUE;
  5023. break;
  5024. case WM_COMMAND:
  5025. switch (LOWORD(wParam))
  5026. {
  5027. case IDC_BUTTON1:
  5028. if(NULL==(pAE_General_Info=(AE_GENERAL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
  5029. break;
  5030. //disable the cancel button
  5031. EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON1), FALSE);
  5032. //signal the cancel event
  5033. if(pAE_General_Info->hCancelEvent)
  5034. SetEvent(pAE_General_Info->hCancelEvent);
  5035. return TRUE;
  5036. }
  5037. break;
  5038. default:
  5039. return FALSE;
  5040. }
  5041. return FALSE;
  5042. }
  5043. //-----------------------------------------------------------------------------
  5044. // AEInteractiveThreadProc
  5045. //
  5046. // The thread procedue to do interactive enrollment
  5047. //-----------------------------------------------------------------------------
  5048. DWORD WINAPI AEInteractiveThreadProc(LPVOID lpParameter)
  5049. {
  5050. BOOL fResult=FALSE;
  5051. AE_GENERAL_INFO *pAE_General_Info = NULL;
  5052. if(NULL==lpParameter)
  5053. return FALSE;
  5054. __try
  5055. {
  5056. pAE_General_Info=(AE_GENERAL_INFO *)lpParameter;
  5057. pAE_General_Info->fUIProcess=TRUE;
  5058. fResult = AEEnrollmentWalker(pAE_General_Info);
  5059. //show the summary page if not canceled
  5060. if(!AECancelled(pAE_General_Info->hCancelEvent))
  5061. {
  5062. AEDisplaySummaryPage(pAE_General_Info);
  5063. }
  5064. //signal that the process is completed
  5065. SetEvent(pAE_General_Info->hCompleteEvent);
  5066. //signal the progress window that we are done
  5067. if(pAE_General_Info->hwndDlg)
  5068. {
  5069. //click the close button
  5070. SendMessage(pAE_General_Info->hwndDlg,
  5071. WM_CLOSE, //WM_COMMAND,
  5072. 0, //IDC_BUTTON1,
  5073. NULL);
  5074. }
  5075. }
  5076. __except ( EXCEPTION_EXECUTE_HANDLER )
  5077. {
  5078. }
  5079. return fResult;
  5080. }
  5081. //-----------------------------------------------------------------------------
  5082. // AEInteractiveEnrollment
  5083. //
  5084. // We are doing interactive enrollment
  5085. //-----------------------------------------------------------------------------
  5086. BOOL AEInteractiveEnrollment(AE_GENERAL_INFO *pAE_General_Info)
  5087. {
  5088. DWORD dwThreadID=0;
  5089. BOOL fResult=FALSE;
  5090. //create a notification event for cancel process
  5091. pAE_General_Info->hCancelEvent=CreateEvent(
  5092. NULL,
  5093. TRUE, // bmanual reset type
  5094. FALSE, // initial state
  5095. NULL);
  5096. if(NULL==(pAE_General_Info->hCancelEvent))
  5097. goto ret;
  5098. //create a notification event for complete process
  5099. pAE_General_Info->hCompleteEvent=CreateEvent(
  5100. NULL,
  5101. TRUE, // bmanual reset type
  5102. FALSE, // initial state
  5103. NULL);
  5104. if(NULL==(pAE_General_Info->hCompleteEvent))
  5105. goto ret;
  5106. //spawn a thread
  5107. pAE_General_Info->hThread = CreateThread(NULL,
  5108. 0,
  5109. AEInteractiveThreadProc,
  5110. pAE_General_Info,
  5111. CREATE_SUSPENDED, //suspend execution
  5112. &dwThreadID);
  5113. if(NULL==(pAE_General_Info->hThread))
  5114. goto ret;
  5115. //create the dialogue
  5116. DialogBoxParam(
  5117. g_hmodThisDll,
  5118. MAKEINTRESOURCE(IDD_USER_AUTOENROLL_GENERAL_DLG),
  5119. pAE_General_Info->hwndParent,
  5120. progressDlgProc,
  5121. (LPARAM)(pAE_General_Info));
  5122. //wait for thread to finish
  5123. if(WAIT_FAILED == WaitForSingleObject(pAE_General_Info->hThread, INFINITE))
  5124. goto ret;
  5125. fResult=TRUE;
  5126. ret:
  5127. //log the event
  5128. if(!fResult)
  5129. {
  5130. AELogAutoEnrollmentEvent(
  5131. pAE_General_Info->dwLogLevel,
  5132. TRUE,
  5133. HRESULT_FROM_WIN32(GetLastError()),
  5134. EVENT_FAIL_INTERACTIVE_START,
  5135. pAE_General_Info->fMachine,
  5136. pAE_General_Info->hToken,
  5137. 0);
  5138. }
  5139. return fResult;
  5140. }
  5141. //-----------------------------------------------------------------------------
  5142. //
  5143. // WinProc for the confirmation to start certificate autoenrollment
  5144. //
  5145. //-----------------------------------------------------------------------------
  5146. INT_PTR CALLBACK AEConfirmDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  5147. {
  5148. switch (msg)
  5149. {
  5150. case WM_INITDIALOG:
  5151. return TRUE;
  5152. break;
  5153. case WM_NOTIFY:
  5154. break;
  5155. case WM_CLOSE:
  5156. EndDialog(hwndDlg, IDC_BUTTON2);
  5157. return TRUE;
  5158. break;
  5159. case WM_COMMAND:
  5160. switch (LOWORD(wParam))
  5161. {
  5162. case IDC_BUTTON1:
  5163. EndDialog(hwndDlg, IDC_BUTTON1);
  5164. return TRUE;
  5165. case IDC_BUTTON2:
  5166. EndDialog(hwndDlg, IDC_BUTTON2);
  5167. return TRUE;
  5168. }
  5169. break;
  5170. default:
  5171. return FALSE;
  5172. }
  5173. return FALSE;
  5174. }
  5175. //-----------------------------------------------------------------------
  5176. //
  5177. // AERegisterSysTrayApp
  5178. //
  5179. // This functin registers autoenrollment in the sys tray area
  5180. // as an notification
  5181. //
  5182. //
  5183. //-----------------------------------------------------------------------
  5184. BOOL AERegisterSysTrayApp(HWND hwndParent)
  5185. {
  5186. BOOL fResult=FALSE;
  5187. BOOL fInit=FALSE;
  5188. INT_PTR ret=0;
  5189. DWORD dwError=0;
  5190. CQueryContinue *pCQueryContinue=NULL;
  5191. if(FAILED(CoInitialize(NULL)))
  5192. goto Ret;
  5193. fInit=TRUE;
  5194. pCQueryContinue=new CQueryContinue();
  5195. if(NULL==pCQueryContinue)
  5196. goto Ret;
  5197. if(S_OK != pCQueryContinue->DoBalloon())
  5198. goto Ret;
  5199. //ask user if autoenrollment should be performed
  5200. ret=DialogBox(g_hmodThisDll,
  5201. (LPCWSTR)MAKEINTRESOURCE(IDD_USER_AUTOENROLL_INFO_DLG),
  5202. hwndParent,
  5203. AEConfirmDlgProc);
  5204. if(IDC_BUTTON1 != ret)
  5205. {
  5206. dwError=GetLastError();
  5207. goto Ret;
  5208. }
  5209. fResult=TRUE;
  5210. Ret:
  5211. if(pCQueryContinue)
  5212. {
  5213. delete pCQueryContinue;
  5214. }
  5215. if(fInit)
  5216. CoUninitialize();
  5217. return fResult;
  5218. }
  5219. //-----------------------------------------------------------------------
  5220. //
  5221. // AEUIDisabled
  5222. //
  5223. // Detect if the user notification balloon is disabled by user
  5224. // setting the autoenrollment registry key in current user
  5225. //
  5226. //
  5227. //-----------------------------------------------------------------------
  5228. BOOL AEUIDisabled()
  5229. {
  5230. BOOL fResult=FALSE;
  5231. HKEY hKey=NULL;
  5232. if(ERROR_SUCCESS == RegOpenKeyEx(
  5233. HKEY_CURRENT_USER, // handle to open key
  5234. AUTO_ENROLLMENT_DISABLE_KEY, // subkey name
  5235. 0, // reserved
  5236. KEY_READ, // security access mask
  5237. &hKey)) // handle to open key
  5238. {
  5239. fResult=TRUE;
  5240. }
  5241. if(hKey)
  5242. RegCloseKey(hKey);
  5243. return fResult;
  5244. }
  5245. //-----------------------------------------------------------------------
  5246. //
  5247. // AEUIRequired
  5248. //
  5249. // Detect if the user notification balloon is needed
  5250. //
  5251. //
  5252. //-----------------------------------------------------------------------
  5253. BOOL AEUIRequired(AE_GENERAL_INFO *pAE_General_Info)
  5254. {
  5255. BOOL fUI=FALSE;
  5256. AE_CERTTYPE_INFO *rgCertTypeInfo = NULL;
  5257. DWORD dwIndex = 0;
  5258. if(NULL==pAE_General_Info)
  5259. return FALSE;
  5260. rgCertTypeInfo = pAE_General_Info->rgCertTypeInfo;
  5261. pAE_General_Info->dwUIEnrollCount=0;
  5262. if(NULL == rgCertTypeInfo)
  5263. return FALSE;
  5264. for(dwIndex=0; dwIndex < pAE_General_Info->dwCertType; dwIndex++)
  5265. {
  5266. if(rgCertTypeInfo[dwIndex].fUIActive)
  5267. {
  5268. if(CERT_REQUEST_STATUS_ACTIVE == rgCertTypeInfo[dwIndex].dwStatus)
  5269. {
  5270. fUI=TRUE;
  5271. (pAE_General_Info->dwUIEnrollCount)++;
  5272. }
  5273. }
  5274. }
  5275. //add the pending count
  5276. if(pAE_General_Info->dwUIPendCount)
  5277. {
  5278. fUI=TRUE;
  5279. (pAE_General_Info->dwUIEnrollCount) +=(pAE_General_Info->dwUIPendCount);
  5280. }
  5281. return fUI;
  5282. }
  5283. //-----------------------------------------------------------------------
  5284. //
  5285. // AEProcessEnrollment
  5286. //
  5287. // This functin does the autoenrollment based on ACL and manage MY
  5288. // store.
  5289. //
  5290. //
  5291. //-----------------------------------------------------------------------
  5292. BOOL AEProcessEnrollment(HWND hwndParent, BOOL fMachine, LDAP *pld, DWORD dwPolicy, DWORD dwLogLevel)
  5293. {
  5294. BOOL fResult=FALSE;
  5295. AE_GENERAL_INFO *pAE_General_Info=NULL;
  5296. pAE_General_Info=(AE_GENERAL_INFO *)LocalAlloc(LPTR, sizeof(AE_GENERAL_INFO));
  5297. if(NULL==pAE_General_Info)
  5298. goto Ret;
  5299. memset(pAE_General_Info, 0, sizeof(AE_GENERAL_INFO));
  5300. if(NULL==pld)
  5301. goto Ret;
  5302. //we obtain all information needed for process enrollment
  5303. pAE_General_Info->hwndParent = hwndParent;
  5304. pAE_General_Info->pld = pld;
  5305. pAE_General_Info->fMachine = fMachine;
  5306. pAE_General_Info->dwPolicy = dwPolicy;
  5307. pAE_General_Info->dwLogLevel = dwLogLevel;
  5308. __try
  5309. {
  5310. if(!AERetrieveGeneralInfo(pAE_General_Info))
  5311. {
  5312. AELogAutoEnrollmentEvent(dwLogLevel,
  5313. TRUE,
  5314. HRESULT_FROM_WIN32(GetLastError()),
  5315. EVENT_FAIL_GENERAL_INFOMATION,
  5316. fMachine,
  5317. pAE_General_Info->hToken,
  5318. 0);
  5319. goto Ret;
  5320. }
  5321. if((0 == pAE_General_Info->dwCertType) || (NULL==pAE_General_Info->rgCertTypeInfo))
  5322. {
  5323. AELogAutoEnrollmentEvent(dwLogLevel, FALSE, S_OK,
  5324. EVENT_NO_CERT_TEMPLATE, fMachine, pAE_General_Info->hToken,0);
  5325. AE_DEBUG((AE_WARNING, L"No CertType's available for auto-enrollment\n\r"));
  5326. goto Ret;
  5327. }
  5328. //we build the auto-enrollment requests based on the ACL on the DS
  5329. if(AUTO_ENROLLMENT_ENABLE_TEMPLATE_CHECK & (pAE_General_Info->dwPolicy))
  5330. {
  5331. if(!AEMarkAutoenrollment(pAE_General_Info))
  5332. goto Ret;
  5333. }
  5334. //we build the auto-enrollment requests based on the ARCS store
  5335. //this is enabled by default and can only be disabled if autoenrollment is
  5336. //completely disabled
  5337. if(!AEMarkAEObject(pAE_General_Info))
  5338. goto Ret;
  5339. //manage MY store. Check if we already have required certificates
  5340. //we should always check my store with different behavior based on
  5341. //AUTO_ENROLLMENT_ENABLE_MY_STORE_MANAGEMENT flag
  5342. if(!AEManageAndMarkMyStore(pAE_General_Info))
  5343. goto Ret;
  5344. //manage UserDS store for user autoenrollment
  5345. if(!fMachine)
  5346. {
  5347. if(!AECheckUserDSStore(pAE_General_Info))
  5348. goto Ret;
  5349. }
  5350. //manage pending request store. Remove expired pending requests
  5351. if(AUTO_ENROLLMENT_ENABLE_PENDING_FETCH & (pAE_General_Info->dwPolicy))
  5352. {
  5353. if(!AECheckPendingRequests(pAE_General_Info))
  5354. goto Ret;
  5355. }
  5356. //get CA information
  5357. if(!AERetrieveCAInfo(pAE_General_Info->pld,
  5358. pAE_General_Info->fMachine,
  5359. pAE_General_Info->hToken,
  5360. &(pAE_General_Info->dwCA),
  5361. &(pAE_General_Info->rgCAInfo)))
  5362. {
  5363. AELogAutoEnrollmentEvent(dwLogLevel, TRUE, HRESULT_FROM_WIN32(GetLastError()),
  5364. EVENT_FAIL_CA_INFORMATION, fMachine, pAE_General_Info->hToken, 0);
  5365. AE_DEBUG((AE_ERROR, L"Unable to retrieve CA information (%lx)\n\r", GetLastError()));
  5366. goto Ret;
  5367. }
  5368. if((0 == pAE_General_Info->dwCA) || (NULL==pAE_General_Info->rgCAInfo))
  5369. {
  5370. //we do not have any CAs on the domain. All we need to do is to archive
  5371. //archive old certificate after the enrollment/renewal
  5372. AEArchiveObsoleteCertificates(pAE_General_Info);
  5373. AELogAutoEnrollmentEvent(dwLogLevel, FALSE, S_OK,
  5374. EVENT_NO_CA, fMachine, pAE_General_Info->hToken, 0);
  5375. AE_DEBUG((AE_WARNING, L"No CA's available for auto-enrollment\n\r"));
  5376. goto Ret;
  5377. }
  5378. //we check if active templates do have a CA that we can enroll for
  5379. if(!AEManageActiveTemplates(pAE_General_Info))
  5380. goto Ret;
  5381. //perform autoenrollment as the background
  5382. pAE_General_Info->fUIProcess=FALSE;
  5383. if(!AEEnrollmentWalker(pAE_General_Info))
  5384. goto Ret;
  5385. //perform autoenrollment as a sys tray application for user only
  5386. if(FALSE == fMachine)
  5387. {
  5388. //test if the notification balloon is disabled
  5389. if(!AEUIDisabled())
  5390. {
  5391. //test if the notification balloon is needed
  5392. if(AEUIRequired(pAE_General_Info))
  5393. {
  5394. //register the sys tray application
  5395. if(AERegisterSysTrayApp(pAE_General_Info->hwndParent))
  5396. {
  5397. //perform autoenrollment in interactive mode
  5398. AEInteractiveEnrollment(pAE_General_Info);
  5399. }
  5400. }
  5401. }
  5402. }
  5403. //archive old certificate after the enrollment/renewal
  5404. if(!AEArchiveObsoleteCertificates(pAE_General_Info))
  5405. goto Ret;
  5406. }
  5407. __except ( EXCEPTION_EXECUTE_HANDLER )
  5408. {
  5409. goto Ret;
  5410. }
  5411. fResult=TRUE;
  5412. Ret:
  5413. //free memory only if no thread is created
  5414. if(pAE_General_Info)
  5415. {
  5416. AEFreeGeneralInfo(pAE_General_Info);
  5417. LocalFree(pAE_General_Info);
  5418. }
  5419. return fResult;
  5420. }
  5421. //-----------------------------------------------------------------------
  5422. //
  5423. // AEExpress
  5424. //
  5425. // Detect if the user autoenrollment has the express key set. If the
  5426. // Express key is set, user autoenrollment will not wait for machine
  5427. // autoenrollment to complete on root certificates download
  5428. //
  5429. //
  5430. //-----------------------------------------------------------------------
  5431. BOOL AEExpress()
  5432. {
  5433. BOOL fResult=FALSE;
  5434. HKEY hKey=NULL;
  5435. if(ERROR_SUCCESS == RegOpenKeyEx(
  5436. HKEY_CURRENT_USER, // handle to open key
  5437. AUTO_ENROLLMENT_EXPRESS_KEY, // subkey name
  5438. 0, // reserved
  5439. KEY_READ, // security access mask
  5440. &hKey)) // handle to open key
  5441. {
  5442. fResult=TRUE;
  5443. }
  5444. if(hKey)
  5445. RegCloseKey(hKey);
  5446. return fResult;
  5447. }
  5448. //-----------------------------------------------------------------------
  5449. //
  5450. // AEMainThreadProc
  5451. //
  5452. // The background thread for non-blocking autoenrollment background
  5453. // processing.
  5454. //
  5455. //-----------------------------------------------------------------------
  5456. DWORD WINAPI AEMainThreadProc(LPVOID lpParameter)
  5457. {
  5458. HRESULT hr=S_OK;
  5459. BOOL fMachine=FALSE;
  5460. DWORD dwPolicy=0;
  5461. DWORD dwLogLevel=STATUS_SEVERITY_ERROR;
  5462. HWND hwndParent=0;
  5463. DWORD dwStatus=0;
  5464. LARGE_INTEGER ftPreTimeStamp;
  5465. LARGE_INTEGER ftPostTimeStamp;
  5466. BOOL fNeedToSetupTimer=FALSE;
  5467. LDAP *pld = NULL;
  5468. LPWSTR pwszDCName=NULL;
  5469. //get the system time stamp
  5470. GetSystemTimeAsFileTime((LPFILETIME)&ftPreTimeStamp);
  5471. //the two input parameters are not yet used
  5472. if(NULL==lpParameter)
  5473. goto CommonReturn;
  5474. hwndParent = ((AE_MAIN_THREAD_INFO *)lpParameter)->hwndParent;
  5475. dwStatus = ((AE_MAIN_THREAD_INFO *)lpParameter)->dwStatus;
  5476. AE_DEBUG((AE_INFO, L"Beginning CertAutoEnrollment(%s).\n", (CERT_AUTO_ENROLLMENT_START_UP==dwStatus?L"START_UP":L"WAKE_UP")));
  5477. //no autoenrollment in the safe boot mode
  5478. //no autoenrollment if we are not in a domain
  5479. if(AEInSafeBoot() || !AEIsDomainMember())
  5480. goto CommonReturn;
  5481. //we need to set up the timer
  5482. fNeedToSetupTimer=TRUE;
  5483. //detect if we are running under user or machine context
  5484. if(!AEIsLocalSystem(&fMachine))
  5485. goto CommonReturn;
  5486. AE_DEBUG((AE_INFO, L"CertAutoEnrollment running as %s.\n", (fMachine?L"machine":L"user")));
  5487. AESetWakeUpFlag(fMachine, TRUE);
  5488. //we wait for 70 seconds for user case to give enough time for
  5489. //machine autoenrollment to complete, which will download certificates
  5490. //from the directory
  5491. if(!fMachine)
  5492. {
  5493. if(!AEExpress())
  5494. {
  5495. Sleep(USER_AUTOENROLL_DELAY_FOR_MACHINE * 1000);
  5496. }
  5497. }
  5498. //get the autoenrollment log level
  5499. if(!AERetrieveLogLevel(fMachine, &dwLogLevel))
  5500. goto CommonReturn;
  5501. //log the autoenrollment start event
  5502. AELogAutoEnrollmentEvent(dwLogLevel, FALSE, S_OK, EVENT_AUTOENROLL_START, fMachine, NULL, 0);
  5503. //get the autoenrollment policy flag
  5504. if(!AEGetPolicyFlag(fMachine, &dwPolicy))
  5505. goto CommonReturn;
  5506. //no need to do anything if autoenrollment is completely disabled
  5507. if(AUTO_ENROLLMENT_DISABLE_ALL & dwPolicy)
  5508. goto CommonReturn;
  5509. //download NTAuth And Enterprise root store for machine
  5510. if(fMachine)
  5511. {
  5512. //bind to the DS
  5513. if(S_OK != (hr=AERobustLdapBind(&pld, &pwszDCName)))
  5514. {
  5515. SetLastError(hr);
  5516. AELogAutoEnrollmentEvent(dwLogLevel, TRUE, hr, EVENT_FAIL_BIND_TO_DS, fMachine, NULL, 0);
  5517. goto CommonReturn;
  5518. }
  5519. AEDownloadStore(pld, pwszDCName);
  5520. }
  5521. //if we are required to do a WIN2K style autoenrollment, and the machine/user's
  5522. //ACRS store is empty, just return as we done.
  5523. if(0 == dwPolicy)
  5524. {
  5525. if(IsACRSStoreEmpty(fMachine))
  5526. goto CommonReturn;
  5527. }
  5528. if(NULL==pld)
  5529. {
  5530. //bind to the DS
  5531. if(S_OK != (hr=AERobustLdapBind(&pld, NULL)))
  5532. {
  5533. SetLastError(hr);
  5534. AELogAutoEnrollmentEvent(dwLogLevel, TRUE, hr, EVENT_FAIL_BIND_TO_DS, fMachine, NULL, 0);
  5535. goto CommonReturn;
  5536. }
  5537. }
  5538. AEProcessEnrollment(hwndParent, fMachine, pld, dwPolicy, dwLogLevel);
  5539. CommonReturn:
  5540. //get the system time
  5541. GetSystemTimeAsFileTime((LPFILETIME)&ftPostTimeStamp);
  5542. //set up the timer for next time
  5543. if(TRUE == fNeedToSetupTimer)
  5544. {
  5545. // we will need to do this again in a few hours.
  5546. AESetWakeUpTimer(fMachine, &ftPreTimeStamp, &ftPostTimeStamp);
  5547. }
  5548. if(pld)
  5549. ldap_unbind(pld);
  5550. if(pwszDCName)
  5551. LocalFree(pwszDCName);
  5552. if(lpParameter)
  5553. LocalFree((HLOCAL)lpParameter);
  5554. AELogAutoEnrollmentEvent(dwLogLevel, FALSE, S_OK, EVENT_AUTOENROLL_COMPLETE, fMachine, NULL, 0);
  5555. return TRUE;
  5556. }
  5557. //--------------------------------------------------------------------------
  5558. //
  5559. // CertAutoEnrollment
  5560. //
  5561. // Function to perform autoenrollment actions. It creates a working
  5562. // thread and return immediately so that it is non-blocking.
  5563. //
  5564. // Parameters:
  5565. // IN hwndParent: The parent window
  5566. // IN dwStatus: The status under which the function is called.
  5567. // It can be one of the following:
  5568. // CERT_AUTO_ENROLLMENT_START_UP
  5569. // CERT_AUTO_ENROLLMENT_WAKE_UP
  5570. //
  5571. //--------------------------------------------------------------------------
  5572. HANDLE
  5573. WINAPI
  5574. CertAutoEnrollment(IN HWND hwndParent,
  5575. IN DWORD dwStatus)
  5576. {
  5577. DWORD dwThreadID=0;
  5578. //memory will be freed in the main thread
  5579. AE_MAIN_THREAD_INFO *pAE_Main_Thread_Info=NULL;
  5580. HANDLE hThread=NULL;
  5581. pAE_Main_Thread_Info=(AE_MAIN_THREAD_INFO *)LocalAlloc(LPTR, sizeof(AE_MAIN_THREAD_INFO));
  5582. if(NULL==pAE_Main_Thread_Info)
  5583. return NULL;
  5584. memset(pAE_Main_Thread_Info, 0, sizeof(AE_MAIN_THREAD_INFO));
  5585. pAE_Main_Thread_Info->hwndParent=hwndParent;
  5586. pAE_Main_Thread_Info->dwStatus=dwStatus;
  5587. hThread = CreateThread(NULL,
  5588. 0,
  5589. AEMainThreadProc,
  5590. pAE_Main_Thread_Info,
  5591. 0, //execute immediately
  5592. &dwThreadID);
  5593. //set the thread priority to low so that we will not compete with the shell
  5594. SetThreadPriority(hThread, THREAD_PRIORITY_BELOW_NORMAL);
  5595. return hThread;
  5596. }
  5597. //--------------------------------------------------------------------
  5598. //
  5599. // AERetrieveClientToken
  5600. //
  5601. //--------------------------------------------------------------------
  5602. BOOL AERetrieveClientToken(HANDLE *phToken)
  5603. {
  5604. HRESULT hr = S_OK;
  5605. HANDLE hHandle = NULL;
  5606. HANDLE hClientToken = NULL;
  5607. hHandle = GetCurrentThread();
  5608. if (NULL == hHandle)
  5609. {
  5610. hr = HRESULT_FROM_WIN32(GetLastError());
  5611. }
  5612. else
  5613. {
  5614. if (!OpenThreadToken(hHandle,
  5615. TOKEN_QUERY,
  5616. TRUE, // open as self
  5617. &hClientToken))
  5618. {
  5619. hr = HRESULT_FROM_WIN32(GetLastError());
  5620. CloseHandle(hHandle);
  5621. hHandle = NULL;
  5622. }
  5623. }
  5624. if(hr != S_OK)
  5625. {
  5626. hHandle = GetCurrentProcess();
  5627. if (NULL == hHandle)
  5628. {
  5629. hr = HRESULT_FROM_WIN32(GetLastError());
  5630. }
  5631. else
  5632. {
  5633. HANDLE hProcessToken = NULL;
  5634. hr = S_OK;
  5635. if (!OpenProcessToken(hHandle,
  5636. TOKEN_DUPLICATE,
  5637. &hProcessToken))
  5638. {
  5639. hr = HRESULT_FROM_WIN32(GetLastError());
  5640. CloseHandle(hHandle);
  5641. hHandle = NULL;
  5642. }
  5643. else
  5644. {
  5645. if(!DuplicateToken(hProcessToken,
  5646. SecurityImpersonation,
  5647. &hClientToken))
  5648. {
  5649. hr = HRESULT_FROM_WIN32(GetLastError());
  5650. CloseHandle(hHandle);
  5651. hHandle = NULL;
  5652. }
  5653. CloseHandle(hProcessToken);
  5654. }
  5655. }
  5656. }
  5657. if(S_OK == hr)
  5658. *phToken = hClientToken;
  5659. if(hHandle)
  5660. CloseHandle(hHandle);
  5661. return (S_OK == hr);
  5662. }
  5663. //--------------------------------------------------------------------------
  5664. //
  5665. // AERetrieveGeneralInfo
  5666. //
  5667. //
  5668. //--------------------------------------------------------------------------
  5669. BOOL AERetrieveGeneralInfo(AE_GENERAL_INFO *pAE_General_Info)
  5670. {
  5671. BOOL fResult = FALSE;
  5672. DWORD dwOpenStoreFlags = CERT_SYSTEM_STORE_CURRENT_USER;
  5673. DWORD cMachineName = MAX_COMPUTERNAME_LENGTH + 2;
  5674. LONG dwResult = 0;
  5675. SCARDCONTEXT hSCContext=NULL;
  5676. //get the client token
  5677. if(pAE_General_Info->fMachine)
  5678. {
  5679. if(!AENetLogonUser(NULL, NULL, NULL, &(pAE_General_Info->hToken)))
  5680. {
  5681. AE_DEBUG((AE_ERROR, L"Obtain local system's token (%lx)\n\r", GetLastError()));
  5682. goto Ret;
  5683. }
  5684. }
  5685. else
  5686. {
  5687. if(!AERetrieveClientToken(&(pAE_General_Info->hToken)))
  5688. goto Ret;
  5689. }
  5690. //get the machine name
  5691. if (!GetComputerNameW(pAE_General_Info->wszMachineName,
  5692. &cMachineName))
  5693. goto Ret;
  5694. if(pAE_General_Info->fMachine)
  5695. dwOpenStoreFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
  5696. //open my store
  5697. if (NULL == (pAE_General_Info->hMyStore = CertOpenStore(
  5698. CERT_STORE_PROV_SYSTEM_W,
  5699. ENCODING_TYPE,
  5700. NULL,
  5701. dwOpenStoreFlags,
  5702. MY_STORE)))
  5703. {
  5704. AE_DEBUG((AE_ERROR, L"Unable to open MY store (%lx)\n\r", GetLastError()));
  5705. goto Ret;
  5706. }
  5707. if(!CertControlStore(pAE_General_Info->hMyStore,
  5708. 0,
  5709. CERT_STORE_CTRL_AUTO_RESYNC,
  5710. NULL))
  5711. {
  5712. AE_DEBUG((AE_ERROR, L"Unable configure MY store for auto-resync(%lx)\n\r", GetLastError()));
  5713. goto Ret;
  5714. }
  5715. //open request store
  5716. if (NULL == (pAE_General_Info->hRequestStore = CertOpenStore(
  5717. CERT_STORE_PROV_SYSTEM_W,
  5718. ENCODING_TYPE,
  5719. NULL,
  5720. dwOpenStoreFlags,
  5721. REQUEST_STORE)))
  5722. {
  5723. AE_DEBUG((AE_ERROR, L"Unable to open Request store (%lx)\n\r", GetLastError()));
  5724. goto Ret;
  5725. }
  5726. //get CertType information
  5727. if(!AERetrieveCertTypeInfo( pAE_General_Info->pld,
  5728. pAE_General_Info->fMachine,
  5729. &(pAE_General_Info->dwCertType),
  5730. &(pAE_General_Info->rgCertTypeInfo)))
  5731. {
  5732. AE_DEBUG((AE_ERROR, L"Unable to retrieve CertType information (%lx)\n\r", GetLastError()));
  5733. goto Ret;
  5734. }
  5735. //load xenroll module. No need to check errors since this is not a fatal error
  5736. pAE_General_Info->hXenroll = LoadLibrary(L"xenroll.dll");
  5737. //detect if the smart card subsystem if running for users only
  5738. if(FALSE == pAE_General_Info->fMachine)
  5739. {
  5740. dwResult = SCardEstablishContext(
  5741. SCARD_SCOPE_USER,
  5742. NULL,
  5743. NULL,
  5744. &hSCContext );
  5745. if((0 == dwResult) && (NULL != hSCContext))
  5746. pAE_General_Info->fSmartcardSystem=TRUE;
  5747. }
  5748. fResult = TRUE;
  5749. Ret:
  5750. if(hSCContext)
  5751. SCardReleaseContext(hSCContext);
  5752. if(FALSE == fResult)
  5753. AEFreeGeneralInfo(pAE_General_Info);
  5754. return fResult;
  5755. }
  5756. //--------------------------------------------------------------------------
  5757. //
  5758. // AEFreeGeneralInfo
  5759. //
  5760. //
  5761. //--------------------------------------------------------------------------
  5762. BOOL AEFreeGeneralInfo(AE_GENERAL_INFO *pAE_General_Info)
  5763. {
  5764. if(pAE_General_Info)
  5765. {
  5766. if(pAE_General_Info->hToken)
  5767. CloseHandle(pAE_General_Info->hToken);
  5768. if(pAE_General_Info->hMyStore)
  5769. CertCloseStore(pAE_General_Info->hMyStore, 0);
  5770. if(pAE_General_Info->hRequestStore)
  5771. CertCloseStore(pAE_General_Info->hRequestStore, 0);
  5772. //free CA information
  5773. AEFreeCAInfo(pAE_General_Info->dwCA, pAE_General_Info->rgCAInfo);
  5774. //free CertType information
  5775. AEFreeCertTypeInfo(pAE_General_Info->dwCertType, pAE_General_Info->rgCertTypeInfo);
  5776. if(pAE_General_Info->hXenroll)
  5777. FreeLibrary(pAE_General_Info->hXenroll);
  5778. if(pAE_General_Info->hCancelEvent)
  5779. CloseHandle(pAE_General_Info->hCancelEvent);
  5780. if(pAE_General_Info->hCompleteEvent)
  5781. CloseHandle(pAE_General_Info->hCompleteEvent);
  5782. if(pAE_General_Info->hThread)
  5783. CloseHandle(pAE_General_Info->hThread);
  5784. memset(pAE_General_Info, 0, sizeof(AE_GENERAL_INFO));
  5785. }
  5786. return TRUE;
  5787. }
  5788. //--------------------------------------------------------------------------
  5789. //
  5790. // AERetrieveCertTypeInfo
  5791. //
  5792. //--------------------------------------------------------------------------
  5793. BOOL AERetrieveCertTypeInfo(LDAP *pld, BOOL fMachine, DWORD *pdwCertType, AE_CERTTYPE_INFO **prgCertType)
  5794. {
  5795. BOOL fResult=FALSE;
  5796. DWORD dwCount=0;
  5797. DWORD dwCertType=0;
  5798. DWORD dwIndex=0;
  5799. HRESULT hr=E_FAIL;
  5800. HCERTTYPE hCTCurrent = NULL;
  5801. HCERTTYPE hCTNew = NULL;
  5802. AE_CERTTYPE_INFO *rgCertTypeInfo=NULL;
  5803. *pdwCertType=0;
  5804. *prgCertType=NULL;
  5805. if(S_OK != (hr = CAEnumCertTypesEx(
  5806. (LPCWSTR)pld,
  5807. fMachine?CT_ENUM_MACHINE_TYPES | CT_FIND_LOCAL_SYSTEM | CT_FLAG_SCOPE_IS_LDAP_HANDLE: CT_ENUM_USER_TYPES | CT_FLAG_SCOPE_IS_LDAP_HANDLE,
  5808. &hCTCurrent)))
  5809. {
  5810. SetLastError(hr);
  5811. goto Ret;
  5812. }
  5813. if((NULL == hCTCurrent) || (0 == (dwCount = CACountCertTypes(hCTCurrent))))
  5814. {
  5815. AE_DEBUG((AE_WARNING, L"No CT's available for auto-enrollment\n\r"));
  5816. fResult=TRUE;
  5817. goto Ret;
  5818. }
  5819. rgCertTypeInfo=(AE_CERTTYPE_INFO *)LocalAlloc(LPTR, sizeof(AE_CERTTYPE_INFO) * dwCount);
  5820. if(NULL==rgCertTypeInfo)
  5821. {
  5822. SetLastError(E_OUTOFMEMORY);
  5823. goto Ret;
  5824. }
  5825. memset(rgCertTypeInfo, 0, sizeof(AE_CERTTYPE_INFO) * dwCount);
  5826. for(dwIndex = 0; dwIndex < dwCount; dwIndex++ )
  5827. {
  5828. //check if we have a new certificate template
  5829. if(dwIndex > 0)
  5830. {
  5831. hr = CAEnumNextCertType(hCTCurrent, &hCTNew);
  5832. if((S_OK != hr) || (NULL == hCTNew))
  5833. {
  5834. // Clean up from previous calls
  5835. if(dwCertType < dwCount)
  5836. AEFreeCertTypeStruct(&(rgCertTypeInfo[dwCertType]));
  5837. break;
  5838. }
  5839. hCTCurrent = hCTNew;
  5840. }
  5841. // Clean up from previous calls
  5842. AEFreeCertTypeStruct(&(rgCertTypeInfo[dwCertType]));
  5843. //copy the new CertType' data
  5844. //hCertType
  5845. rgCertTypeInfo[dwCertType].hCertType = hCTCurrent;
  5846. //CTName
  5847. hr = CAGetCertTypePropertyEx(
  5848. hCTCurrent,
  5849. CERTTYPE_PROP_DN,
  5850. &(rgCertTypeInfo[dwCertType].awszName));
  5851. if((S_OK != hr) ||
  5852. (NULL == rgCertTypeInfo[dwCertType].awszName) ||
  5853. (NULL == (rgCertTypeInfo[dwCertType].awszName)[0])
  5854. )
  5855. {
  5856. AE_DEBUG((AE_INFO, L"No name property for CertType\n\r"));
  5857. continue;
  5858. }
  5859. //FriendlyName
  5860. hr = CAGetCertTypePropertyEx(
  5861. hCTCurrent,
  5862. CERTTYPE_PROP_FRIENDLY_NAME,
  5863. &(rgCertTypeInfo[dwCertType].awszDisplay));
  5864. if((S_OK != hr) ||
  5865. (NULL == rgCertTypeInfo[dwCertType].awszDisplay) ||
  5866. (NULL == (rgCertTypeInfo[dwCertType].awszDisplay)[0])
  5867. )
  5868. {
  5869. AE_DEBUG((AE_INFO, L"No display property for CertType\n\r"));
  5870. //get the DN as the display name
  5871. hr = CAGetCertTypePropertyEx(
  5872. hCTCurrent,
  5873. CERTTYPE_PROP_DN,
  5874. &(rgCertTypeInfo[dwCertType].awszDisplay));
  5875. if((S_OK != hr) ||
  5876. (NULL == rgCertTypeInfo[dwCertType].awszDisplay) ||
  5877. (NULL == (rgCertTypeInfo[dwCertType].awszDisplay)[0])
  5878. )
  5879. {
  5880. AE_DEBUG((AE_INFO, L"No name property for CertType\n\r"));
  5881. continue;
  5882. }
  5883. }
  5884. //dwSchemaVersion
  5885. hr = CAGetCertTypePropertyEx(
  5886. hCTCurrent,
  5887. CERTTYPE_PROP_SCHEMA_VERSION,
  5888. &(rgCertTypeInfo[dwCertType].dwSchemaVersion));
  5889. if(hr != S_OK)
  5890. {
  5891. AE_DEBUG((AE_INFO, L"No schema version for CT %ls\n\r", (rgCertTypeInfo[dwCertType].awszName)[0]));
  5892. continue;
  5893. }
  5894. //dwVersion
  5895. hr = CAGetCertTypePropertyEx(
  5896. hCTCurrent,
  5897. CERTTYPE_PROP_REVISION,
  5898. &(rgCertTypeInfo[dwCertType].dwVersion));
  5899. if(hr != S_OK)
  5900. {
  5901. AE_DEBUG((AE_INFO, L"No major version for CT %ls\n\r", (rgCertTypeInfo[dwCertType].awszName)[0]));
  5902. continue;
  5903. }
  5904. //dwEnrollmentFlag
  5905. hr = CAGetCertTypeFlagsEx(
  5906. hCTCurrent,
  5907. CERTTYPE_ENROLLMENT_FLAG,
  5908. &(rgCertTypeInfo[dwCertType].dwEnrollmentFlag));
  5909. if(hr != S_OK)
  5910. {
  5911. AE_DEBUG((AE_INFO, L"No enrollment flag for CT %ls\n\r", (rgCertTypeInfo[dwCertType].awszName)[0]));
  5912. continue;
  5913. }
  5914. //dwPrivatekeyFlag
  5915. hr = CAGetCertTypeFlagsEx(
  5916. hCTCurrent,
  5917. CERTTYPE_PRIVATE_KEY_FLAG,
  5918. &(rgCertTypeInfo[dwCertType].dwPrivateKeyFlag));
  5919. if(hr != S_OK)
  5920. {
  5921. AE_DEBUG((AE_INFO, L"No private key flag for CT %ls\n\r", (rgCertTypeInfo[dwCertType].awszName)[0]));
  5922. continue;
  5923. }
  5924. //expiration offset
  5925. hr = CAGetCertTypeExpiration(
  5926. hCTCurrent,
  5927. NULL,
  5928. (LPFILETIME)&(rgCertTypeInfo[dwCertType].ftExpirationOffset));
  5929. //we might not get the expiration date
  5930. if(hr != S_OK)
  5931. {
  5932. AE_DEBUG((AE_WARNING, L"Could not get cert type expirations: %ls\n\r", (rgCertTypeInfo[dwCertType].awszName)[0]));
  5933. }
  5934. //oid
  5935. hr = CAGetCertTypePropertyEx(
  5936. hCTCurrent,
  5937. CERTTYPE_PROP_OID,
  5938. &(rgCertTypeInfo[dwCertType].awszOID));
  5939. //we might not get the oid property
  5940. if(rgCertTypeInfo[dwCertType].dwSchemaVersion >= CERTTYPE_SCHEMA_VERSION_2)
  5941. {
  5942. if((S_OK != hr) ||
  5943. (NULL == rgCertTypeInfo[dwCertType].awszOID) ||
  5944. (NULL == (rgCertTypeInfo[dwCertType].awszOID)[0])
  5945. )
  5946. {
  5947. AE_DEBUG((AE_INFO, L"No oid for CT %ls\n\r", (rgCertTypeInfo[dwCertType].awszName)[0]));
  5948. continue;
  5949. }
  5950. }
  5951. //supersede
  5952. hr = CAGetCertTypePropertyEx(
  5953. hCTCurrent,
  5954. CERTTYPE_PROP_SUPERSEDE,
  5955. &(rgCertTypeInfo[dwCertType].awszSupersede));
  5956. //we might not get the supersede property
  5957. if(hr != S_OK)
  5958. {
  5959. AE_DEBUG((AE_INFO, L"No supersede for CT %ls\n\r", (rgCertTypeInfo[dwCertType].awszName)[0]));
  5960. }
  5961. //hArchiveStore
  5962. if(NULL == (rgCertTypeInfo[dwCertType].hArchiveStore=CertOpenStore(
  5963. CERT_STORE_PROV_MEMORY,
  5964. ENCODING_TYPE,
  5965. NULL,
  5966. 0,
  5967. NULL)))
  5968. {
  5969. AE_DEBUG((AE_INFO, L"Unable to open archive cert store for CT %ls\n\r", (rgCertTypeInfo[dwCertType].awszName)[0]));
  5970. continue;
  5971. }
  5972. //hObtainedStore
  5973. if(NULL == (rgCertTypeInfo[dwCertType].hObtainedStore=CertOpenStore(
  5974. CERT_STORE_PROV_MEMORY,
  5975. ENCODING_TYPE,
  5976. NULL,
  5977. 0,
  5978. NULL)))
  5979. {
  5980. AE_DEBUG((AE_INFO, L"Unable to open obtained cert store for CT %ls\n\r", (rgCertTypeInfo[dwCertType].awszName)[0]));
  5981. continue;
  5982. }
  5983. //hIssuedStore
  5984. if(NULL == (rgCertTypeInfo[dwCertType].hIssuedStore=CertOpenStore(
  5985. CERT_STORE_PROV_MEMORY,
  5986. ENCODING_TYPE,
  5987. NULL,
  5988. 0,
  5989. NULL)))
  5990. {
  5991. AE_DEBUG((AE_INFO, L"Unable to open issued cert store for CT %ls\n\r", (rgCertTypeInfo[dwCertType].awszName)[0]));
  5992. continue;
  5993. }
  5994. //allocate memory
  5995. rgCertTypeInfo[dwCertType].prgActive=(DWORD *)LocalAlloc(LPTR, sizeof(DWORD) * dwCount);
  5996. if(NULL == rgCertTypeInfo[dwCertType].prgActive)
  5997. {
  5998. AE_DEBUG((AE_INFO, L"Unable to allocate memory for CT %ls\n\r", (rgCertTypeInfo[dwCertType].awszName)[0]));
  5999. continue;
  6000. }
  6001. memset(rgCertTypeInfo[dwCertType].prgActive, 0, sizeof(DWORD) * dwCount);
  6002. dwCertType++;
  6003. }
  6004. *pdwCertType=dwCertType;
  6005. *prgCertType=rgCertTypeInfo;
  6006. fResult = TRUE;
  6007. Ret:
  6008. return fResult;
  6009. }
  6010. //--------------------------------------------------------------------------
  6011. //
  6012. // AEFreeCertTypeInfo
  6013. //
  6014. //
  6015. //--------------------------------------------------------------------------
  6016. BOOL AEFreeCertTypeInfo(DWORD dwCertType, AE_CERTTYPE_INFO *rgCertTypeInfo)
  6017. {
  6018. DWORD dwIndex=0;
  6019. if(rgCertTypeInfo)
  6020. {
  6021. for(dwIndex=0; dwIndex < dwCertType; dwIndex++)
  6022. AEFreeCertTypeStruct(&(rgCertTypeInfo[dwIndex]));
  6023. LocalFree(rgCertTypeInfo);
  6024. }
  6025. return TRUE;
  6026. }
  6027. //--------------------------------------------------------------------------
  6028. //
  6029. // AEFreeCertTypeStruct
  6030. //
  6031. //
  6032. //--------------------------------------------------------------------------
  6033. BOOL AEFreeCertTypeStruct(AE_CERTTYPE_INFO *pCertTypeInfo)
  6034. {
  6035. DWORD dwIndex=0;
  6036. if(pCertTypeInfo)
  6037. {
  6038. if(pCertTypeInfo->hCertType)
  6039. {
  6040. if(pCertTypeInfo->awszName)
  6041. CAFreeCertTypeProperty(pCertTypeInfo->hCertType, pCertTypeInfo->awszName);
  6042. if(pCertTypeInfo->awszDisplay)
  6043. CAFreeCertTypeProperty(pCertTypeInfo->hCertType, pCertTypeInfo->awszDisplay);
  6044. if(pCertTypeInfo->awszOID)
  6045. CAFreeCertTypeProperty(pCertTypeInfo->hCertType, pCertTypeInfo->awszOID);
  6046. if(pCertTypeInfo->awszSupersede)
  6047. CAFreeCertTypeProperty(pCertTypeInfo->hCertType, pCertTypeInfo->awszSupersede);
  6048. CACloseCertType(pCertTypeInfo->hCertType);
  6049. }
  6050. if(pCertTypeInfo->prgActive)
  6051. LocalFree(pCertTypeInfo->prgActive);
  6052. if(pCertTypeInfo->pOldCert)
  6053. CertFreeCertificateContext(pCertTypeInfo->pOldCert);
  6054. if(pCertTypeInfo->hArchiveStore)
  6055. CertCloseStore(pCertTypeInfo->hArchiveStore, 0);
  6056. if(pCertTypeInfo->hObtainedStore)
  6057. CertCloseStore(pCertTypeInfo->hObtainedStore, 0);
  6058. if(pCertTypeInfo->hIssuedStore)
  6059. CertCloseStore(pCertTypeInfo->hIssuedStore, 0);
  6060. if(pCertTypeInfo->dwPendCount)
  6061. {
  6062. if(pCertTypeInfo->rgPendInfo)
  6063. {
  6064. for(dwIndex=0; dwIndex < pCertTypeInfo->dwPendCount; dwIndex++)
  6065. {
  6066. if((pCertTypeInfo->rgPendInfo[dwIndex]).blobPKCS7.pbData)
  6067. LocalFree((pCertTypeInfo->rgPendInfo[dwIndex]).blobPKCS7.pbData);
  6068. if((pCertTypeInfo->rgPendInfo[dwIndex]).blobHash.pbData)
  6069. LocalFree((pCertTypeInfo->rgPendInfo[dwIndex]).blobHash.pbData);
  6070. }
  6071. LocalFree(pCertTypeInfo->rgPendInfo);
  6072. }
  6073. }
  6074. memset(pCertTypeInfo, 0, sizeof(AE_CERTTYPE_INFO));
  6075. }
  6076. return TRUE;
  6077. }
  6078. //--------------------------------------------------------------------------
  6079. //
  6080. // AERetrieveCAInfo
  6081. //
  6082. //
  6083. //--------------------------------------------------------------------------
  6084. BOOL AERetrieveCAInfo(LDAP *pld, BOOL fMachine, HANDLE hToken, DWORD *pdwCA, AE_CA_INFO **prgCAInfo)
  6085. {
  6086. BOOL fResult = FALSE;
  6087. DWORD dwCount=0;
  6088. DWORD dwCA=0;
  6089. DWORD dwIndex=0;
  6090. HRESULT hr=E_FAIL;
  6091. HCAINFO hCACurrent = NULL;
  6092. HCAINFO hCANew = NULL;
  6093. AE_CA_INFO *rgCAInfo=NULL;
  6094. *pdwCA=0;
  6095. *prgCAInfo=NULL;
  6096. if(S_OK != (hr = CAEnumFirstCA(
  6097. (LPCWSTR)pld,
  6098. CA_FLAG_SCOPE_IS_LDAP_HANDLE | (fMachine?CA_FIND_LOCAL_SYSTEM:0),
  6099. &hCACurrent)))
  6100. {
  6101. SetLastError(hr);
  6102. goto Ret;
  6103. }
  6104. if((NULL == hCACurrent) || (0 == (dwCount = CACountCAs(hCACurrent))))
  6105. {
  6106. AE_DEBUG((AE_WARNING, L"No CA's available for auto-enrollment\n\r"));
  6107. fResult=TRUE;
  6108. goto Ret;
  6109. }
  6110. rgCAInfo=(AE_CA_INFO *)LocalAlloc(LPTR, sizeof(AE_CA_INFO) * dwCount);
  6111. if(NULL==rgCAInfo)
  6112. {
  6113. SetLastError(E_OUTOFMEMORY);
  6114. goto Ret;
  6115. }
  6116. memset(rgCAInfo, 0, sizeof(AE_CA_INFO) * dwCount);
  6117. for(dwIndex = 0; dwIndex < dwCount; dwIndex++ )
  6118. {
  6119. //check if we have a new CA
  6120. if(dwIndex > 0)
  6121. {
  6122. hr = CAEnumNextCA(hCACurrent, &hCANew);
  6123. if((S_OK != hr) || (NULL == hCANew))
  6124. {
  6125. // Clean up from previous calls
  6126. if(dwCA < dwCount)
  6127. AEFreeCAStruct(&(rgCAInfo[dwCA]));
  6128. break;
  6129. }
  6130. hCACurrent = hCANew;
  6131. }
  6132. // Clean up from previous calls
  6133. AEFreeCAStruct(&(rgCAInfo[dwCA]));
  6134. //copy the new CA' data
  6135. //hCAInfo
  6136. rgCAInfo[dwCA].hCAInfo = hCACurrent;
  6137. //CAName
  6138. hr = CAGetCAProperty(hCACurrent,
  6139. CA_PROP_NAME,
  6140. &(rgCAInfo[dwCA].awszCAName));
  6141. if((S_OK != hr) ||
  6142. (NULL == rgCAInfo[dwCA].awszCAName) ||
  6143. (NULL == (rgCAInfo[dwCA].awszCAName)[0])
  6144. )
  6145. {
  6146. AE_DEBUG((AE_INFO, L"No name property for ca\n\r"));
  6147. continue;
  6148. }
  6149. //access check
  6150. if(S_OK != CAAccessCheckEx(rgCAInfo[dwCA].hCAInfo, hToken, CERTTYPE_ACCESS_CHECK_ENROLL | CERTTYPE_ACCESS_CHECK_NO_MAPPING))
  6151. {
  6152. AE_DEBUG((AE_INFO, L"No access for CA %ls\n\r", (rgCAInfo[dwCA].awszCAName)[0]));
  6153. continue;
  6154. }
  6155. //CA Display
  6156. hr = CAGetCAProperty(hCACurrent,
  6157. CA_PROP_DISPLAY_NAME,
  6158. &(rgCAInfo[dwCA].awszCADisplay));
  6159. if((S_OK != hr) ||
  6160. (NULL == rgCAInfo[dwCA].awszCADisplay) ||
  6161. (NULL == (rgCAInfo[dwCA].awszCADisplay)[0])
  6162. )
  6163. {
  6164. AE_DEBUG((AE_INFO, L"No display name property for ca\n\r"));
  6165. hr = CAGetCAProperty(hCACurrent,
  6166. CA_PROP_NAME,
  6167. &(rgCAInfo[dwCA].awszCADisplay));
  6168. if((S_OK != hr) ||
  6169. (NULL == rgCAInfo[dwCA].awszCADisplay) ||
  6170. (NULL == (rgCAInfo[dwCA].awszCADisplay)[0])
  6171. )
  6172. {
  6173. AE_DEBUG((AE_INFO, L"No name property for ca\n\r"));
  6174. continue;
  6175. }
  6176. }
  6177. //CADNS
  6178. hr = CAGetCAProperty(hCACurrent,
  6179. CA_PROP_DNSNAME,
  6180. &(rgCAInfo[dwCA].awszCADNS));
  6181. if((S_OK != hr) ||
  6182. (NULL == rgCAInfo[dwCA].awszCADNS) ||
  6183. (NULL == (rgCAInfo[dwCA].awszCADNS)[0])
  6184. )
  6185. {
  6186. AE_DEBUG((AE_INFO, L"No DNS property for CA %ls\n\r", (rgCAInfo[dwCA].awszCAName)[0]));
  6187. continue;
  6188. }
  6189. //CACertificateTemplate
  6190. hr = CAGetCAProperty(hCACurrent,
  6191. CA_PROP_CERT_TYPES,
  6192. &(rgCAInfo[dwCA].awszCertificateTemplate));
  6193. if((S_OK != hr) ||
  6194. (NULL == rgCAInfo[dwCA].awszCertificateTemplate) ||
  6195. (NULL == (rgCAInfo[dwCA].awszCertificateTemplate)[0])
  6196. )
  6197. {
  6198. AE_DEBUG((AE_INFO, L"No CertType property for CA %ls\n\r", (rgCAInfo[dwCA].awszCAName)[0]));
  6199. continue;
  6200. }
  6201. dwCA++;
  6202. }
  6203. *pdwCA=dwCA;
  6204. *prgCAInfo=rgCAInfo;
  6205. fResult = TRUE;
  6206. Ret:
  6207. return fResult;
  6208. }
  6209. //--------------------------------------------------------------------------
  6210. //
  6211. // AEFreeCAInfo
  6212. //
  6213. //
  6214. //--------------------------------------------------------------------------
  6215. BOOL AEFreeCAInfo(DWORD dwCA, AE_CA_INFO *rgCAInfo)
  6216. {
  6217. DWORD dwIndex=0;
  6218. if(rgCAInfo)
  6219. {
  6220. for(dwIndex=0; dwIndex < dwCA; dwIndex++)
  6221. AEFreeCAStruct(&(rgCAInfo[dwIndex]));
  6222. LocalFree(rgCAInfo);
  6223. }
  6224. return TRUE;
  6225. }
  6226. //--------------------------------------------------------------------------
  6227. //
  6228. // AEFreeCAStruct
  6229. //
  6230. //
  6231. //--------------------------------------------------------------------------
  6232. BOOL AEFreeCAStruct(AE_CA_INFO *pCAInfo)
  6233. {
  6234. if(pCAInfo)
  6235. {
  6236. if(pCAInfo->hCAInfo)
  6237. {
  6238. if(pCAInfo->awszCAName)
  6239. {
  6240. CAFreeCAProperty(pCAInfo->hCAInfo,pCAInfo->awszCAName);
  6241. }
  6242. if(pCAInfo->awszCADisplay)
  6243. {
  6244. CAFreeCAProperty(pCAInfo->hCAInfo,pCAInfo->awszCADisplay);
  6245. }
  6246. if(pCAInfo->awszCADNS)
  6247. {
  6248. CAFreeCAProperty(pCAInfo->hCAInfo, pCAInfo->awszCADNS);
  6249. }
  6250. if(pCAInfo->awszCertificateTemplate)
  6251. {
  6252. CAFreeCAProperty(pCAInfo->hCAInfo,pCAInfo->awszCertificateTemplate);
  6253. }
  6254. CACloseCA(pCAInfo->hCAInfo);
  6255. }
  6256. memset(pCAInfo, 0, sizeof(AE_CA_INFO));
  6257. }
  6258. return TRUE;
  6259. }
  6260. //--------------------------------------------------------------------------
  6261. //
  6262. // AEClearVistedFlag
  6263. //
  6264. //--------------------------------------------------------------------------
  6265. BOOL AEClearVistedFlag(AE_GENERAL_INFO *pAE_General_Info)
  6266. {
  6267. DWORD dwIndex=0;
  6268. if(pAE_General_Info)
  6269. {
  6270. if(pAE_General_Info->rgCertTypeInfo)
  6271. {
  6272. for(dwIndex=0; dwIndex < pAE_General_Info->dwCertType; dwIndex++)
  6273. {
  6274. (pAE_General_Info->rgCertTypeInfo)[dwIndex].fSupersedeVisited=FALSE;
  6275. }
  6276. }
  6277. }
  6278. return TRUE;
  6279. }
  6280. //--------------------------------------------------------------------------
  6281. //
  6282. // AEIfSupersede
  6283. //
  6284. // Recursively find if pwsz is superseded by one of the template in awsz.
  6285. // Notice that we should not loop in the superseding relationship.
  6286. // Superseding tree should be one directional tree without duplicated nodes.
  6287. //
  6288. //--------------------------------------------------------------------------
  6289. BOOL AEIfSupersede(LPWSTR pwsz, LPWSTR *awsz, AE_GENERAL_INFO *pAE_General_Info)
  6290. {
  6291. BOOL fResult = FALSE;
  6292. LPWSTR *pwszArray = awsz;
  6293. AE_TEMPLATE_INFO AETemplateInfo;
  6294. AE_CERTTYPE_INFO *pCertType = NULL;
  6295. LPWSTR *awszSupersede=NULL;
  6296. if((NULL==pwsz) || (NULL==awsz))
  6297. return FALSE;
  6298. while(*pwszArray)
  6299. {
  6300. if(0 == wcscmp(pwsz, *pwszArray))
  6301. {
  6302. fResult = TRUE;
  6303. break;
  6304. }
  6305. //find the template
  6306. memset(&AETemplateInfo, 0, sizeof(AE_TEMPLATE_INFO));
  6307. AETemplateInfo.pwszName=*pwszArray;
  6308. pCertType = AEFindTemplateInRequestTree(
  6309. &AETemplateInfo,
  6310. pAE_General_Info);
  6311. if(pCertType)
  6312. {
  6313. if(!(pCertType->fSupersedeVisited))
  6314. {
  6315. //mark that we have visited superseding relationship for this template
  6316. pCertType->fSupersedeVisited=TRUE;
  6317. if(S_OK == CAGetCertTypePropertyEx(
  6318. pCertType->hCertType,
  6319. CERTTYPE_PROP_SUPERSEDE,
  6320. &(awszSupersede)))
  6321. {
  6322. fResult = AEIfSupersede(pwsz, awszSupersede, pAE_General_Info);
  6323. if(awszSupersede)
  6324. CAFreeCertTypeProperty(
  6325. pCertType->hCertType,
  6326. awszSupersede);
  6327. awszSupersede=NULL;
  6328. if(TRUE == fResult)
  6329. break;
  6330. }
  6331. }
  6332. }
  6333. pwszArray++;
  6334. }
  6335. return fResult;
  6336. }
  6337. //--------------------------------------------------------------------------
  6338. //
  6339. // AEIsAnElement
  6340. //
  6341. //
  6342. //--------------------------------------------------------------------------
  6343. BOOL AEIsAnElement(LPWSTR pwsz, LPWSTR *awsz)
  6344. {
  6345. BOOL fResult = FALSE;
  6346. LPWSTR *pwszArray = awsz;
  6347. if((NULL==pwsz) || (NULL==awsz))
  6348. return FALSE;
  6349. while(*pwszArray)
  6350. {
  6351. if(0 == wcscmp(pwsz, *pwszArray))
  6352. {
  6353. fResult = TRUE;
  6354. break;
  6355. }
  6356. pwszArray++;
  6357. }
  6358. return fResult;
  6359. }
  6360. //--------------------------------------------------------------------------
  6361. //
  6362. // AECopyCertStore
  6363. //
  6364. //
  6365. //--------------------------------------------------------------------------
  6366. BOOL AECopyCertStore(HCERTSTORE hSrcStore,
  6367. HCERTSTORE hDesStore)
  6368. {
  6369. PCCERT_CONTEXT pCertContext=NULL;
  6370. if((NULL==hSrcStore) || (NULL==hDesStore))
  6371. return FALSE;
  6372. while(pCertContext = CertEnumCertificatesInStore(hSrcStore, pCertContext))
  6373. {
  6374. CertAddCertificateContextToStore(hDesStore,
  6375. pCertContext,
  6376. CERT_STORE_ADD_USE_EXISTING,
  6377. NULL);
  6378. }
  6379. return TRUE;
  6380. }
  6381. //--------------------------------------------------------------------------
  6382. //
  6383. // AEGetConfigDN
  6384. //
  6385. //
  6386. //--------------------------------------------------------------------------
  6387. HRESULT
  6388. AEGetConfigDN(
  6389. IN LDAP *pld,
  6390. OUT LPWSTR *pwszConfigDn
  6391. )
  6392. {
  6393. HRESULT hr;
  6394. ULONG LdapError;
  6395. LDAPMessage *SearchResult = NULL;
  6396. LDAPMessage *Entry = NULL;
  6397. WCHAR *Attr = NULL;
  6398. BerElement *BerElement;
  6399. WCHAR **Values = NULL;
  6400. WCHAR *AttrArray[3];
  6401. struct l_timeval timeout;
  6402. WCHAR *ConfigurationNamingContext = L"configurationNamingContext";
  6403. WCHAR *ObjectClassFilter = L"objectCategory=*";
  6404. //
  6405. // Set the out parameters to null
  6406. //
  6407. if(pwszConfigDn)
  6408. {
  6409. *pwszConfigDn = NULL;
  6410. }
  6411. timeout.tv_sec = 300;
  6412. timeout.tv_usec = 0;
  6413. //
  6414. // Query for the ldap server oerational attributes to obtain the default
  6415. // naming context.
  6416. //
  6417. AttrArray[0] = ConfigurationNamingContext;
  6418. AttrArray[1] = NULL; // this is the sentinel
  6419. LdapError = ldap_search_ext_s(pld,
  6420. NULL,
  6421. LDAP_SCOPE_BASE,
  6422. ObjectClassFilter,
  6423. AttrArray,
  6424. FALSE,
  6425. NULL,
  6426. NULL,
  6427. &timeout,
  6428. 10000,
  6429. &SearchResult);
  6430. hr = HRESULT_FROM_WIN32(LdapMapErrorToWin32(LdapError));
  6431. if (S_OK == hr)
  6432. {
  6433. Entry = ldap_first_entry(pld, SearchResult);
  6434. if (Entry)
  6435. {
  6436. Values = ldap_get_values(pld,
  6437. Entry,
  6438. ConfigurationNamingContext);
  6439. if (Values && Values[0])
  6440. {
  6441. (*pwszConfigDn) = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*(wcslen(Values[0])+1));
  6442. if(NULL==(*pwszConfigDn))
  6443. hr=E_OUTOFMEMORY;
  6444. else
  6445. wcscpy((*pwszConfigDn), Values[0]);
  6446. }
  6447. ldap_value_free(Values);
  6448. }
  6449. if (pwszConfigDn && (!(*pwszConfigDn)))
  6450. {
  6451. // We could not get the default domain or out of memory - bail out
  6452. if(E_OUTOFMEMORY != hr)
  6453. hr = HRESULT_FROM_WIN32(ERROR_CANT_ACCESS_DOMAIN_INFO);
  6454. }
  6455. if(SearchResult)
  6456. {
  6457. ldap_msgfree(SearchResult);
  6458. }
  6459. }
  6460. return hr;
  6461. }
  6462. //--------------------------------------------------------------------------
  6463. //
  6464. // AERobustLdapBind
  6465. //
  6466. //--------------------------------------------------------------------------
  6467. HRESULT
  6468. AERobustLdapBind(
  6469. OUT LDAP ** ppldap,
  6470. OUT LPWSTR *ppwszDCName)
  6471. {
  6472. DWORD dwErr = ERROR_SUCCESS;
  6473. HRESULT hr = S_OK;
  6474. BOOL fForceRediscovery = FALSE;
  6475. DWORD dwGetDCFlags = DS_RETURN_DNS_NAME | DS_BACKGROUND_ONLY;
  6476. PDOMAIN_CONTROLLER_INFO pDomainInfo = NULL;
  6477. LDAP *pld = NULL;
  6478. LPWSTR wszDomainControllerName = NULL;
  6479. ULONG ulOptions = 0;
  6480. ULONG ldaperr;
  6481. do {
  6482. if(fForceRediscovery)
  6483. {
  6484. dwGetDCFlags |= DS_FORCE_REDISCOVERY;
  6485. }
  6486. ldaperr = LDAP_SERVER_DOWN;
  6487. // Get the GC location
  6488. dwErr = DsGetDcNameW(NULL, // Delayload wrapped
  6489. NULL,
  6490. NULL,
  6491. NULL,
  6492. dwGetDCFlags,
  6493. &pDomainInfo);
  6494. if(dwErr != ERROR_SUCCESS)
  6495. {
  6496. hr = HRESULT_FROM_WIN32(dwErr);
  6497. goto error;
  6498. }
  6499. if((pDomainInfo == NULL) ||
  6500. ((pDomainInfo->Flags & DS_DNS_CONTROLLER_FLAG) == 0) ||
  6501. (pDomainInfo->DomainControllerName == NULL))
  6502. {
  6503. if(!fForceRediscovery)
  6504. {
  6505. fForceRediscovery = TRUE;
  6506. continue;
  6507. }
  6508. hr = HRESULT_FROM_WIN32(ERROR_CANT_ACCESS_DOMAIN_INFO);
  6509. goto error;
  6510. }
  6511. wszDomainControllerName = pDomainInfo->DomainControllerName;
  6512. // skip past forward slashes (why are they there?)
  6513. while(*wszDomainControllerName == L'\\')
  6514. {
  6515. wszDomainControllerName++;
  6516. }
  6517. // bind to ds
  6518. if((pld = ldap_initW(wszDomainControllerName, LDAP_PORT)) == NULL)
  6519. {
  6520. ldaperr = LdapGetLastError();
  6521. }
  6522. else
  6523. {
  6524. //reduce bogus DNS query
  6525. ulOptions = PtrToUlong(LDAP_OPT_ON);
  6526. (void)ldap_set_optionW(pld, LDAP_OPT_AREC_EXCLUSIVE, &ulOptions );
  6527. ldaperr = ldap_bind_sW(pld, NULL, NULL, LDAP_AUTH_NEGOTIATE);
  6528. }
  6529. hr = HRESULT_FROM_WIN32(LdapMapErrorToWin32(ldaperr));
  6530. if(fForceRediscovery)
  6531. {
  6532. break;
  6533. }
  6534. fForceRediscovery = TRUE;
  6535. } while(ldaperr == LDAP_SERVER_DOWN);
  6536. if(S_OK != hr)
  6537. goto error;
  6538. if(ppwszDCName)
  6539. {
  6540. *ppwszDCName=(LPWSTR)LocalAlloc(LPTR,
  6541. sizeof(WCHAR) * (wcslen(wszDomainControllerName) + 1));
  6542. if(NULL==*ppwszDCName)
  6543. {
  6544. hr=E_OUTOFMEMORY;
  6545. goto error;
  6546. }
  6547. wcscpy(*ppwszDCName, wszDomainControllerName);
  6548. }
  6549. *ppldap = pld;
  6550. pld = NULL;
  6551. hr=S_OK;
  6552. error:
  6553. if(pld)
  6554. {
  6555. ldap_unbind(pld);
  6556. }
  6557. if(pDomainInfo)
  6558. {
  6559. NetApiBufferFree(pDomainInfo);
  6560. }
  6561. return hr;
  6562. }
  6563. //---------------------------------------------------------------------------
  6564. //
  6565. // AEAllocAndCopy
  6566. //
  6567. //---------------------------------------------------------------------------
  6568. BOOL AEAllocAndCopy(LPWSTR pwszSrc, LPWSTR *ppwszDest)
  6569. {
  6570. if((NULL==ppwszDest) || (NULL==pwszSrc))
  6571. {
  6572. SetLastError(E_INVALIDARG);
  6573. return FALSE;
  6574. }
  6575. *ppwszDest=(LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * (wcslen(pwszSrc) + 1));
  6576. if(NULL==(*ppwszDest))
  6577. {
  6578. SetLastError(E_OUTOFMEMORY);
  6579. return FALSE;
  6580. }
  6581. wcscpy(*ppwszDest, pwszSrc);
  6582. return TRUE;
  6583. }
  6584. //--------------------------------------------------------------------------
  6585. // Name: AELogAutoEnrollmentEvent
  6586. //
  6587. // Description: This function registers an event in the event log of the
  6588. // local machine. Takes an optional argument list.
  6589. //
  6590. //--------------------------------------------------------------------------
  6591. void AELogAutoEnrollmentEvent(IN DWORD dwLogLevel,
  6592. IN BOOL fError,
  6593. IN HRESULT hr,
  6594. IN DWORD dwEventId,
  6595. IN BOOL fMachine,
  6596. IN HANDLE hToken,
  6597. IN DWORD dwParamCount,
  6598. ...
  6599. )
  6600. {
  6601. BYTE FastBuffer[MAX_DN_SIZE];
  6602. DWORD cbUser =0;
  6603. BOOL fAlloced = FALSE;
  6604. PSID pSID = NULL;
  6605. WORD dwEventType = 0;
  6606. LPWSTR awszStrings[PENDING_ALLOC_SIZE + 3];
  6607. WORD cStrings = 0;
  6608. LPWSTR wszString = NULL;
  6609. WCHAR wszMsg[MAX_DN_SIZE];
  6610. WCHAR wszUser[MAX_DN_SIZE];
  6611. DWORD dwIndex=0;
  6612. DWORD dwSize=0;
  6613. HANDLE hEventSource = NULL;
  6614. LPWSTR wszHR=NULL;
  6615. PTOKEN_USER ptgUser = NULL;
  6616. va_list ArgList;
  6617. //check the log level; log errors and success by default
  6618. if(((dwEventId >> 30) < dwLogLevel) && ((dwEventId >> 30) != STATUS_SEVERITY_SUCCESS))
  6619. return;
  6620. if(NULL==(hEventSource = RegisterEventSourceW(NULL, EVENT_AUTO_NAME)))
  6621. return;
  6622. //copy the user/machine string
  6623. wszUser[0]=L'\0';
  6624. //use the user name for user case
  6625. if(FALSE == fMachine)
  6626. {
  6627. dwSize=MAX_DN_SIZE;
  6628. if(!GetUserNameEx(
  6629. NameSamCompatible, // name format
  6630. wszUser, // name buffer
  6631. &dwSize)) // size of name buffer
  6632. {
  6633. LoadStringW(g_hmodThisDll, IDS_USER, wszUser, MAX_DN_SIZE);
  6634. }
  6635. }
  6636. else
  6637. {
  6638. LoadStringW(g_hmodThisDll, IDS_MACHINE, wszUser, MAX_DN_SIZE);
  6639. }
  6640. awszStrings[cStrings++] = wszUser;
  6641. //copy the variable strings if present
  6642. va_start(ArgList, dwParamCount);
  6643. for(dwIndex=0; dwIndex < dwParamCount; dwIndex++)
  6644. {
  6645. wszString = va_arg(ArgList, LPWSTR);
  6646. awszStrings[cStrings++] = wszString;
  6647. if(cStrings >= PENDING_ALLOC_SIZE)
  6648. {
  6649. break;
  6650. }
  6651. }
  6652. va_end(ArgList);
  6653. //copy the hr error code
  6654. if(fError)
  6655. {
  6656. if(S_OK == hr)
  6657. hr=E_FAIL;
  6658. wsprintfW(wszMsg, L"0x%lx", hr);
  6659. awszStrings[cStrings++] = wszMsg;
  6660. if(0 != FormatMessage(
  6661. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  6662. NULL,
  6663. hr,
  6664. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  6665. (WCHAR *)&wszHR,
  6666. 0,
  6667. NULL))
  6668. {
  6669. if(wszHR)
  6670. awszStrings[cStrings++] = wszHR;
  6671. }
  6672. }
  6673. // check if the token is non zero is so then impersonating so get the SID
  6674. if((FALSE == fMachine) && (hToken))
  6675. {
  6676. ptgUser = (PTOKEN_USER)FastBuffer; // try fast buffer first
  6677. cbUser = MAX_DN_SIZE;
  6678. if (!GetTokenInformation(
  6679. hToken, // identifies access token
  6680. TokenUser, // TokenUser info type
  6681. ptgUser, // retrieved info buffer
  6682. cbUser, // size of buffer passed-in
  6683. &cbUser // required buffer size
  6684. ))
  6685. {
  6686. if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  6687. {
  6688. if (NULL != (ptgUser = (PTOKEN_USER)LocalAlloc(LPTR, cbUser)))
  6689. {
  6690. fAlloced = TRUE;
  6691. // get the user info and assign the sid if able to
  6692. if (GetTokenInformation(
  6693. hToken, // identifies access token
  6694. TokenUser, // TokenUser info type
  6695. ptgUser, // retrieved info buffer
  6696. cbUser, // size of buffer passed-in
  6697. &cbUser // required buffer size
  6698. ))
  6699. {
  6700. pSID = ptgUser->User.Sid;
  6701. }
  6702. }
  6703. }
  6704. }
  6705. else
  6706. {
  6707. // assign the sid when fast buffer worked
  6708. pSID = ptgUser->User.Sid;
  6709. }
  6710. }
  6711. switch(dwEventId >> 30)
  6712. {
  6713. case 0:
  6714. dwEventType = EVENTLOG_SUCCESS;
  6715. break;
  6716. case 1:
  6717. dwEventType = EVENTLOG_INFORMATION_TYPE;
  6718. break;
  6719. case 2:
  6720. dwEventType = EVENTLOG_WARNING_TYPE;
  6721. break;
  6722. case 3:
  6723. dwEventType = EVENTLOG_ERROR_TYPE;
  6724. break;
  6725. }
  6726. ReportEventW(hEventSource, // handle of event source
  6727. dwEventType, // event type
  6728. 0, // event category
  6729. dwEventId, // event ID
  6730. pSID, // current user's SID
  6731. cStrings, // strings in lpszStrings
  6732. 0, // no bytes of raw data
  6733. (LPCWSTR*)awszStrings, // array of error strings
  6734. NULL // no raw data
  6735. );
  6736. if (hEventSource)
  6737. DeregisterEventSource(hEventSource);
  6738. if(fAlloced)
  6739. {
  6740. if(ptgUser)
  6741. LocalFree(ptgUser);
  6742. }
  6743. if(wszHR)
  6744. LocalFree(wszHR);
  6745. return;
  6746. }
  6747. //--------------------------------------------------------------------------
  6748. //
  6749. // FormatMessageUnicode
  6750. //
  6751. //--------------------------------------------------------------------------
  6752. BOOL FormatMessageUnicode(LPWSTR * ppwszFormat, UINT ids, ...)
  6753. {
  6754. // get format string from resources
  6755. WCHAR wszFormat[1000];
  6756. va_list argList;
  6757. DWORD cbMsg=0;
  6758. BOOL fResult=FALSE;
  6759. if(NULL == ppwszFormat)
  6760. goto Ret;
  6761. if(!LoadStringW(g_hmodThisDll, ids, wszFormat, sizeof(wszFormat) / sizeof(wszFormat[0])))
  6762. goto Ret;
  6763. // format message into requested buffer
  6764. va_start(argList, ids);
  6765. cbMsg = FormatMessageW(
  6766. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
  6767. wszFormat,
  6768. 0, // dwMessageId
  6769. 0, // dwLanguageId
  6770. (LPWSTR) (ppwszFormat),
  6771. 0, // minimum size to allocate
  6772. &argList);
  6773. va_end(argList);
  6774. if(!cbMsg)
  6775. goto Ret;
  6776. fResult=TRUE;
  6777. Ret:
  6778. return fResult;
  6779. }
  6780. //--------------------------------------------------------------------------
  6781. //
  6782. // AENetLogonUser
  6783. //
  6784. //Abstract:
  6785. //
  6786. // This module implements the network logon type by interfacing
  6787. // with the NT Lan Man Security Support Provider (NTLMSSP).
  6788. //
  6789. // If the logon succeds via the provided credentials, we duplicate
  6790. // the resultant Impersonation token to a Primary level token.
  6791. // This allows the result to be used in a call to CreateProcessAsUser
  6792. //
  6793. //Author:
  6794. //
  6795. // Scott Field (sfield) 09-Jun-96
  6796. //--------------------------------------------------------------------------
  6797. BOOL
  6798. AENetLogonUser(
  6799. LPTSTR UserName,
  6800. LPTSTR DomainName,
  6801. LPTSTR Password,
  6802. PHANDLE phToken
  6803. )
  6804. {
  6805. SECURITY_STATUS SecStatus;
  6806. CredHandle CredentialHandle1;
  6807. CredHandle CredentialHandle2;
  6808. CtxtHandle ClientContextHandle;
  6809. CtxtHandle ServerContextHandle;
  6810. SecPkgCredentials_Names sNames;
  6811. ULONG ContextAttributes;
  6812. ULONG PackageCount;
  6813. ULONG PackageIndex;
  6814. PSecPkgInfo PackageInfo;
  6815. DWORD cbMaxToken;
  6816. TimeStamp Lifetime;
  6817. SEC_WINNT_AUTH_IDENTITY AuthIdentity;
  6818. SecBufferDesc NegotiateDesc;
  6819. SecBuffer NegotiateBuffer;
  6820. SecBufferDesc ChallengeDesc;
  6821. SecBuffer ChallengeBuffer;
  6822. HANDLE hImpersonationToken;
  6823. BOOL bSuccess = FALSE ; // assume this function will fail
  6824. NegotiateBuffer.pvBuffer = NULL;
  6825. ChallengeBuffer.pvBuffer = NULL;
  6826. sNames.sUserName = NULL;
  6827. ClientContextHandle.dwUpper = -1;
  6828. ClientContextHandle.dwLower = -1;
  6829. ServerContextHandle.dwUpper = -1;
  6830. ServerContextHandle.dwLower = -1;
  6831. CredentialHandle1.dwUpper = -1;
  6832. CredentialHandle1.dwLower = -1;
  6833. CredentialHandle2.dwUpper = -1;
  6834. CredentialHandle2.dwLower = -1;
  6835. //
  6836. // << this section could be cached in a repeat caller scenario >>
  6837. //
  6838. //
  6839. // Get info about the security packages.
  6840. //
  6841. if(EnumerateSecurityPackages(
  6842. &PackageCount,
  6843. &PackageInfo
  6844. ) != NO_ERROR) return FALSE;
  6845. //
  6846. // loop through the packages looking for NTLM
  6847. //
  6848. for(PackageIndex = 0 ; PackageIndex < PackageCount ; PackageIndex++ ) {
  6849. if(PackageInfo[PackageIndex].Name != NULL) {
  6850. if(lstrcmpi(PackageInfo[PackageIndex].Name, MICROSOFT_KERBEROS_NAME) == 0) {
  6851. cbMaxToken = PackageInfo[PackageIndex].cbMaxToken;
  6852. bSuccess = TRUE;
  6853. break;
  6854. }
  6855. }
  6856. }
  6857. FreeContextBuffer( PackageInfo );
  6858. if(!bSuccess) return FALSE;
  6859. bSuccess = FALSE; // reset to assume failure
  6860. //
  6861. // << end of cached section >>
  6862. //
  6863. //
  6864. // Acquire a credential handle for the server side
  6865. //
  6866. SecStatus = AcquireCredentialsHandle(
  6867. NULL, // New principal
  6868. MICROSOFT_KERBEROS_NAME, // Package Name
  6869. SECPKG_CRED_INBOUND,
  6870. NULL,
  6871. NULL,
  6872. NULL,
  6873. NULL,
  6874. &CredentialHandle1,
  6875. &Lifetime
  6876. );
  6877. if ( SecStatus != NO_ERROR ) {
  6878. goto cleanup;
  6879. }
  6880. //
  6881. // Acquire a credential handle for the client side
  6882. //
  6883. ZeroMemory( &AuthIdentity, sizeof(AuthIdentity) );
  6884. if ( DomainName != NULL ) {
  6885. AuthIdentity.Domain = DomainName;
  6886. AuthIdentity.DomainLength = lstrlen(DomainName);
  6887. }
  6888. if ( UserName != NULL ) {
  6889. AuthIdentity.User = UserName;
  6890. AuthIdentity.UserLength = lstrlen(UserName);
  6891. }
  6892. if ( Password != NULL ) {
  6893. AuthIdentity.Password = Password;
  6894. AuthIdentity.PasswordLength = lstrlen(Password);
  6895. }
  6896. AuthIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  6897. SecStatus = AcquireCredentialsHandle(
  6898. NULL, // New principal
  6899. MICROSOFT_KERBEROS_NAME, // Package Name
  6900. SECPKG_CRED_OUTBOUND,
  6901. NULL,
  6902. (DomainName == NULL && UserName == NULL && Password == NULL) ?
  6903. NULL : &AuthIdentity,
  6904. NULL,
  6905. NULL,
  6906. &CredentialHandle2,
  6907. &Lifetime
  6908. );
  6909. if ( SecStatus != NO_ERROR ) {
  6910. goto cleanup;
  6911. }
  6912. SecStatus = QueryCredentialsAttributes(&CredentialHandle1, SECPKG_CRED_ATTR_NAMES, &sNames);
  6913. if ( SecStatus != NO_ERROR ) {
  6914. goto cleanup;
  6915. }
  6916. //
  6917. // Get the NegotiateMessage (ClientSide)
  6918. //
  6919. NegotiateDesc.ulVersion = 0;
  6920. NegotiateDesc.cBuffers = 1;
  6921. NegotiateDesc.pBuffers = &NegotiateBuffer;
  6922. NegotiateBuffer.cbBuffer = cbMaxToken;
  6923. NegotiateBuffer.BufferType = SECBUFFER_TOKEN;
  6924. NegotiateBuffer.pvBuffer = LocalAlloc( LMEM_FIXED, NegotiateBuffer.cbBuffer );
  6925. if ( NegotiateBuffer.pvBuffer == NULL ) {
  6926. goto cleanup;
  6927. }
  6928. SecStatus = InitializeSecurityContext(
  6929. &CredentialHandle2,
  6930. NULL, // No Client context yet
  6931. sNames.sUserName, // target name
  6932. ISC_REQ_SEQUENCE_DETECT,
  6933. 0, // Reserved 1
  6934. SECURITY_NATIVE_DREP,
  6935. NULL, // No initial input token
  6936. 0, // Reserved 2
  6937. &ClientContextHandle,
  6938. &NegotiateDesc,
  6939. &ContextAttributes,
  6940. &Lifetime
  6941. );
  6942. if(SecStatus != NO_ERROR)
  6943. {
  6944. goto cleanup;
  6945. }
  6946. //
  6947. // Get the ChallengeMessage (ServerSide)
  6948. //
  6949. NegotiateBuffer.BufferType |= SECBUFFER_READONLY;
  6950. ChallengeDesc.ulVersion = 0;
  6951. ChallengeDesc.cBuffers = 1;
  6952. ChallengeDesc.pBuffers = &ChallengeBuffer;
  6953. ChallengeBuffer.cbBuffer = cbMaxToken;
  6954. ChallengeBuffer.BufferType = SECBUFFER_TOKEN;
  6955. ChallengeBuffer.pvBuffer = LocalAlloc( LMEM_FIXED, ChallengeBuffer.cbBuffer );
  6956. if ( ChallengeBuffer.pvBuffer == NULL ) {
  6957. goto cleanup;
  6958. }
  6959. SecStatus = AcceptSecurityContext(
  6960. &CredentialHandle1,
  6961. NULL, // No Server context yet
  6962. &NegotiateDesc,
  6963. ISC_REQ_SEQUENCE_DETECT,
  6964. SECURITY_NATIVE_DREP,
  6965. &ServerContextHandle,
  6966. &ChallengeDesc,
  6967. &ContextAttributes,
  6968. &Lifetime
  6969. );
  6970. if(SecStatus != NO_ERROR)
  6971. {
  6972. goto cleanup;
  6973. }
  6974. if(QuerySecurityContextToken(&ServerContextHandle, phToken) != NO_ERROR)
  6975. goto cleanup;
  6976. bSuccess = TRUE;
  6977. cleanup:
  6978. //
  6979. // Delete context
  6980. //
  6981. if((ClientContextHandle.dwUpper != -1) ||
  6982. (ClientContextHandle.dwLower != -1))
  6983. {
  6984. DeleteSecurityContext( &ClientContextHandle );
  6985. }
  6986. if((ServerContextHandle.dwUpper != -1) ||
  6987. (ServerContextHandle.dwLower != -1))
  6988. {
  6989. DeleteSecurityContext( &ServerContextHandle );
  6990. }
  6991. //
  6992. // Free credential handles
  6993. //
  6994. if((CredentialHandle1.dwUpper != -1) ||
  6995. (CredentialHandle1.dwLower != -1))
  6996. {
  6997. FreeCredentialsHandle( &CredentialHandle1 );
  6998. }
  6999. if((CredentialHandle2.dwUpper != -1) ||
  7000. (CredentialHandle2.dwLower != -1))
  7001. {
  7002. FreeCredentialsHandle( &CredentialHandle2 );
  7003. }
  7004. if ( NegotiateBuffer.pvBuffer != NULL ) {
  7005. ZeroMemory( NegotiateBuffer.pvBuffer, NegotiateBuffer.cbBuffer );
  7006. LocalFree( NegotiateBuffer.pvBuffer );
  7007. }
  7008. if ( ChallengeBuffer.pvBuffer != NULL ) {
  7009. ZeroMemory( ChallengeBuffer.pvBuffer, ChallengeBuffer.cbBuffer );
  7010. LocalFree( ChallengeBuffer.pvBuffer );
  7011. }
  7012. if ( sNames.sUserName != NULL ) {
  7013. FreeContextBuffer( sNames.sUserName );
  7014. }
  7015. return bSuccess;
  7016. }
  7017. //--------------------------------------------------------------------------
  7018. //
  7019. // AEDebugLog
  7020. //
  7021. //--------------------------------------------------------------------------
  7022. #if DBG
  7023. void
  7024. AEDebugLog(long Mask, LPCWSTR Format, ...)
  7025. {
  7026. va_list ArgList;
  7027. int Level = 0;
  7028. int PrefixSize = 0;
  7029. int iOut;
  7030. WCHAR wszOutString[MAX_DEBUG_BUFFER];
  7031. long OriginalMask = Mask;
  7032. if (Mask & g_AutoenrollDebugLevel)
  7033. {
  7034. // Make the prefix first: "Process.Thread> GINA-XXX"
  7035. iOut = wsprintfW(
  7036. wszOutString,
  7037. L"%3d.%3d> AUTOENRL: ",
  7038. GetCurrentProcessId(),
  7039. GetCurrentThreadId());
  7040. va_start(ArgList, Format);
  7041. if (wvsprintfW(&wszOutString[iOut], Format, ArgList) < 0)
  7042. {
  7043. static WCHAR wszOverFlow[] = L"\n<256 byte OVERFLOW!>\n";
  7044. // Less than zero indicates that the string would not fit into the
  7045. // buffer. Output a special message indicating overflow.
  7046. wcscpy(
  7047. &wszOutString[(sizeof(wszOutString) - sizeof(wszOverFlow))/sizeof(WCHAR)],
  7048. wszOverFlow);
  7049. }
  7050. va_end(ArgList);
  7051. OutputDebugStringW(wszOutString);
  7052. }
  7053. }
  7054. #endif
  7055. //--------------------------------------------------------------------------
  7056. //
  7057. // AERemoveRegKey
  7058. //
  7059. // Remove the registry key for local system and all its sub keys.
  7060. //
  7061. //--------------------------------------------------------------------------
  7062. DWORD AERemoveRegKey(LPWSTR pwszRegKey)
  7063. {
  7064. DWORD dwLastError=0; //we should try to clean up as much as possible
  7065. DWORD dwIndex=0;
  7066. DWORD dwSubKey=0;
  7067. DWORD dwSubKeyLen=0;
  7068. DWORD dwData=0;
  7069. HKEY hDSKey=NULL;
  7070. LPWSTR pwszSubKey=NULL;
  7071. //remove the optimization registry. OK if the key does not exist
  7072. if(ERROR_SUCCESS != RegOpenKeyEx(
  7073. HKEY_LOCAL_MACHINE,
  7074. pwszRegKey,
  7075. 0,
  7076. KEY_ALL_ACCESS,
  7077. &hDSKey))
  7078. goto Ret;
  7079. //remove all subkeys of hDSKey
  7080. if(ERROR_SUCCESS != (dwLastError = RegQueryInfoKey(
  7081. hDSKey,
  7082. NULL,
  7083. NULL,
  7084. NULL,
  7085. &dwSubKey,
  7086. &dwSubKeyLen,
  7087. NULL,
  7088. NULL,
  7089. NULL,
  7090. NULL,
  7091. NULL,
  7092. NULL)))
  7093. goto Ret;
  7094. //terminating NULL
  7095. dwSubKeyLen++;
  7096. pwszSubKey=(LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * dwSubKeyLen);
  7097. if(NULL == pwszSubKey)
  7098. {
  7099. dwLastError=ERROR_NOT_ENOUGH_MEMORY;
  7100. goto Ret;
  7101. }
  7102. for(dwIndex=0; dwIndex < dwSubKey; dwIndex++)
  7103. {
  7104. dwData = dwSubKeyLen;
  7105. if(ERROR_SUCCESS == (dwLastError = RegEnumKeyEx(
  7106. hDSKey,
  7107. 0, // As we delete, the index changes
  7108. pwszSubKey,
  7109. &dwData,
  7110. NULL,
  7111. NULL,
  7112. NULL,
  7113. NULL)))
  7114. {
  7115. RegDeleteKey(hDSKey, pwszSubKey);
  7116. }
  7117. }
  7118. //remove the root registry key
  7119. dwLastError=RegDeleteKey(HKEY_LOCAL_MACHINE, pwszRegKey);
  7120. Ret:
  7121. if(pwszSubKey)
  7122. LocalFree(pwszSubKey);
  7123. if(hDSKey)
  7124. RegCloseKey(hDSKey);
  7125. return dwLastError;
  7126. }
  7127. //--------------------------------------------------------------------------
  7128. //
  7129. // CertAutoRemove
  7130. //
  7131. // Function to remove enterprise specific public key trust upon domain disjoin.
  7132. // Should be called under local admin's context.
  7133. //
  7134. // The function will:
  7135. // remove autoenrollment directory cache registry;
  7136. // remove certificates under root enterprise store;
  7137. // remove certificates under NTAuth enterprise store;
  7138. // remove certificates under CA enterprise store;
  7139. //
  7140. //
  7141. // Parameters:
  7142. // IN dwFlags:
  7143. // CERT_AUTO_REMOVE_COMMIT
  7144. // CERT_AUTO_REMOVE_ROLL_BACK
  7145. //
  7146. // Return Value:
  7147. // BOOL: TURE is upon success
  7148. //
  7149. //--------------------------------------------------------------------------
  7150. BOOL
  7151. WINAPI
  7152. CertAutoRemove(IN DWORD dwFlags)
  7153. {
  7154. DWORD dwError=0;
  7155. DWORD dwLastError=0; //we should try to clean up as much as possible
  7156. DWORD dwIndex=0;
  7157. PCCERT_CONTEXT pContext=NULL;
  7158. WCHAR wszNameBuf[64];
  7159. HANDLE hEvent=NULL;
  7160. HCERTSTORE hLocalStore=NULL;
  7161. if((CERT_AUTO_REMOVE_COMMIT != dwFlags) &&
  7162. (CERT_AUTO_REMOVE_ROLL_BACK != dwFlags))
  7163. {
  7164. dwLastError=ERROR_INVALID_PARAMETER;
  7165. goto Ret;
  7166. }
  7167. if(CERT_AUTO_REMOVE_ROLL_BACK == dwFlags)
  7168. {
  7169. //start machine autoenrollment
  7170. wcscpy(wszNameBuf, L"Global\\");
  7171. wcscat(wszNameBuf, MACHINE_AUTOENROLLMENT_TRIGGER_EVENT);
  7172. hEvent=OpenEvent(EVENT_MODIFY_STATE, FALSE, wszNameBuf);
  7173. if (NULL == hEvent)
  7174. {
  7175. dwLastError=GetLastError();
  7176. goto Ret;
  7177. }
  7178. if (!SetEvent(hEvent))
  7179. {
  7180. dwLastError=GetLastError();
  7181. goto Ret;
  7182. }
  7183. }
  7184. else
  7185. {
  7186. //remove all downloaded certificates
  7187. for(dwIndex =0; dwIndex < g_dwStoreInfo; dwIndex++)
  7188. {
  7189. hLocalStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,
  7190. 0,
  7191. 0,
  7192. CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE,
  7193. g_rgStoreInfo[dwIndex].pwszStoreName);
  7194. if(hLocalStore)
  7195. {
  7196. while(pContext = CertEnumCertificatesInStore(hLocalStore, pContext))
  7197. {
  7198. CertDeleteCertificateFromStore(CertDuplicateCertificateContext(pContext));
  7199. }
  7200. CertCloseStore(hLocalStore,0);
  7201. hLocalStore=NULL;
  7202. }
  7203. }
  7204. //remove the local machine's DC GUID cache
  7205. dwLastError=AERemoveRegKey(AUTO_ENROLLMENT_DS_KEY);
  7206. dwError=AERemoveRegKey(AUTO_ENROLLMENT_TEMPLATE_KEY);
  7207. if(0 == dwLastError)
  7208. dwLastError=dwError;
  7209. }
  7210. Ret:
  7211. if(hLocalStore)
  7212. CertCloseStore(hLocalStore,0);
  7213. if (hEvent)
  7214. CloseHandle(hEvent);
  7215. if(0 != dwLastError)
  7216. {
  7217. SetLastError(dwLastError);
  7218. return FALSE;
  7219. }
  7220. return TRUE;
  7221. }
  7222. //--------------------------------------------------------------------------
  7223. //
  7224. // DLLMain
  7225. //
  7226. //
  7227. //--------------------------------------------------------------------------
  7228. extern "C"
  7229. BOOL WINAPI
  7230. DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
  7231. {
  7232. BOOL fResult=TRUE;
  7233. INITCOMMONCONTROLSEX initcomm = {
  7234. sizeof(initcomm), ICC_NATIVEFNTCTL_CLASS | ICC_LISTVIEW_CLASSES | ICC_PROGRESS_CLASS
  7235. };
  7236. switch( dwReason )
  7237. {
  7238. case DLL_PROCESS_ATTACH:
  7239. g_hmodThisDll=hInstance;
  7240. DisableThreadLibraryCalls( hInstance );
  7241. //Init common control for progress bar
  7242. InitCommonControlsEx(&initcomm);
  7243. break;
  7244. case DLL_PROCESS_DETACH:
  7245. break;
  7246. }
  7247. return fResult;
  7248. }