DirectorySecurity IdentityNotMappedException

N

Nick

Hello,

I'm trying to add a DirectorySecurity ACL entry to an existing
directory (based on some code I found in the msdn).

However, this code only works on local machines because I can't specify
a server to resolve the identity, so when I try on a remote machine it
just can't find the user.

Any ideas how the following code can be applied to a remote server?

// Create a new DirectoryInfo object.
DirectoryInfo dInfo = new DirectoryInfo(FileName);

// Get a DirectorySecurity object that represents the
// current security settings.
DirectorySecurity dSecurity = dInfo.GetAccessControl();

try
{
// Add the FileSystemAccessRule to the security settings.
dSecurity.AddAccessRule(new FileSystemAccessRule(
Account, Rights, ControlType));

// Set the new access settings.
dInfo.SetAccessControl(dSecurity);
}
catch (IdentityNotMappedException e)
{
// Exception caught when username is invalid.
}

Cheers everyone!
 
W

Willy Denoyette [MVP]

Nick said:
Hello,

I'm trying to add a DirectorySecurity ACL entry to an existing
directory (based on some code I found in the msdn).

However, this code only works on local machines because I can't specify
a server to resolve the identity, so when I try on a remote machine it
just can't find the user.

Any ideas how the following code can be applied to a remote server?

// Create a new DirectoryInfo object.
DirectoryInfo dInfo = new DirectoryInfo(FileName);

// Get a DirectorySecurity object that represents the
// current security settings.
DirectorySecurity dSecurity = dInfo.GetAccessControl();

try
{
// Add the FileSystemAccessRule to the security settings.
dSecurity.AddAccessRule(new FileSystemAccessRule(
Account, Rights, ControlType));

// Set the new access settings.
dInfo.SetAccessControl(dSecurity);
}
catch (IdentityNotMappedException e)
{
// Exception caught when username is invalid.
}

Cheers everyone!
Not sure what you mean with a remote server here, but I guess you mean that
FileName is a UNC path right?
Well, you can't do that, the code must run on the server where the 'object'
is located, and the account must be a local account or a domain account.

Willy.
 
N

Nick

Hi Willy,

Yes you're exactly right, and I expected as much. The account is a
local account on a remote machine.

Is there an alternative way of setting security permissions on UNC
paths without having to call commands like xcacl?

Nick
 
W

Willy Denoyette [MVP]

Nick said:
Hi Willy,

Yes you're exactly right, and I expected as much. The account is a
local account on a remote machine.

Is there an alternative way of setting security permissions on UNC
paths without having to call commands like xcacl?

Nick

Yes, there are:
- Run your code on the remote server, or if that's no option,
- use WMI (System.Management) to set/change ACL permissions.
But I would prefer xcacls.

Willy.
 
N

Nick

Well, WMI was my first option, but after trawling the msdn library for
a while, I just couldn't find any classes that seemed to do the job.
Possibly because I've only really had experience with IIS WMI classes
so far.

Any idea what classes I should be looking for?
 
W

Willy Denoyette [MVP]

Nick said:
Well, WMI was my first option, but after trawling the msdn library for
a while, I just couldn't find any classes that seemed to do the job.
Possibly because I've only really had experience with IIS WMI classes
so far.

Any idea what classes I should be looking for?

Well using WMI is a non trivial task, there are a number of WMI classes you
need to know and you need a solid grasp of file object security in windows.

Following is basically what you need to do to add an ACE to a DACL on a
remote system.
- Connect to the remote server using WMI, beware that you need appropriate
access privs to the remote server and WMI.
- Create an instance of Win32_LogicalFileSecuritySetting passing the
filesystem object as Path
- call it's GetSecurityDescriptor, using
InvokeMethod("GetSecurityDescriptor,...)
- get the DACL from the SD
- create/initialize a Win32_Trustee instance with the name of the account
you like to add to the DACL
- create/initialize a new Win32_ACE class and set the above trustee as
Trustee property, set the other properties (AccessMask, AceFlags and
AceType)
- add the ACE to the DACL
- rewrite the DACL by calling InvokeMethod("SetSecurityDescriptor", ..)

Willy.
 
N

Nick

Great help wally, that looks like all I need to know. Thanks for the
class names!

Nick
 
M

mail

Finally got round to writing the method to apply security ACE's, and
this is what I've come up with so far. However, the userAccount and
newAce objects seem to be blank. And so it's just adding a blank ACE to
the first element in the DACL.

ManagementScope scope = new ManagementScope(@"\\" + ServerName +
@"\root\cimv2");

ManagementPath path = new ManagementPath();
path.RelativePath = @"Win32_LogicalFileSecuritySetting.Path="
+ "'" + fileName + "'";

ManagementObject fileSecurity = new ManagementObject(
scope, path, null);

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).CreateInstance();
userAccount.Properties["Name"].Value = account;

// Create a new ACE for the descriptor.
ManagementObject newAce = new ManagementClass(scope,
new ManagementPath("Win32_ACE"), null).CreateInstance();
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.
dacl.SetValue(newAce, 0);
descriptor.Properties["Dacl"].Value = dacl;

// User SetSecurityDescriptor to apply the descriptor.
ManagementBaseObject inParams =
fileSecurity.GetMethodParameters("SetSecurityDescriptor");
inParams["Descriptor"] = descriptor;
fileSecurity.InvokeMethod("SetSecurityDescriptor", inParams, null);
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top