答案 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");
}
}
}