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.

646 lines
17 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997-2001.
  5. //
  6. // File: Users.cpp
  7. //
  8. // Contents:
  9. //
  10. //----------------------------------------------------------------------------
  11. // Users.cpp: implementation of the CUsers class.
  12. //
  13. //////////////////////////////////////////////////////////////////////
  14. #include "stdafx.h"
  15. #include "Users.h"
  16. #ifdef _DEBUG
  17. #undef THIS_FILE
  18. static char THIS_FILE[]=__FILE__;
  19. #ifndef ALPHA
  20. #define new DEBUG_NEW
  21. #endif
  22. #endif
  23. //////////////////////////////////////////////////////////////////////
  24. // Construction/Destruction
  25. //////////////////////////////////////////////////////////////////////
  26. CUsers::CUsers()
  27. {
  28. m_UsersRoot = NULL;
  29. m_UserAddedCnt = 0;
  30. m_UserRemovedCnt = 0;
  31. }
  32. //////////////////////////////////////////////////////////////////////
  33. // Walk through the chain to free the memory
  34. //////////////////////////////////////////////////////////////////////
  35. CUsers::~CUsers()
  36. {
  37. Clear();
  38. }
  39. PUSERSONFILE
  40. CUsers::RemoveItemFromHead(void)
  41. {
  42. PUSERSONFILE PItem = m_UsersRoot;
  43. if (m_UsersRoot){
  44. m_UsersRoot = m_UsersRoot->m_pNext;
  45. if ((PItem->m_dwFlag & USERADDED) && !(PItem->m_dwFlag & USERREMOVED)){
  46. m_UserAddedCnt--;
  47. }
  48. if ((PItem->m_dwFlag & USERINFILE) && (PItem->m_dwFlag & USERREMOVED)){
  49. m_UserRemovedCnt--;
  50. }
  51. }
  52. return PItem;
  53. }
  54. DWORD
  55. CUsers::Add( CUsers &NewUsers )
  56. {
  57. PUSERSONFILE NewItem = NewUsers.RemoveItemFromHead();
  58. while ( NewItem )
  59. {
  60. PUSERSONFILE TmpItem = m_UsersRoot;
  61. while ( TmpItem )
  62. {
  63. if ((NewItem->m_szUserName && TmpItem->m_szUserName && !_tcsicmp(NewItem->m_szUserName, TmpItem->m_szUserName)) ||
  64. ( !NewItem->m_szUserName && !TmpItem->m_szUserName))
  65. {
  66. if ( !TmpItem->m_szUserName)
  67. {
  68. bool bUserMatched = false;
  69. if (( !NewItem->m_szDnName && !TmpItem->m_szDnName) ||
  70. (NewItem->m_szDnName && TmpItem->m_szDnName && !_tcsicmp(NewItem->m_szDnName, TmpItem->m_szDnName)))
  71. {
  72. bUserMatched = true;
  73. }
  74. if ( !bUserMatched )
  75. {
  76. TmpItem = TmpItem->m_pNext;
  77. continue;
  78. }
  79. }
  80. //
  81. // User exist
  82. //
  83. if ( TmpItem->m_dwFlag & USERREMOVED )
  84. {
  85. if ( TmpItem->m_dwFlag & USERADDED )
  86. {
  87. ASSERT(!(TmpItem->m_dwFlag & USERINFILE));
  88. //
  89. // User added and removed
  90. //
  91. m_UserAddedCnt++;
  92. }
  93. else if ( TmpItem->m_dwFlag & USERINFILE )
  94. {
  95. //
  96. // User added and removed
  97. //
  98. m_UserRemovedCnt--;
  99. }
  100. TmpItem->m_dwFlag &= ~USERREMOVED;
  101. }
  102. //
  103. // The caller will count on CUsers to release the memory
  104. //
  105. if (NewItem->m_szUserName)
  106. {
  107. delete [] NewItem->m_szUserName;
  108. }
  109. if (NewItem->m_szDnName)
  110. {
  111. delete [] NewItem->m_szDnName;
  112. }
  113. if ( NewItem->m_pCertContext )
  114. {
  115. CertFreeCertificateContext(NewItem->m_pCertContext);
  116. }
  117. delete [] NewItem->m_pCert;
  118. if (NewItem->m_UserSid)
  119. {
  120. delete [] NewItem->m_UserSid;
  121. }
  122. delete NewItem;
  123. NewItem = NULL;
  124. break;
  125. }
  126. TmpItem = TmpItem->m_pNext;
  127. }
  128. if (NewItem )
  129. {
  130. //
  131. // New item. Insert into the head.
  132. //
  133. NewItem->m_pNext = m_UsersRoot;
  134. m_UsersRoot = NewItem;
  135. m_UserAddedCnt++;
  136. }
  137. NewItem = NewUsers.RemoveItemFromHead();
  138. }
  139. return ERROR_SUCCESS;
  140. }
  141. DWORD
  142. CUsers::Add(
  143. LPWSTR pszUserName,
  144. LPWSTR pszDnName,
  145. PVOID UserCert,
  146. PSID UserSid, /* = NULL */
  147. DWORD dwFlag, /* = USERINFILE */
  148. PCCERT_CONTEXT pCertContext /* = NULL */
  149. )
  150. //////////////////////////////////////////////////////////////////////
  151. // Routine Description:
  152. // Create an item for a user
  153. // Arguments:
  154. // m_szUserName -- User's name
  155. // m_szDnName -- User's distinguished name
  156. // UserCert -- User's certificate blob or hash
  157. // m_UserSid -- User's ID. Can be NULL
  158. // m_dwFlag -- Indicate if the item is existing in the file, to be added or removed
  159. // Return Value:
  160. // NO_ERROR if succeed.
  161. // Will throw exception if memory allocation fails. ( From new.)
  162. //
  163. //////////////////////////////////////////////////////////////////////
  164. {
  165. PUSERSONFILE UserItem = 0;
  166. PUSERSONFILE TmpUserItem = m_UsersRoot;
  167. PEFS_CERTIFICATE_BLOB CertBlob;
  168. PEFS_HASH_BLOB CertHashBlob;
  169. DWORD CertSize;
  170. DWORD SidSize;
  171. if ( !UserCert )
  172. {
  173. return ERROR_INVALID_PARAMETER;
  174. }
  175. ASSERT ( (( dwFlag & USERADDED ) || ( dwFlag & USERINFILE )) &&
  176. ( (dwFlag & (USERADDED | USERINFILE)) != (USERADDED | USERINFILE)));
  177. //
  178. // If the user already in the memory, no new item is to be created except for unknown user
  179. //
  180. while ( TmpUserItem )
  181. {
  182. if ( (pszUserName && TmpUserItem->m_szUserName && !_tcsicmp(pszUserName, TmpUserItem->m_szUserName)) ||
  183. ((!pszUserName) && (TmpUserItem->m_szUserName == NULL)))
  184. {
  185. if (!pszUserName)
  186. {
  187. bool bUserMatched = false;
  188. if (( !pszDnName && !TmpUserItem->m_szDnName) ||
  189. (pszDnName && TmpUserItem->m_szDnName && !_tcsicmp(pszDnName, TmpUserItem->m_szDnName)))
  190. {
  191. bUserMatched = true;
  192. }
  193. if ( !bUserMatched )
  194. {
  195. TmpUserItem = TmpUserItem->m_pNext;
  196. continue;
  197. }
  198. }
  199. //
  200. // User exist
  201. //
  202. if ( TmpUserItem->m_dwFlag & USERREMOVED )
  203. {
  204. if ( TmpUserItem->m_dwFlag & USERADDED )
  205. {
  206. ASSERT(!(TmpUserItem->m_dwFlag & USERINFILE));
  207. //
  208. // User added and removed
  209. //
  210. m_UserAddedCnt++;
  211. }
  212. else if ( TmpUserItem->m_dwFlag & USERINFILE )
  213. {
  214. //
  215. // User added and removed
  216. //
  217. m_UserRemovedCnt--;
  218. }
  219. TmpUserItem->m_dwFlag &= ~USERREMOVED;
  220. }
  221. //
  222. // The caller will count on CUsers to release the memory
  223. // for Username and the context if the call is succeeded. This is just for
  224. // performance reason.
  225. //
  226. if (pszUserName)
  227. {
  228. delete [] pszUserName;
  229. }
  230. if (pszDnName)
  231. {
  232. delete [] pszDnName;
  233. }
  234. if ( pCertContext )
  235. {
  236. ::CertFreeCertificateContext (pCertContext);
  237. pCertContext = NULL;
  238. }
  239. return (DWORD) CRYPT_E_EXISTS;
  240. }
  241. TmpUserItem = TmpUserItem->m_pNext;
  242. }
  243. try {
  244. UserItem = new USERSONFILE;
  245. if ( !UserItem )
  246. {
  247. AfxThrowMemoryException( );
  248. }
  249. UserItem->m_pNext = NULL;
  250. //
  251. // In case exception raised, we can call delete.
  252. // Delete NULL is OK, but random data is not OK.
  253. //
  254. UserItem->m_UserSid = NULL;
  255. UserItem->m_pCert = NULL;
  256. UserItem->m_pCertContext = NULL;
  257. if ( UserSid )
  258. {
  259. SidSize = GetLengthSid (UserSid );
  260. if ( SidSize > 0 )
  261. {
  262. UserItem->m_UserSid = new BYTE[SidSize];
  263. if ( !UserItem->m_UserSid )
  264. {
  265. AfxThrowMemoryException( );
  266. }
  267. if ( !CopySid(SidSize, UserItem->m_UserSid, UserSid))
  268. {
  269. delete [] UserItem->m_UserSid;
  270. delete UserItem;
  271. return GetLastError();
  272. }
  273. }
  274. else
  275. {
  276. delete UserItem;
  277. return GetLastError();
  278. }
  279. }
  280. else
  281. {
  282. UserItem->m_UserSid = NULL;
  283. }
  284. if ( dwFlag & USERINFILE )
  285. {
  286. //
  287. // The info is from the file. Use the hash structure
  288. //
  289. CertHashBlob = ( PEFS_HASH_BLOB ) UserCert;
  290. CertSize = sizeof(EFS_HASH_BLOB) + CertHashBlob->cbData;
  291. UserItem->m_pCert = new BYTE[CertSize];
  292. if ( !UserItem->m_pCert )
  293. {
  294. AfxThrowMemoryException( );
  295. }
  296. ((PEFS_HASH_BLOB)UserItem->m_pCert)->cbData = CertHashBlob->cbData;
  297. ((PEFS_HASH_BLOB)UserItem->m_pCert)->pbData = (PBYTE)(UserItem->m_pCert) + sizeof(EFS_HASH_BLOB);
  298. memcpy(((PEFS_HASH_BLOB)UserItem->m_pCert)->pbData,
  299. CertHashBlob->pbData,
  300. CertHashBlob->cbData
  301. );
  302. }
  303. else
  304. {
  305. //
  306. // The info is from the user picked cert. Use m_pCert Blob structure
  307. //
  308. CertBlob = ( PEFS_CERTIFICATE_BLOB ) UserCert;
  309. CertSize = sizeof(EFS_CERTIFICATE_BLOB) + CertBlob->cbData;
  310. UserItem->m_pCert = new BYTE[CertSize];
  311. if ( NULL == UserItem->m_pCert ){
  312. AfxThrowMemoryException( );
  313. }
  314. ((PEFS_CERTIFICATE_BLOB)UserItem->m_pCert)->cbData = CertBlob->cbData;
  315. ((PEFS_CERTIFICATE_BLOB)UserItem->m_pCert)->dwCertEncodingType = CertBlob->dwCertEncodingType;
  316. ((PEFS_CERTIFICATE_BLOB)UserItem->m_pCert)->pbData = (PBYTE)(UserItem->m_pCert) + sizeof(EFS_CERTIFICATE_BLOB);
  317. memcpy(((PEFS_CERTIFICATE_BLOB)UserItem->m_pCert)->pbData,
  318. CertBlob->pbData,
  319. CertBlob->cbData
  320. );
  321. }
  322. UserItem->m_szUserName = pszUserName;
  323. UserItem->m_szDnName = pszDnName;
  324. UserItem->m_pCertContext = pCertContext;
  325. UserItem->m_dwFlag = dwFlag;
  326. if ( dwFlag & USERADDED )
  327. {
  328. m_UserAddedCnt ++;
  329. }
  330. }
  331. catch (...) {
  332. delete [] UserItem->m_UserSid;
  333. delete [] UserItem->m_pCert;
  334. delete UserItem;
  335. AfxThrowMemoryException( );
  336. return ERROR_NOT_ENOUGH_MEMORY;
  337. }
  338. //
  339. // Add to the head
  340. //
  341. if ( m_UsersRoot )
  342. {
  343. UserItem->m_pNext = m_UsersRoot;
  344. }
  345. m_UsersRoot = UserItem;
  346. return NO_ERROR;
  347. }
  348. DWORD
  349. CUsers::Remove(
  350. LPCWSTR m_szUserName,
  351. LPCWSTR UserCertName
  352. )
  353. //////////////////////////////////////////////////////////////////////
  354. // Routine Description:
  355. // Remove a user from the list. Actually just mark for remove.
  356. // Arguments:
  357. // m_szUserName -- User's name
  358. // UserCertName -- User's certificate name
  359. // Return Value:
  360. // NO_ERROR if succeed.
  361. // ERROR_NOT_FOUND if the user cannot be found.
  362. //
  363. //////////////////////////////////////////////////////////////////////
  364. {
  365. PUSERSONFILE TmpUserItem = m_UsersRoot;
  366. bool bUserMatched = false;
  367. while ( TmpUserItem ){
  368. if (((NULL==m_szUserName) && ( NULL == TmpUserItem->m_szUserName)) ||
  369. ( m_szUserName && TmpUserItem->m_szUserName && !_tcsicmp(m_szUserName, TmpUserItem->m_szUserName))){
  370. //
  371. // Make sure the CertName matches also if the user name is NULL
  372. //
  373. if (NULL==m_szUserName)
  374. {
  375. if (((NULL==UserCertName) && ( NULL == TmpUserItem->m_szDnName)) ||
  376. (UserCertName && TmpUserItem->m_szDnName && !_tcsicmp(UserCertName, TmpUserItem->m_szDnName))){
  377. bUserMatched = true;
  378. }
  379. }
  380. else
  381. {
  382. bUserMatched = true;
  383. }
  384. if (bUserMatched)
  385. {
  386. //
  387. // User exist, mark it for remove
  388. //
  389. if ( TmpUserItem->m_dwFlag & USERINFILE ){
  390. m_UserRemovedCnt++;
  391. } else if ( TmpUserItem->m_dwFlag & USERADDED ) {
  392. m_UserAddedCnt--;
  393. }
  394. TmpUserItem->m_dwFlag |= USERREMOVED;
  395. return NO_ERROR;
  396. }
  397. }
  398. TmpUserItem = TmpUserItem->m_pNext;
  399. }
  400. return ERROR_NOT_FOUND;
  401. }
  402. PUSERSONFILE CUsers::StartEnum()
  403. //////////////////////////////////////////////////////////////////////
  404. // Routine Description:
  405. // Prepare for GetNextUser
  406. // Arguments:
  407. //
  408. // Return Value:
  409. // A pointer used for GetNextUser
  410. //
  411. //////////////////////////////////////////////////////////////////////
  412. {
  413. return m_UsersRoot;
  414. }
  415. PUSERSONFILE CUsers::GetNextUser(
  416. PUSERSONFILE Token,
  417. CString &szUserName,
  418. CString &CertName
  419. )
  420. //////////////////////////////////////////////////////////////////////
  421. // Routine Description:
  422. // Get next user in the list.(Not removed).
  423. // Arguments:
  424. // m_szUserName -- m_pNext User's name
  425. // CertName -- Certificate name
  426. // Token -- A pointer returned by previous GetNextUser or StartEnum.
  427. // Return Value:
  428. // A pointer for GetNextUser()
  429. //
  430. //////////////////////////////////////////////////////////////////////
  431. {
  432. PUSERSONFILE TmpItem = Token;
  433. PUSERSONFILE RetPointer = NULL;
  434. while ( TmpItem )
  435. {
  436. if ( TmpItem->m_dwFlag & USERREMOVED )
  437. {
  438. TmpItem = TmpItem->m_pNext;
  439. continue;
  440. }
  441. try{
  442. szUserName = TmpItem->m_szUserName;
  443. CertName = TmpItem->m_szDnName;
  444. RetPointer = TmpItem->m_pNext;
  445. }
  446. catch (...){
  447. //
  448. // Out of memory
  449. //
  450. TmpItem = NULL;
  451. RetPointer = NULL;
  452. }
  453. break;
  454. }
  455. if ( NULL == TmpItem )
  456. {
  457. szUserName.Empty();
  458. CertName.Empty();
  459. }
  460. return RetPointer;
  461. }
  462. DWORD CUsers::GetUserAddedCnt()
  463. {
  464. return m_UserAddedCnt;
  465. }
  466. DWORD CUsers::GetUserRemovedCnt()
  467. {
  468. return m_UserRemovedCnt;
  469. }
  470. PVOID CUsers::GetNextChangedUser(
  471. PVOID Token,
  472. LPWSTR * m_szUserName,
  473. LPWSTR * m_szDnName,
  474. PSID * m_UserSid,
  475. PVOID * CertData,
  476. DWORD * m_dwFlag
  477. )
  478. //////////////////////////////////////////////////////////////////////
  479. // Routine Description:
  480. // Get the info for changed users. This method is not well behaved in the
  481. // sense of OOP. It exposes internal pointers to the ouside world. The gain
  482. // is performance. At this moment, CUsers is a supporting class and used only
  483. // by USERLIST and CAddEFSWizSheet (single thread). We can make USERLIST a
  484. // friend of CUsers if such concerns are raised in the future or reimplement this.
  485. // The same issue applies to the enumerate methods.
  486. //
  487. // Arguments:
  488. // Token -- A pointer to the item returned in previous GetNextChangedUser or StartEnum.
  489. // m_szUserName -- User's name
  490. // m_szDnName -- User's Distinguished name
  491. // CertData -- User's certificate blob or hash
  492. // m_UserSid -- User's ID. Can be NULL
  493. // m_dwFlag -- Indicate if the item is existing in the file, to be added or removed
  494. // Return Value:
  495. // m_pNext item pointer.
  496. //
  497. //////////////////////////////////////////////////////////////////////
  498. {
  499. bool bChangedUserFound = false;
  500. while ( Token )
  501. {
  502. *m_dwFlag = ((PUSERSONFILE) Token)->m_dwFlag;
  503. if ( ( *m_dwFlag & USERADDED ) && !( *m_dwFlag & USERREMOVED ))
  504. {
  505. //
  506. // The user is to to be added to the file
  507. //
  508. *m_dwFlag = USERADDED;
  509. bChangedUserFound = true;
  510. }
  511. else if ( ( *m_dwFlag & USERREMOVED ) && ( *m_dwFlag & USERINFILE))
  512. {
  513. //
  514. // The user is to be removed from the file
  515. //
  516. *m_dwFlag = USERREMOVED;
  517. bChangedUserFound = true;
  518. }
  519. if ( bChangedUserFound )
  520. {
  521. *m_szUserName = ((PUSERSONFILE) Token)->m_szUserName;
  522. *m_szDnName = ((PUSERSONFILE) Token)->m_szDnName;
  523. *m_UserSid = ((PUSERSONFILE) Token)->m_UserSid;
  524. *CertData = ((PUSERSONFILE) Token)->m_pCert;
  525. return ((PUSERSONFILE) Token)->m_pNext;
  526. }
  527. else
  528. {
  529. Token = ((PUSERSONFILE) Token)->m_pNext;
  530. }
  531. }
  532. *m_szUserName = NULL;
  533. *m_szDnName = NULL;
  534. *m_UserSid = NULL;
  535. *CertData = NULL;
  536. *m_dwFlag = 0;
  537. return NULL;
  538. }
  539. void CUsers::Clear()
  540. {
  541. PUSERSONFILE TmpUserItem = m_UsersRoot;
  542. while (TmpUserItem)
  543. {
  544. m_UsersRoot = TmpUserItem->m_pNext;
  545. delete [] TmpUserItem->m_szUserName;
  546. delete [] TmpUserItem->m_szDnName;
  547. delete [] TmpUserItem->m_pCert;
  548. if (TmpUserItem->m_UserSid)
  549. {
  550. delete [] TmpUserItem->m_UserSid;
  551. }
  552. if (TmpUserItem->m_pCertContext)
  553. {
  554. ::CertFreeCertificateContext(TmpUserItem->m_pCertContext);
  555. }
  556. delete TmpUserItem;
  557. TmpUserItem = m_UsersRoot;
  558. }
  559. m_UsersRoot = NULL;
  560. m_UserAddedCnt = 0;
  561. m_UserRemovedCnt = 0;
  562. }