Authz.dll引起的非托管内存问题

时间:2019-01-02 20:26:18

标签: c# dllimport authz

在某些情况下,我需要遍历文件系统并计算用户对文件和目录的有效许可,为此,我正在使用以下代码。问题是此代码在我的情况下最多创建2 GB的托管内存。

我已经尝试了所有可能的方法来修复内存泄漏,如代码所示,但是非托管内存仍在增长。请用下面的代码帮助我。我试图通过使用authz内存释放方法来处置对象,但对我没有任何作用。

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace EffectiveRightsUsingAuthzAPI
{
    public class Helper:IDisposable
    {
        [DllImport("advapi32.dll", SetLastError = true)]
        static extern uint GetEffectiveRightsFromAcl(IntPtr pDacl, ref TRUSTEE pTrustee, ref ACCESS_MASK pAccessRights);

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
        struct TRUSTEE
        {
            IntPtr pMultipleTrustee; // must be null
            public int MultipleTrusteeOperation;
            public TRUSTEE_FORM TrusteeForm;
            public TRUSTEE_TYPE TrusteeType;
            [MarshalAs(UnmanagedType.LPStr)]
            public string ptstrName;
        }
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
        public struct LUID
        {
            public uint LowPart;
            public int HighPart;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct AUTHZ_ACCESS_REQUEST
        {
            public int DesiredAccess;
            public byte[] PrincipalSelfSid;
            public OBJECT_TYPE_LIST[] ObjectTypeList;
            public int ObjectTypeListLength;
            public IntPtr OptionalArguments;
        };
        [StructLayout(LayoutKind.Sequential)]
        public struct OBJECT_TYPE_LIST
        {
            OBJECT_TYPE_LEVEL Level;
            int Sbz;
            IntPtr ObjectType;
        };

        [StructLayout(LayoutKind.Sequential)]
        public struct AUTHZ_ACCESS_REPLY
        {
            public int ResultListLength;
            public IntPtr GrantedAccessMask;
            public IntPtr SaclEvaluationResults;
            public IntPtr Error;
        };

        public enum OBJECT_TYPE_LEVEL : int
        {
            ACCESS_OBJECT_GUID = 0,
            ACCESS_PROPERTY_SET_GUID = 1,
            ACCESS_PROPERTY_GUID = 2,
            ACCESS_MAX_LEVEL = 4
        };
        enum TRUSTEE_FORM
        {
            TRUSTEE_IS_SID,
            TRUSTEE_IS_NAME,
            TRUSTEE_BAD_FORM,
            TRUSTEE_IS_OBJECTS_AND_SID,
            TRUSTEE_IS_OBJECTS_AND_NAME
        }

        enum AUTHZ_RM_FLAG : uint
        {
            AUTHZ_RM_FLAG_NO_AUDIT = 1,
            AUTHZ_RM_FLAG_INITIALIZE_UNDER_IMPERSONATION = 2,
            AUTHZ_RM_FLAG_NO_CENTRAL_ACCESS_POLICIES = 4,
        }

        enum TRUSTEE_TYPE
        {
            TRUSTEE_IS_UNKNOWN,
            TRUSTEE_IS_USER,
            TRUSTEE_IS_GROUP,
            TRUSTEE_IS_DOMAIN,
            TRUSTEE_IS_ALIAS,
            TRUSTEE_IS_WELL_KNOWN_GROUP,
            TRUSTEE_IS_DELETED,
            TRUSTEE_IS_INVALID,
            TRUSTEE_IS_COMPUTER
        }

        [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
        static extern uint GetNamedSecurityInfo(
            string pObjectName,
            SE_OBJECT_TYPE ObjectType,
            SECURITY_INFORMATION SecurityInfo,
            out IntPtr pSidOwner,
            out IntPtr pSidGroup,
            out IntPtr pDacl,
            out IntPtr pSacl,
            out IntPtr pSecurityDescriptor);
        [DllImport("authz.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzInitializeContextFromSid", CharSet = CharSet.Unicode)]
        static extern public bool AuthzInitializeContextFromSid(
                                               int Flags,
                                               IntPtr UserSid,
                                               IntPtr AuthzResourceManager,
                                               IntPtr pExpirationTime,
                                               LUID Identitifier,
                                               IntPtr DynamicGroupArgs,
                                               out IntPtr pAuthzClientContext
                                               );



        [DllImport("authz.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzInitializeResourceManager", CharSet = CharSet.Unicode)]
        static extern public bool AuthzInitializeResourceManager(
                                        int flags,
                                        IntPtr pfnAccessCheck,
                                        IntPtr pfnComputeDynamicGroups,
                                        IntPtr pfnFreeDynamicGroups,
                                        string name,
                                        out IntPtr rm
                                        );
        [DllImport("authz.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzFreeResourceManager", CharSet = CharSet.Unicode)]
        static extern public bool AuthzFreeResourceManager(IntPtr hManager);

        [DllImport("authz.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzFreeHandle", CharSet = CharSet.Unicode)]
        static extern public bool AuthzFreeHandle(IntPtr hAccessCheckResults);

        [DllImport("authz.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzFreeContext", CharSet = CharSet.Unicode)]
        static extern public bool AuthzFreeContext(IntPtr hAuthzClientContext);
        [DllImport("authz.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzFreeCentralAccessPolicyCache", CharSet = CharSet.Unicode)]
        static extern public bool AuthzFreeCentralAccessPolicyCache();

        [DllImport("authz.dll", EntryPoint = "AuthzAccessCheck", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
        private static extern bool AuthzAccessCheck(int flags,
                                                    IntPtr hAuthzClientContext,
                                                     ref AUTHZ_ACCESS_REQUEST pRequest,
                                                     IntPtr AuditEvent,
                                                     IntPtr pSecurityDescriptor,
                                                    byte[] OptionalSecurityDescriptorArray,
                                                    int OptionalSecurityDescriptorCount,
                                                    ref AUTHZ_ACCESS_REPLY pReply,
                                                    out IntPtr phAccessCheckResults);

        enum ACCESS_MASK : uint
        {
            FILE_TRAVERSE = 0x20,
            FILE_LIST_DIRECTORY = 0x1,
            FILE_READ_DATA = 0x1,
            FILE_READ_ATTRIBUTES = 0x80,
            FILE_READ_EA = 0x8,
            FILE_ADD_FILE = 0x2,
            FILE_WRITE_DATA = 0x2,
            FILE_ADD_SUBDIRECTORY = 0x4,
            FILE_APPEND_DATA = 0x4,
            FILE_WRITE_ATTRIBUTES = 0x100,
            FILE_WRITE_EA = 0x10,
            FILE_DELETE_CHILD = 0x40,
            DELETE = 0x10000,
            READ_CONTROL = 0x20000,
            WRITE_DAC = 0x40000,
            WRITE_OWNER = 0x80000,


            ////////FILE_EXECUTE =0x20,   
        }

        [Flags]
        enum SECURITY_INFORMATION : uint
        {
            OWNER_SECURITY_INFORMATION = 0x00000001,
            GROUP_SECURITY_INFORMATION = 0x00000002,
            DACL_SECURITY_INFORMATION = 0x00000004,
            SACL_SECURITY_INFORMATION = 0x00000008,
            UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000,
            UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000,
            PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000,
            PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000
        }

        enum SE_OBJECT_TYPE
        {
            SE_UNKNOWN_OBJECT_TYPE = 0,
            SE_FILE_OBJECT,
            SE_SERVICE,
            SE_PRINTER,
            SE_REGISTRY_KEY,
            SE_LMSHARE,
            SE_KERNEL_OBJECT,
            SE_WINDOW_OBJECT,
            SE_DS_OBJECT,
            SE_DS_OBJECT_ALL,
            SE_PROVIDER_DEFINED_OBJECT,
            SE_WMIGUID_OBJECT,
            SE_REGISTRY_WOW64_32KEY
        }



        public PermissionValues GetEffectivePermissions(string UserName, string Path, out string object_sid)
        {
            List<string> result = new List<string>();
            IntPtr pSidOwner, pSidGroup, pDacl, pSacl, pSecurityDescriptor;
            ACCESS_MASK mask = new ACCESS_MASK();
            uint ret = GetNamedSecurityInfo(Path,
                SE_OBJECT_TYPE.SE_FILE_OBJECT,
                SECURITY_INFORMATION.DACL_SECURITY_INFORMATION | SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION | SECURITY_INFORMATION.GROUP_SECURITY_INFORMATION,
                out pSidOwner, out pSidGroup, out pDacl, out pSacl, out pSecurityDescriptor);

            IntPtr hManager = IntPtr.Zero;

            bool f = AuthzInitializeResourceManager(1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, null, out hManager);

            NTAccount ac = new NTAccount(UserName);
            SecurityIdentifier sid;
            if (Imanami.PermissionProvider.FileSystem.Helper.isObjectSID(UserName))
                sid = new SecurityIdentifier(UserName);
            else
                sid = (SecurityIdentifier)ac.Translate(typeof(SecurityIdentifier));
            object_sid = sid.Value;
            byte[] bytes = new byte[sid.BinaryLength];
            sid.GetBinaryForm(bytes, 0);
            String _psUserSid = "";
            foreach (byte si in bytes)
            {
                _psUserSid += si;
            }

            LUID unusedSid = new LUID();
            IntPtr UserSid = Marshal.AllocHGlobal(bytes.Length);
            Marshal.Copy(bytes, 0, UserSid, bytes.Length);
            IntPtr pClientContext = IntPtr.Zero;

            if (f)
            {
                f = AuthzInitializeContextFromSid(0, UserSid, hManager, IntPtr.Zero, unusedSid, IntPtr.Zero, out pClientContext);


                AUTHZ_ACCESS_REQUEST request = new AUTHZ_ACCESS_REQUEST();
                request.DesiredAccess = 0x02000000;
                request.PrincipalSelfSid = null;
                request.ObjectTypeList = null;
                request.ObjectTypeListLength = 0;
                request.OptionalArguments = IntPtr.Zero;

                AUTHZ_ACCESS_REPLY reply = new AUTHZ_ACCESS_REPLY();
                reply.GrantedAccessMask = IntPtr.Zero;
                reply.ResultListLength = 0;
                reply.SaclEvaluationResults = IntPtr.Zero;
                IntPtr AccessReply = IntPtr.Zero;
                reply.Error = Marshal.AllocHGlobal(1020);
                reply.GrantedAccessMask = Marshal.AllocHGlobal(sizeof(uint));
                reply.ResultListLength = 1;
                int i = 0;
                Dictionary<String, String> rightsmap = new Dictionary<String, String>();
                List<string> effectivePermissionList = new List<string>();
                string[] rights = new string[14] { "Full Control", "Traverse Folder / execute file", "List folder / read data", "Read attributes", "Read extended attributes", "Create files / write files", "Create folders / append data", "Write attributes", "Write extended attributes", "Delete subfolders and files", "Delete", "Read permission", "Change permission", "Take ownership" };
                rightsmap.Add("FILE_TRAVERSE", "Traverse Folder / execute file");
                rightsmap.Add("FILE_LIST_DIRECTORY", "List folder / read data");
                rightsmap.Add("FILE_READ_DATA", "List folder / read data");
                rightsmap.Add("FILE_READ_ATTRIBUTES", "Read attributes");
                rightsmap.Add("FILE_READ_EA", "Read extended attributes");
                rightsmap.Add("FILE_ADD_FILE", "Create files / write files");
                rightsmap.Add("FILE_WRITE_DATA", "Create files /  write files");
                rightsmap.Add("FILE_ADD_SUBDIRECTORY", "Create folders / append data");
                rightsmap.Add("FILE_APPEND_DATA", "Create folders / append data");
                rightsmap.Add("FILE_WRITE_ATTRIBUTES", "Write attributes");
                rightsmap.Add("FILE_WRITE_EA", "Write extended attributes");
                rightsmap.Add("FILE_DELETE_CHILD", "Delete subfolders and files");
                rightsmap.Add("DELETE", "Delete");
                rightsmap.Add("READ_CONTROL", "Read permission");
                rightsmap.Add("WRITE_DAC", "Change permission");
                rightsmap.Add("WRITE_OWNER", "Take ownership");


                f = AuthzAccessCheck(0, pClientContext, ref request, IntPtr.Zero, pSecurityDescriptor, null, 0, ref reply, out AccessReply);
                if (f)
                {
                    int granted_access = Marshal.ReadInt32(reply.GrantedAccessMask);

                    mask = (ACCESS_MASK)granted_access;

                    foreach (ACCESS_MASK item in Enum.GetValues(typeof(ACCESS_MASK)))
                    {
                        if ((mask & item) == item)
                        {
                            effectivePermissionList.Add(rightsmap[item.ToString()]);
                            i++;
                        }

                    }
                }
                //Clear Memory
                {
                    Marshal.FreeHGlobal(reply.GrantedAccessMask);
                    if (reply.Error != IntPtr.Zero)
                        Marshal.FreeHGlobal(reply.Error);
                    if (UserSid != IntPtr.Zero)
                        Marshal.FreeHGlobal(UserSid);
                    if (pSidOwner != IntPtr.Zero)
                        Marshal.Release(pSidOwner);
                    if (pSidGroup != IntPtr.Zero)
                        Marshal.Release(pSidGroup);
                    if (pDacl != IntPtr.Zero)
                        Marshal.Release(pDacl);
                    if (pSacl != IntPtr.Zero)
                        Marshal.Release(pSacl);
                    if (pSecurityDescriptor != IntPtr.Zero)
                        Marshal.Release(pSecurityDescriptor);
                    if (reply.SaclEvaluationResults != IntPtr.Zero)
                        Marshal.Release(reply.SaclEvaluationResults);
                    if (request.OptionalArguments != IntPtr.Zero)
                        Marshal.Release(request.OptionalArguments);

                    if (AccessReply != IntPtr.Zero)
                        AuthzFreeHandle(AccessReply);
                    if (hManager != IntPtr.Zero)
                        AuthzFreeResourceManager(hManager);
                    if (pClientContext != IntPtr.Zero)
                        AuthzFreeContext(pClientContext);
                    AuthzFreeCentralAccessPolicyCache();
                }

                if (i == 16)
                {
                    effectivePermissionList.Insert(0, "Full Control");
                    return PermissionValues.FULL_CONTROL;
                }
                PermissionValues per = PermissionValues.NONE;
                foreach (string r in effectivePermissionList)
                {

                    switch (r)
                    {
                        case "Traverse Folder / execute file":
                            per |= PermissionValues.FILE_TRAVERSE;
                            break;
                        case "List folder / read data":
                            per |= PermissionValues.FILE_LIST_DIRECTORY;
                            break;
                        case "Read attributes":
                            per |= PermissionValues.FILE_READ_ATTRIBUTES;
                            break;
                        case "Read extended attributes":
                            per |= PermissionValues.FILE_READ_EA;
                            break;
                        case "Create files / write files":
                            per |= PermissionValues.FILE_ADD_FILE;
                            break;
                        case "Create files /  write files":
                            per |= PermissionValues.FILE_WRITE_DATA;
                            break;
                        case "Create folders / append data":
                            per |= (PermissionValues.FILE_ADD_SUBDIRECTORY | PermissionValues.FILE_APPEND_DATA);
                            break;
                        case "Write attributes":
                            per |= PermissionValues.FILE_WRITE_ATTRIBUTES;
                            break;
                        case "Write extended attributes":
                            per |= PermissionValues.FILE_WRITE_EA;
                            break;
                        case "Delete subfolders and files":
                            per |= PermissionValues.FILE_DELETE_CHILD;
                            break;
                        case "Delete":
                            per |= PermissionValues.DELETE;
                            break;
                        case "Read permission":
                            per |= PermissionValues.READ_CONTROL;
                            break;
                        case "Change permission":
                            per |= PermissionValues.WRITE_DAC;
                            break;
                        case "Take ownership":
                            per |= PermissionValues.WRITE_OWNER;
                            break;
                    }
                }

                //foreach(var obj in request.ObjectTypeList)
                //{

                //}
                return per;

            }

            return PermissionValues.NONE;

        }

        public void Dispose()
        {
            GC.SuppressFinalize(this);
        }
    }
}

0 个答案:

没有答案