FileSecurity.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / clr / src / BCL / System / Security / AccessControl / FileSecurity.cs / 1 / FileSecurity.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
** 
** Class:  FileSecurity 
**
** 
** Purpose: Managed ACL wrapper for files & directories.
**
**
===========================================================*/ 

using System; 
using System.Collections; 
using System.Security.AccessControl;
using System.Security.Permissions; 
using System.Security.Principal;
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices; 
using System.IO;
using System.Runtime.Versioning; 
 
namespace System.Security.AccessControl
{ 
    // Constants from from winnt.h - search for FILE_WRITE_DATA, etc.
    [Flags]
    public enum FileSystemRights
    { 
        // No None field - An ACE with the value 0 cannot grant nor deny.
        ReadData                     = 0x000001, 
        ListDirectory                = ReadData,     // For directories 
        WriteData                    = 0x000002,
        CreateFiles                  = WriteData,    // For directories 
        AppendData                   = 0x000004,
        CreateDirectories            = AppendData,   // For directories
        ReadExtendedAttributes       = 0x000008,
        WriteExtendedAttributes      = 0x000010, 
        ExecuteFile                  = 0x000020,     // For files
        Traverse                     = ExecuteFile,  // For directories 
        // DeleteSubdirectoriesAndFiles only makes sense on directories, but 
        // the shell explicitly sets it for files in its UI.  So we'll include
        // it in FullControl. 
        DeleteSubdirectoriesAndFiles = 0x000040,
        ReadAttributes               = 0x000080,
        WriteAttributes              = 0x000100,
        Delete                       = 0x010000, 
        ReadPermissions              = 0x020000,
        ChangePermissions            = 0x040000, 
        TakeOwnership                = 0x080000, 
        // From the Core File Services team, CreateFile always requires
        // SYNCHRONIZE access.  Very tricksy, CreateFile is. 
        Synchronize                  = 0x100000,  // Can we wait on the handle?
        FullControl                  = 0x1F01FF,

        // These map to what Explorer sets, and are what most users want. 
        // However, an ACL editor will also want to set the Synchronize
        // bit when allowing access, and exclude the synchronize bit when 
        // denying access. 
        Read = ReadData | ReadExtendedAttributes | ReadAttributes | ReadPermissions,
        ReadAndExecute = Read | ExecuteFile, 
        Write = WriteData | AppendData | WriteExtendedAttributes | WriteAttributes,
        Modify = ReadAndExecute | Write | Delete,
    }
 

    public sealed class FileSystemAccessRule : AccessRule 
    { 
        #region Constructors
 
        //
        // Constructor for creating access rules for file objects
        //
 
        public FileSystemAccessRule(
            IdentityReference identity, 
            FileSystemRights fileSystemRights, 
            AccessControlType type )
            : this( 
                identity,
                AccessMaskFromRights( fileSystemRights, type ),
                false,
                InheritanceFlags.None, 
                PropagationFlags.None,
                type ) 
        { 
        }
 
        public FileSystemAccessRule(
            String identity,
            FileSystemRights fileSystemRights,
            AccessControlType type ) 
            : this(
                new NTAccount(identity), 
                AccessMaskFromRights( fileSystemRights, type ), 
                false,
                InheritanceFlags.None, 
                PropagationFlags.None,
                type )
        {
        } 

        // 
        // Constructor for creating access rules for folder objects 
        //
 
        public FileSystemAccessRule(
            IdentityReference identity,
            FileSystemRights fileSystemRights,
            InheritanceFlags inheritanceFlags, 
            PropagationFlags propagationFlags,
            AccessControlType type ) 
            : this( 
                identity,
                AccessMaskFromRights( fileSystemRights, type ), 
                false,
                inheritanceFlags,
                propagationFlags,
                type ) 
        {
        } 
 
