I had an issue in FlacLibSharp in which I incorrectly removed a file's access rights when saving changes.

To make a test for this issue, I had to do two things:

  • Set a specific access right on a file (in my case, give Everyone Read access)
  • Check if that access right is on the file

Setting Access Rights

I wanted to give the "Everyone" group "Read" access to my file.

To do this in .NET, three things are needed:

  • A SecurityIdentifier
  • A FileSystemAccessRule
  • A FileSystemSecurity

The SecurityIdentifier defines who or what you want to set the access for. In my case for "Everyone":

var everyone = new SecurityIdentifier(WellKnownSidType.WorldSid, null);

There are several "Well Known SID Types" available. "World" is another name for the "Everyone" group.

FileSystemAccessRule defines what actions are being allowed or denied. In my case: "Allow Read for Everyone".

var accessRule = new FileSystemAccessRule(everyone, FileSystemRights.Read, AccessControlType.Allow);

FileSystemSecurity contains information about the target file's current security settings and ACL (Access Control List).

var fileSecurity = File.GetAccessControl(path);

To actually add the access right to the file, the FileSystemAccessRule must be added to the FileSystemSecurity:

fileSecurity.AddAccessRule(accessRule);

And finally this modified security information must be applied to the file:

File.SetAccessControl(path, fileSecurity);

Putting it all together:

private void GiveEveryoneReadAccess(string path)
{
    var everyone = new SecurityIdentifier(WellKnownSidType.WorldSid,
                                          null);

    var accessRule = new FileSystemAccessRule(everyone,
                                              FileSystemRights.Read,
                                              AccessControlType.Allow);

    var fileSecurity = File.GetAccessControl(path);
    fileSecurity.AddAccessRule(accessRule);
    File.SetAccessControl(path, fileSecurity);
}

Checking for specific access rights

Very similar, the following is needed:

  • A SecurityIdentifier
  • A FileSystemSecurity
  • An AuthorizationRuleCollection (an ACL)

These can be found like this:

var everyone = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
var fileSecurity = File.GetAccessControl(path);
var acl = fileSecurity.GetAccessRules(true, true, typeof(SecurityIdentifier));

The first two boolean parameters for GetAccessRules define whether to fetch explicitly set access rights and inherited access rights respectively.

It's then possible to loop through these ACL's and find the specific rule needed. In my case I needed "Read access for Everyone" to be on the file:

foreach(FileSystemAccessRule rule in acl)
{
    if (rule.IdentityReference.Value == everyone.Value
        && rule.AccessControlType == AccessControlType.Allow
        && (rule.FileSystemRights & FileSystemRights.Read) == FileSystemRights.Read)
    {
        return true;
    }
}

Note the following: (rule.FileSystemRights & FileSystemRights.Read) == FileSystemRights.Read

This is needed because the rule's FileSystemRights is a combination of rights, but we only want to see the Read access right, so we mask the others using a bitwise AND.

Conclusion

Getting and setting access rights in windows is a bit more involved than you may expect.

Note that this only works on Windows with the .NET Framework. These API's are not supported in .NET Core.