SecurityDescriptor.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Security / AccessControl / SecurityDescriptor.cs / 1305376 / SecurityDescriptor.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
** 
** Classes:  Security Descriptor family of classes 
**
** 
===========================================================*/

using Microsoft.Win32;
using System; 
using System.Runtime.InteropServices;
using System.Security.Principal; 
using System.Globalization; 
using System.Diagnostics.Contracts;
 
namespace System.Security.AccessControl
{
    [Flags]
 
    public enum ControlFlags
    { 
        None                                = 0x0000, 
        OwnerDefaulted                      = 0x0001, // set by RM only
        GroupDefaulted                      = 0x0002, // set by RM only 
        DiscretionaryAclPresent             = 0x0004, // set by RM or user, 'off' means DACL is null
        DiscretionaryAclDefaulted           = 0x0008, // set by RM only
        SystemAclPresent                    = 0x0010, // same as DiscretionaryAclPresent
        SystemAclDefaulted                  = 0x0020, // sams as DiscretionaryAclDefaulted 
        DiscretionaryAclUntrusted           = 0x0040, // ignore this one
        ServerSecurity                      = 0x0080, // ignore this one 
        DiscretionaryAclAutoInheritRequired = 0x0100, // ignore this one 
        SystemAclAutoInheritRequired        = 0x0200, // ignore this one
        DiscretionaryAclAutoInherited       = 0x0400, // set by RM only 
        SystemAclAutoInherited              = 0x0800, // set by RM only
        DiscretionaryAclProtected           = 0x1000, // when set, RM will stop inheriting
        SystemAclProtected                  = 0x2000, // when set, RM will stop inheriting
        RMControlValid                      = 0x4000, // the reserved 8 bits have some meaning 
        SelfRelative                        = 0x8000, // must always be on
    } 
 

    public abstract class GenericSecurityDescriptor 
    {
        #region Protected Members

        // 
        // Pictorially the structure of a security descriptor is as follows:
        // 
        //       3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 
        //       1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
        //      +---------------------------------------------------------------+ 
        //      |            Control            |Reserved1 (SBZ)|   Revision    |
        //      +---------------------------------------------------------------+
        //      |                            Owner                              |
        //      +---------------------------------------------------------------+ 
        //      |                            Group                              |
        //      +----------------------------------------------------------------+ 
        //      |                            Sacl                               | 
        //      +---------------------------------------------------------------+
        //      |                            Dacl                               | 
        //      +----------------------------------------------------------------+
        //

        internal const int HeaderLength = 20; 
        internal const int OwnerFoundAt = 4;
        internal const int GroupFoundAt = 8; 
        internal const int SaclFoundAt = 12; 
        internal const int DaclFoundAt = 16;
 
        #endregion

        #region Private Methods
 
        //
        // Stores an integer in big-endian format into an array at a given offset 
        // 

        private static void MarshalInt( byte[] binaryForm, int offset, int number ) 
        {
            binaryForm[offset + 0] = ( byte )( number >> 0 );
            binaryForm[offset + 1] = ( byte )( number >> 8 );
            binaryForm[offset + 2] = ( byte )( number >> 16 ); 
            binaryForm[offset + 3] = ( byte )( number >> 24 );
        } 
 
        //
        // Retrieves an integer stored in big-endian format at a given offset in an array 
        //

        internal static int UnmarshalInt( byte[] binaryForm, int offset )
        { 
            return (int)(
                ( binaryForm[offset + 0] <<  0 ) + 
                ( binaryForm[offset + 1] <<  8 ) + 
                ( binaryForm[offset + 2] << 16 ) +
                ( binaryForm[offset + 3] << 24 )); 
        }

        #endregion
 
        #region Constructors
 
        protected GenericSecurityDescriptor() 
        { }
 
        #endregion

        #region Protected Properties
 
        //
        // Marshaling logic requires calling into the derived 
        // class to obtain pointers to SACL and DACL 
        //
 
        internal abstract GenericAcl GenericSacl { get; }
        internal abstract GenericAcl GenericDacl { get; }
        private bool IsCraftedAefaDacl
        { 
            get
            { 
                return  (GenericDacl is DiscretionaryAcl) && (GenericDacl as DiscretionaryAcl).EveryOneFullAccessForNullDacl; 
            }
        } 

        #endregion

        #region Public Properties 

        public static bool IsSddlConversionSupported() 
        { 
            return true; // SDDL to binary conversions are supported on Windows 2000 and higher
        } 

        public static byte Revision
        {
            get { return 1; } 
        }
 
        // 
        // Allows retrieving and setting the control bits for this security descriptor
        // 

        public abstract ControlFlags ControlFlags { get; }

        // 
        // Allows retrieving and setting the owner SID for this security descriptor
        // 
 
        public abstract SecurityIdentifier Owner { get; set; }
 
        //
        // Allows retrieving and setting the group SID for this security descriptor
        //
 
        public abstract SecurityIdentifier Group { get; set; }
 
        // 
        // Retrieves the length of the binary representation
        // of the security descriptor 
        //

        public int BinaryLength
        { 
            get
            { 
                int result = HeaderLength; 

                if ( Owner != null ) 
                {
                    result += Owner.BinaryLength;
                }
 
                if ( Group != null )
                { 
                    result += Group.BinaryLength; 
                }
 
                if (( ControlFlags & ControlFlags.SystemAclPresent ) != 0 &&
                    GenericSacl != null )
                {
                    result += GenericSacl.BinaryLength; 
                }
 
                if (( ControlFlags & ControlFlags.DiscretionaryAclPresent ) != 0 && 
                    GenericDacl != null && !IsCraftedAefaDacl)
                { 
                    result += GenericDacl.BinaryLength;
                }

                return result; 
            }
        } 
 
        #endregion
 
        #region Public Methods

        //
        // Converts the security descriptor to its SDDL form 
        //
 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        public string GetSddlForm( AccessControlSections includeSections )
        { 
            byte[] binaryForm = new byte[BinaryLength];
            string resultSddl;
            int error;
 
            GetBinaryForm( binaryForm, 0 );
 
            SecurityInfos flags = 0; 

            if (( includeSections & AccessControlSections.Owner ) != 0 ) 
            {
                flags |= SecurityInfos.Owner;
            }
 
            if (( includeSections & AccessControlSections.Group ) != 0 )
            { 
                flags |= SecurityInfos.Group; 
            }
 
            if (( includeSections & AccessControlSections.Audit ) != 0 )
            {
                flags |= SecurityInfos.SystemAcl;
            } 

            if (( includeSections & AccessControlSections.Access ) != 0 ) 
            { 
                flags |= SecurityInfos.DiscretionaryAcl;
            } 

            error = Win32.ConvertSdToSddl( binaryForm, 1, flags, out resultSddl );

            if ( error == Win32Native.ERROR_INVALID_PARAMETER || 
                error == Win32Native.ERROR_UNKNOWN_REVISION )
            { 
                // 
                // Indicates that the marshaling logic in GetBinaryForm is busted
                // 

                Contract.Assert( false, "binaryForm produced invalid output" );
                throw new InvalidOperationException();
            } 
            else if ( error != Win32Native.ERROR_SUCCESS )
            { 
                Contract.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.ConvertSdToSddl returned {0}", error )); 
                throw new InvalidOperationException();
            } 

            return resultSddl;
        }
 
        //
        // Converts the security descriptor to its binary form 
        // 

