Changing security permissions on files and directories using c#

  • Thread starter Thread starter Misha
  • Start date Start date
M

Misha

Hello,
I am trying to find a way to change directory permissions using C#
(like dir ownership and access rights). Is there any c# librery that
could help me do that? or should i use other solutions? (what are
they?)

Thanks.
 
Misha,

There is nothing out of the box in .NET that will help you with this.
If you want to do this, you will have to call the appropriate APIs through
the P/Invoke layer to get the same functionality.

Hope this helps.
 
Using .NET v1.0 and 1.1 you have several options, note that whatever method
you use it is not a trivial task, simply because DACL programming is hard as
you need to know exactly how DACL's work.

Listed in order of simplicity/availability....

1- Use the System.Management classes and the WMI classes.
Here is a complete sample illustrating how to list NTFS security objects and
adding an ACE to a DACL:

using System;
using System.Management;
using System.Collections;
// Access mask (see AccessMask property)
[Flags]
enum Mask : uint
{
FileReadData = 0x00000001,
FileWriteData = 0x00000002,
FileAppendData = 0x00000004,
FileReadEA = 0x00000008,
FileWriteEA = 0x00000010,
FileExecute = 0x00000020,
FileDeleteChild = 0x00000040,
FileReadAttributes = 0x00000080,
FileWriteAttributes= 0x00000100,

Delete = 0x00010000,
ReadControl = 0x00020000,
WriteDac = 0x00040000,
WriteOwner = 0x00080000,
Synchronize = 0x00100000,

AccessSystemSecurity = 0x01000000,
MaximumAllowed = 0x02000000,

GenericAll = 0x10000000,
GenericExecute= 0x20000000,
GenericWrite = 0x40000000,
GenericRead = 0x80000000
}
[Flags]
enum AceFlags : uint
{
NonInheritAce = 0,
ObjectInheritAce = 1,
ContainerInheritAce = 2,
NoPropagateInheritAce = 4,
InheritOnlyAce = 8,
InheritedAce = 16
}