        public FileSystemAccessRule(
            String identity, 
            FileSystemRights fileSystemRights,
            InheritanceFlags inheritanceFlags,
            PropagationFlags propagationFlags,
            AccessControlType type ) 
            : this(
                new NTAccount(identity), 
                AccessMaskFromRights( fileSystemRights, type ), 
                false,
                inheritanceFlags, 
                propagationFlags,
                type )
        {
        } 

        // 
        // Internal constructor to be called by public constructors 
        // and the access rule factory methods of {File|Folder}Security
        // 

        internal FileSystemAccessRule(
            IdentityReference identity,
            int accessMask, 
            bool isInherited,
            InheritanceFlags inheritanceFlags, 
            PropagationFlags propagationFlags, 
            AccessControlType type )
            : base( 
                identity,
                accessMask,
                isInherited,
                inheritanceFlags, 
                propagationFlags,
                type ) 
        { 
        }
 
        #endregion

        #region Public properties
 
        public FileSystemRights FileSystemRights
        { 
            get { return RightsFromAccessMask( base.AccessMask ); } 
        }
 
        #endregion

        #region Access mask to rights translation
 
        // ACL's on files have a SYNCHRONIZE bit, and CreateFile ALWAYS
        // asks for it.  So for allows, let's always include this bit, 
        // and for denies, let's never include this bit unless we're denying 
        // full control.  This is the right thing for users, even if it does
        // make the model look asymmetrical from a purist point of view. 
        internal static int AccessMaskFromRights( FileSystemRights fileSystemRights, AccessControlType controlType )
        {
            if (fileSystemRights < (FileSystemRights) 0 || fileSystemRights > FileSystemRights.FullControl)
                throw new ArgumentOutOfRangeException("fileSystemRights", Environment.GetResourceString("Argument_InvalidEnumValue", fileSystemRights, "FileSystemRights")); 

            if (controlType == AccessControlType.Allow) { 
                fileSystemRights |= FileSystemRights.Synchronize; 
            }
            else if (controlType == AccessControlType.Deny) { 
                if (fileSystemRights != FileSystemRights.FullControl &&
                    fileSystemRights != (FileSystemRights.FullControl & ~FileSystemRights.DeleteSubdirectoriesAndFiles))
                    fileSystemRights &= ~FileSystemRights.Synchronize;
            } 

            return ( int )fileSystemRights; 
        } 

        internal static FileSystemRights RightsFromAccessMask( int accessMask ) 
        {
            return ( FileSystemRights )accessMask;
        }
 
        #endregion
    } 
 

    public sealed class FileSystemAuditRule : AuditRule 
    {
        #region Constructors

        public FileSystemAuditRule( 
            IdentityReference identity,
            FileSystemRights fileSystemRights, 
            AuditFlags flags ) 
            : this(
                identity, 
                fileSystemRights,
                InheritanceFlags.None,
                PropagationFlags.None,
                flags ) 
        {
        } 
 
        public FileSystemAuditRule(
            IdentityReference identity, 
            FileSystemRights fileSystemRights,
            InheritanceFlags inheritanceFlags,
            PropagationFlags propagationFlags,
            AuditFlags flags ) 
            : this(
                identity, 
                AccessMaskFromRights( fileSystemRights ), 
                false,
                inheritanceFlags, 
                propagationFlags,
                flags )
        {
        } 

        public FileSystemAuditRule( 
            String identity, 
            FileSystemRights fileSystemRights,
            AuditFlags flags ) 
            : this(
                new NTAccount(identity),
                fileSystemRights,
                InheritanceFlags.None, 
                PropagationFlags.None,
                flags ) 
        { 
        }
 
        public FileSystemAuditRule(
            String identity,
            FileSystemRights fileSystemRights,
            InheritanceFlags inheritanceFlags, 
            PropagationFlags propagationFlags,
            AuditFlags flags ) 
            : this( 
                new NTAccount(identity),
                AccessMaskFromRights( fileSystemRights ), 
                false,
                inheritanceFlags,
                propagationFlags,
                flags ) 
        {
        } 
 