        public void GetBinaryForm( byte[] binaryForm, int offset ) 
        {
            if ( binaryForm == null )
            {
                throw new ArgumentNullException( "binaryForm" ); 
            }
 
            if ( offset < 0 ) 
            {
                throw new ArgumentOutOfRangeException("offset", 
                    Environment.GetResourceString( "ArgumentOutOfRange_NeedNonNegNum" ));
            }

            if ( binaryForm.Length - offset < BinaryLength ) 
            {
                throw new ArgumentOutOfRangeException( 
                    "binaryForm", 
                    Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" ));
            } 
            Contract.EndContractBlock();

            //
            // the offset will grow as we go for each additional field (owner, group, 
            // acl, etc) being written. But for each of such fields, we must use the
            // original offset as passed in, not the growing offset 
            // 

            int originalOffset = offset; 

            //
            // Populate the header
            // 

            int length = BinaryLength; 
 
            byte rmControl =
                (( this is RawSecurityDescriptor ) && 
                 (( ControlFlags & ControlFlags.RMControlValid ) != 0 )) ? (( this as RawSecurityDescriptor ).ResourceManagerControl ) : ( byte )0;

            // if the DACL is our internally crafted NULL replacement, then let us turn off this control
            int materializedControlFlags = ( int )ControlFlags; 
            if (IsCraftedAefaDacl)
            { 
                unchecked {materializedControlFlags &= ~((int)ControlFlags.DiscretionaryAclPresent);} 
            }
 
            binaryForm[offset + 0] = Revision;
            binaryForm[offset + 1] = rmControl;
            binaryForm[offset + 2] = ( byte )(( int )materializedControlFlags >> 0 );
            binaryForm[offset + 3] = ( byte )(( int )materializedControlFlags >> 8 ); 

            // 
            // Compute offsets at which owner, group, SACL and DACL are stored 
            //
 
            int ownerOffset, groupOffset, saclOffset, daclOffset;

            ownerOffset = offset + OwnerFoundAt;
            groupOffset = offset + GroupFoundAt; 
            saclOffset = offset + SaclFoundAt;
            daclOffset = offset + DaclFoundAt; 
 
            offset += HeaderLength;
 
            //
            // Marhsal the Owner SID into place
            //
 
            if ( Owner != null )
            { 
                MarshalInt( binaryForm, ownerOffset, offset - originalOffset ); 
                Owner.GetBinaryForm( binaryForm, offset );
                offset += Owner.BinaryLength; 
            }
            else
            {
                // 
                // If Owner SID is null, store 0 in the offset field
                // 
 
                MarshalInt( binaryForm, ownerOffset, 0 );
            } 

            //
            // Marshal the Group SID into place
            // 

            if ( Group != null ) 
            { 
                MarshalInt( binaryForm, groupOffset, offset - originalOffset );
                Group.GetBinaryForm( binaryForm, offset ); 
                offset += Group.BinaryLength;
            }
            else
            { 
                //
                // If Group SID is null, store 0 in the offset field 
                // 

                MarshalInt( binaryForm, groupOffset, 0 ); 
            }

            //
            // Marshal the SACL into place, if present 
            //
 
            if (( ControlFlags & ControlFlags.SystemAclPresent ) != 0 && 
                GenericSacl != null )
            { 
                MarshalInt( binaryForm, saclOffset, offset - originalOffset );
                GenericSacl.GetBinaryForm( binaryForm, offset );
                offset += GenericSacl.BinaryLength;
            } 
            else
            { 
                // 
                // If SACL is null or not present, store 0 in the offset field
                // 

                MarshalInt( binaryForm, saclOffset, 0 );
            }
 
            //
            // Marshal the DACL into place, if present 
            // 

            if (( ControlFlags & ControlFlags.DiscretionaryAclPresent ) != 0 && 
                GenericDacl != null && !IsCraftedAefaDacl )
            {
                MarshalInt( binaryForm, daclOffset, offset - originalOffset );
                GenericDacl.GetBinaryForm( binaryForm, offset ); 
                offset += GenericDacl.BinaryLength;
            } 
            else 
            {
                // 
                // If DACL is null or not present, store 0 in the offset field
                //

                MarshalInt( binaryForm, daclOffset, 0 ); 
            }
        } 
 
        #endregion
    } 


    public sealed class RawSecurityDescriptor : GenericSecurityDescriptor
    { 
        #region Private Members
 
        private SecurityIdentifier _owner; 
        private SecurityIdentifier _group;
        private ControlFlags _flags; 
        private RawAcl _sacl;
        private RawAcl _dacl;
        private byte _rmControl; // the not-so-reserved SBZ1 field
 
        #endregion
 
        #region Protected Properties 

        internal override GenericAcl GenericSacl 
        {
            get { return _sacl; }
        }
 
        internal override GenericAcl GenericDacl
        { 
            get { return _dacl; } 
        }
 
        #endregion

        #region Private methods
 
        private void CreateFromParts( ControlFlags flags, SecurityIdentifier owner, SecurityIdentifier group, RawAcl systemAcl, RawAcl discretionaryAcl )
        { 
            SetFlags( flags ); 
            Owner = owner;
            Group = group; 
            SystemAcl = systemAcl;
            DiscretionaryAcl = discretionaryAcl;
            ResourceManagerControl = 0;
        } 

        #endregion 
 
        #region Constructors
 
        //
        // Creates a security descriptor explicitly
        //
 
        public RawSecurityDescriptor( ControlFlags flags, SecurityIdentifier owner, SecurityIdentifier group, RawAcl systemAcl, RawAcl discretionaryAcl )
            : base() 
        { 
            CreateFromParts( flags, owner, group, systemAcl, discretionaryAcl );
        } 

        //
        // Creates a security descriptor from an SDDL string
        // 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        public RawSecurityDescriptor( string sddlForm ) 
            : this( BinaryFormFromSddlForm( sddlForm ), 0 )
        { 
        }

        //
        // Creates a security descriptor from its binary representation 
        // Important: the representation must be in self-relative format
        // 
 
        public RawSecurityDescriptor( byte[] binaryForm, int offset )
            : base() 
        {
            //
            // The array passed in must be valid
            // 

            if ( binaryForm == null ) 
            { 
                throw new ArgumentNullException( "binaryForm" );
            } 

            if ( offset < 0 )
            {
                // 
                // Offset must not be negative
                // 
 
                throw new ArgumentOutOfRangeException("offset",
                    Environment.GetResourceString( "ArgumentOutOfRange_NeedNonNegNum" )); 
            }

            //
            // At least make sure the header is in place 
            //
 
            if ( binaryForm.Length - offset < HeaderLength ) 
            {
                throw new ArgumentOutOfRangeException( 
                    "binaryForm",
                    Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" ));
            }
 
            //
            // We only understand revision-1 security descriptors 
            // 

            if ( binaryForm[offset + 0] != Revision ) 
            {
                throw new ArgumentOutOfRangeException("binaryForm",
                    Environment.GetResourceString( "AccessControl_InvalidSecurityDescriptorRevision" ));
            } 
            Contract.EndContractBlock();
 
 
            ControlFlags flags;
            SecurityIdentifier owner, group; 
            RawAcl sacl, dacl;
            byte rmControl;

            // 
            // Extract the ResourceManagerControl field
            // 
 
            rmControl = binaryForm[offset + 1];
 
            //
            // Extract the control flags
            //
 
            flags = ( ControlFlags )(( binaryForm[offset + 2] << 0 ) + ( binaryForm[offset + 3] << 8 ));
 
            // 
            // Make sure that the input is in self-relative format
            // 

            if (( flags & ControlFlags.SelfRelative ) == 0 )
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( "AccessControl_InvalidSecurityDescriptorSelfRelativeForm" ),
                    "binaryForm" ); 
            } 

            // 
            // Extract the owner SID
            //

            int ownerOffset = UnmarshalInt( binaryForm, offset + OwnerFoundAt ); 

            if ( ownerOffset != 0 ) 
            { 
                owner = new SecurityIdentifier( binaryForm, offset + ownerOffset );
            } 
            else
            {
                owner = null;
            } 

            // 
            // Extract the group SID 
            //
 
            int groupOffset = UnmarshalInt( binaryForm, offset + GroupFoundAt );

            if ( groupOffset != 0 )
            { 
                group = new SecurityIdentifier( binaryForm, offset + groupOffset );
            } 
            else 
            {
                group = null; 
            }

            //
            // Extract the SACL 
            //
 
            int saclOffset = UnmarshalInt( binaryForm, offset + SaclFoundAt ); 

            if ((( flags & ControlFlags.SystemAclPresent ) != 0 ) && 
                saclOffset != 0 )
            {
                sacl = new RawAcl( binaryForm, offset + saclOffset );
            } 
            else
            { 
                sacl = null; 
            }
 
            //
            // Extract the DACL
            //
 
            int daclOffset = UnmarshalInt( binaryForm, offset + DaclFoundAt );
 
            if ((( flags & ControlFlags.DiscretionaryAclPresent ) != 0 ) && 
                daclOffset != 0 )
            { 
                dacl = new RawAcl( binaryForm, offset + daclOffset );
            }
            else
            { 
                dacl = null;
            } 
 
            //
            // Create the resulting security descriptor 
            //

            CreateFromParts( flags, owner, group, sacl, dacl );
 
            //
            // In the offchance that the flags indicate that the rmControl 
            // field is meaningful, remember what was there. 
            //
 
            if (( flags & ControlFlags.RMControlValid ) != 0 )
            {
                ResourceManagerControl = rmControl;
            } 
        }
 
        #endregion 

        #region Static Methods 

