// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (c) Microsoft Corporation. All rights reserved using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Security.AccessControl; using System.Security.Principal; using System.Runtime.InteropServices; using System.Text; using System.Linq; using Microsoft.Win32.SafeHandles; namespace Microsoft.Samples.DynamicAccessControl { using Utility; using DWORD = System.UInt32; using ULONG = System.UInt32; using LPVOID = System.IntPtr; using PUCHAR = System.IntPtr; using PDWORD = System.IntPtr; using PSID = System.IntPtr; using PACL = System.IntPtr; using PLARGE_INTEGER = System.IntPtr; using PSECURITY_DESCRIPTOR = System.IntPtr; using AUTHZ_RESOURCE_MANAGER_HANDLE = System.IntPtr; using AUTHZ_CLIENT_CONTEXT_HANDLE = System.IntPtr; using AUTHZ_AUDIT_EVENT_HANDLE = System.IntPtr; using AUTHZ_ACCESS_CHECK_RESULTS_HANDLE = System.IntPtr; using PAUTHZ_RPC_INIT_INFO_CLIENT = System.IntPtr; using POBJECT_TYPE_LIST = System.IntPtr; using PACCESS_MASK = System.IntPtr; internal class EffectiveAccess { #region Constructor public EffectiveAccess(string path, string targetMachine, RawSecurityDescriptor shareSD, SecurityIdentifier userSid, SecurityIdentifier deviceSid, ClaimValueDictionary userClaims, ClaimValueDictionary deviceClaims, GroupsCollection userGroups, GroupsCollection deviceGroups) { if (string.IsNullOrEmpty(targetMachine) && shareSD != null) { throw new ArgumentException("targetMachine must be value when shareSD is not-empty", "targetMachine"); } handle = NativeMethods.CreateFile(path, NativeMethods.FileAccess.GenericRead, NativeMethods.FileShare.Read | NativeMethods.FileShare.Write | NativeMethods.FileShare.Delete, IntPtr.Zero, NativeMethods.FileMode.OpenExisting, NativeMethods.FileFlagAttrib.BackupSemantics, IntPtr.Zero); if (handle.IsInvalid) { throw new Win32Exception(Marshal.GetLastWin32Error()); } this.targetMachine = targetMachine; this.shareSD = shareSD; this.userSid = userSid; this.deviceSid = deviceSid; this.userClaims = userClaims; this.deviceClaims = deviceClaims; this.userGroups = userGroups; this.deviceGroups = deviceGroups; } #endregion #region Public methods /// /// Reports the results of computing effective access for the NTFSAccess list /// /// This methods generates a report in the following format /// /// Permission Access Granted Limited By /// ---------- -------------- ---------- /// Full control [ N ] Share permissions /// Traverse folder / execute file [ N ] File permissions /// List folder / read data [ Y ] - /// Read attributes [ Y ] - /// Read extended attributes [ N ] Central Access Rule Name /// Create files / write data [ N ] Central Policy Name /// Create folders / append data [ Y ] - /// Write attributes [ Y ] - /// Write extended attributes [ Y ] - /// Delete subfolders and files [ Y ] - /// Delete [ Y ] - /// Read permissions [ Y ] - /// Change permissions [ Y ] - /// Take ownership [ Y ] - /// public void GenerateReport() { if (results == null) { return; } int COLUMN1_SPACING = COLUMN_SPACING + Math.Max(HEADER_PERMISSION.Length, MAX_NTFSACCESS_PERM_DESC_WIDTH); int COLUMN2_SPACING = COLUMN_SPACING + HEADER_ACCESS.Length; Console.Write(HEADER_PERMISSION.PadRight(COLUMN1_SPACING)); Console.Write(HEADER_ACCESS.PadRight(COLUMN2_SPACING)); Console.WriteLine(HEADER_LIMITED_BY); Console.Write((new String('-', HEADER_PERMISSION.Length)).PadRight(COLUMN1_SPACING)); Console.Write((new String('-', HEADER_ACCESS.Length)).PadRight(COLUMN2_SPACING)); Console.WriteLine(new String('-', HEADER_LIMITED_BY.Length)); foreach (var permResult in results) { Console.Write(NTFSAccess[permResult.Key].PadRight(COLUMN1_SPACING)); Console.Write((string.IsNullOrEmpty(permResult.Value) ? "[ Y ]" : "[ N ]").PadRight(COLUMN2_SPACING)); Console.WriteLine(string.IsNullOrEmpty(permResult.Value) ? "-" : permResult.Value); } } /// /// Computes effective access rights upon acquiring the necessary security information such as Share's security, /// Central Policy and Resource's security as maybe applicable. /// public void Evaluate() { using (TokenPrivilege seSecurityPrivilege = new TokenPrivilege(TokenPrivilege.Security)) { try { // // SeSecurityPrivilege is required for querying the Central Policy ID (Scope information) from the // file's SD // seSecurityPrivilege.Enable(); var securityObjects = new Dictionary(); // // First include the Share's SD if available. If the share denies a permission, anything else that // denies a permission is of lesser consequence. // if (shareSD != null) { securityObjects.Add("Share", new FileSecurityObject(shareSD)); } SecurityIdentifier capId = null; { RawSecurityDescriptor scopeSD = GetFileSecInfoSD(handle, NativeMethods.SecurityInformationClass.Scope); if (scopeSD != null) { if (scopeSD.SystemAcl != null) { foreach (GenericAce ace in scopeSD.SystemAcl) { // // Scoped Policy ID ACE not yet part of System.Security.AccessControl.AceType // // Since SYSTEM_SCOPED_POLICY_ID_ACE essentially has a SID which is the identifier // for a Central Policy, extract it explicitly. // byte[] rawAce = new byte[ace.BinaryLength]; ace.GetBinaryForm(rawAce, 0); if ((ace.AceFlags & AceFlags.InheritOnly) == 0) { long sidOffset = (long)Marshal.OffsetOf( typeof(NativeMethods.SYSTEM_SCOPED_POLICY_ID_ACE), "SidStart"); if (sidOffset < ace.BinaryLength) { capId = new SecurityIdentifier(rawAce, (int)sidOffset); // // The first Central Policy is the only one honored when there are multiple // in a Security Descriptor. Ignore everything else. // break; } } } } } } // // Obtain file SD // RawSecurityDescriptor fileSD = GetFileSecInfoSD( handle, NativeMethods.SecurityInformationClass.Owner | NativeMethods.SecurityInformationClass.Group | NativeMethods.SecurityInformationClass.Dacl | NativeMethods.SecurityInformationClass.Label | NativeMethods.SecurityInformationClass.Attribute); if (capId != null) { var availableCaps = new AvailableCentralPolicies(targetMachine); Dictionary CARs = availableCaps.FetchCentralAccessRules(capId); if (CARs == null || CARs.Count == 0) { // // If the Central Policy or any of its Central Access Rules could not be retrieved, fall // back to just the granularity of Central Policy. For this, use the file's SD with the // CAP ID. // securityObjects.Add("Central Policy", new FileSecurityObject( GetFileSecInfoSD(handle, NativeMethods.SecurityInformationClass.Owner | NativeMethods.SecurityInformationClass.Group | NativeMethods.SecurityInformationClass.Label | NativeMethods.SecurityInformationClass.Attribute | NativeMethods.SecurityInformationClass.Scope))); } else { // // The merged security descriptor for each Central Access Rule is generated as follows: // Owner + Group + SACL (all from resource's SD) + DACL from Central Access Rule // // If the AppliesTo predicate is present, then we do the following: // Owned + Group + SACL (all from resource's SD) // + A fabricated DACL with an allowed callback ACE containingn the selected user // principal and the AppliesTo predicate appended. // foreach (var rule in CARs) { var sd = new RawSecurityDescriptor(fileSD.ControlFlags, fileSD.Owner, fileSD.Group, fileSD.SystemAcl, rule.Value.EffectivePolicy.DiscretionaryAcl); if (!string.IsNullOrEmpty(rule.Value.AppliesToCondition)) { string appliesToSDDL = "D:(XA;;FR;;;" + userSid.ToString() + ";" + rule.Value.AppliesToCondition + ")"; var appliesToSD = new RawSecurityDescriptor( fileSD.ControlFlags, fileSD.Owner, fileSD.Group, fileSD.SystemAcl, (new RawSecurityDescriptor(appliesToSDDL)).DiscretionaryAcl); securityObjects.Add(rule.Key, new FileSecurityObject(sd, appliesToSD)); } else { securityObjects.Add(rule.Key, new FileSecurityObject(sd)); } } } } securityObjects.Add("File permissions", new FileSecurityObject(fileSD)); results = ComputeEffectiveAccessResult(targetMachine, securityObjects); } finally { seSecurityPrivilege.Revert(); } } } #endregion #region Private implementation /// /// Computes the effective access permissions /// /// User account for which effective access rights are to be determined /// Account to simulate the device where from the resource is being accessed /// Target machine on which the resource /// Security objects that affect that result of the access check /// Dictionary of rights from NTFSAccess and the security object name that limits access to this /// permission Dictionary ComputeEffectiveAccessResult( string serverName, Dictionary securityObjects) { AUTHZ_CLIENT_CONTEXT_HANDLE userClientCtxt = AUTHZ_CLIENT_CONTEXT_HANDLE.Zero; AUTHZ_CLIENT_CONTEXT_HANDLE deviceClientCtxt = AUTHZ_CLIENT_CONTEXT_HANDLE.Zero; AUTHZ_CLIENT_CONTEXT_HANDLE compoundCtxt = AUTHZ_CLIENT_CONTEXT_HANDLE.Zero; try { var rpcInitInfo = new NativeMethods.AUTHZ_RPC_INIT_INFO_CLIENT(); rpcInitInfo.version = NativeMethods.AuthzRpcClientVersion.V1; rpcInitInfo.objectUuid = NativeMethods.AUTHZ_OBJECTUUID_WITHCAP; rpcInitInfo.protocol = NativeMethods.RCP_OVER_TCP_PROTOCOL; rpcInitInfo.server = serverName; SafeAuthzRMHandle authzRM; SafeHGlobalHandle pRpcInitInfo = SafeHGlobalHandle.AllocHGlobalStruct(rpcInitInfo); if (!NativeMethods.AuthzInitializeRemoteResourceManager(pRpcInitInfo.ToIntPtr(), out authzRM)) { int error = Marshal.GetLastWin32Error(); if (error != Win32Error.EPT_S_NOT_REGISTERED) { throw new Win32Exception(error); } // // As a fallback we do AuthzInitializeResourceManager. But the results can be inaccurate. // Helper.LogWarning("The effective rights can only be computed based on group membership on this" + " computer. For more accurate results, calculate effective access rights on " + "the target computer.", true); if (!NativeMethods.AuthzInitializeResourceManager( NativeMethods.AuthzResourceManagerFlags.NO_AUDIT, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, "EffectiveAccessCheck", out authzRM)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } byte[] rawSid = new byte[userSid.BinaryLength]; userSid.GetBinaryForm(rawSid, 0); // // Create an AuthZ context based on the user account // if (!NativeMethods.AuthzInitializeContextFromSid(NativeMethods.AuthzInitFlags.Default, rawSid, authzRM, PLARGE_INTEGER.Zero, Win32.LUID.NullLuid, LPVOID.Zero, out userClientCtxt)) { Win32Exception win32Expn = new Win32Exception(Marshal.GetLastWin32Error()); if (win32Expn.NativeErrorCode != Win32Error.RPC_S_SERVER_UNAVAILABLE) { throw win32Expn; } Helper.LogWarning(string.Format(CultureInfo.CurrentCulture, "{0}. Please enable the inward firewall rule: Netlogon Service " + "Authz(RPC), on the target machine and try again.", win32Expn.Message), true); return null; } // // Create an Authz Compound context based on the userClientCtxt and the device account // if (deviceSid != null) { rawSid = new byte[deviceSid.BinaryLength]; deviceSid.GetBinaryForm(rawSid, 0); if (!NativeMethods.AuthzInitializeContextFromSid(NativeMethods.AuthzInitFlags.Default, rawSid, authzRM, PLARGE_INTEGER.Zero, Win32.LUID.NullLuid, LPVOID.Zero, out deviceClientCtxt)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (!NativeMethods.AuthzInitializeCompoundContext(userClientCtxt, deviceClientCtxt, out compoundCtxt)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } else { compoundCtxt = userClientCtxt; } // // Modify user claims in the Authz context // if (userClaims.Count != 0) { int result = userClaims.ApplyClaims(compoundCtxt); if (result != Win32Error.ERROR_SUCCESS) { throw new Win32Exception(result); } } // // Modify device claims in the Authz context // if (deviceClaims.Count != 0) { int result = deviceClaims.ApplyClaims(compoundCtxt); if (result != Win32Error.ERROR_SUCCESS) { throw new Win32Exception(result); } } // // Include additional group membership in the Authz context // if (userGroups.Count != 0) { int result = userGroups.ApplyGroups(compoundCtxt); if (result != Win32Error.ERROR_SUCCESS) { throw new Win32Exception(result); } } // // Include additional device membership in the Authz context // if (deviceGroups.Count != 0) { int result = deviceGroups.ApplyGroups(compoundCtxt); if (result != Win32Error.ERROR_SUCCESS) { throw new Win32Exception(result); } } PACCESS_MASK[] grantedAccess = new PACCESS_MASK[securityObjects.Count]; PDWORD[] errorSecObj = new PACCESS_MASK[securityObjects.Count]; try { uint Index = 0; foreach (var securityObject in securityObjects) { NativeMethods.AUTHZ_ACCESS_REQUEST request = new NativeMethods.AUTHZ_ACCESS_REQUEST(); request.DesiredAccess = NativeMethods.StdAccess.MAXIMUM_ALLOWED; request.PrincipalSelfSid = null; request.ObjectTypeList = POBJECT_TYPE_LIST.Zero; request.ObjectTypeListLength = 0; request.OptionalArguments = LPVOID.Zero; var reply = new NativeMethods.AUTHZ_ACCESS_REPLY(); reply.ResultListLength = 1; reply.SaclEvaluationResults = PDWORD.Zero; reply.GrantedAccessMask = grantedAccess[Index] = Marshal.AllocHGlobal(sizeof(uint)); reply.Error = errorSecObj[Index] = Marshal.AllocHGlobal(sizeof(uint)); byte[] rawSD = new byte[securityObject.Value.securityDescriptor.BinaryLength]; securityObject.Value.securityDescriptor.GetBinaryForm(rawSD, 0); // // If a security object has the AppliesTo predicate, then we are processing a Central Access // Rule. If the AppliesTo predicate is not satisfied, we do not have to bother performing an // access check on the Central Access Rule's DACL. // if (securityObject.Value.appliesTo != null) { byte[] rawSD2 = new byte[securityObject.Value.appliesTo.BinaryLength]; securityObject.Value.appliesTo.GetBinaryForm(rawSD2, 0); if (!NativeMethods.AuthzAccessCheck(NativeMethods.AuthzACFlags.None, compoundCtxt, ref request, AUTHZ_AUDIT_EVENT_HANDLE.Zero, rawSD2, null, 0, ref reply, AUTHZ_ACCESS_CHECK_RESULTS_HANDLE.Zero)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } // // The applies to DACL is D:(XA;;FR;;;;). // Check if we were successful in acquiring this particular access // var whatWasGranted = (NativeMethods.FileAccess)Marshal.ReadInt32(grantedAccess[Index]); if ((NativeMethods.FileAccess.ReadData & whatWasGranted) == 0) { securityObject.Value.result.grantedAccess = NativeMethods.FileAccess.CategoricalAll; continue; } } if (!NativeMethods.AuthzAccessCheck(NativeMethods.AuthzACFlags.None, compoundCtxt, ref request, AUTHZ_AUDIT_EVENT_HANDLE.Zero, rawSD, null, 0, ref reply, AUTHZ_ACCESS_CHECK_RESULTS_HANDLE.Zero)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } securityObject.Value.result.grantedAccess = (NativeMethods.FileAccess) Marshal.ReadInt32(grantedAccess[Index]); ++Index; } // // Build the effective permission results // var accessLimitedBy = new Dictionary(); foreach (var permission in NTFSAccess) { foreach (var securityObject in securityObjects) { if (!accessLimitedBy.ContainsKey(permission.Key)) { accessLimitedBy.Add(permission.Key, ""); } if ((permission.Key & securityObject.Value.result.grantedAccess) != permission.Key) { if (!string.IsNullOrEmpty(accessLimitedBy[permission.Key])) { accessLimitedBy[permission.Key] += ", "; } accessLimitedBy[permission.Key] += securityObject.Key; } } } return accessLimitedBy; } finally { for (int Index = 0 ; Index < grantedAccess.Length ; ++Index) { Marshal.FreeHGlobal(grantedAccess[Index]); } for (int Index = 0; Index < errorSecObj.Length ; ++Index) { Marshal.FreeHGlobal(errorSecObj[Index]); } } } finally { if (userClientCtxt != AUTHZ_CLIENT_CONTEXT_HANDLE.Zero) { NativeMethods.AuthzFreeContext(userClientCtxt); userClientCtxt = AUTHZ_CLIENT_CONTEXT_HANDLE.Zero; } if (deviceClientCtxt != AUTHZ_CLIENT_CONTEXT_HANDLE.Zero) { NativeMethods.AuthzFreeContext(deviceClientCtxt); deviceClientCtxt = AUTHZ_CLIENT_CONTEXT_HANDLE.Zero; if (compoundCtxt != AUTHZ_CLIENT_CONTEXT_HANDLE.Zero) { NativeMethods.AuthzFreeContext(compoundCtxt); compoundCtxt = AUTHZ_CLIENT_CONTEXT_HANDLE.Zero; } } } } /// /// Retrieves a copy of the security descriptor for an object /// /// A handle to the object from which to retrieve the security information /// Flags that indicate the type(s) of security information to retrieve. /// RawSecurityDescriptor object with the requested type(s) of security information on success. /// static RawSecurityDescriptor GetFileSecInfoSD(SafeFileHandle handle, NativeMethods.SecurityInformationClass infoClass) { PSECURITY_DESCRIPTOR tempSD = PSECURITY_DESCRIPTOR.Zero; try { uint error = NativeMethods.GetSecurityInfo(handle, NativeMethods.ObjectType.File, infoClass, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, out tempSD); if (error != Win32Error.ERROR_SUCCESS) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return new RawSecurityDescriptor(Helper.ConvertSecurityDescriptorToByteArray(tempSD), 0); } finally { Marshal.FreeHGlobal(tempSD); tempSD = PSECURITY_DESCRIPTOR.Zero; } } #endregion #region Private members static Dictionary NTFSAccess = new Dictionary() { { NativeMethods.FileAccess.GenericAll, "Full control"}, { NativeMethods.FileAccess.Execute, "Traverse folder / execute file" }, { NativeMethods.FileAccess.ReadData, "List folder / read data" }, { NativeMethods.FileAccess.ReadAttrib, "Read attributes" }, { NativeMethods.FileAccess.ReadExAttrib, "Read extended attributes" }, { NativeMethods.FileAccess.WriteData, "Create files / write data" }, { NativeMethods.FileAccess.AppendData, "Create folders / append data" }, { NativeMethods.FileAccess.WriteAttrib, "Write attributes" }, { NativeMethods.FileAccess.WriteExAttrib, "Write extended attributes" }, { NativeMethods.FileAccess.DeleteChild, "Delete subfolders and files" }, { NativeMethods.FileAccess.Delete, "Delete" }, { NativeMethods.FileAccess.ReadPermissions, "Read permissions" }, { NativeMethods.FileAccess.ChangePermissions, "Change permissions" }, { NativeMethods.FileAccess.TakeOwnership, "Take ownership" }, }; static int MAX_NTFSACCESS_PERM_DESC_WIDTH = NTFSAccess.Max(n => n.Value.Length); static int COLUMN_SPACING = 5; const string HEADER_PERMISSION = "Permission"; const string HEADER_ACCESS = "Access Granted"; const string HEADER_LIMITED_BY = "Limited By"; #endregion #region Nested class class FileSecurityObject { public RawSecurityDescriptor securityDescriptor; public RawSecurityDescriptor appliesTo; public AccessChkResult result; public FileSecurityObject() { securityDescriptor = null; appliesTo = null; result.grantedAccess = NativeMethods.FileAccess.None; } public FileSecurityObject(RawSecurityDescriptor SD) { securityDescriptor = SD; appliesTo = null; result.grantedAccess = NativeMethods.FileAccess.None; } public FileSecurityObject(RawSecurityDescriptor SD, RawSecurityDescriptor appliesSD) { securityDescriptor = SD; appliesTo = appliesSD; result.grantedAccess = NativeMethods.FileAccess.None; } public struct AccessChkResult { //public bool hasBeenEvaluated; public NativeMethods.FileAccess grantedAccess; }; } #endregion #region Private members /// /// Handle to the file or folder /// SafeFileHandle handle; string targetMachine; RawSecurityDescriptor shareSD; SecurityIdentifier userSid; SecurityIdentifier deviceSid; ClaimValueDictionary userClaims; ClaimValueDictionary deviceClaims; GroupsCollection userGroups; GroupsCollection deviceGroups; /// /// Result of evaluating Effective Access /// /// This is a map of permissions and a string identifying what /// (File permission, share permission, Central Access Rule, Central /// Polict etc.) denied this permission if any. Dictionary results; #endregion #region Nested class for P/Invokes and native (Win32) structures static class NativeMethods { #region authz [StructLayout(LayoutKind.Sequential)] internal struct AUTHZ_ACCESS_REQUEST { public StdAccess DesiredAccess; public byte[] PrincipalSelfSid; public POBJECT_TYPE_LIST ObjectTypeList; public int ObjectTypeListLength; public LPVOID OptionalArguments; } [StructLayout(LayoutKind.Sequential)] internal struct AUTHZ_ACCESS_REPLY { public int ResultListLength; public PACCESS_MASK GrantedAccessMask; public PDWORD SaclEvaluationResults; public PDWORD Error; } internal enum AuthzACFlags : uint // DWORD { None = 0, NoDeepCopySD } [DllImport(Win32.AUTHZ_DLL, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool AuthzAccessCheck( AuthzACFlags flags, AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext, ref AUTHZ_ACCESS_REQUEST pRequest, AUTHZ_AUDIT_EVENT_HANDLE AuditEvent, byte[] rawSecurityDescriptor, PSECURITY_DESCRIPTOR[] OptionalSecurityDescriptorArray, DWORD OptionalSecurityDescriptorCount, ref AUTHZ_ACCESS_REPLY pReply, AUTHZ_ACCESS_CHECK_RESULTS_HANDLE cachedResults); [DllImport(Win32.AUTHZ_DLL, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool AuthzFreeContext(AUTHZ_CLIENT_CONTEXT_HANDLE authzClientContext); internal enum AuthzRpcClientVersion : ushort // USHORT { V1 = 1 } internal const string AUTHZ_OBJECTUUID_WITHCAP = "9a81c2bd-a525-471d-a4ed-49907c0b23da"; internal const string RCP_OVER_TCP_PROTOCOL = "ncacn_ip_tcp"; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct AUTHZ_RPC_INIT_INFO_CLIENT { public AuthzRpcClientVersion version; public string objectUuid; public string protocol; public string server; public string endPoint; public string options; public string serverSpn; } [DllImport(Win32.AUTHZ_DLL, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool AuthzInitializeRemoteResourceManager( PAUTHZ_RPC_INIT_INFO_CLIENT rpcInitInfo, out SafeAuthzRMHandle authRM); [Flags] internal enum AuthzInitFlags : uint { Default = 0x0, SkipTokenGroups = 0x2, RequireS4ULogon = 0x4, ComputePrivileges = 0x8, } [DllImport(Win32.AUTHZ_DLL, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool AuthzInitializeContextFromSid( AuthzInitFlags flags, byte[] rawUserSid, SafeAuthzRMHandle authzRM, PLARGE_INTEGER expirationTime, Win32.LUID Identifier, LPVOID DynamicGroupArgs, out AUTHZ_CLIENT_CONTEXT_HANDLE authzClientContext); [DllImport(Win32.AUTHZ_DLL, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool AuthzInitializeCompoundContext( AUTHZ_CLIENT_CONTEXT_HANDLE userClientContext, AUTHZ_CLIENT_CONTEXT_HANDLE deviceClientContext, out AUTHZ_CLIENT_CONTEXT_HANDLE compoundContext); [Flags] internal enum AuthzResourceManagerFlags : uint { NO_AUDIT = 0x1, } [DllImport(Win32.AUTHZ_DLL, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool AuthzInitializeResourceManager( AuthzResourceManagerFlags flags, IntPtr pfnAccessCheck, IntPtr pfnComputeDynamicGroups, IntPtr pfnFreeDynamicGroups, string szResourceManagerName, out SafeAuthzRMHandle phAuthzResourceManager); #endregion #region PInvoke kernel32 [Flags] internal enum StdAccess : uint { None = 0x0, SYNCHRONIZE = 0x100000, STANDARD_RIGHTS_REQUIRED = 0xF0000, MAXIMUM_ALLOWED = 0x2000000, } [Flags] internal enum FileAccess : uint { None = 0x0, ReadData = 0x1, WriteData = 0x2, AppendData = 0x4, ReadExAttrib = 0x8, WriteExAttrib = 0x10, Execute = 0x20, DeleteChild = 0x40, ReadAttrib = 0x80, WriteAttrib = 0x100, Delete = 0x10000, // DELETE, ReadPermissions = 0x20000, // READ_CONTROL ChangePermissions = 0x40000, // WRITE_DAC, TakeOwnership = 0x80000, // WRITE_OWNER, GenericRead = ReadPermissions | ReadData | ReadAttrib | ReadExAttrib | StdAccess.SYNCHRONIZE, GenericAll = (StdAccess.STANDARD_RIGHTS_REQUIRED | 0x1FF), CategoricalAll = uint.MaxValue } [Flags] internal enum FileShare : uint { None = 0x0, Read = 0x1, Write = 0x2, Delete = 0x4 } internal enum FileMode : uint { OpenExisting = 3, } [Flags] internal enum FileFlagAttrib : uint { BackupSemantics = 0x02000000, } [DllImport(Win32.KERNEL32_DLL, SetLastError = true, CharSet = CharSet.Unicode)] internal static extern SafeFileHandle CreateFile(string lpFileName, FileAccess desiredAccess, FileShare shareMode, IntPtr lpSecurityAttributes, FileMode mode, FileFlagAttrib flagsAndAttributes, IntPtr hTemplateFile); #endregion #region PInvoke advapi32 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] internal struct ACE_HEADER { public byte AceType; public byte AceFlags; public ushort AceSize; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] internal struct SYSTEM_SCOPED_POLICY_ID_ACE { public ACE_HEADER Header; public uint Mask; public uint SidStart; } internal enum ObjectType : uint { File = 1, } [Flags] internal enum SecurityInformationClass : uint { Owner = 0x00001, Group = 0x00002, Dacl = 0x00004, Sacl = 0x00008, Label = 0x00010, Attribute = 0x00020, Scope = 0x00040 } [DllImport(Win32.ADVAPI32_DLL, CallingConvention = CallingConvention.Winapi, SetLastError = true, CharSet = CharSet.Unicode)] internal static extern DWORD GetSecurityInfo( SafeFileHandle handle, ObjectType objectType, SecurityInformationClass infoClass, PSID owner, PSID group, PACL dacl, PACL sacl, out PSECURITY_DESCRIPTOR securityDescriptor); #endregion } #endregion } }