FlashPatcher/FlashPatcher/TaskService/Native/AccessControlExtension.cs

89 lines
3.3 KiB
C#

using System.Linq;
namespace System.Security.AccessControl
{
/// <summary>Extensions for classes in the System.Security.AccessControl namespace.</summary>
public static class AccessControlExtension
{
/// <summary>Canonicalizes the specified Access Control List.</summary>
/// <param name="acl">The Access Control List.</param>
public static void Canonicalize(this RawAcl acl)
{
if (acl == null) throw new ArgumentNullException(nameof(acl));
// Extract aces to list
var aces = new Collections.Generic.List<GenericAce>(acl.Cast<GenericAce>());
// Sort aces based on canonical order
aces.Sort((a, b) => Collections.Generic.Comparer<byte>.Default.Compare(GetComparisonValue(a), GetComparisonValue(b)));
// Add sorted aces back to ACL
while (acl.Count > 0) acl.RemoveAce(0);
var aceIndex = 0;
aces.ForEach(ace => acl.InsertAce(aceIndex++, ace));
}
/// <summary>Sort ACEs according to canonical form for this <see cref="ObjectSecurity"/>.</summary>
/// <param name="objectSecurity">The object security whose DiscretionaryAcl will be made canonical.</param>
public static void CanonicalizeAccessRules(this ObjectSecurity objectSecurity)
{
if (objectSecurity == null) throw new ArgumentNullException(nameof(objectSecurity));
if (objectSecurity.AreAccessRulesCanonical) return;
// Get raw SD from objectSecurity and canonicalize DACL
var sd = new RawSecurityDescriptor(objectSecurity.GetSecurityDescriptorBinaryForm(), 0);
sd.DiscretionaryAcl.Canonicalize();
// Convert SD back into objectSecurity
objectSecurity.SetSecurityDescriptorBinaryForm(sd.GetBinaryForm());
}
/// <summary>Returns an array of byte values that represents the information contained in this <see cref="GenericSecurityDescriptor"/> object.</summary>
/// <param name="sd">The <see cref="GenericSecurityDescriptor"/> object.</param>
/// <returns>The byte array into which the contents of the <see cref="GenericSecurityDescriptor"/> is marshaled.</returns>
public static byte[] GetBinaryForm(this GenericSecurityDescriptor sd)
{
if (sd == null) throw new ArgumentNullException(nameof(sd));
var bin = new byte[sd.BinaryLength];
sd.GetBinaryForm(bin, 0);
return bin;
}
// A canonical ACL must have ACES sorted according to the following order:
// 1. Access-denied on the object
// 2. Access-denied on a child or property
// 3. Access-allowed on the object
// 4. Access-allowed on a child or property
// 5. All inherited ACEs
private static byte GetComparisonValue(GenericAce ace)
{
if ((ace.AceFlags & AceFlags.Inherited) != 0)
return 5;
switch (ace.AceType)
{
case AceType.AccessDenied:
case AceType.AccessDeniedCallback:
case AceType.SystemAudit:
case AceType.SystemAlarm:
case AceType.SystemAuditCallback:
case AceType.SystemAlarmCallback:
return 0;
case AceType.AccessDeniedObject:
case AceType.AccessDeniedCallbackObject:
case AceType.SystemAuditObject:
case AceType.SystemAlarmObject:
case AceType.SystemAuditCallbackObject:
case AceType.SystemAlarmCallbackObject:
return 1;
case AceType.AccessAllowed:
case AceType.AccessAllowedCallback:
return 2;
case AceType.AccessAllowedObject:
case AceType.AccessAllowedCallbackObject:
return 3;
default:
return 4;
}
}
}
}