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.

1069 lines
26 KiB

  1. #include "stdafx.h"
  2. #include "acl.hxx"
  3. #include "dcomperm.h"
  4. #include "Sddl.h"
  5. // Constructor
  6. //
  7. CSecurityDescriptor::CSecurityDescriptor()
  8. {
  9. m_bSDValid = FALSE;
  10. // Initialize DAcl to NULL
  11. m_pDAcl = NULL;
  12. m_pOwner = NULL;
  13. m_pGroup = NULL;
  14. // Initialize SA
  15. m_SA.nLength = sizeof( SECURITY_ATTRIBUTES );
  16. m_SA.lpSecurityDescriptor = &m_SD;
  17. m_SA.bInheritHandle = FALSE;
  18. // Do all the resetting logic in ResetSD
  19. ResetSD();
  20. }
  21. // Desctructor
  22. //
  23. CSecurityDescriptor::~CSecurityDescriptor()
  24. {
  25. // Reset SD, so everything is freed
  26. ResetSD();
  27. }
  28. // InitializeSD
  29. //
  30. // Intialize the SD, and either fail or succeeded. If it
  31. // is already initialized, then we NOP. This is so that
  32. // the user does not need to call initialize themselves,
  33. // we can do it automatically for them
  34. //
  35. BOOL
  36. CSecurityDescriptor::InitializeSD()
  37. {
  38. if ( !m_bSDValid )
  39. {
  40. // At this point, nothing should have been done to the ACL, or
  41. // there is an error
  42. ASSERT( m_pDAcl == NULL );
  43. // Not initalize yet, so lets do it.
  44. m_bSDValid = InitializeSecurityDescriptor( &m_SD, SECURITY_DESCRIPTOR_REVISION ) &&
  45. SetSecurityDescriptorControl( &m_SD, SE_DACL_PROTECTED, SE_DACL_PROTECTED);
  46. }
  47. return m_bSDValid;
  48. }
  49. // SetDAcl
  50. //
  51. // Set the DAcl for the SD, and set the pDAcl internal pointer
  52. //
  53. BOOL
  54. CSecurityDescriptor::SetDAcl( PACL pAcl )
  55. {
  56. BOOL bRet;
  57. // Try to set SD with correct DACL
  58. if ( pAcl )
  59. {
  60. // Set Security Descriptor
  61. bRet = SetSecurityDescriptorDacl( &m_SD, TRUE, pAcl, FALSE );
  62. }
  63. else
  64. {
  65. // Clear it since pAcl is NULL
  66. bRet = SetSecurityDescriptorDacl( &m_SD, FALSE, NULL, TRUE );
  67. }
  68. if ( bRet )
  69. {
  70. // If it was set correctly, then lets free the old pointer,
  71. // and set the new pointer accordingly
  72. if ( m_pDAcl )
  73. {
  74. LocalFree( m_pDAcl );
  75. }
  76. m_pDAcl = pAcl;
  77. }
  78. return bRet;
  79. }
  80. // SetOwner
  81. //
  82. // Set the owner of the SD
  83. //
  84. BOOL
  85. CSecurityDescriptor::SetOwner( PSID pSid )
  86. {
  87. if ( !InitializeSD() )
  88. {
  89. return FALSE;
  90. }
  91. if ( !SetSecurityDescriptorOwner( &m_SD, pSid, FALSE ) )
  92. {
  93. // Failed to Set
  94. return FALSE;
  95. }
  96. m_pOwner = pSid;
  97. return TRUE;
  98. }
  99. // SetGroup
  100. //
  101. // Set the group for the SD
  102. //
  103. BOOL
  104. CSecurityDescriptor::SetGroup( PSID pSid )
  105. {
  106. if ( !InitializeSD() )
  107. {
  108. return FALSE;
  109. }
  110. if ( !SetSecurityDescriptorGroup( &m_SD, pSid, FALSE ) )
  111. {
  112. // Failed to Set
  113. return FALSE;
  114. }
  115. m_pGroup = pSid;
  116. return TRUE;
  117. }
  118. // ResetSD
  119. //
  120. // Reset the SD by removing everything inside of it. Return it to
  121. // its original State.
  122. // If you want, you can call this in the begining, just to make sure the
  123. // initialization worked.
  124. //
  125. BOOL
  126. CSecurityDescriptor::ResetSD()
  127. {
  128. if ( !InitializeSD() )
  129. {
  130. return FALSE;
  131. }
  132. // Initialize to ACL not inheritted
  133. m_bDAclIsInheritted = FALSE;
  134. if ( m_pOwner )
  135. {
  136. FreeSid( m_pOwner );
  137. m_pOwner = NULL;
  138. }
  139. if ( m_pGroup )
  140. {
  141. FreeSid( m_pGroup );
  142. m_pGroup = NULL;
  143. }
  144. return SetDAcl( NULL );
  145. }
  146. // CreateAdminDAcl
  147. //
  148. // This is a wrapper function, that just creates an Admin DAcl. What
  149. // this means is that we create an ACL that ONLY allows
  150. // Administrators and Local System, and allow them FULL access
  151. //
  152. BOOL
  153. CSecurityDescriptor::CreateAdminDAcl( BOOL bIheritable )
  154. {
  155. return AddAccessAcebyWellKnownID( CSecurityDescriptor::GROUP_ADMINISTRATORS,
  156. CSecurityDescriptor::ACCESS_FULL,
  157. TRUE,
  158. bIheritable ) &&
  159. AddAccessAcebyWellKnownID( CSecurityDescriptor::USER_LOCALSYSTEM,
  160. CSecurityDescriptor::ACCESS_FULL,
  161. TRUE,
  162. bIheritable );
  163. }
  164. // GetCurrentDAcl
  165. //
  166. // Return a ppointer to the current DAcl
  167. //
  168. PACL
  169. CSecurityDescriptor::GetCurrentDAcl()
  170. {
  171. return m_pDAcl;
  172. }
  173. // UpdateDACLwithNewACE
  174. //
  175. // Update the DACL with a new ACE. Based on the AccessMode, this can be used to:
  176. // 1) Add Deny or Allow Ace's
  177. // 2) Remove Ace's
  178. //
  179. BOOL
  180. CSecurityDescriptor::UpdateDACLwithNewACE( TRUSTEE_FORM TrusteeForm, LPTSTR szTrusteeName,
  181. DWORD dwAccess, ACCESS_MODE dwAccessMode,
  182. DWORD dwInheitance)
  183. {
  184. PACL pNewDacl = NULL;
  185. EXPLICIT_ACCESS ea;
  186. BOOL bRet = TRUE;
  187. if ( !InitializeSD() )
  188. {
  189. // Count not initialize SD
  190. return FALSE;
  191. }
  192. ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
  193. ea.grfAccessPermissions = dwAccess;
  194. ea.grfAccessMode = dwAccessMode;
  195. ea.grfInheritance = dwInheitance;
  196. ea.Trustee.TrusteeForm = TrusteeForm;
  197. ea.Trustee.ptstrName = szTrusteeName;
  198. if ( SetEntriesInAcl(1, &ea, GetCurrentDAcl(), &pNewDacl) != ERROR_SUCCESS )
  199. {
  200. // Failed to Set Acl
  201. return FALSE;
  202. }
  203. if ( !SetDAcl( pNewDacl ) )
  204. {
  205. // We could not set it, so lets free it, and fail
  206. LocalFree( pNewDacl );
  207. bRet = FALSE;
  208. }
  209. return bRet;
  210. }
  211. // QueryEffectiveRightsForTrustee
  212. //
  213. // Query the effective rights for a Trustee
  214. //
  215. // Parameters:
  216. // dwTrustee - The trustee to query for
  217. // pAccessMask - [out] The effective AccessMask
  218. //
  219. // Return Values:
  220. // TRUE - Success
  221. // FALSE - Failure
  222. BOOL
  223. CSecurityDescriptor::QueryEffectiveRightsForTrustee( DWORD dwTrustee,
  224. PACCESS_MASK pAccessMask )
  225. {
  226. PSID pSid;
  227. TRUSTEE Trustee;
  228. BOOL bRet;
  229. pSid = CreateWellKnowSid( dwTrustee );
  230. if ( !pSid )
  231. {
  232. // Failed to create sid, so fail
  233. return FALSE;
  234. }
  235. // Query Trustee information
  236. Trustee.pMultipleTrustee = NULL;
  237. Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  238. Trustee.TrusteeForm = TRUSTEE_IS_SID;
  239. Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
  240. Trustee.ptstrName = (LPTSTR) pSid;
  241. bRet = GetEffectiveRightsFromAcl( GetCurrentDAcl(),
  242. &Trustee,
  243. pAccessMask ) == ERROR_SUCCESS;
  244. FreeSid( pSid );
  245. return bRet;
  246. }
  247. // AddAccessAceByName
  248. //
  249. // Add either an Access Allowed or Access Denied ACE to this ACL
  250. //
  251. // Parameters:
  252. // szName - The name of the user or group to be added to the ACL
  253. // dwAccess - The access mask to be applied
  254. // bAllow - If TRUE then added Allow ACE, if FALSE, then add Deny ACE
  255. // bInherit - Should this be inherited by children
  256. //
  257. BOOL
  258. CSecurityDescriptor::AddAccessAcebyName( LPTSTR szName, DWORD dwAccess, BOOL bAllow /*= TRUE*/ , BOOL bInherit /*= FALSE*/ )
  259. {
  260. return UpdateDACLwithNewACE( TRUSTEE_IS_NAME, // Trustee is a name
  261. szName, // Username/Group
  262. dwAccess, // Access
  263. bAllow ? SET_ACCESS: DENY_ACCESS,
  264. bInherit ? ( OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE ) : NO_INHERITANCE);
  265. }
  266. // AddAccessAcebyStringSid
  267. //
  268. // Add an Access ace to the SD by it's string SID
  269. //
  270. BOOL
  271. CSecurityDescriptor::AddAccessAcebyStringSid( LPTSTR szStringSid,
  272. DWORD dwAccess,
  273. BOOL bAllow /* = TRUE */ ,
  274. BOOL bInherit /* = FALSE */ )
  275. {
  276. PSID pSid;
  277. BOOL bRet;
  278. if ( !ConvertStringSidToSid( szStringSid, &pSid ) )
  279. {
  280. // Failed to convert to String Sid
  281. return FALSE;
  282. }
  283. bRet = UpdateDACLwithNewACE( TRUSTEE_IS_SID, // Trustee is a name
  284. (LPTSTR) pSid, // SID
  285. dwAccess, // Access
  286. bAllow ? SET_ACCESS: DENY_ACCESS,
  287. bInherit ? ( OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE ) : NO_INHERITANCE);
  288. // Free the Sid that was returned
  289. LocalFree( pSid );
  290. return bRet;
  291. }
  292. // RemoveAccessAcebyName
  293. //
  294. // Remove all DAcl's in our current DAcl for the particular name
  295. // specified
  296. //
  297. BOOL
  298. CSecurityDescriptor::RemoveAccessAcebyName( LPTSTR szName ,BOOL bInherit /*= FALSE*/ )
  299. {
  300. BOOL bUserExisted = TRUE;
  301. DWORD dwReturn = ERROR_SUCCESS;
  302. if ( !m_pDAcl )
  303. {
  304. // If there is no ACL, then we don'e have to worry about
  305. // removing this ACE for it.
  306. return TRUE;
  307. }
  308. while ( bUserExisted &&
  309. ( dwReturn == ERROR_SUCCESS ) )
  310. {
  311. dwReturn = RemovePrincipalFromACL( m_pDAcl, szName, &bUserExisted );
  312. }
  313. return ( dwReturn == ERROR_SUCCESS );
  314. }
  315. // AddAccessAcebyWellKnownID
  316. //
  317. // Add either an Access Allowed or Access Denied ACE to this ACL for a Well Know
  318. // User or Group
  319. //
  320. // Parameters:
  321. // dwID - The id of the User/Group to be added (taken from the const in this class)
  322. // dwAccess - The access mask to be applied
  323. // bAllow - If TRUE then added Allow ACE, if FALSE, then add Deny ACE
  324. // bInherit - Should this be inherited by children
  325. //
  326. BOOL
  327. CSecurityDescriptor::AddAccessAcebyWellKnownID( DWORD dwID, DWORD dwAccess, BOOL bAllow /*= TRUE*/ , BOOL bInherit /*= FALSE*/ )
  328. {
  329. BOOL bRet = TRUE;
  330. PSID pSid;
  331. pSid = CreateWellKnowSid( dwID );
  332. if ( !pSid )
  333. {
  334. return FALSE;
  335. }
  336. bRet = UpdateDACLwithNewACE( TRUSTEE_IS_SID, // Trustee is a name
  337. (LPTSTR) pSid, // SID
  338. dwAccess, // Access
  339. bAllow ? SET_ACCESS: DENY_ACCESS,
  340. bInherit ? ( OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE ) : NO_INHERITANCE);
  341. FreeSid( pSid );
  342. return bRet;
  343. }
  344. // SetOwnerbyWellKnownID
  345. //
  346. // Set the Ownder of the SD by Well Know ID
  347. //
  348. BOOL
  349. CSecurityDescriptor::SetOwnerbyWellKnownID( DWORD dwID )
  350. {
  351. BOOL bRet = TRUE;
  352. PSID pSid;
  353. pSid = CreateWellKnowSid( dwID );
  354. if ( !pSid )
  355. {
  356. return FALSE;
  357. }
  358. bRet = SetOwner( pSid );
  359. if ( !bRet )
  360. {
  361. // Failed, so must set ourself
  362. FreeSid( pSid );
  363. }
  364. return bRet;
  365. }
  366. // SetGroupbyWellKnownID
  367. //
  368. // Set the Group of the SD by Well Know ID
  369. //
  370. BOOL
  371. CSecurityDescriptor::SetGroupbyWellKnownID( DWORD dwID )
  372. {
  373. BOOL bRet = TRUE;
  374. PSID pSid;
  375. pSid = CreateWellKnowSid( dwID );
  376. if ( !pSid )
  377. {
  378. return FALSE;
  379. }
  380. bRet = SetGroup( pSid );
  381. if ( !bRet )
  382. {
  383. // Failed, so must set ourself
  384. FreeSid( pSid );
  385. }
  386. return bRet;
  387. }
  388. // QuerySD
  389. //
  390. // Query a pointer to the Security Descriptor
  391. //
  392. PSECURITY_DESCRIPTOR
  393. CSecurityDescriptor::QuerySD()
  394. {
  395. // We should not call this, before doing some work
  396. ASSERT( m_bSDValid );
  397. if ( !m_bSDValid )
  398. {
  399. // Return NULL, since the SD is not valid
  400. return NULL;
  401. }
  402. return &m_SD;
  403. }
  404. // QuerySA
  405. //
  406. // Query a pointer to the Security Attributes, created for this SD
  407. //
  408. PSECURITY_ATTRIBUTES
  409. CSecurityDescriptor::QuerySA()
  410. {
  411. // We should not call this, before doing some work
  412. ASSERT( m_bSDValid );
  413. return &m_SA;
  414. }
  415. // CreateSidFromName
  416. //
  417. // Create a Sid for the user givem
  418. //
  419. /*BOOL
  420. CSecurityDescriptor::CreateSidFromName( LPTSTR szTrustee )
  421. {
  422. }
  423. */
  424. // CreateWellKnownSid
  425. //
  426. // Create a Well know sid, so that we can use it in the other functions
  427. // to change ACL's
  428. //
  429. PSID
  430. CSecurityDescriptor::CreateWellKnowSid( DWORD dwId )
  431. {
  432. SID_IDENTIFIER_AUTHORITY SidIdentifierNTAuthority = SECURITY_NT_AUTHORITY;
  433. SID_IDENTIFIER_AUTHORITY SidIdentifierWORLDAuthority = SECURITY_WORLD_SID_AUTHORITY;
  434. PSID_IDENTIFIER_AUTHORITY pSidIdentifierAuthority;
  435. DWORD dwCount = 0;
  436. DWORD dwRID[8];
  437. BOOL bRet = TRUE;
  438. PSID pSid = NULL;
  439. // Clear dwRID
  440. memset(&(dwRID[0]), 0, sizeof(dwRID));
  441. switch ( dwId )
  442. {
  443. case GROUP_ADMINISTRATORS:
  444. pSidIdentifierAuthority = &SidIdentifierNTAuthority;
  445. dwRID[dwCount++] = SECURITY_BUILTIN_DOMAIN_RID;
  446. dwRID[dwCount++] = DOMAIN_ALIAS_RID_ADMINS;
  447. break;
  448. case GROUP_USERS:
  449. pSidIdentifierAuthority = &SidIdentifierNTAuthority;
  450. dwRID[dwCount++] = SECURITY_BUILTIN_DOMAIN_RID;
  451. dwRID[dwCount++] = DOMAIN_ALIAS_RID_USERS;
  452. break;
  453. case USER_LOCALSYSTEM:
  454. pSidIdentifierAuthority = &SidIdentifierNTAuthority;
  455. dwRID[dwCount++] = SECURITY_LOCAL_SYSTEM_RID;
  456. break;
  457. case USER_LOCALSERVICE:
  458. pSidIdentifierAuthority = &SidIdentifierNTAuthority;
  459. dwRID[dwCount] = SECURITY_LOCAL_SERVICE_RID;
  460. break;
  461. case USER_NETWORKSERVICE:
  462. pSidIdentifierAuthority = &SidIdentifierNTAuthority;
  463. dwRID[dwCount++] = SECURITY_NETWORK_SERVICE_RID;
  464. break;
  465. case USER_EVERYONE:
  466. pSidIdentifierAuthority = &SidIdentifierWORLDAuthority;
  467. dwRID[dwCount++] = SECURITY_WORLD_RID;
  468. break;
  469. default:
  470. bRet = FALSE;
  471. }
  472. if ( bRet )
  473. {
  474. bRet = AllocateAndInitializeSid( pSidIdentifierAuthority,
  475. (BYTE)dwCount,
  476. dwRID[0],
  477. dwRID[1],
  478. dwRID[2],
  479. dwRID[3],
  480. dwRID[4],
  481. dwRID[5],
  482. dwRID[6],
  483. dwRID[7],
  484. &pSid );
  485. }
  486. if ( !bRet )
  487. {
  488. if ( pSid )
  489. {
  490. FreeSid( pSid );
  491. }
  492. return NULL;
  493. }
  494. return pSid;
  495. }
  496. // SetSecurityInfoOnHandle
  497. //
  498. // Explicity set the SecurityInfo on the Handle Given
  499. //
  500. BOOL
  501. CSecurityDescriptor::SetSecurityInfoOnHandle( HANDLE hHandle, SE_OBJECT_TYPE ObjectType, BOOL bAllowInheritance )
  502. {
  503. // At ths point our SD should be valid
  504. ASSERT( m_bSDValid );
  505. if ( m_bDAclIsInheritted )
  506. {
  507. // Even though they say not to use inheritance, we retrieved an ACL
  508. // which was inheritted. So if we don't set with inheritted, the
  509. // ACL will be different
  510. bAllowInheritance = TRUE;
  511. }
  512. return ( SetSecurityInfo( hHandle, // The Handle
  513. ObjectType, // Object type
  514. DACL_SECURITY_INFORMATION |
  515. ( bAllowInheritance ? UNPROTECTED_DACL_SECURITY_INFORMATION :
  516. PROTECTED_DACL_SECURITY_INFORMATION ),
  517. NULL, // Owner Sid
  518. NULL, // Group Sid
  519. GetCurrentDAcl(), // DAcl
  520. NULL ) == // SAcl
  521. ERROR_SUCCESS );
  522. }
  523. // SetSecurityInfoonFile
  524. //
  525. // Explicity set the Security Info on a File
  526. //
  527. // (If you do not want it to fail on file not existing, call SetSecurityInfoonFiles)
  528. //
  529. BOOL
  530. CSecurityDescriptor::SetSecurityInfoOnFile( LPTSTR szFile, BOOL bAllowInheritance )
  531. {
  532. HANDLE hFile;
  533. BOOL bRet;
  534. hFile = CreateFile( szFile,
  535. WRITE_DAC|READ_CONTROL,
  536. FILE_SHARE_WRITE | FILE_SHARE_READ,
  537. NULL, // No need for security, since it won't do what we want anyways
  538. OPEN_EXISTING,
  539. FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS,
  540. NULL );
  541. if ( hFile == INVALID_HANDLE_VALUE )
  542. {
  543. // Failed to open File
  544. return FALSE;
  545. }
  546. bRet = SetSecurityInfoOnHandle( hFile, SE_FILE_OBJECT, bAllowInheritance );
  547. CloseHandle( hFile );
  548. return bRet;
  549. }
  550. // SetSecurityInfoonFiles
  551. //
  552. // Explicity set the Security Info on a Multiple Files
  553. // The regular wildcard semantics to specify the files (ie. metbase*.xml)
  554. //
  555. // Note: Use this function, instead of SetSecurityInfoonFile if you do not
  556. // want it to fail if the file does not exist. This will ignore such
  557. // errors.
  558. //
  559. BOOL
  560. CSecurityDescriptor::SetSecurityInfoOnFiles( LPTSTR szFile, BOOL bAllowInheritance )
  561. {
  562. BOOL bRet = TRUE;
  563. HANDLE hFiles;
  564. WIN32_FIND_DATA fd;
  565. TSTR_PATH strFileName;
  566. TSTR_PATH strPath;
  567. LPTSTR szLastSlash;
  568. if ( !strPath.Copy( szFile ) )
  569. {
  570. return FALSE;
  571. }
  572. szLastSlash = _tcsrchr( strPath.QueryStr(), _T('\\') );
  573. if ( szLastSlash != NULL )
  574. {
  575. // Lets find the path (ie. c:\foo\test* -> c:\foo, c:\foo\test -> c:\foo)
  576. *szLastSlash = '\0';
  577. }
  578. hFiles = FindFirstFile( szFile, &fd );
  579. if ( hFiles == INVALID_HANDLE_VALUE )
  580. {
  581. if ( ( GetLastError() == ERROR_FILE_NOT_FOUND ) ||
  582. ( GetLastError() == ERROR_PATH_NOT_FOUND ) ||
  583. ( GetLastError() == ERROR_NO_MORE_FILES ) )
  584. {
  585. // If this is the case, then there is nothing to acl
  586. // so return success
  587. return TRUE;
  588. }
  589. // Failed to find the first instance of the file
  590. return FALSE;
  591. }
  592. do {
  593. if ( ( _tcscmp( fd.cFileName, _T(".") ) == 0 ) ||
  594. ( _tcscmp( fd.cFileName, _T("..") ) == 0 ) )
  595. {
  596. // Ignore the . and .. dirs
  597. continue;
  598. }
  599. if ( !strFileName.Copy( strPath ) ||
  600. !strFileName.PathAppend( fd.cFileName ) ||
  601. !SetSecurityInfoOnFile( strFileName.QueryStr() , bAllowInheritance ) )
  602. {
  603. // Failed to set ACL
  604. bRet = FALSE;
  605. }
  606. } while ( FindNextFile( hFiles, &fd ) );
  607. FindClose( hFiles );
  608. return ( bRet &&
  609. ( GetLastError() == ERROR_NO_MORE_FILES ) );
  610. }
  611. // DuplicateACL
  612. //
  613. // Take an ACL, and Duplicate it
  614. //
  615. // Note: This will NOT duplicate the inheritted items in the ACL
  616. //
  617. // Parameters:
  618. // pSourceAcl [in] - The ACL to Duplicate
  619. // pNewlyCreateAcl [out] - The ACL that has been created as a duplicated
  620. // NOTE: If we return TRUE, this must be free'd with LocalFree
  621. // Return Values:
  622. // FALSE - Failed to duplicate
  623. // TRUE - Success (don't forget to free)
  624. BOOL
  625. CSecurityDescriptor::DuplicateACL( PACL pSourceAcl, PACL *pNewlyCreateAcl )
  626. {
  627. BOOL bRet = FALSE;
  628. PEXPLICIT_ACCESS pEA;
  629. ULONG lNumberofEntries;
  630. if ( GetExplicitEntriesFromAcl( pSourceAcl, &lNumberofEntries, &pEA ) == ERROR_SUCCESS )
  631. {
  632. if ( SetEntriesInAcl( lNumberofEntries, pEA, NULL, pNewlyCreateAcl ) == ERROR_SUCCESS )
  633. {
  634. if ( *pNewlyCreateAcl == NULL )
  635. {
  636. // All the entries were inheritted, so create an empty ACL, instead
  637. // or returning NULL!
  638. *pNewlyCreateAcl = ( PACL ) LocalAlloc( LMEM_FIXED, sizeof(ACL) );
  639. if ( *pNewlyCreateAcl &&
  640. InitializeAcl( *pNewlyCreateAcl, sizeof(ACL) , ACL_REVISION ) )
  641. {
  642. bRet = TRUE;
  643. }
  644. if ( !bRet &&
  645. ( *pNewlyCreateAcl != NULL ) )
  646. {
  647. // Free memory on failure
  648. LocalFree( *pNewlyCreateAcl );
  649. *pNewlyCreateAcl = NULL;
  650. }
  651. }
  652. else
  653. {
  654. // Acl was created
  655. bRet = TRUE;
  656. }
  657. }
  658. LocalFree( pEA );
  659. }
  660. return bRet;
  661. }
  662. // IsInerittedAcl
  663. //
  664. // Determines if the acl was inheritted by a parent?
  665. //
  666. // This is important, because when we duplicate an ACL, it does not
  667. // duplicate the inheritted ACE's, so when we set it, we must say to
  668. // inherit the ACE's from parent
  669. //
  670. // Parameters
  671. // pSourceAcl - The Acl to test. NULL is valid here.
  672. //
  673. // Return Values:
  674. // TRUE - It is inheritting from parent
  675. // FALSE - It is not inheritting from parent
  676. //
  677. BOOL
  678. CSecurityDescriptor::IsInherittedAcl( PACL pSourceAcl )
  679. {
  680. BOOL bIsInheritted = FALSE;
  681. LPVOID pAce;
  682. ACE_HEADER *pAceHeader;
  683. DWORD dwCurrentAce = 0;
  684. if ( !pSourceAcl )
  685. {
  686. // If a NULL Acl is specified, then it is not inheritted,
  687. // since it has nothing in it.
  688. return FALSE;
  689. }
  690. while ( !bIsInheritted &&
  691. GetAce( pSourceAcl, dwCurrentAce, &pAce ) )
  692. {
  693. dwCurrentAce++;
  694. pAceHeader = (ACE_HEADER *) pAce;
  695. if ( pAceHeader->AceFlags & INHERITED_ACE )
  696. {
  697. // This ACE was inheritted, so mark it as such
  698. bIsInheritted = TRUE;
  699. }
  700. }
  701. return bIsInheritted;
  702. }
  703. // GetSecurityInfoOnHandle
  704. //
  705. // Retrieve the security Information for a particular Handle
  706. //
  707. BOOL
  708. CSecurityDescriptor::GetSecurityInfoOnHandle( HANDLE hHandle, SE_OBJECT_TYPE ObjectType )
  709. {
  710. BOOL bRet;
  711. PACL pDAcl;
  712. PACL pNewDAcl = NULL;
  713. PSECURITY_DESCRIPTOR pSD;
  714. if ( !InitializeSD() )
  715. {
  716. // Count not initialize SD
  717. return FALSE;
  718. }
  719. bRet = GetSecurityInfo( hHandle, // The Handle
  720. ObjectType, // Object type
  721. DACL_SECURITY_INFORMATION, // right now only retrieve security info
  722. NULL, // Owner Sid
  723. NULL, // Group Sid
  724. &pDAcl, // DAcl
  725. NULL, // SAcl
  726. &pSD ) == ERROR_SUCCESS;
  727. if ( bRet )
  728. {
  729. // This duplication does not copy inherited ACL's, only those
  730. // explicity set on this item, thus we must make sure that the
  731. // set does inherit acl's
  732. bRet = DuplicateACL( pDAcl, &pNewDAcl );
  733. if ( bRet &&
  734. !SetDAcl( pNewDAcl ) )
  735. {
  736. // Failed to set DAcl
  737. LocalFree( pNewDAcl);
  738. bRet = FALSE;
  739. }
  740. if ( bRet )
  741. {
  742. // Since during the duplication, we lost the inheritted acl's
  743. // we must set that bit now
  744. m_bDAclIsInheritted = IsInherittedAcl( pDAcl );
  745. }
  746. // Free the Sources Descriptor since we don't use it
  747. LocalFree(pSD);
  748. }
  749. return bRet;
  750. }
  751. BOOL
  752. CSecurityDescriptor::GetSecurityInfoOnFile( LPTSTR szFile )
  753. {
  754. HANDLE hFile;
  755. BOOL bRet;
  756. hFile = CreateFile( szFile,
  757. READ_CONTROL,
  758. FILE_SHARE_WRITE | FILE_SHARE_READ,
  759. NULL, // No need for security, since it won't do what we want anyways
  760. OPEN_EXISTING,
  761. FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS,
  762. NULL );
  763. if ( hFile == INVALID_HANDLE_VALUE )
  764. {
  765. // Failed to open File
  766. return FALSE;
  767. }
  768. bRet = GetSecurityInfoOnHandle( hFile, SE_FILE_OBJECT );
  769. CloseHandle( hFile );
  770. return bRet;
  771. }
  772. // DuplicateSD
  773. //
  774. // Duplicate the security descriptor that is send in, into
  775. // our class
  776. //
  777. BOOL
  778. CSecurityDescriptor::DuplicateSD( PSECURITY_DESCRIPTOR pSD )
  779. {
  780. SECURITY_DESCRIPTOR_CONTROL sdc;
  781. PACL pOldAcl;
  782. PACL pNewAcl;
  783. BOOL bAclPresent;
  784. BOOL bAclDefaulted;
  785. DWORD dwVersion;
  786. if ( !InitializeSD() )
  787. {
  788. // Count not initialize SD
  789. return FALSE;
  790. }
  791. if ( !GetSecurityDescriptorControl( pSD, &sdc, &dwVersion ) ||
  792. !SetSecurityDescriptorControl( &m_SD,
  793. SE_DACL_AUTO_INHERIT_REQ | // Mask of bits to set
  794. SE_DACL_AUTO_INHERITED |
  795. SE_DACL_PROTECTED |
  796. SE_SACL_AUTO_INHERIT_REQ |
  797. SE_SACL_AUTO_INHERITED |
  798. SE_SACL_PROTECTED,
  799. sdc ) )
  800. {
  801. // Failed to get current Security Descriptor Control,
  802. // or to set it
  803. return FALSE;
  804. }
  805. if ( !GetSecurityDescriptorDacl( &m_SD, &bAclPresent, &pOldAcl, &bAclDefaulted ) )
  806. {
  807. // Failed to get acl from old SD
  808. return FALSE;
  809. }
  810. if ( bAclPresent )
  811. {
  812. // If ACL is present, we must duplicate and set for current
  813. if ( !DuplicateACL( pOldAcl, &pNewAcl ) )
  814. {
  815. // Failed to duplicate DACL
  816. return FALSE;
  817. }
  818. if ( !SetDAcl( pNewAcl ) )
  819. {
  820. // Failed to set as current, so must delete pointer
  821. delete pNewAcl;
  822. return FALSE;
  823. }
  824. }
  825. return TRUE;
  826. }
  827. // CreateSelfRelativeSD
  828. //
  829. // Create a SelfRelative Source Descriptor
  830. //
  831. // Parameters:
  832. // pBuff - [in/out] Pointer to a BUFFER object as input. It is
  833. // filled with the contents of the SD, so it does
  834. // not have to be freed
  835. // pdwSize = [out] The length of the SD inside pBuff
  836. //
  837. BOOL
  838. CSecurityDescriptor::CreateSelfRelativeSD( BUFFER *pBuff, LPDWORD pdwSize )
  839. {
  840. DWORD dwSize = 0;
  841. ASSERT( pdwSize != NULL );
  842. ASSERT( pBuff != NULL );
  843. if ( MakeSelfRelativeSD( &m_SD, NULL, &dwSize ) ||
  844. !pBuff->Resize( dwSize ) )
  845. {
  846. // Either MakeSelfRelative did not fail as we expected with
  847. // the size, or Resize failed
  848. return FALSE;
  849. }
  850. if ( !MakeSelfRelativeSD( &m_SD,
  851. (PSECURITY_DESCRIPTOR) pBuff->QueryPtr(),
  852. &dwSize ) )
  853. {
  854. // Failed to make self relative
  855. return FALSE;
  856. }
  857. *pdwSize = dwSize;
  858. return TRUE;
  859. }
  860. // CreateDirectoryWithSA
  861. //
  862. // Create a Directory with a specific ACL. If the directory already exists,
  863. // then change the acl, and succeed.
  864. //
  865. BOOL CreateDirectoryWithSA( LPTSTR szPath, CSecurityDescriptor &pSD, BOOL bAllowInheritance )
  866. {
  867. BOOL bRet;
  868. // Check if the directory exists
  869. if ( IsFileExist( szPath ) )
  870. {
  871. // If it exists, then set ACL's on it
  872. bRet = pSD.SetSecurityInfoOnFile( szPath, bAllowInheritance );
  873. }
  874. else
  875. {
  876. // Create Directory with ACL's we specified
  877. bRet = CreateDirectory( szPath, pSD.QuerySA() );
  878. }
  879. return bRet;
  880. }
  881. // DoesFileSystemSupportACLs
  882. //
  883. // Does the File System Supplied here support ACLs
  884. //
  885. BOOL
  886. CSecurityDescriptor::DoesFileSystemSupportACLs( LPTSTR szPath, LPBOOL pbSupportAcls )
  887. {
  888. TSTR_PATH strDrivePath;
  889. DWORD dwSystemFlags;
  890. ASSERT( szPath );
  891. if ( !strDrivePath.Copy( szPath ) ||
  892. !strDrivePath.PathAppend( _T("") ) ||
  893. ( strDrivePath.QueryLen() < 3 ) )
  894. {
  895. return FALSE;
  896. }
  897. // Null terminate drive
  898. *( strDrivePath.QueryStr() + 3 ) = _T('\0');
  899. if ( !GetVolumeInformation( strDrivePath.QueryStr(),
  900. NULL, // Volume Name Buffer
  901. 0, // Size of Buffer
  902. NULL, // Serial Number Buffer
  903. NULL, // Max Component Lenght
  904. &dwSystemFlags, // System Flags
  905. NULL, // FS Type
  906. 0 ) )
  907. {
  908. // Failed to do query
  909. return FALSE;
  910. }
  911. *pbSupportAcls = ( dwSystemFlags & FS_PERSISTENT_ACLS ) != 0;
  912. return TRUE;
  913. }