-
Notifications
You must be signed in to change notification settings - Fork 565
[SecurityInterface] Add complete bindings for SecurityInterface framework (macOS only) #25141
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: xcode26.5
Are you sure you want to change the base?
Changes from all commits
6a6d313
6e80cfd
461337c
c729087
27c06f4
a56e257
1d97e40
6fdcda2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| #if __MACOS__ | ||
| #nullable enable | ||
|
|
||
| using System; | ||
| using System.Runtime.Versioning; | ||
| using CoreFoundation; | ||
| using ObjCRuntime; | ||
|
|
||
| namespace Security { | ||
|
|
||
| /// <summary>Represents an opaque reference to an authorization engine used in authorization plugin views.</summary> | ||
| public class AuthorizationEngine : NativeObject { | ||
| [Preserve (Conditional = true)] | ||
| internal AuthorizationEngine (NativeHandle handle, bool owns) | ||
| : base (handle, owns) | ||
| { | ||
| } | ||
| #if !COREBUILD | ||
| /// <summary>Creates an <see cref="AuthorizationEngine" /> from a raw handle without taking ownership.</summary> | ||
| /// <param name="handle">The native <c>AuthorizationEngineRef</c> handle.</param> | ||
| /// <returns>A managed wrapper, or <see langword="null" /> if the handle is zero.</returns> | ||
| public static AuthorizationEngine? Create (NativeHandle handle) | ||
| { | ||
| if (handle == IntPtr.Zero) | ||
| return null; | ||
| return new AuthorizationEngine (handle, owns: false); | ||
| } | ||
| #endif // !COREBUILD | ||
| } | ||
| } | ||
| #endif // __MACOS__ |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,100 @@ | ||||||
| #if __MACOS__ | ||||||
| #nullable enable | ||||||
|
|
||||||
| using System; | ||||||
| using System.Runtime.InteropServices; | ||||||
| using System.Runtime.Versioning; | ||||||
| using ObjCRuntime; | ||||||
| using CoreFoundation; | ||||||
|
|
||||||
| namespace Security { | ||||||
|
|
||||||
| /// <summary>Represents a keychain on macOS.</summary> | ||||||
| public class SecKeychain : NativeObject { | ||||||
| [Preserve (Conditional = true)] | ||||||
| internal SecKeychain (NativeHandle handle, bool owns) | ||||||
| : base (handle, owns) | ||||||
| { | ||||||
| } | ||||||
| #if !COREBUILD | ||||||
| [SupportedOSPlatform ("macos")] | ||||||
| [ObsoletedOSPlatform ("macos10.10")] | ||||||
| [DllImport (Constants.SecurityLibrary)] | ||||||
| extern static unsafe int /* OSStatus */ SecKeychainGetTypeID (); | ||||||
|
|
||||||
| /// <summary>Returns the Core Foundation type identifier for SecKeychain.</summary> | ||||||
| /// <returns>The Core Foundation type identifier.</returns> | ||||||
| public static nint GetTypeID () | ||||||
| { | ||||||
| return SecKeychainGetTypeID (); | ||||||
| } | ||||||
|
|
||||||
| [SupportedOSPlatform ("macos")] | ||||||
| [ObsoletedOSPlatform ("macos10.10")] | ||||||
| [DllImport (Constants.SecurityLibrary)] | ||||||
| extern static unsafe int /* OSStatus */ SecKeychainCopyDefault (IntPtr* keychain); | ||||||
|
|
||||||
| /// <summary>Gets the default keychain.</summary> | ||||||
| /// <returns>The default <see cref="SecKeychain" />, or <see langword="null" /> on failure.</returns> | ||||||
| public static SecKeychain? GetDefault () | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we should provide the status code as an out argument?
Suggested change
|
||||||
| { | ||||||
| IntPtr handle; | ||||||
| int status; | ||||||
| unsafe { | ||||||
| status = SecKeychainCopyDefault (&handle); | ||||||
| } | ||||||
| if (status != 0 || handle == IntPtr.Zero) | ||||||
| return null; | ||||||
| return new SecKeychain (handle, owns: true); | ||||||
| } | ||||||
|
|
||||||
| [SupportedOSPlatform ("macos")] | ||||||
| [ObsoletedOSPlatform ("macos10.10")] | ||||||
| [DllImport (Constants.SecurityLibrary)] | ||||||
| extern static unsafe int /* OSStatus */ SecKeychainOpen (IntPtr pathName, IntPtr* keychain); | ||||||
|
|
||||||
| /// <summary>Opens the keychain at the specified file path.</summary> | ||||||
| /// <param name="path">The file system path of the keychain to open.</param> | ||||||
| /// <returns>A <see cref="SecKeychain" /> for the specified path, or <see langword="null" /> on failure.</returns> | ||||||
| public static SecKeychain? Open (string path) | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nullability wise, the
Suggested change
|
||||||
| { | ||||||
| if (path is null) | ||||||
| ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (path)); | ||||||
| using var pathStr = new TransientString (path); | ||||||
| IntPtr handle; | ||||||
| int status; | ||||||
| unsafe { | ||||||
| status = SecKeychainOpen (pathStr, &handle); | ||||||
| } | ||||||
| if (status != 0 || handle == IntPtr.Zero) | ||||||
| return null; | ||||||
| return new SecKeychain (handle, owns: true); | ||||||
| } | ||||||
|
|
||||||
| [SupportedOSPlatform ("macos")] | ||||||
| [ObsoletedOSPlatform ("macos10.10")] | ||||||
| [DllImport (Constants.SecurityLibrary)] | ||||||
| extern static unsafe int /* OSStatus */ SecKeychainGetPath (IntPtr keychainRef, int* ioPathLength, IntPtr pathName); | ||||||
|
|
||||||
| /// <summary>Gets the file system path of this keychain.</summary> | ||||||
| /// <returns>The POSIX path of the keychain, or <see langword="null" /> on failure.</returns> | ||||||
| public string? GetPath () | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Provide the status code as an |
||||||
| { | ||||||
| int pathLength = 1024; | ||||||
| IntPtr buffer = Marshal.AllocHGlobal (pathLength); | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use a byte array (of length |
||||||
| try { | ||||||
| int status; | ||||||
| unsafe { | ||||||
| status = SecKeychainGetPath (Handle, &pathLength, buffer); | ||||||
| } | ||||||
| if (status != 0) | ||||||
| return null; | ||||||
| return Marshal.PtrToStringUTF8 (buffer, pathLength); | ||||||
| } finally { | ||||||
| Marshal.FreeHGlobal (buffer); | ||||||
| } | ||||||
| } | ||||||
| #endif // !COREBUILD | ||||||
| } | ||||||
| } | ||||||
| #endif // __MACOS__ | ||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,50 @@ | ||||||
| #if __MACOS__ | ||||||
| #nullable enable | ||||||
|
|
||||||
| using System; | ||||||
| using System.Runtime.InteropServices; | ||||||
| using System.Runtime.Versioning; | ||||||
|
|
||||||
| namespace Security { | ||||||
|
|
||||||
| /// <summary>Represents keychain settings for lock behavior on macOS.</summary> | ||||||
| [StructLayout (LayoutKind.Sequential)] | ||||||
| public struct SecKeychainSettings { | ||||||
| int /* UInt32 */ version; | ||||||
| byte /* Boolean */ lockOnSleep; | ||||||
| byte /* Boolean */ useLockInterval; | ||||||
| int /* UInt32 */ lockInterval; | ||||||
|
|
||||||
| /// <summary>Gets or sets the version of this settings structure.</summary> | ||||||
| public int Version { | ||||||
| get => version; | ||||||
| set => version = value; | ||||||
| } | ||||||
|
|
||||||
| /// <summary>Gets or sets whether the keychain locks when the system sleeps.</summary> | ||||||
| public bool LockOnSleep { | ||||||
| get => lockOnSleep != 0; | ||||||
| set => lockOnSleep = value ? (byte) 1 : (byte) 0; | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's an
Suggested change
|
||||||
| } | ||||||
|
|
||||||
| /// <summary>Gets or sets whether the lock interval is used.</summary> | ||||||
| public bool UseLockInterval { | ||||||
| get => useLockInterval != 0; | ||||||
| set => useLockInterval = value ? (byte) 1 : (byte) 0; | ||||||
| } | ||||||
|
|
||||||
| /// <summary>Gets or sets the number of seconds before the keychain auto-locks.</summary> | ||||||
| public int LockInterval { | ||||||
| get => lockInterval; | ||||||
| set => lockInterval = value; | ||||||
| } | ||||||
|
|
||||||
| /// <summary>Creates a new <see cref="SecKeychainSettings" /> with the current version.</summary> | ||||||
| /// <returns>A new <see cref="SecKeychainSettings" /> initialized with version 1.</returns> | ||||||
| public static SecKeychainSettings Create () | ||||||
| { | ||||||
| return new SecKeychainSettings { version = 1 }; | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
| #endif // __MACOS__ | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.