        [System.Security.SecurityCritical]  // auto-generated
        private static byte[] BinaryFormFromSddlForm( string sddlForm )
        { 
            if ( sddlForm == null )
            { 
                throw new ArgumentNullException( "sddlForm" ); 
            }
            Contract.EndContractBlock(); 

            int error;
            IntPtr byteArray = IntPtr.Zero;
            uint byteArraySize = 0; 
            const System.Int32 TRUE = 1;
            byte[] binaryForm = null; 
 
            try
            { 
                if ( TRUE != Win32Native.ConvertStringSdToSd(
                        sddlForm,
                        GenericSecurityDescriptor.Revision,
                        out byteArray, 
                        ref byteArraySize ))
                { 
                    error = Marshal.GetLastWin32Error(); 

                    if ( error == Win32Native.ERROR_INVALID_PARAMETER || 
                        error == Win32Native.ERROR_INVALID_ACL ||
                        error == Win32Native.ERROR_INVALID_SECURITY_DESCR ||
                        error == Win32Native.ERROR_UNKNOWN_REVISION )
                    { 
                        throw new ArgumentException(
                            Environment.GetResourceString( "ArgumentException_InvalidSDSddlForm" ), 
                            "sddlForm" ); 
                    }
                    else if ( error == Win32Native.ERROR_NOT_ENOUGH_MEMORY ) 
                    {
                        throw new OutOfMemoryException();
                    }
                    else if ( error == Win32Native.ERROR_INVALID_SID ) 
                    {
                        throw new ArgumentException( 
                            Environment.GetResourceString( "AccessControl_InvalidSidInSDDLString" ), 
                            "sddlForm" );
                    } 
                    else if ( error != Win32Native.ERROR_SUCCESS )
                    {
                        Contract.Assert( false, string.Format( CultureInfo.InvariantCulture, "Unexpected error out of Win32.ConvertStringSdToSd: {0}", error ));
                        throw new SystemException(); 
                    }
                } 
 
                binaryForm = new byte[byteArraySize];
 
                //
                // Extract the data from the returned pointer
                //
 
                Marshal.Copy( byteArray, binaryForm, 0, ( int )byteArraySize );
            } 
            finally 
            {
                // 
                // Now is a good time to get rid of the returned pointer
                //
                if (byteArray != IntPtr.Zero)
                { 
                    Win32Native.LocalFree( byteArray );
                } 
            } 

            return binaryForm; 
        }

        #endregion
 
        #region Public Properties
 
        // 
        // Allows retrieving the control bits for this security descriptor
        // Important: Special checks must be applied when setting flags and not 
        // all flags can be set (for instance, we only deal with self-relative
        // security descriptors), thus flags can be set through other methods.
        //
 
        public override ControlFlags ControlFlags
        { 
            get 
            {
                return _flags; 
            }
        }

        // 
        // Allows retrieving and setting the owner SID for this security descriptor
        // 
 
        public override SecurityIdentifier Owner
        { 
            get
            {
                return _owner;
            } 

            set 
            { 
                _owner = value;
            } 
        }

        //
        // Allows retrieving and setting the group SID for this security descriptor 
        //
 
        public override SecurityIdentifier Group 
        {
            get 
            {
                return _group;
            }
 
            set
            { 
                _group = value; 
            }
        } 

        //
        // Allows retrieving and setting the SACL for this security descriptor
        // 

        public RawAcl SystemAcl 
        { 
            get
            { 
                return _sacl;
            }

            set 
            {
                _sacl = value; 
            } 
        }
 
        //
        // Allows retrieving and setting the DACL for this security descriptor
        //
 
        public RawAcl DiscretionaryAcl
        { 
            get 
            {
                return _dacl; 
            }

            set
            { 
                _dacl = value;
            } 
        } 

        // 
        // CORNER CASE (LEGACY)
        // The ostensibly "reserved" field in the Security Descriptor header
        // can in fact be used by obscure resource managers which in this
        // case must set the RMControlValid flag. 
        //
 
        public byte ResourceManagerControl 
        {
            get 
            {
                return _rmControl;
            }
 
            set
            { 
                _rmControl = value; 
            }
        } 


        #endregion
 
        #region Public Methods
 
        public void SetFlags( ControlFlags flags ) 
        {
            // 
            // We can not deal with non-self-relative descriptors
            // so just forget about it
            //
 
            _flags = ( flags | ControlFlags.SelfRelative );
        } 
 
        #endregion
    } 


    public sealed class CommonSecurityDescriptor : GenericSecurityDescriptor
    { 
        #region Private Members
 
        bool _isContainer; 
        bool _isDS;
        private RawSecurityDescriptor _rawSd; 
        private SystemAcl _sacl;
        private DiscretionaryAcl _dacl;

 
        #endregion
 
        #region Private Methods 

        private void CreateFromParts( bool isContainer, bool isDS, ControlFlags flags, SecurityIdentifier owner, SecurityIdentifier group, SystemAcl systemAcl, DiscretionaryAcl discretionaryAcl ) 
        {
            if ( systemAcl != null &&
                systemAcl.IsContainer != isContainer )
            { 
                throw new ArgumentException(
                    Environment.GetResourceString( isContainer ? 
                        "AccessControl_MustSpecifyContainerAcl" : 
                        "AccessControl_MustSpecifyLeafObjectAcl" ),
                    "systemAcl" ); 
            }

            if ( discretionaryAcl != null &&
                discretionaryAcl.IsContainer != isContainer ) 
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( isContainer ? 
                        "AccessControl_MustSpecifyContainerAcl" :
                        "AccessControl_MustSpecifyLeafObjectAcl" ), 
                    "discretionaryAcl" );
            }

            _isContainer = isContainer; 

