compare windows file (or folder) permissions

半腔热情 提交于 2020-01-07 05:03:28

问题


I occasionally migrate some website from one web server to another.

After copying all files from the old server to the new server, it takes me quite some time to get (re)acquainted with which folders or files need to be writable by IIS. (Sounds familiar, by the way ? :) )

I have written a WinForms application that allows me to select a starting directory. The application should (recursively) compare if the security permissions of each file/directory are equal to that of its parent directory.

I want to use this application on the old server to scan for directories with different permissions.

Example: C:\MySites\Uploads does not have the same permissions set as its parent directory. (This folder was writable for the IIS user 'IUSR', while its parent folder was only readable.)

The application is almost complete in the sense that I manage to traverse all directories and files. I just need to compare their permissions!

Can you please help? Here is an excerpt of where I need your help.

string results = "";

string parentFolderPath = "c:\\someParentDir";
string childItemPath = "c:\\someParentDir\\SomeChildDir.ext";

DirectorySecurity parentFolderAccessControl = Directory.GetAccessControl(parentFolderPath);
DirectorySecurity childItemAccessControl = Directory.GetAccessControl(childItemPath);

if (!parentFolderAccessControl.Equals(childItemAccessControl)) // <-- D'oh here
{
    results += childItemPath + " does not have the same permissions set as its parent directory.\n";
}

The if is always true, because the DirectorySecurities are never equal. (I understand why that is: reference to different memory allocations ... blah blah.) But what would be the best way to compare the DirectorySecurities?


回答1:


This actually became much more complex while I was working it out, because Windows rights can:

  • split up into Allow and Deny
  • Fragmented over multiple entries (multiple entries per user per Allow/Deny)

Eventually, this is what I made out of it:

