diff options
Diffstat (limited to 'Emby.Common.Implementations/IO/SharpCifs/Smb/ACE.cs')
| -rw-r--r-- | Emby.Common.Implementations/IO/SharpCifs/Smb/ACE.cs | 533 |
1 files changed, 268 insertions, 265 deletions
diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/ACE.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/ACE.cs index 73b742cfb..5f1f90070 100644 --- a/Emby.Common.Implementations/IO/SharpCifs/Smb/ACE.cs +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/ACE.cs @@ -19,269 +19,272 @@ using SharpCifs.Util; namespace SharpCifs.Smb { - /// <summary> - /// An Access Control Entry (ACE) is an element in a security descriptor - /// such as those associated with files and directories. - /// </summary> - /// <remarks> - /// An Access Control Entry (ACE) is an element in a security descriptor - /// such as those associated with files and directories. The Windows OS - /// determines which users have the necessary permissions to access objects - /// based on these entries. - /// <p> - /// To fully understand the information exposed by this class a description - /// of the access check algorithm used by Windows is required. The following - /// is a basic description of the algorithm. For a more complete description - /// we recommend reading the section on Access Control in Keith Brown's - /// "The .NET Developer's Guide to Windows Security" (which is also - /// available online). - /// <p> - /// Direct ACEs are evaluated first in order. The SID of the user performing - /// the operation and the desired access bits are compared to the SID - /// and access mask of each ACE. If the SID matches, the allow/deny flags - /// and access mask are considered. If the ACE is a "deny" - /// ACE and <i>any</i> of the desired access bits match bits in the access - /// mask of the ACE, the whole access check fails. If the ACE is an "allow" - /// ACE and <i>all</i> of the bits in the desired access bits match bits in - /// the access mask of the ACE, the access check is successful. Otherwise, - /// more ACEs are evaluated until all desired access bits (combined) - /// are "allowed". If all of the desired access bits are not "allowed" - /// the then same process is repeated for inherited ACEs. - /// <p> - /// For example, if user <tt>WNET\alice</tt> tries to open a file - /// with desired access bits <tt>0x00000003</tt> (<tt>FILE_READ_DATA | - /// FILE_WRITE_DATA</tt>) and the target file has the following security - /// descriptor ACEs: - /// <pre> - /// Allow WNET\alice 0x001200A9 Direct - /// Allow Administrators 0x001F01FF Inherited - /// Allow SYSTEM 0x001F01FF Inherited - /// </pre> - /// the access check would fail because the direct ACE has an access mask - /// of <tt>0x001200A9</tt> which doesn't have the - /// <tt>FILE_WRITE_DATA</tt> bit on (bit <tt>0x00000002</tt>). Actually, this isn't quite correct. If - /// <tt>WNET\alice</tt> is in the local <tt>Administrators</tt> group the access check - /// will succeed because the inherited ACE allows local <tt>Administrators</tt> - /// both <tt>FILE_READ_DATA</tt> and <tt>FILE_WRITE_DATA</tt> access. - /// </remarks> - public class Ace - { - public const int FileReadData = unchecked(0x00000001); - - public const int FileWriteData = unchecked(0x00000002); - - public const int FileAppendData = unchecked(0x00000004); - - public const int FileReadEa = unchecked(0x00000008); - - public const int FileWriteEa = unchecked(0x00000010); - - public const int FileExecute = unchecked(0x00000020); - - public const int FileDelete = unchecked(0x00000040); - - public const int FileReadAttributes = unchecked(0x00000080); - - public const int FileWriteAttributes = unchecked(0x00000100); - - public const int Delete = unchecked(0x00010000); - - public const int ReadControl = unchecked(0x00020000); - - public const int WriteDac = unchecked(0x00040000); - - public const int WriteOwner = unchecked(0x00080000); - - public const int Synchronize = unchecked(0x00100000); - - public const int GenericAll = unchecked(0x10000000); - - public const int GenericExecute = unchecked(0x20000000); - - public const int GenericWrite = unchecked(0x40000000); - - public const int GenericRead = unchecked((int)(0x80000000)); - - public const int FlagsObjectInherit = unchecked(0x01); - - public const int FlagsContainerInherit = unchecked(0x02); - - public const int FlagsNoPropagate = unchecked(0x04); - - public const int FlagsInheritOnly = unchecked(0x08); - - public const int FlagsInherited = unchecked(0x10); - - internal bool Allow; - - internal int Flags; - - internal int Access; - - internal Sid Sid; - - // 1 - // 2 - // 3 - // 4 - // 5 - // 6 - // 7 - // 8 - // 9 - // 16 - // 17 - // 18 - // 19 - // 20 - // 28 - // 29 - // 30 - // 31 - /// <summary>Returns true if this ACE is an allow ACE and false if it is a deny ACE.</summary> - /// <remarks>Returns true if this ACE is an allow ACE and false if it is a deny ACE.</remarks> - public virtual bool IsAllow() - { - return Allow; - } - - /// <summary>Returns true if this ACE is an inherited ACE and false if it is a direct ACE. - /// </summary> - /// <remarks> - /// Returns true if this ACE is an inherited ACE and false if it is a direct ACE. - /// <p> - /// Note: For reasons not fully understood, <tt>FLAGS_INHERITED</tt> may - /// not be set within all security descriptors even though the ACE was in - /// face inherited. If an inherited ACE is added to a parent the Windows - /// ACL editor will rebuild all children ACEs and set this flag accordingly. - /// </remarks> - public virtual bool IsInherited() - { - return (Flags & FlagsInherited) != 0; - } - - /// <summary>Returns the flags for this ACE.</summary> - /// <remarks> - /// Returns the flags for this ACE. The </tt>isInherited()</tt> - /// method checks the <tt>FLAGS_INHERITED</tt> bit in these flags. - /// </remarks> - public virtual int GetFlags() - { - return Flags; - } - - /// <summary> - /// Returns the 'Apply To' text for inheritance of ACEs on - /// directories such as 'This folder, subfolder and files'. - /// </summary> - /// <remarks> - /// Returns the 'Apply To' text for inheritance of ACEs on - /// directories such as 'This folder, subfolder and files'. For - /// files the text is always 'This object only'. - /// </remarks> - public virtual string GetApplyToText() - { - switch (Flags & (FlagsObjectInherit | FlagsContainerInherit | FlagsInheritOnly - )) - { - case unchecked(0x00): - { - return "This folder only"; - } - - case unchecked(0x03): - { - return "This folder, subfolders and files"; - } - - case unchecked(0x0B): - { - return "Subfolders and files only"; - } - - case unchecked(0x02): - { - return "This folder and subfolders"; - } - - case unchecked(0x0A): - { - return "Subfolders only"; - } - - case unchecked(0x01): - { - return "This folder and files"; - } - - case unchecked(0x09): - { - return "Files only"; - } - } - return "Invalid"; - } - - /// <summary>Returns the access mask accociated with this ACE.</summary> - /// <remarks> - /// Returns the access mask accociated with this ACE. Use the - /// constants for <tt>FILE_READ_DATA</tt>, <tt>FILE_WRITE_DATA</tt>, - /// <tt>READ_CONTROL</tt>, <tt>GENERIC_ALL</tt>, etc with bitwise - /// operators to determine which bits of the mask are on or off. - /// </remarks> - public virtual int GetAccessMask() - { - return Access; - } - - /// <summary>Return the SID associated with this ACE.</summary> - /// <remarks>Return the SID associated with this ACE.</remarks> - public virtual Sid GetSid() - { - return Sid; - } - - internal virtual int Decode(byte[] buf, int bi) - { - Allow = buf[bi++] == unchecked(unchecked(0x00)); - Flags = buf[bi++] & unchecked(0xFF); - int size = ServerMessageBlock.ReadInt2(buf, bi); - bi += 2; - Access = ServerMessageBlock.ReadInt4(buf, bi); - bi += 4; - Sid = new Sid(buf, bi); - return size; - } - - internal virtual void AppendCol(StringBuilder sb, string str, int width) - { - sb.Append(str); - int count = width - str.Length; - for (int i = 0; i < count; i++) - { - sb.Append(' '); - } - } - - /// <summary>Return a string represeting this ACE.</summary> - /// <remarks> - /// Return a string represeting this ACE. - /// <p> - /// Note: This function should probably be changed to return SDDL - /// fragments but currently it does not. - /// </remarks> - public override string ToString() - { - int count; - int i; - string str; - StringBuilder sb = new StringBuilder(); - sb.Append(IsAllow() ? "Allow " : "Deny "); - AppendCol(sb, Sid.ToDisplayString(), 25); - sb.Append(" 0x").Append(Hexdump.ToHexString(Access, 8)).Append(' '); - sb.Append(IsInherited() ? "Inherited " : "Direct "); - AppendCol(sb, GetApplyToText(), 34); - return sb.ToString(); - } - } + /// <summary> + /// An Access Control Entry (ACE) is an element in a security descriptor + /// such as those associated with files and directories. + /// </summary> + /// <remarks> + /// An Access Control Entry (ACE) is an element in a security descriptor + /// such as those associated with files and directories. The Windows OS + /// determines which users have the necessary permissions to access objects + /// based on these entries. + /// <p> + /// To fully understand the information exposed by this class a description + /// of the access check algorithm used by Windows is required. The following + /// is a basic description of the algorithm. For a more complete description + /// we recommend reading the section on Access Control in Keith Brown's + /// "The .NET Developer's Guide to Windows Security" (which is also + /// available online). + /// <p> + /// Direct ACEs are evaluated first in order. The SID of the user performing + /// the operation and the desired access bits are compared to the SID + /// and access mask of each ACE. If the SID matches, the allow/deny flags + /// and access mask are considered. If the ACE is a "deny" + /// ACE and <i>any</i> of the desired access bits match bits in the access + /// mask of the ACE, the whole access check fails. If the ACE is an "allow" + /// ACE and <i>all</i> of the bits in the desired access bits match bits in + /// the access mask of the ACE, the access check is successful. Otherwise, + /// more ACEs are evaluated until all desired access bits (combined) + /// are "allowed". If all of the desired access bits are not "allowed" + /// the then same process is repeated for inherited ACEs. + /// <p> + /// For example, if user <tt>WNET\alice</tt> tries to open a file + /// with desired access bits <tt>0x00000003</tt> (<tt>FILE_READ_DATA | + /// FILE_WRITE_DATA</tt>) and the target file has the following security + /// descriptor ACEs: + /// <pre> + /// Allow WNET\alice 0x001200A9 Direct + /// Allow Administrators 0x001F01FF Inherited + /// Allow SYSTEM 0x001F01FF Inherited + /// </pre> + /// the access check would fail because the direct ACE has an access mask + /// of <tt>0x001200A9</tt> which doesn't have the + /// <tt>FILE_WRITE_DATA</tt> bit on (bit <tt>0x00000002</tt>). Actually, this isn't quite correct. If + /// <tt>WNET\alice</tt> is in the local <tt>Administrators</tt> group the access check + /// will succeed because the inherited ACE allows local <tt>Administrators</tt> + /// both <tt>FILE_READ_DATA</tt> and <tt>FILE_WRITE_DATA</tt> access. + /// </remarks> + public class Ace + { + public const int FileReadData = unchecked(0x00000001); + + public const int FileWriteData = unchecked(0x00000002); + + public const int FileAppendData = unchecked(0x00000004); + + public const int FileReadEa = unchecked(0x00000008); + + public const int FileWriteEa = unchecked(0x00000010); + + public const int FileExecute = unchecked(0x00000020); + + public const int FileDelete = unchecked(0x00000040); + + public const int FileReadAttributes = unchecked(0x00000080); + + public const int FileWriteAttributes = unchecked(0x00000100); + + public const int Delete = unchecked(0x00010000); + + public const int ReadControl = unchecked(0x00020000); + + public const int WriteDac = unchecked(0x00040000); + + public const int WriteOwner = unchecked(0x00080000); + + public const int Synchronize = unchecked(0x00100000); + + public const int GenericAll = unchecked(0x10000000); + + public const int GenericExecute = unchecked(0x20000000); + + public const int GenericWrite = unchecked(0x40000000); + + public const int GenericRead = unchecked((int)(0x80000000)); + + public const int FlagsObjectInherit = unchecked(0x01); + + public const int FlagsContainerInherit = unchecked(0x02); + + public const int FlagsNoPropagate = unchecked(0x04); + + public const int FlagsInheritOnly = unchecked(0x08); + + public const int FlagsInherited = unchecked(0x10); + + internal bool Allow; + + internal int Flags; + + internal int Access; + + internal Sid Sid; + + // 1 + // 2 + // 3 + // 4 + // 5 + // 6 + // 7 + // 8 + // 9 + // 16 + // 17 + // 18 + // 19 + // 20 + // 28 + // 29 + // 30 + // 31 + /// <summary>Returns true if this ACE is an allow ACE and false if it is a deny ACE.</summary> + /// <remarks>Returns true if this ACE is an allow ACE and false if it is a deny ACE.</remarks> + public virtual bool IsAllow() + { + return Allow; + } + + /// <summary>Returns true if this ACE is an inherited ACE and false if it is a direct ACE. + /// </summary> + /// <remarks> + /// Returns true if this ACE is an inherited ACE and false if it is a direct ACE. + /// <p> + /// Note: For reasons not fully understood, <tt>FLAGS_INHERITED</tt> may + /// not be set within all security descriptors even though the ACE was in + /// face inherited. If an inherited ACE is added to a parent the Windows + /// ACL editor will rebuild all children ACEs and set this flag accordingly. + /// </remarks> + public virtual bool IsInherited() + { + return (Flags & FlagsInherited) != 0; + } + + /// <summary>Returns the flags for this ACE.</summary> + /// <remarks> + /// Returns the flags for this ACE. The <tt>isInherited()</tt> + /// method checks the <tt>FLAGS_INHERITED</tt> bit in these flags. + /// </remarks> + public virtual int GetFlags() + { + return Flags; + } + + /// <summary> + /// Returns the 'Apply To' text for inheritance of ACEs on + /// directories such as 'This folder, subfolder and files'. + /// </summary> + /// <remarks> + /// Returns the 'Apply To' text for inheritance of ACEs on + /// directories such as 'This folder, subfolder and files'. For + /// files the text is always 'This object only'. + /// </remarks> + public virtual string GetApplyToText() + { + switch (Flags & (FlagsObjectInherit | FlagsContainerInherit | FlagsInheritOnly)) + { + case unchecked(0x00): + { + return "This folder only"; + } + + case unchecked(0x03): + { + return "This folder, subfolders and files"; + } + + case unchecked(0x0B): + { + return "Subfolders and files only"; + } + + case unchecked(0x02): + { + return "This folder and subfolders"; + } + + case unchecked(0x0A): + { + return "Subfolders only"; + } + + case unchecked(0x01): + { + return "This folder and files"; + } + + case unchecked(0x09): + { + return "Files only"; + } + } + return "Invalid"; + } + + /// <summary>Returns the access mask accociated with this ACE.</summary> + /// <remarks> + /// Returns the access mask accociated with this ACE. Use the + /// constants for <tt>FILE_READ_DATA</tt>, <tt>FILE_WRITE_DATA</tt>, + /// <tt>READ_CONTROL</tt>, <tt>GENERIC_ALL</tt>, etc with bitwise + /// operators to determine which bits of the mask are on or off. + /// </remarks> + public virtual int GetAccessMask() + { + return Access; + } + + /// <summary>Return the SID associated with this ACE.</summary> + /// <remarks>Return the SID associated with this ACE.</remarks> + public virtual Sid GetSid() + { + return Sid; + } + + internal virtual int Decode(byte[] buf, int bi) + { + Allow = buf[bi++] == unchecked(unchecked(0x00)); + Flags = buf[bi++] & unchecked(0xFF); + int size = ServerMessageBlock.ReadInt2(buf, bi); + bi += 2; + Access = ServerMessageBlock.ReadInt4(buf, bi); + bi += 4; + Sid = new Sid(buf, bi); + return size; + } + + internal virtual void AppendCol(StringBuilder sb, string str, int width) + { + sb.Append(str); + int count = width - str.Length; + for (int i = 0; i < count; i++) + { + sb.Append(' '); + } + } + + /// <summary>Return a string represeting this ACE.</summary> + /// <remarks> + /// Return a string represeting this ACE. + /// <p> + /// Note: This function should probably be changed to return SDDL + /// fragments but currently it does not. + /// </remarks> + public override string ToString() + { + int count; + int i; + string str; + StringBuilder sb = new StringBuilder(); + sb.Append(IsAllow() + ? "Allow " + : "Deny "); + AppendCol(sb, Sid.ToDisplayString(), 25); + sb.Append(" 0x").Append(Hexdump.ToHexString(Access, 8)).Append(' '); + sb.Append(IsInherited() + ? "Inherited " + : "Direct "); + AppendCol(sb, GetApplyToText(), 34); + return sb.ToString(); + } + } } |
