CPF/CPF.Mac/Mac/Security/Authorization.cs
2023-11-21 23:05:03 +08:00

144 lines
4.7 KiB
C#

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