            if ( systemAcl != null && 
                systemAcl.IsDS != isDS ) 
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( isDS ?
                        "AccessControl_MustSpecifyDirectoryObjectAcl" :
                        "AccessControl_MustSpecifyNonDirectoryObjectAcl"),
                    "systemAcl"); 
            }
 
            if ( discretionaryAcl != null && 
                discretionaryAcl.IsDS != isDS )
            { 
                throw new ArgumentException(
                    Environment.GetResourceString( isDS ?
                        "AccessControl_MustSpecifyDirectoryObjectAcl" :
                        "AccessControl_MustSpecifyNonDirectoryObjectAcl"), 
                    "discretionaryAcl");
            } 
 
            _isDS = isDS;
 
            _sacl = systemAcl;

            //
            // Replace null DACL with an allow-all for everyone DACL 
            //
 
            if ( discretionaryAcl == null ) 
            {
                // 
                // to conform to native behavior, we will add allow everyone ace for DACL
                //

                discretionaryAcl = DiscretionaryAcl.CreateAllowEveryoneFullAccess(_isDS, _isContainer); 
            }
 
            _dacl = discretionaryAcl; 

            // 
            // DACL is never null. So always set the flag bit on
            //

            ControlFlags actualFlags = flags | ControlFlags.DiscretionaryAclPresent; 

            // 
            // Keep SACL and the flag bit in [....]. 
            //
 
            if (systemAcl == null)
            {
                unchecked { actualFlags &= ~(ControlFlags.SystemAclPresent); }
            } 
            else
            { 
                actualFlags |= (ControlFlags.SystemAclPresent); 
            }
 
            _rawSd = new RawSecurityDescriptor( actualFlags, owner, group, systemAcl == null ? null : systemAcl.RawAcl, discretionaryAcl.RawAcl );
        }

        #endregion 

        #region Constructors 
 
        //
        // Creates a security descriptor explicitly 
        //

        public CommonSecurityDescriptor( bool isContainer, bool isDS, ControlFlags flags, SecurityIdentifier owner, SecurityIdentifier group, SystemAcl systemAcl, DiscretionaryAcl discretionaryAcl )
        { 
            CreateFromParts( isContainer, isDS, flags, owner, group, systemAcl, discretionaryAcl );
        } 
 
        private CommonSecurityDescriptor( bool isContainer, bool isDS, ControlFlags flags, SecurityIdentifier owner, SecurityIdentifier group, RawAcl systemAcl, RawAcl discretionaryAcl )
            : this( isContainer, isDS, flags, owner, group, systemAcl == null ? null : new SystemAcl( isContainer, isDS, systemAcl ), discretionaryAcl == null ? null : new DiscretionaryAcl( isContainer, isDS, discretionaryAcl )) 
        {
        }

        public CommonSecurityDescriptor( bool isContainer, bool isDS, RawSecurityDescriptor rawSecurityDescriptor ) 
            : this( isContainer, isDS, rawSecurityDescriptor, false )
        { 
        } 

        internal CommonSecurityDescriptor( bool isContainer, bool isDS, RawSecurityDescriptor rawSecurityDescriptor, bool trusted ) 
        {
            if ( rawSecurityDescriptor == null )
            {
                throw new ArgumentNullException( "rawSecurityDescriptor" ); 
            }
            Contract.EndContractBlock(); 
 
            CreateFromParts(
                isContainer, 
                isDS,
                rawSecurityDescriptor.ControlFlags,
                rawSecurityDescriptor.Owner,
                rawSecurityDescriptor.Group, 
                rawSecurityDescriptor.SystemAcl == null ? null : new SystemAcl( isContainer, isDS, rawSecurityDescriptor.SystemAcl, trusted ),
                rawSecurityDescriptor.DiscretionaryAcl == null ? null : new DiscretionaryAcl( isContainer, isDS, rawSecurityDescriptor.DiscretionaryAcl, trusted )); 
        } 

        // 
        // Create a security descriptor from an SDDL string
        //

        [System.Security.SecuritySafeCritical]  // auto-generated 
        public CommonSecurityDescriptor( bool isContainer, bool isDS, string sddlForm )
            : this( isContainer, isDS, new RawSecurityDescriptor( sddlForm ), true ) 
        { 
        }
 
        //
        // Create a security descriptor from its binary representation
        //
 
        public CommonSecurityDescriptor( bool isContainer, bool isDS, byte[] binaryForm, int offset )
            : this( isContainer, isDS, new RawSecurityDescriptor( binaryForm, offset ), true ) 
        { 
        }
 
        #endregion

        #region Protected Properties
 
        internal sealed override GenericAcl GenericSacl
        { 
            get { return _sacl; } 
        }
 
        internal sealed override GenericAcl GenericDacl
        {
            get { return _dacl; }
        } 

        #endregion 
 
        #region Public Properties
 
        public bool IsContainer
        {
            get { return _isContainer; }
        } 

        public bool IsDS 
        { 
            get { return _isDS; }
        } 


        //
        // Allows retrieving the control bits for this security descriptor 
        //
 
        public override ControlFlags ControlFlags 
        {
            get 
            {
                return _rawSd.ControlFlags;
            }
        } 

        // 
        // Allows retrieving and setting the owner SID for this security descriptor 
        //
 
        public override SecurityIdentifier Owner
        {
            get
            { 
                return _rawSd.Owner;
            } 
 
            set
            { 
                _rawSd.Owner = value;
            }
        }
 
        //
        // Allows retrieving and setting the group SID for this security descriptor 
        // 

        public override SecurityIdentifier Group 
        {
            get
            {
                return _rawSd.Group; 
            }
 
            set 
            {
                _rawSd.Group = value; 
            }
        }

 
        public SystemAcl SystemAcl
        { 
            get 
            {
                return _sacl; 
            }

            set
            { 
                if ( value != null )
                { 
                    if ( value.IsContainer != this.IsContainer ) 
                    {
                        throw new ArgumentException( 
                            Environment.GetResourceString( this.IsContainer ?
                                "AccessControl_MustSpecifyContainerAcl" :
                                "AccessControl_MustSpecifyLeafObjectAcl" ),
                            "value" ); 
                    }
 
                    if ( value.IsDS != this.IsDS ) 
                    {
                        throw new ArgumentException( 
                            Environment.GetResourceString(this.IsDS ?
                                "AccessControl_MustSpecifyDirectoryObjectAcl" :
                                "AccessControl_MustSpecifyNonDirectoryObjectAcl"),
                            "value"); 
                    }
                } 
 
                _sacl = value;
 
                if ( _sacl != null )
                {
                    _rawSd.SystemAcl = _sacl.RawAcl;
                    AddControlFlags( ControlFlags.SystemAclPresent ); 
                }
                else 
                { 
                    _rawSd.SystemAcl = null;
                    RemoveControlFlags( ControlFlags.SystemAclPresent ); 
                }
            }
        }
 
        //
        // Allows retrieving and setting the DACL for this security descriptor 
        // 

        public DiscretionaryAcl DiscretionaryAcl 
        {
            get
            {
                return _dacl; 
            }
 
            set 
            {
                if ( value != null ) 
                {
                    if ( value.IsContainer != this.IsContainer )
                    {
                        throw new ArgumentException( 
                            Environment.GetResourceString( this.IsContainer ?
                                "AccessControl_MustSpecifyContainerAcl" : 
                                "AccessControl_MustSpecifyLeafObjectAcl" ), 
                            "value" );
                    } 

                    if ( value.IsDS != this.IsDS )
                    {
                        throw new ArgumentException( 
                            Environment.GetResourceString( this.IsDS ?
                                "AccessControl_MustSpecifyDirectoryObjectAcl" : 
                                "AccessControl_MustSpecifyNonDirectoryObjectAcl"), 
                            "value");
                    } 
                }

                //
                // NULL DACLs are replaced with allow everyone full access DACLs. 
                //
 
                if ( value == null ) 
                {
                    _dacl = DiscretionaryAcl.CreateAllowEveryoneFullAccess(IsDS, IsContainer); 
                }
                else
                {
                    _dacl = value; 
                }
 
                _rawSd.DiscretionaryAcl = _dacl.RawAcl; 
                AddControlFlags( ControlFlags.DiscretionaryAclPresent );
            } 
        }

        public bool IsSystemAclCanonical
        { 
            get { return ( SystemAcl == null || SystemAcl.IsCanonical ); }
        } 
 
        public bool IsDiscretionaryAclCanonical
        { 
            get { return ( DiscretionaryAcl == null || DiscretionaryAcl.IsCanonical ); }
        }

        #endregion 

        #region Public Methods 
 
        public void SetSystemAclProtection( bool isProtected, bool preserveInheritance )
        { 
            if ( !isProtected )
            {
                RemoveControlFlags( ControlFlags.SystemAclProtected );
            } 
            else
            { 
                if ( !preserveInheritance && SystemAcl != null ) 
                {
                    SystemAcl.RemoveInheritedAces(); 
                }

                AddControlFlags( ControlFlags.SystemAclProtected );
            } 
        }
 
        public void SetDiscretionaryAclProtection( bool isProtected, bool preserveInheritance ) 
        {
            if ( !isProtected ) 
            {
                RemoveControlFlags( ControlFlags.DiscretionaryAclProtected );
            }
            else 
            {
                if ( !preserveInheritance && DiscretionaryAcl != null ) 
                { 
                    DiscretionaryAcl.RemoveInheritedAces();
                } 

                AddControlFlags( ControlFlags.DiscretionaryAclProtected );
            }
            if (DiscretionaryAcl != null && DiscretionaryAcl.EveryOneFullAccessForNullDacl) 
            {
                DiscretionaryAcl.EveryOneFullAccessForNullDacl = false; 
            } 
        }
 
        public void PurgeAccessControl( SecurityIdentifier sid )
        {
            if ( sid == null )
            { 
                throw new ArgumentNullException( "sid" );
            } 
            Contract.EndContractBlock(); 

            if ( DiscretionaryAcl != null ) 
            {
                DiscretionaryAcl.Purge( sid );
            }
        } 

        public void PurgeAudit( SecurityIdentifier sid ) 
        { 
            if ( sid == null )
            { 
                throw new ArgumentNullException( "sid" );
            }
            Contract.EndContractBlock();
 
            if ( SystemAcl != null )
            { 
                SystemAcl.Purge( sid ); 
            }
        } 

        #endregion

        #region internal Methods 
        internal void UpdateControlFlags(ControlFlags flagsToUpdate, ControlFlags newFlags)
        { 
            ControlFlags finalFlags = newFlags | (_rawSd.ControlFlags & (~flagsToUpdate)); 
            _rawSd.SetFlags(finalFlags);
        } 

        //
        // These two add/remove method must be called with great care (and thus it is internal)
        // The caller is responsible for keeping the SaclPresent and DaclPresent bits in [....] 
        // with the actual SACL and DACL.
        // 
 
        internal void AddControlFlags(ControlFlags flags)
        { 
            _rawSd.SetFlags(_rawSd.ControlFlags | flags);
        }

        internal void RemoveControlFlags(ControlFlags flags) 
        {
            unchecked 
            { 
                _rawSd.SetFlags(_rawSd.ControlFlags & ~flags);
            } 
        }

        internal bool IsSystemAclPresent
        { 
            get
            { 
                return (_rawSd.ControlFlags & ControlFlags.SystemAclPresent) != 0; 
            }
        } 

        internal bool IsDiscretionaryAclPresent
        {
            get 
            {
                return (_rawSd.ControlFlags & ControlFlags.DiscretionaryAclPresent) != 0; 
            } 
        }
        #endregion 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
