Skip to content

Instantly share code, notes, and snippets.

@EmileSonneveld
Last active January 21, 2019 13:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save EmileSonneveld/3b3614d53f86be14110b93cb947951e7 to your computer and use it in GitHub Desktop.
Save EmileSonneveld/3b3614d53f86be14110b93cb947951e7 to your computer and use it in GitHub Desktop.
using System;
using System.Security;
using System.Security.AccessControl;
namespace GCAWeb.Utils
{
/// <span class="code-SummaryComment"><summary>
/// Configuring a Web site through a Web interface can be tricky.
/// If one is to read and write various files, it is useful to know
/// in advance if you have the authority to do so.
///
/// This class contains a simple answer to a
/// potentially complicated question
/// "Can I read this file or can I write to this file?"
///
/// Using the "rule of least privilege",
/// one must check not only is access granted but
/// is it denied at any point including a possibly recursive check of groups.
///
/// For this simple check, a look at the user and immediate groups are only checked.
///
/// This class could be expanded to identify if the applicable allow/deny rule
/// was explicit or inherited
///
/// </summary></span>
public class UserFileAccessRights
{
private readonly string _path;
private readonly System.Security.Principal.WindowsIdentity _principal;
private readonly bool _denyAppendData = false;
private readonly bool _denyChangePermissions = false;
private readonly bool _denyCreateDirectories = false;
private readonly bool _denyCreateFiles = false;
private readonly bool _denyDelete = false;
private readonly bool _denyDeleteSubdirectoriesAndFiles = false;
private readonly bool _denyExecuteFile = false;
private readonly bool _denyFullControl = false;
private readonly bool _denyListDirectory = false;
private readonly bool _denyModify = false;
private readonly bool _denyRead = false;
private readonly bool _denyReadAndExecute = false;
private readonly bool _denyReadAttributes = false;
private readonly bool _denyReadData = false;
private readonly bool _denyReadExtendedAttributes = false;
private readonly bool _denyReadPermissions = false;
private readonly bool _denySynchronize = false;
private readonly bool _denyTakeOwnership = false;
private readonly bool _denyTraverse = false;
private readonly bool _denyWrite = false;
private readonly bool _denyWriteAttributes = false;
private readonly bool _denyWriteData = false;
private readonly bool _denyWriteExtendedAttributes = false;
private readonly bool _allowAppendData = false;
private readonly bool _allowChangePermissions = false;
private readonly bool _allowCreateDirectories = false;
private readonly bool _allowCreateFiles = false;
private readonly bool _allowDelete = false;
private readonly bool _allowDeleteSubdirectoriesAndFiles = false;
private readonly bool _allowExecuteFile = false;
private readonly bool _allowFullControl = false;
private readonly bool _allowListDirectory = false;
private readonly bool _allowModify = false;
private readonly bool _allowRead = false;
private readonly bool _allowReadAndExecute = false;
private readonly bool _allowReadAttributes = false;
private readonly bool _allowReadData = false;
private readonly bool _allowReadExtendedAttributes = false;
private readonly bool _allowReadPermissions = false;
private readonly bool _allowSynchronize = false;
private readonly bool _allowTakeOwnership = false;
private readonly bool _allowTraverse = false;
private readonly bool _allowWrite = false;
private readonly bool _allowWriteAttributes = false;
private readonly bool _allowWriteData = false;
private readonly bool _allowWriteExtendedAttributes = false;
public bool canAppendData() { return !_denyAppendData && _allowAppendData; }
public bool canChangePermissions()
{ return !_denyChangePermissions && _allowChangePermissions; }
public bool canCreateDirectories()
{ return !_denyCreateDirectories && _allowCreateDirectories; }
public bool canCreateFiles() { return !_denyCreateFiles && _allowCreateFiles; }
public bool canDelete() { return !_denyDelete && _allowDelete; }
public bool canDeleteSubdirectoriesAndFiles()
{
return !_denyDeleteSubdirectoriesAndFiles &&
_allowDeleteSubdirectoriesAndFiles;
}
public bool canExecuteFile() { return !_denyExecuteFile && _allowExecuteFile; }
public bool canFullControl() { return !_denyFullControl && _allowFullControl; }
public bool canListDirectory()
{ return !_denyListDirectory && _allowListDirectory; }
public bool canModify() { return !_denyModify && _allowModify; }
public bool canRead() { return !_denyRead && _allowRead; }
public bool canReadAndExecute()
{ return !_denyReadAndExecute && _allowReadAndExecute; }
public bool canReadAttributes()
{ return !_denyReadAttributes && _allowReadAttributes; }
public bool canReadData() { return !_denyReadData && _allowReadData; }
public bool canReadExtendedAttributes()
{
return !_denyReadExtendedAttributes &&
_allowReadExtendedAttributes;
}
public bool canReadPermissions()
{ return !_denyReadPermissions && _allowReadPermissions; }
public bool canSynchronize() { return !_denySynchronize && _allowSynchronize; }
public bool canTakeOwnership()
{ return !_denyTakeOwnership && _allowTakeOwnership; }
public bool canTraverse() { return !_denyTraverse && _allowTraverse; }
public bool canWrite() { return !_denyWrite && _allowWrite; }
public bool canWriteAttributes()
{ return !_denyWriteAttributes && _allowWriteAttributes; }
public bool canWriteData() { return !_denyWriteData && _allowWriteData; }
public bool canWriteExtendedAttributes()
{
return !_denyWriteExtendedAttributes &&
_allowWriteExtendedAttributes;
}
/// <span class="code-SummaryComment"><summary>
/// Simple accessor
/// </summary></span>
/// <span class="code-SummaryComment"><returns></returns></span>
public System.Security.Principal.WindowsIdentity getWindowsIdentity()
{
return _principal;
}
/// <span class="code-SummaryComment"><summary>
/// Simple accessor
/// </summary></span>
/// <span class="code-SummaryComment"><returns></returns></span>
public String getPath()
{
return _path;
}
/// <span class="code-SummaryComment"><summary>
/// Convenience constructor assumes the current user
/// </summary></span>
/// <span class="code-SummaryComment"><param name="path"></param></span>
public UserFileAccessRights(string path) :
this(path, System.Security.Principal.WindowsIdentity.GetCurrent())
{ }
/// <span class="code-SummaryComment"><summary>
/// Supply the path to the file or directory and a user or group.
/// Access checks are done
/// during instantiation to ensure we always have a valid object
/// </summary></span>
/// <span class="code-SummaryComment"><param name="path"></param></span>
/// <span class="code-SummaryComment"><param name="principal"></param></span>
public UserFileAccessRights(string path,
System.Security.Principal.WindowsIdentity principal)
{
this._path = path;
this._principal = principal;
try
{
System.IO.FileInfo fi = new System.IO.FileInfo(_path);
AuthorizationRuleCollection acl = fi.GetAccessControl().GetAccessRules
(true, true, typeof(System.Security.Principal.SecurityIdentifier));
for (int i = 0; i < acl.Count; i++)
{
System.Security.AccessControl.FileSystemAccessRule rule =
(System.Security.AccessControl.FileSystemAccessRule)acl[i];
if (_principal.User.Equals(rule.IdentityReference))
{
if (System.Security.AccessControl.AccessControlType.Deny.Equals
(rule.AccessControlType))
{
if (contains(FileSystemRights.AppendData, rule))
_denyAppendData = true;
if (contains(FileSystemRights.ChangePermissions, rule))
_denyChangePermissions = true;
if (contains(FileSystemRights.CreateDirectories, rule))
_denyCreateDirectories = true;
if (contains(FileSystemRights.CreateFiles, rule))
_denyCreateFiles = true;
if (contains(FileSystemRights.Delete, rule))
_denyDelete = true;
if (contains(FileSystemRights.DeleteSubdirectoriesAndFiles,
rule)) _denyDeleteSubdirectoriesAndFiles = true;
if (contains(FileSystemRights.ExecuteFile, rule))
_denyExecuteFile = true;
if (contains(FileSystemRights.FullControl, rule))
_denyFullControl = true;
if (contains(FileSystemRights.ListDirectory, rule))
_denyListDirectory = true;
if (contains(FileSystemRights.Modify, rule))
_denyModify = true;
if (contains(FileSystemRights.Read, rule)) _denyRead = true;
if (contains(FileSystemRights.ReadAndExecute, rule))
_denyReadAndExecute = true;
if (contains(FileSystemRights.ReadAttributes, rule))
_denyReadAttributes = true;
if (contains(FileSystemRights.ReadData, rule))
_denyReadData = true;
if (contains(FileSystemRights.ReadExtendedAttributes, rule))
_denyReadExtendedAttributes = true;
if (contains(FileSystemRights.ReadPermissions, rule))
_denyReadPermissions = true;
if (contains(FileSystemRights.Synchronize, rule))
_denySynchronize = true;
if (contains(FileSystemRights.TakeOwnership, rule))
_denyTakeOwnership = true;
if (contains(FileSystemRights.Traverse, rule))
_denyTraverse = true;
if (contains(FileSystemRights.Write, rule)) _denyWrite = true;
if (contains(FileSystemRights.WriteAttributes, rule))
_denyWriteAttributes = true;
if (contains(FileSystemRights.WriteData, rule))
_denyWriteData = true;
if (contains(FileSystemRights.WriteExtendedAttributes, rule))
_denyWriteExtendedAttributes = true;
}
else if (System.Security.AccessControl.AccessControlType.
Allow.Equals(rule.AccessControlType))
{
if (contains(FileSystemRights.AppendData, rule))
_allowAppendData = true;
if (contains(FileSystemRights.ChangePermissions, rule))
_allowChangePermissions = true;
if (contains(FileSystemRights.CreateDirectories, rule))
_allowCreateDirectories = true;
if (contains(FileSystemRights.CreateFiles, rule))
_allowCreateFiles = true;
if (contains(FileSystemRights.Delete, rule))
_allowDelete = true;
if (contains(FileSystemRights.DeleteSubdirectoriesAndFiles,
rule)) _allowDeleteSubdirectoriesAndFiles = true;
if (contains(FileSystemRights.ExecuteFile, rule))
_allowExecuteFile = true;
if (contains(FileSystemRights.FullControl, rule))
_allowFullControl = true;
if (contains(FileSystemRights.ListDirectory, rule))
_allowListDirectory = true;
if (contains(FileSystemRights.Modify, rule))
_allowModify = true;
if (contains(FileSystemRights.Read, rule)) _allowRead = true;
if (contains(FileSystemRights.ReadAndExecute, rule))
_allowReadAndExecute = true;
if (contains(FileSystemRights.ReadAttributes, rule))
_allowReadAttributes = true;
if (contains(FileSystemRights.ReadData, rule))
_allowReadData = true;
if (contains(FileSystemRights.ReadExtendedAttributes, rule))
_allowReadExtendedAttributes = true;
if (contains(FileSystemRights.ReadPermissions, rule))
_allowReadPermissions = true;
if (contains(FileSystemRights.Synchronize, rule))
_allowSynchronize = true;
if (contains(FileSystemRights.TakeOwnership, rule))
_allowTakeOwnership = true;
if (contains(FileSystemRights.Traverse, rule))
_allowTraverse = true;
if (contains(FileSystemRights.Write, rule))
_allowWrite = true;
if (contains(FileSystemRights.WriteAttributes, rule))
_allowWriteAttributes = true;
if (contains(FileSystemRights.WriteData, rule))
_allowWriteData = true;
if (contains(FileSystemRights.WriteExtendedAttributes, rule))
_allowWriteExtendedAttributes = true;
}
}
}
System.Security.Principal.IdentityReferenceCollection groups = _principal.Groups;
for (int j = 0; j < groups.Count; j++)
{
for (int i = 0; i < acl.Count; i++)
{
System.Security.AccessControl.FileSystemAccessRule rule =
(System.Security.AccessControl.FileSystemAccessRule)acl[i];
if (groups[j].Equals(rule.IdentityReference))
{
if (System.Security.AccessControl.AccessControlType.
Deny.Equals(rule.AccessControlType))
{
if (contains(FileSystemRights.AppendData, rule))
_denyAppendData = true;
if (contains(FileSystemRights.ChangePermissions, rule))
_denyChangePermissions = true;
if (contains(FileSystemRights.CreateDirectories, rule))
_denyCreateDirectories = true;
if (contains(FileSystemRights.CreateFiles, rule))
_denyCreateFiles = true;
if (contains(FileSystemRights.Delete, rule))
_denyDelete = true;
if (contains(FileSystemRights.
DeleteSubdirectoriesAndFiles, rule))
_denyDeleteSubdirectoriesAndFiles = true;
if (contains(FileSystemRights.ExecuteFile, rule))
_denyExecuteFile = true;
if (contains(FileSystemRights.FullControl, rule))
_denyFullControl = true;
if (contains(FileSystemRights.ListDirectory, rule))
_denyListDirectory = true;
if (contains(FileSystemRights.Modify, rule))
_denyModify = true;
if (contains(FileSystemRights.Read, rule))
_denyRead = true;
if (contains(FileSystemRights.ReadAndExecute, rule))
_denyReadAndExecute = true;
if (contains(FileSystemRights.ReadAttributes, rule))
_denyReadAttributes = true;
if (contains(FileSystemRights.ReadData, rule))
_denyReadData = true;
if (contains(FileSystemRights.
ReadExtendedAttributes, rule))
_denyReadExtendedAttributes = true;
if (contains(FileSystemRights.ReadPermissions, rule))
_denyReadPermissions = true;
if (contains(FileSystemRights.Synchronize, rule))
_denySynchronize = true;
if (contains(FileSystemRights.TakeOwnership, rule))
_denyTakeOwnership = true;
if (contains(FileSystemRights.Traverse, rule))
_denyTraverse = true;
if (contains(FileSystemRights.Write, rule))
_denyWrite = true;
if (contains(FileSystemRights.WriteAttributes, rule))
_denyWriteAttributes = true;
if (contains(FileSystemRights.WriteData, rule))
_denyWriteData = true;
if (contains(FileSystemRights.
WriteExtendedAttributes, rule))
_denyWriteExtendedAttributes = true;
}
else if (System.Security.AccessControl.AccessControlType.
Allow.Equals(rule.AccessControlType))
{
if (contains(FileSystemRights.AppendData, rule))
_allowAppendData = true;
if (contains(FileSystemRights.ChangePermissions, rule))
_allowChangePermissions = true;
if (contains(FileSystemRights.CreateDirectories, rule))
_allowCreateDirectories = true;
if (contains(FileSystemRights.CreateFiles, rule))
_allowCreateFiles = true;
if (contains(FileSystemRights.Delete, rule))
_allowDelete = true;
if (contains(FileSystemRights.
DeleteSubdirectoriesAndFiles, rule))
_allowDeleteSubdirectoriesAndFiles = true;
if (contains(FileSystemRights.ExecuteFile, rule))
_allowExecuteFile = true;
if (contains(FileSystemRights.FullControl, rule))
_allowFullControl = true;
if (contains(FileSystemRights.ListDirectory, rule))
_allowListDirectory = true;
if (contains(FileSystemRights.Modify, rule))
_allowModify = true;
if (contains(FileSystemRights.Read, rule))
_allowRead = true;
if (contains(FileSystemRights.ReadAndExecute, rule))
_allowReadAndExecute = true;
if (contains(FileSystemRights.ReadAttributes, rule))
_allowReadAttributes = true;
if (contains(FileSystemRights.ReadData, rule))
_allowReadData = true;
if (contains(FileSystemRights.
ReadExtendedAttributes, rule))
_allowReadExtendedAttributes = true;
if (contains(FileSystemRights.ReadPermissions, rule))
_allowReadPermissions = true;
if (contains(FileSystemRights.Synchronize, rule))
_allowSynchronize = true;
if (contains(FileSystemRights.TakeOwnership, rule))
_allowTakeOwnership = true;
if (contains(FileSystemRights.Traverse, rule))
_allowTraverse = true;
if (contains(FileSystemRights.Write, rule))
_allowWrite = true;
if (contains(FileSystemRights.WriteAttributes, rule))
_allowWriteAttributes = true;
if (contains(FileSystemRights.WriteData, rule))
_allowWriteData = true;
if (contains(FileSystemRights.WriteExtendedAttributes,
rule)) _allowWriteExtendedAttributes = true;
}
}
}
}
}
catch (Exception e)
{
//Deal with IO exceptions if you want
throw e;
}
}
/// <span class="code-SummaryComment"><summary>
/// Simply displays all allowed rights
///
/// Useful if say you want to test for write access and find
/// it is false;
/// <xmp>
/// UserFileAccessRights rights = new UserFileAccessRights(txtLogPath.Text);
/// System.IO.FileInfo fi = new System.IO.FileInfo(txtLogPath.Text);
/// if (rights.canWrite() && rights.canRead()) {
/// lblLogMsg.Text = "R/W access";
/// } else {
/// if (rights.canWrite()) {
/// lblLogMsg.Text = "Only Write access";
/// } else if (rights.canRead()) {
/// lblLogMsg.Text = "Only Read access";
/// } else {
/// lblLogMsg.CssClass = "error";
/// lblLogMsg.Text = rights.ToString()
/// }
/// }
/// </xmp>
///
/// </summary></span>
/// <span class="code-SummaryComment"><returns></returns></span>
public override String ToString()
{
//string str = "";
System.Text.StringBuilder str = new System.Text.StringBuilder();
if (canAppendData())
{
if (str.Length > 0) str.Append(",");
str.Append("AppendData");
}
if (canChangePermissions())
{
if (str.Length > 0) str.Append(",");
str.Append("ChangePermissions");
}
if (canCreateDirectories())
{
if (str.Length > 0) str.Append(",");
str.Append("CreateDirectories");
}
if (canCreateFiles())
{
if (str.Length > 0) str.Append(",");
str.Append("CreateFiles");
}
if (canDelete())
{
if (str.Length > 0) str.Append(",");
str.Append("Delete");
}
if (canDeleteSubdirectoriesAndFiles())
{
if (str.Length > 0) str.Append(",");
str.Append("DeleteSubdirectoriesAndFiles");
}
if (canExecuteFile())
{
if (str.Length > 0) str.Append(",");
str.Append("ExecuteFile");
}
if (canFullControl())
{
if (str.Length > 0) str.Append(",");
str.Append("FullControl");
}
if (canListDirectory())
{
if (str.Length > 0) str.Append(",");
str.Append("ListDirectory");
}
if (canModify())
{
if (str.Length > 0) str.Append(",");
str.Append("Modify");
}
if (canRead())
{
if (str.Length > 0) str.Append(",");
str.Append("Read");
}
if (canReadAndExecute())
{
if (str.Length > 0) str.Append(",");
str.Append("ReadAndExecute");
}
if (canReadAttributes())
{
if (str.Length > 0) str.Append(",");
str.Append("ReadAttributes");
}
if (canReadData())
{
if (str.Length > 0) str.Append(",");
str.Append("ReadData");
}
if (canReadExtendedAttributes())
{
if (str.Length > 0) str.Append(",");
str.Append("ReadExtendedAttributes");
}
if (canReadPermissions())
{
if (str.Length > 0) str.Append(",");
str.Append("ReadPermissions");
}
if (canSynchronize())
{
if (str.Length > 0) str.Append(",");
str.Append("Synchronize");
}
if (canTakeOwnership())
{
if (str.Length > 0) str.Append(",");
str.Append("TakeOwnership");
}
if (canTraverse())
{
if (str.Length > 0) str.Append(",");
str.Append("Traverse");
}
if (canWrite())
{
if (str.Length > 0) str.Append(",");
str.Append("Write");
}
if (canWriteAttributes())
{
if (str.Length > 0) str.Append(",");
str.Append("WriteAttributes");
}
if (canWriteData())
{
if (str.Length > 0) str.Append(",");
str.Append("WriteData");
}
if (canWriteExtendedAttributes())
{
if (str.Length > 0) str.Append(",");
str.Append("WriteExtendedAttributes");
}
if (str.Length > 0)
str.Append("None");
return str.ToString();
}
/// <span class="code-SummaryComment"><summary>
/// Convenience method to test if the right exists within the given rights
/// </summary></span>
/// <span class="code-SummaryComment"><param name="right"></param></span>
/// <span class="code-SummaryComment"><param name="rule"></param></span>
/// <span class="code-SummaryComment"><returns></returns></span>
public bool contains(System.Security.AccessControl.FileSystemRights right,
System.Security.AccessControl.FileSystemAccessRule rule)
{
return (((int)right & (int)rule.FileSystemRights) == (int)right);
}
public static string FindFirstFailingPath(string path)
{
// Could use bisect to improve performance.
var chars = new char[] { '\\', '/' };
var segments = path.Split(chars);
var aggregate = "";
foreach (var segment in segments)
{
aggregate += segment + '\\';
try
{
var dummy = new UserFileAccessRights(aggregate);
}
catch (Exception e)
{
break; // Found failing path
}
}
return aggregate;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment