mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-10-30 10:12:44 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			288 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			288 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| // This code is derived from jcifs smb client library <jcifs at samba dot org>
 | |
| // Ported by J. Arturo <webmaster at komodosoft dot net>
 | |
| //  
 | |
| // This library is free software; you can redistribute it and/or
 | |
| // modify it under the terms of the GNU Lesser General Public
 | |
| // License as published by the Free Software Foundation; either
 | |
| // version 2.1 of the License, or (at your option) any later version.
 | |
| // 
 | |
| // This library is distributed in the hope that it will be useful,
 | |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| // Lesser General Public License for more details.
 | |
| // 
 | |
| // You should have received a copy of the GNU Lesser General Public
 | |
| // License along with this library; if not, write to the Free Software
 | |
| // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | |
| using System.Text;
 | |
| 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();
 | |
| 		}
 | |
| 	}
 | |
| }
 |