        internal FileSystemAuditRule(
            IdentityReference identity, 
            int accessMask,
            bool isInherited,
            InheritanceFlags inheritanceFlags,
            PropagationFlags propagationFlags, 
            AuditFlags flags )
            : base( 
                identity, 
                accessMask,
                isInherited, 
                inheritanceFlags,
                propagationFlags,
                flags )
        { 
        }
 
        #endregion 

        #region Private methods 

        private static int AccessMaskFromRights( FileSystemRights fileSystemRights )
        {
            if (fileSystemRights < (FileSystemRights) 0 || fileSystemRights > FileSystemRights.FullControl) 
                throw new ArgumentOutOfRangeException("fileSystemRights", Environment.GetResourceString("Argument_InvalidEnumValue", fileSystemRights, "FileSystemRights"));
 
            return ( int )fileSystemRights; 
        }
 
        #endregion

        #region Public properties
 
        public FileSystemRights FileSystemRights
        { 
            get { return FileSystemAccessRule.RightsFromAccessMask( base.AccessMask ); } 
        }
 
        #endregion
    }

 
    public abstract class FileSystemSecurity : NativeObjectSecurity
    { 
        #region Member variables 

        private const ResourceType s_ResourceType = ResourceType.FileObject; 

        #endregion

        internal FileSystemSecurity( bool isContainer ) 
 			: base(isContainer, s_ResourceType, _HandleErrorCode, isContainer)
        { 
        } 

        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        internal FileSystemSecurity( bool isContainer, String name, AccessControlSections includeSections, bool isDirectory )
            : base( isContainer, s_ResourceType, name, includeSections, _HandleErrorCode, isDirectory )
        { 
        }
 
        internal FileSystemSecurity( bool isContainer, SafeFileHandle handle, AccessControlSections includeSections, bool isDirectory ) 
            : base( isContainer, s_ResourceType, handle, includeSections, _HandleErrorCode, isDirectory )
        { 
        }

        private static Exception _HandleErrorCode(int errorCode, string name, SafeHandle handle, object context)
        { 
            System.Exception exception = null;
 
            switch (errorCode) { 
            case Win32Native.ERROR_INVALID_NAME:
                exception = new ArgumentException(Environment.GetResourceString("Argument_InvalidName"),"name"); 
                break;

            case Win32Native.ERROR_INVALID_HANDLE:
                exception = new ArgumentException(Environment.GetResourceString("AccessControl_InvalidHandle")); 
                break;
 
            case Win32Native.ERROR_FILE_NOT_FOUND: 
                if ((context != null) && (context is bool) && ((bool)context)) { // DirectorySecurity
 
                    if ((name != null) && (name.Length != 0))
                        exception = new DirectoryNotFoundException(name);
                    else
                        exception = new DirectoryNotFoundException(); 
                }
                else { 
                    if ((name != null) && (name.Length != 0)) 
                        exception = new FileNotFoundException(name);
                    else 
                        exception = new FileNotFoundException();
                }
                break;
 
            default:
                break; 
            } 

            return exception; 
        }

#region Factories
 
        public sealed override AccessRule AccessRuleFactory(
            IdentityReference identityReference, 
            int accessMask, 
            bool isInherited,
            InheritanceFlags inheritanceFlags, 
            PropagationFlags propagationFlags,
            AccessControlType type )
        {
            return new FileSystemAccessRule( 
                identityReference,
                accessMask, 
                isInherited, 
                inheritanceFlags,
                propagationFlags, 
                type );
        }

        public sealed override AuditRule AuditRuleFactory( 
            IdentityReference identityReference,
            int accessMask, 
            bool isInherited, 
            InheritanceFlags inheritanceFlags,
            PropagationFlags propagationFlags, 
            AuditFlags flags )
        {
            return new FileSystemAuditRule(
                identityReference, 
                accessMask,
                isInherited, 
                inheritanceFlags, 
                propagationFlags,
                flags ); 
        }