[Flags]
enum AceType : uint
{
AccessAllowed = 0,
AccessDenied = 1,
Audit = 2
}
public class FileObjectSecurity : IDisposable
{
ManagementPath path;
ManagementObject lfs;
ManagementBaseObject Descriptor; // Security descriptor for this object
ManagementBaseObject[] dacl;
bool disposed;

public FileObjectSecurity(string FileObject)
{
path = new ManagementPath();
path.Server = "."; // server name (. for local machine)
path.NamespacePath = @"root\cimv2";
path.RelativePath = @"Win32_LogicalFileSecuritySetting.Path=" + "'" +
FileObject + "'";
lfs = new ManagementObject(path);
}

// Get array of ACE's.
// Dump ACE's to console if DumpToConsole = true
public void GetACEs(bool DumpToConsole)
{
GetObjectDacl();
if(DumpToConsole)
DumpDaclToConsole();
}
private void DumpDaclToConsole()
{
foreach(ManagementBaseObject mbo in this.dacl){
Console.WriteLine("-------------------------------------------------");
Console.WriteLine("{0:X} - {1} - {2}", mbo["AccessMask"],
Enum.Format(typeof(AceFlags), mbo["AceFlags"], "g") , mbo["AceType"]);
// Access allowed/denied ACE
if(Convert.ToInt32(mbo["AceType"]) == (int)AceType.AccessDenied)
Console.WriteLine("DENIED ACE TYPE");
else
Console.WriteLine("ALLOWED ACE TYPE");
// Dump trustees
ManagementBaseObject Trustee = ((ManagementBaseObject)(mbo["Trustee"]));
Console.WriteLine("Name: {0} - Domain: {1} - SID {2}\n",
Trustee.Properties["Name"].Value,
Trustee.Properties["Domain"].Value,
Trustee.Properties["SIDString"].Value);
// Dump ACE mask in readable form
UInt32 mask = (UInt32)mbo["AccessMask"];
Console.WriteLine(System.Enum.Format(typeof(Mask), mask, "g"));
}
}

private bool WriteSecurityDescriptor(ManagementBaseObject[] Dacl)
{
ManagementBaseObject inParams =
lfs.GetMethodParameters("SetSecurityDescriptor");
Descriptor.Properties["Dacl"].Value = Dacl;
inParams["Descriptor"] = Descriptor;
ManagementBaseObject ret = lfs.InvokeMethod("SetSecurityDescriptor",
inParams, null);
if ((Convert.ToUInt32(ret.Properties["ReturnValue"].Value) == 0))
return true;
else
return false;
}
// Add an ACE to the DACL
public bool AddACEToDacl(string TrusteeName, Enum Mask)
{
Array newDACL;
// Copy the non-inherit aces
ArrayList aceList = new ArrayList();
foreach(ManagementBaseObject entry in this.dacl)
{
if ((uint)entry["AceFlags"] == (uint)AceFlags.NonInheritAce)
{
aceList.Add(entry);
}
}
// Creates and initializes a one-dimensional Array of type
ManagementBaseObject
// with space for one extra direct ACE.
newDACL=Array.CreateInstance( typeof(ManagementBaseObject), aceList.Count
+ 1);
// Copy AL to Array
aceList.CopyTo(newDACL);
ManagementBaseObject trustee = null;
ManagementBaseObject ace = null;

// Initialize new Trustee (here a local accoun as sample)
try {
trustee = new ManagementClass( @"Win32_Trustee" );
// trustee.Properties["Domain"].Value = ""; // if domain other then local
machine
trustee.Properties["Name"].Value = TrusteeName;
}
// catch if non existing trustee
catch (Exception e)
{
Console.WriteLine(e.Message);
return false;
}
try {
ace = new ManagementClass( @"Win32_ACE" );
ace.Properties["AccessMask"].Value = Mask;
ace.Properties["AceFlags"].Value = AceFlags.NoPropagateInheritAce;
ace.Properties["AceType"].Value = AceType.AccessAllowed;
ace.Properties["Trustee"].Value = trustee;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return false;
}
Console.WriteLine(newDACL.Length);
newDACL.SetValue(ace, newDACL.Length - 1);
return WriteSecurityDescriptor((ManagementBaseObject[])newDACL);
}

private void GetObjectDacl()
{
// Get the security descriptor for this object
bool EnablePrivileges = lfs.Scope.Options.EnablePrivileges;
lfs.Scope.Options.EnablePrivileges = true;
ManagementBaseObject outParams =
lfs.InvokeMethod("GetSecurityDescriptor", null, null);
if (((uint)(outParams.Properties["ReturnValue"].Value)) == 0) // if
success
{
Descriptor =
((ManagementBaseObject)(outParams.Properties["Descriptor"].Value));
//The DACL is an array of Win32_ACE objects.
dacl = ((ManagementBaseObject[])(Descriptor.Properties["Dacl"].Value));
}
return;
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if(!this.disposed)
{
// Release ManagementObject.
lfs.Dispose();
}
disposed = true;
}

~FileObjectSecurity()
{
Dispose(false);
// BUG BUG, finalizer should never be called. Object should be Disposed
by client.
// Failing to call dispose, will throw in debug build
#if DEBUG
throw new Exception("Finalizer called on disposable object");
#endif
}
}


class Tester {
public static void Main()
{
// Create FileObjectSecurity passing the file object (filepath) to the
ctor.
// Beware the double backslashes !!!!

using (FileObjectSecurity fos = new
FileObjectSecurity(@"c:\\somedir\\somefile"))
{
fos.GetACEs(false); // Get DACL no console dump
fos.AddACEToDacl("Users", Mask.FileWriteData);
fos.GetACEs(true); // Get DACL and dump to console

}
}
}


2- Use System.DirectoryServices and ADSI security client (included in
activeds.dll on XP and higher).
Using this method is similar to 1, but it requires a reference to
activeds.tld and COM interop.

3- Use MC++ and IJW interop with the NTFS security API's.

4- Use PInvoke interop from C# to call the NTFS security API's.

5- Wait for .NET v2.0.

Willy.
 
Back
Top