** 
** Classes:  Security Descriptor family of classes 
**
** 
===========================================================*/

using Microsoft.Win32;
using System; 
using System.Runtime.InteropServices;
using System.Security.Principal; 
using System.Globalization; 
using System.Diagnostics.Contracts;
 
namespace System.Security.AccessControl
{
    [Flags]
 
    public enum ControlFlags
    { 
        None                                = 0x0000, 
        OwnerDefaulted                      = 0x0001, // set by RM only
        GroupDefaulted                      = 0x0002, // set by RM only 
        DiscretionaryAclPresent             = 0x0004, // set by RM or user, 'off' means DACL is null
        DiscretionaryAclDefaulted           = 0x0008, // set by RM only
        SystemAclPresent                    = 0x0010, // same as DiscretionaryAclPresent
        SystemAclDefaulted                  = 0x0020, // sams as DiscretionaryAclDefaulted 
        DiscretionaryAclUntrusted           = 0x0040, // ignore this one
        ServerSecurity                      = 0x0080, // ignore this one 
        DiscretionaryAclAutoInheritRequired = 0x0100, // ignore this one 
        SystemAclAutoInheritRequired        = 0x0200, // ignore this one
        DiscretionaryAclAutoInherited       = 0x0400, // set by RM only 
        SystemAclAutoInherited              = 0x0800, // set by RM only
        DiscretionaryAclProtected           = 0x1000, // when set, RM will stop inheriting
        SystemAclProtected                  = 0x2000, // when set, RM will stop inheriting
        RMControlValid                      = 0x4000, // the reserved 8 bits have some meaning 
        SelfRelative                        = 0x8000, // must always be on
    } 
 

    public abstract class GenericSecurityDescriptor 
    {
        #region Protected Members

        // 
        // Pictorially the structure of a security descriptor is as follows:
        // 
        //       3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 
        //       1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
        //      +---------------------------------------------------------------+ 
        //      |            Control            |Reserved1 (SBZ)|   Revision    |
        //      +---------------------------------------------------------------+
        //      |                            Owner                              |
        //      +---------------------------------------------------------------+ 
        //      |                            Group                              |
        //      +----------------------------------------------------------------+ 
        //      |                            Sacl                               | 
        //      +---------------------------------------------------------------+
        //      |                            Dacl                               | 
        //      +----------------------------------------------------------------+
        //

        internal const int HeaderLength = 20; 
        internal const int OwnerFoundAt = 4;
        internal const int GroupFoundAt = 8; 
        internal const int SaclFoundAt = 12; 
        internal const int DaclFoundAt = 16;
 
        #endregion

        #region Private Methods
 
        //
        // Stores an integer in big-endian format into an array at a given offset 
        // 

        private static void MarshalInt( byte[] binaryForm, int offset, int number ) 
        {
            binaryForm[offset + 0] = ( byte )( number >> 0 );
            binaryForm[offset + 1] = ( byte )( number >> 8 );
            binaryForm[offset + 2] = ( byte )( number >> 16 ); 
            binaryForm[offset + 3] = ( byte )( number >> 24 );
        } 
 
        //
        // Retrieves an integer stored in big-endian format at a given offset in an array 
        //

        internal static int UnmarshalInt( byte[] binaryForm, int offset )
        { 
            return (int)(
                ( binaryForm[offset + 0] <<  0 ) + 
                ( binaryForm[offset + 1] <<  8 ) + 
                ( binaryForm[offset + 2] << 16 ) +
                ( binaryForm[offset + 3] << 24 )); 
        }

        #endregion
 
        #region Constructors
 
        protected GenericSecurityDescriptor() 
        { }
 
        #endregion

        #region Protected Properties
 
        //
        // Marshaling logic requires calling into the derived 
        // class to obtain pointers to SACL and DACL 
        //
 
        internal abstract GenericAcl GenericSacl { get; }
        internal abstract GenericAcl GenericDacl { get; }
        private bool IsCraftedAefaDacl
        { 
            get
            { 
                return  (GenericDacl is DiscretionaryAcl) && (GenericDacl as DiscretionaryAcl).EveryOneFullAccessForNullDacl; 
            }
        } 

        #endregion

        #region Public Properties 

        public static bool IsSddlConversionSupported() 
        { 
            return true; // SDDL to binary conversions are supported on Windows 2000 and higher
        } 

        public static byte Revision
        {
            get { return 1; } 
        }
 
        // 
        // Allows retrieving and setting the control bits for this security descriptor
        // 

        public abstract ControlFlags ControlFlags { get; }

        // 
        // Allows retrieving and setting the owner SID for this security descriptor
        // 
 
        public abstract SecurityIdentifier Owner { get; set; }
 
        //
        // Allows retrieving and setting the group SID for this security descriptor
        //
 
        public abstract SecurityIdentifier Group { get; set; }
 
        // 
        // Retrieves the length of the binary representation
        // of the security descriptor 
        //

        public int BinaryLength
        { 
            get
            { 
                int result = HeaderLength; 

                if ( Owner != null ) 
                {
                    result += Owner.BinaryLength;
                }
 
                if ( Group != null )
                { 
                    result += Group.BinaryLength; 
                }
 
                if (( ControlFlags & ControlFlags.SystemAclPresent ) != 0 &&
                    GenericSacl != null )
                {
                    result += GenericSacl.BinaryLength; 
                }
 
                if (( ControlFlags & ControlFlags.DiscretionaryAclPresent ) != 0 && 
                    GenericDacl != null && !IsCraftedAefaDacl)
                { 
                    result += GenericDacl.BinaryLength;
                }

                return result; 
            }
        } 
 
        #endregion
 
        #region Public Methods

        //
        // Converts the security descriptor to its SDDL form 
        //
 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        public string GetSddlForm( AccessControlSections includeSections )
        { 
            byte[] binaryForm = new byte[BinaryLength];
            string resultSddl;
            int error;
 
            GetBinaryForm( binaryForm, 0 );
 
            SecurityInfos flags = 0; 

            if (( includeSections & AccessControlSections.Owner ) != 0 ) 
            {
                flags |= SecurityInfos.Owner;
            }
 
            if (( includeSections & AccessControlSections.Group ) != 0 )
            { 
                flags |= SecurityInfos.Group; 
            }
 
            if (( includeSections & AccessControlSections.Audit ) != 0 )
            {
                flags |= SecurityInfos.SystemAcl;
            } 

            if (( includeSections & AccessControlSections.Access ) != 0 ) 
            { 
                flags |= SecurityInfos.DiscretionaryAcl;
            } 

            error = Win32.ConvertSdToSddl( binaryForm, 1, flags, out resultSddl );

            if ( error == Win32Native.ERROR_INVALID_PARAMETER || 
                error == Win32Native.ERROR_UNKNOWN_REVISION )
            { 
                // 
                // Indicates that the marshaling logic in GetBinaryForm is busted
                // 

                Contract.Assert( false, "binaryForm produced invalid output" );
                throw new InvalidOperationException();
            } 
            else if ( error != Win32Native.ERROR_SUCCESS )
            { 
                Contract.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.ConvertSdToSddl returned {0}", error )); 
                throw new InvalidOperationException();
            } 

            return resultSddl;
        }
 
        //
        // Converts the security descriptor to its binary form 
        // 

