|
@@ -6,12 +6,12 @@ using System.Net;
|
|
|
using System.Net.Security;
|
|
|
using System.Net.Sockets;
|
|
|
using System.Runtime.ConstrainedExecution;
|
|
|
+using System.Security.Cryptography;
|
|
|
using System.Security.Cryptography.X509Certificates;
|
|
|
using System.Text;
|
|
|
using System.Threading;
|
|
|
using DnsClient;
|
|
|
|
|
|
-
|
|
|
|
|
|
|
|
|
#region __________ INIT __________
|
|
@@ -71,8 +71,8 @@ finally
|
|
|
|
|
|
async Task RealMain()
|
|
|
{
|
|
|
- const string url = "http://www.example.org/index.html";
|
|
|
- const string host = "www.example.org";
|
|
|
+ const string url = "http://example.com/index.html";
|
|
|
+ const string host = "example.com";
|
|
|
const string path = "/index.html";
|
|
|
|
|
|
const string dnsServerName = "reliable-dns-server-in-hosts";
|
|
@@ -98,19 +98,31 @@ async Task RealMain()
|
|
|
|
|
|
if (certificate is not X509Certificate2 cert2) return false;
|
|
|
|
|
|
-
|
|
|
- var certName = cert2.GetNameInfo(X509NameType.DnsName, false);
|
|
|
- if (certName.StartsWith("*."))
|
|
|
+
|
|
|
+ if (DateTime.Now < cert2.NotBefore || DateTime.Now > cert2.NotAfter) return false;
|
|
|
+
|
|
|
+
|
|
|
+ var names = GetAllSubjectAlternativeNames(cert2);
|
|
|
+ var flagNameMatched = false;
|
|
|
+ foreach (var certName in names)
|
|
|
{
|
|
|
- if (!host.EndsWith(certName[2..], StringComparison.OrdinalIgnoreCase)) return false;
|
|
|
- }
|
|
|
- else if (!certName.Equals(host, StringComparison.OrdinalIgnoreCase)) return false;
|
|
|
+ if (certName.StartsWith("*."))
|
|
|
+ {
|
|
|
+ if (!host.EndsWith(certName[2..], StringComparison.OrdinalIgnoreCase)) continue;
|
|
|
+ flagNameMatched = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
+ if (certName.Equals(host, StringComparison.OrdinalIgnoreCase))
|
|
|
+ {
|
|
|
+ flagNameMatched = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-
|
|
|
- if (DateTime.Now < cert2.NotBefore || DateTime.Now > cert2.NotAfter) return false;
|
|
|
+ if (flagNameMatched == false) return false;
|
|
|
|
|
|
-
|
|
|
+
|
|
|
if (chain == null) return false;
|
|
|
|
|
|
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
|
|
@@ -136,7 +148,6 @@ async Task RealMain()
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
-
|
|
|
}
|
|
|
};
|
|
|
|
|
@@ -148,15 +159,46 @@ async Task RealMain()
|
|
|
|
|
|
var reader = new StreamReader(ssl);
|
|
|
|
|
|
- var lines = new List<string>();
|
|
|
+ var lines = new List<string>();
|
|
|
do
|
|
|
{
|
|
|
var line = reader.ReadLine();
|
|
|
if (line == "") break;
|
|
|
lines.Add(line);
|
|
|
-
|
|
|
} while (true);
|
|
|
|
|
|
-
|
|
|
int bp = 0;
|
|
|
-}
|
|
|
+}
|
|
|
+
|
|
|
+IReadOnlyList<string> GetAllSubjectAlternativeNames(X509Certificate2 cert)
|
|
|
+{
|
|
|
+ var names = new HashSet<string>();
|
|
|
+
|
|
|
+ foreach (var extension in cert.Extensions)
|
|
|
+ {
|
|
|
+ if (extension is X509SubjectAlternativeNameExtension sanExtension)
|
|
|
+ {
|
|
|
+ foreach (var name in sanExtension.EnumerateDnsNames()) names.Add(name);
|
|
|
+ }
|
|
|
+ else if (extension.Oid?.Value == "2.5.29.17")
|
|
|
+ {
|
|
|
+ var asnData = new AsnEncodedData(extension.Oid, extension.RawData);
|
|
|
+ var sanString = asnData.Format(true);
|
|
|
+
|
|
|
+ var sanParts = sanString.Split(new[] { ", ", "DNS Name=", " " }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
+ foreach (var part in sanParts)
|
|
|
+ {
|
|
|
+ if (!string.IsNullOrEmpty(part) && !part.StartsWith("IPAddress") && !part.StartsWith("Uri"))
|
|
|
+ {
|
|
|
+ names.Add(part);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ var certName = cert.GetNameInfo(X509NameType.DnsName, false);
|
|
|
+ if (!string.IsNullOrEmpty(certName)) names.Add(certName);
|
|
|
+
|
|
|
+ return [.. names];
|
|
|
+}
|