From 03bd938b7c1644a46d73eac060fc0767b2217549 Mon Sep 17 00:00:00 2001 From: dahall Date: Tue, 9 Nov 2021 13:16:27 -0700 Subject: [PATCH] Work on fixing and enabling Audit log writes using AuthzReportSecurityEvent and AuthzReportSecurityEventFromParams. The prior is now fully working. (#251) --- PInvoke/Security/Authz/AdtGen.cs | 101 ++++++- PInvoke/Security/Authz/Authz.cs | 306 +++++++------------- UnitTests/PInvoke/Security/Authz/AuthzTests.cs | 384 +++++++++++-------------- 3 files changed, 358 insertions(+), 433 deletions(-) diff --git a/PInvoke/Security/Authz/AdtGen.cs b/PInvoke/Security/Authz/AdtGen.cs index c88721b7..bdb02f00 100644 --- a/PInvoke/Security/Authz/AdtGen.cs +++ b/PInvoke/Security/Authz/AdtGen.cs @@ -1,5 +1,8 @@ using System; +using System.Collections; +using System.Collections.Generic; using System.Runtime.InteropServices; +using Vanara.Extensions; using Vanara.InteropServices; namespace Vanara.PInvoke @@ -7,8 +10,8 @@ namespace Vanara.PInvoke public static partial class Authz { /// The AUDIT_PARAM_TYPE enumeration defines the type of audit parameters that are available. - // https://docs.microsoft.com/en-us/windows/desktop/api/adtgen/ne-adtgen-_audit_param_type typedef enum _AUDIT_PARAM_TYPE { APT_None, - // APT_String, APT_Ulong, APT_Pointer, APT_Sid, APT_LogonId, APT_ObjectTypeList, APT_Luid, APT_Guid, APT_Time, APT_Int64, + // https://docs.microsoft.com/en-us/windows/desktop/api/adtgen/ne-adtgen-_audit_param_type typedef enum _AUDIT_PARAM_TYPE { + // APT_None, APT_String, APT_Ulong, APT_Pointer, APT_Sid, APT_LogonId, APT_ObjectTypeList, APT_Luid, APT_Guid, APT_Time, APT_Int64, // APT_IpAddress, APT_LogonIdWithSid } AUDIT_PARAM_TYPE; [PInvokeData("adtgen.h", MSDNShortId = "1ECC866A-2DD3-4EE4-B2CC-7F5ADF7FFC99")] public enum AUDIT_PARAM_TYPE @@ -17,9 +20,11 @@ namespace Vanara.PInvoke APT_None = 1, /// A string that terminates with NULL. + [CorrespondingType(typeof(string), EncodingType = typeof(System.Text.UnicodeEncoding))] APT_String, /// An unsigned long. + [CorrespondingType(typeof(uint))] APT_Ulong, /// @@ -27,39 +32,105 @@ namespace Vanara.PInvoke /// this option when you are interested in the absolute value of the pointer. The memory to which the pointer points is not /// marshaled when using this type. /// + [CorrespondingType(typeof(IntPtr))] APT_Pointer, /// The security identifier (SID). + [CorrespondingType(typeof(PSID))] APT_Sid, - /// The logon identifier (LUID) that results in three output parameters: + /// + /// The logon identifier (LUID) that results in three output parameters: + /// 1. Account Name 2. Authority Name 3. LogonID + /// + [CorrespondingType(typeof(uint))] APT_LogonId, /// Object type list. + [CorrespondingType(typeof(AUDIT_OBJECT_TYPES))] APT_ObjectTypeList, /// LUID that is not translated to LogonId. + [CorrespondingType(typeof(uint))] APT_Luid, /// GUID. + [CorrespondingType(typeof(GuidPtr))] APT_Guid, /// Time as FILETIME. + [CorrespondingType(typeof(System.Runtime.InteropServices.ComTypes.FILETIME))] APT_Time, - /// ULONGLONG. + /// LONGLONG. + [CorrespondingType(typeof(long))] APT_Int64, /// /// IP Address (IPv4 and IPv6). This logs the address as the first parameter and the port as the second parameter. You must /// ensure that two entries are added in the event message file. You should ensure that the buffer size is 128 bytes. /// + [CorrespondingType(typeof(byte[]))] APT_IpAddress, - /// Logon ID with SID that results in four output parameters: + /// + /// Logon ID with SID that results in four output parameters: + /// 1. SID 2. Account Name 3. Authority Name 4. LogonID + /// APT_LogonIdWithSid, } + /// + /// IP Addess (IPv4 and IPv6). This logs the address as the first parameter and the port as the second. So ensure that 2 entries are + /// added in the event message file, one for the address and the immediate next entry as the port + /// + [PInvokeData("adtgen.h")] + [StructLayout(LayoutKind.Sequential)] + public struct AUDIT_IP_ADDRESS + { + private const int _AUTHZ_SS_MAXSIZE = 128; + + /// The IP address bytes. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = _AUTHZ_SS_MAXSIZE)] + public byte[] pIpAddress; + } + + /// Element of an object-type-list + [PInvokeData("adtgen.h")] + [StructLayout(LayoutKind.Sequential)] + public struct AUDIT_OBJECT_TYPE + { + /// guid of the (sub)object + public Guid ObjectType; + + /// currently not defined + public ushort Flags; + + /// level within the hierarchy. 0 is the root level + public ushort Level; + + /// access-mask for this (sub)object + public ACCESS_MASK AccessMask; + } + + /// + /// The AUDIT_OBJECT_TYPES structure identifies an object type element in a hierarchy of object types. The AccessCheckByType + /// functions use an array of such structures to define a hierarchy of an object and its subobjects, such as property sets and properties. + /// + [PInvokeData("adtgen.h")] + [StructLayout(LayoutKind.Sequential)] + public struct AUDIT_OBJECT_TYPES + { + /// number of object-types in pObjectTypes + public ushort Count; + + /// currently not defined + public ushort Flags; + + /// array of object-types (i.e. AUDIT_OBJECT_TYPE[]) + public IntPtr pObjectTypes; + } + /// /// Structure that defines a single audit parameter. LsaGenAuditEvent accepts an array of such elements to represent the parameters /// of the audit to be generated. It is best to initialize this structure using AdtInitParams function. This will ensure @@ -69,15 +140,15 @@ namespace Vanara.PInvoke [StructLayout(LayoutKind.Explicit, Size = 32, CharSet = CharSet.Unicode)] public struct AUDIT_PARAM { - /// + /// Type [FieldOffset(0)] public AUDIT_PARAM_TYPE Type; - /// + /// currently unused [FieldOffset(4)] public uint Length; - /// + /// currently unused [FieldOffset(8)] public uint Flags; @@ -99,11 +170,11 @@ namespace Vanara.PInvoke /// [FieldOffset(16)] - public IntPtr pguid; + public GuidPtr pguid; /// [FieldOffset(16)] - public int LogonId_LowPart; + public uint LogonId_LowPart; /// [FieldOffset(16)] @@ -127,17 +198,17 @@ namespace Vanara.PInvoke [StructLayout(LayoutKind.Sequential)] public struct AUDIT_PARAMS { - /// + /// size in bytes public uint Length; - /// + /// currently unused public uint Flags; - /// + /// number of parameters public ushort Count; - /// + /// array of parameters (i.e. AUDIT_PARAM[]) public IntPtr Parameters; } } -} +} \ No newline at end of file diff --git a/PInvoke/Security/Authz/Authz.cs b/PInvoke/Security/Authz/Authz.cs index f1d8b7ae..10686241 100644 --- a/PInvoke/Security/Authz/Authz.cs +++ b/PInvoke/Security/Authz/Authz.cs @@ -943,17 +943,14 @@ namespace Vanara.PInvoke /// An array of AUTHZ_SOURCE_SCHEMA_REGISTRATION structures that returns the registered security event sources. // https://docs.microsoft.com/en-us/windows/desktop/api/authz/nf-authz-authzenumeratesecurityeventsources AUTHZAPI BOOL [PInvokeData("authz.h", MSDNShortId = "2a20ccc9-f2ac-41e4-9d86-745004775e67")] - public static IEnumerable AuthzEnumerateSecurityEventSources() + public static IEnumerable AuthzEnumerateSecurityEventSources() { var len = 0U; if (!AuthzEnumerateSecurityEventSources(0, IntPtr.Zero, out _, ref len) && len == 0) Win32Error.ThrowLastError(); - using (var mem = new SafeHGlobalHandle((int)len)) - { - if (!AuthzEnumerateSecurityEventSources(0, (IntPtr)mem, out var cnt, ref len)) - Win32Error.ThrowLastError(); - return mem.ToEnumerable((int)cnt).Select(r => new SafeAUTHZ_SOURCE_SCHEMA_REGISTRATION(r)).ToArray(); - } + using var mem = new SafeHGlobalHandle((int)len); + Win32Error.ThrowLastErrorIfFalse(AuthzEnumerateSecurityEventSources(0, mem, out var cnt, ref len)); + return mem.ToEnumerable((int)cnt).ToArray(); } /// @@ -1679,7 +1676,8 @@ namespace Vanara.PInvoke [DllImport(Lib.Authz, SetLastError = true, ExactSpelling = true)] [PInvokeData("authz.h", MSDNShortId = "77cb5c6c-1634-4449-8d05-ce6357ad4e4b")] [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool AuthzInstallSecurityEventSource([Optional] uint dwFlags, in AUTHZ_SOURCE_SCHEMA_REGISTRATION pRegistration); + public static extern bool AuthzInstallSecurityEventSource([Optional] uint dwFlags, + [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(VanaraCustomMarshaler))] AUTHZ_SOURCE_SCHEMA_REGISTRATION pRegistration); /// /// The AuthzModifyClaims function adds, deletes, or modifies user and device claims in the Authz client context. @@ -1921,32 +1919,23 @@ namespace Vanara.PInvoke // https://docs.microsoft.com/en-us/windows/desktop/api/authz/nf-authz-authzreportsecurityevent AUTHZAPI BOOL // AuthzReportSecurityEvent( DWORD dwFlags, AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE hEventProvider, DWORD dwAuditId, PSID pUserSid, // DWORD dwCount, ... ); - [DllImport(Lib.Authz, SetLastError = true, ExactSpelling = true)] + [DllImport(Lib.Authz, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] [PInvokeData("authz.h", MSDNShortId = "95d561ef-3233-433a-a1e7-b914df1dd211")] [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool AuthzReportSecurityEvent(APF dwFlags, AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE hEventProvider, uint dwAuditId, [Optional] PSID pUserSid, uint dwCount, __arglist); + public static extern bool AuthzReportSecurityEvent(APF dwFlags, AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE hEventProvider, uint dwAuditId, + [Optional] PSID pUserSid, uint dwCount, __arglist); /// - /// - /// The AuthzReportSecurityEventFromParams function generates a security audit for a registered security event source by using - /// the specified array of audit parameters. - /// + /// The AuthzReportSecurityEventFromParams function generates a security audit for a registered security event source by + /// using the specified array of audit parameters. /// - /// - /// Reserved for future use. - /// - /// - /// A handle to the registered security event source to use for the audit. - /// - /// - /// The identifier of the audit. - /// + /// Reserved for future use. + /// A handle to the registered security event source to use for the audit. + /// The identifier of the audit. /// - /// A pointer to the security identifier (SID) that will be listed as the source of the audit in the event log. - /// - /// - /// An array of audit parameters. + /// A pointer to the security identifier (SID) that will be listed as the source of the audit in the event log. /// + /// An array of audit parameters. /// /// If the function succeeds, the function returns TRUE. /// If the function fails, it returns FALSE. For extended error information, call GetLastError. @@ -1954,10 +1943,35 @@ namespace Vanara.PInvoke // https://docs.microsoft.com/en-us/windows/desktop/api/authz/nf-authz-authzreportsecurityeventfromparams AUTHZAPI BOOL // AuthzReportSecurityEventFromParams( DWORD dwFlags, AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE hEventProvider, DWORD dwAuditId, PSID // pUserSid, PAUDIT_PARAMS pParams ); - [DllImport(Lib.Authz, SetLastError = true, ExactSpelling = true)] + [DllImport(Lib.Authz, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] [PInvokeData("authz.h", MSDNShortId = "ee5b598a-0a89-4b32-a9bc-e9c811573b08")] [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool AuthzReportSecurityEventFromParams([Optional] uint dwFlags, AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE hEventProvider, uint dwAuditId, [Optional] PSID pUserSid, in AUDIT_PARAMS pParams); + public static extern bool AuthzReportSecurityEventFromParams([Optional] uint dwFlags, AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE hEventProvider, + uint dwAuditId, [Optional] PSID pUserSid, in AUDIT_PARAMS pParams); + + /// + /// The AuthzReportSecurityEventFromParams function generates a security audit for a registered security event source by + /// using the specified array of audit parameters. + /// + /// Reserved for future use. + /// A handle to the registered security event source to use for the audit. + /// The identifier of the audit. + /// + /// A pointer to the security identifier (SID) that will be listed as the source of the audit in the event log. + /// + /// An array of audit parameters. + /// + /// If the function succeeds, the function returns TRUE. + /// If the function fails, it returns FALSE. For extended error information, call GetLastError. + /// + // https://docs.microsoft.com/en-us/windows/desktop/api/authz/nf-authz-authzreportsecurityeventfromparams AUTHZAPI BOOL + // AuthzReportSecurityEventFromParams( DWORD dwFlags, AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE hEventProvider, DWORD dwAuditId, PSID + // pUserSid, PAUDIT_PARAMS pParams ); + [DllImport(Lib.Authz, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] + [PInvokeData("authz.h", MSDNShortId = "ee5b598a-0a89-4b32-a9bc-e9c811573b08")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AuthzReportSecurityEventFromParams([Optional] uint dwFlags, AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE hEventProvider, + uint dwAuditId, [Optional] PSID pUserSid, [In, MarshalAs(UnmanagedType.LPArray)] AUDIT_PARAMS[] pParams); /// /// The AuthzSetAppContainerInformation function sets the app container and capability information in a current Authz context. @@ -2052,14 +2066,14 @@ namespace Vanara.PInvoke [StructLayout(LayoutKind.Sequential)] public struct AUTHZ_ACCESS_CHECK_RESULTS_HANDLE : IHandle { - private IntPtr handle; + private readonly IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public AUTHZ_ACCESS_CHECK_RESULTS_HANDLE(IntPtr preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with . - public static AUTHZ_ACCESS_CHECK_RESULTS_HANDLE NULL => new AUTHZ_ACCESS_CHECK_RESULTS_HANDLE(IntPtr.Zero); + public static AUTHZ_ACCESS_CHECK_RESULTS_HANDLE NULL => new(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; @@ -2072,7 +2086,7 @@ namespace Vanara.PInvoke /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. - public static implicit operator AUTHZ_ACCESS_CHECK_RESULTS_HANDLE(IntPtr h) => new AUTHZ_ACCESS_CHECK_RESULTS_HANDLE(h); + public static implicit operator AUTHZ_ACCESS_CHECK_RESULTS_HANDLE(IntPtr h) => new(h); /// Implements the operator !=. /// The first handle. @@ -2087,7 +2101,7 @@ namespace Vanara.PInvoke public static bool operator ==(AUTHZ_ACCESS_CHECK_RESULTS_HANDLE h1, AUTHZ_ACCESS_CHECK_RESULTS_HANDLE h2) => h1.Equals(h2); /// - public override bool Equals(object obj) => obj is AUTHZ_ACCESS_CHECK_RESULTS_HANDLE h ? handle == h.handle : false; + public override bool Equals(object obj) => obj is AUTHZ_ACCESS_CHECK_RESULTS_HANDLE h && handle == h.handle; /// public override int GetHashCode() => handle.GetHashCode(); @@ -2140,14 +2154,14 @@ namespace Vanara.PInvoke [StructLayout(LayoutKind.Sequential)] public struct AUTHZ_AUDIT_EVENT_HANDLE : IHandle { - private IntPtr handle; + private readonly IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public AUTHZ_AUDIT_EVENT_HANDLE(IntPtr preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with . - public static AUTHZ_AUDIT_EVENT_HANDLE NULL => new AUTHZ_AUDIT_EVENT_HANDLE(IntPtr.Zero); + public static AUTHZ_AUDIT_EVENT_HANDLE NULL => new(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; @@ -2160,7 +2174,7 @@ namespace Vanara.PInvoke /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. - public static implicit operator AUTHZ_AUDIT_EVENT_HANDLE(IntPtr h) => new AUTHZ_AUDIT_EVENT_HANDLE(h); + public static implicit operator AUTHZ_AUDIT_EVENT_HANDLE(IntPtr h) => new(h); /// Implements the operator !=. /// The first handle. @@ -2175,7 +2189,7 @@ namespace Vanara.PInvoke public static bool operator ==(AUTHZ_AUDIT_EVENT_HANDLE h1, AUTHZ_AUDIT_EVENT_HANDLE h2) => h1.Equals(h2); /// - public override bool Equals(object obj) => obj is AUTHZ_AUDIT_EVENT_HANDLE h ? handle == h.handle : false; + public override bool Equals(object obj) => obj is AUTHZ_AUDIT_EVENT_HANDLE h && handle == h.handle; /// public override int GetHashCode() => handle.GetHashCode(); @@ -2188,7 +2202,7 @@ namespace Vanara.PInvoke [StructLayout(LayoutKind.Sequential)] public struct AUTHZ_CAP_CHANGE_SUBSCRIPTION_HANDLE : IHandle { - private IntPtr handle; + private readonly IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. @@ -2197,7 +2211,7 @@ namespace Vanara.PInvoke /// /// Returns an invalid handle by instantiating a object with . /// - public static AUTHZ_CAP_CHANGE_SUBSCRIPTION_HANDLE NULL => new AUTHZ_CAP_CHANGE_SUBSCRIPTION_HANDLE(IntPtr.Zero); + public static AUTHZ_CAP_CHANGE_SUBSCRIPTION_HANDLE NULL => new(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; @@ -2210,7 +2224,7 @@ namespace Vanara.PInvoke /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. - public static implicit operator AUTHZ_CAP_CHANGE_SUBSCRIPTION_HANDLE(IntPtr h) => new AUTHZ_CAP_CHANGE_SUBSCRIPTION_HANDLE(h); + public static implicit operator AUTHZ_CAP_CHANGE_SUBSCRIPTION_HANDLE(IntPtr h) => new(h); /// Implements the operator !=. /// The first handle. @@ -2225,7 +2239,7 @@ namespace Vanara.PInvoke public static bool operator ==(AUTHZ_CAP_CHANGE_SUBSCRIPTION_HANDLE h1, AUTHZ_CAP_CHANGE_SUBSCRIPTION_HANDLE h2) => h1.Equals(h2); /// - public override bool Equals(object obj) => obj is AUTHZ_CAP_CHANGE_SUBSCRIPTION_HANDLE h ? handle == h.handle : false; + public override bool Equals(object obj) => obj is AUTHZ_CAP_CHANGE_SUBSCRIPTION_HANDLE h && handle == h.handle; /// public override int GetHashCode() => handle.GetHashCode(); @@ -2238,14 +2252,14 @@ namespace Vanara.PInvoke [StructLayout(LayoutKind.Sequential)] public struct AUTHZ_CLIENT_CONTEXT_HANDLE : IHandle { - private IntPtr handle; + private readonly IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public AUTHZ_CLIENT_CONTEXT_HANDLE(IntPtr preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with . - public static AUTHZ_CLIENT_CONTEXT_HANDLE NULL => new AUTHZ_CLIENT_CONTEXT_HANDLE(IntPtr.Zero); + public static AUTHZ_CLIENT_CONTEXT_HANDLE NULL => new(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; @@ -2258,7 +2272,7 @@ namespace Vanara.PInvoke /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. - public static implicit operator AUTHZ_CLIENT_CONTEXT_HANDLE(IntPtr h) => new AUTHZ_CLIENT_CONTEXT_HANDLE(h); + public static implicit operator AUTHZ_CLIENT_CONTEXT_HANDLE(IntPtr h) => new(h); /// Implements the operator !=. /// The first handle. @@ -2273,7 +2287,7 @@ namespace Vanara.PInvoke public static bool operator ==(AUTHZ_CLIENT_CONTEXT_HANDLE h1, AUTHZ_CLIENT_CONTEXT_HANDLE h2) => h1.Equals(h2); /// - public override bool Equals(object obj) => obj is AUTHZ_CLIENT_CONTEXT_HANDLE h ? handle == h.handle : false; + public override bool Equals(object obj) => obj is AUTHZ_CLIENT_CONTEXT_HANDLE h && handle == h.handle; /// public override int GetHashCode() => handle.GetHashCode(); @@ -2354,11 +2368,12 @@ namespace Vanara.PInvoke // _AUTHZ_REGISTRATION_OBJECT_TYPE_NAME_OFFSET { PWSTR szObjectTypeName; DWORD dwOffset; } // AUTHZ_REGISTRATION_OBJECT_TYPE_NAME_OFFSET, *PAUTHZ_REGISTRATION_OBJECT_TYPE_NAME_OFFSET; [PInvokeData("authz.h", MSDNShortId = "2ec39edc-7819-41a5-8798-dc51c00ba85e")] - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct AUTHZ_REGISTRATION_OBJECT_TYPE_NAME_OFFSET { /// A pointer to a wide character string that represents the name of the object type. - public StrPtrUni szObjectTypeName; + [MarshalAs(UnmanagedType.LPTStr)] + public string szObjectTypeName; /// Offset of the object type name in an object types message DLL. public uint dwOffset; @@ -2368,14 +2383,14 @@ namespace Vanara.PInvoke [StructLayout(LayoutKind.Sequential)] public struct AUTHZ_RESOURCE_MANAGER_HANDLE : IHandle { - private IntPtr handle; + private readonly IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public AUTHZ_RESOURCE_MANAGER_HANDLE(IntPtr preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with . - public static AUTHZ_RESOURCE_MANAGER_HANDLE NULL => new AUTHZ_RESOURCE_MANAGER_HANDLE(IntPtr.Zero); + public static AUTHZ_RESOURCE_MANAGER_HANDLE NULL => new(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; @@ -2388,7 +2403,7 @@ namespace Vanara.PInvoke /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. - public static implicit operator AUTHZ_RESOURCE_MANAGER_HANDLE(IntPtr h) => new AUTHZ_RESOURCE_MANAGER_HANDLE(h); + public static implicit operator AUTHZ_RESOURCE_MANAGER_HANDLE(IntPtr h) => new(h); /// Implements the operator !=. /// The first handle. @@ -2403,7 +2418,7 @@ namespace Vanara.PInvoke public static bool operator ==(AUTHZ_RESOURCE_MANAGER_HANDLE h1, AUTHZ_RESOURCE_MANAGER_HANDLE h2) => h1.Equals(h2); /// - public override bool Equals(object obj) => obj is AUTHZ_RESOURCE_MANAGER_HANDLE h ? handle == h.handle : false; + public override bool Equals(object obj) => obj is AUTHZ_RESOURCE_MANAGER_HANDLE h && handle == h.handle; /// public override int GetHashCode() => handle.GetHashCode(); @@ -2608,7 +2623,7 @@ namespace Vanara.PInvoke [StructLayout(LayoutKind.Sequential)] public struct AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE : IHandle { - private IntPtr handle; + private readonly IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. @@ -2617,7 +2632,7 @@ namespace Vanara.PInvoke /// /// Returns an invalid handle by instantiating a object with . /// - public static AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE NULL => new AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE(IntPtr.Zero); + public static AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE NULL => new(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; @@ -2630,7 +2645,7 @@ namespace Vanara.PInvoke /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. - public static implicit operator AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE(IntPtr h) => new AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE(h); + public static implicit operator AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE(IntPtr h) => new(h); /// Implements the operator !=. /// The first handle. @@ -2645,7 +2660,7 @@ namespace Vanara.PInvoke public static bool operator ==(AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE h1, AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE h2) => h1.Equals(h2); /// - public override bool Equals(object obj) => obj is AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE h ? handle == h.handle : false; + public override bool Equals(object obj) => obj is AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE h && handle == h.handle; /// public override int GetHashCode() => handle.GetHashCode(); @@ -2662,7 +2677,8 @@ namespace Vanara.PInvoke // ObjectTypeNames[ANYSIZE_ARRAY]; } AUTHZ_SOURCE_SCHEMA_REGISTRATION, *PAUTHZ_SOURCE_SCHEMA_REGISTRATION; [PInvokeData("authz.h", MSDNShortId = "8b4d6e14-fb9c-428a-bd94-34eba668edc6")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public struct AUTHZ_SOURCE_SCHEMA_REGISTRATION + [VanaraMarshaler(typeof(SafeAnysizeStructMarshaler), nameof(dwObjectTypeNameCount))] + public class AUTHZ_SOURCE_SCHEMA_REGISTRATION { /// /// Flags that control the behavior of the operation. The following table shows a possible value. @@ -2690,21 +2706,26 @@ namespace Vanara.PInvoke public SOURCE_SCHEMA_REGISTRATION_FLAGS dwFlags; /// A pointer to a wide character string that represents the name of the event source. - public StrPtrUni szEventSourceName; + [MarshalAs(UnmanagedType.LPTStr)] + public string szEventSourceName; /// A pointer to a wide character string that represents the name of the resource that contains the event messages. - public StrPtrUni szEventMessageFile; + [MarshalAs(UnmanagedType.LPTStr)] + public string szEventMessageFile; /// A pointer to a wide character string that represents the name of the XML schema file for the event source. - public StrPtrUni szEventSourceXmlSchemaFile; + [MarshalAs(UnmanagedType.LPTStr)] + public string szEventSourceXmlSchemaFile; /// /// A pointer to a wide character string that represents the name of the resource that contains the event parameter strings. /// - public StrPtrUni szEventAccessStringsFile; + [MarshalAs(UnmanagedType.LPTStr)] + public string szEventAccessStringsFile; /// This member is reserved and must be set to NULL. - public StrPtrUni szExecutableImagePath; + [MarshalAs(UnmanagedType.LPTStr)] + public string szExecutableImagePath; /// /// The GUID of a migrated publisher. The value of this member is converted to a string and stored in the registry if the caller @@ -2716,123 +2737,8 @@ namespace Vanara.PInvoke public uint dwObjectTypeNameCount; /// An array of AUTHZ_REGISTRATION_OBJECT_TYPE_NAME_OFFSET structures that represents the object types for the events. - public AUTHZ_REGISTRATION_OBJECT_TYPE_NAME_OFFSET ObjectTypeNames; - } - - /// - public class SafeAUTHZ_SOURCE_SCHEMA_REGISTRATION : IDisposable - { - private List mem = new List(7); - - /// - /// Flags that control the behavior of the operation. The following table shows a possible value. - /// - /// - /// Value - /// Meaning - /// - /// - /// AUTHZ_ALLOW_MULTIPLE_SOURCE_INSTANCES 0x1 - /// - /// Allows registration of multiple sources with the same name. Use of this flag means that more than one source can call the - /// AuthzRegisterSecurityEventSource function with the same szEventSourceName at runtime. - /// - /// - /// - /// AUTHZ_MIGRATED_LEGACY_PUBLISHER 0x2 - /// - /// The caller is a migrated publisher that has registered a manifest with WEvtUtil.exe. The GUID of the provider specified by - /// the pProviderGuid member is stored in the registry. - /// - /// - /// - /// - public SOURCE_SCHEMA_REGISTRATION_FLAGS dwFlags { get; set; } - - /// A string that represents the name of the event source. - public string szEventSourceName { get; set; } - - /// A string that represents the name of the resource that contains the event messages. - public string szEventMessageFile { get; set; } - - /// A string that represents the name of the XML schema file for the event source. - public string szEventSourceXmlSchemaFile { get; set; } - - /// - /// A pointer to a wide character string that represents the name of the resource that contains the event parameter strings. - /// - public string szEventAccessStringsFile { get; set; } - - /// This member is reserved and must be set to . - public string szExecutableImagePath { get; set; } - - /// - /// The GUID of a migrated publisher. The value of this member is converted to a string and stored in the registry if the caller - /// is a migrated publisher. - /// - public Guid? pProviderGuid { get; set; } - - /// A pointer to a wide character string that represents the name of the object type. - public string szObjectTypeName { get; set; } - - /// Offset of the object type name in an object types message DLL. - public uint dwOffset { get; set; } - - /// Initializes a new instance of the class. - public SafeAUTHZ_SOURCE_SCHEMA_REGISTRATION() { } - - /// - /// Initializes a new instance of the class from its unmanaged equivalent. - /// - /// The native instance. - public SafeAUTHZ_SOURCE_SCHEMA_REGISTRATION(AUTHZ_SOURCE_SCHEMA_REGISTRATION outValue) - { - dwFlags = outValue.dwFlags; - szEventSourceName = outValue.szEventSourceName; - szEventMessageFile = outValue.szEventMessageFile; - szEventSourceXmlSchemaFile = outValue.szEventSourceXmlSchemaFile; - szEventAccessStringsFile = outValue.szEventAccessStringsFile; - szExecutableImagePath = outValue.szExecutableImagePath; - pProviderGuid = outValue.pProviderGuid; - szObjectTypeName = outValue.ObjectTypeNames.szObjectTypeName; - dwOffset = outValue.ObjectTypeNames.dwOffset; - } - - /// Performs an implicit conversion from to . - /// The managed equivalent. - /// The result of the conversion. - public static implicit operator AUTHZ_SOURCE_SCHEMA_REGISTRATION(SafeAUTHZ_SOURCE_SCHEMA_REGISTRATION mgd) - { - // Write all pointer instances to memory stream so they will be kept in memory - var ret = new AUTHZ_SOURCE_SCHEMA_REGISTRATION { dwFlags = mgd.dwFlags }; - ret.szEventSourceName = SetPtr(mgd.szEventSourceName); - ret.szEventMessageFile = SetPtr(mgd.szEventMessageFile); - ret.szEventSourceXmlSchemaFile = SetPtr(mgd.szEventSourceXmlSchemaFile); - ret.szEventAccessStringsFile = SetPtr(mgd.szEventAccessStringsFile); - ret.szExecutableImagePath = SetPtr(mgd.szExecutableImagePath); - if (mgd.pProviderGuid.HasValue) - { - var ptr = SafeHGlobalHandle.CreateFromStructure(mgd.pProviderGuid.Value); - mgd.mem.Add(ptr); - ret.pProviderGuid = ptr.DangerousGetHandle(); - } - ret.dwObjectTypeNameCount = mgd.szObjectTypeName is null ? 0 : 1U; - ret.ObjectTypeNames.szObjectTypeName = SetPtr(mgd.szObjectTypeName); - ret.ObjectTypeNames.dwOffset = mgd.dwOffset; - - return ret; - - IntPtr SetPtr(string value) - { - if (value is null) return IntPtr.Zero; - var ptr = new SafeHGlobalHandle(value); - mgd.mem.Add(ptr); - return ptr.DangerousGetHandle(); - } - } - - /// - public void Dispose() { foreach (var m in mem) m.Dispose(); mem.Clear(); } + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] + public AUTHZ_REGISTRATION_OBJECT_TYPE_NAME_OFFSET[] ObjectTypeNames; } /// @@ -2877,23 +2783,17 @@ namespace Vanara.PInvoke Error = Marshal.AllocHGlobal(sz); } -#pragma warning disable 612 /// Gets or sets the granted access mask values. The length of this array must match the value in . /// The granted access mask values. public uint[] GrantedAccessMaskValues { - get - { - if (GrantedAccessMask != IntPtr.Zero && ResultListLength > 0) - return GrantedAccessMask.ToArray(ResultListLength); - return new uint[0]; - } + get => GrantedAccessMask != IntPtr.Zero && ResultListLength > 0 ? GrantedAccessMask.ToArray(ResultListLength) : (new uint[0]); set { - if (value == null && ResultListLength != 0) + if (value is null && ResultListLength != 0) throw new ArgumentNullException(nameof(GrantedAccessMaskValues), $"Value cannot be null if {nameof(ResultListLength)} field does not equal 0."); - if (value != null && value.Length != ResultListLength) + if (value is not null && value.Length != ResultListLength) throw new ArgumentOutOfRangeException(nameof(GrantedAccessMaskValues), $"Number of items must match value of {nameof(ResultListLength)} field."); CopyArrayToPtr(value, GrantedAccessMask); } @@ -2915,17 +2815,14 @@ namespace Vanara.PInvoke /// The system access control list (SACL) evaluation results values. public uint[] SaclEvaluationResultsValues { - get - { - if (SaclEvaluationResults != IntPtr.Zero && ResultListLength > 0) - return SaclEvaluationResults.ToArray(ResultListLength); - return new uint[0]; - } + get => SaclEvaluationResults != IntPtr.Zero && ResultListLength > 0 + ? SaclEvaluationResults.ToArray(ResultListLength) + : (new uint[0]); set { - if (value == null && ResultListLength != 0) + if (value is null && ResultListLength != 0) throw new ArgumentNullException(nameof(SaclEvaluationResultsValues), $"Value cannot be null if {nameof(ResultListLength)} field does not equal 0."); - if (value != null && value.Length != ResultListLength) + if (value is not null && value.Length != ResultListLength) throw new ArgumentOutOfRangeException(nameof(SaclEvaluationResultsValues), $"Number of items must match value of {nameof(ResultListLength)} field."); CopyArrayToPtr(value, SaclEvaluationResults); } @@ -2935,24 +2832,17 @@ namespace Vanara.PInvoke /// The results values. public uint[] ErrorValues { - get - { - if (Error != IntPtr.Zero && ResultListLength > 0) - return Error.ToArray(ResultListLength); - return new uint[0]; - } + get => Error != IntPtr.Zero && ResultListLength > 0 ? Error.ToArray(ResultListLength) : (new uint[0]); set { - if (value == null && ResultListLength != 0) + if (value is null && ResultListLength != 0) throw new ArgumentNullException(nameof(ErrorValues), $"Value cannot be null if {nameof(ResultListLength)} field does not equal 0."); - if (value != null && value.Length != ResultListLength) + if (value is not null && value.Length != ResultListLength) throw new ArgumentOutOfRangeException(nameof(ErrorValues), $"Number of items must match value of {nameof(ResultListLength)} field."); CopyArrayToPtr(value, Error); } } -#pragma warning restore 612 - void IDisposable.Dispose() { Marshal.FreeHGlobal(GrantedAccessMask); @@ -3152,7 +3042,7 @@ namespace Vanara.PInvoke internal class AUTHZ_SECURITY_ATTRIBUTES_INFORMATION_Marshaler : ICustomMarshaler { - public static ICustomMarshaler GetInstance(string cookie) => new AUTHZ_SECURITY_ATTRIBUTES_INFORMATION_Marshaler(); + public static ICustomMarshaler GetInstance(string _) => new AUTHZ_SECURITY_ATTRIBUTES_INFORMATION_Marshaler(); public void CleanUpManagedData(object ManagedObj) { @@ -3165,7 +3055,7 @@ namespace Vanara.PInvoke public IntPtr MarshalManagedToNative(object ManagedObj) { // Determine size - if (!(ManagedObj is AUTHZ_SECURITY_ATTRIBUTES_INFORMATION attrInfo)) throw new InvalidOperationException("This marshaler only works on AUTHZ_SECURITY_ATTRIBUTES_INFORMATION structures."); + if (ManagedObj is not AUTHZ_SECURITY_ATTRIBUTES_INFORMATION attrInfo) throw new InvalidOperationException("This marshaler only works on AUTHZ_SECURITY_ATTRIBUTES_INFORMATION structures."); var sz1 = Marshal.SizeOf(typeof(Internal_AUTHZ_SECURITY_ATTRIBUTES_INFORMATION)) + attrInfo.AttributeCount * Marshal.SizeOf(typeof(Internal_AUTHZ_SECURITY_ATTRIBUTE_V1)); var sz2 = 0L; @@ -3267,7 +3157,7 @@ namespace Vanara.PInvoke return new AUTHZ_SECURITY_ATTRIBUTES_INFORMATION(attrInfo.pAttributeV1 == IntPtr.Zero ? null : Array.ConvertAll(attrInfo.pAttributeV1.ToArray((int)attrInfo.AttributeCount), Conv)); - AUTHZ_SECURITY_ATTRIBUTE_V1 Conv(Internal_AUTHZ_SECURITY_ATTRIBUTE_V1 input) + static AUTHZ_SECURITY_ATTRIBUTE_V1 Conv(Internal_AUTHZ_SECURITY_ATTRIBUTE_V1 input) { var v1 = new AUTHZ_SECURITY_ATTRIBUTE_V1 { pName = StringHelper.GetString(input.pName, CharSet.Unicode), Flags = input.Flags, ValueCount = input.ValueCount, ValueType = input.ValueType }; switch (v1.ValueType) diff --git a/UnitTests/PInvoke/Security/Authz/AuthzTests.cs b/UnitTests/PInvoke/Security/Authz/AuthzTests.cs index cc4cc0b4..d42abe6c 100644 --- a/UnitTests/PInvoke/Security/Authz/AuthzTests.cs +++ b/UnitTests/PInvoke/Security/Authz/AuthzTests.cs @@ -1,8 +1,6 @@ using NUnit.Framework; using System; using System.Linq; -using System.Runtime.InteropServices; -using Vanara.Extensions; using Vanara.InteropServices; using static Vanara.PInvoke.AdvApi32; using static Vanara.PInvoke.Authz; @@ -15,198 +13,165 @@ namespace Vanara.PInvoke.Tests { public static SafeAUTHZ_AUDIT_EVENT_HANDLE GetAuthzInitializeObjectAccessAuditEvent() { - var b = AuthzInitializeObjectAccessAuditEvent(AuthzAuditEventFlags.AUTHZ_NO_ALLOC_STRINGS, IntPtr.Zero, "", "", "", "", out var hEvt); - if (!b) TestContext.WriteLine($"AuthzInitializeObjectAccessAuditEvent:{Win32Error.GetLastError()}"); - Assert.That(b); + Assert.That(AuthzInitializeObjectAccessAuditEvent(AuthzAuditEventFlags.AUTHZ_NO_ALLOC_STRINGS, IntPtr.Zero, "", "", "", "", out SafeAUTHZ_AUDIT_EVENT_HANDLE hEvt), ResultIs.Successful); Assert.That(!hEvt.IsInvalid); return hEvt; } public static SafeAUTHZ_RESOURCE_MANAGER_HANDLE GetAuthzInitializeResourceManager() { - var b = AuthzInitializeResourceManager(AuthzResourceManagerFlags.AUTHZ_RM_FLAG_NO_AUDIT, null, null, null, "Test", out var hResMgr); - if (!b) TestContext.WriteLine($"AuthzInitializeResourceManager:{Win32Error.GetLastError()}"); - Assert.That(b); + Assert.That(AuthzInitializeResourceManager(AuthzResourceManagerFlags.AUTHZ_RM_FLAG_NO_AUDIT, null, null, null, "Test", out SafeAUTHZ_RESOURCE_MANAGER_HANDLE hResMgr), ResultIs.Successful); Assert.That(!hResMgr.IsInvalid); return hResMgr; } public static SafeHGlobalHandle GetCtxInfo(SafeAUTHZ_CLIENT_CONTEXT_HANDLE hCtx, AUTHZ_CONTEXT_INFORMATION_CLASS type) { - var b = AuthzGetInformationFromContext(hCtx, type, 0, out var szReq, IntPtr.Zero); - if (!b && Win32Error.GetLastError() != Win32Error.ERROR_INSUFFICIENT_BUFFER) TestContext.WriteLine($"AuthzGetInformationFromContext:{Win32Error.GetLastError()}"); + bool b = AuthzGetInformationFromContext(hCtx, type, 0, out uint szReq, IntPtr.Zero); + if (!b && Win32Error.GetLastError() != Win32Error.ERROR_INSUFFICIENT_BUFFER) + { + TestContext.WriteLine($"AuthzGetInformationFromContext:{Win32Error.GetLastError()}"); + } + Assert.That(!b); - if (szReq == 0) return SafeHGlobalHandle.Null; - var buf = new SafeHGlobalHandle((int)szReq); - b = AuthzGetInformationFromContext(hCtx, type, szReq, out szReq, (IntPtr)buf); - if (!b) TestContext.WriteLine($"AuthzGetInformationFromContext:{Win32Error.GetLastError()}"); - Assert.That(b); + if (szReq == 0) + { + return SafeHGlobalHandle.Null; + } + + SafeHGlobalHandle buf = new((int)szReq); + Assert.That(AuthzGetInformationFromContext(hCtx, type, szReq, out _, buf), ResultIs.Successful); return buf; } public static SafeAUTHZ_CLIENT_CONTEXT_HANDLE GetCurrentUserAuthContext(SafeAUTHZ_RESOURCE_MANAGER_HANDLE hResMgr) { - var b = AuthzInitializeContextFromSid(AuthzContextFlags.DEFAULT, SafePSID.Current, hResMgr, IntPtr.Zero, new LUID(), IntPtr.Zero, out var hCtx); - if (!b) TestContext.WriteLine($"AuthzInitializeContextFromSid:{Win32Error.GetLastError()}"); - Assert.That(b); + Assert.That(AuthzInitializeContextFromSid(AuthzContextFlags.DEFAULT, SafePSID.Current, hResMgr, IntPtr.Zero, new LUID(), IntPtr.Zero, out SafeAUTHZ_CLIENT_CONTEXT_HANDLE hCtx), ResultIs.Successful); Assert.That(!hCtx.IsInvalid); return hCtx; } public static SafeAUTHZ_CLIENT_CONTEXT_HANDLE GetTokenAuthContext(SafeAUTHZ_RESOURCE_MANAGER_HANDLE hRM) { - using (var hTok = SafeHTOKEN.FromProcess(GetCurrentProcess(), TokenAccess.TOKEN_QUERY)) - { - var b = AuthzInitializeContextFromToken(0, hTok, hRM, IntPtr.Zero, new LUID(), IntPtr.Zero, out var hCtx); - if (!b) TestContext.WriteLine($"AuthzAccessCheck:{Win32Error.GetLastError()}"); - Assert.That(b); - Assert.That(!hCtx.IsInvalid); - return hCtx; - } + using SafeHTOKEN hTok = SafeHTOKEN.FromProcess(GetCurrentProcess(), TokenAccess.TOKEN_QUERY); + Assert.That(AuthzInitializeContextFromToken(0, hTok, hRM, IntPtr.Zero, new LUID(), IntPtr.Zero, out SafeAUTHZ_CLIENT_CONTEXT_HANDLE hCtx), ResultIs.Successful); + Assert.That(!hCtx.IsInvalid); + return hCtx; } [Test] public void AuthzAddSidsToContextTest() { - using (var everyoneSid = ConvertStringSidToSid("S-1-1-0")) - using (var localSid = ConvertStringSidToSid("S-1-2-0")) - { - var sids = new SID_AND_ATTRIBUTES { Sid = everyoneSid, Attributes = (uint)GroupAttributes.SE_GROUP_ENABLED }; - var restrictedSids = new SID_AND_ATTRIBUTES { Sid = localSid, Attributes = (uint)GroupAttributes.SE_GROUP_ENABLED }; - using (var hRM = GetAuthzInitializeResourceManager()) - using (var hCtx = GetCurrentUserAuthContext(hRM)) - Assert.That(AuthzAddSidsToContext(hCtx, sids, 1, restrictedSids, 1, out var hNewCtx), Is.True); - } + using SafePSID everyoneSid = ConvertStringSidToSid("S-1-1-0"); + using SafePSID localSid = ConvertStringSidToSid("S-1-2-0"); + SID_AND_ATTRIBUTES sids = new() { Sid = everyoneSid, Attributes = (uint)GroupAttributes.SE_GROUP_ENABLED }; + SID_AND_ATTRIBUTES restrictedSids = new() { Sid = localSid, Attributes = (uint)GroupAttributes.SE_GROUP_ENABLED }; + using SafeAUTHZ_RESOURCE_MANAGER_HANDLE hRM = GetAuthzInitializeResourceManager(); + using SafeAUTHZ_CLIENT_CONTEXT_HANDLE hCtx = GetCurrentUserAuthContext(hRM); + Assert.That(AuthzAddSidsToContext(hCtx, sids, 1, restrictedSids, 1, out SafeAUTHZ_CLIENT_CONTEXT_HANDLE hNewCtx), ResultIs.Successful); } [Test] public void AuthzEnumerateSecurityEventSourcesTest() { - using (var mem = new SafeNativeArray(200)) - { - var sz = (uint)mem.Size; - var b = AuthzEnumerateSecurityEventSources(0, (IntPtr)mem, out var len, ref sz); - Assert.That(b, Is.True); - Assert.That(sz, Is.LessThanOrEqualTo(mem.Size)); - Assert.That(len, Is.GreaterThan(0)); - Assert.That(() => TestContext.WriteLine(string.Join("\n", mem.Take((int)len).Select(r => r.szEventSourceName.ToString()))), Throws.Nothing); - } - } - - [Test] - public void AuthzEnumerateSecurityEventSourcesTest2() - { - Assert.That(AuthzEnumerateSecurityEventSources(), Is.Not.Empty); + var srcs = AuthzEnumerateSecurityEventSources().ToArray(); + Assert.That(srcs, Is.Not.Empty); + Assert.That(() => TestContext.WriteLine(string.Join("\n", srcs.Select(r => r.szEventSourceName))), Throws.Nothing); } [Test] public void AuthzAccessCheckAndCachedTest() { - using (var hRM = GetAuthzInitializeResourceManager()) - using (var hCtx = GetCurrentUserAuthContext(hRM)) - using (var hEvt = GetAuthzInitializeObjectAccessAuditEvent()) - using (var psd = AdvApi32Tests.GetSD(TestCaseSources.SmallFile)) - using (var reply = new AUTHZ_ACCESS_REPLY(1)) - { - var req = new AUTHZ_ACCESS_REQUEST((uint)ACCESS_MASK.MAXIMUM_ALLOWED); - var b = AuthzAccessCheck(AuthzAccessCheckFlags.NONE, hCtx, req, hEvt, psd, null, 0, reply, out var hRes); - if (!b) TestContext.WriteLine($"AuthzAccessCheck:{Win32Error.GetLastError()}"); - Assert.That(b); - Assert.That(reply.GrantedAccessMask, Is.Not.EqualTo(IntPtr.Zero)); - TestContext.WriteLine($"Access:{string.Join(",", reply.GrantedAccessMaskValues.Select(u => ((FileAccess)u).ToString()))}"); + using SafeAUTHZ_RESOURCE_MANAGER_HANDLE hRM = GetAuthzInitializeResourceManager(); + using SafeAUTHZ_CLIENT_CONTEXT_HANDLE hCtx = GetCurrentUserAuthContext(hRM); + using SafeAUTHZ_AUDIT_EVENT_HANDLE hEvt = GetAuthzInitializeObjectAccessAuditEvent(); + using SafePSECURITY_DESCRIPTOR psd = AdvApi32Tests.GetSD(TestCaseSources.SmallFile); + using AUTHZ_ACCESS_REPLY reply = new(1); + AUTHZ_ACCESS_REQUEST req = new(ACCESS_MASK.MAXIMUM_ALLOWED); + Assert.That(AuthzAccessCheck(AuthzAccessCheckFlags.NONE, hCtx, req, hEvt, psd, null, 0, reply, out SafeAUTHZ_ACCESS_CHECK_RESULTS_HANDLE hRes), ResultIs.Successful); + Assert.That(reply.GrantedAccessMask, Is.Not.EqualTo(IntPtr.Zero)); + TestContext.WriteLine($"Access:{string.Join(",", reply.GrantedAccessMaskValues.Select(u => ((FileAccess)u).ToString()))}"); - Assert.That(AuthzCachedAccessCheck(0, hRes, req, default, reply), Is.True); + Assert.That(AuthzCachedAccessCheck(0, hRes, req, default, reply), Is.True); - hRes.Dispose(); - Assert.That(hRes.IsClosed); + hRes.Dispose(); + Assert.That(hRes.IsClosed); - Assert.That(AuthzFreeCentralAccessPolicyCache(), Is.True); - } + Assert.That(AuthzFreeCentralAccessPolicyCache(), Is.True); } [Test] public void AuthzGetInformationFromContextTest() { - using (var hRM = GetAuthzInitializeResourceManager()) - using (var hCtx = GetCurrentUserAuthContext(hRM)) - { - var buf = GetCtxInfo(hCtx, AUTHZ_CONTEXT_INFORMATION_CLASS.AuthzContextInfoGroupsSids); - var tg = buf.ToStructure(); - Assert.That(tg.GroupCount, Is.GreaterThan(0)); + using SafeAUTHZ_RESOURCE_MANAGER_HANDLE hRM = GetAuthzInitializeResourceManager(); + using SafeAUTHZ_CLIENT_CONTEXT_HANDLE hCtx = GetCurrentUserAuthContext(hRM); + SafeHGlobalHandle buf = GetCtxInfo(hCtx, AUTHZ_CONTEXT_INFORMATION_CLASS.AuthzContextInfoGroupsSids); + TOKEN_GROUPS tg = buf.ToStructure(); + Assert.That(tg.GroupCount, Is.GreaterThan(0)); - buf = GetCtxInfo(hCtx, AUTHZ_CONTEXT_INFORMATION_CLASS.AuthzContextInfoUserClaims); - var ai = AUTHZ_SECURITY_ATTRIBUTES_INFORMATION.FromPtr((IntPtr)buf); - if (ai == null) return; - Assert.That(ai.Version, Is.EqualTo(1)); - TestContext.WriteLine($"AuthzGetInformationFromContext(AuthzContextInfoUserClaims)={ai.AttributeCount}"); + buf = GetCtxInfo(hCtx, AUTHZ_CONTEXT_INFORMATION_CLASS.AuthzContextInfoUserClaims); + AUTHZ_SECURITY_ATTRIBUTES_INFORMATION ai = AUTHZ_SECURITY_ATTRIBUTES_INFORMATION.FromPtr(buf); + if (ai == null) + { + return; } + + Assert.That(ai.Version, Is.EqualTo(1)); + TestContext.WriteLine($"AuthzGetInformationFromContext(AuthzContextInfoUserClaims)={ai.AttributeCount}"); } [Test] public void AuthzInitializeCompoundContextTest() { - using (var hRM = GetAuthzInitializeResourceManager()) - using (var hCtx = GetCurrentUserAuthContext(hRM)) - using (var hDevCtx = GetTokenAuthContext(hRM)) - { - var b = AuthzInitializeCompoundContext(hCtx, hDevCtx, out var hCompCtx); - if (!b) TestContext.WriteLine($"AuthzAccessCheck:{Win32Error.GetLastError()}"); - Assert.That(b); - Assert.That(!hCompCtx.IsInvalid); - } + using SafeAUTHZ_RESOURCE_MANAGER_HANDLE hRM = GetAuthzInitializeResourceManager(); + using SafeAUTHZ_CLIENT_CONTEXT_HANDLE hCtx = GetCurrentUserAuthContext(hRM); + using SafeAUTHZ_CLIENT_CONTEXT_HANDLE hDevCtx = GetTokenAuthContext(hRM); + Assert.That(AuthzInitializeCompoundContext(hCtx, hDevCtx, out SafeAUTHZ_CLIENT_CONTEXT_HANDLE hCompCtx), ResultIs.Successful); + Assert.That(!hCompCtx.IsInvalid); } [Test] public void AuthzInitializeContextFromAuthzContextTest() { - using (var hRM = GetAuthzInitializeResourceManager()) - using (var hCtx = GetCurrentUserAuthContext(hRM)) - { - var b = AuthzInitializeContextFromAuthzContext(0, hCtx, long.MaxValue, new LUID(), new IntPtr(2), out var hNewCtx); - Assert.That(b, Is.True); - } + using SafeAUTHZ_RESOURCE_MANAGER_HANDLE hRM = GetAuthzInitializeResourceManager(); + using SafeAUTHZ_CLIENT_CONTEXT_HANDLE hCtx = GetCurrentUserAuthContext(hRM); + Assert.That(AuthzInitializeContextFromAuthzContext(0, hCtx, long.MaxValue, new LUID(), new IntPtr(2), out SafeAUTHZ_CLIENT_CONTEXT_HANDLE hNewCtx), ResultIs.Successful); } [Test] public void AuthzInitializeContextFromSidTest() { - using (var hRM = GetAuthzInitializeResourceManager()) - using (var hCtx = GetCurrentUserAuthContext(hRM)) - { - Assert.That(hCtx.IsInvalid, Is.False); - } + using SafeAUTHZ_RESOURCE_MANAGER_HANDLE hRM = GetAuthzInitializeResourceManager(); + using SafeAUTHZ_CLIENT_CONTEXT_HANDLE hCtx = GetCurrentUserAuthContext(hRM); + Assert.That(hCtx.IsInvalid, Is.False); } [Test] public void AuthzInitializeContextFromTokenTest() { - using (var hRM = GetAuthzInitializeResourceManager()) - using (var hDevCtx = GetTokenAuthContext(hRM)) - { - Assert.That(hDevCtx.IsInvalid, Is.False); - } + using SafeAUTHZ_RESOURCE_MANAGER_HANDLE hRM = GetAuthzInitializeResourceManager(); + using SafeAUTHZ_CLIENT_CONTEXT_HANDLE hDevCtx = GetTokenAuthContext(hRM); + Assert.That(hDevCtx.IsInvalid, Is.False); } [Test] public void AuthzInitializeObjectAccessAuditEventTest() { - using (var hEvent = GetAuthzInitializeObjectAccessAuditEvent()) - Assert.That(hEvent.IsInvalid, Is.False); + using SafeAUTHZ_AUDIT_EVENT_HANDLE hEvent = GetAuthzInitializeObjectAccessAuditEvent(); + Assert.That(hEvent.IsInvalid, Is.False); } [Test] public void AuthzInitializeObjectAccessAuditEvent2Test() { - var b = AuthzInitializeObjectAccessAuditEvent2(0, default, "", "", "", "", "", out var hEvent); - if (!b) TestContext.WriteLine($"AuthzInitializeObjectAccessAuditEvent2:{Win32Error.GetLastError()}"); - Assert.That(b, Is.True); + Assert.That(AuthzInitializeObjectAccessAuditEvent2(0, default, "", "", "", "", "", out SafeAUTHZ_AUDIT_EVENT_HANDLE hEvent), ResultIs.Successful); Assert.That(hEvent.IsInvalid, Is.False); } [Test] public void AuthzInitializeRemoteResourceManagerTest() { - var client = new AUTHZ_RPC_INIT_INFO_CLIENT + AUTHZ_RPC_INIT_INFO_CLIENT client = new() { version = AUTHZ_RPC_INIT_INFO_CLIENT.AUTHZ_RPC_INIT_INFO_CLIENT_VERSION_V1, ObjectUuid = "5fc860e0-6f6e-4fc2-83cd-46324f25e90b", @@ -214,173 +179,172 @@ namespace Vanara.PInvoke.Tests NetworkAddr = "192.168.0.1", Endpoint = "192.168.0.202[80]" }; - var b = AuthzInitializeRemoteResourceManager(client, out var hResMgr); - if (!b) TestContext.WriteLine($"AuthzInitializeResourceManager:{Win32Error.GetLastError()}"); - Assert.That(b); + Assert.That(AuthzInitializeRemoteResourceManager(client, out SafeAUTHZ_RESOURCE_MANAGER_HANDLE hResMgr), ResultIs.Successful); Assert.That(!hResMgr.IsInvalid); } [Test] - public void AuthzInitializeResourceManagerTest() - { - GetAuthzInitializeResourceManager(); - } + public void AuthzInitializeResourceManagerTest() => GetAuthzInitializeResourceManager(); [Test] public void AuthzInitializeResourceManagerExTest() { - var info = new AUTHZ_INIT_INFO + AUTHZ_INIT_INFO info = new() { version = AUTHZ_INIT_INFO.AUTHZ_INIT_INFO_VERSION_V1 }; - var b = AuthzInitializeResourceManagerEx(AuthzResourceManagerFlags.AUTHZ_RM_FLAG_NO_AUDIT, info, out var hResMgr); - if (!b) TestContext.WriteLine($"AuthzInitializeResourceManager:{Win32Error.GetLastError()}"); - Assert.That(b); + Assert.That(AuthzInitializeResourceManagerEx(AuthzResourceManagerFlags.AUTHZ_RM_FLAG_NO_AUDIT, info, out SafeAUTHZ_RESOURCE_MANAGER_HANDLE hResMgr), ResultIs.Successful); Assert.That(!hResMgr.IsInvalid); } [Test] public void AuthzModifyClaimsTest() { - using (var hRM = GetAuthzInitializeResourceManager()) - using (var hCtx = GetCurrentUserAuthContext(hRM)) - { - var attrs = new AUTHZ_SECURITY_ATTRIBUTES_INFORMATION(new[] { new AUTHZ_SECURITY_ATTRIBUTE_V1("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", Environment.UserName) }); - var b = AuthzModifyClaims(hCtx, AUTHZ_CONTEXT_INFORMATION_CLASS.AuthzContextInfoUserClaims, new[] { AUTHZ_SECURITY_ATTRIBUTE_OPERATION.AUTHZ_SECURITY_ATTRIBUTE_OPERATION_ADD }, attrs); - if (!b) TestContext.WriteLine($"AuthzModifyClaims:{Win32Error.GetLastError()}"); - Assert.That(b); - } + using SafeAUTHZ_RESOURCE_MANAGER_HANDLE hRM = GetAuthzInitializeResourceManager(); + using SafeAUTHZ_CLIENT_CONTEXT_HANDLE hCtx = GetCurrentUserAuthContext(hRM); + AUTHZ_SECURITY_ATTRIBUTES_INFORMATION attrs = new(new[] { new AUTHZ_SECURITY_ATTRIBUTE_V1("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", Environment.UserName) }); + Assert.That(AuthzModifyClaims(hCtx, AUTHZ_CONTEXT_INFORMATION_CLASS.AuthzContextInfoUserClaims, new[] { AUTHZ_SECURITY_ATTRIBUTE_OPERATION.AUTHZ_SECURITY_ATTRIBUTE_OPERATION_ADD }, attrs), ResultIs.Successful); } [Test] public void AuthzModifySecurityAttributesTest() { - using (var hRM = GetAuthzInitializeResourceManager()) - using (var hCtx = GetCurrentUserAuthContext(hRM)) - { - var attrs = new AUTHZ_SECURITY_ATTRIBUTES_INFORMATION(new[] { new AUTHZ_SECURITY_ATTRIBUTE_V1("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", Environment.UserName) }); - var b = AuthzModifySecurityAttributes(hCtx, new[] { AUTHZ_SECURITY_ATTRIBUTE_OPERATION.AUTHZ_SECURITY_ATTRIBUTE_OPERATION_ADD }, attrs); - if (!b) TestContext.WriteLine($"AuthzModifySecurityAttributes:{Win32Error.GetLastError()}"); - Assert.That(b); - } + using SafeAUTHZ_RESOURCE_MANAGER_HANDLE hRM = GetAuthzInitializeResourceManager(); + using SafeAUTHZ_CLIENT_CONTEXT_HANDLE hCtx = GetCurrentUserAuthContext(hRM); + AUTHZ_SECURITY_ATTRIBUTES_INFORMATION attrs = new(new[] { new AUTHZ_SECURITY_ATTRIBUTE_V1("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", Environment.UserName) }); + Assert.That(AuthzModifySecurityAttributes(hCtx, new[] { AUTHZ_SECURITY_ATTRIBUTE_OPERATION.AUTHZ_SECURITY_ATTRIBUTE_OPERATION_ADD }, attrs), ResultIs.Successful); } [Test] public void AuthzModifySidsTest() { - using (var hRM = GetAuthzInitializeResourceManager()) - using (var hCtx = GetCurrentUserAuthContext(hRM)) - { - var tg = new TOKEN_GROUPS(1); - var psid = new SafePSID("S-1-5-32-551"); - tg.Groups[0] = new SID_AND_ATTRIBUTES { Attributes = (uint)GroupAttributes.SE_GROUP_ENABLED, Sid = (IntPtr)psid }; - var b = AuthzModifySids(hCtx, AUTHZ_CONTEXT_INFORMATION_CLASS.AuthzContextInfoGroupsSids, new[] { AUTHZ_SID_OPERATION.AUTHZ_SID_OPERATION_ADD }, in tg); - if (!b) TestContext.WriteLine($"AuthzModifySids:{Win32Error.GetLastError()}"); - Assert.That(b); - } + using SafeAUTHZ_RESOURCE_MANAGER_HANDLE hRM = GetAuthzInitializeResourceManager(); + using SafeAUTHZ_CLIENT_CONTEXT_HANDLE hCtx = GetCurrentUserAuthContext(hRM); + TOKEN_GROUPS tg = new(1); + SafePSID psid = new("S-1-5-32-551"); + tg.Groups[0] = new SID_AND_ATTRIBUTES { Attributes = (uint)GroupAttributes.SE_GROUP_ENABLED, Sid = (IntPtr)psid }; + Assert.That(AuthzModifySids(hCtx, AUTHZ_CONTEXT_INFORMATION_CLASS.AuthzContextInfoGroupsSids, new[] { AUTHZ_SID_OPERATION.AUTHZ_SID_OPERATION_ADD }, in tg), ResultIs.Successful); } [Test] public void AuthzOpenObjectAuditTest() { - using (var hRM = GetAuthzInitializeResourceManager()) - using (var hCtx = GetCurrentUserAuthContext(hRM)) - using (var hEvt = GetAuthzInitializeObjectAccessAuditEvent()) - using (var psd = AdvApi32Tests.GetSD(TestCaseSources.SmallFile)) - using (var reply = new AUTHZ_ACCESS_REPLY(1)) - { - var req = new AUTHZ_ACCESS_REQUEST((uint)ACCESS_MASK.MAXIMUM_ALLOWED); - var b = AuthzOpenObjectAudit(0, hCtx, req, hEvt, psd, null, 0, reply); - if (!b) TestContext.WriteLine($"AuthzOpenObjectAudit:{Win32Error.GetLastError()}"); - Assert.That(b, Is.True); - } + using SafeAUTHZ_RESOURCE_MANAGER_HANDLE hRM = GetAuthzInitializeResourceManager(); + using SafeAUTHZ_CLIENT_CONTEXT_HANDLE hCtx = GetCurrentUserAuthContext(hRM); + using SafeAUTHZ_AUDIT_EVENT_HANDLE hEvt = GetAuthzInitializeObjectAccessAuditEvent(); + using SafePSECURITY_DESCRIPTOR psd = AdvApi32Tests.GetSD(TestCaseSources.SmallFile); + using AUTHZ_ACCESS_REPLY reply = new(1); + AUTHZ_ACCESS_REQUEST req = new(ACCESS_MASK.MAXIMUM_ALLOWED); + Assert.That(AuthzOpenObjectAudit(0, hCtx, req, hEvt, psd, null, 0, reply), ResultIs.Successful); } [Test] public void AuthzRegisterCapChangeNotificationTest() { - Assert.That(AuthzRegisterCapChangeNotification(out var hSub, callback, new IntPtr(2)), Is.True); + Assert.That(AuthzRegisterCapChangeNotification(out SafeAUTHZ_CAP_CHANGE_SUBSCRIPTION_HANDLE hSub, callback, new IntPtr(2)), Is.True); // TODO: Find way to make something happen Assert.That(AuthzUnregisterCapChangeNotification(hSub), Is.True); - uint callback(IntPtr lpThreadParameter) { Assert.That(lpThreadParameter.ToInt32(), Is.EqualTo(2)); return 0; } + static uint callback(IntPtr lpThreadParameter) { Assert.That(lpThreadParameter.ToInt32(), Is.EqualTo(2)); return 0; } } [Test] - public void SafeAUTHZ_SOURCE_SCHEMA_REGISTRATIONTest() + public void AuthzReportSecurityEventTest() { - const string eventSource = "TestEventSource"; - var guid = Guid.NewGuid(); - using (var srcReg = new SafeAUTHZ_SOURCE_SCHEMA_REGISTRATION { szEventSourceName = eventSource, szEventAccessStringsFile = @"%SystemRoot%\System32\MsObjs.dll", szObjectTypeName = "Obj1", pProviderGuid = guid }) + const int eventId = 4624; + const string eventFile = "Some random string"; + const string eventSource = "TestAddEventSource"; + + using (new ElevPriv("SeAuditPrivilege")) { - var nSrc = (AUTHZ_SOURCE_SCHEMA_REGISTRATION)srcReg; - Assert.That(nSrc.szEventSourceName.ToString(), Is.EqualTo(eventSource)); - Assert.That(nSrc.pProviderGuid, Is.Not.EqualTo(IntPtr.Zero)); - Assert.That(nSrc.dwObjectTypeNameCount, Is.EqualTo(1U)); - Assert.That(nSrc.ObjectTypeNames.szObjectTypeName.ToString(), Is.EqualTo("Obj1")); - Assert.That(null, Is.EqualTo((string)nSrc.szEventMessageFile)); - using (var srcReg2 = new SafeAUTHZ_SOURCE_SCHEMA_REGISTRATION(nSrc)) + AUTHZ_SOURCE_SCHEMA_REGISTRATION srcReg = new() { - Assert.That(srcReg2.szEventSourceName, Is.EqualTo(eventSource)); - Assert.That(srcReg2.pProviderGuid.HasValue, Is.True); - Assert.That(srcReg2.pProviderGuid.Value, Is.EqualTo(guid)); - Assert.That(srcReg2.szObjectTypeName, Is.EqualTo("Obj1")); - Assert.That(srcReg2.szEventMessageFile, Is.Null); + dwFlags = SOURCE_SCHEMA_REGISTRATION_FLAGS.AUTHZ_ALLOW_MULTIPLE_SOURCE_INSTANCES, + szEventSourceName = eventSource, + szEventMessageFile = eventFile, + szEventAccessStringsFile = eventFile, + }; + Assert.IsTrue(AuthzInstallSecurityEventSource(0, srcReg) || Win32Error.GetLastError() == Win32Error.ERROR_OBJECT_ALREADY_EXISTS); + + Assert.That(AuthzRegisterSecurityEventSource(0, eventSource, out SafeAUTHZ_SECURITY_EVENT_PROVIDER_HANDLE hEvtProv), ResultIs.Successful); + try + { + Assert.That(AuthzReportSecurityEvent(APF.APF_AuditSuccess, hEvtProv, eventId, PSID.NULL, 6, __arglist( + AUDIT_PARAM_TYPE.APT_String, "Testing", + AUDIT_PARAM_TYPE.APT_Ulong, 123, + AUDIT_PARAM_TYPE.APT_Guid, (IntPtr)new SafeCoTaskMemStruct(Guid.NewGuid()), + AUDIT_PARAM_TYPE.APT_Sid, (IntPtr)SafePSID.Current, + AUDIT_PARAM_TYPE.APT_Int64, long.MaxValue - 1, + AUDIT_PARAM_TYPE.APT_Time, DateTime.Now.ToFileTime() + )), ResultIs.Successful); } + finally { Assert.That(() => hEvtProv.Dispose(), Throws.Nothing); } } } [Test] - public void AuthzRegisterSecurityEventSourceTest() + public void AuthzReportSecurityEventFromParamsTest() { - const string eventSource = "TestEventSource"; + const int eventId = 4624; + const string eventFile = "Some random string"; + const string eventSource = "TestAddEventSource"; using (new ElevPriv("SeAuditPrivilege")) { - var srcReg = new SafeAUTHZ_SOURCE_SCHEMA_REGISTRATION { szEventSourceName = eventSource, szEventAccessStringsFile = @"%SystemRoot%\System32\MsObjs.dll", szObjectTypeName = "Obj1", pProviderGuid = Guid.NewGuid() }; - Assert.That(AuthzInstallSecurityEventSource(0, srcReg), Is.True); - var b = AuthzRegisterSecurityEventSource(0, eventSource, out var hEvtProv); - if (!b) TestContext.WriteLine($"AuthzRegisterSecurityEventSource:{Win32Error.GetLastError()}"); - //Assert.That(b, Is.True); This is due to a Domain-defined Local policy - - if (b) + AUTHZ_SOURCE_SCHEMA_REGISTRATION srcReg = new() { - using (var data = new SafeHGlobalHandle("Testing")) - using (var mem = SafeHGlobalHandle.CreateFromStructure(new AUDIT_PARAM { Type = AUDIT_PARAM_TYPE.APT_String, Data0 = (IntPtr)data })) - { - var ap = new AUDIT_PARAMS { Count = 1, Parameters = (IntPtr)mem }; - b = AuthzReportSecurityEventFromParams(0, hEvtProv, 4624, PSID.NULL, ap); - if (!b) TestContext.WriteLine($"AuthzReportSecurityEvent:{Win32Error.GetLastError()}"); - Assert.That(b, Is.True); - } + dwFlags = SOURCE_SCHEMA_REGISTRATION_FLAGS.AUTHZ_ALLOW_MULTIPLE_SOURCE_INSTANCES, + szEventSourceName = eventSource, + szEventMessageFile = eventFile, + szEventAccessStringsFile = eventFile, + }; + Assert.IsTrue(AuthzInstallSecurityEventSource(0, srcReg) || Win32Error.GetLastError() == Win32Error.ERROR_OBJECT_ALREADY_EXISTS); - b = AuthzReportSecurityEvent(APF.APF_AuditSuccess, hEvtProv, 4624, PSID.NULL, 1, __arglist(AUDIT_PARAM_TYPE.APT_String, "Testing")); - if (!b) TestContext.WriteLine($"AuthzReportSecurityEvent:{Win32Error.GetLastError()}"); - Assert.That(b, Is.True); - - Assert.That(AuthzUnregisterSecurityEventSource(0, hEvtProv), Is.True); + Assert.That(AuthzRegisterSecurityEventSource(0, eventSource, out SafeAUTHZ_SECURITY_EVENT_PROVIDER_HANDLE hEvtProv), ResultIs.Successful); + try + { + using SafeCoTaskMemString data = new("Testing"); + //using SafeCoTaskMemString name = new("MyName"); + using SafeNativeArray mem = new(new[] { new AUDIT_PARAM { Type = AUDIT_PARAM_TYPE.APT_String, Data0 = data/*, Data1 = name*/ } }); + AUDIT_PARAMS ap = new() { Count = 1, Parameters = mem }; + Assert.That(AuthzReportSecurityEventFromParams(0, hEvtProv, eventId, PSID.NULL, ap), ResultIs.Successful); } + finally { Assert.That(() => hEvtProv.Dispose(), Throws.Nothing); } + } + } + [Test] + public void AuthzInstallSecurityEventSourceTest() + { + const string eventFile = "Some random string"; + const string eventSource = "InstTestEventSource"; + + using (new ElevPriv("SeAuditPrivilege")) + { + AUTHZ_SOURCE_SCHEMA_REGISTRATION srcReg = new() + { + dwFlags = SOURCE_SCHEMA_REGISTRATION_FLAGS.AUTHZ_ALLOW_MULTIPLE_SOURCE_INSTANCES, + szEventSourceName = eventSource, + szEventMessageFile = eventFile, + szEventAccessStringsFile = eventFile, + }; + Assert.That(AuthzInstallSecurityEventSource(0, srcReg), ResultIs.Successful); Assert.That(AuthzUninstallSecurityEventSource(0, eventSource), Is.True); } } // TODO: Figure out how AuthzSetAppContainerInformation works // [Test] - public void AuthzSetAppContainerInformationTest() + public void AuthzSetAppContainerInformationTest() { - using (var hRM = GetAuthzInitializeResourceManager()) - using (var hCtx = GetCurrentUserAuthContext(hRM)) - using (var localSid = ConvertStringSidToSid("S-1-2-0")) - using (var hTok = SafeHTOKEN.FromProcess(GetCurrentProcess(), TokenAccess.TOKEN_ALL_ACCESS)) - { - var i = hTok.GetInfo(TOKEN_INFORMATION_CLASS.TokenAppContainerSid); - //var sids = new SID_AND_ATTRIBUTES(localSid, (uint)GroupAttributes.SE_GROUP_ENABLED); - //var b = AuthzSetAppContainerInformation(hCtx, i.TokenAppContainer, 1, new[] { sids }); - var b = AuthzSetAppContainerInformation(hCtx, i.TokenAppContainer, 0, null); - if (!b) TestContext.WriteLine($"AuthzSetAppContainerInformation:{Win32Error.GetLastError()}"); - Assert.That(b, Is.True); - } + using SafeAUTHZ_RESOURCE_MANAGER_HANDLE hRM = GetAuthzInitializeResourceManager(); + using SafeAUTHZ_CLIENT_CONTEXT_HANDLE hCtx = GetCurrentUserAuthContext(hRM); + using SafePSID localSid = ConvertStringSidToSid("S-1-2-0"); + using SafeHTOKEN hTok = SafeHTOKEN.FromProcess(GetCurrentProcess(), TokenAccess.TOKEN_ALL_ACCESS); + TOKEN_APPCONTAINER_INFORMATION i = hTok.GetInfo(TOKEN_INFORMATION_CLASS.TokenAppContainerSid); + //var sids = new SID_AND_ATTRIBUTES(localSid, (uint)GroupAttributes.SE_GROUP_ENABLED); + //var b = AuthzSetAppContainerInformation(hCtx, i.TokenAppContainer, 1, new[] { sids }); + Assert.That(AuthzSetAppContainerInformation(hCtx, i.TokenAppContainer, 0, null), ResultIs.Successful); } } } \ No newline at end of file