        public void GetBinaryForm( byte[] binaryForm, int offset ) 
        {
            if ( binaryForm == null )
            {
                throw new ArgumentNullException( "binaryForm" ); 
            }
 
            if ( offset < 0 ) 
            {
                throw new ArgumentOutOfRangeException("offset", 
                    Environment.GetResourceString( "ArgumentOutOfRange_NeedNonNegNum" ));
            }

            if ( binaryForm.Length - offset < BinaryLength ) 
            {
                throw new ArgumentOutOfRangeException( 
                    "binaryForm", 
                    Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" ));
            } 
            Contract.EndContractBlock();

            //
            // the offset will grow as we go for each additional field (owner, group, 
            // acl, etc) being written. But for each of such fields, we must use the
            // original offset as passed in, not the growing offset 
            // 

            int originalOffset = offset; 

            //
            // Populate the header
            // 

            int length = BinaryLength; 
 
            byte rmControl =
                (( this is RawSecurityDescriptor ) && 
                 (( ControlFlags & ControlFlags.RMControlValid ) != 0 )) ? (( this as RawSecurityDescriptor ).ResourceManagerControl ) : ( byte )0;

            // if the DACL is our internally crafted NULL replacement, then let us turn off this control
            int materializedControlFlags = ( int )ControlFlags; 
            if (IsCraftedAefaDacl)
            { 
                unchecked {materializedControlFlags &= ~((int)ControlFlags.DiscretionaryAclPresent);} 
            }
 
            binaryForm[offset + 0] = Revision;
            binaryForm[offset + 1] = rmControl;
            binaryForm[offset + 2] = ( byte )(( int )materializedControlFlags >> 0 );
            binaryForm[offset + 3] = ( byte )(( int )materializedControlFlags >> 8 ); 

            // 
            // Compute offsets at which owner, group, SACL and DACL are stored 
            //
 
            int ownerOffset, groupOffset, saclOffset, daclOffset;

            ownerOffset = offset + OwnerFoundAt;
            groupOffset = offset + GroupFoundAt; 
            saclOffset = offset + SaclFoundAt;
            daclOffset = offset + DaclFoundAt; 
 
            offset += HeaderLength;
 
            //
            // Marhsal the Owner SID into place
            //
 
            if ( Owner != null )
            { 
                MarshalInt( binaryForm, ownerOffset, offset - originalOffset ); 
                Owner.GetBinaryForm( binaryForm, offset );
                offset += Owner.BinaryLength; 
            }
            else
            {
                // 
                // If Owner SID is null, store 0 in the offset field
                // 
 
                MarshalInt( binaryForm, ownerOffset, 0 );
            } 

            //
            // Marshal the Group SID into place
            // 

            if ( Group != null ) 
            { 
                MarshalInt( binaryForm, groupOffset, offset - originalOffset );
                Group.GetBinaryForm( binaryForm, offset ); 
                offset += Group.BinaryLength;
            }
            else
            { 
                //
                // If Group SID is null, store 0 in the offset field 
                // 

                MarshalInt( binaryForm, groupOffset, 0 ); 
            }

            //
            // Marshal the SACL into place, if present 
            //
 
            if (( ControlFlags & ControlFlags.SystemAclPresent ) != 0 && 
                GenericSacl != null )
            { 
                MarshalInt( binaryForm, saclOffset, offset - originalOffset );
                GenericSacl.GetBinaryForm( binaryForm, offset );
                offset += GenericSacl.BinaryLength;
            } 
            else
            { 
                // 
                // If SACL is null or not present, store 0 in the offset field
                // 

                MarshalInt( binaryForm, saclOffset, 0 );
            }
 
            //
            // Marshal the DACL into place, if present 
            // 

            if (( ControlFlags & ControlFlags.DiscretionaryAclPresent ) != 0 && 
                GenericDacl != null && !IsCraftedAefaDacl )
            {
                MarshalInt( binaryForm, daclOffset, offset - originalOffset );
                GenericDacl.GetBinaryForm( binaryForm, offset ); 
                offset += GenericDacl.BinaryLength;
            } 
            else 
            {
                // 
                // If DACL is null or not present, store 0 in the offset field
                //

                MarshalInt( binaryForm, daclOffset, 0 ); 
            }
        } 
 
        #endregion
    } 


    public sealed class RawSecurityDescriptor : GenericSecurityDescriptor
    { 
        #region Private Members
 
        private SecurityIdentifier _owner; 
        private SecurityIdentifier _group;
        private ControlFlags _flags; 
        private RawAcl _sacl;
        private RawAcl _dacl;
        private byte _rmControl; // the not-so-reserved SBZ1 field
 
        #endregion
 
        #region Protected Properties 

        internal override GenericAcl GenericSacl 
        {
            get { return _sacl; }
        }
 
        internal override GenericAcl GenericDacl
        { 
            get { return _dacl; } 
        }
 
        #endregion

        #region Private methods
 
        private void CreateFromParts( ControlFlags flags, SecurityIdentifier owner, SecurityIdentifier group, RawAcl systemAcl, RawAcl discretionaryAcl )
        { 
            SetFlags( flags ); 
            Owner = owner;
            Group = group; 
            SystemAcl = systemAcl;
            DiscretionaryAcl = discretionaryAcl;
            ResourceManagerControl = 0;
        } 

        #endregion 
 
        #region Constructors
 
        //
        // Creates a security descriptor explicitly
        //
 
        public RawSecurityDescriptor( ControlFlags flags, SecurityIdentifier owner, SecurityIdentifier group, RawAcl systemAcl, RawAcl discretionaryAcl )
            : base() 
        { 
            CreateFromParts( flags, owner, group, systemAcl, discretionaryAcl );
        } 

        //
        // Creates a security descriptor from an SDDL string
        // 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        public RawSecurityDescriptor( string sddlForm ) 
            : this( BinaryFormFromSddlForm( sddlForm ), 0 )
        { 
        }

        //
        // Creates a security descriptor from its binary representation 
        // Important: the representation must be in self-relative format
        // 
 
        public RawSecurityDescriptor( byte[] binaryForm, int offset )
            : base() 
        {
            //
            // The array passed in must be valid
            // 

            if ( binaryForm == null ) 
            { 
                throw new ArgumentNullException( "binaryForm" );
            } 

            if ( offset < 0 )
            {
                // 
                // Offset must not be negative
                // 
 
                throw new ArgumentOutOfRangeException("offset",
                    Environment.GetResourceString( "ArgumentOutOfRange_NeedNonNegNum" )); 
            }

            //
            // At least make sure the header is in place 
            //
 
            if ( binaryForm.Length - offset < HeaderLength ) 
            {
                throw new ArgumentOutOfRangeException( 
                    "binaryForm",
                    Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" ));
            }
 
            //
            // We only understand revision-1 security descriptors 
            // 

            if ( binaryForm[offset + 0] != Revision ) 
            {
                throw new ArgumentOutOfRangeException("binaryForm",
                    Environment.GetResourceString( "AccessControl_InvalidSecurityDescriptorRevision" ));
            } 
            Contract.EndContractBlock();
 
 
            ControlFlags flags;
            SecurityIdentifier owner, group; 
            RawAcl sacl, dacl;
            byte rmControl;

            // 
            // Extract the ResourceManagerControl field
            // 
 
            rmControl = binaryForm[offset + 1];
 
            //
            // Extract the control flags
            //
 
            flags = ( ControlFlags )(( binaryForm[offset + 2] << 0 ) + ( binaryForm[offset + 3] << 8 ));
 
            // 
            // Make sure that the input is in self-relative format
            // 

            if (( flags & ControlFlags.SelfRelative ) == 0 )
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( "AccessControl_InvalidSecurityDescriptorSelfRelativeForm" ),
                    "binaryForm" ); 
            } 

            // 
            // Extract the owner SID
            //

            int ownerOffset = UnmarshalInt( binaryForm, offset + OwnerFoundAt ); 

            if ( ownerOffset != 0 ) 
            { 
                owner = new SecurityIdentifier( binaryForm, offset + ownerOffset );
            } 
            else
            {
                owner = null;
            } 

            // 
            // Extract the group SID 
            //
 
            int groupOffset = UnmarshalInt( binaryForm, offset + GroupFoundAt );

            if ( groupOffset != 0 )
            { 
                group = new SecurityIdentifier( binaryForm, offset + groupOffset );
            } 
            else 
            {
                group = null; 
            }

            //
            // Extract the SACL 
            //
 
            int saclOffset = UnmarshalInt( binaryForm, offset + SaclFoundAt ); 

            if ((( flags & ControlFlags.SystemAclPresent ) != 0 ) && 
                saclOffset != 0 )
            {
                sacl = new RawAcl( binaryForm, offset + saclOffset );
            } 
            else
            { 
                sacl = null; 
            }
 
            //
            // Extract the DACL
            //
 
            int daclOffset = UnmarshalInt( binaryForm, offset + DaclFoundAt );
 
            if ((( flags & ControlFlags.DiscretionaryAclPresent ) != 0 ) && 
                daclOffset != 0 )
            { 
                dacl = new RawAcl( binaryForm, offset + daclOffset );
            }
            else
            { 
                dacl = null;
            } 
 
            //
            // Create the resulting security descriptor 
            //

            CreateFromParts( flags, owner, group, sacl, dacl );
 
            //
            // In the offchance that the flags indicate that the rmControl 
            // field is meaningful, remember what was there. 
            //
 
            if (( flags & ControlFlags.RMControlValid ) != 0 )
            {
                ResourceManagerControl = rmControl;
            } 
        }
 
        #endregion 

        #region Static Methods 

