From 52a76350d1a32d79432fc72b441d7d2db024007d Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Thu, 20 Aug 2009 18:26:28 +0000 Subject: [PATCH] 2009-08-20 Sebastien Pouliot * SslStream.cs : Always use/provide a X509Chain even if this duplicates some of the old/existing logic of Mono.Security. This makes it possible to provide a callback using ServicePointManager.ServerCertificateValidationCallback svn path=/trunk/mcs/; revision=140359 --- .../System/System.Net.Security/ChangeLog | 7 ++++ .../System/System.Net.Security/SslStream.cs | 39 ++++++++++++++++--- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/mcs/class/System/System.Net.Security/ChangeLog b/mcs/class/System/System.Net.Security/ChangeLog index e0d7cc0834b38..6b3d89cd536c7 100644 --- a/mcs/class/System/System.Net.Security/ChangeLog +++ b/mcs/class/System/System.Net.Security/ChangeLog @@ -1,3 +1,10 @@ +2009-08-20 Sebastien Pouliot + + * SslStream.cs : Always use/provide a X509Chain even if this + duplicates some of the old/existing logic of Mono.Security. + This makes it possible to provide a callback using + ServicePointManager.ServerCertificateValidationCallback + 2007-08-24 Atsushi Enomoto * SslStream.cs : uh, fixed the build. diff --git a/mcs/class/System/System.Net.Security/SslStream.cs b/mcs/class/System/System.Net.Security/SslStream.cs index b47171a524f44..fd5927efacfc6 100644 --- a/mcs/class/System/System.Net.Security/SslStream.cs +++ b/mcs/class/System/System.Net.Security/SslStream.cs @@ -348,13 +348,40 @@ public virtual IAsyncResult BeginAuthenticateAsClient (string targetHost, X509Ce if (validation_callback != null) s.ServerCertValidationDelegate = delegate (X509Certificate cert, int [] certErrors) { - X509Chain chain = null; - if (cert is X509Certificate2) { - chain = new X509Chain (); - chain.Build ((X509Certificate2) cert); + X509Chain chain = new X509Chain (); + X509Certificate2 x2 = (cert as X509Certificate2); + if (x2 == null) + x2 = new X509Certificate2 (cert); + + if (!ServicePointManager.CheckCertificateRevocationList) + chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; + + // SSL specific checks (done by Mono.Security.dll SSL/TLS implementation) + SslPolicyErrors errors = SslPolicyErrors.None; + foreach (int i in certErrors) { + switch (i) { + case -2146762490: // CERT_E_PURPOSE + errors |= SslPolicyErrors.RemoteCertificateNotAvailable; + break; + case -2146762481: // CERT_E_CN_NO_MATCH + errors |= SslPolicyErrors.RemoteCertificateNameMismatch; + break; + default: + errors |= SslPolicyErrors.RemoteCertificateChainErrors; + break; + } } - // FIXME: SslPolicyErrors is incomplete - SslPolicyErrors errors = certErrors.Length > 0 ? SslPolicyErrors.RemoteCertificateChainErrors : SslPolicyErrors.None; + + chain.Build (x2); + + // non-SSL specific X509 checks (i.e. RFC3280 related checks) + foreach (X509ChainStatus status in chain.ChainStatus) { + if ((status.Status & X509ChainStatusFlags.PartialChain) != 0) + errors |= SslPolicyErrors.RemoteCertificateNotAvailable; + else + errors |= SslPolicyErrors.RemoteCertificateChainErrors; + } + return validation_callback (this, cert, chain, errors); }; if (selection_callback != null)