Imported Upstream version 5.18.0.142

Former-commit-id: 7467d4b717762eeaf652d77f1486dd11ffb1ff1f
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-10-09 08:20:59 +00:00
parent e52655b4dc
commit 0abdbe5a7d
1547 changed files with 93792 additions and 47893 deletions

View File

@@ -81,4 +81,4 @@ using System.Runtime.InteropServices;
#if XAMMAC || XAMMAC_4_5
[assembly: InternalsVisibleTo ("Xamarin.Mac, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
#endif
#endif

View File

@@ -0,0 +1,77 @@
//
// Copyright (c) 2018 Microsoft
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
namespace Internal.Cryptography
{
/// <summary>
/// Fully managed implementation of OidLookup for the commonly supported Oids.
/// </summary>
internal static partial class OidLookup
{
private static bool ShouldUseCache(OidGroup oidGroup)
{
return true;
}
private static string NativeOidToFriendlyName(string oid, OidGroup oidGroup, bool fallBackToAllGroups)
{
switch (oid) {
case "1.2.840.113549.1.7.1": return "PKCS 7 Data";
case "1.2.840.113549.1.9.3": return "Content Type";
case "1.2.840.113549.1.9.4": return "Message Digest";
case "1.2.840.113549.1.9.5": return "Signing Time";
case "1.2.840.113549.1.9.16.3.3": return "id-smime-alg-3DESwrap";
case "2.5.29.14": return "Subject Key Identifier";
case "2.5.29.15": return "Key Usage";
case "2.5.29.17": return "Subject Alternative Name";
case "2.5.29.19": return "Basic Constraints";
case "2.5.29.37": return "Extended Key Usage";
case "2.16.840.1.113730.1.1": return "Netscape Cert Type";
}
return null;
}
private static string NativeFriendlyNameToOid(string friendlyName, OidGroup oidGroup, bool fallBackToAllGroups)
{
switch (friendlyName) {
case "PKCS 7 Data": return "1.2.840.113549.1.7.1";
case "Content Type": return "1.2.840.113549.1.9.3";
case "Message Digest": return "1.2.840.113549.1.9.4";
case "Signing Time": return "1.2.840.113549.1.9.5";
case "id-smime-alg-3DESwrap": return "1.2.840.113549.1.9.16.3.3";
case "Subject Key Identifier": return "2.5.29.14";
case "Key Usage": return "2.5.29.15";
case "Subject Alternative Name": return "2.5.29.17";
case "Basic Constraints": return "2.5.29.19";
case "Extended Key Usage": return "2.5.29.37";
case "Netscape Cert Type": return "2.16.840.1.113730.1.1";
};
return null;
}
}
}

View File

@@ -29,7 +29,8 @@ RESX_RESOURCE_STRING = \
../../../external/corefx/src/System.Net.Http/src/Resources/Strings.resx \
../../../external/corefx/src/System.Text.RegularExpressions/src/Resources/Strings.resx \
../../../external/corefx/src/System.IO.FileSystem.Watcher/src/Resources/Strings.resx \
../../../external/corefx/src/System.ComponentModel.TypeConverter/src/Resources/Strings.resx
../../../external/corefx/src/System.ComponentModel.TypeConverter/src/Resources/Strings.resx \
../../../external/corefx/src/System.Security.Cryptography.Encoding/src/Resources/Strings.resx
TEST_RESOURCES = \
Test/System/test-uri-props.txt \
@@ -110,7 +111,7 @@ endif
TXT_RESOURCE_STRINGS = ../referencesource/System/System.txt
API_BIN_REFS := System.Net.Http System.Xml
API_BIN_REFS := System.Net.Http System.Xml System.Core
ifndef MOBILE_PROFILE
API_BIN_REFS += System.Configuration
@@ -118,9 +119,6 @@ LIB_MCS_FLAGS += -d:CONFIGURATION_DEP
endif
EXTRA_DISTFILES = \
common.sources \
common_networking.sources \
corefx.unix.sources \
Test/test-config-file \
Test/System.Security.Cryptography.X509Certificates/pkits/Makefile \
Test/System.Security.Cryptography.X509Certificates/pkits/README \

View File

@@ -1,5 +1,4 @@
#if SECURITY_DEP && MONO_FEATURE_APPLETLS
//
//
// AppleCertificateHelper.cs
//
// Author:
@@ -28,7 +27,7 @@ namespace Mono.AppleTls
{
static class AppleCertificateHelper
{
public static SecIdentity GetIdentity (X509Certificate certificate)
public static SafeSecIdentityHandle GetIdentity (X509Certificate certificate)
{
/*
* If we got an 'X509Certificate2', then we require it to have a private key
@@ -36,11 +35,7 @@ namespace Mono.AppleTls
*/
var certificate2 = certificate as X509Certificate2;
if (certificate2 != null)
#if MONOTOUCH
return SecIdentity.Import (certificate2);
#else
return SecImportExport.ItemImport (certificate2);
#endif
return MonoCertificatePal.ImportIdentity (certificate2);
/*
* Reading Certificates from the Mac Keychain
@@ -87,32 +82,35 @@ namespace Mono.AppleTls
*/
#if MOBILE
using (var secCert = new SecCertificate (certificate)) {
return SecKeyChain.FindIdentity (secCert, true);
}
using (var secCert = MonoCertificatePal.FromOtherCertificate (certificate))
return MonoCertificatePal.FindIdentity (secCert, true);
#else
return null;
return new SafeSecIdentityHandle ();
#endif
}
public static SecIdentity GetIdentity (X509Certificate certificate, out SecCertificate[] intermediateCerts)
public static SafeSecIdentityHandle GetIdentity (X509Certificate certificate, out SafeSecCertificateHandle[] intermediateCerts)
{
var identity = GetIdentity (certificate);
var impl2 = certificate.Impl as X509Certificate2Impl;
if (impl2 == null || impl2.IntermediateCertificates == null) {
intermediateCerts = new SecCertificate [0];
intermediateCerts = new SafeSecCertificateHandle [0];
return identity;
}
intermediateCerts = new SafeSecCertificateHandle [impl2.IntermediateCertificates.Count];
try {
intermediateCerts = new SecCertificate [impl2.IntermediateCertificates.Count];
for (int i = 0; i < intermediateCerts.Length; i++)
intermediateCerts [i] = new SecCertificate (impl2.IntermediateCertificates [i]);
intermediateCerts [i] = MonoCertificatePal.FromOtherCertificate (impl2.IntermediateCertificates[i]);
return identity;
} catch {
identity.Dispose ();
for (int i = 0; i < intermediateCerts.Length; i++) {
intermediateCerts [i]?.Dispose ();
}
identity?.Dispose ();
throw;
}
}
@@ -158,4 +156,3 @@ namespace Mono.AppleTls
}
}
}
#endif

View File

@@ -1,4 +1,3 @@
#if SECURITY_DEP && MONO_FEATURE_APPLETLS
//
// AppleTlsContext.cs
//
@@ -48,8 +47,8 @@ namespace Mono.AppleTls
SslReadFunc readFunc;
SslWriteFunc writeFunc;
SecIdentity serverIdentity;
SecIdentity clientIdentity;
SafeSecIdentityHandle serverIdentity;
SafeSecIdentityHandle clientIdentity;
X509Certificate remoteCertificate;
X509Certificate localClientCertificate;
@@ -168,9 +167,9 @@ namespace Mono.AppleTls
SetSessionOption (SslSessionOption.BreakOnServerAuth, true);
if (IsServer) {
SecCertificate[] intermediateCerts;
SafeSecCertificateHandle[] intermediateCerts;
serverIdentity = AppleCertificateHelper.GetIdentity (LocalServerCertificate, out intermediateCerts);
if (serverIdentity == null)
if (serverIdentity.IsInvalid)
throw new SSA.AuthenticationException ("Unable to get server certificate from keychain.");
SetCertificate (serverIdentity, intermediateCerts);
@@ -225,9 +224,9 @@ namespace Mono.AppleTls
if (localClientCertificate == null)
return;
clientIdentity = AppleCertificateHelper.GetIdentity (localClientCertificate);
if (clientIdentity == null)
if (clientIdentity.IsInvalid)
throw new TlsException (AlertDescription.CertificateUnknown);
SetCertificate (clientIdentity, new SecCertificate [0]);
SetCertificate (clientIdentity, new SafeSecCertificateHandle [0]);
}
void EvaluateTrust ()
@@ -662,26 +661,21 @@ namespace Mono.AppleTls
[DllImport (SecurityLibrary)]
extern unsafe static /* OSStatus */ SslStatus SSLSetCertificate (/* SSLContextRef */ IntPtr context, /* CFArrayRef */ IntPtr certRefs);
CFArray Bundle (SecIdentity identity, IEnumerable<SecCertificate> certificates)
CFArray Bundle (SafeSecIdentityHandle identity, IList<SafeSecCertificateHandle> certificates)
{
if (identity == null)
throw new ArgumentNullException ("identity");
int i = 0;
if (identity == null || identity.IsInvalid)
throw new ArgumentNullException (nameof (identity));
if (certificates == null)
throw new ArgumentNullException (nameof (certificates));
int n = 0;
if (certificates != null) {
foreach (var obj in certificates)
n++;
}
var ptrs = new IntPtr [n + 1];
ptrs [0] = identity.Handle;
foreach (var certificate in certificates)
ptrs [++i] = certificate.Handle;
var ptrs = new IntPtr [certificates.Count + 1];
ptrs [0] = identity.DangerousGetHandle ();
for (int i = 0; i < certificates.Count; i++)
ptrs [i + 1] = certificates [i].DangerousGetHandle ();
return CFArray.CreateArray (ptrs);
}
public void SetCertificate (SecIdentity identify, IEnumerable<SecCertificate> certificates)
void SetCertificate (SafeSecIdentityHandle identify, IList<SafeSecCertificateHandle> certificates)
{
using (var array = Bundle (identify, certificates)) {
var result = SSLSetCertificate (Handle, array.Handle);
@@ -1020,4 +1014,3 @@ namespace Mono.AppleTls
}
}
}
#endif