        [System.Security.SecurityCritical]  // auto-generated
        private static byte[] BinaryFormFromSddlForm( string sddlForm )
        { 
            if ( sddlForm == null )
            { 
                throw new ArgumentNullException( "sddlForm" ); 
            }
            Contract.EndContractBlock(); 

            int error;
            IntPtr byteArray = IntPtr.Zero;
            uint byteArraySize = 0; 
            const System.Int32 TRUE = 1;
            byte[] binaryForm = null; 
 
            try
            { 
                if ( TRUE != Win32Native.ConvertStringSdToSd(
                        sddlForm,
                        GenericSecurityDescriptor.Revision,
                        out byteArray, 
                        ref byteArraySize ))
                { 
                    error = Marshal.GetLastWin32Error(); 

                    if ( error == Win32Native.ERROR_INVALID_PARAMETER || 
                        error == Win32Native.ERROR_INVALID_ACL ||
                        error == Win32Native.ERROR_INVALID_SECURITY_DESCR ||
                        error == Win32Native.ERROR_UNKNOWN_REVISION )
                    { 
                        throw new ArgumentException(
                            Environment.GetResourceString( "ArgumentException_InvalidSDSddlForm" ), 
                            "sddlForm" ); 
                    }
                    else if ( error == Win32Native.ERROR_NOT_ENOUGH_MEMORY ) 
                    {
                        throw new OutOfMemoryException();
                    }
                    else if ( error == Win32Native.ERROR_INVALID_SID ) 
                    {
                        throw new ArgumentException( 
                            Environment.GetResourceString( "AccessControl_InvalidSidInSDDLString" ), 
                            "sddlForm" );
                    } 
                    else if ( error != Win32Native.ERROR_SUCCESS )
                    {
                        Contract.Assert( false, string.Format( CultureInfo.InvariantCulture, "Unexpected error out of Win32.ConvertStringSdToSd: {0}", error ));
                        throw new SystemException(); 
                    }
                } 
 
                binaryForm = new byte[byteArraySize];
 
                //
                // Extract the data from the returned pointer
                //
 
                Marshal.Copy( byteArray, binaryForm, 0, ( int )byteArraySize );
            } 
            finally 
            {
                // 
                // Now is a good time to get rid of the returned pointer
                //
                if (byteArray != IntPtr.Zero)
                { 
                    Win32Native.LocalFree( byteArray );
                } 
            } 

            return binaryForm; 
        }

        #endregion
 
        #region Public Properties
 
        // 
        // Allows retrieving the control bits for this security descriptor
        // Important: Special checks must be applied when setting flags and not 
        // all flags can be set (for instance, we only deal with self-relative
        // security descriptors), thus flags can be set through other methods.
        //
 
        public override ControlFlags ControlFlags
        { 
            get 
            {
                return _flags; 
            }
        }

        // 
        // Allows retrieving and setting the owner SID for this security descriptor
        // 
 
        public override SecurityIdentifier Owner
        { 
            get
            {
                return _owner;
            } 

            set 
            { 
                _owner = value;
            } 
        }

        //
        // Allows retrieving and setting the group SID for this security descriptor 
        //
 
        public override SecurityIdentifier Group 
        {
            get 
            {
                return _group;
            }
 
            set
            { 
                _group = value; 
            }
        } 

        //
        // Allows retrieving and setting the SACL for this security descriptor
        // 

        public RawAcl SystemAcl 
        { 
            get
            { 
                return _sacl;
            }

            set 
            {
                _sacl = value; 
            } 
        }
 
        //
        // Allows retrieving and setting the DACL for this security descriptor
        //
 
        public RawAcl DiscretionaryAcl
        { 
            get 
            {
                return _dacl; 
            }

            set
            { 
                _dacl = value;
            } 
        } 

        // 
        // CORNER CASE (LEGACY)
        // The ostensibly "reserved" field in the Security Descriptor header
        // can in fact be used by obscure resource managers which in this
        // case must set the RMControlValid flag. 
        //
 
        public byte ResourceManagerControl 
        {
            get 
            {
                return _rmControl;
            }
 
            set
            { 
                _rmControl = value; 
            }
        } 


        #endregion
 
        #region Public Methods
 
        public void SetFlags( ControlFlags flags ) 
        {
            // 
            // We can not deal with non-self-relative descriptors
            // so just forget about it
            //
 
            _flags = ( flags | ControlFlags.SelfRelative );
        } 
 
        #endregion
    } 


    public sealed class CommonSecurityDescriptor : GenericSecurityDescriptor
    { 
        #region Private Members
 
        bool _isContainer; 
        bool _isDS;
        private RawSecurityDescriptor _rawSd; 
        private SystemAcl _sacl;
        private DiscretionaryAcl _dacl;

 
        #endregion
 
        #region Private Methods 

        private void CreateFromParts( bool isContainer, bool isDS, ControlFlags flags, SecurityIdentifier owner, SecurityIdentifier group, SystemAcl systemAcl, DiscretionaryAcl discretionaryAcl ) 
        {
            if ( systemAcl != null &&
                systemAcl.IsContainer != isContainer )
            { 
                throw new ArgumentException(
                    Environment.GetResourceString( isContainer ? 
                        "AccessControl_MustSpecifyContainerAcl" : 
                        "AccessControl_MustSpecifyLeafObjectAcl" ),
                    "systemAcl" ); 
            }

            if ( discretionaryAcl != null &&
                discretionaryAcl.IsContainer != isContainer ) 
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( isContainer ? 
                        "AccessControl_MustSpecifyContainerAcl" :
                        "AccessControl_MustSpecifyLeafObjectAcl" ), 
                    "discretionaryAcl" );
            }

            _isContainer = isContainer; 

