X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem%2FMono.AppleTls%2FCertificate.cs;h=7463ef1aa3afbb2119954b98b5716149945051a5;hb=e3685c4c9aad38851097cff877dc0fb7ed47ab10;hp=e78a85f174e3e7e94f27443a37d802b7506f2389;hpb=f704d56c378b28e252572db4730a6e13edc14aa0;p=mono.git diff --git a/mcs/class/System/Mono.AppleTls/Certificate.cs b/mcs/class/System/Mono.AppleTls/Certificate.cs index e78a85f174e..7463ef1aa3a 100644 --- a/mcs/class/System/Mono.AppleTls/Certificate.cs +++ b/mcs/class/System/Mono.AppleTls/Certificate.cs @@ -31,11 +31,12 @@ #if SECURITY_DEP && MONO_FEATURE_APPLETLS using System; +using System.Collections.Generic; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; using Mono.Net; -using ObjCRuntime; +using ObjCRuntimeInternal; namespace Mono.AppleTls { @@ -198,6 +199,8 @@ namespace Mono.AppleTls { static readonly CFString ImportExportPassphase; static readonly CFString ImportItemIdentity; + static readonly CFString ImportExportAccess; + static readonly CFString ImportExportKeychain; static SecIdentity () { @@ -208,6 +211,8 @@ namespace Mono.AppleTls { try { ImportExportPassphase = CFObject.GetStringConstant (handle, "kSecImportExportPassphrase"); ImportItemIdentity = CFObject.GetStringConstant (handle, "kSecImportItemIdentity"); + ImportExportAccess = CFObject.GetStringConstant (handle, "kSecImportExportAccess"); + ImportExportKeychain = CFObject.GetStringConstant (handle, "kSecImportExportKeychain"); } finally { CFObject.dlclose (handle); } @@ -240,16 +245,46 @@ namespace Mono.AppleTls { } } - public static SecIdentity Import (byte[] data, string password) + internal class ImportOptions + { +#if !MONOTOUCH + public SecAccess Access { + get; set; + } + public SecKeyChain KeyChain { + get; set; + } +#endif + } + + static CFDictionary CreateImportOptions (CFString password, ImportOptions options = null) + { + if (options == null) + return CFDictionary.FromObjectAndKey (password.Handle, ImportExportPassphase.Handle); + + var items = new List> (); + items.Add (new Tuple (ImportExportPassphase.Handle, password.Handle)); + +#if !MONOTOUCH + if (options.KeyChain != null) + items.Add (new Tuple (ImportExportKeychain.Handle, options.KeyChain.Handle)); + if (options.Access != null) + items.Add (new Tuple (ImportExportAccess.Handle, options.Access.Handle)); +#endif + + return CFDictionary.FromKeysAndObjects (items); + } + + public static SecIdentity Import (byte[] data, string password, ImportOptions options = null) { if (data == null) throw new ArgumentNullException ("data"); if (string.IsNullOrEmpty (password)) // SecPKCS12Import() doesn't allow empty passwords. throw new ArgumentException ("password"); using (var pwstring = CFString.Create (password)) - using (var options = CFDictionary.FromObjectAndKey (pwstring.Handle, ImportExportPassphase.Handle)) { + using (var optionDict = CreateImportOptions (pwstring, options)) { CFDictionary [] array; - SecStatusCode result = SecImportExport.ImportPkcs12 (data, options, out array); + SecStatusCode result = SecImportExport.ImportPkcs12 (data, optionDict, out array); if (result != SecStatusCode.Success) throw new InvalidOperationException (result.ToString ()); @@ -257,7 +292,7 @@ namespace Mono.AppleTls { } } - public static SecIdentity Import (X509Certificate2 certificate) + public static SecIdentity Import (X509Certificate2 certificate, ImportOptions options = null) { if (certificate == null) throw new ArgumentNullException ("certificate"); @@ -270,7 +305,7 @@ namespace Mono.AppleTls { */ var password = Guid.NewGuid ().ToString (); var pkcs12 = certificate.Export (X509ContentType.Pfx, password); - return Import (pkcs12, password); + return Import (pkcs12, password, options); } ~SecIdentity () @@ -301,6 +336,7 @@ namespace Mono.AppleTls { partial class SecKey : INativeObject, IDisposable { internal IntPtr handle; + internal IntPtr owner; public SecKey (IntPtr handle, bool owns = false) { @@ -309,6 +345,17 @@ namespace Mono.AppleTls { CFObject.CFRetain (handle); } + /* + * SecItemImport() returns a SecArrayRef. We need to free the array, not the items inside it. + * + */ + internal SecKey (IntPtr handle, IntPtr owner) + { + this.handle = handle; + this.owner = owner; + CFObject.CFRetain (owner); + } + [DllImport (AppleTlsContext.SecurityLibrary, EntryPoint="SecKeyGetTypeID")] public extern static IntPtr GetTypeID (); @@ -331,11 +378,73 @@ namespace Mono.AppleTls { protected virtual void Dispose (bool disposing) { - if (handle != IntPtr.Zero){ + if (owner != IntPtr.Zero) { + CFObject.CFRelease (owner); + owner = handle = IntPtr.Zero; + } else if (handle != IntPtr.Zero) { CFObject.CFRelease (handle); handle = IntPtr.Zero; } } } + +#if !MONOTOUCH + class SecAccess : INativeObject, IDisposable { + internal IntPtr handle; + + public SecAccess (IntPtr handle, bool owns = false) + { + this.handle = handle; + if (!owns) + CFObject.CFRetain (handle); + } + + ~SecAccess () + { + Dispose (false); + } + + public IntPtr Handle { + get { + return handle; + } + } + + [DllImport (AppleTlsContext.SecurityLibrary)] + extern static /* OSStatus */ SecStatusCode SecAccessCreate (/* CFStringRef */ IntPtr descriptor, /* CFArrayRef */ IntPtr trustedList, /* SecAccessRef _Nullable * */ out IntPtr accessRef); + + public static SecAccess Create (string descriptor) + { + var descriptorHandle = CFString.Create (descriptor); + if (descriptorHandle == null) + throw new InvalidOperationException (); + + try { + IntPtr accessRef; + var result = SecAccessCreate (descriptorHandle.Handle, IntPtr.Zero, out accessRef); + if (result != SecStatusCode.Success) + throw new InvalidOperationException (result.ToString ()); + + return new SecAccess (accessRef, true); + } finally { + descriptorHandle.Dispose (); + } + } + + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + + protected virtual void Dispose (bool disposing) + { + if (handle != IntPtr.Zero) { + CFObject.CFRelease (handle); + handle = IntPtr.Zero; + } + } + } +#endif } #endif