Programmatically Configuring Permissions on a Share

I was asked this problem on how to set up permission for a share programmatically using .Net Framework. Well, I am not aware of any API that can do that. Searching does not return any good result. There are lot of resources on how to configure permission settings for local folder, but not so much for UNC path. At the end, I dug msdn and had my solution, using WMI.

To setup a share, you need these information, the share that you want to setup (securable or trustee), whom you will give the permissions to the share (principal), what kind of permissions you want to give.

Using this scenario, you have a share \\ContosoServer\JohnShare, and you want John Doe (contoso\johndoe) to have full access to this share. The steps to configure the share permissions are as follow:

  • Create a WMI instance of the principal (Win32_Trustee).
    //Getting the Sid value is not required for Vista.
    NTAccount account = newNTAccount(Domain, UserName);
    SecurityIdentifiersid = (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier));
    byte[] sidArray = new byte[sid.BinaryLength];
    sid.GetBinaryForm(sidArray, 0);

    ManagementObject Trustee = new ManagementClass(new ManagementPath("Win32_Trustee"), null);
    Trustee["Domain"] = "contoso";
    Trustee["Name"] = "johndoe";
    Trustee["SID"] = sidArray;

  • Create a WMI instance of Win32_Ace, assign the Trustee to this Win32_Ace instance.
    ManagementObject AdminACE = new ManagementClass(new ManagementPath("Win32_Ace"), null);
    AdminACE["AccessMask"] = 2032127;
    AdminACE["AceFlags"] = 3;
    AdminACE["AceType"] = 0;
    AdminACE["Trustee"] = Trustee;

    To know what values you need to put there, check msdn (link). I actually encourage you to write an enum flag to encapsulate those values.
    In nut shell, 2032127 is for full access, Access Flags 3 is for non-container and container child objects to inherit the ACE, and Ace Type 0 is to allow the trustee to access it.

  • Create a WMI instance of the security descriptor (Win32_SecurityDescriptor)
    ManagementObject secDescriptor = new ManagementClass(new ManagementPath("Win32_SecurityDescriptor"), null);
    secDescriptor["ControlFlags"] = 4; //SE_DACL_PRESENT
    secDescriptor["DACL"] = new object[] { AdminACE};

  • Now, create a WMI instance of Win32_Share, and setup the security.
    ManagementObject share = new ManagementObject(@"\\ContosoServer\root\cimv2:Win32_Share.Name='JohnShare'");
    share.InvokeMethod("SetShareInfo", new object[] {Int32.MaxValue, "This is John's share", secDescriptor});
    Check the return value of the Invoke, the method returns an Object, convert it to Int32.

That code will overwrite the existing permission, so be careful. WMI stuff are available in System.Management assemblies.

For references, these are the links that you will be interested with, Win32_Trustee, Win32_ACE, Win32_SecurityDescriptor, and Win32_Share.

Update (6/9/2008)

I updated the first step with the code to assign Sid, thanks to David Smith for his email. With Windows Vista, you do not need to supply Sid. You can supply just the domain name and the user name, it will work. Using Server 2003, and most likely XP, you have to supply all three, user name, domain, and Sid.