to better support the 2.0 validation callback.
svn path=/trunk/mcs/; revision=153443
++2010-03-11 Gonzalo Paniagua Javier <gonzalo@novell.com>
++
++ * TlsServerCertificate.cs: chain is built and validated in
++ System.dll now.
++
2010-03-01 Gonzalo Paniagua Javier <gonzalo@novell.com>
* TlsServerCertificate.cs:
#if NET_2_0
if (context.SslStream.HaveRemoteValidation2Callback) {
-- if (context.SslStream.RaiseServerCertificateValidation2 (certificates))
++ ValidationResult res = context.SslStream.RaiseServerCertificateValidation2 (certificates);
++ if (res.Trusted)
return;
-- // Give a chance to the 1.x ICertificatePolicy callback
++
++ long error = res.ErrorCode;
++ switch (error) {
++ case 0x800B0101:
++ description = AlertDescription.CertificateExpired;
++ break;
++ case 0x800B010A:
++ description = AlertDescription.UnknownCA;
++ break;
++ case 0x800B0109:
++ description = AlertDescription.UnknownCA;
++ break;
++ default:
++ description = AlertDescription.CertificateUnknown;
++ break;
++ }
++ throw new TlsException (description, "Invalid certificate received from server.");
}
#endif
// the leaf is the web server certificate
result = false;
}
-- // Attempt to use OSX certificates
-- //
-- // Ideally we should return the SecTrustResult
--#if !MONOTOUCH
-- if (System.IO.File.Exists (OSX509Certificates.SecurityLibrary)){
--#endif
-- OSX509Certificates.SecTrustResult trustResult = OSX509Certificates.TrustEvaluateSsl (certificates);
--
-- // We could use the other values of trustResult to pass this extra information to the .NET 2 callback
-- // for values like SecTrustResult.Confirm
-- result = (trustResult == OSX509Certificates.SecTrustResult.Proceed ||
-- trustResult == OSX509Certificates.SecTrustResult.Unspecified);
--#if !MONOTOUCH
-- }
--#endif
--
if (!result)
{
switch (verify.Status)
++2010-03-11 Gonzalo Paniagua Javier <gonzalo@novell.com>
++
++ * SslStreamBase.cs:
++ * SslClientStream.cs:
++ * SslServerStream.cs: modify the 2.0 callback to return more info.
++
2010-03-01 Gonzalo Paniagua Javier <gonzalo@novell.com>
* HttpsClientStream.cs: use Address instead
public delegate bool CertificateValidationCallback(
X509Certificate certificate,
int[] certificateErrors);
-- public delegate bool CertificateValidationCallback2 (Mono.Security.X509.X509CertificateCollection collection);
++
++ public class ValidationResult {
++ bool trusted;
++ bool user_denied;
++ int error_code;
++
++ public ValidationResult (bool trusted, bool user_denied, int error_code)
++ {
++ this.trusted = trusted;
++ this.user_denied = user_denied;
++ this.error_code = error_code;
++ }
++
++ public bool Trusted {
++ get { return trusted; }
++ }
++
++ public bool UserDenied {
++ get { return user_denied; }
++ }
++
++ public int ErrorCode {
++ get { return error_code; }
++ }
++ }
++
++ public delegate ValidationResult CertificateValidationCallback2 (Mono.Security.X509.X509CertificateCollection collection);
public delegate X509Certificate CertificateSelectionCallback(
X509CertificateCollection clientCertificates,
get { return ServerCertValidation2 != null; }
}
-- internal override bool OnRemoteCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection)
++ internal override ValidationResult OnRemoteCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection)
{
CertificateValidationCallback2 cb = ServerCertValidation2;
if (cb != null)
return cb (collection);
-- return false;
++ return null;
}
internal override bool OnRemoteCertificateValidation(X509Certificate certificate, int[] errors)
return base.RaiseRemoteCertificateValidation(certificate, certificateErrors);
}
-- internal virtual bool RaiseServerCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection)
++ internal virtual ValidationResult RaiseServerCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection)
{
return base.RaiseRemoteCertificateValidation2 (collection);
}
get { return ClientCertValidation2 != null; }
}
-- internal override bool OnRemoteCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection)
++ internal override ValidationResult OnRemoteCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection)
{
CertificateValidationCallback2 cb = ClientCertValidation2;
if (cb != null)
return cb (collection);
-- return false;
++ return null;
}
internal bool RaiseClientCertificateValidation(
X509CertificateCollection serverRequestedCertificates);
internal abstract bool OnRemoteCertificateValidation(X509Certificate certificate, int[] errors);
-- internal abstract bool OnRemoteCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection);
++ internal abstract ValidationResult OnRemoteCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection);
internal abstract bool HaveRemoteValidation2Callback { get; }
internal abstract AsymmetricAlgorithm OnLocalPrivateKeySelection(X509Certificate certificate, string targetHost);
return OnRemoteCertificateValidation(certificate, errors);
}
-- internal bool RaiseRemoteCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection)
++ internal ValidationResult RaiseRemoteCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection)
{
return OnRemoteCertificateValidation2 (collection);
}
++2010-03-11 Gonzalo Paniagua Javier <gonzalo@novell.com>
++
++ * OSX509Certificates.cs: moved to System.dll.
++
2010-02-27 Miguel de Icaza <miguel@novell.com>
* OSX509Certificates.cs: Add support to validate X509 certificate
+++ /dev/null
--// Copyright (C) 2010 Novell, Inc (http://www.novell.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.Runtime.InteropServices;
--using Mono.Security.X509;
--using Mono.Security.X509.Extensions;
--
--namespace Mono.Security.X509 {
--
-- internal class OSX509Certificates {
-- public const string SecurityLibrary = "/System/Library/Frameworks/Security.framework/Security";
-- public const string CoreFoundationLibrary = "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation";
--
-- [DllImport (SecurityLibrary)]
-- extern static IntPtr SecCertificateCreateWithData (IntPtr allocator, IntPtr nsdataRef);
--
-- [DllImport (SecurityLibrary)]
-- extern static int SecTrustCreateWithCertificates (IntPtr certOrCertArray, IntPtr policies, out IntPtr sectrustref);
--
-- [DllImport (SecurityLibrary)]
-- extern static IntPtr SecPolicyCreateSSL (int server, IntPtr cfStringHostname);
--
-- [DllImport (SecurityLibrary)]
-- extern static int SecTrustEvaluate (IntPtr secTrustRef, out SecTrustResult secTrustResultTime);
--
-- [DllImport (CoreFoundationLibrary)]
-- unsafe extern static IntPtr CFDataCreate (IntPtr allocator, byte *bytes, IntPtr length);
--
-- [DllImport (CoreFoundationLibrary)]
-- unsafe extern static void CFRelease (IntPtr handle);
--
-- [DllImport (CoreFoundationLibrary)]
-- extern static IntPtr CFArrayCreate (IntPtr allocator, IntPtr values, IntPtr numValues, IntPtr callbacks);
--
-- public enum SecTrustResult {
-- Invalid,
-- Proceed,
-- Confirm,
-- Deny,
-- Unspecified,
-- RecoverableTrustFailure,
-- FatalTrustFailure,
-- ResultOtherError,
-- }
--
-- static IntPtr sslsecpolicy = SecPolicyCreateSSL (0, IntPtr.Zero);
--
-- static IntPtr MakeCFData (byte [] data)
-- {
-- unsafe {
-- fixed (byte *ptr = &data [0])
-- return CFDataCreate (IntPtr.Zero, ptr, (IntPtr) data.Length);
-- }
-- }
--
-- static unsafe IntPtr FromIntPtrs (IntPtr [] values)
-- {
-- fixed (IntPtr* pv = values) {
-- return CFArrayCreate (
-- IntPtr.Zero,
-- (IntPtr) pv,
-- (IntPtr) values.Length,
-- IntPtr.Zero);
-- }
-- }
--
-- public static SecTrustResult TrustEvaluateSsl (X509CertificateCollection certificates)
-- {
-- try {
-- return _TrustEvaluateSsl (certificates);
-- } catch {
-- return SecTrustResult.Deny;
-- }
-- }
--
-- static SecTrustResult _TrustEvaluateSsl (X509CertificateCollection certificates)
-- {
-- if (certificates == null)
-- throw new ArgumentNullException ("certificates");
--
-- int certCount = certificates.Count;
-- IntPtr [] cfDataPtrs = new IntPtr [certCount];
-- IntPtr [] secCerts = new IntPtr [certCount];
-- IntPtr certArray = IntPtr.Zero;
--
-- try {
-- for (int i = 0; i < certCount; i++)
-- cfDataPtrs [i] = MakeCFData (certificates [i].RawData);
--
-- for (int i = 0; i < certCount; i++){
-- secCerts [i] = SecCertificateCreateWithData (IntPtr.Zero, cfDataPtrs [i]);
-- if (secCerts [i] == IntPtr.Zero){
-- CFRelease (cfDataPtrs [i]);
-- return SecTrustResult.Deny;
-- }
-- }
-- certArray = FromIntPtrs (secCerts);
-- IntPtr sectrust;
-- int code = SecTrustCreateWithCertificates (certArray, sslsecpolicy, out sectrust);
-- if (code == 0){
-- SecTrustResult result;
-- code = SecTrustEvaluate (sectrust, out result);
-- if (code != 0)
-- return SecTrustResult.Deny;
--
-- CFRelease (sectrust);
-- CFRelease (sslsecpolicy);
--
-- return result;
-- }
-- return SecTrustResult.Deny;
-- } finally {
-- for (int i = 0; i < certCount; i++)
-- if (secCerts [i] != IntPtr.Zero)
-- CFRelease (cfDataPtrs [i]);
--
-- if (certArray != IntPtr.Zero)
-- CFRelease (certArray);
-- }
-- }
-- }
--}
--
./Mono.Security.Cryptography/SHA224.cs
./Mono.Security.Cryptography/SHA224Managed.cs
./Mono.Security.Cryptography/SymmetricTransform.cs
--./Mono.Security.X509/OSX509Certificates.cs
./Mono.Security.X509/PKCS12.cs
./Mono.Security.X509/X501Name.cs
./Mono.Security.X509/X509Builder.cs
++2010-03-11 Gonzalo Paniagua Javier <gonzalo@novell.com>
++
++ * ServicePointManager.cs: perform the entire chain validation here.
+
+2010-03-09 Gonzalo Paniagua Javier <gonzalo@novell.com>
+
+ * HttpConnection.cs: set the right position when a CR is found.
+ Fixes bug #577891.
+
+2010-03-09 Gonzalo Paniagua Javier <gonzalo@novell.com>
+
+ * HttpListener.cs:
+ * HttpListenerRequest.cs:
+ * ListenerAsyncResult.cs:
+ * HttpConnection.cs: make sure there is no pending input when reusing
+ the connection.
+
+2010-03-08 Gonzalo Paniagua Javier <gonzalo@novell.com>
+
+ * HttpListenerContext.cs: split the auth header in 2 parts.
+ * HttpListener.cs: backported SelectAuthenticationScheme and
+ added new InternalEndGetContext used for connections that require
+ authentication.
+ * ListenerAsyncResult.cs: allow this object to be just a forwarder
+ when nesting connections for authentication purposes.
+ Fixes bug #585455.
+
+2010-03-06 Gonzalo Paniagua Javier <gonzalo@novell.com>
+
+ * WebClient.cs: fix for UploadStringAsync(). Closes bug #577818.
+ Patch by Atsushi.
+
+2010-03-04 Atsushi Enomoto <atsushi@ximian.com>
+
+ * HttpListenerContext.cs : WWW-Authenticate header should not be
+ limited to Basic.
+
+2010-03-04 Atsushi Enomoto <atsushi@ximian.com>
+
+ * HttpListenerContext.cs : The header line here is already trimmed
+ "Authorization:" , so do not try to remove it.
+
+2010-03-04 Atsushi Enomoto <atsushi@ximian.com>
+
+ * HttpListener.cs, ListenerAsyncResult.cs : fix authentication
+ scheme selection mismatch.
+
2010-03-03 Atsushi Enomoto <atsushi@ximian.com>
* HttpListenerContext.cs, HttpListener.cs :
//
// System.Net.ServicePointManager
//
--// Author:
++// Authors:
// Lawrence Pit (loz@cable.a2000.nl)
++// Gonzalo Paniagua Javier (gonzalo@novell.com)
++//
++// Copyright (c) 2003-2010 Novell, Inc (http://www.novell.com)
//
//
using Mono.Security;
using Mono.Security.Cryptography;
using Mono.Security.X509.Extensions;
++using Mono.Security.Protocol.Tls;
++using MSX = Mono.Security.X509;
#endif
#endif
// Properties
#if NET_2_0
-- [Obsolete ("Use ServerCertificateValidationCallback instead",
-- false)]
++ [Obsolete ("Use ServerCertificateValidationCallback instead", false)]
#endif
public static ICertificatePolicy CertificatePolicy {
get { return policy; }
// Used when the obsolete ICertificatePolicy is set to DefaultCertificatePolicy
// and the new ServerCertificateValidationCallback is not null
-- internal bool ValidateChain (Mono.Security.X509.X509CertificateCollection certs)
++ internal ValidationResult ValidateChain (Mono.Security.X509.X509CertificateCollection certs)
{
++ // user_denied is true if the user callback is called and returns false
++ bool user_denied = false;
if (certs == null || certs.Count == 0)
-- return false;
++ return null;
++ ICertificatePolicy policy = ServicePointManager.CertificatePolicy;
RemoteCertificateValidationCallback cb = ServicePointManager.ServerCertificateValidationCallback;
-- if (cb == null)
-- return false;
X509Chain chain = new X509Chain ();
chain.ChainPolicy = new X509ChainPolicy ();
}
X509Certificate2 leaf = new X509Certificate2 (certs [0].RawData);
++ int status11 = 0; // Error code passed to the obsolete ICertificatePolicy callback
SslPolicyErrors errors = 0;
if (!chain.Build (leaf))
errors |= GetErrorsFromChain (chain);
-- if (!CheckCertificateUsage (leaf)) // -2146762490: CERT_E_PURPOSE
++ if (!CheckCertificateUsage (leaf)) {
errors |= SslPolicyErrors.RemoteCertificateChainErrors;
-- if (!CheckServerIdentity (leaf, Host))
++ status11 = -2146762490; //CERT_E_PURPOSE 0x800B0106
++ }
++ if (!CheckServerIdentity (leaf, Host)) {
errors |= SslPolicyErrors.RemoteCertificateNameMismatch;
-- return cb (sender, leaf, chain, errors);
++ status11 = -2146762481; // CERT_E_CN_NO_MATCH 0x800B010F
++ }
++
++ bool result = false;
++ // No certificate root found means no mozroots or monotouch
++ if (Environment.OSVersion.Platform == PlatformID.MacOSX) {
++#if !MONOTOUCH
++ if (System.IO.File.Exists (MSX.OSX509Certificates.SecurityLibrary)) {
++#endif
++ // Attempt to use OSX certificates
++ // Ideally we should return the SecTrustResult
++ MSX.OSX509Certificates.SecTrustResult trustResult;
++ try {
++ trustResult = MSX.OSX509Certificates.TrustEvaluateSsl (certs);
++ // We could use the other values of trustResult to pass this extra information
++ // to the .NET 2 callback for values like SecTrustResult.Confirm
++ result = (trustResult == MSX.OSX509Certificates.SecTrustResult.Proceed ||
++ trustResult == MSX.OSX509Certificates.SecTrustResult.Unspecified);
++
++ } catch {
++ // Ignore
++ }
++ // Clear error status if the OS told us to trust the certificate
++ if (result) {
++ status11 = 0;
++ errors = 0;
++ }
++#if !MONOTOUCH
++ }
++#endif
++ }
++
++ if (policy != null && (!(policy is DefaultCertificatePolicy) || cb == null)) {
++ ServicePoint sp = null;
++ HttpWebRequest req = sender as HttpWebRequest;
++ if (req != null)
++ sp = req.ServicePoint;
++ if (status11 == 0 && errors != 0)
++ status11 = GetStatusFromChain (chain);
++
++ // pre 2.0 callback
++ result = policy.CheckValidationResult (sp, leaf, req, status11);
++ user_denied = !result && !(policy is DefaultCertificatePolicy);
++ }
++ // If there's a 2.0 callback, it takes precedence
++ if (cb != null) {
++ result = cb (sender, leaf, chain, errors);
++ user_denied = !result;
++ }
++ return new ValidationResult (result, user_denied, status11);
++ }
++
++ static int GetStatusFromChain (X509Chain chain)
++ {
++ long result = 0;
++ foreach (var status in chain.ChainStatus) {
++ X509ChainStatusFlags flags = status.Status;
++ if (flags == X509ChainStatusFlags.NoError)
++ continue;
++
++ // CERT_E_EXPIRED
++ if ((flags & X509ChainStatusFlags.NotTimeValid) != 0) result = 0x800B0101;
++ // CERT_E_VALIDITYPERIODNESTING
++ else if ((flags & X509ChainStatusFlags.NotTimeNested) != 0) result = 0x800B0102;
++ // CERT_E_REVOKED
++ else if ((flags & X509ChainStatusFlags.Revoked) != 0) result = 0x800B010C;
++ // TRUST_E_CERT_SIGNATURE
++ else if ((flags & X509ChainStatusFlags.NotSignatureValid) != 0) result = 0x80096004;
++ // CERT_E_WRONG_USAGE
++ else if ((flags & X509ChainStatusFlags.NotValidForUsage) != 0) result = 0x800B0110;
++ // CERT_E_UNTRUSTEDROOT
++ else if ((flags & X509ChainStatusFlags.UntrustedRoot) != 0) result = 0x800B0109;
++ // CRYPT_E_NO_REVOCATION_CHECK
++ else if ((flags & X509ChainStatusFlags.RevocationStatusUnknown) != 0) result = 0x80092012;
++ // CERT_E_CHAINING
++ else if ((flags & X509ChainStatusFlags.Cyclic) != 0) result = 0x800B010A;
++ // TRUST_E_FAIL - generic
++ else if ((flags & X509ChainStatusFlags.InvalidExtension) != 0) result = 0x800B010B;
++ // CERT_E_UNTRUSTEDROOT
++ else if ((flags & X509ChainStatusFlags.InvalidPolicyConstraints) != 0) result = 0x800B010D;
++ // TRUST_E_BASIC_CONSTRAINTS
++ else if ((flags & X509ChainStatusFlags.InvalidBasicConstraints) != 0) result = 0x80096019;
++ // CERT_E_INVALID_NAME
++ else if ((flags & X509ChainStatusFlags.InvalidNameConstraints) != 0) result = 0x800B0114;
++ // CERT_E_INVALID_NAME
++ else if ((flags & X509ChainStatusFlags.HasNotSupportedNameConstraint) != 0) result = 0x800B0114;
++ // CERT_E_INVALID_NAME
++ else if ((flags & X509ChainStatusFlags.HasNotDefinedNameConstraint) != 0) result = 0x800B0114;
++ // CERT_E_INVALID_NAME
++ else if ((flags & X509ChainStatusFlags.HasNotPermittedNameConstraint) != 0) result = 0x800B0114;
++ // CERT_E_INVALID_NAME
++ else if ((flags & X509ChainStatusFlags.HasExcludedNameConstraint) != 0) result = 0x800B0114;
++ // CERT_E_CHAINING
++ else if ((flags & X509ChainStatusFlags.PartialChain) != 0) result = 0x800B010A;
++ // CERT_E_EXPIRED
++ else if ((flags & X509ChainStatusFlags.CtlNotTimeValid) != 0) result = 0x800B0101;
++ // TRUST_E_CERT_SIGNATURE
++ else if ((flags & X509ChainStatusFlags.CtlNotSignatureValid) != 0) result = 0x80096004;
++ // CERT_E_WRONG_USAGE
++ else if ((flags & X509ChainStatusFlags.CtlNotValidForUsage) != 0) result = 0x800B0110;
++ // CRYPT_E_NO_REVOCATION_CHECK
++ else if ((flags & X509ChainStatusFlags.OfflineRevocation) != 0) result = 0x80092012;
++ // CERT_E_ISSUERCHAINING
++ else if ((flags & X509ChainStatusFlags.NoIssuanceChainPolicy) != 0) result = 0x800B0107;
++ else result = 0x800B010B; // TRUST_E_FAIL - generic
++
++ break; // Exit the loop on the first error
++ }
++ return (int) result;
}
static SslPolicyErrors GetErrorsFromChain (X509Chain chain)
}
}
++/*
++ // Attempt to use OSX certificates
++ //
++ // Ideally we should return the SecTrustResult
++#if !MONOTOUCH
++ if (System.IO.File.Exists (OSX509Certificates.SecurityLibrary)){
++#endif
++ OSX509Certificates.SecTrustResult trustResult = OSX509Certificates.TrustEvaluateSsl (certificates);
++
++ // We could use the other values of trustResult to pass this extra information to the .NET 2 callback
++ // for values like SecTrustResult.Confirm
++ result = (trustResult == OSX509Certificates.SecTrustResult.Proceed ||
++ trustResult == OSX509Certificates.SecTrustResult.Unspecified);
++#if !MONOTOUCH
++ }
++#endif
++*/
++2010-03-11 Gonzalo Paniagua Javier <gonzalo@novell.com>
++
++ * OSX509Certificates.cs: moved here from Mono.Security.
++
2009-07-10 Gonzalo Paniagua Javier <gonzalo@novell.com>
* X509Chain.cs: revert my last change here since it caused 2 tests to
--- /dev/null
--- /dev/null
++// Copyright (C) 2010 Novell, Inc (http://www.novell.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.
++//
++#if SECURITY_DEP
++using System;
++using System.Runtime.InteropServices;
++using Mono.Security.X509;
++using Mono.Security.X509.Extensions;
++
++namespace Mono.Security.X509 {
++
++ internal class OSX509Certificates {
++ public const string SecurityLibrary = "/System/Library/Frameworks/Security.framework/Security";
++ public const string CoreFoundationLibrary = "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation";
++
++ [DllImport (SecurityLibrary)]
++ extern static IntPtr SecCertificateCreateWithData (IntPtr allocator, IntPtr nsdataRef);
++
++ [DllImport (SecurityLibrary)]
++ extern static int SecTrustCreateWithCertificates (IntPtr certOrCertArray, IntPtr policies, out IntPtr sectrustref);
++
++ [DllImport (SecurityLibrary)]
++ extern static IntPtr SecPolicyCreateSSL (int server, IntPtr cfStringHostname);
++
++ [DllImport (SecurityLibrary)]
++ extern static int SecTrustEvaluate (IntPtr secTrustRef, out SecTrustResult secTrustResultTime);
++
++ [DllImport (CoreFoundationLibrary)]
++ unsafe extern static IntPtr CFDataCreate (IntPtr allocator, byte *bytes, IntPtr length);
++
++ [DllImport (CoreFoundationLibrary)]
++ unsafe extern static void CFRelease (IntPtr handle);
++
++ [DllImport (CoreFoundationLibrary)]
++ extern static IntPtr CFArrayCreate (IntPtr allocator, IntPtr values, IntPtr numValues, IntPtr callbacks);
++
++ public enum SecTrustResult {
++ Invalid,
++ Proceed,
++ Confirm,
++ Deny,
++ Unspecified,
++ RecoverableTrustFailure,
++ FatalTrustFailure,
++ ResultOtherError,
++ }
++
++ static IntPtr sslsecpolicy = SecPolicyCreateSSL (0, IntPtr.Zero);
++
++ static IntPtr MakeCFData (byte [] data)
++ {
++ unsafe {
++ fixed (byte *ptr = &data [0])
++ return CFDataCreate (IntPtr.Zero, ptr, (IntPtr) data.Length);
++ }
++ }
++
++ static unsafe IntPtr FromIntPtrs (IntPtr [] values)
++ {
++ fixed (IntPtr* pv = values) {
++ return CFArrayCreate (
++ IntPtr.Zero,
++ (IntPtr) pv,
++ (IntPtr) values.Length,
++ IntPtr.Zero);
++ }
++ }
++
++ public static SecTrustResult TrustEvaluateSsl (X509CertificateCollection certificates)
++ {
++ try {
++ return _TrustEvaluateSsl (certificates);
++ } catch {
++ return SecTrustResult.Deny;
++ }
++ }
++
++ static SecTrustResult _TrustEvaluateSsl (X509CertificateCollection certificates)
++ {
++ if (certificates == null)
++ throw new ArgumentNullException ("certificates");
++
++ int certCount = certificates.Count;
++ IntPtr [] cfDataPtrs = new IntPtr [certCount];
++ IntPtr [] secCerts = new IntPtr [certCount];
++ IntPtr certArray = IntPtr.Zero;
++
++ try {
++ for (int i = 0; i < certCount; i++)
++ cfDataPtrs [i] = MakeCFData (certificates [i].RawData);
++
++ for (int i = 0; i < certCount; i++){
++ secCerts [i] = SecCertificateCreateWithData (IntPtr.Zero, cfDataPtrs [i]);
++ if (secCerts [i] == IntPtr.Zero){
++ CFRelease (cfDataPtrs [i]);
++ return SecTrustResult.Deny;
++ }
++ }
++ certArray = FromIntPtrs (secCerts);
++ IntPtr sectrust;
++ int code = SecTrustCreateWithCertificates (certArray, sslsecpolicy, out sectrust);
++ if (code == 0){
++ SecTrustResult result;
++ code = SecTrustEvaluate (sectrust, out result);
++ if (code != 0)
++ return SecTrustResult.Deny;
++
++ CFRelease (sectrust);
++ CFRelease (sslsecpolicy);
++
++ return result;
++ }
++ return SecTrustResult.Deny;
++ } finally {
++ for (int i = 0; i < certCount; i++)
++ if (secCerts [i] != IntPtr.Zero)
++ CFRelease (cfDataPtrs [i]);
++
++ if (certArray != IntPtr.Zero)
++ CFRelease (certArray);
++ }
++ }
++ }
++}
++#endif
System.Security.Cryptography/Oid.cs
System.Security.Cryptography/OidEnumerator.cs
System.Security.Cryptography.X509Certificates/OpenFlags.cs
++System.Security.Cryptography.X509Certificates/OSX509Certificates.cs
System.Security.Cryptography.X509Certificates/PublicKey.cs
System.Security.Cryptography.X509Certificates/StoreLocation.cs
System.Security.Cryptography.X509Certificates/StoreName.cs
System.Security.Cryptography/OidEnumerator.cs
System.Security.Cryptography.X509Certificates/OpenFlags.cs
++System.Security.Cryptography.X509Certificates/OSX509Certificates.cs
System.Security.Cryptography.X509Certificates/PublicKey.cs
System.Security.Cryptography.X509Certificates/StoreLocation.cs
System.Security.Cryptography.X509Certificates/StoreName.cs