using CPF.Mac.ObjCRuntime; using System; using System.Runtime.InteropServices; namespace CPF.Mac.Security { public class Authorization : INativeObject, IDisposable { private IntPtr handle; public IntPtr Handle => handle; [DllImport("/System/Library/Frameworks/Security.framework/Security")] private unsafe static extern int AuthorizationCreate(AuthorizationItemSet* rights, AuthorizationItemSet* environment, AuthorizationFlags flags, out IntPtr auth); [DllImport("/System/Library/Frameworks/Security.framework/Security")] private static extern int AuthorizationExecuteWithPrivileges(IntPtr handle, string pathToTool, AuthorizationFlags flags, string[] args, IntPtr FILEPtr); [DllImport("/System/Library/Frameworks/Security.framework/Security")] private static extern int AuthorizationFree(IntPtr handle, AuthorizationFlags flags); internal Authorization(IntPtr handle) { this.handle = handle; } public int ExecuteWithPrivileges(string pathToTool, AuthorizationFlags flags, string[] args) { return AuthorizationExecuteWithPrivileges(handle, pathToTool, flags, args, IntPtr.Zero); } public void Dispose() { GC.SuppressFinalize(this); Dispose(AuthorizationFlags.Defaults, disposing: true); } ~Authorization() { Dispose(AuthorizationFlags.Defaults, disposing: false); } public virtual void Dispose(AuthorizationFlags flags, bool disposing) { if (handle != IntPtr.Zero) { AuthorizationFree(handle, flags); handle = IntPtr.Zero; } } public static Authorization Create(AuthorizationFlags flags) { return Create(null, null, flags); } private static void EncodeString(ref AuthorizationItem item, string key, string value) { item.name = Messaging.NativeUtf8FromString(key); if (value != null) { item.value = Messaging.NativeUtf8FromString(value); item.valueLen = (IntPtr)value.Length; } } public unsafe static Authorization Create(AuthorizationParameters parameters, AuthorizationEnvironment environment, AuthorizationFlags flags) { AuthorizationItemSet authorizationItemSet = default(AuthorizationItemSet); AuthorizationItemSet* ptr = null; AuthorizationItem* ptr2 = null; AuthorizationItemSet authorizationItemSet2 = default(AuthorizationItemSet); AuthorizationItemSet* ptr3 = null; AuthorizationItem* ptr4 = null; try { if (parameters != null) { ptr = &authorizationItemSet; authorizationItemSet.ptrToAuthorization = (AuthorizationItem*)(void*)Marshal.AllocHGlobal(sizeof(AuthorizationItem) * 3); if (parameters.PathToSystemPrivilegeTool != null) { EncodeString(ref authorizationItemSet.ptrToAuthorization[authorizationItemSet.count++], "system.privilege.admin", parameters.PathToSystemPrivilegeTool); } if (parameters.Prompt != null) { EncodeString(ref authorizationItemSet.ptrToAuthorization[authorizationItemSet.count++], "prompt", parameters.Prompt); } if (parameters.IconPath != null) { EncodeString(ref authorizationItemSet.ptrToAuthorization[authorizationItemSet.count++], "prompt", parameters.IconPath); } } if (environment != null) { ptr3 = &authorizationItemSet2; authorizationItemSet2.ptrToAuthorization = (AuthorizationItem*)(void*)Marshal.AllocHGlobal(sizeof(AuthorizationItem) * 3); if (environment.Username != null) { EncodeString(ref authorizationItemSet2.ptrToAuthorization[authorizationItemSet2.count++], "username", environment.Username); } if (environment.Password != null) { EncodeString(ref authorizationItemSet2.ptrToAuthorization[authorizationItemSet2.count++], "password", environment.Password); } if (environment.AddToSharedCredentialPool) { EncodeString(ref authorizationItemSet2.ptrToAuthorization[authorizationItemSet2.count++], "shared", null); } } if (AuthorizationCreate(ptr, ptr3, flags, out IntPtr auth) != 0) { return null; } return new Authorization(auth); } finally { if (ptr != null) { for (int i = 0; i < authorizationItemSet.count; i++) { Marshal.FreeHGlobal(authorizationItemSet.ptrToAuthorization[i].name); Marshal.FreeHGlobal(authorizationItemSet.ptrToAuthorization[i].value); } Marshal.FreeHGlobal((IntPtr)(void*)authorizationItemSet.ptrToAuthorization); } if (ptr3 != null) { for (int j = 0; j < authorizationItemSet2.count; j++) { Marshal.FreeHGlobal(authorizationItemSet2.ptrToAuthorization[j].name); if (authorizationItemSet2.ptrToAuthorization[j].value != IntPtr.Zero) { Marshal.FreeHGlobal(authorizationItemSet2.ptrToAuthorization[j].value); } } Marshal.FreeHGlobal((IntPtr)(void*)authorizationItemSet2.ptrToAuthorization); } } } } }