/// <summary> /// Computes effective access rights upon acquiring the necessary security information such as Share's security, /// Central Policy and Resource's security as maybe applicable. /// </summary> public void Evaluate() { using (TokenPrivilege seSecurityPrivilege = new TokenPrivilege(TokenPrivilege.Security)) { try { // // SeSecurityPrivilege is required for querying the Central Policy ID (Scope information) from the // file's SD // seSecurityPrivilege.Enable(); var securityObjects = new Dictionary <string, FileSecurityObject>(); // // First include the Share's SD if available. If the share denies a permission, anything else that // denies a permission is of lesser consequence. // if (shareSD != null) { securityObjects.Add("Share", new FileSecurityObject(shareSD)); } SecurityIdentifier capId = null; { RawSecurityDescriptor scopeSD = GetFileSecInfoSD(handle, NativeMethods.SecurityInformationClass.Scope); if (scopeSD != null) { if (scopeSD.SystemAcl != null) { foreach (GenericAce ace in scopeSD.SystemAcl) { // // Scoped Policy ID ACE not yet part of System.Security.AccessControl.AceType // // Since SYSTEM_SCOPED_POLICY_ID_ACE essentially has a SID which is the identifier // for a Central Policy, extract it explicitly. // byte[] rawAce = new byte[ace.BinaryLength]; ace.GetBinaryForm(rawAce, 0); if ((ace.AceFlags & AceFlags.InheritOnly) == 0) { long sidOffset = (long)Marshal.OffsetOf( typeof(NativeMethods.SYSTEM_SCOPED_POLICY_ID_ACE), "SidStart"); if (sidOffset < ace.BinaryLength) { capId = new SecurityIdentifier(rawAce, (int)sidOffset); // // The first Central Policy is the only one honored when there are multiple // in a Security Descriptor. Ignore everything else. // break; } } } } } } // // Obtain file SD // RawSecurityDescriptor fileSD = GetFileSecInfoSD( handle, NativeMethods.SecurityInformationClass.Owner | NativeMethods.SecurityInformationClass.Group | NativeMethods.SecurityInformationClass.Dacl | NativeMethods.SecurityInformationClass.Label | NativeMethods.SecurityInformationClass.Attribute); if (capId != null) { var availableCaps = new AvailableCentralPolicies(targetMachine); Dictionary <string, CentralAccessRule> CARs = availableCaps.FetchCentralAccessRules(capId); if (CARs == null || CARs.Count == 0) { // // If the Central Policy or any of its Central Access Rules could not be retrieved, fall // back to just the granularity of Central Policy. For this, use the file's SD with the // CAP ID. // securityObjects.Add("Central Policy", new FileSecurityObject( GetFileSecInfoSD(handle, NativeMethods.SecurityInformationClass.Owner | NativeMethods.SecurityInformationClass.Group | NativeMethods.SecurityInformationClass.Label | NativeMethods.SecurityInformationClass.Attribute | NativeMethods.SecurityInformationClass.Scope))); } else { // // The merged security descriptor for each Central Access Rule is generated as follows: // Owner + Group + SACL (all from resource's SD) + DACL from Central Access Rule // // If the AppliesTo predicate is present, then we do the following: // Owned + Group + SACL (all from resource's SD) // + A fabricated DACL with an allowed callback ACE containingn the selected user // principal and the AppliesTo predicate appended. // foreach (var rule in CARs) { var sd = new RawSecurityDescriptor(fileSD.ControlFlags, fileSD.Owner, fileSD.Group, fileSD.SystemAcl, rule.Value.EffectivePolicy.DiscretionaryAcl); if (!string.IsNullOrEmpty(rule.Value.AppliesToCondition)) { string appliesToSDDL = "D:(XA;;FR;;;" + userSid.ToString() + ";" + rule.Value.AppliesToCondition + ")"; var appliesToSD = new RawSecurityDescriptor( fileSD.ControlFlags, fileSD.Owner, fileSD.Group, fileSD.SystemAcl, (new RawSecurityDescriptor(appliesToSDDL)).DiscretionaryAcl); securityObjects.Add(rule.Key, new FileSecurityObject(sd, appliesToSD)); } else { securityObjects.Add(rule.Key, new FileSecurityObject(sd)); } } } } securityObjects.Add("File permissions", new FileSecurityObject(fileSD)); results = ComputeEffectiveAccessResult(targetMachine, securityObjects); } finally { seSecurityPrivilege.Revert(); } } }
/// <summary> /// Computes effective access rights upon acquiring the necessary security information such as Share's security, /// Central Policy and Resource's security as maybe applicable. /// </summary> public void Evaluate() { using (TokenPrivilege seSecurityPrivilege = new TokenPrivilege(TokenPrivilege.Security)) { try { // // SeSecurityPrivilege is required for querying the Central Policy ID (Scope information) from the // file's SD // seSecurityPrivilege.Enable(); var securityObjects = new Dictionary<string, FileSecurityObject>(); // // First include the Share's SD if available. If the share denies a permission, anything else that // denies a permission is of lesser consequence. // if (shareSD != null) { securityObjects.Add("Share", new FileSecurityObject(shareSD)); } SecurityIdentifier capId = null; { RawSecurityDescriptor scopeSD = GetFileSecInfoSD(handle, NativeMethods.SecurityInformationClass.Scope); if (scopeSD != null) { if (scopeSD.SystemAcl != null) { foreach (GenericAce ace in scopeSD.SystemAcl) { // // Scoped Policy ID ACE not yet part of System.Security.AccessControl.AceType // // Since SYSTEM_SCOPED_POLICY_ID_ACE essentially has a SID which is the identifier // for a Central Policy, extract it explicitly. // byte[] rawAce = new byte[ace.BinaryLength]; ace.GetBinaryForm(rawAce, 0); if ((ace.AceFlags & AceFlags.InheritOnly) == 0) { long sidOffset = (long)Marshal.OffsetOf( typeof(NativeMethods.SYSTEM_SCOPED_POLICY_ID_ACE), "SidStart"); if (sidOffset < ace.BinaryLength) { capId = new SecurityIdentifier(rawAce, (int)sidOffset); // // The first Central Policy is the only one honored when there are multiple // in a Security Descriptor. Ignore everything else. // break; } } } } } } // // Obtain file SD // RawSecurityDescriptor fileSD = GetFileSecInfoSD( handle, NativeMethods.SecurityInformationClass.Owner | NativeMethods.SecurityInformationClass.Group | NativeMethods.SecurityInformationClass.Dacl | NativeMethods.SecurityInformationClass.Label | NativeMethods.SecurityInformationClass.Attribute); if (capId != null) { var availableCaps = new AvailableCentralPolicies(targetMachine); Dictionary<string, CentralAccessRule> CARs = availableCaps.FetchCentralAccessRules(capId); if (CARs == null || CARs.Count == 0) { // // If the Central Policy or any of its Central Access Rules could not be retrieved, fall // back to just the granularity of Central Policy. For this, use the file's SD with the // CAP ID. // securityObjects.Add("Central Policy", new FileSecurityObject( GetFileSecInfoSD(handle, NativeMethods.SecurityInformationClass.Owner | NativeMethods.SecurityInformationClass.Group | NativeMethods.SecurityInformationClass.Label | NativeMethods.SecurityInformationClass.Attribute | NativeMethods.SecurityInformationClass.Scope))); } else { // // The merged security descriptor for each Central Access Rule is generated as follows: // Owner + Group + SACL (all from resource's SD) + DACL from Central Access Rule // // If the AppliesTo predicate is present, then we do the following: // Owned + Group + SACL (all from resource's SD) // + A fabricated DACL with an allowed callback ACE containingn the selected user // principal and the AppliesTo predicate appended. // foreach (var rule in CARs) { var sd = new RawSecurityDescriptor(fileSD.ControlFlags, fileSD.Owner, fileSD.Group, fileSD.SystemAcl, rule.Value.EffectivePolicy.DiscretionaryAcl); if (!string.IsNullOrEmpty(rule.Value.AppliesToCondition)) { string appliesToSDDL = "D:(XA;;FR;;;" + userSid.ToString() + ";" + rule.Value.AppliesToCondition + ")"; var appliesToSD = new RawSecurityDescriptor( fileSD.ControlFlags, fileSD.Owner, fileSD.Group, fileSD.SystemAcl, (new RawSecurityDescriptor(appliesToSDDL)).DiscretionaryAcl); securityObjects.Add(rule.Key, new FileSecurityObject(sd, appliesToSD)); } else { securityObjects.Add(rule.Key, new FileSecurityObject(sd)); } } } } securityObjects.Add("File permissions", new FileSecurityObject(fileSD)); results = ComputeEffectiveAccessResult(targetMachine, securityObjects); } finally { seSecurityPrivilege.Revert(); } } }