            if ( systemAcl != null && 
                systemAcl.IsDS != isDS ) 
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( isDS ?
                        "AccessControl_MustSpecifyDirectoryObjectAcl" :
                        "AccessControl_MustSpecifyNonDirectoryObjectAcl"),
                    "systemAcl"); 
            }
 
            if ( discretionaryAcl != null && 
                discretionaryAcl.IsDS != isDS )
            { 
                throw new ArgumentException(
                    Environment.GetResourceString( isDS ?
                        "AccessControl_MustSpecifyDirectoryObjectAcl" :
                        "AccessControl_MustSpecifyNonDirectoryObjectAcl"), 
                    "discretionaryAcl");
            } 
 
            _isDS = isDS;
 
            _sacl = systemAcl;

            //
            // Replace null DACL with an allow-all for everyone DACL 
            //
 
            if ( discretionaryAcl == null ) 
            {
                // 
                // to conform to native behavior, we will add allow everyone ace for DACL
                //

                discretionaryAcl = DiscretionaryAcl.CreateAllowEveryoneFullAccess(_isDS, _isContainer); 
            }
 
            _dacl = discretionaryAcl; 

            // 
            // DACL is never null. So always set the flag bit on
            //

            ControlFlags actualFlags = flags | ControlFlags.DiscretionaryAclPresent; 

            // 
            // Keep SACL and the flag bit in [....]. 
            //
 
            if (systemAcl == null)
            {
                unchecked { actualFlags &= ~(ControlFlags.SystemAclPresent); }
            } 
            else
            { 
                actualFlags |= (ControlFlags.SystemAclPresent); 
            }
 
            _rawSd = new RawSecurityDescriptor( actualFlags, owner, group, systemAcl == null ? null : systemAcl.RawAcl, discretionaryAcl.RawAcl );
        }

        #endregion 

        #region Constructors 
 
        //
        // Creates a security descriptor explicitly 
        //

        public CommonSecurityDescriptor( bool isContainer, bool isDS, ControlFlags flags, SecurityIdentifier owner, SecurityIdentifier group, SystemAcl systemAcl, DiscretionaryAcl discretionaryAcl )
        { 
            CreateFromParts( isContainer, isDS, flags, owner, group, systemAcl, discretionaryAcl );
        } 
 
        private CommonSecurityDescriptor( bool isContainer, bool isDS, ControlFlags flags, SecurityIdentifier owner, SecurityIdentifier group, RawAcl systemAcl, RawAcl discretionaryAcl )
            : this( isContainer, isDS, flags, owner, group, systemAcl == null ? null : new SystemAcl( isContainer, isDS, systemAcl ), discretionaryAcl == null ? null : new DiscretionaryAcl( isContainer, isDS, discretionaryAcl )) 
        {
        }

        public CommonSecurityDescriptor( bool isContainer, bool isDS, RawSecurityDescriptor rawSecurityDescriptor ) 
            : this( isContainer, isDS, rawSecurityDescriptor, false )
        { 
        } 

        internal CommonSecurityDescriptor( bool isContainer, bool isDS, RawSecurityDescriptor rawSecurityDescriptor, bool trusted ) 
        {
            if ( rawSecurityDescriptor == null )
            {
                throw new ArgumentNullException( "rawSecurityDescriptor" ); 
            }
            Contract.EndContractBlock(); 
 
            CreateFromParts(
                isContainer, 
                isDS,
                rawSecurityDescriptor.ControlFlags,
                rawSecurityDescriptor.Owner,
                rawSecurityDescriptor.Group, 
                rawSecurityDescriptor.SystemAcl == null ? null : new SystemAcl( isContainer, isDS, rawSecurityDescriptor.SystemAcl, trusted ),
                rawSecurityDescriptor.DiscretionaryAcl == null ? null : new DiscretionaryAcl( isContainer, isDS, rawSecurityDescriptor.DiscretionaryAcl, trusted )); 
        } 

        // 
        // Create a security descriptor from an SDDL string
        //

        [System.Security.SecuritySafeCritical]  // auto-generated 
        public CommonSecurityDescriptor( bool isContainer, bool isDS, string sddlForm )
            : this( isContainer, isDS, new RawSecurityDescriptor( sddlForm ), true ) 
        { 
        }
 
        //
        // Create a security descriptor from its binary representation
        //
 
        public CommonSecurityDescriptor( bool isContainer, bool isDS, byte[] binaryForm, int offset )
            : this( isContainer, isDS, new RawSecurityDescriptor( binaryForm, offset ), true ) 
        { 
        }
 
        #endregion

        #region Protected Properties
 
        internal sealed override GenericAcl GenericSacl
        { 
            get { return _sacl; } 
        }
 
        internal sealed override GenericAcl GenericDacl
        {
            get { return _dacl; }
        } 

        #endregion 
 
        #region Public Properties
 
        public bool IsContainer
        {
            get { return _isContainer; }
        } 

        public bool IsDS 
        { 
            get { return _isDS; }
        } 


        //
        // Allows retrieving the control bits for this security descriptor 
        //
 
        public override ControlFlags ControlFlags 
        {
            get 
            {
                return _rawSd.ControlFlags;
            }
        } 

        // 
        // Allows retrieving and setting the owner SID for this security descriptor 
        //
 
        public override SecurityIdentifier Owner
        {
            get
            { 
                return _rawSd.Owner;
            } 
 
            set
            { 
                _rawSd.Owner = value;
            }
        }
 
        //
        // Allows retrieving and setting the group SID for this security descriptor 
        // 

        public override SecurityIdentifier Group 
        {
            get
            {
                return _rawSd.Group; 
            }
 
            set 
            {
                _rawSd.Group = value; 
            }
        }

 
        public SystemAcl SystemAcl
        { 
            get 
            {
                return _sacl; 
            }

            set
            { 
                if ( value != null )
                { 
                    if ( value.IsContainer != this.IsContainer ) 
                    {
                        throw new ArgumentException( 
                            Environment.GetResourceString( this.IsContainer ?
                                "AccessControl_MustSpecifyContainerAcl" :
                                "AccessControl_MustSpecifyLeafObjectAcl" ),
                            "value" ); 
                    }
 
                    if ( value.IsDS != this.IsDS ) 
                    {
                        throw new ArgumentException( 
                            Environment.GetResourceString(this.IsDS ?
                                "AccessControl_MustSpecifyDirectoryObjectAcl" :
                                "AccessControl_MustSpecifyNonDirectoryObjectAcl"),
                            "value"); 
                    }
                } 
 
                _sacl = value;
 
                if ( _sacl != null )
                {
                    _rawSd.SystemAcl = _sacl.RawAcl;
                    AddControlFlags( ControlFlags.SystemAclPresent ); 
                }
                else 
                { 
                    _rawSd.SystemAcl = null;
                    RemoveControlFlags( ControlFlags.SystemAclPresent ); 
                }
            }
        }
 
        //
        // Allows retrieving and setting the DACL for this security descriptor 
        // 

        public DiscretionaryAcl DiscretionaryAcl 
        {
            get
            {
                return _dacl; 
            }
 
            set 
            {
                if ( value != null ) 
                {
                    if ( value.IsContainer != this.IsContainer )
                    {
                        throw new ArgumentException( 
                            Environment.GetResourceString( this.IsContainer ?
                                "AccessControl_MustSpecifyContainerAcl" : 
                                "AccessControl_MustSpecifyLeafObjectAcl" ), 
                            "value" );
                    } 

                    if ( value.IsDS != this.IsDS )
                    {
                        throw new ArgumentException( 
                            Environment.GetResourceString( this.IsDS ?
                                "AccessControl_MustSpecifyDirectoryObjectAcl" : 
                                "AccessControl_MustSpecifyNonDirectoryObjectAcl"), 
                            "value");
                    } 
                }

                //
                // NULL DACLs are replaced with allow everyone full access DACLs. 
                //
 
                if ( value == null ) 
                {
                    _dacl = DiscretionaryAcl.CreateAllowEveryoneFullAccess(IsDS, IsContainer); 
                }
                else
                {
                    _dacl = value; 
                }
 
                _rawSd.DiscretionaryAcl = _dacl.RawAcl; 
                AddControlFlags( ControlFlags.DiscretionaryAclPresent );
            } 
        }

        public bool IsSystemAclCanonical
        { 
            get { return ( SystemAcl == null || SystemAcl.IsCanonical ); }
        } 
 
        public bool IsDiscretionaryAclCanonical
        { 
            get { return ( DiscretionaryAcl == null || DiscretionaryAcl.IsCanonical ); }
        }

        #endregion 

        #region Public Methods 
 
        public void SetSystemAclProtection( bool isProtected, bool preserveInheritance )
        { 
            if ( !isProtected )
            {
                RemoveControlFlags( ControlFlags.SystemAclProtected );
            } 
            else
            { 
                if ( !preserveInheritance && SystemAcl != null ) 
                {
                    SystemAcl.RemoveInheritedAces(); 
                }

                AddControlFlags( ControlFlags.SystemAclProtected );
            } 
        }
 
        public void SetDiscretionaryAclProtection( bool isProtected, bool preserveInheritance ) 
        {
            if ( !isProtected ) 
            {
                RemoveControlFlags( ControlFlags.DiscretionaryAclProtected );
            }
            else 
            {
                if ( !preserveInheritance && DiscretionaryAcl != null ) 
                { 
                    DiscretionaryAcl.RemoveInheritedAces();
                } 

                AddControlFlags( ControlFlags.DiscretionaryAclProtected );
            }
            if (DiscretionaryAcl != null && DiscretionaryAcl.EveryOneFullAccessForNullDacl) 
            {
                DiscretionaryAcl.EveryOneFullAccessForNullDacl = false; 
            } 
        }
 
        public void PurgeAccessControl( SecurityIdentifier sid )
        {
            if ( sid == null )
            { 
                throw new ArgumentNullException( "sid" );
            } 
            Contract.EndContractBlock(); 

            if ( DiscretionaryAcl != null ) 
            {
                DiscretionaryAcl.Purge( sid );
            }
        } 

        public void PurgeAudit( SecurityIdentifier sid ) 
        { 
            if ( sid == null )
            { 
                throw new ArgumentNullException( "sid" );
            }
            Contract.EndContractBlock();
 
            if ( SystemAcl != null )
            { 
                SystemAcl.Purge( sid ); 
            }
        } 

        #endregion

        #region internal Methods 
        internal void UpdateControlFlags(ControlFlags flagsToUpdate, ControlFlags newFlags)
        { 
            ControlFlags finalFlags = newFlags | (_rawSd.ControlFlags & (~flagsToUpdate)); 
            _rawSd.SetFlags(finalFlags);
        } 

        //
        // These two add/remove method must be called with great care (and thus it is internal)
        // The caller is responsible for keeping the SaclPresent and DaclPresent bits in [....] 
        // with the actual SACL and DACL.
        // 
 
        internal void AddControlFlags(ControlFlags flags)
        { 
            _rawSd.SetFlags(_rawSd.ControlFlags | flags);
        }

        internal void RemoveControlFlags(ControlFlags flags) 
        {
            unchecked 
            { 
                _rawSd.SetFlags(_rawSd.ControlFlags & ~flags);
            } 
        }

        internal bool IsSystemAclPresent
        { 
            get
            { 
                return (_rawSd.ControlFlags & ControlFlags.SystemAclPresent) != 0; 
            }
        } 

        internal bool IsDiscretionaryAclPresent
        {
            get 
            {
                return (_rawSd.ControlFlags & ControlFlags.DiscretionaryAclPresent) != 0; 
            } 
        }
        #endregion 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

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