// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#if NET45
using System;
using System.Collections.Generic;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
namespace Microsoft.AspNet.Security
{
///
/// Provides pinned certificate validation based on the certificate thumbprint.
///
public class CertificateThumbprintValidator : ICertificateValidator
{
private readonly HashSet _validCertificateThumbprints;
///
/// Initializes a new instance of the class.
///
/// A set of thumbprints which are valid for an HTTPS request.
public CertificateThumbprintValidator([NotNull] IEnumerable validThumbprints)
{
_validCertificateThumbprints = new HashSet(validThumbprints, StringComparer.OrdinalIgnoreCase);
if (_validCertificateThumbprints.Count == 0)
{
throw new ArgumentOutOfRangeException("validThumbprints");
}
}
///
/// Validates that the certificate thumbprints in the signing chain match at least one whitelisted thumbprint.
///
/// An object that contains state information for this validation.
/// The certificate used to authenticate the remote party.
/// The chain of certificate authorities associated with the remote certificate.
/// One or more errors associated with the remote certificate.
/// A Boolean value that determines whether the specified certificate is accepted for authentication.
public bool Validate(object sender, X509Certificate certificate, [NotNull] X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors != SslPolicyErrors.None)
{
return false;
}
if (chain.ChainElements.Count < 2)
{
// Self signed.
return false;
}
foreach (var chainElement in chain.ChainElements)
{
string thumbprintToCheck = chainElement.Certificate.Thumbprint;
if (thumbprintToCheck == null)
{
continue;
}
if (_validCertificateThumbprints.Contains(thumbprintToCheck))
{
return true;
}
}
return false;
}
}
}
#endif