Leaked source code of windows server 2003
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.

1076 lines
46 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997-2002.
  5. //
  6. // File: locate.cpp
  7. //
  8. // Contents: Implementation of Add EFS Agent Wizard Location Page
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. #include "AddSheet.h"
  13. #include "Locate.h"
  14. #pragma warning(push, 3)
  15. #include <initguid.h>
  16. #include <cmnquery.h>
  17. #include <dsquery.h>
  18. #include <winldap.h>
  19. #include <dsgetdc.h>
  20. #include <ntdsapi.h>
  21. #include <efsstruc.h>
  22. #pragma warning(pop)
  23. USE_HANDLE_MACROS("CERTMGR(locate.cpp)")
  24. #ifdef _DEBUG
  25. #ifndef ALPHA
  26. #define new DEBUG_NEW
  27. #endif
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31. #define szCertAttr _T ("?userCertificate")
  32. /////////////////////////////////////////////////////////////////////////////
  33. // CAddEFSWizLocate property page
  34. IMPLEMENT_DYNCREATE(CAddEFSWizLocate, CWizard97PropertyPage)
  35. CAddEFSWizLocate::CAddEFSWizLocate() : CWizard97PropertyPage(CAddEFSWizLocate::IDD)
  36. {
  37. //{{AFX_DATA_INIT(CAddEFSWizLocate)
  38. // NOTE: the ClassWizard will add member initialization here
  39. //}}AFX_DATA_INIT
  40. VERIFY (m_szHeaderTitle.LoadString (IDS_EFS_LOCATE_TITLE));
  41. VERIFY (m_szHeaderSubTitle.LoadString (IDS_EFS_LOCATE_SUBTITLE));
  42. InitWizard97 (FALSE);
  43. }
  44. CAddEFSWizLocate::~CAddEFSWizLocate()
  45. {
  46. }
  47. void CAddEFSWizLocate::DoDataExchange(CDataExchange* pDX)
  48. {
  49. CWizard97PropertyPage::DoDataExchange(pDX);
  50. //{{AFX_DATA_MAP(CAddEFSWizLocate)
  51. DDX_Control (pDX, IDC_ADDLIST, m_UserAddList);
  52. //}}AFX_DATA_MAP
  53. InitWizard97 (FALSE);
  54. }
  55. BEGIN_MESSAGE_MAP(CAddEFSWizLocate, CWizard97PropertyPage)
  56. //{{AFX_MSG_MAP(CAddEFSWizLocate)
  57. ON_BN_CLICKED (IDC_BROWSE_DIR, OnBrowseDir)
  58. ON_BN_CLICKED (IDC_BROWSE_FILE, OnBrowseFile)
  59. //}}AFX_MSG_MAP
  60. END_MESSAGE_MAP()
  61. /////////////////////////////////////////////////////////////////////////////
  62. // CAddEFSWizLocate message handlers
  63. BOOL CAddEFSWizLocate::OnSetActive ()
  64. {
  65. BOOL bResult = CWizard97PropertyPage::OnSetActive ();
  66. EnableControls ();
  67. return bResult;
  68. }
  69. void CAddEFSWizLocate::OnBrowseDir ()
  70. {
  71. FindUserFromDir ();
  72. EnableControls ();
  73. }
  74. void CAddEFSWizLocate::OnBrowseFile ()
  75. {
  76. CString szFileFilter;
  77. VERIFY (szFileFilter.LoadString (IDS_CERTFILEFILTER));
  78. // replace "|" with 0;
  79. // security review 2/27/2002 BryanWal ok
  80. const size_t nFilterLen = wcslen (szFileFilter) + 1;
  81. PWSTR pszFileFilter = new WCHAR [nFilterLen];
  82. if ( pszFileFilter )
  83. {
  84. // security review 2/27/2002 BryanWal ok
  85. wcscpy (pszFileFilter, szFileFilter);
  86. for (int nIndex = 0; nIndex < nFilterLen; nIndex++)
  87. {
  88. if ( L'|' == pszFileFilter[nIndex] )
  89. pszFileFilter[nIndex] = 0;
  90. }
  91. WCHAR szFile[MAX_PATH];
  92. // security review 2/27/2002 BryanWal ok
  93. ::ZeroMemory (szFile, sizeof (szFile));
  94. OPENFILENAME ofn;
  95. // security review 2/27/2002 BryanWal ok
  96. ::ZeroMemory (&ofn, sizeof (ofn));
  97. ofn.lStructSize = sizeof (OPENFILENAME);
  98. ofn.hwndOwner = m_hWnd;
  99. ofn.lpstrFilter = (PCWSTR) pszFileFilter;
  100. ofn.lpstrFile = szFile;
  101. ofn.nMaxFile = MAX_PATH;
  102. ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  103. BOOL bResult = ::GetOpenFileName (&ofn);
  104. if ( bResult )
  105. {
  106. CString szFileName = ofn.lpstrFile;
  107. //
  108. // Open cert store from the file
  109. //
  110. HCERTSTORE hCertStore = NULL;
  111. PVOID FileNameVoidP = (PVOID) (LPCWSTR)szFileName;
  112. PCCERT_CONTEXT pCertContext = NULL;
  113. DWORD dwEncodingType = 0;
  114. DWORD dwContentType = 0;
  115. DWORD dwFormatType = 0;
  116. BOOL bReturn = ::CryptQueryObject (
  117. CERT_QUERY_OBJECT_FILE,
  118. FileNameVoidP,
  119. CERT_QUERY_CONTENT_FLAG_ALL,
  120. CERT_QUERY_FORMAT_FLAG_ALL,
  121. 0,
  122. &dwEncodingType,
  123. &dwContentType,
  124. &dwFormatType,
  125. &hCertStore,
  126. NULL,
  127. (const void **)&pCertContext);
  128. ASSERT (bReturn);
  129. if ( bReturn )
  130. {
  131. //
  132. // Success. See what we get back. A store or a cert.
  133. //
  134. if ( (dwContentType == CERT_QUERY_CONTENT_SERIALIZED_STORE)
  135. && hCertStore)
  136. {
  137. CERT_ENHKEY_USAGE enhKeyUsage;
  138. // security review 2/27/2002 BryanWal ok
  139. ::ZeroMemory (&enhKeyUsage, sizeof (enhKeyUsage));
  140. enhKeyUsage.cUsageIdentifier = 1;
  141. enhKeyUsage.rgpszUsageIdentifier[0] = szOID_EFS_RECOVERY;
  142. //
  143. // We get the certificate store
  144. //
  145. pCertContext = ::CertFindCertificateInStore (
  146. hCertStore,
  147. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  148. 0,
  149. CERT_FIND_ENHKEY_USAGE,
  150. &enhKeyUsage,
  151. NULL);
  152. if ( !pCertContext )
  153. {
  154. CString caption;
  155. CString text;
  156. CThemeContextActivator activator;
  157. VERIFY (text.LoadString (IDS_EFS_FILE_HAS_NO_EFS_USAGE));
  158. VERIFY (caption.LoadString (IDS_ADD_RECOVERY_AGENT));
  159. MessageBox (text, caption, MB_OK);
  160. return;
  161. }
  162. if ( hCertStore )
  163. ::CertCloseStore (hCertStore, 0);
  164. }
  165. else if ( (dwContentType != CERT_QUERY_CONTENT_CERT) || !pCertContext )
  166. {
  167. //
  168. // Neither a valid cert file nor a store file we like.
  169. //
  170. if ( hCertStore )
  171. ::CertCloseStore (hCertStore, 0);
  172. if ( pCertContext )
  173. ::CertFreeCertificateContext (pCertContext);
  174. CString ErrMsg;
  175. CThemeContextActivator activator;
  176. VERIFY (ErrMsg.LoadString (IDS_CERTFILEFORMATERR));
  177. MessageBox (ErrMsg);
  178. return;
  179. }
  180. if ( hCertStore )
  181. {
  182. ::CertCloseStore (hCertStore, 0);
  183. hCertStore = NULL;
  184. }
  185. //
  186. // Add the user
  187. //
  188. if ( CertHasEFSKeyUsage (pCertContext) )
  189. {
  190. //
  191. // We got the cert. Add it to the structure. We need get the subject name first.
  192. //
  193. // verify that certificate is not revoked
  194. if ( !IsCertificateRevoked (pCertContext) )
  195. {
  196. // verify that certificate is valid
  197. if ( 0 == CertVerifyTimeValidity (NULL, pCertContext->pCertInfo) )
  198. {
  199. LPWSTR pszUserCertName = 0;
  200. INT_PTR iRetCode = GetCertNameFromCertContext (
  201. pCertContext,
  202. &pszUserCertName);
  203. if ( ERROR_SUCCESS != iRetCode )
  204. {
  205. if ( pCertContext )
  206. {
  207. ::CertFreeCertificateContext (pCertContext);
  208. }
  209. return;
  210. }
  211. CAddEFSWizSheet* pAddSheet = reinterpret_cast <CAddEFSWizSheet*> (m_pWiz);
  212. ASSERT (pAddSheet);
  213. if ( !pAddSheet )
  214. return;
  215. EFS_CERTIFICATE_BLOB certBlob;
  216. certBlob.cbData = pCertContext->cbCertEncoded;
  217. certBlob.pbData = pCertContext->pbCertEncoded;
  218. certBlob.dwCertEncodingType = pCertContext->dwCertEncodingType;
  219. iRetCode = pAddSheet->Add (
  220. NULL,
  221. pszUserCertName,
  222. (PVOID)&certBlob,
  223. NULL,
  224. USERADDED,
  225. pCertContext);
  226. if ( (ERROR_SUCCESS != iRetCode) && (CRYPT_E_EXISTS != iRetCode) )
  227. {
  228. //
  229. // Error in adding the user
  230. //
  231. ::CertFreeCertificateContext (pCertContext);
  232. pCertContext = NULL;
  233. }
  234. else
  235. {
  236. //
  237. // Add the user to the list box.
  238. //
  239. if ( iRetCode == ERROR_SUCCESS )
  240. {
  241. LV_ITEM fillItem;
  242. CString userUnknown;
  243. try {
  244. if (!userUnknown.LoadString (IDS_UNKNOWNUSER))
  245. {
  246. ASSERT (0);
  247. userUnknown.Empty ();
  248. }
  249. }
  250. catch (...)
  251. {
  252. userUnknown.Empty ();
  253. }
  254. fillItem.mask = LVIF_TEXT;
  255. fillItem.iItem = 0;
  256. fillItem.iSubItem = 0;
  257. if ( userUnknown.IsEmpty () )
  258. {
  259. fillItem.pszText = _T ("");
  260. }
  261. else
  262. {
  263. fillItem.pszText = userUnknown.GetBuffer (userUnknown.GetLength () + 1);
  264. }
  265. fillItem.iItem = m_UserAddList.InsertItem (&fillItem);
  266. if ( !userUnknown.IsEmpty () )
  267. {
  268. userUnknown.ReleaseBuffer ();
  269. }
  270. if ( fillItem.iItem != -1 )
  271. {
  272. fillItem.pszText = pszUserCertName;
  273. fillItem.iSubItem = 1;
  274. m_UserAddList.SetItem (&fillItem);
  275. }
  276. else
  277. {
  278. pAddSheet->Remove (NULL, pszUserCertName);
  279. }
  280. pszUserCertName = NULL;
  281. }
  282. else
  283. {
  284. //
  285. // Already deleted inside the Add.
  286. //
  287. pszUserCertName = NULL;
  288. }
  289. }
  290. if (pszUserCertName)
  291. {
  292. delete [] pszUserCertName;
  293. pszUserCertName = NULL;
  294. }
  295. }
  296. else
  297. {
  298. CString text;
  299. CString caption;
  300. CThemeContextActivator activator;
  301. VERIFY (text.LoadString (IDS_EFS_CERT_IS_NOT_VALID));
  302. VERIFY (caption.LoadString (IDS_ADD_RECOVERY_AGENT));
  303. MessageBox (text, caption, MB_OK);
  304. }
  305. }
  306. }
  307. else
  308. {
  309. CString caption;
  310. CString text;
  311. CThemeContextActivator activator;
  312. VERIFY (text.LoadString (IDS_EFS_FILE_HAS_NO_EFS_USAGE));
  313. VERIFY (caption.LoadString (IDS_ADD_RECOVERY_AGENT));
  314. MessageBox (text, caption, MB_OK);
  315. }
  316. }
  317. else
  318. {
  319. //
  320. // Fail. Get the error code.
  321. //
  322. DWORD dwErr = GetLastError ();
  323. CString text;
  324. CString caption;
  325. CThemeContextActivator activator;
  326. VERIFY (caption.LoadString (IDS_ADD_RECOVERY_AGENT));
  327. text.FormatMessage (IDS_CERTFILEOPENERR,
  328. szFileName, GetSystemMessage (dwErr));
  329. MessageBox (text, caption);
  330. }
  331. }
  332. delete [] pszFileFilter;
  333. }
  334. EnableControls ();
  335. }
  336. HRESULT CAddEFSWizLocate::FindUserFromDir ()
  337. {
  338. HRESULT hr = S_OK;
  339. LPWSTR pszListUserName = NULL;
  340. LPWSTR pszUserCertName = NULL;
  341. FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  342. STGMEDIUM medium = { TYMED_NULL, NULL, NULL };
  343. ICommonQuery* pCommonQuery = NULL;
  344. OPENQUERYWINDOW oqw;
  345. DSQUERYINITPARAMS dqip;
  346. bool bCheckDS = false;
  347. HANDLE hDS = NULL;
  348. CAddEFSWizSheet* pAddSheet = reinterpret_cast <CAddEFSWizSheet *> (m_pWiz);
  349. ASSERT (pAddSheet);
  350. if ( !pAddSheet )
  351. return E_POINTER;
  352. // security review 2/27/2002 BryanWal ok
  353. hr = ::CoCreateInstance (CLSID_CommonQuery, NULL, CLSCTX_INPROC_SERVER,
  354. IID_ICommonQuery, (LPVOID*)&pCommonQuery);
  355. ASSERT (SUCCEEDED (hr));
  356. if ( SUCCEEDED (hr) )
  357. {
  358. dqip.cbStruct = sizeof (dqip);
  359. dqip.dwFlags = DSQPF_SHOWHIDDENOBJECTS |
  360. DSQPF_ENABLEADMINFEATURES;
  361. dqip.pDefaultScope = NULL; //szScopeLocn
  362. oqw.cbStruct = sizeof (oqw);
  363. oqw.dwFlags = OQWF_OKCANCEL |
  364. // OQWF_SINGLESELECT |
  365. OQWF_DEFAULTFORM |
  366. OQWF_REMOVEFORMS ;
  367. oqw.clsidHandler = CLSID_DsQuery;
  368. oqw.pHandlerParameters = &dqip;
  369. oqw.clsidDefaultForm = CLSID_DsFindPeople;
  370. IDataObject* pDataObject = NULL;
  371. hr = pCommonQuery->OpenQueryWindow (m_hWnd, &oqw, &pDataObject);
  372. ASSERT (SUCCEEDED (hr));
  373. if ( SUCCEEDED (hr) && pDataObject )
  374. {
  375. // Fill the list view
  376. fmte.cfFormat = pAddSheet->GetDataFormat ();
  377. hr = pDataObject->GetData (&fmte, &medium);
  378. // A return of DV_E_FORMATETC (0x80040064) here can mean that
  379. // nothing was selected in the query window
  380. if ( SUCCEEDED (hr) )
  381. {
  382. LPDSOBJECTNAMES pDsObjects = (LPDSOBJECTNAMES)medium.hGlobal;
  383. hr = DsBind (NULL, NULL, &hDS);
  384. if ( SUCCEEDED (hr) )
  385. {
  386. //
  387. // We are going to use the DS to crack the names
  388. //
  389. bCheckDS = true;
  390. }
  391. if ( pDsObjects->cItems )
  392. {
  393. // Verify that each user has a cert that allows the necessary
  394. // action (efs decryption)
  395. for ( UINT i = 0 ; i < pDsObjects->cItems ; i++ )
  396. {
  397. PWSTR pszTemp = (PWSTR)
  398. ( ( (LPBYTE)pDsObjects)+pDsObjects->aObjects[i].offsetName);
  399. DS_NAME_RESULT* pUserName = NULL;
  400. PSID userSID = NULL;
  401. DWORD cbSid = 0;
  402. PWSTR pszReferencedDomainName = NULL;
  403. DWORD cbReferencedDomainName = 0;
  404. SID_NAME_USE SidUse;
  405. //
  406. // Get rid of the head :\\
  407. //
  408. LPWSTR pszSearch = wcschr (pszTemp, _T (':'));
  409. if (pszSearch && (pszSearch[1] == _T ('/')) && (pszSearch[2] == _T ('/')))
  410. {
  411. pszTemp = pszSearch + 3;
  412. }
  413. if ( bCheckDS )
  414. {
  415. hr = DsCrackNames (
  416. hDS,
  417. DS_NAME_NO_FLAGS,
  418. DS_FQDN_1779_NAME,
  419. DS_NT4_ACCOUNT_NAME,
  420. 1,
  421. &pszTemp,
  422. &pUserName
  423. );
  424. if ( SUCCEEDED (hr) && pUserName )
  425. {
  426. if ( ( pUserName->cItems > 0 ) && (DS_NAME_NO_ERROR == pUserName->rItems[0].status))
  427. {
  428. //
  429. // Save the NT4 name first, in case we cannot get the principle name
  430. //
  431. pszListUserName = new WCHAR[wcslen (pUserName->rItems[0].pName) + 1];
  432. if (pszListUserName)
  433. {
  434. // security review 2/27/2002 BryanWal ok
  435. wcscpy (pszListUserName, pUserName->rItems[0].pName);
  436. }
  437. else
  438. {
  439. hr = E_OUTOFMEMORY;
  440. break;
  441. }
  442. BOOL bReturn = ::LookupAccountName (
  443. NULL,
  444. pUserName->rItems[0].pName,
  445. userSID,
  446. &cbSid,
  447. pszReferencedDomainName,
  448. &cbReferencedDomainName,
  449. &SidUse
  450. );
  451. hr = GetLastError ();
  452. if ( !bReturn && (HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER) == hr) )
  453. {
  454. //
  455. // We are expecting this error
  456. //
  457. userSID = new BYTE[cbSid];
  458. pszReferencedDomainName = new WCHAR[cbReferencedDomainName];
  459. if ( userSID && pszReferencedDomainName )
  460. {
  461. bReturn = ::LookupAccountName (
  462. NULL,
  463. pUserName->rItems[0].pName,
  464. userSID,
  465. &cbSid,
  466. pszReferencedDomainName,
  467. &cbReferencedDomainName,
  468. &SidUse);
  469. delete [] pszReferencedDomainName;
  470. pszReferencedDomainName = NULL;
  471. if (!bReturn)
  472. {
  473. //
  474. // Get SID failed. We can live with it.
  475. //
  476. userSID = NULL;
  477. }
  478. }
  479. else
  480. {
  481. if (userSID)
  482. {
  483. delete [] userSID;
  484. userSID = NULL;
  485. }
  486. if (pszReferencedDomainName)
  487. {
  488. delete [] pszReferencedDomainName;
  489. pszReferencedDomainName = NULL;
  490. }
  491. hr = E_OUTOFMEMORY;
  492. break;
  493. }
  494. }
  495. else
  496. {
  497. ASSERT (!bReturn);
  498. userSID = NULL;
  499. }
  500. }
  501. }
  502. else
  503. {
  504. //
  505. // Cannot get the NT4 name. Set the SID to NULL. Go on.
  506. //
  507. userSID = NULL;
  508. }
  509. if (pUserName)
  510. {
  511. DsFreeNameResult (pUserName);
  512. pUserName = NULL;
  513. }
  514. hr = DsCrackNames (
  515. hDS,
  516. DS_NAME_NO_FLAGS,
  517. DS_FQDN_1779_NAME,
  518. DS_USER_PRINCIPAL_NAME,
  519. 1,
  520. &pszTemp,
  521. &pUserName);
  522. ASSERT (SUCCEEDED (hr));
  523. if ( (HRESULT_FROM_WIN32 (ERROR_SUCCESS) == hr) &&
  524. ( pUserName->cItems > 0 ) &&
  525. (DS_NAME_NO_ERROR == pUserName->rItems[0].status) )
  526. {
  527. //
  528. // We got the principal name
  529. //
  530. LPWSTR pszTmpNameStr =
  531. new WCHAR[wcslen (pUserName->rItems[0].pName) + 1];
  532. if ( pszTmpNameStr )
  533. {
  534. // security review 2/27/2002 BryanWal ok
  535. wcscpy (pszTmpNameStr, pUserName->rItems[0].pName);
  536. delete [] pszListUserName;
  537. pszListUserName = pszTmpNameStr;
  538. }
  539. else
  540. {
  541. hr = ERROR_OUTOFMEMORY;
  542. }
  543. }
  544. }
  545. if ( (HRESULT_FROM_WIN32 (ERROR_OUTOFMEMORY) != hr) && ( !pszListUserName))
  546. {
  547. //
  548. // Use the LDAP name
  549. //
  550. pszListUserName = new WCHAR[wcslen (pszTemp)+1];
  551. if ( pszListUserName )
  552. {
  553. // security review 2/27/2002 BryanWal ok
  554. wcscpy (pszListUserName, pszTemp);
  555. }
  556. else
  557. {
  558. hr = ERROR_OUTOFMEMORY;
  559. }
  560. }
  561. if (pUserName)
  562. {
  563. DsFreeNameResult (pUserName);
  564. pUserName = NULL;
  565. }
  566. if ( HRESULT_FROM_WIN32 (ERROR_OUTOFMEMORY) != hr )
  567. {
  568. //
  569. // Now is the time to get the certificate
  570. //
  571. PCWSTR pszHeader1 = L"LDAP://";
  572. PCWSTR pszHeader2 = L"LDAP:///";
  573. PWSTR pszLdapUrl = new WCHAR[wcslen (pszTemp) +
  574. wcslen (pszHeader2) + // pszHeader2 because it's the longer of the two
  575. wcslen (szCertAttr) + 2];
  576. if ( pszLdapUrl )
  577. {
  578. PCWSTR szCN = L"CN=";
  579. //
  580. // This is really not necessary. MS should make the name convention consistant.
  581. //
  582. // security review 2/27/2002 BryanWal ok
  583. if ( !wcsncmp (pszTemp, szCN, wcslen (szCN)) )
  584. {
  585. // pszTemp is object name without server
  586. wcscpy (pszLdapUrl, pszHeader2);
  587. }
  588. else
  589. wcscpy (pszLdapUrl, pszHeader1);
  590. wcscat (pszLdapUrl, pszTemp);
  591. wcscat (pszLdapUrl, szCertAttr);
  592. hr = ERROR_SUCCESS;
  593. HCERTSTORE hDSCertStore = ::CertOpenStore (
  594. sz_CERT_STORE_PROV_LDAP,
  595. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  596. NULL,
  597. CERT_STORE_MAXIMUM_ALLOWED_FLAG,
  598. (void*) pszLdapUrl);
  599. //
  600. // In case delete change the result of GetLastError ()
  601. //
  602. hr = GetLastError ();
  603. if (hDSCertStore)
  604. {
  605. CERT_ENHKEY_USAGE enhKeyUsage;
  606. // security review 2/27/2002 BryanWal ok
  607. ::ZeroMemory (&enhKeyUsage, sizeof (enhKeyUsage));
  608. enhKeyUsage.cUsageIdentifier = 1;
  609. enhKeyUsage.rgpszUsageIdentifier = new LPSTR[1];
  610. if ( enhKeyUsage.rgpszUsageIdentifier )
  611. {
  612. enhKeyUsage.rgpszUsageIdentifier[0] = szOID_EFS_RECOVERY;
  613. //
  614. // We get the certificate store
  615. //
  616. PCCERT_CONTEXT pCertContext =
  617. ::CertFindCertificateInStore (
  618. hDSCertStore,
  619. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  620. 0,
  621. CERT_FIND_ENHKEY_USAGE,
  622. &enhKeyUsage,
  623. NULL);
  624. if ( pCertContext )
  625. {
  626. if ( CertHasEFSKeyUsage (pCertContext) )
  627. {
  628. // check to see if cert is revoked
  629. if ( !IsCertificateRevoked (pCertContext) )
  630. {
  631. // verify that certificate is valid
  632. if ( 0 == CertVerifyTimeValidity (NULL, pCertContext->pCertInfo) )
  633. {
  634. //
  635. // We got the certificate. Add it to the lists.
  636. // Get the certificate display name first
  637. //
  638. hr = GetCertNameFromCertContext (
  639. pCertContext,
  640. &pszUserCertName);
  641. //
  642. // Add the user
  643. //
  644. EFS_CERTIFICATE_BLOB certBlob;
  645. certBlob.cbData = pCertContext->cbCertEncoded;
  646. certBlob.pbData = pCertContext->pbCertEncoded;
  647. certBlob.dwCertEncodingType = pCertContext->dwCertEncodingType;
  648. hr = pAddSheet->Add (
  649. pszListUserName,
  650. pszUserCertName,
  651. (PVOID)&certBlob,
  652. userSID,
  653. USERADDED,
  654. pCertContext);
  655. if ( FAILED (hr) && (HRESULT_FROM_WIN32 (CRYPT_E_EXISTS) != hr) )
  656. {
  657. //
  658. // Error in adding the user
  659. //
  660. ::CertFreeCertificateContext (pCertContext);
  661. pCertContext = NULL;
  662. }
  663. else
  664. {
  665. //
  666. // Add the user to the list box.
  667. //
  668. if ( SUCCEEDED (hr) )
  669. {
  670. LV_ITEM fillItem;
  671. fillItem.mask = LVIF_TEXT;
  672. fillItem.iItem = 0;
  673. fillItem.iSubItem = 0;
  674. fillItem.pszText = pszListUserName;
  675. fillItem.iItem = m_UserAddList.InsertItem (&fillItem);
  676. if ( fillItem.iItem == -1 )
  677. {
  678. pAddSheet->Remove ( pszListUserName, pszUserCertName);
  679. }
  680. else
  681. {
  682. fillItem.pszText = pszUserCertName;
  683. fillItem.iSubItem = 1;
  684. m_UserAddList.SetItem (&fillItem);
  685. }
  686. }
  687. //
  688. //Either deleted (CRYPT_E_EXISTS) or should not be freed (ERROR_SUCCESS)
  689. //
  690. pszListUserName = NULL;
  691. pszUserCertName = NULL;
  692. }
  693. }
  694. else
  695. {
  696. CString text;
  697. CString caption;
  698. CThemeContextActivator activator;
  699. VERIFY (text.LoadString (IDS_EFS_CERT_IS_NOT_VALID));
  700. VERIFY (caption.LoadString (IDS_ADD_RECOVERY_AGENT));
  701. MessageBox (text, caption, MB_OK);
  702. }
  703. }
  704. }
  705. else
  706. {
  707. CString caption;
  708. CString text;
  709. CThemeContextActivator activator;
  710. VERIFY (text.LoadString (IDS_USER_OBJECT_HAS_NO_CERTS));
  711. VERIFY (caption.LoadString (IDS_ADD_RECOVERY_AGENT));
  712. MessageBox (text, caption, MB_OK);
  713. }
  714. }
  715. else
  716. {
  717. CString text;
  718. CString caption;
  719. CThemeContextActivator activator;
  720. VERIFY (text.LoadString (IDS_USER_OBJECT_HAS_NO_CERTS));
  721. VERIFY (caption.LoadString (IDS_ADD_RECOVERY_AGENT));
  722. MessageBox (text, caption, MB_OK);
  723. }
  724. delete [] enhKeyUsage.rgpszUsageIdentifier;
  725. }
  726. else
  727. {
  728. hr = E_OUTOFMEMORY;
  729. }
  730. delete [] userSID;
  731. userSID = NULL;
  732. if (pszListUserName)
  733. {
  734. delete [] pszListUserName;
  735. pszListUserName = NULL;
  736. }
  737. if (pszUserCertName)
  738. {
  739. delete [] pszUserCertName;
  740. pszUserCertName = NULL;
  741. }
  742. if ( hDSCertStore )
  743. {
  744. CertCloseStore (hDSCertStore, 0);
  745. hDSCertStore = NULL;
  746. }
  747. }
  748. else
  749. {
  750. //
  751. // Failed to open the cert store
  752. //
  753. delete [] userSID;
  754. userSID = NULL;
  755. if (pszListUserName)
  756. {
  757. delete [] pszListUserName;
  758. pszListUserName = NULL;
  759. }
  760. if (pszUserCertName)
  761. {
  762. delete [] pszUserCertName;
  763. pszUserCertName = NULL;
  764. }
  765. CString caption;
  766. CString text;
  767. CThemeContextActivator activator;
  768. VERIFY (caption.LoadString (IDS_CERTIFICATE_MANAGER));
  769. text.FormatMessage (IDS_UNABLE_TO_OPEN_EFS_STORE, pszLdapUrl,
  770. GetSystemMessage (hr));
  771. ::MessageBox (NULL, text, caption, MB_OK);
  772. }
  773. delete [] pszLdapUrl;
  774. pszLdapUrl = NULL;
  775. }
  776. else
  777. {
  778. hr = ERROR_OUTOFMEMORY;
  779. }
  780. }
  781. if ( HRESULT_FROM_WIN32 (ERROR_OUTOFMEMORY) == hr )
  782. {
  783. //
  784. // Free the memory. Delete works for NULL. No check is needed.
  785. //
  786. delete [] userSID;
  787. userSID = NULL;
  788. delete [] pszListUserName;
  789. pszListUserName = NULL;
  790. delete [] pszUserCertName;
  791. pszUserCertName = NULL;
  792. }
  793. }//For
  794. }
  795. if (bCheckDS)
  796. {
  797. DsUnBindW ( &hDS);
  798. }
  799. ReleaseStgMedium (&medium);
  800. }
  801. pDataObject->Release ();
  802. }
  803. pCommonQuery->Release ();
  804. }
  805. return hr;
  806. }
  807. DWORD CAddEFSWizLocate::GetCertNameFromCertContext (
  808. PCCERT_CONTEXT pCertContext, PWSTR *ppwszUserCertName)
  809. //////////////////////////////////////////////////////////////////////
  810. // Routine Description:
  811. // Get the user name from the certificate
  812. // Arguments:
  813. // pCertContext -- Cert Context
  814. // pszUserCertName -- User name
  815. // ( Caller is responsible to delete this memory using delete [] )
  816. // Return Value:
  817. // ERROR_SUCCESS if succeed.
  818. // If No Name if found. "USER_UNKNOWN is returned".
  819. //
  820. //////////////////////////////////////////////////////////////////////
  821. {
  822. if ( !ppwszUserCertName || !pCertContext)
  823. {
  824. return ERROR_INVALID_PARAMETER;
  825. }
  826. *ppwszUserCertName = NULL;
  827. CString szSubjectName = ::GetNameString (pCertContext, 0);
  828. if ( !szSubjectName.IsEmpty () )
  829. {
  830. // security review 2/27/2002 BryanWal ok
  831. *ppwszUserCertName = new WCHAR[wcslen (szSubjectName) + 1];
  832. if ( *ppwszUserCertName )
  833. {
  834. // security review 2/27/2002 BryanWal ok
  835. wcscpy (*ppwszUserCertName, szSubjectName);
  836. }
  837. else
  838. return ERROR_NOT_ENOUGH_MEMORY;
  839. }
  840. else
  841. return ERROR_FILE_NOT_FOUND;
  842. return ERROR_SUCCESS;
  843. }
  844. BOOL CAddEFSWizLocate::OnInitDialog ()
  845. {
  846. CWizard97PropertyPage::OnInitDialog ();
  847. CString userNameTitle;
  848. CString userDNTitle;
  849. RECT rcList;
  850. try {
  851. m_UserAddList.GetClientRect (&rcList);
  852. DWORD dwColWidth = (rcList.right - rcList.left)/2;
  853. VERIFY (userNameTitle.LoadString (IDS_USERCOLTITLE));
  854. VERIFY (userDNTitle.LoadString (IDS_DNCOLTITLE));
  855. m_UserAddList.InsertColumn (0, userNameTitle, LVCFMT_LEFT, dwColWidth);
  856. m_UserAddList.InsertColumn (1, userDNTitle, LVCFMT_LEFT, dwColWidth);
  857. }
  858. catch (...){
  859. }
  860. CAddEFSWizSheet* pAddSheet = reinterpret_cast <CAddEFSWizSheet*> (m_pWiz);
  861. ASSERT (pAddSheet);
  862. if ( pAddSheet )
  863. {
  864. if ( pAddSheet->m_bMachineIsStandAlone )
  865. GetDlgItem (IDC_BROWSE_DIR)->EnableWindow (FALSE);
  866. }
  867. return TRUE; // return TRUE unless you set the focus to a control
  868. // EXCEPTION: OCX Property Pages should return FALSE
  869. }
  870. LRESULT CAddEFSWizLocate::OnWizardBack ()
  871. {
  872. CAddEFSWizSheet *pAddSheet = reinterpret_cast <CAddEFSWizSheet *> (m_pWiz);
  873. ASSERT (pAddSheet);
  874. if ( !pAddSheet )
  875. return -1;
  876. pAddSheet->ClearUserList ();
  877. m_UserAddList.DeleteAllItems ();
  878. return CWizard97PropertyPage::OnWizardBack ();
  879. }
  880. void CAddEFSWizLocate::EnableControls ()
  881. {
  882. if ( m_UserAddList.GetItemCount () <= 0 )
  883. {
  884. GetParent ()->PostMessage (PSM_SETWIZBUTTONS, 0, PSWIZB_BACK);
  885. }
  886. else
  887. GetParent ()->PostMessage (PSM_SETWIZBUTTONS, 0, PSWIZB_NEXT | PSWIZB_BACK);
  888. }
  889. bool CAddEFSWizLocate::IsCertificateRevoked (PCCERT_CONTEXT pCertContext)
  890. {
  891. ASSERT (pCertContext);
  892. if ( !pCertContext )
  893. return true;
  894. bool bIsRevoked = false;
  895. const DWORD cNumCerts = 1;
  896. PVOID rgpvContext[cNumCerts] = {(PVOID)pCertContext};
  897. CERT_REVOCATION_PARA crp;
  898. CERT_REVOCATION_STATUS crs;
  899. ::ZeroMemory (&crp, sizeof (crp));
  900. crp.cbSize = sizeof (crp);
  901. ::ZeroMemory (&crs, sizeof (crs));
  902. crs.cbSize = sizeof (crs);
  903. BOOL bResult = ::CertVerifyRevocation (
  904. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  905. CERT_CONTEXT_REVOCATION_TYPE,
  906. cNumCerts,
  907. rgpvContext,
  908. 0, // dwFlags
  909. &crp,
  910. &crs);
  911. if ( !bResult )
  912. {
  913. DWORD dwErr = GetLastError ();
  914. CString text;
  915. CString caption;
  916. CThemeContextActivator activator;
  917. VERIFY (caption.LoadString (IDS_ADD_RECOVERY_AGENT));
  918. if ( CRYPT_E_REVOKED == HRESULT_FROM_WIN32 (dwErr) )
  919. {
  920. text.FormatMessage (IDS_EFS_CERT_IS_REVOKED, GetSystemMessage (dwErr));
  921. MessageBox (text, caption, MB_OK);
  922. bIsRevoked = true;
  923. }
  924. else
  925. {
  926. text.FormatMessage (IDS_EFS_CERT_REVOCATION_NOT_VERIFIED, GetSystemMessage (GetLastError ()));
  927. if ( IDNO == MessageBox (text, caption, MB_YESNO) )
  928. bIsRevoked = true;
  929. }
  930. }
  931. else
  932. bIsRevoked = false;
  933. return bIsRevoked;
  934. }