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.

2488 lines
70 KiB

  1. // USERLIST.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "EFSADU.h"
  5. #include "USERLIST.h"
  6. #include "cryptui.h"
  7. #include "objsel.h"
  8. #include <winefs.h>
  9. #include "efsui.h"
  10. #ifdef _DEBUG
  11. #define new DEBUG_NEW
  12. #undef THIS_FILE
  13. static char THIS_FILE[] = __FILE__;
  14. #endif
  15. #define OTHERPEOPLE L"AddressBook"
  16. #define TRUSTEDPEOPLE L"TrustedPeople"
  17. #define KEYPATH TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\EFS\\CurrentKeys")
  18. #define CERT_HASH TEXT("CertificateHash")
  19. LPSTR EfsOidlpstr = szOID_KP_EFS;
  20. PCCERT_CONTEXT GetCertInMyStore(PCRYPT_HASH_BLOB pHashBlob);
  21. PCRYPT_KEY_PROV_INFO GetKeyProvInfo(PCCERT_CONTEXT pCertContext);
  22. BOOLEAN CertHasKey(PCCERT_CONTEXT pCertContext);
  23. /////////////////////////////////////////////////////////////////////////////
  24. // USERLIST dialog
  25. USERLIST::USERLIST(CWnd* pParent /*=NULL*/)
  26. : CDialog(USERLIST::IDD, pParent)
  27. {
  28. //{{AFX_DATA_INIT(USERLIST)
  29. //}}AFX_DATA_INIT
  30. }
  31. USERLIST::USERLIST(LPCTSTR FileName, CWnd* pParent /*=NULL*/)
  32. : CDialog(USERLIST::IDD, pParent)
  33. {
  34. m_FileName = FileName;
  35. }
  36. void USERLIST::DoDataExchange(CDataExchange* pDX)
  37. {
  38. CDialog::DoDataExchange(pDX);
  39. //{{AFX_DATA_MAP(USERLIST)
  40. DDX_Control(pDX, IDC_BACKUP, m_BackupButton);
  41. DDX_Control(pDX, IDC_LISTRA, m_RecoveryListCtrl);
  42. DDX_Control(pDX, IDC_LISTUSER, m_UserListCtrl);
  43. DDX_Control(pDX, IDC_ADD, m_AddButton);
  44. DDX_Control(pDX, IDC_REMOVE, m_RemoveButton);
  45. //}}AFX_DATA_MAP
  46. }
  47. BEGIN_MESSAGE_MAP(USERLIST, CDialog)
  48. //{{AFX_MSG_MAP(USERLIST)
  49. ON_BN_CLICKED(IDC_REMOVE, OnRemove)
  50. ON_BN_CLICKED(IDC_ADD, OnAdd)
  51. ON_NOTIFY(NM_SETFOCUS, IDC_LISTUSER, OnSetfocusListuser)
  52. ON_NOTIFY(NM_KILLFOCUS, IDC_LISTUSER, OnKillfocusListuser)
  53. ON_NOTIFY(LVN_ITEMCHANGED, IDC_LISTUSER, OnItemchangedListuser)
  54. ON_NOTIFY(NM_SETFOCUS, IDC_LISTRA, OnSetfocusListra)
  55. ON_BN_CLICKED(IDC_BACKUP, OnBackup)
  56. //}}AFX_MSG_MAP
  57. END_MESSAGE_MAP()
  58. /////////////////////////////////////////////////////////////////////////////
  59. // USERLIST message handlers
  60. void USERLIST::OnRemove()
  61. {
  62. int ItemPos;
  63. BOOL NoAction = FALSE;
  64. CString NoCertName;
  65. try{
  66. NoCertName.LoadString(IDS_NOCERTNAME);
  67. }
  68. catch(...){
  69. NoAction = TRUE;
  70. }
  71. if (NoAction){
  72. return;
  73. }
  74. ItemPos = m_UserListCtrl.GetNextItem( -1, LVNI_SELECTED );
  75. while ( ItemPos != -1 ){
  76. CString CertName;
  77. LPTSTR pCertName;
  78. CertName = m_UserListCtrl.GetItemText( ItemPos, 0 );
  79. if ( !CertName.Compare(NoCertName) ){
  80. pCertName = NULL;
  81. } else {
  82. pCertName = CertName.GetBuffer(CertName.GetLength() + 1);
  83. }
  84. m_Users.Remove( pCertName);
  85. m_UserListCtrl.DeleteItem( ItemPos );
  86. if (pCertName){
  87. CertName.ReleaseBuffer();
  88. }
  89. //
  90. // Because we have deleted the item. We have to start from -1 again.
  91. //
  92. ItemPos = m_UserListCtrl.GetNextItem( -1, LVNI_SELECTED );
  93. }
  94. m_AddButton.SetFocus();
  95. }
  96. void USERLIST::OnCancel()
  97. {
  98. // TODO: Add extra cleanup here
  99. CDialog::OnCancel();
  100. }
  101. void USERLIST::OnOK()
  102. {
  103. // TODO: Add extra validation here
  104. LONG NoUsersToAdd = m_Users.GetUserAddedCnt();
  105. LONG NoUsersToRemove = m_Users.GetUserRemovedCnt();
  106. if ( (NoUsersToRemove - NoUsersToAdd) >= m_CurrentUsers) {
  107. //
  108. // All the users are going to be removed from the file. Do not allow.
  109. //
  110. CString ErrMsg;
  111. if (ErrMsg.LoadString(IDS_NOREMOVEALL)){
  112. MessageBox(ErrMsg);
  113. }
  114. return;
  115. }
  116. CDialog::OnOK();
  117. }
  118. STDAPI_(void) EfsDetail(HWND hwndParent, LPCWSTR FileName)
  119. {
  120. INT_PTR RetCode;
  121. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  122. DWORD FileAttributes = GetFileAttributes(FileName);
  123. if ( (-1 != FileAttributes) && ( FileAttributes & FILE_ATTRIBUTE_DIRECTORY)){
  124. CString ErrMsg;
  125. if (ErrMsg.LoadString(IDS_NOADDUSERDIR)){
  126. MessageBox(hwndParent, ErrMsg, NULL, MB_OK);
  127. }
  128. return;
  129. }
  130. CWnd cwnd;
  131. cwnd.FromHandle(hwndParent);
  132. USERLIST DetailDialog(FileName, &cwnd);
  133. RetCode = DetailDialog.DoModal();
  134. if ( IDOK == RetCode ){
  135. //
  136. // Commit the change
  137. //
  138. DetailDialog.ApplyChanges( FileName );
  139. } else if (IDCANCEL == RetCode) {
  140. //
  141. // Nothing needs to be done
  142. //
  143. }
  144. }
  145. BOOL WINAPI EfsFilter(
  146. PCCERT_CONTEXT pCertContext,
  147. BOOL *pfInitialSelectedCert,
  148. void *pvCallbackData
  149. )
  150. {
  151. BOOL disp = FALSE;
  152. PCERT_ENHKEY_USAGE pUsage = NULL;
  153. DWORD cbUsage = 0;
  154. if ( CertVerifyTimeValidity(
  155. NULL,
  156. pCertContext->pCertInfo
  157. )){
  158. return disp;
  159. }
  160. if (CertGetEnhancedKeyUsage(
  161. pCertContext,
  162. 0,
  163. NULL,
  164. &cbUsage) && 0 != cbUsage){
  165. pUsage = (PCERT_ENHKEY_USAGE) new BYTE[cbUsage];
  166. if (pUsage){
  167. if (CertGetEnhancedKeyUsage(
  168. pCertContext,
  169. 0,
  170. pUsage,
  171. &cbUsage)){
  172. //
  173. // Search for EFS usage
  174. //
  175. DWORD cUsages = pUsage->cUsageIdentifier;
  176. while (cUsages){
  177. if (!strcmp(szOID_KP_EFS, pUsage->rgpszUsageIdentifier[cUsages-1])){
  178. disp = TRUE;
  179. break;
  180. }
  181. cUsages--;
  182. }
  183. }
  184. delete [] pUsage;
  185. }
  186. }
  187. return disp;
  188. }
  189. BOOL USERLIST::OnInitDialog()
  190. {
  191. CDialog::OnInitDialog();
  192. CString WinTitle;
  193. RECT ListRect;
  194. DWORD ColWidth;
  195. CString ColName;
  196. CString ColCert;
  197. CString RecName;
  198. LPTSTR UserCertName = NULL;
  199. BOOL EnableAddButton = FALSE;
  200. PENCRYPTION_CERTIFICATE_HASH_LIST pUsers = NULL;
  201. PENCRYPTION_CERTIFICATE_HASH_LIST pRecs = NULL;
  202. try {
  203. DWORD RetCode;
  204. AfxFormatString1( WinTitle, IDS_DETAILWINTITLE, m_FileName );
  205. SetWindowText( WinTitle );
  206. m_CertChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
  207. m_CertChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
  208. //
  209. // Check EFS EKU
  210. //
  211. m_CertChainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
  212. m_CertChainPara.RequestedUsage.Usage.rgpszUsageIdentifier=&EfsOidlpstr;
  213. m_UserListCtrl.GetClientRect(&ListRect);
  214. ColName.LoadString(IDS_USERCOLTITLE);
  215. ColCert.LoadString(IDS_CERTCOLTITLE);
  216. RecName.LoadString(IDS_RECCOLTITLE);
  217. ColWidth = ( ListRect.right - ListRect.left ) / 4;
  218. m_UserListCtrl.InsertColumn(0, ColName, LVCFMT_LEFT, ColWidth*3 );
  219. m_UserListCtrl.InsertColumn(1, ColCert, LVCFMT_LEFT, ColWidth );
  220. m_RecoveryListCtrl.GetClientRect(&ListRect);
  221. ColWidth = ( ListRect.right - ListRect.left ) / 4;
  222. m_RecoveryListCtrl.InsertColumn(0, RecName, LVCFMT_LEFT, ColWidth*3 );
  223. m_RecoveryListCtrl.InsertColumn(1, ColCert, LVCFMT_LEFT, ColWidth );
  224. RetCode = QueryUsersOnEncryptedFile( (LPWSTR)(LPCWSTR) m_FileName, &pUsers);
  225. if ( !RetCode ){
  226. RetCode = QueryRecoveryAgentsOnEncryptedFile( (LPWSTR)(LPCWSTR) m_FileName, &pRecs);
  227. if ( !RetCode ){
  228. //
  229. // Got the info about the encrypted file
  230. //
  231. DWORD NUsers = pUsers->nCert_Hash;
  232. BOOL RecDone = FALSE;
  233. PENCRYPTION_CERTIFICATE_HASH_LIST pCertHashList = pUsers;
  234. m_CurrentUsers = (LONG) NUsers;
  235. //
  236. // Get all the users
  237. //
  238. while ( NUsers > 0 ){
  239. UserCertName = new TCHAR[_tcslen(pCertHashList->pUsers[NUsers - 1]->lpDisplayInformation) + 1];
  240. if (UserCertName){
  241. _tcscpy(UserCertName, pCertHashList->pUsers[NUsers - 1]->lpDisplayInformation);
  242. } else {
  243. AfxThrowMemoryException( );
  244. }
  245. //
  246. // We got the user name
  247. //
  248. if (RecDone){
  249. RetCode = m_Recs.Add(
  250. UserCertName,
  251. pCertHashList->pUsers[NUsers - 1]->pHash,
  252. NULL
  253. );
  254. } else {
  255. //
  256. // Try to get a better name from the cert
  257. //
  258. LPTSTR UserName;
  259. RetCode = TryGetBetterNameInCert(pCertHashList->pUsers[NUsers - 1]->pHash, &UserName);
  260. if (ERROR_SUCCESS == RetCode){
  261. //
  262. // We get a better name from the certs
  263. //
  264. delete [] UserCertName;
  265. UserCertName = UserName;
  266. }
  267. RetCode = m_Users.Add(
  268. UserCertName,
  269. pCertHashList->pUsers[NUsers - 1]->pHash,
  270. NULL
  271. );
  272. }
  273. if ( NO_ERROR != RetCode ) {
  274. delete [] UserCertName;
  275. UserCertName = NULL;
  276. }
  277. NUsers--;
  278. if (NUsers == 0 && !RecDone){
  279. //
  280. // Let's deal with the recovery agents.
  281. //
  282. RecDone = TRUE;
  283. pCertHashList = pRecs;
  284. NUsers = pRecs->nCert_Hash;
  285. }
  286. }
  287. if ( pRecs ){
  288. FreeEncryptionCertificateHashList( pRecs );
  289. pRecs = NULL;
  290. }
  291. //
  292. // In memory intial list established
  293. //
  294. SetUpListBox(&EnableAddButton);
  295. } else {
  296. //
  297. // Cannot get recovery info
  298. //
  299. CString ErrMsg;
  300. if (ErrMsg.LoadString(IDS_NORECINFO)){
  301. MessageBox(ErrMsg);
  302. }
  303. }
  304. if ( pUsers ){
  305. FreeEncryptionCertificateHashList( pUsers );
  306. pUsers = NULL;
  307. }
  308. } else {
  309. //
  310. // Cannot get user info
  311. //
  312. CString ErrMsg;
  313. if (ErrMsg.LoadString(IDS_NOINFO)){
  314. MessageBox(ErrMsg);
  315. }
  316. }
  317. }
  318. catch (...) {
  319. //
  320. // The exception mostly is caused by out of memory.
  321. // We can not prevent the page to be displayed from this routine,
  322. // So we just go ahead with empty list
  323. //
  324. m_UserListCtrl.DeleteAllItems( );
  325. m_RecoveryListCtrl.DeleteAllItems( );
  326. //
  327. // Delete works even if UserCertName == NULL
  328. //
  329. delete [] UserCertName;
  330. if ( pUsers ){
  331. FreeEncryptionCertificateHashList( pUsers );
  332. }
  333. if ( pRecs ){
  334. FreeEncryptionCertificateHashList( pRecs );
  335. }
  336. }
  337. m_RemoveButton.EnableWindow( FALSE );
  338. if ( !EnableAddButton ){
  339. m_AddButton.EnableWindow( FALSE );
  340. }
  341. ShowBackup();
  342. return TRUE; // return TRUE unless you set the focus to a control
  343. // EXCEPTION: OCX Property Pages should return FALSE
  344. }
  345. void USERLIST::ShowRemove()
  346. {
  347. if (m_UserListCtrl.GetSelectedCount() > 0){
  348. //
  349. // Enable the Remove Button
  350. //
  351. m_RemoveButton.EnableWindow( TRUE );
  352. } else {
  353. //
  354. // Disable the Remove Button
  355. //
  356. m_RemoveButton.EnableWindow( FALSE );
  357. }
  358. }
  359. DWORD
  360. USERLIST::ApplyChanges(
  361. LPCTSTR FileName
  362. )
  363. {
  364. DWORD RetCode = NO_ERROR;
  365. DWORD NoUsersToRemove;
  366. DWORD NoUsersToAdd;
  367. DWORD RemoveUserIndex;
  368. DWORD AddUserIndex;
  369. PENCRYPTION_CERTIFICATE_HASH_LIST RemoveUserList = NULL;
  370. PENCRYPTION_CERTIFICATE_LIST AddUserList = NULL;
  371. PVOID EnumHandle;
  372. //
  373. // Get all the users to be added or removed first
  374. //
  375. NoUsersToAdd = m_Users.GetUserAddedCnt();
  376. NoUsersToRemove = m_Users.GetUserRemovedCnt();
  377. if ( (NoUsersToAdd == 0) && (NoUsersToRemove == 0)){
  378. return NO_ERROR;
  379. }
  380. if ( NoUsersToAdd ) {
  381. //
  382. // At least one user is to be added
  383. //
  384. DWORD BytesToAllocate;
  385. BytesToAllocate = sizeof ( ENCRYPTION_CERTIFICATE_LIST ) +
  386. NoUsersToAdd * sizeof ( PENCRYPTION_CERTIFICATE ) +
  387. NoUsersToAdd * sizeof (ENCRYPTION_CERTIFICATE);
  388. AddUserList = (PENCRYPTION_CERTIFICATE_LIST) new BYTE[BytesToAllocate];
  389. if ( NULL == AddUserList ){
  390. //
  391. // Out of memory. Try our best to display the error message.
  392. //
  393. try {
  394. CString ErrMsg;
  395. if (ErrMsg.LoadString(IDS_ERRORMEM)){
  396. ::MessageBox(NULL, ErrMsg, NULL, MB_OK);
  397. }
  398. }
  399. catch (...) {
  400. }
  401. return ERROR_NOT_ENOUGH_MEMORY;
  402. }
  403. AddUserList->nUsers = NoUsersToAdd;
  404. AddUserList->pUsers = (PENCRYPTION_CERTIFICATE *)(((PBYTE) AddUserList) +
  405. sizeof ( ENCRYPTION_CERTIFICATE_LIST ));
  406. }
  407. if ( NoUsersToRemove ){
  408. //
  409. // At least one user is to be removed
  410. //
  411. DWORD BytesToAllocate;
  412. BytesToAllocate = sizeof ( ENCRYPTION_CERTIFICATE_HASH_LIST ) +
  413. NoUsersToRemove * sizeof ( PENCRYPTION_CERTIFICATE_HASH) +
  414. NoUsersToRemove * sizeof (ENCRYPTION_CERTIFICATE_HASH);
  415. RemoveUserList = (PENCRYPTION_CERTIFICATE_HASH_LIST) new BYTE[BytesToAllocate];
  416. if ( NULL == RemoveUserList ){
  417. //
  418. // Out of memory. Try our best to display the error message.
  419. //
  420. if (AddUserList){
  421. delete [] AddUserList;
  422. AddUserList = NULL;
  423. }
  424. try {
  425. CString ErrMsg;
  426. if (ErrMsg.LoadString(IDS_ERRORMEM)){
  427. ::MessageBox(NULL, ErrMsg, NULL, MB_OK);
  428. }
  429. }
  430. catch (...) {
  431. }
  432. return ERROR_NOT_ENOUGH_MEMORY;
  433. }
  434. RemoveUserList->nCert_Hash = NoUsersToRemove;
  435. RemoveUserList->pUsers = (PENCRYPTION_CERTIFICATE_HASH *)(((PBYTE) RemoveUserList) +
  436. sizeof ( ENCRYPTION_CERTIFICATE_HASH_LIST ));
  437. }
  438. EnumHandle = m_Users.StartEnum();
  439. RemoveUserIndex = 0;
  440. AddUserIndex = 0;
  441. while ( EnumHandle ){
  442. DWORD Flag;
  443. PSID UserSid;
  444. PVOID CertData;
  445. LPTSTR UserName;
  446. EnumHandle = m_Users.GetNextChangedUser(
  447. EnumHandle,
  448. &UserName,
  449. &UserSid,
  450. &CertData,
  451. &Flag
  452. );
  453. if ( Flag ){
  454. //
  455. // We get our changed user
  456. //
  457. if ( Flag & USERADDED ){
  458. ASSERT( AddUserList );
  459. //
  460. // Add the user to the adding list
  461. //
  462. PENCRYPTION_CERTIFICATE EfsCert;
  463. ASSERT (AddUserIndex < NoUsersToAdd);
  464. EfsCert= (PENCRYPTION_CERTIFICATE)(((PBYTE) AddUserList) +
  465. sizeof ( ENCRYPTION_CERTIFICATE_LIST ) +
  466. NoUsersToAdd * sizeof ( PENCRYPTION_CERTIFICATE) +
  467. AddUserIndex * sizeof (ENCRYPTION_CERTIFICATE));
  468. AddUserList->pUsers[AddUserIndex] = EfsCert;
  469. EfsCert->pUserSid = (SID *) UserSid;
  470. EfsCert->cbTotalLength = sizeof (ENCRYPTION_CERTIFICATE);
  471. EfsCert->pCertBlob = (PEFS_CERTIFICATE_BLOB) CertData;
  472. AddUserIndex++;
  473. } else if ( Flag & USERREMOVED ) {
  474. ASSERT (RemoveUserList);
  475. //
  476. // Add the user to the removing list
  477. //
  478. PENCRYPTION_CERTIFICATE_HASH EfsCertHash;
  479. ASSERT (RemoveUserIndex < NoUsersToRemove);
  480. EfsCertHash= (PENCRYPTION_CERTIFICATE_HASH)(((PBYTE) RemoveUserList) +
  481. sizeof ( ENCRYPTION_CERTIFICATE_HASH_LIST ) +
  482. NoUsersToRemove * sizeof ( PENCRYPTION_CERTIFICATE_HASH) +
  483. RemoveUserIndex * sizeof (ENCRYPTION_CERTIFICATE_HASH));
  484. RemoveUserList->pUsers[RemoveUserIndex] = EfsCertHash;
  485. EfsCertHash->cbTotalLength = sizeof (ENCRYPTION_CERTIFICATE_HASH);
  486. EfsCertHash->pUserSid = (SID *)UserSid;
  487. EfsCertHash->pHash = (PEFS_HASH_BLOB) CertData;
  488. EfsCertHash->lpDisplayInformation = NULL;
  489. RemoveUserIndex++;
  490. } else {
  491. ASSERT(FALSE);
  492. }
  493. }
  494. }
  495. ASSERT(RemoveUserIndex == NoUsersToRemove);
  496. ASSERT(AddUserIndex == NoUsersToAdd);
  497. if ( AddUserIndex && AddUserList ){
  498. //
  499. // Add the user to the file list
  500. //
  501. RetCode = AddUsersToEncryptedFile(FileName, AddUserList);
  502. if ( NO_ERROR != RetCode ){
  503. CString ErrMsg;
  504. TCHAR ErrCode[16];
  505. if (ERROR_ACCESS_DENIED != RetCode) {
  506. _ltot(RetCode, ErrCode, 10 );
  507. AfxFormatString1( ErrMsg, IDS_ADDUSERERR, ErrCode );
  508. } else {
  509. ErrMsg.LoadString(IDS_ADDUSERDENIED);
  510. }
  511. MessageBox(ErrMsg);
  512. }
  513. }
  514. if ( RemoveUserIndex && RemoveUserList){
  515. //
  516. // Remove the user from the list
  517. //
  518. DWORD RetCodeBak = RetCode;
  519. RetCode = RemoveUsersFromEncryptedFile(FileName, RemoveUserList);
  520. if ( NO_ERROR != RetCode ){
  521. CString ErrMsg;
  522. TCHAR ErrCode[16];
  523. if (ERROR_ACCESS_DENIED != RetCode) {
  524. _ltot(RetCode, ErrCode, 10 );
  525. AfxFormatString1( ErrMsg, IDS_REMOVEUSERERR, ErrCode );
  526. } else {
  527. ErrMsg.LoadString(IDS_REMOVEUSERDENIED);
  528. }
  529. MessageBox(ErrMsg);
  530. } else {
  531. //
  532. // Reflect the error happened
  533. //
  534. RetCode = RetCodeBak;
  535. }
  536. }
  537. if (AddUserList){
  538. delete [] AddUserList;
  539. }
  540. if (RemoveUserList){
  541. delete [] RemoveUserList;
  542. }
  543. return RetCode;
  544. }
  545. DWORD
  546. USERLIST::AddNewUsers(CUsers &NewUser)
  547. {
  548. DWORD RetCode = ERROR_SUCCESS;
  549. m_UserListCtrl.DeleteAllItems( );
  550. RetCode = m_Users.Add(NewUser);
  551. SetUpListBox(NULL);
  552. return RetCode;
  553. }
  554. void USERLIST::SetUpListBox(BOOL *EnableAdd)
  555. {
  556. PVOID EnumHandle;
  557. try{
  558. CString NoCertName;
  559. NoCertName.LoadString(IDS_NOCERTNAME);
  560. if (EnumHandle = m_Users.StartEnum()){
  561. LV_ITEM fillItem;
  562. fillItem.mask = LVIF_TEXT;
  563. //
  564. // At least one user is available
  565. //
  566. while ( EnumHandle ){
  567. CString CertName;
  568. CString CertHash;
  569. fillItem.iItem = 0;
  570. fillItem.iSubItem = 0;
  571. EnumHandle = m_Users.GetNextUser(EnumHandle, CertName, CertHash);
  572. if (!EnumHandle && CertName.IsEmpty() && CertHash.IsEmpty()) {
  573. //
  574. // No more items.
  575. //
  576. break;
  577. }
  578. if (CertName.IsEmpty()){
  579. fillItem.pszText = NoCertName.GetBuffer(NoCertName.GetLength() + 1);
  580. } else {
  581. fillItem.pszText = CertName.GetBuffer(CertName.GetLength() + 1);
  582. }
  583. //
  584. // Add the user to the list
  585. //
  586. fillItem.iItem = m_UserListCtrl.InsertItem(&fillItem);
  587. if (CertName.IsEmpty()){
  588. NoCertName.ReleaseBuffer();
  589. } else {
  590. CertName.ReleaseBuffer();
  591. }
  592. if ( fillItem.iItem != -1 ){
  593. if ( EnableAdd ){
  594. *EnableAdd = TRUE;
  595. }
  596. if (CertHash.IsEmpty()){
  597. fillItem.pszText = NULL;
  598. } else {
  599. fillItem.pszText = CertHash.GetBuffer(CertHash.GetLength() + 1);
  600. }
  601. fillItem.iSubItem = 1;
  602. m_UserListCtrl.SetItem(&fillItem);
  603. if (!CertHash.IsEmpty()){
  604. CertHash.ReleaseBuffer();
  605. }
  606. }
  607. }
  608. }
  609. if (EnableAdd){
  610. //
  611. // From the dialog init. Do the Rec list as well
  612. //
  613. if (EnumHandle = m_Recs.StartEnum()){
  614. LV_ITEM fillItem;
  615. fillItem.mask = LVIF_TEXT;
  616. //
  617. // At least one user is available
  618. //
  619. while ( EnumHandle ){
  620. CString CertName;
  621. CString CertHash;
  622. fillItem.iItem = 0;
  623. fillItem.iSubItem = 0;
  624. EnumHandle = m_Recs.GetNextUser(EnumHandle, CertName, CertHash);
  625. if (!EnumHandle && CertName.IsEmpty() && CertHash.IsEmpty()) {
  626. //
  627. // No more items.
  628. //
  629. break;
  630. }
  631. //
  632. // Add the agent to the list
  633. //
  634. if (CertName.IsEmpty()){
  635. fillItem.pszText = NoCertName.GetBuffer(NoCertName.GetLength() + 1);
  636. } else {
  637. fillItem.pszText = CertName.GetBuffer(CertName.GetLength() + 1);
  638. }
  639. fillItem.iItem = m_RecoveryListCtrl.InsertItem(&fillItem);
  640. if (CertName.IsEmpty()){
  641. NoCertName.ReleaseBuffer();
  642. } else {
  643. CertName.ReleaseBuffer();
  644. }
  645. if ( fillItem.iItem != -1 ){
  646. if (CertHash.IsEmpty()){
  647. fillItem.pszText = NULL;
  648. } else {
  649. fillItem.pszText = CertHash.GetBuffer(CertHash.GetLength() + 1);
  650. }
  651. fillItem.iSubItem = 1;
  652. m_RecoveryListCtrl.SetItem(&fillItem);
  653. if (!CertHash.IsEmpty()){
  654. CertHash.ReleaseBuffer();
  655. }
  656. }
  657. }
  658. }
  659. }
  660. }
  661. catch(...){
  662. m_UserListCtrl.DeleteAllItems( );
  663. m_RecoveryListCtrl.DeleteAllItems( );
  664. if ( EnableAdd ){
  665. *EnableAdd = FALSE;
  666. }
  667. }
  668. }
  669. DWORD
  670. USERLIST::GetCertNameFromCertContext(
  671. PCCERT_CONTEXT CertContext,
  672. LPTSTR * UserDispName
  673. )
  674. //////////////////////////////////////////////////////////////////////
  675. // Routine Description:
  676. // Get the user name from the certificate
  677. // Arguments:
  678. // CertContext -- Cert Context
  679. // UserCertName -- User Common Name
  680. // ( Caller is responsible to delete this memory using delete [] )
  681. // Return Value:
  682. // ERROR_SUCCESS if succeed.
  683. // If No Name found. "USER_UNKNOWN is returned".
  684. //
  685. //////////////////////////////////////////////////////////////////////
  686. {
  687. DWORD NameLength;
  688. DWORD UserNameBufLen = 0;
  689. DWORD BlobLen = 0;
  690. PCERT_EXTENSION AlterNameExt = NULL;
  691. BOOL b;
  692. LPTSTR DNSName = NULL;
  693. LPTSTR UPNName = NULL;
  694. LPTSTR CommonName = NULL;
  695. if ( NULL == UserDispName ){
  696. return ERROR_SUCCESS;
  697. }
  698. *UserDispName = NULL;
  699. AlterNameExt = CertFindExtension(
  700. szOID_SUBJECT_ALT_NAME2,
  701. CertContext->pCertInfo->cExtension,
  702. CertContext->pCertInfo->rgExtension
  703. );
  704. if (AlterNameExt){
  705. //
  706. // Find the alternative name
  707. //
  708. b = CryptDecodeObject(
  709. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  710. szOID_SUBJECT_ALT_NAME ,
  711. AlterNameExt->Value.pbData,
  712. AlterNameExt->Value.cbData,
  713. 0,
  714. NULL,
  715. &BlobLen
  716. );
  717. if (b){
  718. //
  719. // Let's decode it
  720. //
  721. CERT_ALT_NAME_INFO *AltNameInfo = NULL;
  722. AltNameInfo = (CERT_ALT_NAME_INFO *) new BYTE[BlobLen];
  723. if (AltNameInfo){
  724. b = CryptDecodeObject(
  725. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  726. szOID_SUBJECT_ALT_NAME,
  727. AlterNameExt->Value.pbData,
  728. AlterNameExt->Value.cbData,
  729. 0,
  730. AltNameInfo,
  731. &BlobLen
  732. );
  733. if (b){
  734. //
  735. // Now search for the UPN, SPN, DNS, EFS name
  736. //
  737. DWORD cAltEntry = AltNameInfo->cAltEntry;
  738. DWORD ii = 0;
  739. while (ii < cAltEntry){
  740. if ((AltNameInfo->rgAltEntry[ii].dwAltNameChoice == CERT_ALT_NAME_OTHER_NAME ) &&
  741. !strcmp(szOID_NT_PRINCIPAL_NAME, AltNameInfo->rgAltEntry[ii].pOtherName->pszObjId)
  742. ){
  743. //
  744. // We found the UPN name
  745. //
  746. CERT_NAME_VALUE* CertUPNName = NULL;
  747. b = CryptDecodeObject(
  748. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  749. X509_UNICODE_ANY_STRING,
  750. AltNameInfo->rgAltEntry[ii].pOtherName->Value.pbData,
  751. AltNameInfo->rgAltEntry[ii].pOtherName->Value.cbData,
  752. 0,
  753. NULL,
  754. &BlobLen
  755. );
  756. if (b){
  757. CertUPNName = (CERT_NAME_VALUE *) new BYTE[BlobLen];
  758. if (CertUPNName){
  759. b = CryptDecodeObject(
  760. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  761. X509_UNICODE_ANY_STRING,
  762. AltNameInfo->rgAltEntry[ii].pOtherName->Value.pbData,
  763. AltNameInfo->rgAltEntry[ii].pOtherName->Value.cbData,
  764. 0,
  765. CertUPNName,
  766. &BlobLen
  767. );
  768. if (b){
  769. UPNName = (LPTSTR)new BYTE[CertUPNName->Value.cbData + sizeof(WCHAR)];
  770. if (UPNName){
  771. wcscpy(UPNName, (LPCTSTR) CertUPNName->Value.pbData);
  772. }
  773. }
  774. delete [] CertUPNName;
  775. if (UPNName){
  776. //
  777. // Got the UPN name. Stop searching.
  778. //
  779. break;
  780. }
  781. }
  782. }
  783. } else {
  784. //
  785. // Check for other alternative name
  786. //
  787. if (AltNameInfo->rgAltEntry[ii].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME){
  788. DNSName = AltNameInfo->rgAltEntry[ii].pwszDNSName;
  789. }
  790. }
  791. ii++;
  792. }
  793. if ( NULL == UPNName ){
  794. //
  795. // No UPN name, let's get the other option
  796. //
  797. if (DNSName){
  798. UPNName = (LPTSTR)new TCHAR[wcslen( DNSName ) + 1];
  799. if (UPNName){
  800. wcscpy(UPNName, DNSName);
  801. }
  802. }
  803. }
  804. }
  805. delete [] AltNameInfo;
  806. }
  807. }
  808. }
  809. NameLength = CertGetNameString(
  810. CertContext,
  811. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  812. 0,
  813. NULL,
  814. NULL,
  815. 0
  816. );
  817. if ( NameLength > 1){
  818. //
  819. // The display name exist. Go get the display name.
  820. //
  821. CommonName = new TCHAR[NameLength];
  822. if ( NULL == CommonName ){
  823. if (UPNName){
  824. delete [] UPNName;
  825. }
  826. return ERROR_NOT_ENOUGH_MEMORY;
  827. }
  828. UserNameBufLen = NameLength;
  829. NameLength = CertGetNameString(
  830. CertContext,
  831. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  832. 0,
  833. NULL,
  834. CommonName,
  835. UserNameBufLen
  836. );
  837. ASSERT (NameLength == UserNameBufLen);
  838. }
  839. if (CommonName || UPNName){
  840. NameLength = 3;
  841. if (CommonName){
  842. NameLength += wcslen(CommonName);
  843. }
  844. if (UPNName){
  845. NameLength += wcslen(UPNName);
  846. }
  847. *UserDispName = new TCHAR[NameLength];
  848. if (CommonName){
  849. wcscpy(*UserDispName, CommonName);
  850. if (UPNName){
  851. wcscat(*UserDispName, L"(");
  852. wcscat(*UserDispName, UPNName);
  853. wcscat(*UserDispName, L")");
  854. }
  855. } else {
  856. wcscpy(*UserDispName, UPNName);
  857. }
  858. if (CommonName){
  859. delete [] CommonName;
  860. }
  861. if (UPNName){
  862. delete [] UPNName;
  863. }
  864. return ERROR_SUCCESS;
  865. }
  866. try {
  867. CString UnknownCertName;
  868. UnknownCertName.LoadString(IDS_NOCERTNAME);
  869. UserNameBufLen = UnknownCertName.GetLength();
  870. *UserDispName = new TCHAR[UserNameBufLen + 1];
  871. _tcscpy( *UserDispName, UnknownCertName);
  872. }
  873. catch (...){
  874. return ERROR_NOT_ENOUGH_MEMORY;
  875. }
  876. return ERROR_SUCCESS;
  877. }
  878. void USERLIST::OnAdd()
  879. {
  880. CRYPTUI_SELECTCERTIFICATE_STRUCTW cryptUI;
  881. HCERTSTORE otherStore;
  882. HCERTSTORE trustedStore;
  883. HCERTSTORE memStore;
  884. HCERTSTORE localStore[2];
  885. PCCERT_CONTEXT selectedCert;
  886. CString DlgTitle;
  887. CString DispText;
  888. LPTSTR UserDispName;
  889. HRESULT hr;
  890. DWORD rc;
  891. DWORD StoreNum = 0;
  892. DWORD StoreIndex = 0xffffffff;
  893. BOOL EfsEkuExist = FALSE;
  894. DWORD ii;
  895. BOOL ContinueProcess = TRUE;
  896. otherStore = CertOpenStore(
  897. CERT_STORE_PROV_SYSTEM_W,
  898. 0, // dwEncodingType
  899. 0, // hCryptProv,
  900. CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_MAXIMUM_ALLOWED_FLAG,
  901. OTHERPEOPLE
  902. );
  903. trustedStore = CertOpenStore(
  904. CERT_STORE_PROV_SYSTEM_W,
  905. 0, // dwEncodingType
  906. 0, // hCryptProv,
  907. CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_MAXIMUM_ALLOWED_FLAG,
  908. TRUSTEDPEOPLE
  909. );
  910. if (otherStore) {
  911. localStore[0] = otherStore;
  912. StoreNum++;
  913. }
  914. if (trustedStore) {
  915. localStore[StoreNum] = trustedStore;
  916. StoreNum++;
  917. }
  918. memStore = CertOpenStore(
  919. CERT_STORE_PROV_MEMORY,
  920. 0,
  921. 0,
  922. CERT_STORE_MAXIMUM_ALLOWED_FLAG,
  923. NULL
  924. );
  925. if (!memStore) {
  926. CString ErrMsg;
  927. TCHAR ErrCode[16];
  928. _ltot(GetLastError(), ErrCode, 10 );
  929. AfxFormatString1( ErrMsg, IDS_INTERNALERROR, ErrCode );
  930. MessageBox(ErrMsg);
  931. if (otherStore) {
  932. CertCloseStore( otherStore, 0 );
  933. }
  934. if (trustedStore) {
  935. CertCloseStore( trustedStore, 0 );
  936. }
  937. return;
  938. }
  939. //
  940. // Let's put it into a memory store to eliminate the redundancy
  941. //
  942. ii = 0;
  943. while ( (ii < StoreNum) && ContinueProcess ) {
  944. PCCERT_CONTEXT pCertContext = NULL;
  945. while (pCertContext = CertEnumCertificatesInStore(
  946. localStore[ii],
  947. pCertContext
  948. )) {
  949. if (!CertAddCertificateLinkToStore(
  950. memStore,
  951. pCertContext,
  952. CERT_STORE_ADD_USE_EXISTING,
  953. NULL
  954. )){
  955. CString ErrMsg;
  956. TCHAR ErrCode[16];
  957. _ltot(GetLastError(), ErrCode, 10 );
  958. AfxFormatString1( ErrMsg, IDS_INTERNALERROR, ErrCode );
  959. MessageBox(ErrMsg);
  960. ContinueProcess = FALSE;
  961. break;
  962. }
  963. }
  964. ii++;
  965. }
  966. if (!ContinueProcess) {
  967. if (otherStore) {
  968. CertCloseStore( otherStore, 0 );
  969. }
  970. if (trustedStore) {
  971. CertCloseStore( trustedStore, 0 );
  972. }
  973. CertCloseStore( memStore, 0 );
  974. return;
  975. }
  976. if (StoreNum != 0) {
  977. RtlZeroMemory(&cryptUI, sizeof (CRYPTUI_SELECTCERTIFICATE_STRUCTW));
  978. cryptUI.dwSize = sizeof (CRYPTUI_SELECTCERTIFICATE_STRUCTW);
  979. cryptUI.dwFlags = CRYPTUI_SELECTCERT_ADDFROMDS;
  980. cryptUI.cDisplayStores = 1;
  981. cryptUI.rghDisplayStores = &memStore;
  982. cryptUI.pFilterCallback = EfsFilter;
  983. cryptUI.dwDontUseColumn = CRYPTUI_SELECT_LOCATION_COLUMN | CRYPTUI_SELECT_ISSUEDBY_COLUMN | CRYPTUI_SELECT_INTENDEDUSE_COLUMN;
  984. if (DlgTitle.LoadString(IDS_DLGTITLE)){
  985. cryptUI.szTitle = (LPCWSTR) DlgTitle.GetBuffer(DlgTitle.GetLength() + 1);
  986. }
  987. if (DispText.LoadString(IDS_DISPTEXT)){
  988. cryptUI.szDisplayString = (LPCWSTR) DispText.GetBuffer(DispText.GetLength() + 1);
  989. }
  990. selectedCert = CryptUIDlgSelectCertificateW(&cryptUI);
  991. if ( selectedCert ){
  992. PCCERT_CHAIN_CONTEXT pChainContext;
  993. //
  994. // Let's first see if the cert is from DS, if Yes, add the EFS EKU first if no EKU.
  995. //
  996. StoreIndex = CertInStore(localStore, StoreNum, selectedCert);
  997. if (StoreIndex >= StoreNum){
  998. //
  999. // The cert is not in the local stores. Let's see if we need add the EKU or not.
  1000. //
  1001. EfsEkuExist = EfsFilter(selectedCert, NULL, NULL);
  1002. if (!EfsEkuExist) {
  1003. //
  1004. // Let's add the EFS EKU
  1005. //
  1006. CTL_USAGE EfsEkuUsage;
  1007. DWORD cbEncoded;
  1008. void *pbEncoded;
  1009. CRYPT_DATA_BLOB EfsEkuBlob;
  1010. EfsEkuUsage.cUsageIdentifier = 1; // Only adding EFS EKU
  1011. EfsEkuUsage.rgpszUsageIdentifier = &EfsOidlpstr;
  1012. if(!CryptEncodeObjectEx(
  1013. X509_ASN_ENCODING,
  1014. szOID_ENHANCED_KEY_USAGE,
  1015. &EfsEkuUsage,
  1016. CRYPT_ENCODE_ALLOC_FLAG,
  1017. NULL, // Use LocalFree
  1018. &pbEncoded,
  1019. &cbEncoded
  1020. )){
  1021. //
  1022. // Failed to encode the EFS EKU
  1023. //
  1024. CString ErrMsg;
  1025. TCHAR ErrCode[16];
  1026. ContinueProcess = FALSE;
  1027. _ltot(GetLastError(), ErrCode, 10 );
  1028. AfxFormatString1( ErrMsg, IDS_ADDEFSEKUFAIL, ErrCode );
  1029. MessageBox(ErrMsg);
  1030. } else {
  1031. //
  1032. // Now let's add the EKU to the cert
  1033. //
  1034. EfsEkuBlob.cbData=cbEncoded;
  1035. EfsEkuBlob.pbData=(BYTE *)pbEncoded;
  1036. if(!CertSetCertificateContextProperty(
  1037. selectedCert,
  1038. CERT_ENHKEY_USAGE_PROP_ID,
  1039. 0,
  1040. &EfsEkuBlob)){
  1041. //
  1042. // Failed to add the EFS EKU
  1043. //
  1044. CString ErrMsg;
  1045. TCHAR ErrCode[16];
  1046. ContinueProcess = FALSE;
  1047. _ltot(GetLastError(), ErrCode, 10 );
  1048. AfxFormatString1( ErrMsg, IDS_ADDEFSEKUFAIL, ErrCode );
  1049. MessageBox(ErrMsg);
  1050. }
  1051. }
  1052. }
  1053. }
  1054. //
  1055. // Let's validate the cert first
  1056. //
  1057. if (ContinueProcess && CertGetCertificateChain (
  1058. HCCE_CURRENT_USER,
  1059. selectedCert,
  1060. NULL,
  1061. NULL,
  1062. &m_CertChainPara,
  1063. CERT_CHAIN_REVOCATION_CHECK_CHAIN,
  1064. NULL,
  1065. &pChainContext
  1066. )) {
  1067. PCERT_SIMPLE_CHAIN pChain = pChainContext->rgpChain[ 0 ];
  1068. PCERT_CHAIN_ELEMENT pElement = pChain->rgpElement[ 0 ];
  1069. BOOL bSelfSigned = pElement->TrustStatus.dwInfoStatus & CERT_TRUST_IS_SELF_SIGNED;
  1070. BOOL ContinueAdd = TRUE;
  1071. DWORD dwErrorStatus = pChainContext->TrustStatus.dwErrorStatus;
  1072. if (0 == (dwErrorStatus & ~CERT_TRUST_REVOCATION_STATUS_UNKNOWN)) {
  1073. //
  1074. // The validation succeed. If the cert is from the DS (not in the store we opened), we will put it
  1075. // in the my Other People's store
  1076. //
  1077. if (StoreIndex >= StoreNum) {
  1078. //
  1079. // The cert is not in our local stores. Add it to the other people
  1080. //
  1081. if (otherStore) {
  1082. if(!CertAddCertificateContextToStore(
  1083. otherStore,
  1084. selectedCert,
  1085. CERT_STORE_ADD_NEW,
  1086. NULL) ) {
  1087. //
  1088. // The error code is only for debug.
  1089. // If we failed to add the cert to other People store,
  1090. // it is fine to continue
  1091. //
  1092. rc = GetLastError();
  1093. }
  1094. }
  1095. }
  1096. } else {
  1097. //
  1098. // The cert validation failed, as the user if we will accept the cert. If yes, the cert
  1099. // will be added to my TrustedPeople.
  1100. //
  1101. // (((dwErrorStatus & ~CERT_TRUST_REVOCATION_STATUS_UNKNOWN) == CERT_TRUST_IS_UNTRUSTED_ROOT) && bSelfSigned) {
  1102. if (bSelfSigned && !(dwErrorStatus & (CERT_TRUST_IS_NOT_TIME_VALID |
  1103. CERT_TRUST_IS_NOT_SIGNATURE_VALID |
  1104. CERT_TRUST_IS_NOT_VALID_FOR_USAGE))){
  1105. //
  1106. // A self signed cert. Ask the user if he would like to accept.
  1107. // If it is already in the trusted store, we can skip the pop up.
  1108. //
  1109. DWORD StoreIndex;
  1110. if (trustedStore) {
  1111. StoreIndex = CertInStore(&trustedStore, 1, selectedCert);
  1112. }
  1113. if (StoreIndex >= 1) {
  1114. CString ErrMsg;
  1115. TCHAR ErrCode[16];
  1116. int buttonID;
  1117. _ltot(GetLastError(), ErrCode, 10 );
  1118. AfxFormatString1( ErrMsg, IDS_ACCEPTSELFCERT, ErrCode );
  1119. buttonID = MessageBox(ErrMsg, NULL, MB_ICONQUESTION | MB_YESNO);
  1120. if (IDYES == buttonID) {
  1121. //
  1122. // User Accepted the cert.
  1123. //
  1124. if (trustedStore) {
  1125. if(!CertAddCertificateContextToStore(
  1126. trustedStore,
  1127. selectedCert,
  1128. CERT_STORE_ADD_NEW,
  1129. NULL) ) {
  1130. //
  1131. // The error code is only for debug.
  1132. // If we failed to add the cert to other People store,
  1133. // it is fine to continue
  1134. //
  1135. rc = GetLastError();
  1136. }
  1137. }
  1138. } else {
  1139. //
  1140. // User declined the cert.
  1141. //
  1142. ContinueAdd = FALSE;
  1143. }
  1144. }
  1145. } else {
  1146. //
  1147. // Let's get the error code of the chain building.
  1148. //
  1149. CERT_CHAIN_POLICY_PARA PolicyPara;
  1150. CERT_CHAIN_POLICY_STATUS PolicyStatus;
  1151. ContinueAdd = FALSE;
  1152. RtlZeroMemory(&PolicyPara, sizeof(CERT_CHAIN_POLICY_PARA));
  1153. RtlZeroMemory(&PolicyStatus, sizeof(CERT_CHAIN_POLICY_STATUS));
  1154. PolicyPara.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
  1155. PolicyStatus.cbSize = sizeof(CERT_CHAIN_POLICY_STATUS);
  1156. if (CertVerifyCertificateChainPolicy(
  1157. CERT_CHAIN_POLICY_BASE,
  1158. pChainContext,
  1159. &PolicyPara,
  1160. &PolicyStatus
  1161. ) && PolicyStatus.dwError ) {
  1162. //
  1163. // Display the error to the user.
  1164. //
  1165. DWORD len;
  1166. LPWSTR DisplayBuffer;
  1167. len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  1168. NULL, PolicyStatus.dwError, 0,
  1169. (LPWSTR)&DisplayBuffer, 0, NULL);
  1170. if (len && DisplayBuffer) {
  1171. MessageBox(DisplayBuffer);
  1172. LocalFree(DisplayBuffer);
  1173. }
  1174. }
  1175. }
  1176. }
  1177. CertFreeCertificateChain( pChainContext );
  1178. if (ContinueAdd) {
  1179. hr = GetCertNameFromCertContext(selectedCert, &UserDispName);
  1180. if ( ERROR_SUCCESS == hr ){
  1181. EFS_CERTIFICATE_BLOB CertBlob;
  1182. CertBlob.cbData = selectedCert->cbCertEncoded;
  1183. CertBlob.pbData = selectedCert->pbCertEncoded;
  1184. CertBlob.dwCertEncodingType = selectedCert->dwCertEncodingType;
  1185. hr = m_Users.Add(
  1186. UserDispName,
  1187. (PVOID)&CertBlob,
  1188. NULL,
  1189. USERADDED,
  1190. (PVOID)selectedCert
  1191. );
  1192. if ( (ERROR_SUCCESS != hr) && (CRYPT_E_EXISTS != hr) ){
  1193. //
  1194. // Error in adding the user
  1195. //
  1196. CertFreeCertificateContext(selectedCert);
  1197. selectedCert = NULL;
  1198. } else {
  1199. //
  1200. // We could just insert the items here to improve the performace.
  1201. // But we don't have the time right now. We could fix this later
  1202. // if performance is a problem here.
  1203. //
  1204. m_UserListCtrl.DeleteAllItems( );
  1205. SetUpListBox(NULL);
  1206. if ( hr == ERROR_SUCCESS ){
  1207. //
  1208. // UserDispName is used in m_Users.Add
  1209. //
  1210. UserDispName = NULL;
  1211. }
  1212. /* This is the old code when we have the single list.
  1213. //
  1214. // Add the user to the list box.
  1215. //
  1216. if ( hr == ERROR_SUCCESS ){
  1217. if (m_UsersList.AddString(UserDispName) < 0){
  1218. //
  1219. // Error to add to the list box
  1220. //
  1221. m_Users.Remove(UserDispName);
  1222. }
  1223. UserDispName = NULL;
  1224. } else {
  1225. //
  1226. // Let's check if we need to add this to the list box.
  1227. //
  1228. if (m_UsersList.FindStringExact( 0, UserDispName ) < 0){
  1229. //
  1230. // Not found
  1231. //
  1232. if (m_UsersList.AddString(UserDispName) < 0){
  1233. //
  1234. // Error to add to the list box
  1235. //
  1236. m_Users.Remove(UserDispName);
  1237. }
  1238. }
  1239. }
  1240. */
  1241. }
  1242. if (UserDispName){
  1243. delete [] UserDispName;
  1244. }
  1245. } else {
  1246. CertFreeCertificateContext(selectedCert);
  1247. }
  1248. }
  1249. } else {
  1250. CString ErrMsg;
  1251. TCHAR ErrCode[16];
  1252. CertFreeCertificateContext(selectedCert);
  1253. if (ContinueProcess) {
  1254. //
  1255. // The error has not been processed.
  1256. //
  1257. _ltot(GetLastError(), ErrCode, 10 );
  1258. AfxFormatString1( ErrMsg, IDS_COULDNOTVERIFYCERT, ErrCode );
  1259. MessageBox(ErrMsg);
  1260. }
  1261. }
  1262. }
  1263. if (!DlgTitle.IsEmpty()){
  1264. DlgTitle.ReleaseBuffer();
  1265. }
  1266. if (!DispText.IsEmpty()){
  1267. DispText.ReleaseBuffer();
  1268. }
  1269. if (otherStore) {
  1270. CertCloseStore( otherStore, 0 );
  1271. }
  1272. if (trustedStore) {
  1273. CertCloseStore( trustedStore, 0 );
  1274. }
  1275. }
  1276. CertCloseStore( memStore, 0 );
  1277. return;
  1278. }
  1279. DWORD USERLIST::TryGetBetterNameInCert(PEFS_HASH_BLOB HashData, LPTSTR *UserName)
  1280. {
  1281. HCERTSTORE localStore;
  1282. PCCERT_CONTEXT pCertContext;
  1283. DWORD retCode;
  1284. //
  1285. // We will add the remote case later
  1286. //
  1287. localStore = CertOpenStore(
  1288. CERT_STORE_PROV_SYSTEM_W,
  1289. 0, // dwEncodingType
  1290. 0, // hCryptProv,
  1291. CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_MAXIMUM_ALLOWED_FLAG,
  1292. TRUSTEDPEOPLE
  1293. );
  1294. if (localStore != NULL) {
  1295. //
  1296. // Let's try to the cert in the store
  1297. //
  1298. pCertContext = CertFindCertificateInStore( localStore,
  1299. CRYPT_ASN_ENCODING,
  1300. 0,
  1301. CERT_FIND_HASH,
  1302. (CRYPT_HASH_BLOB *)HashData,
  1303. NULL
  1304. );
  1305. if ( pCertContext ){
  1306. retCode = GetCertNameFromCertContext(
  1307. pCertContext,
  1308. UserName
  1309. );
  1310. CertFreeCertificateContext(pCertContext);
  1311. }
  1312. else {
  1313. retCode = GetLastError();
  1314. }
  1315. CertCloseStore( localStore, 0 );
  1316. } else {
  1317. retCode = GetLastError();
  1318. }
  1319. return retCode;
  1320. }
  1321. DWORD USERLIST::CertInStore(HCERTSTORE *pStores, DWORD StoreNum, PCCERT_CONTEXT selectedCert)
  1322. {
  1323. DWORD ii = 0;
  1324. PCCERT_CONTEXT pCert = NULL;
  1325. while (ii < StoreNum) {
  1326. pCert = CertFindCertificateInStore(
  1327. pStores[ii],
  1328. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1329. 0,
  1330. CERT_FIND_EXISTING,
  1331. selectedCert,
  1332. pCert
  1333. );
  1334. if (pCert) {
  1335. //
  1336. // We found it.
  1337. //
  1338. CertFreeCertificateContext(pCert);
  1339. break;
  1340. }
  1341. ii++;
  1342. }
  1343. return ii;
  1344. }
  1345. void USERLIST::OnSetfocusListuser(NMHDR* pNMHDR, LRESULT* pResult)
  1346. {
  1347. int ItemPos;
  1348. ShowRemove();
  1349. ShowBackup();
  1350. ItemPos = m_UserListCtrl.GetNextItem( -1, LVNI_SELECTED );
  1351. if ( ItemPos == -1 ){
  1352. m_UserListCtrl.SetItem(0, 0, LVIF_STATE, NULL, 0, LVIS_SELECTED, LVIS_SELECTED, 0);
  1353. }
  1354. *pResult = 0;
  1355. }
  1356. void USERLIST::OnKillfocusListuser(NMHDR* pNMHDR, LRESULT* pResult)
  1357. {
  1358. ShowRemove();
  1359. ShowBackup();
  1360. *pResult = 0;
  1361. }
  1362. void USERLIST::OnItemchangedListuser(NMHDR* pNMHDR, LRESULT* pResult)
  1363. {
  1364. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  1365. ShowRemove();
  1366. ShowBackup();
  1367. *pResult = 0;
  1368. }
  1369. void USERLIST::OnSetfocusListra(NMHDR* pNMHDR, LRESULT* pResult)
  1370. {
  1371. int ItemPos;
  1372. ItemPos = m_RecoveryListCtrl.GetNextItem( -1, LVNI_SELECTED );
  1373. if ( ItemPos == -1 ){
  1374. if (m_RecoveryListCtrl.GetItemCount( ) > 0){
  1375. m_RecoveryListCtrl.SetItem(0, 0, LVIF_STATE, NULL, 0, LVIS_SELECTED, LVIS_SELECTED, 0);
  1376. }
  1377. }
  1378. *pResult = 0;
  1379. }
  1380. void USERLIST::OnBackup()
  1381. {
  1382. int ItemPos;
  1383. DWORD rc;
  1384. PCRYPT_HASH_BLOB pHashBlob;
  1385. PCCERT_CONTEXT pCertContext = NULL;
  1386. PCRYPT_KEY_PROV_INFO pCryptKeyProvInfo = NULL;
  1387. HCRYPTKEY hLocalKey = 0;
  1388. HCRYPTPROV hLocalProv = 0;
  1389. BOOLEAN ValidCertFound = FALSE;
  1390. BOOL NoAction = FALSE;
  1391. CString NoCertName;
  1392. try{
  1393. NoCertName.LoadString(IDS_NOCERTNAME);
  1394. }
  1395. catch(...){
  1396. NoAction = TRUE;
  1397. }
  1398. if (NoAction){
  1399. return;
  1400. }
  1401. //
  1402. // Get the selected item first
  1403. //
  1404. ItemPos = m_UserListCtrl.GetNextItem( -1, LVNI_SELECTED );
  1405. if ( ItemPos != -1 ){
  1406. //
  1407. // Get the hash
  1408. //
  1409. CString CertName;
  1410. LPTSTR pCertName;
  1411. BOOLEAN ReleaseCertContext = FALSE;
  1412. CertName = m_UserListCtrl.GetItemText( ItemPos, 0 );
  1413. if ( !CertName.Compare(NoCertName) ){
  1414. pCertName = NULL;
  1415. } else {
  1416. pCertName = CertName.GetBuffer(CertName.GetLength() + 1);
  1417. }
  1418. rc = m_Users.GetCertInfo(
  1419. pCertName,
  1420. (PVOID *) &pHashBlob,
  1421. (PVOID *) &pCertContext
  1422. );
  1423. if (pCertName){
  1424. CertName.ReleaseBuffer();
  1425. }
  1426. if (rc == ERROR_SUCCESS) {
  1427. if (pCertContext == NULL) {
  1428. //
  1429. // We don't have the cert context. Try to create one
  1430. //
  1431. pCertContext = GetCertInMyStore(pHashBlob);
  1432. if (pCertContext) {
  1433. ReleaseCertContext = TRUE;
  1434. } else {
  1435. rc = GetLastError();
  1436. }
  1437. }
  1438. //
  1439. // We should have the cert context now
  1440. //
  1441. if (pCertContext) {
  1442. //
  1443. // Now try to get the keys.
  1444. //
  1445. ValidCertFound = CertHasKey(pCertContext);
  1446. if (ValidCertFound) {
  1447. BOOL bRet;
  1448. //
  1449. // Now do the export
  1450. //
  1451. CRYPTUI_WIZ_EXPORT_INFO myWizardInfo;
  1452. RtlZeroMemory(&myWizardInfo, sizeof (CRYPTUI_WIZ_EXPORT_INFO));
  1453. myWizardInfo.dwSize = sizeof(CRYPTUI_WIZ_EXPORT_INFO);
  1454. myWizardInfo.dwSubjectChoice = CRYPTUI_WIZ_EXPORT_CERT_CONTEXT;
  1455. myWizardInfo.pCertContext = pCertContext;
  1456. bRet = CryptUIWizExport(
  1457. CRYPTUI_WIZ_EXPORT_PRIVATE_KEY | CRYPTUI_WIZ_EXPORT_NO_DELETE_PRIVATE_KEY,
  1458. NULL,
  1459. NULL,
  1460. &myWizardInfo,
  1461. NULL
  1462. );
  1463. if (!bRet) {
  1464. //
  1465. // Give the error message
  1466. //
  1467. rc = GetLastError();
  1468. if (ERROR_CANCELLED != rc) {
  1469. CString ErrMsg;
  1470. TCHAR ErrCode[16];
  1471. _ltot(rc, ErrCode, 10 );
  1472. AfxFormatString1( ErrMsg, IDS_NOCERTORKEY, ErrCode );
  1473. MessageBox(ErrMsg);
  1474. }
  1475. }
  1476. } else {
  1477. //
  1478. // Give the error message
  1479. //
  1480. CString ErrMsg;
  1481. TCHAR ErrCode[16];
  1482. rc = GetLastError();
  1483. _ltot(rc, ErrCode, 10 );
  1484. AfxFormatString1( ErrMsg, IDS_NOCERTORKEY, ErrCode );
  1485. MessageBox(ErrMsg);
  1486. }
  1487. if (ReleaseCertContext) {
  1488. CertFreeCertificateContext( pCertContext );
  1489. }
  1490. } else {
  1491. //
  1492. // The cert is not available
  1493. //
  1494. //
  1495. // Give the error message
  1496. //
  1497. CString ErrMsg;
  1498. TCHAR ErrCode[16];
  1499. _ltot(rc, ErrCode, 10 );
  1500. AfxFormatString1( ErrMsg, IDS_NOCERTORKEY, ErrCode );
  1501. MessageBox(ErrMsg);
  1502. }
  1503. } else {
  1504. //
  1505. // We should not come here. The user were added by us. We expect to find him in our list.
  1506. //
  1507. ASSERT(FALSE);
  1508. return;
  1509. }
  1510. }
  1511. }
  1512. void USERLIST::ShowBackup()
  1513. {
  1514. if (m_UserListCtrl.GetSelectedCount() == 1){
  1515. //
  1516. // Enable the Backup Button
  1517. //
  1518. m_BackupButton.EnableWindow( TRUE );
  1519. } else {
  1520. //
  1521. // Disable the Backup Button
  1522. //
  1523. m_BackupButton.EnableWindow( FALSE );
  1524. }
  1525. }
  1526. PCCERT_CONTEXT
  1527. GetCertInMyStore(
  1528. PCRYPT_HASH_BLOB pHashBlob
  1529. )
  1530. {
  1531. DWORD rc = ERROR_SUCCESS;
  1532. HCERTSTORE myStore;
  1533. PCCERT_CONTEXT pCertContext = NULL;
  1534. myStore = CertOpenStore(
  1535. CERT_STORE_PROV_SYSTEM_REGISTRY_W,
  1536. 0, // dwEncodingType
  1537. 0, // hCryptProv,
  1538. CERT_SYSTEM_STORE_CURRENT_USER,
  1539. L"My"
  1540. );
  1541. if (myStore != NULL) {
  1542. //
  1543. // Let's try to get the cert in the store
  1544. //
  1545. pCertContext = CertFindCertificateInStore( myStore,
  1546. CRYPT_ASN_ENCODING,
  1547. 0,
  1548. CERT_FIND_HASH,
  1549. pHashBlob,
  1550. NULL
  1551. );
  1552. if (pCertContext == NULL) {
  1553. rc = GetLastError();
  1554. }
  1555. CertCloseStore( myStore, 0 );
  1556. if (rc != ERROR_SUCCESS) {
  1557. SetLastError(rc);
  1558. }
  1559. }
  1560. return pCertContext;
  1561. }
  1562. PCRYPT_KEY_PROV_INFO
  1563. GetKeyProvInfo(
  1564. PCCERT_CONTEXT pCertContext
  1565. )
  1566. {
  1567. DWORD cbData = 0;
  1568. BOOL b;
  1569. PCRYPT_KEY_PROV_INFO pCryptKeyProvInfo = NULL;
  1570. b = CertGetCertificateContextProperty(
  1571. pCertContext,
  1572. CERT_KEY_PROV_INFO_PROP_ID,
  1573. NULL,
  1574. &cbData
  1575. );
  1576. if (b) {
  1577. pCryptKeyProvInfo = (PCRYPT_KEY_PROV_INFO) new BYTE[cbData];
  1578. if (pCryptKeyProvInfo != NULL) {
  1579. b = CertGetCertificateContextProperty(
  1580. pCertContext,
  1581. CERT_KEY_PROV_INFO_PROP_ID,
  1582. pCryptKeyProvInfo,
  1583. &cbData
  1584. );
  1585. if (!b) {
  1586. delete [] pCryptKeyProvInfo;
  1587. pCryptKeyProvInfo = NULL;
  1588. }
  1589. } else {
  1590. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  1591. }
  1592. }
  1593. return ( pCryptKeyProvInfo );
  1594. }
  1595. BOOLEAN
  1596. CertHasKey(
  1597. PCCERT_CONTEXT pCertContext
  1598. )
  1599. {
  1600. PCRYPT_KEY_PROV_INFO pCryptKeyProvInfo = NULL;
  1601. DWORD rc = ERROR_SUCCESS;
  1602. HCRYPTKEY hLocalKey = 0;
  1603. HCRYPTPROV hLocalProv = 0;
  1604. BOOLEAN ValidCertFound = FALSE;
  1605. pCryptKeyProvInfo = GetKeyProvInfo( pCertContext );
  1606. if (pCryptKeyProvInfo) {
  1607. if (CryptAcquireContext( &hLocalProv, pCryptKeyProvInfo->pwszContainerName, pCryptKeyProvInfo->pwszProvName, PROV_RSA_FULL, CRYPT_SILENT)) {
  1608. if (CryptGetUserKey(hLocalProv, AT_KEYEXCHANGE, &hLocalKey)) {
  1609. //
  1610. // We found the key. Let's add the cert to Memory store
  1611. //
  1612. ValidCertFound = TRUE;
  1613. CryptDestroyKey( hLocalKey );
  1614. } else {
  1615. rc = GetLastError();
  1616. }
  1617. CryptReleaseContext( hLocalProv, 0 );
  1618. } else {
  1619. rc = GetLastError();
  1620. }
  1621. delete [] pCryptKeyProvInfo;
  1622. }
  1623. if (rc != ERROR_SUCCESS) {
  1624. SetLastError(rc);
  1625. }
  1626. return ValidCertFound;
  1627. }
  1628. void CALLBACK
  1629. BackCurrentEfsCert(
  1630. HWND hwnd,
  1631. HINSTANCE hinst,
  1632. LPWSTR lpszCmdLine,
  1633. int nCmdShow
  1634. )
  1635. {
  1636. DWORD RetCode;
  1637. HKEY hRegKey = NULL;
  1638. CRYPT_HASH_BLOB HashBlob;
  1639. PCCERT_CONTEXT pCertContext=NULL;
  1640. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1641. RetCode = RegOpenKeyEx(
  1642. HKEY_CURRENT_USER,
  1643. KEYPATH,
  1644. 0,
  1645. GENERIC_READ,
  1646. &hRegKey
  1647. );
  1648. if (RetCode == ERROR_SUCCESS) {
  1649. DWORD Type;
  1650. RetCode = RegQueryValueEx(
  1651. hRegKey,
  1652. CERT_HASH,
  1653. NULL,
  1654. &Type,
  1655. NULL,
  1656. &(HashBlob.cbData)
  1657. );
  1658. if (RetCode == ERROR_SUCCESS) {
  1659. //
  1660. // Query out the thumbprint, find the cert, and return the key information.
  1661. //
  1662. if ( HashBlob.pbData = (PBYTE) malloc(HashBlob.cbData) ) {
  1663. RetCode = RegQueryValueEx(
  1664. hRegKey,
  1665. CERT_HASH,
  1666. NULL,
  1667. &Type,
  1668. HashBlob.pbData,
  1669. &(HashBlob.cbData)
  1670. );
  1671. if (RetCode == ERROR_SUCCESS) {
  1672. //
  1673. // We get the cert hash.
  1674. //
  1675. pCertContext = GetCertInMyStore(&HashBlob);
  1676. if (pCertContext != NULL) {
  1677. BOOLEAN ValidCertFound;
  1678. //
  1679. // Let's try to see if keys are available
  1680. //
  1681. ValidCertFound = CertHasKey(pCertContext);
  1682. if (ValidCertFound) {
  1683. BOOL bRet;
  1684. //
  1685. // Now do the export
  1686. //
  1687. CRYPTUI_WIZ_EXPORT_INFO myWizardInfo;
  1688. RtlZeroMemory(&myWizardInfo, sizeof (CRYPTUI_WIZ_EXPORT_INFO));
  1689. myWizardInfo.dwSize = sizeof(CRYPTUI_WIZ_EXPORT_INFO);
  1690. myWizardInfo.dwSubjectChoice = CRYPTUI_WIZ_EXPORT_CERT_CONTEXT;
  1691. myWizardInfo.pCertContext = pCertContext;
  1692. if (!CryptUIWizExport(
  1693. CRYPTUI_WIZ_EXPORT_PRIVATE_KEY | CRYPTUI_WIZ_EXPORT_NO_DELETE_PRIVATE_KEY,
  1694. NULL,
  1695. NULL,
  1696. &myWizardInfo,
  1697. NULL
  1698. )){
  1699. RetCode = GetLastError();
  1700. if (ERROR_CANCELLED != RetCode) {
  1701. CString ErrMsg;
  1702. TCHAR ErrCode[16];
  1703. _ltot(RetCode, ErrCode, 10 );
  1704. AfxFormatString1( ErrMsg, IDS_NOCERTORKEY, ErrCode );
  1705. MessageBox(hwnd, ErrMsg, NULL, MB_OK);
  1706. }
  1707. }
  1708. } else {
  1709. //
  1710. // Cert has no key.
  1711. //
  1712. RetCode = GetLastError();
  1713. CString ErrMsg;
  1714. TCHAR ErrCode[16];
  1715. _ltot(RetCode, ErrCode, 10 );
  1716. AfxFormatString1( ErrMsg, IDS_NOCERTORKEY, ErrCode );
  1717. MessageBox(hwnd, ErrMsg, NULL, MB_OK);
  1718. }
  1719. CertFreeCertificateContext( pCertContext );
  1720. pCertContext = NULL;
  1721. } else {
  1722. //
  1723. // Cert not find in MY store
  1724. //
  1725. RetCode = GetLastError();
  1726. CString ErrMsg;
  1727. TCHAR ErrCode[16];
  1728. _ltot(RetCode, ErrCode, 10 );
  1729. AfxFormatString1( ErrMsg, IDS_CERTNOTINMY, ErrCode );
  1730. MessageBox(hwnd, ErrMsg, NULL, MB_OK);
  1731. }
  1732. } else {
  1733. //
  1734. // Error in read EFS current key. Not likely to happen.
  1735. //
  1736. CString ErrMsg;
  1737. TCHAR ErrCode[16];
  1738. _ltot(RetCode, ErrCode, 10 );
  1739. AfxFormatString1( ErrMsg, IDS_NOCRNTCERT, ErrCode );
  1740. MessageBox(hwnd, ErrMsg, NULL, MB_OK);
  1741. }
  1742. free(HashBlob.pbData);
  1743. } else {
  1744. //
  1745. // Out of memory
  1746. //
  1747. CString ErrMsg;
  1748. if (ErrMsg.LoadString(IDS_ERRORMEM)){
  1749. MessageBox(hwnd, ErrMsg, NULL, MB_OK);
  1750. }
  1751. }
  1752. } else {
  1753. //
  1754. // No current EFS Cert
  1755. //
  1756. CString ErrMsg;
  1757. TCHAR ErrCode[16];
  1758. _ltot(RetCode, ErrCode, 10 );
  1759. AfxFormatString1( ErrMsg, IDS_NOCRNTCERT, ErrCode );
  1760. MessageBox(hwnd, ErrMsg, NULL, MB_OK);
  1761. }
  1762. //
  1763. // Close the key handle
  1764. //
  1765. RegCloseKey( hRegKey );
  1766. } else {
  1767. //
  1768. // No current EFS Cert
  1769. //
  1770. CString ErrMsg;
  1771. TCHAR ErrCode[16];
  1772. _ltot(RetCode, ErrCode, 10 );
  1773. AfxFormatString1( ErrMsg, IDS_NOCRNTCERT, ErrCode );
  1774. MessageBox(hwnd, ErrMsg, NULL, MB_OK);
  1775. }
  1776. }
  1777. void CALLBACK
  1778. AddUserToObjectW(
  1779. HWND hwnd,
  1780. HINSTANCE hinst,
  1781. LPWSTR lpszCmdLine,
  1782. int nCmdShow
  1783. )
  1784. {
  1785. DWORD FileAttributes = GetFileAttributes(lpszCmdLine);
  1786. if ((-1 == FileAttributes) || (!(FileAttributes & FILE_ATTRIBUTE_ENCRYPTED)) || ((FileAttributes & FILE_ATTRIBUTE_DIRECTORY))) {
  1787. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1788. if (-1 == FileAttributes) {
  1789. CString ErrMsg;
  1790. if (ErrMsg.LoadString(IDS_NOOBJECT)){
  1791. MessageBox(hwnd, ErrMsg, NULL, MB_OK);
  1792. }
  1793. return;
  1794. }
  1795. if ( !(FileAttributes & FILE_ATTRIBUTE_ENCRYPTED)){
  1796. CString ErrMsg;
  1797. if (ErrMsg.LoadString(IDS_NOTENCRYPTED)){
  1798. MessageBox(hwnd, ErrMsg, NULL, MB_OK);
  1799. }
  1800. return;
  1801. }
  1802. if ( (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)){
  1803. CString ErrMsg;
  1804. if (ErrMsg.LoadString(IDS_NOADDUSERDIR)){
  1805. MessageBox(hwnd, ErrMsg, NULL, MB_OK);
  1806. }
  1807. return;
  1808. }
  1809. }
  1810. EfsDetail(hwnd, lpszCmdLine);
  1811. }