none
Can I get analog of SetFileSecurity function in C#? RRS feed

  • Question

  • I'm very newbie in C#. I need to re-write some tests from Python, so, I'm stuck on this part:
    In Python I can freely edit DACL with pywin32 (it's a modules with C++ implementation to work with Windows API). 
    I can edit any ACE with win32security.

    Change owner to Everyone? Okay.

    # set_owner_everyone.py
    import win32security
    win32security.SetNamedSecurityInfo("somefile.txt", win32security.SE_FILE_OBJECT, win32security.OWNER_SECURITY_INFORMATION, win32security.ConvertStringSidToSid("S-1-1-0"))
    sd.SetSecurityDescriptorDacl(1, dacl, 0)
    win32security.SetFileSecurity(filename, win32security.DACL_SECURITY_INFORMATION, sd)

    Remove one of inherited ACE? Easy.

    # remove_one_ace.py

    import win32security sd = win32security.GetFileSecurity("", win32security.DACL_SECURITY_INFORMATION) dacl = SECURITY_DESCRIPTOR.GetSecurityDescriptorDacl() dacl.DeleteAce(0) sd.SetSecurityDescriptorDacl(1, dacl, 0) # may not be necessary win32security.SetFileSecurity(filename, win32security.DACL_SECURITY_INFORMATION, sd)

    And all of those without some special permissions.

    But if I want to do something like this in C# (one way I found is changing security descriptor with pure SDDL), but `System.Security.File.SetAccessControl()` with `FileSecurity`, that defined by `SetSecutiryDesctiptorSddlForm` doesn't work without privelege `SeSecurityPrivelege`. Also, even with administrator token with nearly all privileges, if I want to change something in "wrong" way (delete some inherited ACE's), security descriptor doesn't apply. If I try to do something "very wrong", like set owner to Everyone, exception will be thrown.

    var sddl_everyone_owner = @"O:S-1-1-0G:DUD:P";
    var path = @"C:\Users\someuser\test.txt";
    FileSecurity fs_edit = new FileSecurity();
    
    fs_edit.SetSecurityDescriptorSddlForm(sddl_everyone_owner);
    File.SetAccessControl(path, fs_edit);

    Run with administrator token:

        Unhandled Exception: System.InvalidOperationException: The security identifier is not 
        allowed to be the owner of this object.
        at System.Security.AccessControl.NativeObjectSecurity.Persist(String name, SafeHandle 
           handle, 
           AccessControlSections includeSections, Object exceptionContext)
        at System.Security.AccessControl.NativeObjectSecurity.Persist(String name, 
           AccessControlSections includeSections, Object exceptionContext)
        at System.Security.AccessControl.NativeObjectSecurity.Persist(String name, 
           AccessControlSections includeSections)
        at System.Security.AccessControl.FileSystemSecurity.Persist(String fullPath)
        at System.IO.File.SetAccessControl(String path, FileSecurity fileSecurity)
        at rtest.Program.Main(String[] args) in C:\somepath\Program.cs:line 52


    Specification of C++ SetFileSecurity function: [I can't post links] just google 'SetFileSecurity function'


    Wednesday, June 20, 2018 4:24 PM

All replies

  • Hi Egor Egorov,

    Thank you for posting here.

    According to your question, the SetSecurityDescriptorSddlForm is used to set security descriptor. It could do the operations like changing owner to everyone.

    For more details about SetSecurityDescriptorSddlForm, please refer to the MSDN document.

    https://msdn.microsoft.com/en-us/library/59y7ckty%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396

    If you want to set the rights of a file using C#, you could try the code below.

            public static void AddFileSecurity(string fileName, string account,
                FileSystemRights rights, AccessControlType controlType)
            {
    
    
                // Get a FileSecurity object that represents the
                // current security settings.
                FileSecurity fSecurity = File.GetAccessControl(fileName);
    
                // Add the FileSystemAccessRule to the security settings.
                fSecurity.AddAccessRule(new FileSystemAccessRule(account,
                    rights, controlType));
    
                // Set the new access settings.
                File.SetAccessControl(fileName, fSecurity);
    
            }

    For more details about the code sample, you could refer to the MSDN document.

    https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.filesecurity(v=vs.110).aspx

    And the dll which works well in Python, if the dll is c++ dll, you could try to call the dll in C#. It could do the same thing which you do in Python.

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Thursday, June 21, 2018 8:08 AM
    Moderator
  • After 11 hours of googling, then trying to write some woking code i have this:

    // changes SDDL of file:
    using System;
    using System.Runtime.InteropServices; // DllImport
        
    public class SomeClass
        {
        [DllImport("Advapi32.dll", SetLastError = true)]
        static extern void SetFileSecurity(string path, int type_of_sd, IntPtr sd);
        [DllImport("Advapi32.dll", SetLastError = true)]
        static extern bool ConvertStringSecurityDescriptorToSecurityDescriptor(string StringSecurityDescriptor, uint StringSDRevision, out IntPtr SecurityDescriptor, out UIntPtr SecurityDescriptorSize);
        private static void Main()
        {
            string path = @"C:\Some\path\to\file";
            string sddl = "D:AI(A;ID;FA;;;S-1-1-0)"; // set only one ACE: inherited full access to Everyone
            uint sd_revision = 1;  // the only revision of SECURITY_DESCRIPTOR
            int DACL_SECURITY_INFORMATION = 4; // can be changed to change other properties, not DACL, relying on SECURITY_DESCRIPTOR_CONTROL parameters https://msdn.microsoft.com/ru-ru/library/windows/desktop/aa379566%28v=vs.85%29.aspx
            IntPtr sd_ptr = new IntPtr();
            UIntPtr sd_size_ptr = new UIntPtr();
            ConvertStringSecurityDescriptorToSecurityDescriptor(sddl, sd_revision, out sd_ptr, out sd_size_ptr);
            SetFileSecurity(path, DACL_SECURITY_INFORMATION, sd_ptr);
        }
    }

    This code import functions from Advapi32.dll right to C# code. 
    Special thanks to PInvoke dot net (I still doesn't able to add hyperlinks)
    Added this code to code samples there.

        
    • Edited by Egor Egorov Thursday, June 21, 2018 4:35 PM
    Thursday, June 21, 2018 2:57 PM