[SecurityInterface] Add complete bindings for SecurityInterface framework (macOS only)#25141
[SecurityInterface] Add complete bindings for SecurityInterface framework (macOS only)#25141
Conversation
…work (macOS only) Add C# bindings for Apple's SecurityInterface framework, which provides UI components for security operations on macOS: certificate viewers, trust panels, identity choosers, keychain management panels, and authorization plugin views. This resolves all 108 entries in macOS-SecurityInterface.todo. ## Bound Types (9 ObjC classes + 3 informal protocol delegates) - SFAuthorizationPluginView: Host view for loginwindow authorization plugins - SFAuthorizationView: Lock icon view for controlling privileged operations - SFAuthorizationViewDelegate: Informal protocol for auth state changes - SFCertificatePanel: Panel displaying one or more certificates - SFCertificatePanelDelegate: Informal protocol for help button handling - SFCertificateTrustPanel: Panel for trust decisions on unverified certs - SFCertificateView: View displaying certificate contents with disclosure - SFChooseIdentityPanel: Panel for choosing a digital identity - SFChooseIdentityPanelDelegate: Informal protocol for help button handling - SFChooseIdentityTableCellView: Cell view in the identity chooser - SFKeychainSavePanel: NSSavePanel-based UI for creating keychains - SFKeychainSettingsPanel: Panel for editing keychain lock settings ## Enums (3) - SFAuthorizationViewState: Startup, Locked, InProgress, Unlocked - SFButtonType: Cancel, Ok, Back, Login - SFViewType: IdentityAndCredentials, Credentials These are plain C enums (not NS_ENUM), bound with ': int' backing. ## Fields (4) - SFAuthorizationPluginViewUserNameKey / UserShortNameKey - SFCertificateViewDisclosureStateDidChange (Notification) - SFDisplayViewException ## New Managed Types in Security Namespace - SecKeychain: NativeObject wrapper for SecKeychainRef. Provides GetDefault(), Open(path), GetPath(), GetTypeID(). All P/Invokes use blittable unsafe pointer signatures with TransientString for string marshaling. P/Invokes marked [ObsoletedOSPlatform(macos10.10)] matching the native API deprecation. Guarded with #if __MACOS__ to prevent leaking onto iOS/tvOS/MacCatalyst. - SecKeychainSettings: Blittable managed struct matching the native SecKeychainSettings layout. Uses byte backing fields for Boolean members with property accessors. Guarded with #if __MACOS__. - AuthorizationEngine: NativeObject wrapper for the opaque AuthorizationEngineRef. Guarded with #if __MACOS__. Registered as a bgen marshal type with conditional TypeCache lookup (frameworks.HaveSecurityInterface) so it only resolves on macOS. ## New Managed Types in SecurityInterface Namespace - AuthorizationCallbacks: INativeObject (non-owning) wrapper around the native AuthorizationCallbacks struct. Uses delegate* unmanaged<> function pointer fields in a blittable native struct layout. Provides safe managed methods: SetResult, RequestInterrupt, DidDeactivate, Get/SetContextValue, Get/SetHintValue, RemoveHintValue, RemoveContextValue. All methods take AuthorizationEngine + string keys, marshal strings via fixed UTF-8 byte arrays, and call GC.KeepAlive on NativeObject parameters. - AuthorizationRights: IDisposable + INativeObject + IReadOnlyList collection that owns allocated unmanaged memory for AuthorizationItem arrays. Supports construction from string arrays or AuthorizationRight structs. FromHandle() clones native data into managed ownership. Properly frees all allocated name strings, value buffers, and the items array on Dispose. - AuthorizationRight: Readonly struct for individual right items with Name (string), Value (byte[]?), and Flags (uint). Value is defensively copied on construction and access. - AuthorizationResult: Enum (Allow, Deny, Undefined, UserCanceled) - AuthorizationContextFlags: Flags enum (Extractable, Volatile, Sticky) ## bgen Marshal Type Registration - SecCertificate: NEW marshal type registration (TypeCache + MarshalTypeList). Generates Runtime.GetINativeObject<SecCertificate> marshaling for properties and return values. - SecKeychain, AuthorizationEngine: Conditional marshal types, only registered when frameworks.HaveSecurityInterface is true. Uses ConditionalLookup in TypeCache to avoid BI1052 on non-macOS platforms. ## Manual Wrappers (replacing [Internal] IntPtr bgen definitions) - SFAuthorizationPluginView: Public constructor taking AuthorizationCallbacks + AuthorizationEngine. Public Callbacks property returning AuthorizationCallbacks?. - SFAuthorizationView: SetAuthorizationString(string) using TransientString for blittable C string marshaling (avoiding bgen's non-blittable [PlainString] Messaging P/Invokes). AuthorizationRightsSet property (get/set) wrapping the internal IntPtr with AuthorizationRights.FromHandle / Handle. ## Informal Protocol Handling All three delegate protocols (SFAuthorizationViewDelegate, SFCertificatePanelDelegate, SFChooseIdentityPanelDelegate) are declared as NSObject categories in the native headers, not @protocol. Bound with [Protocol(IsInformal = true, BackwardsCompatibleCodeGeneration = false)]. The 8 NSObject category selectors are in macOS-SecurityInterface.ignore because xtro sees them on NSObject, not on the formal protocol. ## Platform Availability No [Mac(X,Y)] or [NoiOS/NoTV/NoMacCatalyst] attributes on types because all APIs predate the minimum macOS 12.0. The framework being listed only in MACOS_FRAMEWORKS (frameworks.sources) handles platform exclusion. Security/* types use #if __MACOS__ to prevent compilation on other platforms. ## Test Known Failure Entries - HandleSafety.KnownFailures (9 entries): AuthorizationCallbacks methods that call engine.GetNonNullHandle() followed by GC.KeepAlive(engine). The IL analyzer cannot trace liveness through delegate* unmanaged<> function pointer calls (a novel pattern in this codebase), so it conservatively flags them as unsafe Handle accesses. The code IS safe — GC.KeepAlive is called after every function pointer invocation. This matches the pattern of 200+ existing entries (e.g. Security.SecRecord, CoreFoundation.CFArray). - ApiTest.KnownFailures/BannedAttributes (2 entries): [Preserve(Conditional = true)] on the internal (NativeHandle, bool) constructors of AuthorizationEngine and SecKeychain. The test prefers [DynamicDependency] but every NativeObject subclass in the repo uses [Preserve] — SecCertificate, SecIdentity, SecKey, SecPolicy, SecTrust all have the same entry. Following established convention. - ConstructorTest exclusion (1 entry): AuthorizationCallbacks is INativeObject (not NativeObject) with a non-owning (NativeHandle) constructor. Added to the skip list alongside AudioBuffers, AURenderEventEnumerator, and other non-refcounted INativeObject types. - HandleSafety.cs exclusion (2 entries): AuthorizationCallbacks and AuthorizationRights get_Handle() marked safe (non-owning pointer wrapper and IDisposable-managed memory, respectively). - Documentation.KnownFailures (2 entries): bgen-generated Dispose(bool) overrides on SFAuthorizationView and SFChooseIdentityTableCellView that cannot have XML docs added in source. ## Monotouch Tests (9 test files, 40+ tests) All tests are macOS-only (#if __MACOS__): - SecKeychainTest: GetTypeID, GetDefault, GetPath, Open, null handling - SecKeychainSettingsTest: Create, property round-trips, struct size - AuthorizationRightsTest: Construction, enumeration, dispose, copying - AuthorizationManualBindingsTest: - AuthorizationCallbacksTest: Version reads from fake native struct, handle wrapping, live memory updates - AuthorizationEngineTest: Create factory null/non-null paths - AuthorizationRightsRoundTripTest: Native handle round-trip with names+values+flags, 100-item sets, Unicode names, empty vs null - SFAuthorizationPluginViewManualTest: ObjC class existence check - SFAuthorizationViewTest: Constructor, state, SetAuthorizationString, AuthorizationRightsSet get/set, delegate, flags, autoupdate - SFCertificateViewTest: Constructor, certificate get/set, trust/detail properties, disclosure notification field - SFCertificatePanelTest: Shared instances, CertificateView, help/titles - SFChooseIdentityPanelTest: Shared instance, properties, TableCellView - SFKeychainPanelTest: SavePanel/SettingsPanel shared instances - SFFieldsAndEnumsTest: All enum values, all Field constants Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
5e6de9f to
6a6d313
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
- Add SecurityInterface.framework to expectedFrameworks_macOS_None in LinkedWithNativeLibraries test (new framework linked at build time) - Update MacOSX-CoreCLR-Interpreter app size baseline (+140KB for new SecurityInterface bindings in the macOS assembly) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
- Remove AuthorizationEngine.Create_NonZero test: creating a NativeObject with a fake handle (0x12345678) causes CFRetain to segfault when the GC finalizes the object. - Remove SFAuthorizationView.AuthorizationRightsSet_SetAndGet and SetNull tests: the native SFAuthorizationView._copyAuthorizationRights crashes (null dereference) when calling setAuthorizationRights: with a null or freshly-allocated AuthorizationRights pointer. The native API requires a properly initialized SFAuthorization context. - Fix SFCertificatePanelTest.CertificateView: SharedCertificatePanel's CertificateView returns null until the panel is presented. Remove non-null assertion. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
3652ba4 to
5872e6a
Compare
5872e6a to
dfbcfef
Compare
This comment has been minimized.
This comment has been minimized.
Comprehensive macOS app exercising SecurityInterface bindings: Tab 1 - Authorization View: - SFAuthorizationView embedded in window with lock icon - AuthorizationViewDelegate callbacks for state changes - AuthorizationRights creation and management - Authorization state display Tab 2 - Certificate Viewer: - SFCertificateView displaying default keychain certs - Certificate detail/trust/policy disclosure controls - SecCertificate integration Tab 3 - Panels: - SFCertificatePanel as sheet with custom button titles - SFCertificateTrustPanel with informative text - SFChooseIdentityPanel with domain and message - SFKeychainSavePanel for keychain creation Tab 4 - Keychain: - SecKeychain.GetDefault() and GetPath() - SecKeychain.Open() for login keychain - SecKeychainSettings struct round-trip - SecKeychain.GetTypeID() Tab 5 - Manual Bindings: - AuthorizationRights creation, enumeration, round-trip - AuthorizationCallbacks structural test - AuthorizationRight value/flag inspection - All enum values and field constants Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
dfbcfef to
27c06f4
Compare
This reverts commit 27c06f4.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
✅ [CI Build #6fdcda2] Build passed (Build packages) ✅Pipeline on Agent |
✅ [PR Build #6fdcda2] Build passed (Detect API changes) ✅Pipeline on Agent |
✅ API diff for current PR / commitNET (empty diffs)✅ API diff vs stableNET (empty diffs)ℹ️ Generator diffGenerator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes) Pipeline on Agent |
✅ [CI Build #6fdcda2] Build passed (Build macOS tests) ✅Pipeline on Agent |
🚀 [CI Build #6fdcda2] Test results 🚀Test results✅ All tests passed on VSTS: test results. 🎉 All 158 tests passed 🎉 Tests counts✅ cecil: All 1 tests passed. Html Report (VSDrops) Download macOS tests✅ Tests on macOS Monterey (12): All 5 tests passed. Html Report (VSDrops) Download Linux Build VerificationPipeline on Agent |
Add C# bindings for Apple's SecurityInterface framework, which provides UI components for security operations on macOS: certificate viewers, trust panels, identity choosers, keychain management panels, and authorization plugin views.
This resolves all 108 entries in macOS-SecurityInterface.todo.
Bound Types (9 ObjC classes + 3 informal protocol delegates)
Enums (3)
These are plain C enums (not NS_ENUM), bound with ': int' backing.
Fields (4)
New Managed Types in Security Namespace
SecKeychain: NativeObject wrapper for SecKeychainRef. Provides GetDefault(), Open(path), GetPath(), GetTypeID(). All P/Invokes use blittable unsafe pointer signatures with TransientString for string marshaling. P/Invokes marked [ObsoletedOSPlatform(macos10.10)] matching the native API deprecation. Guarded with #if MACOS to prevent leaking onto iOS/tvOS/MacCatalyst.
SecKeychainSettings: Blittable managed struct matching the native SecKeychainSettings layout. Uses byte backing fields for Boolean members with property accessors. Guarded with #if MACOS.
AuthorizationEngine: NativeObject wrapper for the opaque AuthorizationEngineRef. Guarded with #if MACOS. Registered as a bgen marshal type with conditional TypeCache lookup (frameworks.HaveSecurityInterface) so it only resolves on macOS.
New Managed Types in SecurityInterface Namespace
AuthorizationCallbacks: INativeObject (non-owning) wrapper around the native AuthorizationCallbacks struct. Uses delegate* unmanaged<> function pointer fields in a blittable native struct layout. Provides safe managed methods: SetResult, RequestInterrupt, DidDeactivate, Get/SetContextValue, Get/SetHintValue, RemoveHintValue, RemoveContextValue. All methods take AuthorizationEngine + string keys, marshal strings via fixed UTF-8 byte arrays, and call GC.KeepAlive on NativeObject parameters.
AuthorizationRights: IDisposable + INativeObject + IReadOnlyList collection that owns allocated unmanaged memory for AuthorizationItem arrays. Supports construction from string arrays or AuthorizationRight structs. FromHandle() clones native data into managed ownership. Properly frees all allocated name strings, value buffers, and the items array on Dispose.
AuthorizationRight: Readonly struct for individual right items with Name (string), Value (byte[]?), and Flags (uint). Value is defensively copied on construction and access.
AuthorizationResult: Enum (Allow, Deny, Undefined, UserCanceled)
AuthorizationContextFlags: Flags enum (Extractable, Volatile, Sticky)
bgen Marshal Type Registration
SecCertificate: NEW marshal type registration (TypeCache + MarshalTypeList). Generates Runtime.GetINativeObject marshaling for properties and return values.
SecKeychain, AuthorizationEngine: Conditional marshal types, only registered when frameworks.HaveSecurityInterface is true. Uses ConditionalLookup in TypeCache to avoid BI1052 on non-macOS platforms.
Manual Wrappers (replacing [Internal] IntPtr bgen definitions)
SFAuthorizationPluginView: Public constructor taking AuthorizationCallbacks + AuthorizationEngine. Public Callbacks property returning AuthorizationCallbacks?.
SFAuthorizationView: SetAuthorizationString(string) using TransientString for blittable C string marshaling (avoiding bgen's non-blittable [PlainString] Messaging P/Invokes). AuthorizationRightsSet property (get/set) wrapping the internal IntPtr with AuthorizationRights.FromHandle / Handle.
Informal Protocol Handling
All three delegate protocols (SFAuthorizationViewDelegate, SFCertificatePanelDelegate, SFChooseIdentityPanelDelegate) are declared as NSObject categories in the native headers, not @protocol. Bound with [Protocol(IsInformal = true, BackwardsCompatibleCodeGeneration = false)]. The 8 NSObject category selectors are in macOS-SecurityInterface.ignore because xtro sees them on NSObject, not on the formal protocol.
Platform Availability
No [Mac(X,Y)] or [NoiOS/NoTV/NoMacCatalyst] attributes on types because all APIs predate the minimum macOS 12.0. The framework being listed only in MACOS_FRAMEWORKS (frameworks.sources) handles platform exclusion. Security/* types use #if MACOS to prevent compilation on other platforms.
Test Known Failure Entries
HandleSafety.KnownFailures (9 entries): AuthorizationCallbacks methods that call engine.GetNonNullHandle() followed by GC.KeepAlive(engine). The IL analyzer cannot trace liveness through delegate* unmanaged<> function pointer calls (a novel pattern in this codebase), so it conservatively flags them as unsafe Handle accesses. The code IS safe — GC.KeepAlive is called after every function pointer invocation. This matches the pattern of 200+ existing entries (e.g. Security.SecRecord, CoreFoundation.CFArray).
ApiTest.KnownFailures/BannedAttributes (2 entries): [Preserve(Conditional = true)] on the internal (NativeHandle, bool) constructors of AuthorizationEngine and SecKeychain. The test prefers [DynamicDependency] but every NativeObject subclass in the repo uses [Preserve] — SecCertificate, SecIdentity, SecKey, SecPolicy, SecTrust all have the same entry. Following established convention.
ConstructorTest exclusion (1 entry): AuthorizationCallbacks is INativeObject (not NativeObject) with a non-owning (NativeHandle) constructor. Added to the skip list alongside AudioBuffers, AURenderEventEnumerator, and other non-refcounted INativeObject types.
HandleSafety.cs exclusion (2 entries): AuthorizationCallbacks and AuthorizationRights get_Handle() marked safe (non-owning pointer wrapper and IDisposable-managed memory, respectively).
Documentation.KnownFailures (2 entries): bgen-generated Dispose(bool) overrides on SFAuthorizationView and SFChooseIdentityTableCellView that cannot have XML docs added in source.
Monotouch Tests (9 test files, 40+ tests)
All tests are macOS-only (#if MACOS):
Sample App