Repository navigation
Expand file tree
/
Copy pathCertificateSubjectKeyIdentifierValidator.cs
More file actions
81 lines (70 loc) · 3.31 KB
/
Copy pathCertificateSubjectKeyIdentifierValidator.cs
File metadata and controls
81 lines (70 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#if DNX451
using System;
using System.Collections.Generic;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Authentication
{
/// <summary>
/// Provides pinned certificate validation based on the subject key identifier of the certificate.
/// </summary>
public class CertificateSubjectKeyIdentifierValidator : ICertificateValidator
{
private readonly HashSet<string> _validSubjectKeyIdentifiers;
/// <summary>
/// Initializes a new instance of the <see cref="CertificateSubjectKeyIdentifierValidator"/> class.
/// </summary>
/// <param name="validSubjectKeyIdentifiers">A set of subject key identifiers which are valid for an HTTPS request.</param>
public CertificateSubjectKeyIdentifierValidator([NotNull] IEnumerable<string> validSubjectKeyIdentifiers)
{
_validSubjectKeyIdentifiers = new HashSet<string>(validSubjectKeyIdentifiers, StringComparer.OrdinalIgnoreCase);
if (_validSubjectKeyIdentifiers.Count == 0)
{
throw new ArgumentOutOfRangeException(nameof(validSubjectKeyIdentifiers));
}
}
/// <summary>
/// Verifies the remote Secure Sockets Layer (SSL) certificate used for authentication.
/// </summary>
/// <param name="sender">An object that contains state information for this validation.</param>
/// <param name="certificate">The certificate used to authenticate the remote party.</param>
/// <param name="chain">The chain of certificate authorities associated with the remote certificate.</param>
/// <param name="sslPolicyErrors">One or more errors associated with the remote certificate.</param>
/// <returns>A Boolean value that determines whether the specified certificate is accepted for authentication.</returns>
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 subjectKeyIdentifier = GetSubjectKeyIdentifier(chainElement.Certificate);
if (string.IsNullOrWhiteSpace(subjectKeyIdentifier))
{
continue;
}
if (_validSubjectKeyIdentifiers.Contains(subjectKeyIdentifier))
{
return true;
}
}
return false;
}
private static string GetSubjectKeyIdentifier(X509Certificate2 certificate)
{
const string SubjectKeyIdentifierOid = "2.5.29.14";
var extension = certificate.Extensions[SubjectKeyIdentifierOid] as X509SubjectKeyIdentifierExtension;
return extension == null ? null : extension.SubjectKeyIdentifier;
}
}
}
#endif