Merge remote branch 'upstream/master'
[mono.git] / mcs / class / System / System.Net / ServicePointManager.cs
index a2692c615db9313fbf8c2048f861c44065243abf..b277d9f89cc9430d8633987824445e1783f177e6 100644 (file)
@@ -36,7 +36,6 @@ using System.Configuration;
 using System.Net.Configuration;
 using System.Security.Cryptography.X509Certificates;
 
-#if NET_2_0
 using System.Globalization;
 using System.Net.Security;
 #if SECURITY_DEP
@@ -47,7 +46,6 @@ using Mono.Security.X509.Extensions;
 using Mono.Security.Protocol.Tls;
 using MSX = Mono.Security.X509;
 #endif
-#endif
 
 //
 // notes:
@@ -69,8 +67,11 @@ using MSX = Mono.Security.X509;
 
 namespace System.Net 
 {
-       public class ServicePointManager
-       {
+#if MOONLIGHT
+       internal class ServicePointManager {
+#else
+       public class ServicePointManager {
+#endif
                class SPKey {
                        Uri uri; // schema/host/port
                        bool use_connect;
@@ -121,23 +122,21 @@ namespace System.Net
 #endif
                static bool useNagle;
 #endif
-#if NET_2_0
                static RemoteCertificateValidationCallback server_cert_cb;
-#endif
 
                // Fields
                
                public const int DefaultNonPersistentConnectionLimit = 4;
                public const int DefaultPersistentConnectionLimit = 2;
 
-#if !MONOTOUCH
+#if !NET_2_1
                const string configKey = "system.net/connectionManagement";
                static ConnectionManagementData manager;
 #endif
                
                static ServicePointManager ()
                {
-#if !MONOTOUCH
+#if !NET_2_1
 #if NET_2_0 && CONFIGURATION_DEP
                        object cfg = ConfigurationManager.GetSection (configKey);
                        ConnectionManagementSection s = cfg as ConnectionManagementSection;
@@ -258,7 +257,6 @@ namespace System.Net
                        set { _securityProtocol = value; }
                }
 
-#if NET_2_0
                public static RemoteCertificateValidationCallback ServerCertificateValidationCallback
                {
                        get {
@@ -268,7 +266,6 @@ namespace System.Net
                                server_cert_cb = value;
                        }
                }
-#endif
 
 #if NET_1_1
                public static bool Expect100Continue {
@@ -326,7 +323,7 @@ namespace System.Net
                                        throw new InvalidOperationException ("maximum number of service points reached");
 
                                string addr = address.ToString ();
-#if MONOTOUCH
+#if NET_2_1
                                int limit = defaultConnectionLimit;
 #else
                                int limit = (int) manager.GetMaxConnections (addr);
@@ -380,10 +377,29 @@ namespace System.Net
                                        servicePoints.Remove (list.GetByIndex (i));
                        }
                }
-#if NET_2_0 && SECURITY_DEP
+#if MOONLIGHT && SECURITY_DEP
+               internal class ChainValidationHelper {
+                       object sender;
+
+                       public ChainValidationHelper (object sender)
+                       {
+                               this.sender = sender;
+                       }
+
+                       // no need to check certificates since we are either
+                       // (a) loading from the site of origin (and we accepted its certificate to load from it)
+                       // (b) loading from a cross-domain site and we downloaded the policy file using the browser stack
+                       //     i.e. the certificate was accepted (or the policy would not be valid)
+                       internal ValidationResult ValidateChain (Mono.Security.X509.X509CertificateCollection certs)
+                       {
+                               return new ValidationResult (true, false, 0);
+                       }
+               }
+#elif NET_2_0 && SECURITY_DEP
                internal class ChainValidationHelper {
                        object sender;
                        string host;
+                       static bool is_macosx = System.IO.File.Exists (MSX.OSX509Certificates.SecurityLibrary);
 
                        public ChainValidationHelper (object sender)
                        {
@@ -422,22 +438,29 @@ namespace System.Net
                                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);
+                               try {
+                                       if (!chain.Build (leaf))
+                                               errors |= GetErrorsFromChain (chain);
+                               } catch (Exception e) {
+                                       Console.Error.WriteLine ("ERROR building certificate chain: {0}", e);
+                                       Console.Error.WriteLine ("Please, report this problem to the Mono team");
+                                       errors |= SslPolicyErrors.RemoteCertificateChainErrors;
+                               }
+
                                if (!CheckCertificateUsage (leaf)) {
                                        errors |= SslPolicyErrors.RemoteCertificateChainErrors;
                                        status11 = -2146762490; //CERT_E_PURPOSE 0x800B0106
                                }
-                               if (!CheckServerIdentity (leaf, Host)) {
+
+                               if (!CheckServerIdentity (certs [0], Host)) {
                                        errors |= SslPolicyErrors.RemoteCertificateNameMismatch;
                                        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)) {
+                               if (is_macosx) {
 #endif
                                        // Attempt to use OSX certificates
                                        // Ideally we should return the SecTrustResult
@@ -460,7 +483,6 @@ namespace System.Net
 #if !MONOTOUCH
                                }
 #endif
-                               }
 
                                if (policy != null && (!(policy is DefaultCertificatePolicy) || cb == null)) {
                                        ServicePoint sp = null;
@@ -562,37 +584,43 @@ namespace System.Net
                        // DH certificates requires some changes - does anyone use one ?
                        static bool CheckCertificateUsage (X509Certificate2 cert) 
                        {
-                               // certificate extensions are required for this
-                               // we "must" accept older certificates without proofs
-                               if (cert.Version < 3)
-                                       return true;
-
-                               X509KeyUsageExtension kux = (X509KeyUsageExtension) cert.Extensions ["2.5.29.15"];
-                               X509EnhancedKeyUsageExtension eku = (X509EnhancedKeyUsageExtension) cert.Extensions ["2.5.29.37"];
-                               if (kux != null && eku != null) {
-                                       // RFC3280 states that when both KeyUsageExtension and 
-                                       // ExtendedKeyUsageExtension are present then BOTH should
-                                       // be valid
-                                       if ((kux.KeyUsages & s_flags) == 0)
-                                               return false;
-                                       return eku.EnhancedKeyUsages ["1.3.6.1.5.5.7.3.1"] != null ||
-                                               eku.EnhancedKeyUsages ["2.16.840.1.113730.4.1"] != null;
-                               } else if (kux != null) {
-                                       return ((kux.KeyUsages & s_flags) != 0);
-                               } else if (eku != null) {
-                                       // Server Authentication (1.3.6.1.5.5.7.3.1) or
-                                       // Netscape Server Gated Crypto (2.16.840.1.113730.4)
-                                       return eku.EnhancedKeyUsages ["1.3.6.1.5.5.7.3.1"] != null ||
-                                               eku.EnhancedKeyUsages ["2.16.840.1.113730.4.1"] != null;
-                               }
+                               try {
+                                       // certificate extensions are required for this
+                                       // we "must" accept older certificates without proofs
+                                       if (cert.Version < 3)
+                                               return true;
+
+                                       X509KeyUsageExtension kux = (X509KeyUsageExtension) cert.Extensions ["2.5.29.15"];
+                                       X509EnhancedKeyUsageExtension eku = (X509EnhancedKeyUsageExtension) cert.Extensions ["2.5.29.37"];
+                                       if (kux != null && eku != null) {
+                                               // RFC3280 states that when both KeyUsageExtension and 
+                                               // ExtendedKeyUsageExtension are present then BOTH should
+                                               // be valid
+                                               if ((kux.KeyUsages & s_flags) == 0)
+                                                       return false;
+                                               return eku.EnhancedKeyUsages ["1.3.6.1.5.5.7.3.1"] != null ||
+                                                       eku.EnhancedKeyUsages ["2.16.840.1.113730.4.1"] != null;
+                                       } else if (kux != null) {
+                                               return ((kux.KeyUsages & s_flags) != 0);
+                                       } else if (eku != null) {
+                                               // Server Authentication (1.3.6.1.5.5.7.3.1) or
+                                               // Netscape Server Gated Crypto (2.16.840.1.113730.4)
+                                               return eku.EnhancedKeyUsages ["1.3.6.1.5.5.7.3.1"] != null ||
+                                                       eku.EnhancedKeyUsages ["2.16.840.1.113730.4.1"] != null;
+                                       }
 
-                               // last chance - try with older (deprecated) Netscape extensions
-                               X509Extension ext = cert.Extensions ["2.16.840.1.113730.1.1"];
-                               if (ext != null) {
-                                       string text = ext.NetscapeCertType (false);
-                                       return text.IndexOf ("SSL Server Authentication") != -1;
+                                       // last chance - try with older (deprecated) Netscape extensions
+                                       X509Extension ext = cert.Extensions ["2.16.840.1.113730.1.1"];
+                                       if (ext != null) {
+                                               string text = ext.NetscapeCertType (false);
+                                               return text.IndexOf ("SSL Server Authentication") != -1;
+                                       }
+                                       return true;
+                               } catch (Exception e) {
+                                       Console.Error.WriteLine ("ERROR processing certificate: {0}", e);
+                                       Console.Error.WriteLine ("Please, report this problem to the Mono team");
+                                       return false;
                                }
-                               return true;
                        }
 
                        // RFC2818 - HTTP Over TLS, Section 3.1
@@ -605,28 +633,33 @@ namespace System.Net
                        // 2.1.         exact match is required
                        // 3.   Use of the most specific Common Name (CN=) in the Subject
                        // 3.1          Existing practice but DEPRECATED
-                       static bool CheckServerIdentity (X509Certificate2 cert, string targetHost) 
+                       static bool CheckServerIdentity (Mono.Security.X509.X509Certificate cert, string targetHost) 
                        {
-                               X509Extension ext = cert.Extensions ["2.5.29.17"];
-                               // 1. subjectAltName
-                               if (ext != null) {
-                                       ASN1 asn = new ASN1 (ext.RawData);
-                                       SubjectAltNameExtension subjectAltName = new SubjectAltNameExtension (asn);
-                                       // 1.1 - multiple dNSName
-                                       foreach (string dns in subjectAltName.DNSNames) {
-                                               // 1.2 TODO - wildcard support
-                                               if (Match (targetHost, dns))
-                                                       return true;
-                                       }
-                                       // 2. ipAddress
-                                       foreach (string ip in subjectAltName.IPAddresses) {
-                                               // 2.1. Exact match required
-                                               if (ip == targetHost)
-                                                       return true;
+                               try {
+                                       Mono.Security.X509.X509Extension ext = cert.Extensions ["2.5.29.17"];
+                                       // 1. subjectAltName
+                                       if (ext != null) {
+                                               SubjectAltNameExtension subjectAltName = new SubjectAltNameExtension (ext);
+                                               // 1.1 - multiple dNSName
+                                               foreach (string dns in subjectAltName.DNSNames) {
+                                                       // 1.2 TODO - wildcard support
+                                                       if (Match (targetHost, dns))
+                                                               return true;
+                                               }
+                                               // 2. ipAddress
+                                               foreach (string ip in subjectAltName.IPAddresses) {
+                                                       // 2.1. Exact match required
+                                                       if (ip == targetHost)
+                                                               return true;
+                                               }
                                        }
+                                       // 3. Common Name (CN=)
+                                       return CheckDomainName (cert.SubjectName, targetHost);
+                               } catch (Exception e) {
+                                       Console.Error.WriteLine ("ERROR processing certificate: {0}", e);
+                                       Console.Error.WriteLine ("Please, report this problem to the Mono team");
+                                       return false;
                                }
-                               // 3. Common Name (CN=)
-                               return CheckDomainName (cert.SubjectName.Format (false), targetHost);
                        }
 
                        static bool CheckDomainName (string subjectName, string targetHost)
@@ -695,20 +728,3 @@ namespace System.Net
        }
 }
 
-/*
-                       // 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
-*/