|
|
|
|
using Alphaleonis.Win32.Filesystem;
|
|
|
|
|
using System;
|
fix: write only the sections of the security descriptor that a cmdlet changes
The access and audit cmdlets wrote the owner of an item back with the
entries they changed. For a DACL without the auto-inherit flag, Windows
returns the owner and the group even when only the DACL is read, and the
cmdlets wrote every section that the descriptor held. Without the Restore
privilege, or on a file server that refuses the owner, the write failed
with error 1307 (#34).
- Add-NTFSAccess, Clear-NTFSAccess, Add-NTFSAudit, and Clear-NTFSAudit
read only the DACL or the SACL. FileSystemSecurity2.Write(),
Remove-NTFSAccess, and Remove-NTFSAudit write only the sections they
read, which also fixes the access inheritance cmdlets.
- Read together with the SACL, the inherited entries of such a DACL lose
their inherited flag when the parent folder has no SACL, and the
cmdlets stored them as explicit copies. Get-NTFSSecurityDescriptor now
reads the DACL in a separate call.
- Set-NTFSSecurityDescriptor writes only the sections that changed since
they were read; an unchanged descriptor writes nothing (maintainer
decision of 2026-10-06).
- Clear-NTFSAudit writes nothing for an item without a SACL, and reports
an error without the Security privilege (maintainer decision).
The regression tests failed before and pass after the fix in Windows
PowerShell 5.1 and PowerShell 7, elevated and as a basic user.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
4 weeks ago
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Security.AccessControl;
|
|
|
|
|
|
|
|
|
|
namespace Security2
|
|
|
|
|
{
|
|
|
|
|
public class FileSystemSecurity2
|
|
|
|
|
{
|
|
|
|
|
protected FileSecurity fileSecurityDescriptor;
|
|
|
|
|
protected DirectorySecurity directorySecurityDescriptor;
|
|
|
|
|
protected FileSystemInfo item;
|
|
|
|
|
protected FileSystemSecurity sd;
|
|
|
|
|
protected AccessControlSections sections;
|
|
|
|
|
protected bool isFile = false;
|
|
|
|
|
|
fix: write only the sections of the security descriptor that a cmdlet changes
The access and audit cmdlets wrote the owner of an item back with the
entries they changed. For a DACL without the auto-inherit flag, Windows
returns the owner and the group even when only the DACL is read, and the
cmdlets wrote every section that the descriptor held. Without the Restore
privilege, or on a file server that refuses the owner, the write failed
with error 1307 (#34).
- Add-NTFSAccess, Clear-NTFSAccess, Add-NTFSAudit, and Clear-NTFSAudit
read only the DACL or the SACL. FileSystemSecurity2.Write(),
Remove-NTFSAccess, and Remove-NTFSAudit write only the sections they
read, which also fixes the access inheritance cmdlets.
- Read together with the SACL, the inherited entries of such a DACL lose
their inherited flag when the parent folder has no SACL, and the
cmdlets stored them as explicit copies. Get-NTFSSecurityDescriptor now
reads the DACL in a separate call.
- Set-NTFSSecurityDescriptor writes only the sections that changed since
they were read; an unchanged descriptor writes nothing (maintainer
decision of 2026-10-06).
- Clear-NTFSAudit writes nothing for an item without a SACL, and reports
an error without the Security privilege (maintainer decision).
The regression tests failed before and pass after the fix in Windows
PowerShell 5.1 and PowerShell 7, elevated and as a basic user.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
4 weeks ago
|
|
|
// The SDDL form of each section as it was read or last written, so that WriteChanges writes only the
|
|
|
|
|
// sections that changed since.
|
|
|
|
|
private Dictionary<AccessControlSections, string> sectionsAsRead;
|
|
|
|
|
|
|
|
|
|
public FileSystemInfo Item
|
|
|
|
|
{
|
|
|
|
|
get { return item; }
|
|
|
|
|
set { item = value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string FullName { get { return item.FullName; } }
|
|
|
|
|
|
|
|
|
|
public string Name { get { return item.Name; } }
|
|
|
|
|
|
|
|
|
|
public bool IsFile { get { return isFile; } }
|
|
|
|
|
|
|
|
|
|
public FileSystemSecurity2(FileSystemInfo item, AccessControlSections sections)
|
|
|
|
|
{
|
|
|
|
|
this.sections = sections;
|
|
|
|
|
|
|
|
|
|
if (item is FileInfo)
|
|
|
|
|
{
|
|
|
|
|
this.item = (FileInfo)item;
|
|
|
|
|
|
|
|
|
|
sd = ((FileInfo)this.item).GetAccessControl(sections);
|
|
|
|
|
|
|
|
|
|
isFile = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.item = (DirectoryInfo)item;
|
|
|
|
|
|
|
|
|
|
sd = ((DirectoryInfo)this.item).GetAccessControl(sections);
|
|
|
|
|
}
|
fix: write only the sections of the security descriptor that a cmdlet changes
The access and audit cmdlets wrote the owner of an item back with the
entries they changed. For a DACL without the auto-inherit flag, Windows
returns the owner and the group even when only the DACL is read, and the
cmdlets wrote every section that the descriptor held. Without the Restore
privilege, or on a file server that refuses the owner, the write failed
with error 1307 (#34).
- Add-NTFSAccess, Clear-NTFSAccess, Add-NTFSAudit, and Clear-NTFSAudit
read only the DACL or the SACL. FileSystemSecurity2.Write(),
Remove-NTFSAccess, and Remove-NTFSAudit write only the sections they
read, which also fixes the access inheritance cmdlets.
- Read together with the SACL, the inherited entries of such a DACL lose
their inherited flag when the parent folder has no SACL, and the
cmdlets stored them as explicit copies. Get-NTFSSecurityDescriptor now
reads the DACL in a separate call.
- Set-NTFSSecurityDescriptor writes only the sections that changed since
they were read; an unchanged descriptor writes nothing (maintainer
decision of 2026-10-06).
- Clear-NTFSAudit writes nothing for an item without a SACL, and reports
an error without the Security privilege (maintainer decision).
The regression tests failed before and pass after the fix in Windows
PowerShell 5.1 and PowerShell 7, elevated and as a basic user.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
4 weeks ago
|
|
|
|
|
|
|
|
RememberSections();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public FileSystemSecurity2(FileSystemInfo item)
|
|
|
|
|
{
|
|
|
|
|
if (item is FileInfo)
|
|
|
|
|
{
|
|
|
|
|
this.item = (FileInfo)item;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
sd = ((FileInfo)this.item).GetAccessControl(AccessControlSections.All);
|
|
|
|
|
sections = AccessControlSections.All;
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
sd = ((FileInfo)this.item).GetAccessControl(AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group);
|
|
|
|
|
sections = AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group;
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
sd = ((FileInfo)this.item).GetAccessControl(AccessControlSections.Access);
|
|
|
|
|
sections = AccessControlSections.Access;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
isFile = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.item = (DirectoryInfo)item;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
sd = ((DirectoryInfo)this.item).GetAccessControl(AccessControlSections.All);
|
|
|
|
|
sections = AccessControlSections.All;
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
sd = ((DirectoryInfo)this.item).GetAccessControl(AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group);
|
|
|
|
|
sections = AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group;
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
sd = ((DirectoryInfo)this.item).GetAccessControl(AccessControlSections.Access);
|
|
|
|
|
sections = AccessControlSections.Access;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
fix: write only the sections of the security descriptor that a cmdlet changes
The access and audit cmdlets wrote the owner of an item back with the
entries they changed. For a DACL without the auto-inherit flag, Windows
returns the owner and the group even when only the DACL is read, and the
cmdlets wrote every section that the descriptor held. Without the Restore
privilege, or on a file server that refuses the owner, the write failed
with error 1307 (#34).
- Add-NTFSAccess, Clear-NTFSAccess, Add-NTFSAudit, and Clear-NTFSAudit
read only the DACL or the SACL. FileSystemSecurity2.Write(),
Remove-NTFSAccess, and Remove-NTFSAudit write only the sections they
read, which also fixes the access inheritance cmdlets.
- Read together with the SACL, the inherited entries of such a DACL lose
their inherited flag when the parent folder has no SACL, and the
cmdlets stored them as explicit copies. Get-NTFSSecurityDescriptor now
reads the DACL in a separate call.
- Set-NTFSSecurityDescriptor writes only the sections that changed since
they were read; an unchanged descriptor writes nothing (maintainer
decision of 2026-10-06).
- Clear-NTFSAudit writes nothing for an item without a SACL, and reports
an error without the Security privilege (maintainer decision).
The regression tests failed before and pass after the fix in Windows
PowerShell 5.1 and PowerShell 7, elevated and as a basic user.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
4 weeks ago
|
|
|
|
|
|
|
|
// Read together with the SACL, the inherited entries of a DACL without the auto-inherit flag lose their
|
|
|
|
|
// inherited flag when the parent folder has no SACL, and writing such a DACL back stores them as explicit
|
|
|
|
|
// entries. Read alone, the DACL keeps the flags.
|
|
|
|
|
if (HasAuditSection)
|
|
|
|
|
{
|
|
|
|
|
var accessSecurity = isFile
|
|
|
|
|
? (FileSystemSecurity)((FileInfo)this.item).GetAccessControl(AccessControlSections.Access)
|
|
|
|
|
: ((DirectoryInfo)this.item).GetAccessControl(AccessControlSections.Access);
|
|
|
|
|
sd.SetSecurityDescriptorBinaryForm(accessSecurity.GetSecurityDescriptorBinaryForm(), AccessControlSections.Access);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RememberSections();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Without the Security privilege, the security descriptor is read without its SACL.
|
|
|
|
|
internal bool HasAuditSection
|
|
|
|
|
{
|
|
|
|
|
get { return (sections & AccessControlSections.Audit) == AccessControlSections.Audit; }
|
|
|
|
|
}
|
|
|
|
|
|
fix: write only the sections of the security descriptor that a cmdlet changes
The access and audit cmdlets wrote the owner of an item back with the
entries they changed. For a DACL without the auto-inherit flag, Windows
returns the owner and the group even when only the DACL is read, and the
cmdlets wrote every section that the descriptor held. Without the Restore
privilege, or on a file server that refuses the owner, the write failed
with error 1307 (#34).
- Add-NTFSAccess, Clear-NTFSAccess, Add-NTFSAudit, and Clear-NTFSAudit
read only the DACL or the SACL. FileSystemSecurity2.Write(),
Remove-NTFSAccess, and Remove-NTFSAudit write only the sections they
read, which also fixes the access inheritance cmdlets.
- Read together with the SACL, the inherited entries of such a DACL lose
their inherited flag when the parent folder has no SACL, and the
cmdlets stored them as explicit copies. Get-NTFSSecurityDescriptor now
reads the DACL in a separate call.
- Set-NTFSSecurityDescriptor writes only the sections that changed since
they were read; an unchanged descriptor writes nothing (maintainer
decision of 2026-10-06).
- Clear-NTFSAudit writes nothing for an item without a SACL, and reports
an error without the Security privilege (maintainer decision).
The regression tests failed before and pass after the fix in Windows
PowerShell 5.1 and PowerShell 7, elevated and as a basic user.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
4 weeks ago
|
|
|
// An item without audit entries can have no SACL at all, also when the SACL was read.
|
|
|
|
|
internal bool HasSystemAcl
|
|
|
|
|
{
|
|
|
|
|
get { return new RawSecurityDescriptor(sd.GetSecurityDescriptorBinaryForm(), 0).SystemAcl != null; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The sections that differ from the ones that were read or last written.
|
|
|
|
|
internal AccessControlSections ChangedSections
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
var changed = AccessControlSections.None;
|
|
|
|
|
foreach (var section in sectionsAsRead)
|
|
|
|
|
{
|
|
|
|
|
if (sd.GetSecurityDescriptorSddlForm(section.Key) != section.Value)
|
|
|
|
|
{
|
|
|
|
|
changed |= section.Key;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return changed;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RememberSections()
|
|
|
|
|
{
|
|
|
|
|
sectionsAsRead = new Dictionary<AccessControlSections, string>();
|
|
|
|
|
foreach (var section in new[] { AccessControlSections.Access, AccessControlSections.Audit, AccessControlSections.Owner, AccessControlSections.Group })
|
|
|
|
|
{
|
|
|
|
|
sectionsAsRead[section] = sd.GetSecurityDescriptorSddlForm(section);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public FileSystemSecurity SecurityDescriptor
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return sd;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
fix: write only the sections of the security descriptor that a cmdlet changes
The access and audit cmdlets wrote the owner of an item back with the
entries they changed. For a DACL without the auto-inherit flag, Windows
returns the owner and the group even when only the DACL is read, and the
cmdlets wrote every section that the descriptor held. Without the Restore
privilege, or on a file server that refuses the owner, the write failed
with error 1307 (#34).
- Add-NTFSAccess, Clear-NTFSAccess, Add-NTFSAudit, and Clear-NTFSAudit
read only the DACL or the SACL. FileSystemSecurity2.Write(),
Remove-NTFSAccess, and Remove-NTFSAudit write only the sections they
read, which also fixes the access inheritance cmdlets.
- Read together with the SACL, the inherited entries of such a DACL lose
their inherited flag when the parent folder has no SACL, and the
cmdlets stored them as explicit copies. Get-NTFSSecurityDescriptor now
reads the DACL in a separate call.
- Set-NTFSSecurityDescriptor writes only the sections that changed since
they were read; an unchanged descriptor writes nothing (maintainer
decision of 2026-10-06).
- Clear-NTFSAudit writes nothing for an item without a SACL, and reports
an error without the Security privilege (maintainer decision).
The regression tests failed before and pass after the fix in Windows
PowerShell 5.1 and PowerShell 7, elevated and as a basic user.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
4 weeks ago
|
|
|
// Writes the sections that the descriptor was read with. Windows can return the owner and the group with a DACL
|
|
|
|
|
// that is read alone, and writing them back fails for an owner that the user cannot assign (#34).
|
|
|
|
|
public void Write()
|
|
|
|
|
{
|
|
|
|
|
if (isFile)
|
|
|
|
|
{
|
fix: write only the sections of the security descriptor that a cmdlet changes
The access and audit cmdlets wrote the owner of an item back with the
entries they changed. For a DACL without the auto-inherit flag, Windows
returns the owner and the group even when only the DACL is read, and the
cmdlets wrote every section that the descriptor held. Without the Restore
privilege, or on a file server that refuses the owner, the write failed
with error 1307 (#34).
- Add-NTFSAccess, Clear-NTFSAccess, Add-NTFSAudit, and Clear-NTFSAudit
read only the DACL or the SACL. FileSystemSecurity2.Write(),
Remove-NTFSAccess, and Remove-NTFSAudit write only the sections they
read, which also fixes the access inheritance cmdlets.
- Read together with the SACL, the inherited entries of such a DACL lose
their inherited flag when the parent folder has no SACL, and the
cmdlets stored them as explicit copies. Get-NTFSSecurityDescriptor now
reads the DACL in a separate call.
- Set-NTFSSecurityDescriptor writes only the sections that changed since
they were read; an unchanged descriptor writes nothing (maintainer
decision of 2026-10-06).
- Clear-NTFSAudit writes nothing for an item without a SACL, and reports
an error without the Security privilege (maintainer decision).
The regression tests failed before and pass after the fix in Windows
PowerShell 5.1 and PowerShell 7, elevated and as a basic user.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
4 weeks ago
|
|
|
((FileInfo)item).SetAccessControl((FileSecurity)sd, sections);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
fix: write only the sections of the security descriptor that a cmdlet changes
The access and audit cmdlets wrote the owner of an item back with the
entries they changed. For a DACL without the auto-inherit flag, Windows
returns the owner and the group even when only the DACL is read, and the
cmdlets wrote every section that the descriptor held. Without the Restore
privilege, or on a file server that refuses the owner, the write failed
with error 1307 (#34).
- Add-NTFSAccess, Clear-NTFSAccess, Add-NTFSAudit, and Clear-NTFSAudit
read only the DACL or the SACL. FileSystemSecurity2.Write(),
Remove-NTFSAccess, and Remove-NTFSAudit write only the sections they
read, which also fixes the access inheritance cmdlets.
- Read together with the SACL, the inherited entries of such a DACL lose
their inherited flag when the parent folder has no SACL, and the
cmdlets stored them as explicit copies. Get-NTFSSecurityDescriptor now
reads the DACL in a separate call.
- Set-NTFSSecurityDescriptor writes only the sections that changed since
they were read; an unchanged descriptor writes nothing (maintainer
decision of 2026-10-06).
- Clear-NTFSAudit writes nothing for an item without a SACL, and reports
an error without the Security privilege (maintainer decision).
The regression tests failed before and pass after the fix in Windows
PowerShell 5.1 and PowerShell 7, elevated and as a basic user.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
4 weeks ago
|
|
|
((DirectoryInfo)item).SetAccessControl((DirectorySecurity)sd, sections);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RememberSections();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Writes only the sections that changed since they were read or last written, so that, for example, an
|
|
|
|
|
// unchanged owner that the user cannot assign isn't written back (#34). Without a change, it writes nothing.
|
|
|
|
|
internal void WriteChanges()
|
|
|
|
|
{
|
|
|
|
|
var changedSections = ChangedSections;
|
|
|
|
|
if (changedSections == AccessControlSections.None)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isFile)
|
|
|
|
|
{
|
|
|
|
|
((FileInfo)item).SetAccessControl((FileSecurity)sd, changedSections);
|
|
|
|
|
}
|
fix: write only the sections of the security descriptor that a cmdlet changes
The access and audit cmdlets wrote the owner of an item back with the
entries they changed. For a DACL without the auto-inherit flag, Windows
returns the owner and the group even when only the DACL is read, and the
cmdlets wrote every section that the descriptor held. Without the Restore
privilege, or on a file server that refuses the owner, the write failed
with error 1307 (#34).
- Add-NTFSAccess, Clear-NTFSAccess, Add-NTFSAudit, and Clear-NTFSAudit
read only the DACL or the SACL. FileSystemSecurity2.Write(),
Remove-NTFSAccess, and Remove-NTFSAudit write only the sections they
read, which also fixes the access inheritance cmdlets.
- Read together with the SACL, the inherited entries of such a DACL lose
their inherited flag when the parent folder has no SACL, and the
cmdlets stored them as explicit copies. Get-NTFSSecurityDescriptor now
reads the DACL in a separate call.
- Set-NTFSSecurityDescriptor writes only the sections that changed since
they were read; an unchanged descriptor writes nothing (maintainer
decision of 2026-10-06).
- Clear-NTFSAudit writes nothing for an item without a SACL, and reports
an error without the Security privilege (maintainer decision).
The regression tests failed before and pass after the fix in Windows
PowerShell 5.1 and PowerShell 7, elevated and as a basic user.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
4 weeks ago
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
((DirectoryInfo)item).SetAccessControl((DirectorySecurity)sd, changedSections);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RememberSections();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Write(FileSystemInfo item)
|
|
|
|
|
{
|
|
|
|
|
if (item is FileInfo)
|
|
|
|
|
{
|
|
|
|
|
((FileInfo)item).SetAccessControl((FileSecurity)sd);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
((DirectoryInfo)item).SetAccessControl((DirectorySecurity)sd);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Write(string path)
|
|
|
|
|
{
|
|
|
|
|
FileSystemInfo item = null;
|
|
|
|
|
|
|
|
|
|
if (File.Exists(path))
|
|
|
|
|
{
|
|
|
|
|
item = new FileInfo(path);
|
|
|
|
|
}
|
|
|
|
|
else if (Directory.Exists(path))
|
|
|
|
|
{
|
|
|
|
|
item = new DirectoryInfo(path);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
throw new System.IO.FileNotFoundException("File not found", path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Write(item);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region Conversion
|
|
|
|
|
public static implicit operator FileSecurity(FileSystemSecurity2 fs2)
|
|
|
|
|
{
|
|
|
|
|
return fs2.fileSecurityDescriptor;
|
|
|
|
|
}
|
|
|
|
|
public static implicit operator FileSystemSecurity2(FileSecurity fs)
|
|
|
|
|
{
|
|
|
|
|
return new FileSystemSecurity2(new FileInfo(""));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static implicit operator DirectorySecurity(FileSystemSecurity2 fs2)
|
|
|
|
|
{
|
|
|
|
|
return fs2.directorySecurityDescriptor;
|
|
|
|
|
}
|
|
|
|
|
public static implicit operator FileSystemSecurity2(DirectorySecurity fs)
|
|
|
|
|
{
|
|
|
|
|
return new FileSystemSecurity2(new DirectoryInfo(""));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//REQUIRED BECAUSE OF CONVERSION OPERATORS
|
|
|
|
|
public override bool Equals(object obj)
|
|
|
|
|
{
|
|
|
|
|
return this.fileSecurityDescriptor == (FileSecurity)obj;
|
|
|
|
|
}
|
|
|
|
|
public override int GetHashCode()
|
|
|
|
|
{
|
|
|
|
|
return fileSecurityDescriptor.GetHashCode();
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
public static void ConvertToFileSystemFlags(ApplyTo ApplyTo, out InheritanceFlags inheritanceFlags, out PropagationFlags propagationFlags)
|
|
|
|
|
{
|
|
|
|
|
inheritanceFlags = InheritanceFlags.None;
|
|
|
|
|
propagationFlags = PropagationFlags.None;
|
|
|
|
|
|
|
|
|
|
switch (ApplyTo)
|
|
|
|
|
{
|
|
|
|
|
case ApplyTo.FilesOnly:
|
|
|
|
|
inheritanceFlags = InheritanceFlags.ObjectInherit;
|
|
|
|
|
propagationFlags = PropagationFlags.InheritOnly;
|
|
|
|
|
break;
|
|
|
|
|
case ApplyTo.SubfoldersAndFilesOnly:
|
|
|
|
|
inheritanceFlags = InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit;
|
|
|
|
|
propagationFlags = PropagationFlags.InheritOnly;
|
|
|
|
|
break;
|
|
|
|
|
case ApplyTo.SubfoldersOnly:
|
|
|
|
|
inheritanceFlags = InheritanceFlags.ContainerInherit;
|
|
|
|
|
propagationFlags = PropagationFlags.InheritOnly;
|
|
|
|
|
break;
|
|
|
|
|
case ApplyTo.ThisFolderAndFiles:
|
|
|
|
|
inheritanceFlags = InheritanceFlags.ObjectInherit;
|
|
|
|
|
propagationFlags = PropagationFlags.None;
|
|
|
|
|
break;
|
|
|
|
|
case ApplyTo.ThisFolderAndSubfolders:
|
|
|
|
|
inheritanceFlags = InheritanceFlags.ContainerInherit;
|
|
|
|
|
propagationFlags = PropagationFlags.None;
|
|
|
|
|
break;
|
|
|
|
|
case ApplyTo.ThisFolderOnly:
|
|
|
|
|
inheritanceFlags = InheritanceFlags.None;
|
|
|
|
|
propagationFlags = PropagationFlags.None;
|
|
|
|
|
break;
|
|
|
|
|
case ApplyTo.ThisFolderSubfoldersAndFiles:
|
|
|
|
|
inheritanceFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
|
|
|
|
|
propagationFlags = PropagationFlags.None;
|
|
|
|
|
break;
|
|
|
|
|
case ApplyTo.FilesOnlyOneLevel:
|
|
|
|
|
inheritanceFlags = InheritanceFlags.ObjectInherit;
|
|
|
|
|
propagationFlags = PropagationFlags.InheritOnly | PropagationFlags.NoPropagateInherit;
|
|
|
|
|
break;
|
|
|
|
|
case ApplyTo.SubfoldersAndFilesOnlyOneLevel:
|
|
|
|
|
inheritanceFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
|
|
|
|
|
propagationFlags = PropagationFlags.InheritOnly | PropagationFlags.NoPropagateInherit;
|
|
|
|
|
break;
|
|
|
|
|
case ApplyTo.SubfoldersOnlyOneLevel:
|
|
|
|
|
inheritanceFlags = InheritanceFlags.ContainerInherit;
|
|
|
|
|
propagationFlags = PropagationFlags.InheritOnly | PropagationFlags.NoPropagateInherit;
|
|
|
|
|
break;
|
|
|
|
|
case ApplyTo.ThisFolderAndFilesOneLevel:
|
|
|
|
|
inheritanceFlags = InheritanceFlags.ObjectInherit;
|
|
|
|
|
propagationFlags = PropagationFlags.NoPropagateInherit;
|
|
|
|
|
break;
|
|
|
|
|
case ApplyTo.ThisFolderAndSubfoldersOneLevel:
|
|
|
|
|
inheritanceFlags = InheritanceFlags.ContainerInherit;
|
|
|
|
|
propagationFlags = PropagationFlags.NoPropagateInherit;
|
|
|
|
|
break;
|
|
|
|
|
case ApplyTo.ThisFolderSubfoldersAndFilesOneLevel:
|
|
|
|
|
inheritanceFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
|
|
|
|
|
propagationFlags = PropagationFlags.NoPropagateInherit;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static ApplyTo ConvertToApplyTo(InheritanceFlags InheritanceFlags, PropagationFlags PropagationFlags)
|
|
|
|
|
{
|
|
|
|
|
if (InheritanceFlags == InheritanceFlags.ObjectInherit & PropagationFlags == PropagationFlags.InheritOnly)
|
|
|
|
|
return ApplyTo.FilesOnly;
|
|
|
|
|
else if (InheritanceFlags == (InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit) & PropagationFlags == PropagationFlags.InheritOnly)
|
|
|
|
|
return ApplyTo.SubfoldersAndFilesOnly;
|
|
|
|
|
else if (InheritanceFlags == InheritanceFlags.ContainerInherit & PropagationFlags == PropagationFlags.InheritOnly)
|
|
|
|
|
return ApplyTo.SubfoldersOnly;
|
|
|
|
|
else if (InheritanceFlags == InheritanceFlags.ObjectInherit & PropagationFlags == PropagationFlags.None)
|
|
|
|
|
return ApplyTo.ThisFolderAndFiles;
|
|
|
|
|
else if (InheritanceFlags == InheritanceFlags.ContainerInherit & PropagationFlags == PropagationFlags.None)
|
|
|
|
|
return ApplyTo.ThisFolderAndSubfolders;
|
|
|
|
|
else if (InheritanceFlags == InheritanceFlags.None & PropagationFlags == PropagationFlags.None)
|
|
|
|
|
return ApplyTo.ThisFolderOnly;
|
|
|
|
|
else if (InheritanceFlags == (InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit) & PropagationFlags == PropagationFlags.None)
|
|
|
|
|
return ApplyTo.ThisFolderSubfoldersAndFiles;
|
|
|
|
|
else if (InheritanceFlags == (InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit) & PropagationFlags == PropagationFlags.NoPropagateInherit)
|
|
|
|
|
return ApplyTo.ThisFolderSubfoldersAndFilesOneLevel;
|
|
|
|
|
else if (InheritanceFlags == InheritanceFlags.ContainerInherit & PropagationFlags == PropagationFlags.NoPropagateInherit)
|
|
|
|
|
return ApplyTo.ThisFolderAndSubfoldersOneLevel;
|
|
|
|
|
else if (InheritanceFlags == InheritanceFlags.ObjectInherit & PropagationFlags == PropagationFlags.NoPropagateInherit)
|
|
|
|
|
return ApplyTo.ThisFolderAndFilesOneLevel;
|
|
|
|
|
else if (InheritanceFlags == (InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit) & PropagationFlags == (PropagationFlags.InheritOnly | PropagationFlags.NoPropagateInherit))
|
|
|
|
|
return ApplyTo.SubfoldersAndFilesOnlyOneLevel;
|
|
|
|
|
else if (InheritanceFlags == InheritanceFlags.ContainerInherit & PropagationFlags == (PropagationFlags.InheritOnly | PropagationFlags.NoPropagateInherit))
|
|
|
|
|
return ApplyTo.SubfoldersOnlyOneLevel;
|
|
|
|
|
else if (InheritanceFlags == InheritanceFlags.ObjectInherit & PropagationFlags == (PropagationFlags.InheritOnly | PropagationFlags.NoPropagateInherit))
|
|
|
|
|
return ApplyTo.FilesOnlyOneLevel;
|
|
|
|
|
|
|
|
|
|
throw new RightsConverionException("The combination of InheritanceFlags and PropagationFlags could not be translated");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static FileSystemRights MapGenericRightsToFileSystemRights(uint originalRights)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var r = Enum.Parse(typeof(FileSystemRights), (originalRights).ToString());
|
|
|
|
|
if (r.ToString() == originalRights.ToString())
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentOutOfRangeException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var fileSystemRights = (FileSystemRights)originalRights;
|
|
|
|
|
return fileSystemRights;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception)
|
|
|
|
|
{
|
|
|
|
|
FileSystemRights rights = 0;
|
|
|
|
|
if (Convert.ToBoolean(originalRights & (uint)GenericRights.GENERIC_EXECUTE))
|
|
|
|
|
{
|
|
|
|
|
rights |= (FileSystemRights)MappedGenericRights.FILE_GENERIC_EXECUTE;
|
|
|
|
|
originalRights ^= (uint)GenericRights.GENERIC_EXECUTE;
|
|
|
|
|
}
|
|
|
|
|
if (Convert.ToBoolean(originalRights & (uint)GenericRights.GENERIC_READ))
|
|
|
|
|
{
|
|
|
|
|
rights |= (FileSystemRights)MappedGenericRights.FILE_GENERIC_READ;
|
|
|
|
|
originalRights ^= (uint)GenericRights.GENERIC_READ;
|
|
|
|
|
}
|
|
|
|
|
if (Convert.ToBoolean(originalRights & (uint)GenericRights.GENERIC_WRITE))
|
|
|
|
|
{
|
|
|
|
|
rights |= (FileSystemRights)MappedGenericRights.FILE_GENERIC_WRITE;
|
|
|
|
|
originalRights ^= (uint)GenericRights.GENERIC_WRITE;
|
|
|
|
|
}
|
|
|
|
|
if (Convert.ToBoolean(originalRights & (uint)GenericRights.GENERIC_ALL))
|
|
|
|
|
{
|
|
|
|
|
rights |= (FileSystemRights)MappedGenericRights.FILE_GENERIC_ALL;
|
|
|
|
|
originalRights ^= (uint)GenericRights.GENERIC_ALL;
|
|
|
|
|
}
|
|
|
|
|
//throw new RightsConverionException("Cannot convert GenericRights into FileSystemRights");
|
|
|
|
|
|
|
|
|
|
var remainingRights = (FileSystemRights)Enum.Parse(typeof(FileSystemRights), (originalRights).ToString());
|
|
|
|
|
|
|
|
|
|
rights |= remainingRights;
|
|
|
|
|
|
|
|
|
|
return rights;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|