|
|
|
|
using Alphaleonis.Win32.Filesystem;
|
|
|
|
|
using System.Security.AccessControl;
|
|
|
|
|
|
|
|
|
|
namespace Security2
|
|
|
|
|
{
|
|
|
|
|
public partial class FileSystemAccessRule2
|
|
|
|
|
{
|
|
|
|
|
#region Properties
|
|
|
|
|
private FileSystemAccessRule fileSystemAccessRule;
|
|
|
|
|
private string fullName;
|
|
|
|
|
private bool inheritanceEnabled;
|
|
|
|
|
private string inheritedFrom;
|
|
|
|
|
|
|
|
|
|
public string Name { get { return System.IO.Path.GetFileName(fullName); } }
|
|
|
|
|
public string FullName { get { return fullName; } set { fullName = value; } }
|
|
|
|
|
public bool InheritanceEnabled { get { return inheritanceEnabled; } set { inheritanceEnabled = value; } }
|
|
|
|
|
public string InheritedFrom { get { return inheritedFrom; } set { inheritedFrom = value; } }
|
|
|
|
|
public AccessControlType AccessControlType { get { return fileSystemAccessRule.AccessControlType; } }
|
|
|
|
|
public FileSystemRights2 AccessRights { get { return (FileSystemRights2)fileSystemAccessRule.FileSystemRights; } }
|
|
|
|
|
public IdentityReference2 Account { get { return fileSystemAccessRule.IdentityReference; } }
|
|
|
|
|
public InheritanceFlags InheritanceFlags { get { return fileSystemAccessRule.InheritanceFlags; } }
|
|
|
|
|
public bool IsInherited { get { return fileSystemAccessRule.IsInherited; } }
|
|
|
|
|
public PropagationFlags PropagationFlags { get { return fileSystemAccessRule.PropagationFlags; } }
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
public FileSystemAccessRule2(FileSystemAccessRule fileSystemAccessRule)
|
|
|
|
|
{
|
|
|
|
|
this.fileSystemAccessRule = fileSystemAccessRule;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public FileSystemAccessRule2(FileSystemAccessRule fileSystemAccessRule, FileSystemInfo item)
|
|
|
|
|
{
|
|
|
|
|
this.fileSystemAccessRule = fileSystemAccessRule;
|
fix(security2): let the readers handle a descriptor that has no item
3.1 made a FileSystemSecurity2 without an item reachable from a .NET
caller (the conversions from FileSecurity and DirectorySecurity), but
six sibling call sites still dereferenced the item without checking it
first, so a caller who converted a FileSecurity or DirectorySecurity
and then read its entries, owner, inheritance, or effective access met
a NullReferenceException instead of a usable result.
GetFileSystemAccessRules and GetFileSystemAuditRules (the
FileSystemSecurity2 overload) now give each returned entry the same
null FullName that the descriptor itself reports; asking for the
source of an inherited entry (getInheritedFrom) needs the path of the
item, so it now throws one clear InvalidOperationException instead,
naming the reason, when the descriptor has none. FileSystemOwner and
FileSystemInheritanceInfo give a null FullName (and Name) the same
way; FileSystemOwner.ToString, which must never return null, gives an
empty string instead, since there is no other representation to fall
back to. The FileSystemAccessRule2(rule, item) constructor, which
EffectiveAccess.GetEffectiveAccess uses to build its result, now
accepts a null item the same way, so effective access can be
calculated for such a descriptor and the result names no path.
Every existing behavior for an item that is not null is unchanged;
only a .NET caller that reads such a descriptor can notice the
difference, and only for the better: a usable result or a clear error
instead of an unrelated NullReferenceException. Public signatures are
unchanged.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
1 week ago
|
|
|
// Null without an item, such as when EffectiveAccess.GetEffectiveAccess builds this from a
|
|
|
|
|
// FileSystemSecurity2 that has none, instead of a NullReferenceException.
|
|
|
|
|
this.fullName = item != null ? item.FullName : null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public FileSystemAccessRule2(FileSystemAccessRule fileSystemAccessRule, string path)
|
|
|
|
|
{
|
|
|
|
|
this.fileSystemAccessRule = fileSystemAccessRule;
|
|
|
|
|
this.fullName = path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static implicit operator FileSystemAccessRule(FileSystemAccessRule2 ace2)
|
|
|
|
|
{
|
|
|
|
|
return ace2.fileSystemAccessRule;
|
|
|
|
|
}
|
|
|
|
|
public static implicit operator FileSystemAccessRule2(FileSystemAccessRule ace)
|
|
|
|
|
{
|
|
|
|
|
return new FileSystemAccessRule2(ace);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Like the entries of .NET, two objects are equal when they wrap the same entry; an entry of .NET is never equal,
|
|
|
|
|
// so that equality is the same in both directions. A cast instead of "as" threw an InvalidCastException.
|
|
|
|
|
public override bool Equals(object obj)
|
|
|
|
|
{
|
fix: compare output objects and report InheritedFrom correctly
Equals of FileSystemAccessRule2, FileSystemAuditRule2, and
FileSystemSecurity2 cast its argument to the .NET type, which throws for
the wrapper types themselves: -eq and -contains, and in PowerShell 7 also
Select-Object -Unique and Compare-Object, stopped with an
InvalidCastException. GetHashCode of FileSystemSecurity2 read a field
that is never set and threw a NullReferenceException. Two objects are now
equal when they hold the same entry or descriptor, like the .NET types.
InheritedFrom: Win32.GetInheritedFrom returned the sources of the SACL
whenever the descriptor had one, also for the access entries, and the
callers gave the filtered entries of -ExcludeExplicit the sources of the
first entries of the ACL. Get-NTFSAccess -SecurityDescriptor stopped with
an ArgumentOutOfRangeException for a descriptor with audit entries, as
Get-NTFSSecurityDescriptor reads them in an elevated session. The method
now takes the ACL of the entries, and the callers map the sources before
they filter.
The coverage report of rc6 pointed at both; each test fails without its
fix.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
3 weeks ago
|
|
|
var other = obj as FileSystemAccessRule2;
|
|
|
|
|
return other != null && ReferenceEquals(fileSystemAccessRule, other.fileSystemAccessRule);
|
|
|
|
|
}
|
|
|
|
|
public override int GetHashCode()
|
|
|
|
|
{
|
|
|
|
|
return fileSystemAccessRule.GetHashCode();
|
|
|
|
|
}
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
return string.Format("{0} '{1}' ({2})",
|
|
|
|
|
AccessControlType.ToString()[0],
|
|
|
|
|
Account.AccountName,
|
|
|
|
|
AccessRights.ToString()
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
public SimpleFileSystemAccessRule ToSimpleFileSystemAccessRule2()
|
|
|
|
|
{
|
|
|
|
|
return new SimpleFileSystemAccessRule(fullName, Account, AccessRights, AccessControlType);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|