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.

643 lines
14 KiB

  1. /*****************************************************************************/
  2. /* Copyright (c) 1999-2002 Microsoft Corporation, All Rights Reserved /
  3. /*****************************************************************************/
  4. /*
  5. * CSACL.cpp - implementation file for CAccessEntry class.
  6. */
  7. #include "precomp.h"
  8. #include "aclapi.h"
  9. #include "AccessEntryList.h"
  10. #include "SACL.h"
  11. #include <accctrl.h>
  12. #include "wbemnetapi32.h"
  13. #include "SecUtils.h"
  14. ///////////////////////////////////////////////////////////////////
  15. //
  16. // Function: CSACL::CSACL
  17. //
  18. // Default class constructor.
  19. //
  20. // Inputs:
  21. // None.
  22. //
  23. // Outputs:
  24. // None.
  25. //
  26. // Returns:
  27. // None.
  28. //
  29. // Comments:
  30. //
  31. ///////////////////////////////////////////////////////////////////
  32. CSACL::CSACL( void )
  33. : m_SACLSections(NULL)
  34. {
  35. }
  36. ///////////////////////////////////////////////////////////////////
  37. //
  38. // Function: CSACL::~CSACL
  39. //
  40. // Class destructor.
  41. //
  42. // Inputs:
  43. // None.
  44. //
  45. // Outputs:
  46. // None.
  47. //
  48. // Returns:
  49. // None.
  50. //
  51. // Comments:
  52. //
  53. ///////////////////////////////////////////////////////////////////
  54. CSACL::~CSACL( void )
  55. {
  56. Clear();
  57. }
  58. ///////////////////////////////////////////////////////////////////
  59. //
  60. // Function: CSCL::Init
  61. //
  62. // Initializes the SACL member list.
  63. //
  64. // Inputs:
  65. //
  66. //
  67. // Outputs:
  68. // None.
  69. //
  70. // Returns:
  71. // DWORD Success/Failure
  72. //
  73. // Comments:
  74. //
  75. ///////////////////////////////////////////////////////////////////
  76. DWORD CSACL::Init(PACL a_pSACL)
  77. {
  78. DWORD t_dwRes = E_FAIL;
  79. if(a_pSACL == NULL)
  80. {
  81. return ERROR_INVALID_PARAMETER;
  82. }
  83. if(m_SACLSections != NULL)
  84. {
  85. delete m_SACLSections;
  86. m_SACLSections = NULL;
  87. }
  88. try
  89. {
  90. m_SACLSections = new CAccessEntryList;
  91. }
  92. catch(...)
  93. {
  94. if(m_SACLSections != NULL)
  95. {
  96. delete m_SACLSections;
  97. m_SACLSections = NULL;
  98. }
  99. throw;
  100. }
  101. t_dwRes = m_SACLSections->InitFromWin32ACL(a_pSACL);
  102. return t_dwRes;
  103. }
  104. ///////////////////////////////////////////////////////////////////
  105. //
  106. // Function: CSACL::AddSACLEntry
  107. //
  108. // Adds a System Audit entry to the ACL. By default, these go
  109. // to the front of the list.
  110. //
  111. // Inputs:
  112. // PSID psid - PSID
  113. // DWORD dwAccessMask - Access Mask
  114. // BYTE bAceFlags - Flags
  115. //
  116. // Outputs:
  117. // None.
  118. //
  119. // Returns:
  120. // BOOL Success/Failure
  121. //
  122. // Comments:
  123. //
  124. ///////////////////////////////////////////////////////////////////
  125. bool CSACL::AddSACLEntry( PSID psid, SACLTYPE SaclType, DWORD dwAccessMask, BYTE bAceFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid )
  126. {
  127. bool fReturn = true;
  128. BYTE bACEType;
  129. // Sid must be valid
  130. if ( (psid != NULL) && IsValidSid( psid ) )
  131. {
  132. switch(SaclType)
  133. {
  134. case ENUM_SYSTEM_AUDIT_ACE_TYPE:
  135. bACEType = SYSTEM_AUDIT_ACE_TYPE;
  136. break;
  137. /********************************* type not yet supported under w2k ********************************************
  138. case ENUM_SYSTEM_ALARM_ACE_TYPE:
  139. bACEType = SYSTEM_ALARM_ACE_TYPE;
  140. break;
  141. /********************************* type not yet supported under w2k ********************************************/
  142. case ENUM_SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  143. bACEType = SYSTEM_AUDIT_OBJECT_ACE_TYPE;
  144. break;
  145. /********************************* type not yet supported under w2k ********************************************
  146. case ENUM_SYSTEM_ALARM_OBJECT_ACE_TYPE:
  147. bACEType = SYSTEM_ALARM_OBJECT_ACE_TYPE;
  148. break;
  149. /********************************* type not yet supported under w2k ********************************************/
  150. default:
  151. fReturn = false;
  152. break;
  153. }
  154. // We will overwrite the Access Mask of a duplicate entry.
  155. if(fReturn)
  156. {
  157. if(m_SACLSections == NULL)
  158. {
  159. try
  160. {
  161. m_SACLSections = new CAccessEntryList;
  162. }
  163. catch(...)
  164. {
  165. if(m_SACLSections != NULL)
  166. {
  167. delete m_SACLSections;
  168. m_SACLSections = NULL;
  169. }
  170. throw;
  171. }
  172. if(m_SACLSections != NULL)
  173. {
  174. fReturn = m_SACLSections->AppendNoDup( psid, bACEType, bAceFlags, dwAccessMask, pguidObjGuid, pguidInhObjGuid );
  175. }
  176. }
  177. else
  178. {
  179. fReturn = m_SACLSections->AppendNoDup( psid, bACEType, bAceFlags, dwAccessMask, pguidObjGuid, pguidInhObjGuid );
  180. }
  181. }
  182. }
  183. else
  184. {
  185. fReturn = true;
  186. }
  187. return fReturn;
  188. }
  189. ///////////////////////////////////////////////////////////////////
  190. //
  191. // Function: CSACL::RemoveSACLEntry
  192. //
  193. // Removes a system audit entry from the ACL.
  194. //
  195. // Inputs:
  196. // CSid& sid - PSID
  197. // DWORD dwAccessMask - Access Mask
  198. // BYTE bAceFlags - Flags
  199. //
  200. // Outputs:
  201. // None.
  202. //
  203. // Returns:
  204. // BOOL Success/Failure
  205. //
  206. // Comments:
  207. //
  208. // Removed entry MUST match the supplied parameters.
  209. //
  210. ///////////////////////////////////////////////////////////////////
  211. bool CSACL::RemoveSACLEntry( CSid& sid, SACLTYPE SaclType, DWORD dwAccessMask, BYTE bAceFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid )
  212. {
  213. bool fReturn = false;
  214. // We need an ACE to compare
  215. CAccessEntry ACE( &sid, SYSTEM_AUDIT_ACE_TYPE, bAceFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask );
  216. ACLPOSITION pos;
  217. if ( m_SACLSections->BeginEnum( pos ) )
  218. {
  219. ON_BLOCK_EXIT_OBJ ( *m_SACLSections, CAccessEntryList::EndEnum, ByRef ( pos ) ) ;
  220. CAccessEntry* pACE = NULL;
  221. try
  222. {
  223. // For loop will try to find a matching ACE in the list
  224. for ( CAccessEntry* pACE = m_SACLSections->GetNext( pos );
  225. NULL != pACE
  226. || ACE == *pACE;
  227. pACE = m_SACLSections->GetNext( pos ) );
  228. }
  229. catch(...)
  230. {
  231. if(pACE != NULL)
  232. {
  233. delete pACE;
  234. pACE = NULL;
  235. }
  236. throw;
  237. }
  238. // If we got a match, delete the ACE.
  239. if ( NULL != pACE )
  240. {
  241. m_SACLSections->Remove( pACE );
  242. delete pACE;
  243. fReturn = true;
  244. }
  245. }
  246. return fReturn;
  247. }
  248. ///////////////////////////////////////////////////////////////////
  249. //
  250. // Function: CSACL::RemoveSACLEntry
  251. //
  252. // Removes a system audit entry from the ACL.
  253. //
  254. // Inputs:
  255. // CSid& sid - PSID
  256. // BYTE bAceFlags - Flags
  257. //
  258. // Outputs:
  259. // None.
  260. //
  261. // Returns:
  262. // BOOL Success/Failure
  263. //
  264. // Comments:
  265. //
  266. // Removed entry MUST match the supplied parameters.
  267. //
  268. ///////////////////////////////////////////////////////////////////
  269. bool CSACL::RemoveSACLEntry( CSid& sid, SACLTYPE SaclType, BYTE bAceFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid )
  270. {
  271. bool fReturn = false;
  272. // We need an ACE to compare
  273. ACLPOSITION pos;
  274. if ( m_SACLSections->BeginEnum( pos ) )
  275. {
  276. ON_BLOCK_EXIT_OBJ ( *m_SACLSections, CAccessEntryList::EndEnum, ByRef ( pos ) ) ;
  277. // For loop will try to find a matching ACE in the list
  278. CAccessEntry* pACE = NULL;
  279. try
  280. {
  281. for ( pACE = m_SACLSections->GetNext( pos );
  282. NULL != pACE;
  283. pACE = m_SACLSections->GetNext( pos ) )
  284. {
  285. CAccessEntry caeTemp(sid, SaclType, bAceFlags, pguidObjGuid, pguidInhObjGuid, pACE->GetAccessMask());
  286. // If we got a match, delete the ACE.
  287. if (*pACE == caeTemp)
  288. {
  289. m_SACLSections->Remove( pACE );
  290. fReturn = true;
  291. break;
  292. }
  293. delete pACE;
  294. }
  295. }
  296. catch(...)
  297. {
  298. if(pACE != NULL)
  299. {
  300. delete pACE;
  301. pACE = NULL;
  302. }
  303. throw;
  304. }
  305. }
  306. return fReturn;
  307. }
  308. ///////////////////////////////////////////////////////////////////
  309. //
  310. // Function: CSACL::RemoveSACLEntry
  311. //
  312. // Removes a system audit entry from the ACL.
  313. //
  314. // Inputs:
  315. // CSid& sid - PSID
  316. // DWORD dwIndex - Index to remove.
  317. //
  318. // Outputs:
  319. // None.
  320. //
  321. // Returns:
  322. // BOOL Success/Failure
  323. //
  324. // Comments:
  325. //
  326. // Removes dwIndex entry matching sid.
  327. //
  328. ///////////////////////////////////////////////////////////////////
  329. bool CSACL::RemoveSACLEntry( CSid& sid, SACLTYPE SaclType, DWORD dwIndex /*= 0*/ )
  330. {
  331. bool fReturn = false;
  332. // We need an ACE to compare
  333. CSid tempsid;
  334. ACLPOSITION pos;
  335. DWORD dwCtr = 0;
  336. if ( m_SACLSections->BeginEnum( pos ) )
  337. {
  338. ON_BLOCK_EXIT_OBJ ( *m_SACLSections, CAccessEntryList::EndEnum, ByRef ( pos ) ) ;
  339. // For each ACE we find, see if it is an SYSTEM_AUDIT_ACE_TYPE,
  340. // and if the Sid matches the one passed in. If it does, increment
  341. // the counter, then if we're on the right index remove the ACE,
  342. // delete it and quit.
  343. CAccessEntry* pACE = NULL;
  344. try
  345. {
  346. for ( pACE = m_SACLSections->GetNext( pos );
  347. NULL != pACE;
  348. pACE = m_SACLSections->GetNext( pos ) )
  349. {
  350. if ( SYSTEM_AUDIT_ACE_TYPE == pACE->GetACEType() )
  351. {
  352. pACE->GetSID( tempsid );
  353. if ( sid == tempsid )
  354. {
  355. if ( dwCtr == dwIndex )
  356. {
  357. m_SACLSections->Remove( pACE );
  358. fReturn = true;
  359. break;
  360. }
  361. else
  362. {
  363. ++dwCtr;
  364. }
  365. }
  366. delete pACE;
  367. }
  368. }
  369. }
  370. catch(...)
  371. {
  372. if(pACE != NULL)
  373. {
  374. delete pACE;
  375. pACE = NULL;
  376. }
  377. throw;
  378. }
  379. }
  380. return fReturn;
  381. }
  382. ///////////////////////////////////////////////////////////////////
  383. //
  384. // Function: CSACL::Find
  385. //
  386. // Finds the specified ace in the dacl
  387. //
  388. //
  389. // Returns:
  390. // true if found it.
  391. //
  392. // Comments:
  393. //
  394. // Helps support NT 5 canonical order in DACLs.
  395. //
  396. ///////////////////////////////////////////////////////////////////
  397. bool CSACL::Find( const CSid& sid, BYTE bACEType, BYTE bACEFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid, DWORD dwAccessMask, CAccessEntry& ace )
  398. {
  399. return m_SACLSections->Find( sid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace );
  400. }
  401. ///////////////////////////////////////////////////////////////////
  402. //
  403. // Function: CSACL::Find
  404. //
  405. // Finds the specified ace in the dacl
  406. //
  407. //
  408. // Returns:
  409. // true if found it.
  410. //
  411. // Comments:
  412. //
  413. // Helps support NT 5 canonical order in DACLs.
  414. //
  415. ///////////////////////////////////////////////////////////////////
  416. bool CSACL::Find( PSID psid, BYTE bACEType, BYTE bACEFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid, DWORD dwAccessMask, CAccessEntry& ace )
  417. {
  418. return m_SACLSections->Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace );
  419. }
  420. ///////////////////////////////////////////////////////////////////
  421. //
  422. // Function: CSACL::::ConfigureSACL
  423. //
  424. // Configures a Win32 PACL with SACL information.
  425. //
  426. // Inputs:
  427. // None.
  428. //
  429. // Outputs:
  430. // PACL& pSacl - Pointer to a SACL.
  431. //
  432. // Returns:
  433. // DWORD ERROR_SUCCESS if successful.
  434. //
  435. // Comments:
  436. //
  437. ///////////////////////////////////////////////////////////////////
  438. DWORD CSACL::ConfigureSACL( PACL& pSacl )
  439. {
  440. DWORD dwReturn = ERROR_SUCCESS,
  441. dwSACLLength = 0;
  442. if ( CalculateSACLSize( &dwSACLLength ) )
  443. {
  444. if ( 0 != dwSACLLength )
  445. {
  446. pSacl = NULL;
  447. try
  448. {
  449. pSacl = (PACL) malloc( dwSACLLength );
  450. if ( NULL != pSacl )
  451. {
  452. if ( !InitializeAcl( (PACL) pSacl, dwSACLLength, ACL_REVISION ) )
  453. {
  454. dwReturn = ::GetLastError();
  455. }
  456. } // If NULL != pSACL
  457. }
  458. catch(...)
  459. {
  460. if(pSacl != NULL)
  461. {
  462. free(pSacl);
  463. pSacl = NULL;
  464. }
  465. throw;
  466. }
  467. } // If 0 != dwSACLLength
  468. } // If Calcaulate SACL Size
  469. else
  470. {
  471. dwReturn = ERROR_INVALID_PARAMETER; // One or more of the SACLs is bad
  472. }
  473. if ( ERROR_SUCCESS == dwReturn )
  474. {
  475. dwReturn = FillSACL( pSacl );
  476. }
  477. if ( ERROR_SUCCESS != dwReturn )
  478. {
  479. free( pSacl );
  480. pSacl = NULL;
  481. }
  482. return dwReturn;
  483. }
  484. ///////////////////////////////////////////////////////////////////
  485. //
  486. // Function: CSACL::::CalculateSACLSize
  487. //
  488. // Obtains the size necessary to populate a SACL.
  489. //
  490. // Inputs:
  491. // None.
  492. //
  493. // Outputs:
  494. // LPDWORD pdwSACLLength - Calculated Length.
  495. //
  496. // Returns:
  497. // BOOL TRUE/FALSE
  498. //
  499. // Comments:
  500. //
  501. ///////////////////////////////////////////////////////////////////
  502. BOOL CSACL::CalculateSACLSize( LPDWORD pdwSACLLength )
  503. {
  504. BOOL fReturn = FALSE;
  505. *pdwSACLLength = 0;
  506. if ( NULL != m_SACLSections )
  507. {
  508. fReturn = m_SACLSections->CalculateWin32ACLSize( pdwSACLLength );
  509. }
  510. return fReturn;
  511. }
  512. ///////////////////////////////////////////////////////////////////
  513. //
  514. // Function: CSACL::FillSACL
  515. //
  516. // Fills out a SACL.
  517. //
  518. // Inputs:
  519. // PACL pSacl - Sacl to fill out.
  520. //
  521. // Outputs:
  522. // None.
  523. //
  524. // Returns:
  525. // BOOL TRUE/FALSE
  526. //
  527. // Comments:
  528. //
  529. ///////////////////////////////////////////////////////////////////
  530. DWORD CSACL::FillSACL( PACL pSACL )
  531. {
  532. DWORD dwReturn = ERROR_SUCCESS;
  533. if ( NULL != m_SACLSections )
  534. {
  535. dwReturn = m_SACLSections->FillWin32ACL( pSACL );
  536. }
  537. return dwReturn;
  538. }
  539. void CSACL::Clear()
  540. {
  541. if ( NULL != m_SACLSections )
  542. {
  543. delete m_SACLSections;
  544. m_SACLSections = NULL;
  545. }
  546. }
  547. bool CSACL::GetMergedACL
  548. (
  549. CAccessEntryList& a_aclIn
  550. )
  551. {
  552. // Actually somewhat of a misnomer for the time being (until the
  553. // day when the sacl ordering matters, and we have multiple sections
  554. // as we do in dacl for that reason). We just hand back our
  555. // member acl, if it is not null:
  556. bool fRet = false;
  557. if(m_SACLSections != NULL)
  558. {
  559. fRet = a_aclIn.Copy(*m_SACLSections);
  560. }
  561. return fRet;
  562. }
  563. void CSACL::DumpSACL(LPCWSTR wstrFilename)
  564. {
  565. Output(L"SACL contents follow...", wstrFilename);
  566. if(m_SACLSections != NULL)
  567. {
  568. m_SACLSections->DumpAccessEntryList(wstrFilename);
  569. }
  570. }