throw new ArgumentOutOfRangeException ("value");
defaultConnectionLimit = value;
+ if (manager != null)
+ manager.Add ("*", defaultConnectionLimit);
}
}
throw new ArgumentNullException ("address");
RecycleServicePoints ();
+
+ var origAddress = new Uri (address.Scheme + "://" + address.Authority);
bool usesProxy = false;
bool useConnect = false;
ServicePoint sp = null;
lock (servicePoints) {
- SPKey key = new SPKey (address, useConnect);
+ SPKey key = new SPKey (origAddress, useConnect);
sp = servicePoints [key] as ServicePoint;
if (sp != null)
return sp;
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 {
int status11 = 0; // Error code passed to the obsolete ICertificatePolicy callback
SslPolicyErrors errors = 0;
X509Chain chain = null;
-#if !MONOTOUCH
+ bool result = false;
+#if MONOTOUCH
+ // The X509Chain is not really usable with MonoTouch (since the decision is not based on this data)
+ // However if someone wants to override the results (good or bad) from iOS then they will want all
+ // the certificates that the server provided (which generally does not include the root) so, only
+ // if there's a user callback, we'll create the X509Chain but won't build it
+ // ref: https://bugzilla.xamarin.com/show_bug.cgi?id=7245
+ if (cb != null) {
+#endif
chain = new X509Chain ();
chain.ChainPolicy = new X509ChainPolicy ();
chain.ChainPolicy.RevocationMode = revocation_mode;
X509Certificate2 c2 = new X509Certificate2 (certs [i].RawData);
chain.ChainPolicy.ExtraStore.Add (c2);
}
-
+#if MONOTOUCH
+ }
+#else
try {
if (!chain.Build (leaf))
errors |= GetErrorsFromChain (chain);
Console.Error.WriteLine ("Please, report this problem to the Mono team");
errors |= SslPolicyErrors.RemoteCertificateChainErrors;
}
-#endif
- if (!CheckCertificateUsage (leaf)) {
- errors |= SslPolicyErrors.RemoteCertificateChainErrors;
- status11 = -2146762490; //CERT_E_PURPOSE 0x800B0106
- }
- if (!CheckServerIdentity (certs [0], Host)) {
- errors |= SslPolicyErrors.RemoteCertificateNameMismatch;
- status11 = -2146762481; // CERT_E_CN_NO_MATCH 0x800B010F
- }
+ // for OSX and iOS we're using the native API to check for the SSL server policy and host names
+ if (!is_macosx) {
+ if (!CheckCertificateUsage (leaf)) {
+ errors |= SslPolicyErrors.RemoteCertificateChainErrors;
+ status11 = -2146762490; //CERT_E_PURPOSE 0x800B0106
+ }
- bool result = false;
- // No certificate root found means no mozroots or monotouch
-#if !MONOTOUCH
- if (is_macosx) {
+ if (!CheckServerIdentity (certs [0], Host)) {
+ errors |= SslPolicyErrors.RemoteCertificateNameMismatch;
+ status11 = -2146762481; // CERT_E_CN_NO_MATCH 0x800B010F
+ }
+ } else {
#endif
// Attempt to use OSX certificates
// Ideally we should return the SecTrustResult
MSX.OSX509Certificates.SecTrustResult trustResult = MSX.OSX509Certificates.SecTrustResult.Deny;
try {
- trustResult = MSX.OSX509Certificates.TrustEvaluateSsl (certs);
+ trustResult = MSX.OSX509Certificates.TrustEvaluateSsl (certs, Host);
// 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;
+ // TrustEvaluateSsl was successful so there's no trust error
+ // IOW we discard our own chain (since we trust OSX one instead)
errors = 0;
} else {
// callback and DefaultCertificatePolicy needs this since 'result' is not specified
#endif
#if MONODROID
- result = monodroidCallback (certs);
+ result = AndroidPlatform.TrustEvaluateSsl (certs, sender, leaf, chain, errors);
if (result) {
- status11 = 0;
- errors = 0;
+ // chain.Build() + GetErrorsFromChain() (above) will ALWAYS fail on
+ // Android (there are no mozroots or preinstalled root certificates),
+ // thus `errors` will ALWAYS have RemoteCertificateChainErrors.
+ // Android just verified the chain; clear RemoteCertificateChainErrors.
+ errors &= ~SslPolicyErrors.RemoteCertificateChainErrors;
}
#endif
}
return (int) result;
}
-
+#if !MONOTOUCH
static SslPolicyErrors GetErrorsFromChain (X509Chain chain)
{
SslPolicyErrors errors = SslPolicyErrors.None;
string start = pattern.Substring (0, index);
return (String.Compare (hostname, 0, start, 0, start.Length, true, CultureInfo.InvariantCulture) == 0);
}
+#endif
}
#endif
}