        #endregion
 
        #region Internal Methods
 
        internal AccessControlSections GetAccessControlSectionsFromChanges() 
        {
            AccessControlSections persistRules = AccessControlSections.None; 
            if ( AccessRulesModified )
                persistRules = AccessControlSections.Access;
            if ( AuditRulesModified )
                persistRules |= AccessControlSections.Audit; 
            if ( OwnerModified )
                persistRules |= AccessControlSections.Owner; 
            if ( GroupModified ) 
                persistRules |= AccessControlSections.Group;
            return persistRules; 
        }

        [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)]
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        internal void Persist( String fullPath ) 
        { 
            new FileIOPermission( FileIOPermissionAccess.NoAccess, AccessControlActions.Change, fullPath ).Demand();
 
            WriteLock();

            try
            { 
                AccessControlSections persistRules = GetAccessControlSectionsFromChanges();
                base.Persist( fullPath, persistRules ); 
                OwnerModified = GroupModified = AuditRulesModified = AccessRulesModified = false; 
            }
            finally 
            {
                WriteUnlock();
            }
        } 

        [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)] 
        internal void Persist( SafeFileHandle handle, String fullPath ) 
        {
            if ( fullPath != null ) 
                new FileIOPermission( FileIOPermissionAccess.NoAccess, AccessControlActions.Change, fullPath ).Demand();
            else
                new FileIOPermission( PermissionState.Unrestricted ).Demand();
 
            WriteLock();
 
            try 
            {
                AccessControlSections persistRules = GetAccessControlSectionsFromChanges(); 
                base.Persist( handle, persistRules );
                OwnerModified = GroupModified = AuditRulesModified = AccessRulesModified = false;
            }
            finally 
            {
                WriteUnlock(); 
            } 
        }
 
        #endregion

        #region Public Methods
 
        public void AddAccessRule( FileSystemAccessRule rule )
        { 
            base.AddAccessRule( rule ); 

            //PersistIfPossible(); 
        }

        public void SetAccessRule( FileSystemAccessRule rule )
        { 
            base.SetAccessRule( rule );
        } 
 
        public void ResetAccessRule( FileSystemAccessRule rule )
        { 
            base.ResetAccessRule( rule );
        }

        public bool RemoveAccessRule( FileSystemAccessRule rule ) 
        {
            if ( rule == null ) 
                throw new ArgumentNullException("rule"); 

            // If the rule to be removed matches what is there currently then 
            // remove it unaltered. That is, don't mask off the Synchronize bit.
            // This is to avoid dangling synchronize bit

            AuthorizationRuleCollection rules = GetAccessRules(true, true, rule.IdentityReference.GetType()); 

            for (int i=0; i FileSystemRights.FullControl)
                throw new ArgumentOutOfRangeException("fileSystemRights", Environment.GetResourceString("Argument_InvalidEnumValue", fileSystemRights, "FileSystemRights")); 

            if (controlType == AccessControlType.Allow) { 
                fileSystemRights |= FileSystemRights.Synchronize; 
            }
            else if (controlType == AccessControlType.Deny) { 
                if (fileSystemRights != FileSystemRights.FullControl &&
                    fileSystemRights != (FileSystemRights.FullControl & ~FileSystemRights.DeleteSubdirectoriesAndFiles))
                    fileSystemRights &= ~FileSystemRights.Synchronize;
            } 

            return ( int )fileSystemRights; 
        } 

        internal static FileSystemRights RightsFromAccessMask( int accessMask ) 
        {
            return ( FileSystemRights )accessMask;
        }
 
        #endregion
    } 
 

    public sealed class FileSystemAuditRule : AuditRule 
    {
        #region Constructors

        public FileSystemAuditRule( 
            IdentityReference identity,
            FileSystemRights fileSystemRights, 
            AuditFlags flags ) 
            : this(
                identity, 
                fileSystemRights,
                InheritanceFlags.None,
                PropagationFlags.None,
                flags ) 
        {
        } 
 
        public FileSystemAuditRule(
            IdentityReference identity, 
            FileSystemRights fileSystemRights,
            InheritanceFlags inheritanceFlags,
            PropagationFlags propagationFlags,
            AuditFlags flags ) 
            : this(
                identity, 
                AccessMaskFromRights( fileSystemRights ), 
                false,
                inheritanceFlags, 
                propagationFlags,
                flags )
        {
        } 

        public FileSystemAuditRule( 
            String identity, 
            FileSystemRights fileSystemRights,
            AuditFlags flags ) 
            : this(
                new NTAccount(identity),
                fileSystemRights,
                InheritanceFlags.None, 
                PropagationFlags.None,
                flags ) 
        { 
        }
 
        public FileSystemAuditRule(
            String identity,
            FileSystemRights fileSystemRights,
            InheritanceFlags inheritanceFlags, 
            PropagationFlags propagationFlags,
            AuditFlags flags ) 
            : this( 
                new NTAccount(identity),
                AccessMaskFromRights( fileSystemRights ), 
                false,
                inheritanceFlags,
                propagationFlags,
                flags ) 
        {
        } 
 
        internal FileSystemAuditRule(
            IdentityReference identity, 
            int accessMask,
            bool isInherited,
            InheritanceFlags inheritanceFlags,
            PropagationFlags propagationFlags, 
            AuditFlags flags )
            : base( 
                identity, 
                accessMask,
                isInherited, 
                inheritanceFlags,
                propagationFlags,
                flags )
        { 
        }
 
        #endregion 

        #region Private methods 

        private static int AccessMaskFromRights( FileSystemRights fileSystemRights )
        {
            if (fileSystemRights < (FileSystemRights) 0 || fileSystemRights > FileSystemRights.FullControl) 
                throw new ArgumentOutOfRangeException("fileSystemRights", Environment.GetResourceString("Argument_InvalidEnumValue", fileSystemRights, "FileSystemRights"));
 
            return ( int )fileSystemRights; 
        }
 
        #endregion

        #region Public properties
 
        public FileSystemRights FileSystemRights
        { 
            get { return FileSystemAccessRule.RightsFromAccessMask( base.AccessMask ); } 
        }
 
        #endregion
    }

 
    public abstract class FileSystemSecurity : NativeObjectSecurity
    { 
        #region Member variables 

        private const ResourceType s_ResourceType = ResourceType.FileObject; 

        #endregion

        internal FileSystemSecurity( bool isContainer ) 
 			: base(isContainer, s_ResourceType, _HandleErrorCode, isContainer)
        { 
        } 

        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        internal FileSystemSecurity( bool isContainer, String name, AccessControlSections includeSections, bool isDirectory )
            : base( isContainer, s_ResourceType, name, includeSections, _HandleErrorCode, isDirectory )
        { 
        }
 
        internal FileSystemSecurity( bool isContainer, SafeFileHandle handle, AccessControlSections includeSections, bool isDirectory ) 
            : base( isContainer, s_ResourceType, handle, includeSections, _HandleErrorCode, isDirectory )
        { 
        }

        private static Exception _HandleErrorCode(int errorCode, string name, SafeHandle handle, object context)
        { 
            System.Exception exception = null;
 
            switch (errorCode) { 
            case Win32Native.ERROR_INVALID_NAME:
                exception = new ArgumentException(Environment.GetResourceString("Argument_InvalidName"),"name"); 
                break;

            case Win32Native.ERROR_INVALID_HANDLE:
                exception = new ArgumentException(Environment.GetResourceString("AccessControl_InvalidHandle")); 
                break;
 
            case Win32Native.ERROR_FILE_NOT_FOUND: 
                if ((context != null) && (context is bool) && ((bool)context)) { // DirectorySecurity
 
                    if ((name != null) && (name.Length != 0))
                        exception = new DirectoryNotFoundException(name);
                    else
                        exception = new DirectoryNotFoundException(); 
                }
                else { 
                    if ((name != null) && (name.Length != 0)) 
                        exception = new FileNotFoundException(name);
                    else 
                        exception = new FileNotFoundException();
                }
                break;
 
            default:
                break; 
            } 

            return exception; 
        }

#region Factories
 
        public sealed override AccessRule AccessRuleFactory(
            IdentityReference identityReference, 
            int accessMask, 
            bool isInherited,
            InheritanceFlags inheritanceFlags, 
            PropagationFlags propagationFlags,
            AccessControlType type )
        {
            return new FileSystemAccessRule( 
                identityReference,
                accessMask, 
                isInherited, 
                inheritanceFlags,
                propagationFlags, 
                type );
        }

        public sealed override AuditRule AuditRuleFactory( 
            IdentityReference identityReference,
            int accessMask, 
            bool isInherited, 
            InheritanceFlags inheritanceFlags,
            PropagationFlags propagationFlags, 
            AuditFlags flags )
        {
            return new FileSystemAuditRule(
                identityReference, 
                accessMask,
                isInherited, 
                inheritanceFlags, 
                propagationFlags,
                flags ); 
        }

        #endregion
 
        #region Internal Methods
 
        internal AccessControlSections GetAccessControlSectionsFromChanges() 
        {
            AccessControlSections persistRules = AccessControlSections.None; 
            if ( AccessRulesModified )
                persistRules = AccessControlSections.Access;
            if ( AuditRulesModified )
                persistRules |= AccessControlSections.Audit; 
            if ( OwnerModified )
                persistRules |= AccessControlSections.Owner; 
            if ( GroupModified ) 
                persistRules |= AccessControlSections.Group;
            return persistRules; 
        }

        [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)]
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        internal void Persist( String fullPath ) 
        { 
            new FileIOPermission( FileIOPermissionAccess.NoAccess, AccessControlActions.Change, fullPath ).Demand();
 
            WriteLock();

            try
            { 
                AccessControlSections persistRules = GetAccessControlSectionsFromChanges();
                base.Persist( fullPath, persistRules ); 
                OwnerModified = GroupModified = AuditRulesModified = AccessRulesModified = false; 
            }
            finally 
            {
                WriteUnlock();
            }
        } 

        [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)] 
        internal void Persist( SafeFileHandle handle, String fullPath ) 
        {
            if ( fullPath != null ) 
                new FileIOPermission( FileIOPermissionAccess.NoAccess, AccessControlActions.Change, fullPath ).Demand();
            else
                new FileIOPermission( PermissionState.Unrestricted ).Demand();
 
            WriteLock();
 
            try 
            {
                AccessControlSections persistRules = GetAccessControlSectionsFromChanges(); 
                base.Persist( handle, persistRules );
                OwnerModified = GroupModified = AuditRulesModified = AccessRulesModified = false;
            }
            finally 
            {
                WriteUnlock(); 
            } 
        }
 
        #endregion

        #region Public Methods
 
        public void AddAccessRule( FileSystemAccessRule rule )
        { 
            base.AddAccessRule( rule ); 

            //PersistIfPossible(); 
        }

        public void SetAccessRule( FileSystemAccessRule rule )
        { 
            base.SetAccessRule( rule );
        } 
 
        public void ResetAccessRule( FileSystemAccessRule rule )
        { 
            base.ResetAccessRule( rule );
        }

        public bool RemoveAccessRule( FileSystemAccessRule rule ) 
        {
            if ( rule == null ) 
                throw new ArgumentNullException("rule"); 

            // If the rule to be removed matches what is there currently then 
            // remove it unaltered. That is, don't mask off the Synchronize bit.
            // This is to avoid dangling synchronize bit

            AuthorizationRuleCollection rules = GetAccessRules(true, true, rule.IdentityReference.GetType()); 

            for (int i=0; i

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK