将SDDL转换为.NET中的可读文本

时间:2011-10-11 09:43:53

标签: c# .net

有没有一种方法可以将SDDL权限代码转换为.NET中的可读文本?

例如,将GR转换为Generic Read等。

由于

2 个答案:

答案 0 :(得分:15)

下面是我将Parse SDDL放在一起并生成Human Readable输出的类:

class SDDLParser
{
    static private Dictionary<string, string> ACE_Types = null;
    static private Dictionary<string, string> ACE_Flags = null;
    static private Dictionary<string, string> Permissions = null;
    static private Dictionary<string, string> Trustee = null;

    private static void Initialize()
    {
        ACE_Types = new Dictionary<string, string>();
        ACE_Flags = new Dictionary<string, string>();
        Permissions = new Dictionary<string, string>();
        Trustee = new Dictionary<string, string>();
        #region Add ACE_Types
        ACE_Types.Add("A", "Access Allowed");
        ACE_Types.Add("D", "Access Denied");
        ACE_Types.Add("OA", "Object Access Allowed");
        ACE_Types.Add("OD", "Object Access Denied");
        ACE_Types.Add("AU", "System Audit");
        ACE_Types.Add("AL", "System Alarm");
        ACE_Types.Add("OU", "Object System Audit");
        ACE_Types.Add("OL", "Object System Alarm");
        #endregion
        #region Add ACE_Flags
        ACE_Flags.Add("CI", "Container Inherit");
        ACE_Flags.Add("OI", "Object Inherit");
        ACE_Flags.Add("NP", "No Propagate");
        ACE_Flags.Add("IO", "Inheritance Only");
        ACE_Flags.Add("ID", "Inherited");
        ACE_Flags.Add("SA", "Successful Access Audit");
        ACE_Flags.Add("FA", "Failed Access Audit");
        #endregion
        #region Add Permissions
        #region Generic Access Rights
        Permissions.Add("GA", "Generic All");
        Permissions.Add("GR", "Generic Read");
        Permissions.Add("GW", "Generic Write");
        Permissions.Add("GX", "Generic Execute");
        #endregion
        #region Directory Access Rights
        Permissions.Add("RC", "Read Permissions");
        Permissions.Add("SD", "Delete");
        Permissions.Add("WD", "Modify Permissions");
        Permissions.Add("WO", "Modify Owner");
        Permissions.Add("RP", "Read All Properties");
        Permissions.Add("WP", "Write All Properties");
        Permissions.Add("CC", "Create All Child Objects");
        Permissions.Add("DC", "Delete All Child Objects");
        Permissions.Add("LC", "List Contents");
        Permissions.Add("SW", "All Validated Writes");
        Permissions.Add("LO", "List Object");
        Permissions.Add("DT", "Delete Subtree");
        Permissions.Add("CR", "All Extended Rights");
        #endregion
        #region File Access Rights
        Permissions.Add("FA", "File All Access");
        Permissions.Add("FR", "File Generic Read");
        Permissions.Add("FW", "File Generic Write");
        Permissions.Add("FX", "File Generic Execute");
        #endregion
        #region Registry Key Access Rights
        Permissions.Add("KA", "Key All Access");
        Permissions.Add("KR", "Key Read");
        Permissions.Add("KW", "Key Write");
        Permissions.Add("KX", "Key Execute");
        #endregion
        #endregion
        #region Add Trustee's
        Trustee.Add("AO", "Account Operators");
        Trustee.Add("RU", "Alias to allow previous Windows 2000");
        Trustee.Add("AN", "Anonymous Logon");
        Trustee.Add("AU", "Authenticated Users");
        Trustee.Add("BA", "Built-in Administrators");
        Trustee.Add("BG", "Built in Guests");
        Trustee.Add("BO", "Backup Operators");
        Trustee.Add("BU", "Built-in Users");
        Trustee.Add("CA", "Certificate Server Administrators");
        Trustee.Add("CG", "Creator Group");
        Trustee.Add("CO", "Creator Owner");
        Trustee.Add("DA", "Domain Administrators");
        Trustee.Add("DC", "Domain Computers");
        Trustee.Add("DD", "Domain Controllers");
        Trustee.Add("DG", "Domain Guests");
        Trustee.Add("DU", "Domain Users");
        Trustee.Add("EA", "Enterprise Administrators");
        Trustee.Add("ED", "Enterprise Domain Controllers");
        Trustee.Add("WD", "Everyone");
        Trustee.Add("PA", "Group Policy Administrators");
        Trustee.Add("IU", "Interactively logged-on user");
        Trustee.Add("LA", "Local Administrator");
        Trustee.Add("LG", "Local Guest");
        Trustee.Add("LS", "Local Service Account");
        Trustee.Add("SY", "Local System");
        Trustee.Add("NU", "Network Logon User");
        Trustee.Add("NO", "Network Configuration Operators");
        Trustee.Add("NS", "Network Service Account");
        Trustee.Add("PO", "Printer Operators");
        Trustee.Add("PS", "Self");
        Trustee.Add("PU", "Power Users");
        Trustee.Add("RS", "RAS Servers group");
        Trustee.Add("RD", "Terminal Server Users");
        Trustee.Add("RE", "Replicator");
        Trustee.Add("RC", "Restricted Code");
        Trustee.Add("SA", "Schema Administrators");
        Trustee.Add("SO", "Server Operators");
        Trustee.Add("SU", "Service Logon User");
        #endregion
    }

