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.

647 lines
18 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997-2002.
  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. // security review 2/27/2002 BryanWal ok
  268. if ( !::CopySid(SidSize, UserItem->m_UserSid, UserSid))
  269. {
  270. delete [] UserItem->m_UserSid;
  271. delete UserItem;
  272. return GetLastError();
  273. }
  274. }
  275. else
  276. {
  277. delete UserItem;
  278. return GetLastError();
  279. }
  280. }
  281. else
  282. {
  283. UserItem->m_UserSid = NULL;
  284. }
  285. if ( dwFlag & USERINFILE )
  286. {
  287. //
  288. // The info is from the file. Use the hash structure
  289. //
  290. CertHashBlob = ( PEFS_HASH_BLOB ) UserCert;
  291. CertSize = sizeof(EFS_HASH_BLOB) + CertHashBlob->cbData;
  292. UserItem->m_pCert = new BYTE[CertSize];
  293. if ( !UserItem->m_pCert )
  294. {
  295. AfxThrowMemoryException( );
  296. }
  297. ((PEFS_HASH_BLOB)UserItem->m_pCert)->cbData = CertHashBlob->cbData;
  298. ((PEFS_HASH_BLOB)UserItem->m_pCert)->pbData = (PBYTE)(UserItem->m_pCert) + sizeof(EFS_HASH_BLOB);
  299. // security review 2/27/2002 BryanWal ok
  300. memcpy(((PEFS_HASH_BLOB)UserItem->m_pCert)->pbData,
  301. CertHashBlob->pbData,
  302. CertHashBlob->cbData);
  303. }
  304. else
  305. {
  306. //
  307. // The info is from the user picked cert. Use m_pCert Blob structure
  308. //
  309. CertBlob = ( PEFS_CERTIFICATE_BLOB ) UserCert;
  310. CertSize = sizeof(EFS_CERTIFICATE_BLOB) + CertBlob->cbData;
  311. UserItem->m_pCert = new BYTE[CertSize];
  312. if ( NULL == UserItem->m_pCert ){
  313. AfxThrowMemoryException( );
  314. }
  315. ((PEFS_CERTIFICATE_BLOB)UserItem->m_pCert)->cbData = CertBlob->cbData;
  316. ((PEFS_CERTIFICATE_BLOB)UserItem->m_pCert)->dwCertEncodingType = CertBlob->dwCertEncodingType;
  317. ((PEFS_CERTIFICATE_BLOB)UserItem->m_pCert)->pbData = (PBYTE)(UserItem->m_pCert) + sizeof(EFS_CERTIFICATE_BLOB);
  318. // security review 2/27/2002 BryanWal ok
  319. memcpy(((PEFS_CERTIFICATE_BLOB)UserItem->m_pCert)->pbData,
  320. CertBlob->pbData,
  321. CertBlob->cbData);
  322. }
  323. UserItem->m_szUserName = pszUserName;
  324. UserItem->m_szDnName = pszDnName;
  325. UserItem->m_pCertContext = pCertContext;
  326. UserItem->m_dwFlag = dwFlag;
  327. if ( dwFlag & USERADDED )
  328. {
  329. m_UserAddedCnt ++;
  330. }
  331. }
  332. catch (...) {
  333. delete [] UserItem->m_UserSid;
  334. delete [] UserItem->m_pCert;
  335. delete UserItem;
  336. AfxThrowMemoryException( );
  337. return ERROR_NOT_ENOUGH_MEMORY;
  338. }
  339. //
  340. // Add to the head
  341. //
  342. if ( m_UsersRoot )
  343. {
  344. UserItem->m_pNext = m_UsersRoot;
  345. }
  346. m_UsersRoot = UserItem;
  347. return NO_ERROR;
  348. }
  349. DWORD
  350. CUsers::Remove(
  351. LPCWSTR m_szUserName,
  352. LPCWSTR UserCertName
  353. )
  354. //////////////////////////////////////////////////////////////////////
  355. // Routine Description:
  356. // Remove a user from the list. Actually just mark for remove.
  357. // Arguments:
  358. // m_szUserName -- User's name
  359. // UserCertName -- User's certificate name
  360. // Return Value:
  361. // NO_ERROR if succeed.
  362. // ERROR_NOT_FOUND if the user cannot be found.
  363. //
  364. //////////////////////////////////////////////////////////////////////
  365. {
  366. PUSERSONFILE TmpUserItem = m_UsersRoot;
  367. bool bUserMatched = false;
  368. while ( TmpUserItem ){
  369. if (((NULL==m_szUserName) && ( NULL == TmpUserItem->m_szUserName)) ||
  370. ( m_szUserName && TmpUserItem->m_szUserName && !_tcsicmp(m_szUserName, TmpUserItem->m_szUserName))){
  371. //
  372. // Make sure the CertName matches also if the user name is NULL
  373. //
  374. if (NULL==m_szUserName)
  375. {
  376. if (((NULL==UserCertName) && ( NULL == TmpUserItem->m_szDnName)) ||
  377. (UserCertName && TmpUserItem->m_szDnName && !_tcsicmp(UserCertName, TmpUserItem->m_szDnName))){
  378. bUserMatched = true;
  379. }
  380. }
  381. else
  382. {
  383. bUserMatched = true;
  384. }
  385. if (bUserMatched)
  386. {
  387. //
  388. // User exist, mark it for remove
  389. //
  390. if ( TmpUserItem->m_dwFlag & USERINFILE ){
  391. m_UserRemovedCnt++;
  392. } else if ( TmpUserItem->m_dwFlag & USERADDED ) {
  393. m_UserAddedCnt--;
  394. }
  395. TmpUserItem->m_dwFlag |= USERREMOVED;
  396. return NO_ERROR;
  397. }
  398. }
  399. TmpUserItem = TmpUserItem->m_pNext;
  400. }
  401. return ERROR_NOT_FOUND;
  402. }
  403. PUSERSONFILE CUsers::StartEnum()
  404. //////////////////////////////////////////////////////////////////////
  405. // Routine Description:
  406. // Prepare for GetNextUser
  407. // Arguments:
  408. //
  409. // Return Value:
  410. // A pointer used for GetNextUser
  411. //
  412. //////////////////////////////////////////////////////////////////////
  413. {
  414. return m_UsersRoot;
  415. }
  416. PUSERSONFILE CUsers::GetNextUser(
  417. PUSERSONFILE Token,
  418. CString &szUserName,
  419. CString &CertName
  420. )
  421. //////////////////////////////////////////////////////////////////////
  422. // Routine Description:
  423. // Get next user in the list.(Not removed).
  424. // Arguments:
  425. // m_szUserName -- m_pNext User's name
  426. // CertName -- Certificate name
  427. // Token -- A pointer returned by previous GetNextUser or StartEnum.
  428. // Return Value:
  429. // A pointer for GetNextUser()
  430. //
  431. //////////////////////////////////////////////////////////////////////
  432. {
  433. PUSERSONFILE TmpItem = Token;
  434. PUSERSONFILE RetPointer = NULL;
  435. while ( TmpItem )
  436. {
  437. if ( TmpItem->m_dwFlag & USERREMOVED )
  438. {
  439. TmpItem = TmpItem->m_pNext;
  440. continue;
  441. }
  442. try{
  443. szUserName = TmpItem->m_szUserName;
  444. CertName = TmpItem->m_szDnName;
  445. RetPointer = TmpItem->m_pNext;
  446. }
  447. catch (...){
  448. //
  449. // Out of memory
  450. //
  451. TmpItem = NULL;
  452. RetPointer = NULL;
  453. }
  454. break;
  455. }
  456. if ( NULL == TmpItem )
  457. {
  458. szUserName.Empty();
  459. CertName.Empty();
  460. }
  461. return RetPointer;
  462. }
  463. DWORD CUsers::GetUserAddedCnt()
  464. {
  465. return m_UserAddedCnt;
  466. }
  467. DWORD CUsers::GetUserRemovedCnt()
  468. {
  469. return m_UserRemovedCnt;
  470. }
  471. PVOID CUsers::GetNextChangedUser(
  472. PVOID Token,
  473. LPWSTR * m_szUserName,
  474. LPWSTR * m_szDnName,
  475. PSID * m_UserSid,
  476. PVOID * CertData,
  477. DWORD * m_dwFlag
  478. )
  479. //////////////////////////////////////////////////////////////////////
  480. // Routine Description:
  481. // Get the info for changed users. This method is not well behaved in the
  482. // sense of OOP. It exposes internal pointers to the ouside world. The gain
  483. // is performance. At this moment, CUsers is a supporting class and used only
  484. // by USERLIST and CAddEFSWizSheet (single thread). We can make USERLIST a
  485. // friend of CUsers if such concerns are raised in the future or reimplement this.
  486. // The same issue applies to the enumerate methods.
  487. //
  488. // Arguments:
  489. // Token -- A pointer to the item returned in previous GetNextChangedUser or StartEnum.
  490. // m_szUserName -- User's name
  491. // m_szDnName -- User's Distinguished name
  492. // CertData -- User's certificate blob or hash
  493. // m_UserSid -- User's ID. Can be NULL
  494. // m_dwFlag -- Indicate if the item is existing in the file, to be added or removed
  495. // Return Value:
  496. // m_pNext item pointer.
  497. //
  498. //////////////////////////////////////////////////////////////////////
  499. {
  500. bool bChangedUserFound = false;
  501. while ( Token )
  502. {
  503. *m_dwFlag = ((PUSERSONFILE) Token)->m_dwFlag;
  504. if ( ( *m_dwFlag & USERADDED ) && !( *m_dwFlag & USERREMOVED ))
  505. {
  506. //
  507. // The user is to to be added to the file
  508. //
  509. *m_dwFlag = USERADDED;
  510. bChangedUserFound = true;
  511. }
  512. else if ( ( *m_dwFlag & USERREMOVED ) && ( *m_dwFlag & USERINFILE))
  513. {
  514. //
  515. // The user is to be removed from the file
  516. //
  517. *m_dwFlag = USERREMOVED;
  518. bChangedUserFound = true;
  519. }
  520. if ( bChangedUserFound )
  521. {
  522. *m_szUserName = ((PUSERSONFILE) Token)->m_szUserName;
  523. *m_szDnName = ((PUSERSONFILE) Token)->m_szDnName;
  524. *m_UserSid = ((PUSERSONFILE) Token)->m_UserSid;
  525. *CertData = ((PUSERSONFILE) Token)->m_pCert;
  526. return ((PUSERSONFILE) Token)->m_pNext;
  527. }
  528. else
  529. {
  530. Token = ((PUSERSONFILE) Token)->m_pNext;
  531. }
  532. }
  533. *m_szUserName = NULL;
  534. *m_szDnName = NULL;
  535. *m_UserSid = NULL;
  536. *CertData = NULL;
  537. *m_dwFlag = 0;
  538. return NULL;
  539. }
  540. void CUsers::Clear()
  541. {
  542. PUSERSONFILE TmpUserItem = m_UsersRoot;
  543. while (TmpUserItem)
  544. {
  545. m_UsersRoot = TmpUserItem->m_pNext;
  546. delete [] TmpUserItem->m_szUserName;
  547. delete [] TmpUserItem->m_szDnName;
  548. delete [] TmpUserItem->m_pCert;
  549. if (TmpUserItem->m_UserSid)
  550. {
  551. delete [] TmpUserItem->m_UserSid;
  552. }
  553. if (TmpUserItem->m_pCertContext)
  554. {
  555. ::CertFreeCertificateContext(TmpUserItem->m_pCertContext);
  556. }
  557. delete TmpUserItem;
  558. TmpUserItem = m_UsersRoot;
  559. }
  560. m_UsersRoot = NULL;
  561. m_UserAddedCnt = 0;
  562. m_UserRemovedCnt = 0;
  563. }