/// <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); }