    private static string friendlyTrusteeName(string trustee)
    {
        if (Trustee.Keys.Contains(trustee))
        {
            return Trustee[trustee];
        }
        else
        {
            try
            {
                System.Security.Principal.SecurityIdentifier sid = new System.Security.Principal.SecurityIdentifier(trustee);
                return sid.Translate(typeof(System.Security.Principal.NTAccount)).ToString();
            }
            catch (Exception)
            {
                return trustee;
            }
        }
    }

    private static string doParse(string subSDDL, string Separator, string Separator2)
    {
        string retval = "";
        char type = subSDDL.ToCharArray()[0];
        if (type == 'O')
        {
            string owner = subSDDL.Substring(2);
            return "Owner: " + friendlyTrusteeName(owner) + Separator;
        }
        else if (type == 'G')
        {
            string group = subSDDL.Substring(2);
            return "Group: " + friendlyTrusteeName(group) + Separator;
        }
        else if ((type == 'D') || (type == 'S'))
        {
            if (type == 'D')
            {
                retval += "DACL" + Separator;
            }
            else
            {
                retval += "SACL" + Separator;
            }
            string[] sections = subSDDL.Split('(');
            for (int count = 1; count < sections.Length; count++)
            {
                retval += "# " + count.ToString() + " of " + (sections.Length - 1).ToString() + Separator;
                string[] parts = sections[count].TrimEnd(')').Split(';');
                retval += "";
                if (ACE_Types.Keys.Contains(parts[0]))
                {
                    retval += Separator2 + "Type: " + ACE_Types[parts[0]] + Separator;
                }
                if (ACE_Flags.Keys.Contains(parts[1]))
                {
                    retval += Separator2 + "Inheritance: " + ACE_Flags[parts[1]] + Separator;
                }
                for (int count2 = 0; count2 < parts[2].Length; count2 += 2)
                {
                    string perm = parts[2].Substring(count2, 2);
                    if (Permissions.Keys.Contains(perm))
                    {
                        if (count2 == 0)
                        {
                            retval += Separator2 + "Permissions: " + Permissions[perm];
                        }
                        else
                        {
                            retval += "|" + Permissions[perm];
                        }
                    }
                }
                retval += Separator;
                retval += Separator2 + "Trustee: " + friendlyTrusteeName(parts[5]) + Separator;
            }
        }
        return retval;
    }

    public static string Parse(string SDDL)
    {
        return Parse(SDDL, "\r\n", "\t");
    }

    public static string Parse(string SDDL, string Separator, string Separator2)
    {
        string retval = "";
        if (ACE_Types == null)
        {
            Initialize();
        }
        int startindex = 0;
        int nextindex = 0;
        int first = 0;
        string section;
        while (true)
        {
            first = SDDL.IndexOf(':', nextindex) - 1;
            startindex = nextindex;
            if (first < 0)
            {
                break;
            }
            if (first != 0)
            {
                section = SDDL.Substring(startindex - 2, first - startindex + 2);
                retval += doParse(section, Separator, Separator2);
            }
            nextindex = first + 2;
        }
        section = SDDL.Substring(startindex - 2);
        retval += doParse(section, Separator, Separator2);
        return retval;
    }
}

您可以自由使用此代码,并根据您的需要进行调整。

答案 1 :(得分:1)

仅仅因为我之前还需要一个类似的功能,并且接受的答案(虽然优秀)打破了不能用双字符串表示的权限,但我敲了一个类似的人类可读解析器。

