* If @serverMode is true, then we're a server and want to validate a certificate that we received from a client.
*/
ValidationResult ValidateCertificate (string targetHost, bool serverMode, X509CertificateCollection certificates);
+ }
+
+ internal interface ICertificateValidator2 : ICertificateValidator
+ {
+ /*
+ * Internal use only.
+ */
+ ValidationResult ValidateCertificate (string targetHost, bool serverMode, X509Certificate leaf, X509Chain chain);
/*
* On OS X and Mobile, the @chain will be initialized with the @certificates, but not actually built.
get { return supportsTrustAnchors; }
}
- static ICertificateValidator GetDefaultValidator (MonoTlsProvider provider, MonoTlsSettings settings)
+ static ICertificateValidator2 GetDefaultValidator (MonoTlsProvider provider, MonoTlsSettings settings)
{
- return (ICertificateValidator)NoReflectionHelper.GetDefaultCertificateValidator (provider, settings);
+ return (ICertificateValidator2)NoReflectionHelper.GetDefaultCertificateValidator (provider, settings);
}
/*
* Internal API, intended to be used by MonoTlsProvider implementations.
*/
- public static ICertificateValidator GetValidator (MonoTlsProvider provider, MonoTlsSettings settings)
+ internal static ICertificateValidator2 GetValidator (MonoTlsProvider provider, MonoTlsSettings settings)
{
return GetDefaultValidator (provider, settings);
}
/*
* Allows a TLS provider to provide a custom system certificiate validator.
*/
- public virtual bool HasCustomSystemCertificateValidator {
+ internal virtual bool HasCustomSystemCertificateValidator {
get { return false; }
}
* Returns `true` if certificate validation has been performed and `false` to invoke the
* default system validator.
*/
- public virtual bool InvokeSystemCertificateValidator (
- ICertificateValidator validator, string targetHost, bool serverMode,
- X509CertificateCollection certificates, ref X509Chain chain, out bool success,
- ref MonoSslPolicyErrors errors, ref int status11)
+ internal virtual bool InvokeSystemCertificateValidator (
+ ICertificateValidator2 validator, string targetHost, bool serverMode,
+ X509CertificateCollection certificates, bool wantsChain, ref X509Chain chain,
+ out bool success, ref MonoSslPolicyErrors errors, ref int status11)
{
- success = false;
- return false;
+ throw new InvalidOperationException ();
}
#endregion
{
internal delegate bool ServerCertValidationCallbackWrapper (ServerCertValidationCallback callback, X509Certificate certificate, X509Chain chain, MonoSslPolicyErrors sslPolicyErrors);
- internal class ChainValidationHelper : ICertificateValidator
+ internal class ChainValidationHelper : ICertificateValidator2
{
readonly object sender;
readonly MonoTlsSettings settings;
var certs = new XX509CertificateCollection ();
certs.Add (new X509Certificate2 (certificate.GetRawCertData ()));
- var result = ValidateChain (string.Empty, true, certs, (SslPolicyErrors)errors);
+ var result = ValidateChain (string.Empty, true, certificate, null, certs, (SslPolicyErrors)errors);
if (result == null)
return false;
public ValidationResult ValidateCertificate (string host, bool serverMode, XX509CertificateCollection certs)
{
try {
- var result = ValidateChain (host, serverMode, certs, 0);
+ X509Certificate leaf;
+ if (certs != null && certs.Count != 0)
+ leaf = certs [0];
+ else
+ leaf = null;
+ var result = ValidateChain (host, serverMode, leaf, null, certs, 0);
+ if (tlsStream != null)
+ tlsStream.CertificateValidationFailed = result == null || !result.Trusted || result.UserDenied;
+ return result;
+ } catch {
+ if (tlsStream != null)
+ tlsStream.CertificateValidationFailed = true;
+ throw;
+ }
+ }
+
+ public ValidationResult ValidateCertificate (string host, bool serverMode, X509Certificate leaf, XX509Chain xchain)
+ {
+ try {
+ var chain = (X509Chain)(object)xchain;
+ var result = ValidateChain (host, serverMode, leaf, chain, null, 0);
if (tlsStream != null)
tlsStream.CertificateValidationFailed = result == null || !result.Trusted || result.UserDenied;
return result;
}
}
- ValidationResult ValidateChain (string host, bool server, XX509CertificateCollection certs, SslPolicyErrors errors)
+ ValidationResult ValidateChain (string host, bool server, X509Certificate leaf,
+ X509Chain chain, XX509CertificateCollection certs,
+ SslPolicyErrors errors)
+ {
+ var oldChain = chain;
+ var ownsChain = chain == null;
+ try {
+ var result = ValidateChain (host, server, leaf, ref chain, certs, errors);
+ if (chain != oldChain)
+ ownsChain = true;
+
+ return result;
+ } finally {
+ // If ValidateChain() changed the chain, then we need to free it.
+ if (ownsChain && chain != null)
+ chain.Dispose ();
+ }
+ }
+
+ ValidationResult ValidateChain (string host, bool server, X509Certificate leaf,
+ ref X509Chain chain, XX509CertificateCollection certs,
+ SslPolicyErrors errors)
{
// user_denied is true if the user callback is called and returns false
bool user_denied = false;
var hasCallback = certValidationCallback != null || callbackWrapper != null;
- X509Certificate leaf;
- if (certs == null || certs.Count == 0)
- leaf = null;
- else
- leaf = certs [0];
-
if (tlsStream != null)
request.ServicePoint.UpdateServerCertificate (leaf);
ICertificatePolicy policy = ServicePointManager.GetLegacyCertificatePolicy ();
int status11 = 0; // Error code passed to the obsolete ICertificatePolicy callback
- X509Chain chain = null;
bool wantsChain = SystemCertificateValidator.NeedsChain (settings);
if (!wantsChain && hasCallback) {
wantsChain = true;
}
- if (wantsChain)
- chain = SystemCertificateValidator.CreateX509Chain (certs);
-
bool providerValidated = false;
if (provider != null && provider.HasCustomSystemCertificateValidator) {
var xerrors = (MonoSslPolicyErrors)errors;
var xchain = (XX509Chain)(object)chain;
- providerValidated = provider.InvokeSystemCertificateValidator (this, host, server, certs, ref xchain, out result, ref xerrors, ref status11);
+ providerValidated = provider.InvokeSystemCertificateValidator (this, host, server, certs, wantsChain, ref xchain, out result, ref xerrors, ref status11);
chain = (X509Chain)(object)xchain;
errors = (SslPolicyErrors)xerrors;
+ } else if (wantsChain) {
+ chain = SystemCertificateValidator.CreateX509Chain (certs);
}
if (!providerValidated)