private bool compareAccessControls(
    DirectorySecurity parentAccessControl,
    DirectorySecurity childAccessControl,
    out Dictionary<IdentityReference, FileSystemRights> accessAllowRulesGainedByChild,
    out Dictionary<IdentityReference, FileSystemRights> accessDenyRulesGainedByChild,
    out Dictionary<IdentityReference, FileSystemRights> accessAllowRulesGainedByParent,
    out Dictionary<IdentityReference, FileSystemRights> accessDenyRulesGainedByParent
)
{
    // combine parent access rules

    Dictionary<IdentityReference, FileSystemRights> combinedParentAccessAllowRules = new Dictionary<IdentityReference, FileSystemRights>();
    Dictionary<IdentityReference, FileSystemRights> combinedParentAccessDenyRules = new Dictionary<IdentityReference, FileSystemRights>();
    foreach (FileSystemAccessRule parentAccessRule in parentAccessControl.GetAccessRules(true, true, typeof(NTAccount)))
    {
        if (parentAccessRule.AccessControlType == AccessControlType.Allow)
            if (combinedParentAccessAllowRules.ContainsKey(parentAccessRule.IdentityReference))
                combinedParentAccessAllowRules[parentAccessRule.IdentityReference] = combinedParentAccessAllowRules[parentAccessRule.IdentityReference] | parentAccessRule.FileSystemRights;
            else
                combinedParentAccessAllowRules.Add(parentAccessRule.IdentityReference, parentAccessRule.FileSystemRights);
        else
            if (combinedParentAccessDenyRules.ContainsKey(parentAccessRule.IdentityReference))
                combinedParentAccessDenyRules[parentAccessRule.IdentityReference] = combinedParentAccessDenyRules[parentAccessRule.IdentityReference] | parentAccessRule.FileSystemRights;
            else
                combinedParentAccessDenyRules.Add(parentAccessRule.IdentityReference, parentAccessRule.FileSystemRights);
    }

    // combine child access rules

    Dictionary<IdentityReference, FileSystemRights> combinedChildAccessAllowRules = new Dictionary<IdentityReference, FileSystemRights>();
    Dictionary<IdentityReference, FileSystemRights> combinedChildAccessDenyRules = new Dictionary<IdentityReference, FileSystemRights>();
    foreach (FileSystemAccessRule childAccessRule in childAccessControl.GetAccessRules(true, true, typeof(NTAccount)))
    {
        if (childAccessRule.AccessControlType == AccessControlType.Allow)
            if (combinedChildAccessAllowRules.ContainsKey(childAccessRule.IdentityReference))
                combinedChildAccessAllowRules[childAccessRule.IdentityReference] = combinedChildAccessAllowRules[childAccessRule.IdentityReference] | childAccessRule.FileSystemRights;
            else
                combinedChildAccessAllowRules.Add(childAccessRule.IdentityReference, childAccessRule.FileSystemRights);
        else
            if (combinedChildAccessDenyRules.ContainsKey(childAccessRule.IdentityReference))
                combinedChildAccessDenyRules[childAccessRule.IdentityReference] = combinedChildAccessDenyRules[childAccessRule.IdentityReference] | childAccessRule.FileSystemRights;
            else
                combinedChildAccessDenyRules.Add(childAccessRule.IdentityReference, childAccessRule.FileSystemRights);
    }

    // compare combined rules

    accessAllowRulesGainedByChild = new Dictionary<IdentityReference, FileSystemRights>();
    foreach (KeyValuePair<IdentityReference, FileSystemRights> combinedChildAccessAllowRule in combinedChildAccessAllowRules)
    {
        if (combinedParentAccessAllowRules.ContainsKey(combinedChildAccessAllowRule.Key))
        {
            FileSystemRights accessAllowRuleGainedByChild = combinedChildAccessAllowRule.Value & ~combinedParentAccessAllowRules[combinedChildAccessAllowRule.Key];
            if (accessAllowRuleGainedByChild != default(FileSystemRights))
                accessAllowRulesGainedByChild.Add(combinedChildAccessAllowRule.Key, accessAllowRuleGainedByChild);
        }
        else
        {
            accessAllowRulesGainedByChild.Add(combinedChildAccessAllowRule.Key, combinedChildAccessAllowRule.Value);
        }
    }

    accessDenyRulesGainedByChild = new Dictionary<IdentityReference, FileSystemRights>();
    foreach (KeyValuePair<IdentityReference, FileSystemRights> combinedChildAccessDenyRule in combinedChildAccessDenyRules)
    {
        if (combinedParentAccessDenyRules.ContainsKey(combinedChildAccessDenyRule.Key))
        {
            FileSystemRights accessDenyRuleGainedByChild = combinedChildAccessDenyRule.Value & ~combinedParentAccessDenyRules[combinedChildAccessDenyRule.Key];
            if (accessDenyRuleGainedByChild != default(FileSystemRights))
                accessDenyRulesGainedByChild.Add(combinedChildAccessDenyRule.Key, accessDenyRuleGainedByChild);
        }
        else
        {
            accessDenyRulesGainedByChild.Add(combinedChildAccessDenyRule.Key, combinedChildAccessDenyRule.Value);
        }
    }

    accessAllowRulesGainedByParent = new Dictionary<IdentityReference, FileSystemRights>();
    foreach (KeyValuePair<IdentityReference, FileSystemRights> combinedParentAccessAllowRule in combinedParentAccessAllowRules)
    {
        if (combinedChildAccessAllowRules.ContainsKey(combinedParentAccessAllowRule.Key))
        {
            FileSystemRights accessAllowRuleGainedByParent = combinedParentAccessAllowRule.Value & ~combinedChildAccessAllowRules[combinedParentAccessAllowRule.Key];
            if (accessAllowRuleGainedByParent != default(FileSystemRights))
                accessAllowRulesGainedByParent.Add(combinedParentAccessAllowRule.Key, accessAllowRuleGainedByParent);
        }
        else
        {
            accessAllowRulesGainedByParent.Add(combinedParentAccessAllowRule.Key, combinedParentAccessAllowRule.Value);
        }
    }

    accessDenyRulesGainedByParent = new Dictionary<IdentityReference, FileSystemRights>();
    foreach (KeyValuePair<IdentityReference, FileSystemRights> combinedParentAccessDenyRule in combinedParentAccessDenyRules)
    {
        if (combinedChildAccessDenyRules.ContainsKey(combinedParentAccessDenyRule.Key))
        {
            FileSystemRights accessDenyRuleGainedByParent = combinedParentAccessDenyRule.Value & ~combinedChildAccessDenyRules[combinedParentAccessDenyRule.Key];
            if (accessDenyRuleGainedByParent != default(FileSystemRights))
                accessDenyRulesGainedByParent.Add(combinedParentAccessDenyRule.Key, accessDenyRuleGainedByParent);
        }
        else
        {
            accessDenyRulesGainedByParent.Add(combinedParentAccessDenyRule.Key, combinedParentAccessDenyRule.Value);
        }
    }

    if (accessAllowRulesGainedByChild.Count > 0 || accessDenyRulesGainedByChild.Count > 0 || accessAllowRulesGainedByParent.Count > 0 || accessDenyRulesGainedByParent.Count > 0)
        return false;
    else
        return true;
}



回答2:


You cannot use Equals() since this method is inherited from Object. You need to find a identifying attribute on that DirectorySecurity class. I think String GetSecurityDescriptorSddlForm()

should do your job. You can invoke Equals() on that.

Edit: Well sorry, this method needs a parameter for invocation. Try finding another attribute on the DirectorySecurity which is better for comparison.

Edit2: I'm not familar with .NET Security Framework and Right-Management, but something like this should be your approach. You can do != resp: == on FileSystemAccessRule.FileSystemRights because that attribute is an enum (internally an int).

ArrayList notIdenticalList = new ArrayList(); 

        DirectorySecurity parentFolderAccessControl = Directory.GetAccessControl(null);
        DirectorySecurity childItemAccessControl = Directory.GetAccessControl(null);
        foreach (FileSystemAccessRule parentRule in parentFolderAccessControl.GetAccessRules(true, true, typeof(NTAccount)))
        {
            foreach (FileSystemAccessRule childRule in childItemAccessControl.GetAccessRules(true, true, typeof(NTAccount)))
            {
                if (parentRule.FileSystemRights != childRule.FileSystemRights)
                {
                    // add to not identical-list
                    notIdenticalList.Add(fileToAdd...);
                    break;
                }
            }
        }


来源:https://stackoverflow.com/questions/17029638/compare-windows-file-or-folder-permissions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!