由于权限位依赖于它们应用的对象,因此必须传递字符串和权限位的合适Flags枚举。在大多数情况下,这些是在System.Security.AccessControl中预定义的,但是,对于更多深奥的对象(如终端服务会话),可能需要手动定义枚举。

(类型参数和枚举hackery很讨厌 - 当大多数常见的查询以枚举形式存在时,我只是不想将另一个查询传递给该方法。)< / p>

总之...

void Main()
{
    var sddl = "O:SYG:SYD:(A;CI;0xf03bf;;;SY)(A;;CCLO;;;LS)(A;;CCLO;;;NS)(A;;0xf03bf;;;BA)(A;;CC;;;IU)S:NO_ACCESS_CONTROL";

    SddlDecoder.DecodeString<FileSystemRights>(sddl).Dump("FileSystem");
    SddlDecoder.DecodeString<RegistryRights>(sddl).Dump("Registry");
    SddlDecoder.DecodeString<SemaphoreRights>(sddl).Dump("Semaphore");
}

// Define other methods and classes here
public static class SddlDecoder
{
    private static readonly ConcurrentDictionary<Type, Dictionary<uint, string>> _rights
        = new ConcurrentDictionary<Type, Dictionary<uint, string>>();

    public static string DecodeString<TRightsEnum>(string sddl) where TRightsEnum : struct
    {
        var rightsEnumType = typeof(TRightsEnum);
        if (!rightsEnumType.IsEnum ||
            Marshal.SizeOf(Enum.GetUnderlyingType(rightsEnumType)) != 4 ||
            !rightsEnumType.GetCustomAttributes(typeof(FlagsAttribute), true).Any())
        {
            throw new ArgumentException("TRightsEnum must be a 32-bit integer System.Enum with Flags attribute", "TRightsEnum");
        }
        else if (string.IsNullOrWhiteSpace(sddl))
            throw new ArgumentNullException("sddl");

        var descriptor = new RawSecurityDescriptor(sddl);

        var rights = _rights.GetOrAdd(rightsEnumType, 
                                      t => Enum.GetValues(rightsEnumType)
                                               .Cast<uint>()
                                               .Where(n => n != 0 && (n & (n - 1)) == 0)
                                               .Distinct()
                                               .OrderBy(n => n)
                                               .Select(v => new { v, n = Enum.GetName(rightsEnumType, v) })
                                               .ToDictionary(x => x.v, x => x.n));

        var builder = new StringBuilder();

        builder.Append("Owner: ").AppendLine(SidToAccountName(descriptor.Owner));
        builder.Append("Group: ").AppendLine(SidToAccountName(descriptor.Group));

        if (descriptor.SystemAcl != null)
        {
            builder.AppendLine("System ACL:");
            DecodeAclEntries(builder, descriptor.SystemAcl, rights);
        }

        if (descriptor.DiscretionaryAcl != null)
        {
            builder.AppendLine("Discretionary ACL:");
            DecodeAclEntries(builder, descriptor.DiscretionaryAcl, rights);
        }

        return builder.ToString();
    }

    private static string SidToAccountName(SecurityIdentifier sid)
    {
        return (sid.IsValidTargetType(typeof(NTAccount)))
             ? ((NTAccount)sid.Translate(typeof(NTAccount))).Value
             : sid.Value;
    }

    private static void DecodeAclEntries(StringBuilder builder, RawAcl acl, Dictionary<uint, string> rights)
    {
        var counter = 0;
        foreach (var ace in acl)
        {
            builder.Append("  #")
                   .Append(++counter)
                   .Append(": ");

            var knownAce = ace as KnownAce;
            if (knownAce != null)
            {
                builder.Append(knownAce.AceType > AceType.MaxDefinedAceType
                                ? "Custom Access"
                                : knownAce.AceType.ToString())
                       .Append(" for ")
                       .Append(SidToAccountName(knownAce.SecurityIdentifier));

                if (knownAce.AceFlags != AceFlags.None)
                {
                    builder.Append(" (")
                           .Append(knownAce.AceFlags)
                           .Append(')');
                }

                builder.AppendLine();

                var mask = unchecked((uint)knownAce.AccessMask);

                foreach (var r in rights.Keys)
                {
                    if ((mask & r) == r)
                    {
                        builder.Append("    - ")
                               .AppendLine(rights[r]);
                    }
                }
            }
            else builder.AppendLine("Unknown ACE");
        }
    }
}