Hi guys,
So far I've spent about a week hacking away at this code, and I just
can't get it to add an ACE to a the DACL for a network share using WMI.
Just to set the scene, I'm trying to add an ACL from machine A
(workstation; Saturn) and set it to a UNC path
(\\Mercury\Inetpub\Websites\LocalUser\Test) on machine B (server;
Mercury).
Neither of these machines are on a domain, and the trustee for the new
ACL is a local user on machine B (server; Mercury), lets call him
'test' for now.
I don't want to use xcacls because it's a bit of a hack, and the ADSI
code from Microsoft looks a little offputting as it uses COM
(http://support.microsoft.com/kb/899553/EN-US/).
At this point I'm able to use the following code to apply permissions
to a local resource on machine A (e.g. C:\Test), however when I try it
on a UNC path it throws a ManagementException with the message "Not
Found", which isn't very useful.
I can only presume it's complaing about the UNC path. I've tried
doubling up the slashes, and just having single slashes (which makes no
difference).
// Works when server name is ".", "SATURN" but not "MERCURY".
ManagementScope scope = new ManagementScope(@"\\" + ServerName +
@"\root\cimv2");
// Works when fileName is local directory, but not UNC path.
ManagementPath path = new ManagementPath();
path.RelativePath = @"Win32_LogicalFileSecuritySetting.Path="
+ "'" + fileName + "'";
ManagementObject fileSecurity = new ManagementObject(
scope, path, null);
// When used with UNC path, exception with "Not Found" is thrown.
ManagementBaseObject outParams =
(ManagementBaseObject)fileSecurity.InvokeMethod(
"GetSecurityDescriptor", null, null);
// Get security descriptor and DACL for specified file.
ManagementBaseObject descriptor =
(ManagementBaseObject)outParams.Properties["Descriptor"].Value;
ManagementBaseObject[] dacl =
(ManagementBaseObject[])descriptor.Properties["Dacl"].Value;
// Get the user account to be trustee.
ManagementObject userAccount = new ManagementClass(scope,
new ManagementPath("Win32_Trustee"), null);
userAccount.Properties["Name"].Value = account;
// Create a new ACE for the descriptor.
ManagementObject newAce = new ManagementClass(scope,
new ManagementPath("Win32_ACE"), null);
newAce.Properties["Trustee"].Value = userAccount;
// Low level ace flags.
int FILE_READ_DATA = 0x0;
int FILE_WRITE_DATA = 0x1;
int FILE_APPEND_DATA = 0x4;
int DELETE = 0x10000;
// Translate FileSystemRights to flags.
switch (accessRights)
{
case FileSystemRights.Read:
newAce.Properties["AccessMask"].Value = FILE_READ_DATA;
break;
case FileSystemRights.Modify:
newAce.Properties["AccessMask"].Value = FILE_READ_DATA
| FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE;
break;
}
// ACL will be inherited.
newAce.Properties["AceFlags"].Value = 0x10;
// Allow access to resource.
newAce.Properties["AceType"].Value = 0;
// Add ACE to DACL and set to descriptor.
ArrayList daclArray = new ArrayList(dacl);
daclArray.Add(newAce);
descriptor.Properties["Dacl"].Value = daclArray.ToArray();
// User SetSecurityDescriptor to apply the descriptor.
ManagementBaseObject inParams =
fileSecurity.GetMethodParameters("SetSecurityDescr iptor");
inParams["Descriptor"] = descriptor;
fileSecurity.InvokeMethod("SetSecurityDescriptor", inParams, null);