View File

@@ -1,5 +1,4 @@
#if SECURITY_DEP && MONO_FEATURE_APPLETLS
//
//
// AppleTlsProvider.cs
//
// Author:
@@ -84,4 +83,3 @@ namespace Mono.AppleTls
}
}
}
#endif

View File

@@ -1,4 +1,3 @@
#if SECURITY_DEP && MONO_FEATURE_APPLETLS
//
// AppleTlsStream.cs
//
@@ -43,4 +42,3 @@ namespace Mono.AppleTls
}
}
}
#endif

View File

@@ -1,450 +0,0 @@
//
// Certificate.cs: Implements the managed SecCertificate wrapper.
//
// Authors:
// Miguel de Icaza
// Sebastien Pouliot <sebastien@xamarin.com>
//
// Copyright 2010 Novell, Inc
// Copyright 2012-2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#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 ObjCRuntimeInternal;
namespace Mono.AppleTls {
partial class SecCertificate : INativeObject, IDisposable {
internal IntPtr handle;
internal SecCertificate (IntPtr handle, bool owns = false)
{
if (handle == IntPtr.Zero)
throw new Exception ("Invalid handle");
this.handle = handle;
if (!owns)
CFObject.CFRetain (handle);
}
[DllImport (AppleTlsContext.SecurityLibrary, EntryPoint="SecCertificateGetTypeID")]
public extern static IntPtr GetTypeID ();
[DllImport (AppleTlsContext.SecurityLibrary)]
extern static IntPtr SecCertificateCreateWithData (IntPtr allocator, IntPtr cfData);
public SecCertificate (X509Certificate certificate)
{
if (certificate == null)
throw new ArgumentNullException ("certificate");
handle = certificate.Impl.GetNativeAppleCertificate ();
if (handle != IntPtr.Zero) {
CFObject.CFRetain (handle);
return;
}
using (CFData cert = CFData.FromData (certificate.GetRawCertData ())) {
Initialize (cert);
}
}
internal SecCertificate (X509CertificateImpl impl)
{
handle = impl.GetNativeAppleCertificate ();
if (handle != IntPtr.Zero) {
CFObject.CFRetain (handle);
return;
}
using (CFData cert = CFData.FromData (impl.GetRawCertData ())) {
Initialize (cert);
}
}
void Initialize (CFData data)
{
handle = SecCertificateCreateWithData (IntPtr.Zero, data.Handle);
if (handle == IntPtr.Zero)
throw new ArgumentException ("Not a valid DER-encoded X.509 certificate");
}
[DllImport (AppleTlsContext.SecurityLibrary)]
extern static IntPtr SecCertificateCopySubjectSummary (IntPtr cert);
public string SubjectSummary {
get {
if (handle == IntPtr.Zero)
throw new ObjectDisposedException ("SecCertificate");
IntPtr subjectSummaryHandle = IntPtr.Zero;
try {
subjectSummaryHandle = SecCertificateCopySubjectSummary (handle);
CFString subjectSummary = CFString.AsString (subjectSummaryHandle);
return subjectSummary;
}
finally {
if (subjectSummaryHandle != IntPtr.Zero)
CFObject.CFRelease (subjectSummaryHandle);
}
}
}
[DllImport (AppleTlsContext.SecurityLibrary)]
extern static /* CFDataRef */ IntPtr SecCertificateCopyData (/* SecCertificateRef */ IntPtr cert);
public CFData DerData {
get {
if (handle == IntPtr.Zero)
throw new ObjectDisposedException ("SecCertificate");
IntPtr data = SecCertificateCopyData (handle);
if (data == IntPtr.Zero)
throw new ArgumentException ("Not a valid certificate");
return new CFData (data, true);
}
}
public X509Certificate ToX509Certificate ()
{
if (handle == IntPtr.Zero)
throw new ObjectDisposedException ("SecCertificate");
return new X509Certificate (handle);
}
internal static bool Equals (SecCertificate first, SecCertificate second)
{
/*
* This is a little bit expensive, but unfortunately there is no better API to compare two
* SecCertificateRef's for equality.
*/
if (first == null)
throw new ArgumentNullException ("first");
if (second == null)
throw new ArgumentNullException ("second");
if (first.Handle == second.Handle)
return true;
using (var firstData = first.DerData)
using (var secondData = second.DerData) {
if (firstData.Handle == secondData.Handle)
return true;
if (firstData.Length != secondData.Length)
return false;
IntPtr length = (IntPtr)firstData.Length;
for (long i = 0; i < (long)length; i++) {
if (firstData [i] != secondData [i])
return false;
}
return true;
}
}
~SecCertificate ()
{
Dispose (false);
}
public IntPtr Handle {
get {
return handle;
}
}
public void Dispose ()
{
Dispose (true);
GC.SuppressFinalize (this);
}
protected virtual void Dispose (bool disposing)
{
if (handle != IntPtr.Zero){
CFObject.CFRelease (handle);
handle = IntPtr.Zero;
}
}
}
partial class SecIdentity : INativeObject, IDisposable {
static readonly CFString ImportExportPassphase;
static readonly CFString ImportItemIdentity;
static readonly CFString ImportExportAccess;
static readonly CFString ImportExportKeychain;
static SecIdentity ()
{
var handle = CFObject.dlopen (AppleTlsContext.SecurityLibrary, 0);
if (handle == IntPtr.Zero)
return;
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);
}
}
internal IntPtr handle;
internal SecIdentity (IntPtr handle, bool owns = false)
{
this.handle = handle;
if (!owns)
CFObject.CFRetain (handle);
}
[DllImport (AppleTlsContext.SecurityLibrary, EntryPoint="SecIdentityGetTypeID")]
public extern static IntPtr GetTypeID ();
[DllImport (AppleTlsContext.SecurityLibrary)]
extern static /* OSStatus */ SecStatusCode SecIdentityCopyCertificate (/* SecIdentityRef */ IntPtr identityRef, /* SecCertificateRef* */ out IntPtr certificateRef);
public SecCertificate Certificate {
get {
if (handle == IntPtr.Zero)
throw new ObjectDisposedException ("SecIdentity");
IntPtr cert;
SecStatusCode result = SecIdentityCopyCertificate (handle, out cert);
if (result != SecStatusCode.Success)
throw new InvalidOperationException (result.ToString ());
return new SecCertificate (cert, true);
}
}
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<Tuple<IntPtr, IntPtr>> ();
items.Add (new Tuple<IntPtr, IntPtr> (ImportExportPassphase.Handle, password.Handle));
#if !MONOTOUCH
if (options.KeyChain != null)
items.Add (new Tuple<IntPtr, IntPtr> (ImportExportKeychain.Handle, options.KeyChain.Handle));
if (options.Access != null)
items.Add (new Tuple<IntPtr, IntPtr> (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 optionDict = CreateImportOptions (pwstring, options)) {
CFDictionary [] array;
SecStatusCode result = SecImportExport.ImportPkcs12 (data, optionDict, out array);
if (result != SecStatusCode.Success)
throw new InvalidOperationException (result.ToString ());
return new SecIdentity (array [0].GetValue (ImportItemIdentity.Handle));
}
}
public static SecIdentity Import (X509Certificate2 certificate, ImportOptions options = null)
{
if (certificate == null)
throw new ArgumentNullException ("certificate");
if (!certificate.HasPrivateKey)
throw new InvalidOperationException ("Need X509Certificate2 with a private key.");
/*
* SecPSK12Import does not allow any empty passwords, so let's generate
* a semi-random one here.
*/
var password = Guid.NewGuid ().ToString ();
var pkcs12 = certificate.Export (X509ContentType.Pfx, password);
return Import (pkcs12, password, options);
}
~SecIdentity ()
{
Dispose (false);
}
public IntPtr Handle {
get {
return handle;
}
}
public void Dispose ()
{
Dispose (true);
GC.SuppressFinalize (this);
}
protected virtual void Dispose (bool disposing)
{
if (handle != IntPtr.Zero){
CFObject.CFRelease (handle);
handle = IntPtr.Zero;
}
}
}
partial class SecKey : INativeObject, IDisposable {
internal IntPtr handle;
internal IntPtr owner;
public SecKey (IntPtr handle, bool owns = false)
{
this.handle = handle;
if (!owns)
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 ();
~SecKey ()
{
Dispose (false);
}
public IntPtr Handle {
get {
return handle;
}
}
public void Dispose ()
{
Dispose (true);
GC.SuppressFinalize (this);
}
protected virtual void Dispose (bool disposing)
{
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

View File

@@ -1,4 +1,3 @@
#if MONO_FEATURE_APPLETLS
// Copyright 2011-2015 Xamarin Inc. All rights reserved.
using ObjCRuntimeInternal;
@@ -405,4 +404,3 @@ namespace Mono.AppleTls {
ResultOtherError,
}
}
#endif

View File

@@ -1,356 +0,0 @@
#if SECURITY_DEP && MONO_FEATURE_APPLETLS
//
// Items.cs: Implements the KeyChain query access APIs
//
// We use strong types and a helper SecQuery class to simplify the
// creation of the dictionary used to query the Keychain
//
// Authors:
// Miguel de Icaza
// Sebastien Pouliot
//
// Copyright 2010 Novell, Inc
// Copyright 2011-2016 Xamarin Inc
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
using System.Runtime.InteropServices;
using ObjCRuntimeInternal;
using Mono.Net;
namespace Mono.AppleTls {
enum SecKind {
Identity,
Certificate
}
#if MONOTOUCH
static class SecKeyChain {
#else
class SecKeyChain : INativeObject, IDisposable {
#endif
internal static readonly IntPtr MatchLimitAll;
internal static readonly IntPtr MatchLimitOne;
internal static readonly IntPtr MatchLimit;
#if !MONOTOUCH
IntPtr handle;
internal SecKeyChain (IntPtr handle, bool owns = false)
{
if (handle == IntPtr.Zero)
throw new ArgumentException ("Invalid handle");
this.handle = handle;
if (!owns)
CFObject.CFRetain (handle);
}
#endif
static SecKeyChain ()
{
var handle = CFObject.dlopen (AppleTlsContext.SecurityLibrary, 0);
if (handle == IntPtr.Zero)
return;
try {
MatchLimit = CFObject.GetIntPtr (handle, "kSecMatchLimit");
MatchLimitAll = CFObject.GetIntPtr (handle, "kSecMatchLimitAll");
MatchLimitOne = CFObject.GetIntPtr (handle, "kSecMatchLimitOne");
} finally {
CFObject.dlclose (handle);
}
}
public static SecIdentity FindIdentity (SecCertificate certificate, bool throwOnError = false)
{
if (certificate == null)
throw new ArgumentNullException ("certificate");
var identity = FindIdentity (cert => SecCertificate.Equals (certificate, cert));
if (!throwOnError || identity != null)
return identity;
throw new InvalidOperationException (string.Format ("Could not find SecIdentity for certificate '{0}' in keychain.", certificate.SubjectSummary));
}
static SecIdentity FindIdentity (Predicate<SecCertificate> filter)
{
/*
* Unfortunately, SecItemCopyMatching() does not allow any search
* filters when looking up an identity.
*
* The following lookup will return all identities from the keychain -
* we then need need to find the right one.
*/
using (var record = new SecRecord (SecKind.Identity)) {
SecStatusCode status;
var result = SecKeyChain.QueryAsReference (record, -1, out status);
if (status != SecStatusCode.Success || result == null)
return null;
for (int i = 0; i < result.Length; i++) {
var identity = (SecIdentity)result [i];
if (filter (identity.Certificate))
return identity;
}
}
return null;
}
static INativeObject [] QueryAsReference (SecRecord query, int max, out SecStatusCode result)
{
if (query == null) {
result = SecStatusCode.Param;
return null;
}
using (var copy = query.QueryDict.MutableCopy ()) {
copy.SetValue (CFBoolean.True.Handle, SecItem.ReturnRef);
SetLimit (copy, max);
return QueryAsReference (copy, out result);
}
}
static INativeObject [] QueryAsReference (CFDictionary query, out SecStatusCode result)
{
if (query == null) {
result = SecStatusCode.Param;
return null;
}
IntPtr ptr;
result = SecItem.SecItemCopyMatching (query.Handle, out ptr);
if (result == SecStatusCode.Success && ptr != IntPtr.Zero) {
var array = CFArray.ArrayFromHandle<INativeObject> (ptr, p => {
IntPtr cfType = CFType.GetTypeID (p);
if (cfType == SecCertificate.GetTypeID ())
return new SecCertificate (p, true);
if (cfType == SecKey.GetTypeID ())
return new SecKey (p, true);
if (cfType == SecIdentity.GetTypeID ())
return new SecIdentity (p, true);
throw new Exception (String.Format ("Unexpected type: 0x{0:x}", cfType));
});
return array;
}
return null;
}
internal static CFNumber SetLimit (CFMutableDictionary dict, int max)
{
CFNumber n = null;
IntPtr val;
if (max == -1)
val = MatchLimitAll;
else if (max == 1)
val = MatchLimitOne;
else {
n = CFNumber.FromInt32 (max);
val = n.Handle;
}
dict.SetValue (val, SecKeyChain.MatchLimit);
return n;
}
#if !MONOTOUCH
[DllImport (AppleTlsContext.SecurityLibrary)]
extern static /* OSStatus */ SecStatusCode SecKeychainCreate (/* const char * */ IntPtr pathName, uint passwordLength, /* const void * */ IntPtr password,
bool promptUser, /* SecAccessRef */ IntPtr initialAccess,
/* SecKeychainRef _Nullable * */ out IntPtr keychain);
internal static SecKeyChain Create (string pathName, string password)
{
IntPtr handle;
var pathNamePtr = Marshal.StringToHGlobalAnsi (pathName);
var passwordPtr = Marshal.StringToHGlobalAnsi (password);
var result = SecKeychainCreate (pathNamePtr, (uint)password.Length, passwordPtr, false, IntPtr.Zero, out handle);
if (result != SecStatusCode.Success)
throw new InvalidOperationException (result.ToString ());
return new SecKeyChain (handle, true);
}
[DllImport (AppleTlsContext.SecurityLibrary)]
extern static /* OSStatus */ SecStatusCode SecKeychainOpen (/* const char * */ IntPtr pathName, /* SecKeychainRef _Nullable * */ out IntPtr keychain);
internal static SecKeyChain Open (string pathName)
{
IntPtr handle;
IntPtr pathNamePtr = IntPtr.Zero;
try {
pathNamePtr = Marshal.StringToHGlobalAnsi (pathName);
var result = SecKeychainOpen (pathNamePtr, out handle);
if (result != SecStatusCode.Success)
throw new InvalidOperationException (result.ToString ());
return new SecKeyChain (handle, true);
} finally {
if (pathNamePtr != IntPtr.Zero)
Marshal.FreeHGlobal (pathNamePtr);
}
}
internal static SecKeyChain OpenSystemRootCertificates ()
{
return Open ("/System/Library/Keychains/SystemRootCertificates.keychain");
}
~SecKeyChain ()
{
Dispose (false);
}
public IntPtr Handle {
get {
return handle;
}
}
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
}
class SecRecord : IDisposable {
internal static readonly IntPtr SecClassKey;
static SecRecord ()
{
var handle = CFObject.dlopen (AppleTlsContext.SecurityLibrary, 0);
if (handle == IntPtr.Zero)
return;
try {
SecClassKey = CFObject.GetIntPtr (handle, "kSecClass");
} finally {
CFObject.dlclose (handle);
}
}
CFMutableDictionary _queryDict;
internal CFMutableDictionary QueryDict {
get {
return _queryDict;
}
}
internal void SetValue (IntPtr key, IntPtr value)
{
_queryDict.SetValue (key, value);
}
public SecRecord (SecKind secKind)
{
var kind = SecClass.FromSecKind (secKind);
_queryDict = CFMutableDictionary.Create ();
_queryDict.SetValue (SecClassKey, kind);
}
public void Dispose ()
{
Dispose (true);
GC.SuppressFinalize (this);
}
protected virtual void Dispose (bool disposing)
{
if (_queryDict != null){
if (disposing){
_queryDict.Dispose ();
_queryDict = null;
}
}
}
~SecRecord ()
{
Dispose (false);
}
}
partial class SecItem {
public static readonly IntPtr ReturnRef;
public static readonly IntPtr MatchSearchList;
static SecItem ()
{
var handle = CFObject.dlopen (AppleTlsContext.SecurityLibrary, 0);
if (handle == IntPtr.Zero)
return;
try {
ReturnRef = CFObject.GetIntPtr (handle, "kSecReturnRef");
MatchSearchList = CFObject.GetIntPtr (handle, "kSecMatchSearchList");
} finally {
CFObject.dlclose (handle);
}
}
[DllImport (AppleTlsContext.SecurityLibrary)]
internal extern static SecStatusCode SecItemCopyMatching (/* CFDictionaryRef */ IntPtr query, /* CFTypeRef* */ out IntPtr result);
}
static partial class SecClass {
public static readonly IntPtr Identity;
public static readonly IntPtr Certificate;
static SecClass ()
{
var handle = CFObject.dlopen (AppleTlsContext.SecurityLibrary, 0);
if (handle == IntPtr.Zero)
return;
try {
Identity = CFObject.GetIntPtr (handle, "kSecClassIdentity");
Certificate = CFObject.GetIntPtr (handle, "kSecClassCertificate");
} finally {
CFObject.dlclose (handle);
}
}
public static IntPtr FromSecKind (SecKind secKind)
{
switch (secKind){
case SecKind.Identity:
return Identity;
case SecKind.Certificate:
return Certificate;
default:
throw new ArgumentException ("secKind");
}
}
}
}
#endif

View File

@@ -0,0 +1,189 @@
//
// MonoCertificatePal.Mobile.cs
//
// Authors:
// Miguel de Icaza
// Sebastien Pouliot <sebastien@xamarin.com>
// Martin Baulig <mabaul@microsoft.com>
//
// Copyright 2010 Novell, Inc
// Copyright 2011-2014 Xamarin Inc.
// Copyright (c) 2018 Xamarin Inc. (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Threading;
using System.Runtime.InteropServices;
using System.Security.Cryptography.Apple;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Win32.SafeHandles;
using Mono.Net;
namespace Mono.AppleTls
{
static partial class MonoCertificatePal
{
static int initialized;
static CFString ImportExportPassphase;
static CFString ImportItemIdentity;
static IntPtr MatchLimitAll;
static IntPtr MatchLimitOne;
static IntPtr MatchLimit;
static IntPtr SecClassKey;
static IntPtr SecClassIdentity;
static IntPtr SecClassCertificate;
static IntPtr ReturnRef;
static IntPtr MatchSearchList;
static void Initialize ()
{
if (Interlocked.CompareExchange (ref initialized, 1, 0) != 0)
return;
var handle = CFObject.dlopen (AppleTlsContext.SecurityLibrary, 0);
if (handle == IntPtr.Zero)
return;
try {
ImportExportPassphase = CFObject.GetStringConstant (handle, "kSecImportExportPassphrase");
ImportItemIdentity = CFObject.GetStringConstant (handle, "kSecImportItemIdentity");
MatchLimit = CFObject.GetIntPtr (handle, "kSecMatchLimit");
MatchLimitAll = CFObject.GetIntPtr (handle, "kSecMatchLimitAll");
MatchLimitOne = CFObject.GetIntPtr (handle, "kSecMatchLimitOne");
SecClassKey = CFObject.GetIntPtr (handle, "kSecClass");
SecClassIdentity = CFObject.GetIntPtr (handle, "kSecClassIdentity");
SecClassCertificate = CFObject.GetIntPtr (handle, "kSecClassCertificate");
ReturnRef = CFObject.GetIntPtr (handle, "kSecReturnRef");
MatchSearchList = CFObject.GetIntPtr (handle, "kSecMatchSearchList");
} finally {
CFObject.dlclose (handle);
}
}
static SafeSecIdentityHandle ImportIdentity (byte[] data, string password)
{
if (data == null)
throw new ArgumentNullException (nameof (data));
if (string.IsNullOrEmpty (password)) // SecPKCS12Import() doesn't allow empty passwords.
throw new ArgumentException (nameof (password));
Initialize ();
using (var pwstring = CFString.Create (password))
using (var optionDict = CFDictionary.FromObjectAndKey (pwstring.Handle, ImportExportPassphase.Handle)) {
var result = ImportPkcs12 (data, optionDict, out var array);
if (result != SecStatusCode.Success)
throw new InvalidOperationException (result.ToString ());
return new SafeSecIdentityHandle (array [0].GetValue (ImportItemIdentity.Handle));
}
}
[DllImport (AppleTlsContext.SecurityLibrary)]
extern static SecStatusCode SecPKCS12Import (IntPtr pkcs12_data, IntPtr options, out IntPtr items);
static SecStatusCode ImportPkcs12 (byte[] buffer, CFDictionary options, out CFDictionary[] array)
{
using (CFData data = CFData.FromData (buffer)) {
return ImportPkcs12 (data, options, out array);
}
}
static SecStatusCode ImportPkcs12 (CFData data, CFDictionary options, out CFDictionary[] array)
{
if (options == null)
throw new ArgumentNullException (nameof (options));
var code = SecPKCS12Import (data.Handle, options.Handle, out var handle);
array = CFArray.ArrayFromHandle<CFDictionary> (handle, h => new CFDictionary (h, false));
if (handle != IntPtr.Zero)
CFObject.CFRelease (handle);
return code;
}
public static SafeSecIdentityHandle ImportIdentity (X509Certificate2 certificate)
{
if (certificate == null)
throw new ArgumentNullException (nameof (certificate));
if (!certificate.HasPrivateKey)
throw new InvalidOperationException ("Need X509Certificate2 with a private key.");
SafeSecIdentityHandle identity;
/*
* SecPSK12Import does not allow any empty passwords, so let's generate
* a semi-random one here.
*/
Initialize ();
var password = Guid.NewGuid ().ToString ();
var pkcs12 = certificate.Export (X509ContentType.Pfx, password);
identity = ImportIdentity (pkcs12, password);
return identity ?? new SafeSecIdentityHandle ();
}
[DllImport (AppleTlsContext.SecurityLibrary)]
extern static SecStatusCode SecItemCopyMatching (/* CFDictionaryRef */ IntPtr query, /* CFTypeRef* */ out IntPtr result);
public static SafeSecIdentityHandle FindIdentity (SafeSecCertificateHandle certificate, bool throwOnError = false)
{
if (certificate == null || certificate.IsInvalid)
throw new ObjectDisposedException (nameof (certificate));
var identity = FindIdentity (cert => MonoCertificatePal.Equals (certificate, cert)) ?? new SafeSecIdentityHandle ();
if (!throwOnError || identity.IsInvalid)
return identity;
var subject = MonoCertificatePal.GetSubjectSummary (certificate);
throw new InvalidOperationException ($"Could not find SecIdentity for certificate '{subject}' in keychain.");
}
static SafeSecIdentityHandle FindIdentity (Predicate<SafeSecCertificateHandle> filter)
{
Initialize ();
/*
* Unfortunately, SecItemCopyMatching() does not allow any search
* filters when looking up an identity.
*
* The following lookup will return all identities from the keychain -
* we then need need to find the right one.
*/
using (var query = CFMutableDictionary.Create ()) {
query.SetValue (SecClassKey, SecClassIdentity);
query.SetValue (CFBoolean.True.Handle, ReturnRef);
query.SetValue (MatchLimitAll, MatchLimit);
var status = SecItemCopyMatching (query.Handle, out var ptr);
if (status != SecStatusCode.Success || ptr == IntPtr.Zero)
return null;
using (var array = new CFArray (ptr, false)) {
for (int i = 0; i < array.Count; i++) {
var item = array[i];
if (!MonoCertificatePal.IsSecIdentity (item))
throw new InvalidOperationException ();
using (var identity = new SafeSecIdentityHandle (item))
using (var certificate = MonoCertificatePal.GetCertificate (identity)) {
if (filter (certificate))
return new SafeSecIdentityHandle (item);
}
}
}
}
return null;
}
}
}

View File

@@ -1,37 +1,39 @@
#if SECURITY_DEP && MONO_FEATURE_APPLETLS
//
// ImportExport.cs
//
// MonoCertificatePal.OSX.cs
//
// Authors:
// Sebastien Pouliot <sebastien@xamarin.com>
//
// Miguel de Icaza
// Sebastien Pouliot <sebastien@xamarin.com>
// Martin Baulig <mabaul@microsoft.com>
//
// Copyright 2010 Novell, Inc
// Copyright 2011-2014 Xamarin Inc.
// Copyright (c) 2018 Xamarin Inc. (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Threading;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.Apple;
using System.Security.Cryptography.X509Certificates;
using ObjCRuntimeInternal;
using Microsoft.Win32.SafeHandles;
using Mono.Net;
#if MONO_FEATURE_BTLS
@@ -40,34 +42,20 @@ using Mono.Btls;
using Mono.Security.Cryptography;
#endif
namespace Mono.AppleTls {
internal partial class SecImportExport {
[DllImport (AppleTlsContext.SecurityLibrary)]
extern static SecStatusCode SecPKCS12Import (IntPtr pkcs12_data, IntPtr options, out IntPtr items);
static public SecStatusCode ImportPkcs12 (byte[] buffer, CFDictionary options, out CFDictionary[] array)
namespace Mono.AppleTls
{
static partial class MonoCertificatePal
{
public static SafeSecIdentityHandle ImportIdentity (X509Certificate2 certificate)
{
using (CFData data = CFData.FromData (buffer)) {
return ImportPkcs12 (data, options, out array);
}
if (certificate == null)
throw new ArgumentNullException (nameof (certificate));
if (!certificate.HasPrivateKey)
throw new InvalidOperationException ("Need X509Certificate2 with a private key.");
return ItemImport (certificate) ?? new SafeSecIdentityHandle ();
}
static public SecStatusCode ImportPkcs12 (CFData data, CFDictionary options, out CFDictionary [] array)
{
if (options == null)
throw new ArgumentNullException ("options");
IntPtr handle;
SecStatusCode code = SecPKCS12Import (data.Handle, options.Handle, out handle);
array = CFArray.ArrayFromHandle <CFDictionary> (handle, h => new CFDictionary (h, false));
if (handle != IntPtr.Zero)
CFObject.CFRelease (handle);
return code;
}
#if !MONOTOUCH
[DllImport (AppleTlsContext.SecurityLibrary)]
extern static SecStatusCode SecItemImport (
/* CFDataRef */ IntPtr importedData,
@@ -91,15 +79,15 @@ namespace Mono.AppleTls {
}
static CFArray ItemImport (CFData data, SecExternalFormat format, SecExternalItemType itemType,
SecItemImportExportFlags flags = SecItemImportExportFlags.None,
SecItemImportExportKeyParameters? keyParams = null)
SecItemImportExportFlags flags = SecItemImportExportFlags.None,
SecItemImportExportKeyParameters? keyParams = null)
{
return ItemImport (data, ref format, ref itemType, flags, keyParams);
}
static CFArray ItemImport (CFData data, ref SecExternalFormat format, ref SecExternalItemType itemType,
SecItemImportExportFlags flags = SecItemImportExportFlags.None,
SecItemImportExportKeyParameters? keyParams = null)
SecItemImportExportFlags flags = SecItemImportExportFlags.None,
SecItemImportExportKeyParameters? keyParams = null)
{
IntPtr keyParamsPtr = IntPtr.Zero;
if (keyParams != null) {
@@ -127,18 +115,18 @@ namespace Mono.AppleTls {
/* SecCertificateRef */ IntPtr certificate,
/* SecKeyRef */ IntPtr privateKey);
static public SecIdentity ItemImport (X509Certificate2 certificate)
static public SafeSecIdentityHandle ItemImport (X509Certificate2 certificate)
{
if (!certificate.HasPrivateKey)
throw new NotSupportedException ();
using (var key = ImportPrivateKey (certificate))
using (var cert = new SecCertificate (certificate)) {
var identity = SecIdentityCreate (IntPtr.Zero, cert.Handle, key.Handle);
if (CFType.GetTypeID (identity) != SecIdentity.GetTypeID ())
using (var cert = MonoCertificatePal.FromOtherCertificate (certificate)) {
var identity = SecIdentityCreate (IntPtr.Zero, cert.DangerousGetHandle (), key.DangerousGetHandle ());
if (!MonoCertificatePal.IsSecIdentity (identity))
throw new InvalidOperationException ();
return new SecIdentity (identity, true);
return new SafeSecIdentityHandle (identity, true);
}
}
@@ -152,7 +140,7 @@ namespace Mono.AppleTls {
#endif
}
static SecKey ImportPrivateKey (X509Certificate2 certificate)
static SafeSecKeyRefHandle ImportPrivateKey (X509Certificate2 certificate)
{
if (!certificate.HasPrivateKey)
throw new NotSupportedException ();
@@ -166,10 +154,10 @@ namespace Mono.AppleTls {
throw new InvalidOperationException ("Private key import failed.");
var imported = items[0];
if (CFType.GetTypeID (imported) != SecKey.GetTypeID ())
if (!MonoCertificatePal.IsSecKey (imported))
throw new InvalidOperationException ("Private key import doesn't return SecKey.");
return new SecKey (imported, items.Handle);
return new SafeSecKeyRefHandle (imported, items.Handle);
} finally {
items.Dispose ();
}
@@ -178,7 +166,8 @@ namespace Mono.AppleTls {
const int SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION = 0;
// Native enum; don't change.
enum SecExternalFormat : int {
enum SecExternalFormat : int
{
Unknown = 0,
OpenSSL = 1,
X509Cert = 9,
@@ -188,7 +177,8 @@ namespace Mono.AppleTls {
}
// Native enum; don't change.
enum SecExternalItemType : int {
enum SecExternalItemType : int
{
Unknown = 0,
PrivateKey = 1,
PublicKey = 2,
@@ -198,14 +188,16 @@ namespace Mono.AppleTls {
}
// Native enum; don't change
enum SecItemImportExportFlags : int {
enum SecItemImportExportFlags : int
{
None,
PemArmour = 0x00000001, /* exported blob is PEM formatted */
}
// Native struct; don't change
[StructLayout (LayoutKind.Sequential)]
struct SecItemImportExportKeyParameters {
struct SecItemImportExportKeyParameters
{
public int version; /* SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION */
public int flags; /* SecKeyImportExportFlags bits */
public IntPtr passphrase; /* SecExternalFormat.PKCS12 only. Legal types are CFStringRef and CFDataRef. */
@@ -218,7 +210,5 @@ namespace Mono.AppleTls {
IntPtr keyUsage;
IntPtr keyAttributes;
}
#endif
}
}
#endif

View File

@@ -0,0 +1,190 @@
//
// MonoCertificatePal.cs
//
// Authors:
// Miguel de Icaza
// Sebastien Pouliot <sebastien@xamarin.com>
// Martin Baulig <mabaul@microsoft.com>
//
// Copyright 2010 Novell, Inc
// Copyright 2011-2014 Xamarin Inc.
// Copyright (c) 2018 Xamarin Inc. (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Threading;
using System.Runtime.InteropServices;
using System.Security.Cryptography.Apple;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Win32.SafeHandles;
using Mono.Net;
namespace Mono.AppleTls
{
static partial class MonoCertificatePal
{
[DllImport (AppleTlsContext.SecurityLibrary)]
extern static IntPtr SecCertificateCreateWithData (IntPtr allocator, IntPtr cfData);
public static SafeSecCertificateHandle FromOtherCertificate (X509Certificate certificate)
{
if (certificate == null)
throw new ArgumentNullException (nameof (certificate));
return FromOtherCertificate (certificate.Impl);
}
public static SafeSecCertificateHandle FromOtherCertificate (X509CertificateImpl impl)
{
X509Helper.ThrowIfContextInvalid (impl);
var handle = impl.GetNativeAppleCertificate ();
if (handle != IntPtr.Zero)
return new SafeSecCertificateHandle (handle, false);
using (var data = CFData.FromData (impl.RawData)) {
handle = SecCertificateCreateWithData (IntPtr.Zero, data.Handle);
if (handle == IntPtr.Zero)
throw new ArgumentException ("Not a valid DER-encoded X.509 certificate");
return new SafeSecCertificateHandle (handle, true);
}
}
[DllImport (AppleTlsContext.SecurityLibrary)]
extern static IntPtr SecIdentityGetTypeID ();
public static bool IsSecIdentity (IntPtr ptr)
{
if (ptr == IntPtr.Zero)
return false;
return CFType.GetTypeID (ptr) == SecIdentityGetTypeID ();
}
[DllImport (AppleTlsContext.SecurityLibrary)]
public extern static IntPtr SecKeyGetTypeID ();
public static bool IsSecKey (IntPtr ptr)
{
if (ptr == IntPtr.Zero)
return false;
return CFType.GetTypeID (ptr) == SecKeyGetTypeID ();
}
[DllImport (AppleTlsContext.SecurityLibrary)]
extern static /* OSStatus */ SecStatusCode SecIdentityCopyCertificate (/* SecIdentityRef */ IntPtr identityRef, /* SecCertificateRef* */ out IntPtr certificateRef);
public static SafeSecCertificateHandle GetCertificate (SafeSecIdentityHandle identity)
{
if (identity == null || identity.IsInvalid)
throw new ArgumentNullException (nameof (identity));
var result = SecIdentityCopyCertificate (identity.DangerousGetHandle (), out var cert);
if (result != SecStatusCode.Success)
throw new InvalidOperationException (result.ToString ());
return new SafeSecCertificateHandle (cert, true);
}
[DllImport (AppleTlsContext.SecurityLibrary)]
extern static IntPtr SecCertificateCopySubjectSummary (IntPtr cert);
public static string GetSubjectSummary (SafeSecCertificateHandle certificate)
{
if (certificate == null || certificate.IsInvalid)
throw new ArgumentNullException (nameof (certificate));
var subjectSummaryHandle = IntPtr.Zero;
try {
subjectSummaryHandle = SecCertificateCopySubjectSummary (certificate.DangerousGetHandle ());
return CFString.AsString (subjectSummaryHandle);
} finally {
if (subjectSummaryHandle != IntPtr.Zero)
CFObject.CFRelease (subjectSummaryHandle);
}
}
[DllImport (AppleTlsContext.SecurityLibrary)]
extern static /* CFDataRef */ IntPtr SecCertificateCopyData (/* SecCertificateRef */ IntPtr cert);
public static byte[] GetRawData (SafeSecCertificateHandle certificate)
{
if (certificate == null || certificate.IsInvalid)
throw new ArgumentNullException (nameof (certificate));
var dataPtr = SecCertificateCopyData (certificate.DangerousGetHandle ());
if (dataPtr == IntPtr.Zero)
throw new ArgumentException ("Not a valid certificate");
using (var data = new CFData (dataPtr, true)) {
var buffer = new byte[(int)data.Length];
Marshal.Copy (data.Bytes, buffer, 0, buffer.Length);
return buffer;
}
}
public static bool Equals (SafeSecCertificateHandle first, SafeSecCertificateHandle second)
{
/*
* This is a little bit expensive, but unfortunately there is no better API to compare two
* SecCertificateRef's for equality.
*/
if (first == null || first.IsInvalid)
throw new ArgumentNullException (nameof (first));
if (second == null || second.IsInvalid)
throw new ArgumentNullException (nameof (second));
if (first.DangerousGetHandle () == second.DangerousGetHandle ())
return true;
var firstDataPtr = SecCertificateCopyData (first.DangerousGetHandle ());
var secondDataPtr = SecCertificateCopyData (first.DangerousGetHandle ());
try {
if (firstDataPtr == IntPtr.Zero || secondDataPtr == IntPtr.Zero)
throw new ArgumentException ("Not a valid certificate.");
if (firstDataPtr == secondDataPtr)
return true;
var firstLength = (int)CFData.CFDataGetLength (firstDataPtr);
var secondLength = (int)CFData.CFDataGetLength (secondDataPtr);
if (firstLength != secondLength)
return false;
var firstBytePtr = CFData.CFDataGetBytePtr (firstDataPtr);
var secondBytePtr = CFData.CFDataGetBytePtr (secondDataPtr);
if (firstBytePtr == secondBytePtr)
return true;
var firstBuffer = new byte[firstLength];
var secondBuffer = new byte[secondLength];
Marshal.Copy (firstBytePtr, firstBuffer, 0, firstBuffer.Length);
Marshal.Copy (secondBytePtr, secondBuffer, 0, secondBuffer.Length);
for (int i = 0; i < firstBuffer.Length; i++)
if (firstBuffer[i] != secondBuffer[i])
return false;
return true;
} finally {
if (firstDataPtr != IntPtr.Zero)
CFObject.CFRelease (firstDataPtr);
if (secondDataPtr != IntPtr.Zero)
CFObject.CFRelease (secondDataPtr);
}
}
}
}

View File

@@ -1,4 +1,3 @@
#if SECURITY_DEP && MONO_FEATURE_APPLETLS
//
// Policy.cs: Implements the managed SecPolicy wrapper.
//
@@ -84,4 +83,3 @@ namespace Mono.AppleTls {
}
}
}
#endif

View File

@@ -0,0 +1,94 @@
//
// SafeHandles.cs
//
// Author:
// Martin Baulig <mabaul@microsoft.com>
//
// Copyright (c) 2018 Xamarin Inc. (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Runtime.InteropServices;
using System.Security.Cryptography.Apple;
using Microsoft.Win32.SafeHandles;
using Mono.Net;
namespace System.Security.Cryptography.X509Certificates
{
partial class SafeSecIdentityHandle
{
public SafeSecIdentityHandle (IntPtr handle, bool ownsHandle = false)
: base (handle, ownsHandle)
{
}
}
partial class SafeSecCertificateHandle
{
public SafeSecCertificateHandle (IntPtr handle, bool ownsHandle = false)
: base (handle, ownsHandle)
{
}
}
}
namespace System.Security.Cryptography.Apple
{
partial class SafeKeychainItemHandle
{
public SafeKeychainItemHandle (IntPtr handle, bool ownsHandle)
: base (handle, ownsHandle)
{
if (!ownsHandle)
CFObject.CFRetain (handle);
}
}
partial class SafeSecKeyRefHandle
{
public SafeSecKeyRefHandle (IntPtr handle, bool ownsHandle = false)
: base (handle, ownsHandle)
{
}
IntPtr owner;
/*
* SecItemImport() returns a SecArrayRef. We need to free the array, not the items inside it.
*
*/
public SafeSecKeyRefHandle (IntPtr handle, IntPtr owner)
: base (handle, false)
{
this.owner = owner;
CFObject.CFRetain (owner);
}
protected override bool ReleaseHandle ()
{
if (owner != IntPtr.Zero) {
CFObject.CFRelease (owner);
owner = IntPtr.Zero;
SetHandle (IntPtr.Zero);
return true;
}
return base.ReleaseHandle ();
}
}
}

View File

@@ -0,0 +1,71 @@
//
// SafeHandles.Mono.cs
//
// Author:
// Martin Baulig <mabaul@microsoft.com>
//
// Copyright (c) 2018 Xamarin Inc. (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Runtime.InteropServices;
using System.Security.Cryptography.Apple;
using Microsoft.Win32.SafeHandles;
using Mono.Net;
namespace System.Security.Cryptography.X509Certificates
{
sealed partial class SafeSecIdentityHandle : SafeKeychainItemHandle
{
public SafeSecIdentityHandle ()
{
}
}
sealed partial class SafeSecCertificateHandle : SafeKeychainItemHandle
{
public SafeSecCertificateHandle ()
{
}
}
}
namespace System.Security.Cryptography.Apple
{
partial class SafeKeychainItemHandle : SafeHandle
{
internal SafeKeychainItemHandle ()
: base (IntPtr.Zero, ownsHandle: true)
{
}
protected override bool ReleaseHandle ()
{
if (handle != IntPtr.Zero)
CFObject.CFRelease (handle);
SetHandle (IntPtr.Zero);
return true;
}
public override bool IsInvalid => handle == IntPtr.Zero;
}
partial class SafeSecKeyRefHandle : SafeKeychainItemHandle
{
}
}

View File

@@ -1,4 +1,3 @@
#if MONO_FEATURE_APPLETLS
// Copyright 2014 Xamarin Inc. All rights reserved.
namespace Mono.AppleTls {
@@ -248,4 +247,3 @@ namespace Mono.AppleTls {
TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0xC032, // iOS 9+
}
}
#endif

View File

@@ -1,4 +1,3 @@
#if MONO_FEATURE_APPLETLS
//
// SslConnection
//
@@ -15,4 +14,3 @@ namespace Mono.AppleTls
delegate SslStatus SslReadFunc (IntPtr connection, IntPtr data, /* size_t* */ ref IntPtr dataLength);
delegate SslStatus SslWriteFunc (IntPtr connection, IntPtr data, /* size_t* */ ref IntPtr dataLength);
}
#endif

View File

@@ -1,4 +1,3 @@
#if SECURITY_DEP && MONO_FEATURE_APPLETLS
//
// Trust.cs: Implements the managed SecTrust wrapper.
//
@@ -61,18 +60,21 @@ namespace Mono.AppleTls {
if (certificates == null)
throw new ArgumentNullException ("certificates");
SecCertificate[] array = new SecCertificate [certificates.Count];
var array = new SafeSecCertificateHandle [certificates.Count];
int i = 0;
foreach (var certificate in certificates)
array [i++] = new SecCertificate (certificate);
array [i++] = MonoCertificatePal.FromOtherCertificate (certificate);
Initialize (array, policy);
for (i = 0; i < array.Length; i++)
array [i].Dispose ();
}
void Initialize (SecCertificate[] array, SecPolicy policy)
void Initialize (SafeSecCertificateHandle[] array, SecPolicy policy)
{
using (var certs = CFArray.CreateArray (array)) {
var handles = new IntPtr [array.Length];
for (int i = 0; i < array.Length; i++)
handles [i] = array [i].DangerousGetHandle ();
using (var certs = CFArray.CreateArray (handles)) {
Initialize (certs.Handle, policy);
}
}
@@ -113,17 +115,6 @@ namespace Mono.AppleTls {
[DllImport (AppleTlsContext.SecurityLibrary)]
extern static IntPtr /* SecCertificateRef */ SecTrustGetCertificateAtIndex (IntPtr /* SecTrustRef */ trust, IntPtr /* CFIndex */ ix);
public SecCertificate this [IntPtr index] {
get {
if (handle == IntPtr.Zero)
throw new ObjectDisposedException ("SecTrust");
if (((long)index < 0) || ((long)index >= Count))
throw new ArgumentOutOfRangeException ("index");
return new SecCertificate (SecTrustGetCertificateAtIndex (handle, index));
}
}
internal X509Certificate GetCertificate (int index)
{
if (handle == IntPtr.Zero)
@@ -132,7 +123,8 @@ namespace Mono.AppleTls {
throw new ArgumentOutOfRangeException ("index");
var ptr = SecTrustGetCertificateAtIndex (handle, (IntPtr)index);
return new X509Certificate (ptr);
var impl = new X509CertificateImplApple (ptr, false);
return new X509Certificate (impl);
}
[DllImport (AppleTlsContext.SecurityLibrary)]
@@ -145,18 +137,21 @@ namespace Mono.AppleTls {
if (certificates == null)
return SecTrustSetAnchorCertificates (handle, IntPtr.Zero);
SecCertificate[] array = new SecCertificate [certificates.Count];
var array = new SafeSecCertificateHandle [certificates.Count];
int i = 0;
foreach (var certificate in certificates)
array [i++] = new SecCertificate (certificate);
array [i++] = MonoCertificatePal.FromOtherCertificate (certificate);
return SetAnchorCertificates (array);
}
public SecStatusCode SetAnchorCertificates (SecCertificate[] array)
public SecStatusCode SetAnchorCertificates (SafeSecCertificateHandle[] array)
{
if (array == null)
return SecTrustSetAnchorCertificates (handle, IntPtr.Zero);
using (var certs = CFArray.FromNativeObjects (array)) {
var handles = new IntPtr [array.Length];
for (int i = 0; i < array.Length; i++)
handles [i] = array [i].DangerousGetHandle ();
using (var certs = CFArray.CreateArray (handles)) {
return SecTrustSetAnchorCertificates (handle, certs.Handle);
}
}
@@ -205,4 +200,3 @@ namespace Mono.AppleTls {
}
}
}
#endif

View File

@@ -0,0 +1,173 @@
#if MONO_FEATURE_APPLETLS || MONO_FEATURE_APPLE_X509
#if MONO_SECURITY_ALIAS
extern alias MonoSecurity;
#endif
#if MONO_SECURITY_ALIAS
using MX = MonoSecurity::Mono.Security.X509;
#else
using MX = Mono.Security.X509;
#endif
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Win32.SafeHandles;
using XamMac.CoreFoundation;
namespace Mono.AppleTls
{
class X509CertificateImplApple : X509CertificateImpl
{
IntPtr handle;
X509CertificateImpl fallback;
public X509CertificateImplApple (IntPtr handle, bool owns)
{
this.handle = handle;
if (!owns)
CFHelpers.CFRetain (handle);
}
public override bool IsValid {
get { return handle != IntPtr.Zero; }
}
public override IntPtr Handle {
get { return handle; }
}
public override IntPtr GetNativeAppleCertificate ()
{
ThrowIfContextInvalid ();
return handle;
}
public override X509CertificateImpl Clone ()
{
ThrowIfContextInvalid ();
return new X509CertificateImplApple (handle, false);
}
[DllImport (CFHelpers.SecurityLibrary)]
extern static IntPtr SecCertificateCopySubjectSummary (IntPtr cert);
[DllImport (CFHelpers.SecurityLibrary)]
extern static IntPtr SecCertificateCopyData (IntPtr cert);
public override byte[] RawData {
get {
ThrowIfContextInvalid ();
var data = SecCertificateCopyData (handle);
if (data == IntPtr.Zero)
throw new ArgumentException ("Not a valid certificate");
try {
return CFHelpers.FetchDataBuffer (data);
} finally {
CFHelpers.CFRelease (data);
}
}
}
public string GetSubjectSummary ()
{
ThrowIfContextInvalid ();
IntPtr cfstr = SecCertificateCopySubjectSummary (handle);
string ret = CFHelpers.FetchString (cfstr);
CFHelpers.CFRelease (cfstr);
return ret;
}
public override byte[] Thumbprint {
get {
// FIXME: might just return 'null' when 'lazy' is true.
ThrowIfContextInvalid ();
SHA1 sha = SHA1.Create ();
return sha.ComputeHash (RawData);
}
}
public override bool Equals (X509CertificateImpl other, out bool result)
{
var otherAppleImpl = other as X509CertificateImplApple;
if (otherAppleImpl != null && otherAppleImpl.handle == handle) {
result = true;
return true;
}
result = false;
return false;
}
void MustFallback ()
{
ThrowIfContextInvalid ();
if (fallback != null)
return;
var mxCert = new MX.X509Certificate (RawData);
fallback = new X509Certificate2ImplMono (mxCert);
}
public X509CertificateImpl FallbackImpl {
get {
MustFallback ();
return fallback;
}
}
public override string Subject => FallbackImpl.Subject;
public override string Issuer => FallbackImpl.Issuer;
public override string LegacySubject => FallbackImpl.LegacySubject;
public override string LegacyIssuer => FallbackImpl.LegacyIssuer;
public override DateTime NotAfter => FallbackImpl.NotAfter;
public override DateTime NotBefore => FallbackImpl.NotBefore;
public override string KeyAlgorithm => FallbackImpl.KeyAlgorithm;
public override byte[] KeyAlgorithmParameters => FallbackImpl.KeyAlgorithmParameters;
public override byte[] PublicKeyValue => FallbackImpl.PublicKeyValue;
public override byte[] SerialNumber => FallbackImpl.SerialNumber;
public override byte[] Export (X509ContentType contentType, SafePasswordHandle password)
{
ThrowIfContextInvalid ();
switch (contentType) {
case X509ContentType.Cert:
return RawData;
case X509ContentType.Pfx: // this includes Pkcs12
// TODO
throw new NotSupportedException ();
case X509ContentType.SerializedCert:
// TODO
throw new NotSupportedException ();
default:
string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType);
throw new CryptographicException (msg);
}
}
protected override void Dispose (bool disposing)
{
if (handle != IntPtr.Zero){
CFHelpers.CFRelease (handle);
handle = IntPtr.Zero;
}
if (fallback != null) {
fallback.Dispose ();
fallback = null;
}
}
}
}
#endif

Some files were not shown because too many files have changed in this diff Show More