Pass SSL certificate chain, not just collection, to Mono.Android.dll
authorJonathan Pryor <jonpryor@vt.edu>
Mon, 13 Aug 2012 17:44:16 +0000 (13:44 -0400)
committerJonathan Pryor <jonpryor@vt.edu>
Mon, 13 Aug 2012 17:48:16 +0000 (13:48 -0400)
Fixes BCL half of: https://bugzilla.xamarin.com/show_bug.cgi?id=6501

Today I learned that the SSL certificate collection (as held in
X509CertificateCollection) is a potentially unordered sequence of SSL
certificates, which not all versions of Android will validate.

The fix is to use the properly ordered SSL certificate chain (as held
in X509Chain), and have Android validate that.

mcs/class/System/System.Net/ServicePointManager.cs
mcs/class/System/System/AndroidPlatform.cs [new file with mode: 0644]
mcs/class/System/monodroid_System.dll.sources

index 23c56bd28e71cb96c1b108306a38205fa4ab0095..d64f58cd1e53ea2b9a4dbf954471e3da70928092 100644 (file)
@@ -408,19 +408,8 @@ namespace System.Net
                        static bool is_macosx = System.IO.File.Exists (MSX.OSX509Certificates.SecurityLibrary);
                        static X509RevocationMode revocation_mode;
 
-#if MONODROID
-                       static readonly Converter<Mono.Security.X509.X509CertificateCollection, bool> monodroidCallback;
-#endif
-
                        static ChainValidationHelper ()
                        {
-#if MONODROID
-                               monodroidCallback = (Converter<Mono.Security.X509.X509CertificateCollection, bool>)
-                                       Delegate.CreateDelegate (typeof(Converter<Mono.Security.X509.X509CertificateCollection, bool>), 
-                                                       Type.GetType ("Android.Runtime.AndroidEnvironment, Mono.Android", true)
-                                                       .GetMethod ("TrustEvaluateSsl", 
-                                                               System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic));
-#endif
 #if !MONOTOUCH
                                revocation_mode = X509RevocationMode.NoCheck;
                                try {
@@ -524,7 +513,7 @@ namespace System.Net
 #endif
 
 #if MONODROID
-                               result = monodroidCallback (certs);
+                               result = AndroidPlatform.TrustEvaluateSsl (certs, sender, leaf, chain, errors);
                                if (result) {
                                        status11 = 0;
                                        errors = 0;
diff --git a/mcs/class/System/System/AndroidPlatform.cs b/mcs/class/System/System/AndroidPlatform.cs
new file mode 100644 (file)
index 0000000..9719ea7
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// System.AndroidPlatform.cs
+//
+// Author:
+//   Jonathan Pryor (jonp@xamarin.com)
+//
+// Copyright (C) 2012 Xamarin Inc (http://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.
+//
+
+#if MONODROID
+using System;
+using System.Net.Security;
+using System.Security.Cryptography.X509Certificates;
+
+using MSX = Mono.Security.X509;
+
+namespace System {
+
+       internal static class AndroidPlatform {
+
+#if SECURITY_DEP
+               static readonly Converter<MSX.X509CertificateCollection, bool> trustEvaluateSsl;
+               static readonly Func<MSX.X509CertificateCollection, object, X509Certificate2, X509Chain, SslPolicyErrors, bool> trustEvaluateSsl2;
+#endif  // SECURITY_DEP
+
+
+               static AndroidPlatform ()
+               {
+#if SECURITY_DEP
+                       var t = Type.GetType ("Android.Runtime.AndroidEnvironment, Mono.Android", throwOnError:true);
+                       trustEvaluateSsl2 = (Func<MSX.X509CertificateCollection, object, X509Certificate2, X509Chain, SslPolicyErrors, bool>)
+                               Delegate.CreateDelegate (
+                                               typeof (Func<MSX.X509CertificateCollection, object, X509Certificate2, X509Chain, SslPolicyErrors, bool>),
+                                               t,
+                                               "TrustEvaluateSsl2",
+                                               ignoreCase:false,
+                                               throwOnBindFailure:false);
+                       if (trustEvaluateSsl2 == null)
+                               trustEvaluateSsl = (Converter<MSX.X509CertificateCollection, bool>)
+                                       Delegate.CreateDelegate (typeof (Converter<MSX.X509CertificateCollection, bool>),
+                                                       t,
+                                                       "TrustEvaluateSsl",
+                                                       ignoreCase:false,
+                                                       throwOnBindFailure:true);
+#endif  // SECURITY_DEP
+               }
+
+#if SECURITY_DEP
+               internal static bool TrustEvaluateSsl (MSX.X509CertificateCollection collection, object sender, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors errors)
+               {
+                       if (trustEvaluateSsl2 != null)
+                               return trustEvaluateSsl2 (collection, sender, certificate, chain, errors);
+                       return trustEvaluateSsl (collection);
+               }
+#endif  // SECURITY_DEP
+       }
+}
+#endif  // MONODROID
index be5e81d6e53d1493bdc50398d3c889b32477d123..019f8681bd186d69f849f06af8941bfd50f989af 100644 (file)
@@ -1,2 +1,3 @@
 #include mobile_System.dll.sources
+System/AndroidPlatform.cs
 System.CodeDom.Compiler/IndentedTextWriter.cs