Why do the following access rule show up as "Special permission" when I browse permissions in the explorer property window? I want it to appear as a normal "modify" access.
var di = new DirectoryInfo(ConfigDirectory);
DirectorySecurity security = di.GetAccessControl();
var rule = new FileSystemAccessRule(domainSid, FileSystemRights.Modify, AccessControlType.Allow);
security.AddAccessRule(rule);
di.SetAccessControl(security);
domainSid = SID for domain users.
How do I create the rule so it's inherited by all files that are created in that folder?
Use this instead:
var di = new DirectoryInfo(ConfigDirectory);
DirectorySecurity security = di.GetAccessControl();
var rule = new FileSystemAccessRule(domainSid, FileSystemRights.Modify, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.None, AccessControlType.Allow);
security.AddAccessRule(rule);
security.SetAccessRule(rule);
di.SetAccessControl(security);
The difference is using a FileSystemAccessRule Constructor that allows you to specifiy inheritance and the call to security.SetAccessRule(rule);
Related
I need a file to be editable by all local users. The application saves common information to all users in its own folder under ProgramData. I need to guarantee reading and writing to all users, it is so little information that it does not merit the use of a database.
I get the path to the folder from:Path.Combine(Application.CommonAppDataPath, "InfoConfig");
All users can read, write and create in this folder. Except the files that are created by the other users.
I already tried to remove Creator Owner without success. So my last attempt was not to inherit from the container folder and create the permissions from scratch for SYSTEM, Administrators and Users. But it didn't work either, here is my code.
string sharedFolder = Path.Combine(Application.CommonAppDataPath, "InfoConfig");
if (!Directory.Exists(sharedFolder))
{
DirectoryInfo directoryInfo = Directory.CreateDirectory(sharedFolder);
DirectorySecurity directorySecurity = directoryInfo.GetAccessControl();
directorySecurity.SetAccessRuleProtection(true, false);
FileSystemRights fileSystemRights =
FileSystemRights.FullControl |
FileSystemRights.Modify |
FileSystemRights.Read |
FileSystemRights.Delete;
SecurityIdentifier usersSid =
new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
SecurityIdentifier systemSid =
new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);
SecurityIdentifier adminsSid =
new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
FileSystemAccessRule rule =
new FileSystemAccessRule(systemSid, fileSystemRights, AccessControlType.Allow);
directorySecurity.AddAccessRule(rule);
rule = new FileSystemAccessRule(adminsSid, fileSystemRights, AccessControlType.Allow);
directorySecurity.AddAccessRule(rule);
rule = new FileSystemAccessRule(usersSid, FileSystemRights.Read
| FileSystemRights.Write
| FileSystemRights.Modify,
AccessControlType.Allow);
directorySecurity.AddAccessRule(rule);
directoryInfo.SetAccessControl(directorySecurity);
}
It still doesn't work. What am I doing wrong?
I have only considered the below snippet for usersSid, you can tweak it for the other userTypes as well
Have added ObjectSecurity.ModifyAccessRule(AccessControlModification, AccessRule, Boolean) which applies the specified modification to the Discretionary Access Control List (DACL) associated with this ObjectSecurity object (directorySecurity in our instance).
string sharedFolder = Path.Combine(Application.CommonAppDataPath, "InfoConfig");
if (!Directory.Exists(sharedFolder))
{
DirectoryInfo directoryInfo = Directory.CreateDirectory(sharedFolder);
DirectorySecurity directorySecurity = directoryInfo.GetAccessControl();
directorySecurity.SetAccessRuleProtection(true, false);
FileSystemRights fileSystemRights =
FileSystemRights.FullControl |
FileSystemRights.Modify |
FileSystemRights.Read |
FileSystemRights.Delete;
SecurityIdentifier usersSid =
new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
FileSystemAccessRule rule = new FileSystemAccessRule(usersSid, fileSystemRights,InheritanceFlags.None, PropagationFlags.NoPropagateInherit, AccessControlType.Allow);
directorySecurity.AddAccessRule(rule);
bool result;
directorySecurity.ModifyAccessRule(AccessControlModification.Set, rule, out result);
if (!result)
{
throw new InvalidOperationException("Failed to give full-control permission to all users for path " + path);
}
FileSystemAccessRule inheritedRule = new FileSystemAccessRule(
usersSid,
fileSystemRights,
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
PropagationFlags.InheritOnly,
AccessControlType.Allow);
bool inheritedResult;
directorySecurity.ModifyAccessRule(AccessControlModification.Add, inheritedRule, out inheritedResult);
if (!inheritedResult)
{
throw new InvalidOperationException("Failed to give full-control permission inheritance to all users for " + path);
}
directoryInfo.SetAccessControl(directorySecurity);
}
I'm trying to add the Full Control permission (for a NT service account) to a folder through C#. However, the permission is not set, what I am missing here?
var directoryInfo = new DirectoryInfo(#"C:\Test");
var directorySecurity = directoryInfo.GetAccessControl();
directorySecurity.AddAccessRule(new FileSystemAccessRule("NT Service\\FileMoverService",
FileSystemRights.FullControl, AccessControlType.Allow));
directoryInfo.SetAccessControl(directorySecurity);
You need to specify the inheritance flags:
directorySecurity.AddAccessRule(new FileSystemAccessRule(#"NT Service\FileMoverService",
FileSystemRights.FullControl,
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
PropagationFlags.None,
AccessControlType.Allow));
The method GrantFullControl can be used to set the Full Control permission for a given directory and user.
private static void GrantFullControl(string directoryPath, string username)
{
if (!Directory.Exists(directoryPath))
return;
var directorySecurity = Directory.GetAccessControl(directoryPath);
directorySecurity.AddAccessRule(new FileSystemAccessRule(username, FileSystemRights.FullControl,
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None,
AccessControlType.Allow));
Directory.SetAccessControl(directoryPath, directorySecurity);
}
Just call the method as shown below.
GrantFullControl(#"C:\Test", #"NT Service\FileMoverService");
I had a lot of pain programmatic creating a folder with ACL and owner..
Taks:
Create a folder only accessible by one user (not even Administrator).
(current) Solution:
Run as Admin:
// path is the directory, "target" the parent directory
String path = Path.Combine(target, "Data");
DirectorySecurity ds = Directory.GetAccessControl(target);
// up is the "UserPrincipal"
ds.AddAccessRule(new FileSystemAccessRule(up.Sid, FileSystemRights.CreateDirectories, AccessControlType.Allow));
Directory.SetAccessControl(target, ds);
// safeTokenHandle_SecureUser is the token of the already logged in User stored in "up"
using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(safeTokenHandle_SecureUser.DangerousGetHandle()))
{
ds = new DirectorySecurity();
// Set owner only works impersonated
ds.SetOwner(up.Sid);
// Inherited needs impersonation
ds.AddAccessRule(new FileSystemAccessRule(up.Sid, FileSystemRights.FullControl, InheritanceFlags.ObjectInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));
// Add Backupgroup
ds.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier("S-1-5-32-551"), FileSystemRights.Read, InheritanceFlags.ObjectInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));
DirectoryInfo directory = Directory.CreateDirectory(path, ds);
}
Problem:
Path created in "C:\temp\Sec53" (jea, count my tries.. but multiple tries are i the same directory..)
c:\temp\Sec53>whoami
pc-XXX\YYYuser93
c:\temp\Sec53>dir /q (1)
Datenträger in Laufwerk C: ist Windows
Volumeseriennummer: ...
Verzeichnis von c:\temp\Sec53
13.02.2019 13:13 <DIR> VORDEFINIERT\Administra. (2)
13.02.2019 13:13 <DIR> AAA\BBB ..
13.02.2019 13:13 <DIR> XXX\YYYUser93 Data
(TRIM)
c:\temp\Sec53>cacls *
c:\temp\Sec53\Data VORDEFINIERT\Sicherungs-Operatoren:(OI)(IO)(Beschränkter Zugriff:) (3)
READ_CONTROL
SYNCHRONIZE
FILE_GENERIC_READ
FILE_READ_DATA
FILE_READ_EA
FILE_READ_ATTRIBUTES
XXX\YYYUser93:(OI)(IO)F
(TRIM)
c:\temp\Sec53>cd Data
Zugriff verweigert (4)
"Dir /q" shows the owner
User is: Predefined / Administrator
User is: Predefined / Backup operator group
Tranlated: Access denied
You can see, I'm logged in CMD with this user. The directory exists and the owner is the user. Permissions to this user are set to Full. But I'm still not able to change in this directory.
What is wrong? WTF? What can I do?
Got it, at try number 75..
two rules needed, one for current object, one for inherited..
ds.AddAccessRule(new FileSystemAccessRule(up.Sid, FileSystemRights.FullControl, AccessControlType.Allow));
ds.AddAccessRule(new FileSystemAccessRule(up.Sid, FileSystemRights.FullControl, InheritanceFlags.ContainerInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));
In the question I only create the inherited rule (with wrong Flags).
OS Windows 7 SP1 x64
I set ACL permissions to my folder for some account:
var accessRule = new FileSystemAccessRule(account,
fileSystemRights: FileSystemRights.Modify,
inheritanceFlags: InheritanceFlags.ContainerInherit |
InheritanceFlags.ObjectInherit,
propagationFlags: PropagationFlags.None,
type: AccessControlType.Allow);
// Get a DirectorySecurity object that represents the
// current security settings.
DirectorySecurity dSecurity = directoryinfo.GetAccessControl();
// Add the FileSystemAccessRule to the security settings.
dSecurity.AddAccessRule(accessRule);
// Set the new access settings.
directoryinfo.SetAccessControl(dSecurity);
At this case I allowed read and write for account. It works fine.
But later I wanted to change the rights for that account: to allow read only permissions. I use such code:
var accessRule = new FileSystemAccessRule(account,
fileSystemRights: FileSystemRights.ReadAndExecute,
inheritanceFlags: InheritanceFlags.ContainerInherit |
InheritanceFlags.ObjectInherit,
propagationFlags: PropagationFlags.None,
type: AccessControlType.Allow);
// Get a DirectorySecurity object that represents the
// current security settings.
DirectorySecurity dSecurity = directoryinfo.GetAccessControl();
// Add the FileSystemAccessRule to the security settings.
dSecurity.AddAccessRule(accessRule);
// Set the new access settings.
directoryinfo.SetAccessControl(dSecurity);
But the account has write permissions still. How can I fix it? Also, how can I remove the ACL permissions for that account when I will want to do it later?
It is quite easy:
dSecurity = directoryinfo.GetAccessControl();
accessRule = new FileSystemAccessRule(account,
fileSystemRights: FileSystemRights.ReadAndExecute,
inheritanceFlags: InheritanceFlags.ContainerInherit |
InheritanceFlags.ObjectInherit,
propagationFlags: PropagationFlags.None,
type: AccessControlType.Allow);
dSecurity.SetAccessRule(accessRule);
directoryinfo.SetAccessControl(dSecurity);
and for removing:
dSecurity = directoryinfo.GetAccessControl();
accessRule = new FileSystemAccessRule(account, 0, 0);
dSecurity.RemoveAccessRuleAll(accessRule);
directoryinfo.SetAccessControl(dSecurity);
Note that the SetAccessRule will work even if there is no access rule for the account (so it can even be used to do the initial Add)
I want to change some folder permissions (set to Read-Only) to ReadWriteExecute!
I wrote this code, but the folder permission is still Read-Only:
private void ChangePermissions(string folder)
{
string userName = Environment.UserName;
FileSystemAccessRule accessRule = new FileSystemAccessRule(userName, FileSystemRights.FullControl, InheritanceFlags.ContainerInherit
| InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow);
DirectoryInfo directoryInfo = new DirectoryInfo(folder);
DirectorySecurity directorySec = directoryInfo.GetAccessControl();
directorySec.AddAccessRule(accessRule);
directoryInfo.SetAccessControl(directorySec);
}
If I want delete this directory with Directory.Delete(folder, true) I get this error message:
"Access to the path 'entries' is denied."
Sure, the permissions are still Read-Only!
What is wrong here?
You could try something like this:
var dirInfo = new DirectoryInfo(folder);
dirInfo.Attributes &= ~FileAttributes.ReadOnly;
This uses the bitwise logical AND operator (&=) to append to the existing Attributes property the inverse of FileAttributes.ReadOnly (because ~ is bitwise NOT).