Merge pull request #2274 from esdrubal/udpclientreceive
[mono.git] / mcs / class / System / System.Security.Cryptography.X509Certificates / OSX509Certificates.cs
index e35c2f7d7a364e938f65143dd30a262daba9ef60..184e586471dd30c167be16eca420d930c5c12bfb 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 #if SECURITY_DEP
+#if MONO_X509_ALIAS
+extern alias PrebuiltSystem;
+#endif
 
-#if MONOTOUCH || MONODROID
-using MSX = Mono.Security.X509;
+#if MONO_X509_ALIAS
+using XX509CertificateCollection = PrebuiltSystem::System.Security.Cryptography.X509Certificates.X509CertificateCollection;
 #else
-extern alias MonoSecurity;
-using MSX = MonoSecurity::Mono.Security.X509;
+using XX509CertificateCollection = System.Security.Cryptography.X509Certificates.X509CertificateCollection;
 #endif
 
 using System;
-using System.Collections.Generic;
 using System.Runtime.InteropServices;
 
 namespace System.Security.Cryptography.X509Certificates {
@@ -45,6 +46,9 @@ namespace System.Security.Cryptography.X509Certificates {
                [DllImport (SecurityLibrary)]
                extern static /* OSStatus */ int SecTrustCreateWithCertificates (IntPtr certOrCertArray, IntPtr policies, out IntPtr sectrustref);
                
+               [DllImport (SecurityLibrary)]
+               extern static /* OSStatus */ int SecTrustSetAnchorCertificates (IntPtr /* SecTrustRef */ trust, IntPtr /* CFArrayRef */ anchorCertificates);
+
                [DllImport (SecurityLibrary)]
                extern static IntPtr SecPolicyCreateSSL ([MarshalAs (UnmanagedType.I1)] bool server, IntPtr cfStringHostname);
                
@@ -57,6 +61,9 @@ namespace System.Security.Cryptography.X509Certificates {
                [DllImport (CoreFoundationLibrary)]
                unsafe extern static IntPtr CFDataCreate (IntPtr allocator, byte *bytes, /* CFIndex */ IntPtr length);
 
+               [DllImport (CoreFoundationLibrary)]
+               extern static void CFRetain (IntPtr handle);
+
                [DllImport (CoreFoundationLibrary)]
                extern static void CFRelease (IntPtr handle);
 
@@ -94,88 +101,97 @@ namespace System.Security.Cryptography.X509Certificates {
                        }
                }
 
-               static IList<byte[]> CreateArray (X509Certificate2Collection certificates)
-               {
-                       var list = new List<byte[]> (certificates.Count);
-                       for (int i = 0; i < certificates.Count; i++)
-                               list.Add (certificates [i].RawData);
-                       return list;
-               }
-               
-               static IList<byte[]> CreateArray (MSX.X509CertificateCollection certificates)
-               {
-                       var list = new List<byte[]> (certificates.Count);
-                       for (int i = 0; i < certificates.Count; i++)
-                               list.Add (certificates [i].RawData);
-                       return list;
-               }
-
-               public static SecTrustResult TrustEvaluateSsl (MSX.X509CertificateCollection certificates, string host)
+               static IntPtr GetCertificate (X509Certificate certificate, out IntPtr dataPtr)
                {
-                       if (certificates == null)
-                               return SecTrustResult.Deny;
-
-                       try {
-                               var certArray = CreateArray (certificates);
-                               return _TrustEvaluateSsl (certArray, host);
-                       } catch {
-                               return SecTrustResult.Deny;
+                       var handle = certificate.Handle;
+                       if (handle != IntPtr.Zero) {
+                               dataPtr = IntPtr.Zero;
+                               CFRetain (handle);
+                               return handle;
                        }
+                       dataPtr = MakeCFData (certificate.GetRawCertData ());
+                       return SecCertificateCreateWithData (IntPtr.Zero, dataPtr);
                }
-
-               public static SecTrustResult TrustEvaluateSsl (X509Certificate2Collection certificates, string host)
+               
+               public static SecTrustResult TrustEvaluateSsl (XX509CertificateCollection certificates, XX509CertificateCollection anchors, string host)
                {
                        if (certificates == null)
                                return SecTrustResult.Deny;
 
                        try {
-                               var certArray = CreateArray (certificates);
-                               return _TrustEvaluateSsl (certArray, host);
+                               return _TrustEvaluateSsl (certificates, anchors, host);
                        } catch {
                                return SecTrustResult.Deny;
                        }
                }
 
-               static SecTrustResult _TrustEvaluateSsl (IList<byte[]> certificates, string hostName)
+               static SecTrustResult _TrustEvaluateSsl (XX509CertificateCollection certificates, XX509CertificateCollection anchors, string hostName)
                {
                        int certCount = certificates.Count;
+                       int anchorCount = anchors != null ? anchors.Count : 0;
                        IntPtr [] cfDataPtrs = new IntPtr [certCount];
                        IntPtr [] secCerts = new IntPtr [certCount];
+                       IntPtr [] cfDataAnchorPtrs = new IntPtr [anchorCount];
+                       IntPtr [] secCertAnchors = new IntPtr [anchorCount];
                        IntPtr certArray = IntPtr.Zero;
+                       IntPtr anchorArray = IntPtr.Zero;
                        IntPtr sslsecpolicy = IntPtr.Zero;
                        IntPtr host = IntPtr.Zero;
                        IntPtr sectrust = IntPtr.Zero;
                        SecTrustResult result = SecTrustResult.Deny;
 
                        try {
-                               for (int i = 0; i < certCount; i++)
-                                       cfDataPtrs [i] = MakeCFData (certificates [i]);
-                               
-                               for (int i = 0; i < certCount; i++){
-                                       secCerts [i] = SecCertificateCreateWithData (IntPtr.Zero, cfDataPtrs [i]);
+                               for (int i = 0; i < certCount; i++) {
+                                       secCerts [i] = GetCertificate (certificates [i], out cfDataPtrs [i]);
                                        if (secCerts [i] == IntPtr.Zero)
                                                return SecTrustResult.Deny;
                                }
+
+                               for (int i = 0; i < anchorCount; i++) {
+                                       secCertAnchors [i] = GetCertificate (anchors [i], out cfDataAnchorPtrs [i]);
+                                       if (secCertAnchors [i] == IntPtr.Zero)
+                                               return SecTrustResult.Deny;
+                               }
+
                                certArray = FromIntPtrs (secCerts);
+
                                host = CFStringCreateWithCharacters (IntPtr.Zero, hostName, (IntPtr) hostName.Length);
                                sslsecpolicy = SecPolicyCreateSSL (true, host);
 
                                int code = SecTrustCreateWithCertificates (certArray, sslsecpolicy, out sectrust);
-                               if (code == 0)
-                                       code = SecTrustEvaluate (sectrust, out result);
+                               if (code != 0)
+                                       return SecTrustResult.Deny;
+
+                               if (anchorCount > 0) {
+                                       anchorArray = FromIntPtrs (secCertAnchors);
+                                       SecTrustSetAnchorCertificates (sectrust, anchorArray);
+                               }
+
+                               code = SecTrustEvaluate (sectrust, out result);
                                return result;
                        } finally {
                                for (int i = 0; i < certCount; i++)
                                        if (cfDataPtrs [i] != IntPtr.Zero)
                                                CFRelease (cfDataPtrs [i]);
 
+                               for (int i = 0; i < anchorCount; i++)
+                                       if (cfDataAnchorPtrs [i] != IntPtr.Zero)
+                                               CFRelease (cfDataAnchorPtrs [i]);
+
                                if (certArray != IntPtr.Zero)
                                        CFRelease (certArray);
+
+                               if (anchorArray != IntPtr.Zero)
+                                       CFRelease (anchorArray);
                                
                                for (int i = 0; i < certCount; i++)
                                        if (secCerts [i] != IntPtr.Zero)
                                                CFRelease (secCerts [i]);
 
+                               for (int i = 0; i < anchorCount; i++)
+                                       if (secCertAnchors [i] != IntPtr.Zero)
+                                               CFRelease (secCertAnchors [i]);
+
                                if (sslsecpolicy != IntPtr.Zero)
                                        CFRelease (sslsecpolicy);
                                if (host != IntPtr.Zero)