ln.http/ln.http/TlsListener.cs

91 lines
3.4 KiB
C#

using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
namespace ln.http;
public class TlsListener : Listener
{
private CertificateStore _certificateStore;
public X509Certificate DefaultCertificate { get; set; }
public TlsListener(HttpRouter httpRouter, CertificateStore certificateStore)
:this(httpRouter, null, certificateStore){}
public TlsListener(HttpRouter httpRouter, IPAddress bind, int port, CertificateStore certificateStore)
:this(httpRouter, new IPEndPoint(bind, port), certificateStore){}
public TlsListener(HttpRouter httpRouter, IPEndPoint bind, CertificateStore certificateStore)
: this(httpRouter, bind, certificateStore, null)
{
}
public TlsListener(HttpRouter httpRouter, IPEndPoint bind, CertificateStore certificateStore, X509Certificate defaultCertificate) :base(httpRouter, bind)
{
_certificateStore = certificateStore;
DefaultCertificate = defaultCertificate;
if (DefaultCertificate is null)
{
if (_certificateStore.TryGetCertificate("localhost", out defaultCertificate))
DefaultCertificate = defaultCertificate;
}
}
protected override void Accepted(Socket connectedSocket, Stream connectionStream)
{
SslStream sslStream = new SslStream(connectionStream, false, null, CertificateSelectionCallback);
try
{
sslStream.AuthenticateAsServer(DefaultCertificate);
// ToDo: Check for correct ALPN protocol identifier
base.Accepted(connectedSocket, sslStream);
}
catch (Exception e)
{
}
finally
{
sslStream?.Dispose();
}
}
private X509Certificate CertificateSelectionCallback(object sender, string targethost,
X509CertificateCollection localcertificates, X509Certificate? remotecertificate, string[] acceptableissuers)
{
if (!_certificateStore.TryGetCertificate(targethost, out X509Certificate certificate))
return null;
return certificate;
}
private X509Certificate2 buildSelfSignedServerCertificate()
{
SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
sanBuilder.AddIpAddress(LocalEndpoint.Address);
sanBuilder.AddDnsName(Environment.MachineName);
X500DistinguishedName distinguishedName = new X500DistinguishedName($"CN={LocalEndpoint.Address.ToString()}");
using (RSA rsa = RSA.Create(4096))
{
var request = new CertificateRequest(distinguishedName, rsa, HashAlgorithmName.SHA256,RSASignaturePadding.Pkcs1);
request.CertificateExtensions.Add(
new X509KeyUsageExtension(X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature , false));
request.CertificateExtensions.Add(
new X509EnhancedKeyUsageExtension(
new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") }, false));
request.CertificateExtensions.Add(sanBuilder.Build());
var certificate= request.CreateSelfSigned(new DateTimeOffset(DateTime.UtcNow.AddDays(-1)), new DateTimeOffset(DateTime.UtcNow.AddDays(3650)));
return certificate;
}
}
}