예제 #1
0
        /// <summary>
        /// Returns a value indicating if the principal is authorized for the requested access in any given security descriptor. The access evaluated is the logical concatination of all the supplied security descriptors
        /// </summary>
        /// <param name="securityDescriptors">The security descriptors to check</param>
        /// <param name="requestedAccessMask">The access mask desired</param>
        /// <param name="selfSid">The SID to use when the security descriptor contains the 'SELF' principal</param>
        /// <returns>True if the request is allowed, false if it is denied.</returns>
        public bool AccessCheck(IList <GenericSecurityDescriptor> securityDescriptors, int requestedAccessMask, SecurityIdentifier selfSid)
        {
            if (securityDescriptors == null)
            {
                throw new ArgumentNullException(nameof(securityDescriptors));
            }

            if (securityDescriptors.Count == 0)
            {
                return(false);
            }

            GenericSecurityDescriptor        primarySecurityDescriptor = securityDescriptors[0];
            List <GenericSecurityDescriptor> otherSecurityDescriptors  = securityDescriptors.ToList();

            otherSecurityDescriptors.RemoveAt(0);

            byte[] primarySecurityDescriptorBytes = primarySecurityDescriptor.ToBytes();

            if (primarySecurityDescriptor.Owner == null)
            {
                throw new Win32Exception(87, "The security descriptor must include an owner");
            }

            AuthzAccessRequest request = new AuthzAccessRequest();

            request.PrincipalSelfSid = selfSid?.ToBytes();
            request.DesiredAccess    = requestedAccessMask;

            AuthzAccessReply       reply           = new AuthzAccessReply();
            SafeAllocHGlobalHandle accessMaskReply = new SafeAllocHGlobalHandle(Marshal.SizeOf <uint>());
            SafeAllocHGlobalHandle errorReply      = new SafeAllocHGlobalHandle(Marshal.SizeOf <uint>());
            SafeAllocHGlobalHandle saclReply       = new SafeAllocHGlobalHandle(Marshal.SizeOf <uint>());

            reply.ResultListLength      = 1;
            reply.GrantedAccessMask     = accessMaskReply.DangerousGetHandle();
            reply.SaclEvaluationResults = saclReply.DangerousGetHandle();
            reply.Error = errorReply.DangerousGetHandle();

            IntPtr pOthers     = IntPtr.Zero;
            int    othersCount = otherSecurityDescriptors?.Count ?? 0;

            if (othersCount > 0)
            {
                LpArrayOfByteArrayConverter r = new LpArrayOfByteArrayConverter(otherSecurityDescriptors.Select(t => t.ToBytes()).ToList());
                pOthers = r.Ptr;
            }

            if (!NativeMethods.AuthzAccessCheck(AuthzAccessCheckFlags.None, this.authzContext, ref request, IntPtr.Zero, primarySecurityDescriptorBytes, pOthers, othersCount, ref reply, IntPtr.Zero))
            {
                throw new AuthorizationContextException("AuthzAccessCheck failed", new Win32Exception(Marshal.GetLastWin32Error()));
            }

            int maskResult = Marshal.ReadInt32(reply.GrantedAccessMask);
            int error      = Marshal.ReadInt32(reply.Error);

            if (error == 0)
            {
                return((requestedAccessMask & maskResult) == requestedAccessMask);
            }

            return(false);
        }