locked
Trouble comparing ACLs for equality: SetNamedSecurityInfo RRS feed

  • Question

  • I work at a backup company and we're trying to preserve security descriptors when customers backup and restore their files. However, the SetSecurityInfo and SetNamedSecurityInfo functions can modify the DACL transparently, thus causing the comparison of security descriptors (via SDDL string equality) to fail.

    We need to preserve and restore all ACLs, both sane and insane. For example, if I have an ACL with two entries: file-read to everyone and file-all-access to everyone:

    (A;;FR;;;WD)(A;;FA;;;WD)

    using SetNamedSecurityInfo will modify these and append inheritable ACEs from the parent. If the parent grants file-read to authenticated users as an inheritable ACE, SetNamedSecurityInfo will simplify the above ACL and append the ACE from the parent:

    (A;;FA;;;WD)(A;OICIIO;FR;;;AU)

    Obviously, these two SDDL strings aren't equal.

    There's EqualSID for comparing SIDs, but I don't see a way to compare ACLs for effective equality. Lastly, SetFileSecurity yields permission denied irregularly and I can't figure out why. Since that API is deprecated, we're migrating to SetNamedSecurityInfo.

    I could enumerate the ACEs in the ACL and perform GetEffectiveRightsFromACL on each SID present, but doing that for every single file in our backup utility will slow down the utility greatly.

    I have extensive knowledge and understanding about the Windows security model and relevant APIs, and so I welcome very technical answers.

    Friday, December 5, 2014 7:46 PM

Answers

  • I believe the Backup APIs are going to read/write all the streams in the file.  You can read/write individual streams via CreateFile() but you are going to have an issue with the permissions on the file if you aren't backing/restoring to the same system with the same security permissions when the backup happened.

    It sounds like from your description, attempting to maintain the same security permissions is going to be difficult.

    thanks

    Frank K [MSFT]

    • Marked as answer by Peter W Schultz Wednesday, December 10, 2014 11:55 PM
    Wednesday, December 10, 2014 10:59 PM

All replies

  • You should be using BackupRead() and BackupWrite() which will back up the entire security descriptor.

    thanks

    Frank K[MSFT]

    • Proposed as answer by Pavel A Tuesday, December 9, 2014 2:29 PM
    • Unproposed as answer by Peter W Schultz Tuesday, December 9, 2014 7:40 PM
    Tuesday, December 9, 2014 4:35 AM
  • There's a complication that makes BackupRead() and BackupWrite() not usable in all situations.

    We allow customers to backup their data to a web-visible storage system and download files by either mounting the system as a network drive or browsing to our internal file browser and downloading the file that way. Both of these methods assume the file is in its normal state and neither case can make use of BackupWrite() without some very heavy modifications.

    Can I select the streams I want to backup and restore, omitting $DATA (unnamed and named)? There isn't documentation on dissecting the backup data or configuring what you want to read/write.

    Tuesday, December 9, 2014 7:39 PM
  • I believe the Backup APIs are going to read/write all the streams in the file.  You can read/write individual streams via CreateFile() but you are going to have an issue with the permissions on the file if you aren't backing/restoring to the same system with the same security permissions when the backup happened.

    It sounds like from your description, attempting to maintain the same security permissions is going to be difficult.

    thanks

    Frank K [MSFT]

    • Marked as answer by Peter W Schultz Wednesday, December 10, 2014 11:55 PM
    Wednesday, December 10, 2014 10:59 PM
  • You are going to have to use a low level API to set these and not the high level API's that apply inheritance to the children of the objects.   For example, use SetKernelObjectSecurity to set your descriptor.

    If you use GetSecurityInfo you can get the ppSecurityDescriptor, just access the data in this pointer and save it raw to your backup then write it raw using SetKernelObjectSecurity when you want to restore it. 

    They have documented that SetFileSecurity is depreciated but, that is a low level API that ignores setting inheritance ACE's.  It is better at setting 'insane' ACE's but not always.  Also, using the API's to read the descriptor to a string and then back also seem to be 'goofy'.  There is no need to make the descriptor readable, so just save it off to your backup raw.

    I would use GetSecurityInfo  to get ALL descriptors and then save if off without trying to convert it to a string (meaning binary, not converting it to (A;;FR;;;WD)(A;;FA;;;WD) . . . ).  Then when you restore, read back your raw descriptor and use SetKernelObjectSecurity to save it.

     
    Friday, June 19, 2015 3:48 PM