Skip to content

Commit

Permalink
add BindingEndPoint
Browse files Browse the repository at this point in the history
  • Loading branch information
segor committed Feb 16, 2024
1 parent f45cdd0 commit a0e1b92
Show file tree
Hide file tree
Showing 12 changed files with 186 additions and 57 deletions.
2 changes: 1 addition & 1 deletion src/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ csharp_using_directive_placement = outside_namespace:suggestion
csharp_prefer_braces = true:silent
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = false:none
csharp_prefer_static_local_function = true:suggestion
csharp_prefer_static_local_function = false:suggestion
csharp_prefer_simple_using_statement = false:none
csharp_style_prefer_switch_expression = true:suggestion

Expand Down
18 changes: 9 additions & 9 deletions src/SslCertBinding.Net.Sample/Program.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net;
using System.Security.Cryptography.X509Certificates;

namespace SslCertBinding.Net.Sample
{
#if NET5_0_OR_GREATER
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
#endif
static class Program
{
Expand Down Expand Up @@ -38,7 +37,7 @@ private static void Show(string[] args, CertificateBindingConfiguration configur
{
Console.WriteLine("SSL Certificate bindings:\r\n-------------------------\r\n");
var stores = new Dictionary<string, X509Store>();
IPEndPoint ipEndPoint = args.Length > 1 ? ParseIpEndPoint(args[1]) : null;
BindingEndPoint ipEndPoint = args.Length > 1 ? ParseEndPoint(args[1]) : null;
IReadOnlyList<CertificateBinding> certificateBindings = configuration.Query(ipEndPoint);
foreach (CertificateBinding info in certificateBindings)
{
Expand Down Expand Up @@ -67,7 +66,7 @@ private static void Show(string[] args, CertificateBindingConfiguration configur
DS Mapper Usage : {13}
Negotiate Client Certificate: {14}
",
info.Thumbprint, info.StoreName, info.IpPort, info.AppId, certificate.Subject, certificate.Issuer,
info.Thumbprint, info.StoreName, info.EndPoint, info.AppId, certificate.Subject, certificate.Issuer,
!info.Options.DoNotVerifyCertificateRevocation, info.Options.VerifyRevocationWithCachedCertificateOnly, !info.Options.NoUsageCheck,
info.Options.RevocationFreshnessTime + (info.Options.EnableRevocationFreshnessTime ? string.Empty : " (disabled)"),
info.Options.RevocationUrlRetrievalTimeout, info.Options.SslCtlIdentifier, info.Options.SslCtlStoreName,
Expand All @@ -78,22 +77,23 @@ private static void Show(string[] args, CertificateBindingConfiguration configur

private static void Bind(string[] args, CertificateBindingConfiguration configuration)
{
IPEndPoint endPoint = ParseIpEndPoint(args[3]);
BindingEndPoint endPoint = ParseEndPoint(args[3]);
configuration.Bind(new CertificateBinding(args[1], args[2], endPoint, Guid.Parse(args[4])));
Console.WriteLine("The binding record has been successfully applied.");
}

private static void Delete(string[] args, CertificateBindingConfiguration configuration)
{
IPEndPoint endPoint = ParseIpEndPoint(args[1]);
BindingEndPoint endPoint = ParseEndPoint(args[1]);
configuration.Delete(endPoint);
Console.WriteLine("The binding record has been successfully removed.");
}

private static IPEndPoint ParseIpEndPoint(string str)
private static BindingEndPoint ParseEndPoint(string str)
{
string[] ipPort = str.Split(':');
return new IPEndPoint(IPAddress.Parse(ipPort[0]), int.Parse(ipPort[1], CultureInfo.InvariantCulture));
return BindingEndPoint.TryParse(str, out BindingEndPoint endpoint)
? endpoint
: throw new FormatException();
}
}
}
12 changes: 7 additions & 5 deletions src/SslCertBinding.Net.Tests/CertConfigCmd.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace SslCertBinding.Net.Tests
{
public class CertConfigCmd
internal class CertConfigCmd
{
public class CommandResult
{
Expand All @@ -22,7 +22,8 @@ public class CommandResult
public class Options
{
#pragma warning disable CA1051 // Do not declare visible instance fields
public IPEndPoint ipport;
#pragma warning disable CS0649 // Field 'CertConfigCmd.Options.verifyclientcertrevocation' is never assigned to, and will always have its default value
public DnsEndPoint ipport;
public string certhash;
public Guid appid;
public string certstorename;
Expand All @@ -35,23 +36,24 @@ public class Options
public string sslctlstorename;
public bool? dsmapperusage;
public bool? clientcertnegotiation;
#pragma warning restore CS0649 // Field 'CertConfigCmd.Options.verifyclientcertrevocation' is never assigned to, and will always have its default value
#pragma warning restore CA1051 // Do not declare visible instance fields
}

public static Task<CommandResult> Show(IPEndPoint ipPort = null, bool throwExcepton = false)
public static Task<CommandResult> Show(BindingEndPoint ipPort = null, bool throwExcepton = false)
{
return ExecCommand(string.Format(CultureInfo.InvariantCulture, "http show sslcert {0}", ipPort), throwExcepton);
}

public static async Task<bool> IpPortIsPresentInConfig(IPEndPoint ipPort)
public static async Task<bool> IpPortIsPresentInConfig(BindingEndPoint ipPort)
{
CommandResult result = await Show(ipPort);
return result.IsSuccessfull;
}

public static Task<CommandResult> Add(Options options)
{
_ = options ?? throw new ArgumentNullException(nameof(options));
options = options ?? throw new ArgumentNullException(nameof(options));

var sb = new StringBuilder();
foreach (FieldInfo optionField in options.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public void QueryOnLinuxIsNotSupported()
public void DeleteOnLinuxIsNotSupported()
{
var config = new CertificateBindingConfiguration();
var endPoint = new IPEndPoint(1, 1);
var endPoint = new IPEndPoint(1, 1).ToDnsEndPoint();
PlatformNotSupportedException ex = Assert.Throws<PlatformNotSupportedException>(() => config.Delete(endPoint));
Assert.That(ex, Has.InnerException.TypeOf<DllNotFoundException>());
}
Expand All @@ -31,7 +31,8 @@ public void DeleteOnLinuxIsNotSupported()
public void BindOnLinuxIsNotSupported()
{
var config = new CertificateBindingConfiguration();
var binding = new CertificateBinding("98BC1AACBC38F564B95E1499FA2BA0FC30899A3E", "MY", new IPEndPoint(1, 1), Guid.Empty);
BindingEndPoint iPEndPoint = new IPEndPoint(1, 1).ToBindingEndPoint();
var binding = new CertificateBinding("98BC1AACBC38F564B95E1499FA2BA0FC30899A3E", "MY", iPEndPoint, Guid.Empty);
PlatformNotSupportedException ex = Assert.Throws<PlatformNotSupportedException>(() => config.Bind(binding));
Assert.That(ex, Has.InnerException.TypeOf<DllNotFoundException>());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class CertificateBindingConfigurationTests
[TestCase("::")]
public async Task QueryOne(string ip)
{
IPEndPoint ipPort = await GetEndpointWithFreeRandomPort(ip);
BindingEndPoint ipPort = await GetIpEndpointWithFreeRandomPort(ip);
var appId = Guid.NewGuid();

await CertConfigCmd.Add(new CertConfigCmd.Options
Expand All @@ -41,7 +41,7 @@ public async Task QueryOne(string ip)
Assert.Multiple(() =>
{
Assert.That(binding.AppId, Is.EqualTo(appId));
Assert.That(binding.IpPort, Is.EqualTo(ipPort));
Assert.That(binding.EndPoint, Is.EqualTo(ipPort));
Assert.That(binding.StoreName, Is.EqualTo("MY"));
Assert.That(binding.Thumbprint, Is.EqualTo(s_testingCertThumbprint));
Assert.That(binding.Options.DoNotPassRequestsToRawFilters, Is.EqualTo(false));
Expand All @@ -61,7 +61,7 @@ public async Task QueryOne(string ip)
[Test]
public void QueryNone()
{
var notFoundIpPort = new IPEndPoint(0, IPEndPoint.MaxPort);
BindingEndPoint notFoundIpPort = new IPEndPoint(0, IPEndPoint.MaxPort).ToBindingEndPoint();
var config = new CertificateBindingConfiguration();
IReadOnlyList<CertificateBinding> bindingsByIpPort = config.Query(notFoundIpPort);
Assert.That(bindingsByIpPort, Is.Empty);
Expand All @@ -70,7 +70,7 @@ public void QueryNone()
[Test]
public async Task QueryAll()
{
IPEndPoint ipPort1 = await GetEndpointWithFreeRandomPort();
BindingEndPoint ipPort1 = await GetIpEndpointWithFreeRandomPort();
var appId1 = Guid.NewGuid();
await CertConfigCmd.Add(new CertConfigCmd.Options
{
Expand All @@ -80,7 +80,7 @@ public async Task QueryAll()
certstorename = StoreName.My.ToString(),
});

IPEndPoint ipPort2 = await GetEndpointWithFreeRandomPort();
BindingEndPoint ipPort2 = await GetIpEndpointWithFreeRandomPort();
var appId2 = Guid.NewGuid();
await CertConfigCmd.Add(new CertConfigCmd.Options
{
Expand All @@ -97,13 +97,13 @@ public async Task QueryAll()

var config = new CertificateBindingConfiguration();
IReadOnlyList<CertificateBinding> allBindings = config.Query();
List<CertificateBinding> addedBindings = allBindings.Where(b => b.IpPort.Equals(ipPort1) || b.IpPort.Equals(ipPort2)).ToList();
List<CertificateBinding> addedBindings = allBindings.Where(b => b.EndPoint.Equals(ipPort1) || b.EndPoint.Equals(ipPort2)).ToList();
Assert.That(addedBindings, Has.Count.EqualTo(2));
CertificateBinding binding1 = addedBindings[0];
Assert.Multiple(() =>
{
Assert.That(binding1.AppId, Is.EqualTo(appId1));
Assert.That(binding1.IpPort, Is.EqualTo(ipPort1));
Assert.That(binding1.EndPoint, Is.EqualTo(ipPort1));
Assert.That(binding1.StoreName, Is.EqualTo(StoreName.My.ToString()));
Assert.That(binding1.Thumbprint, Is.EqualTo(s_testingCertThumbprint));
Assert.That(binding1.Options.DoNotPassRequestsToRawFilters, Is.EqualTo(false));
Expand All @@ -123,7 +123,7 @@ public async Task QueryAll()
Assert.Multiple(() =>
{
Assert.That(binding2.AppId, Is.EqualTo(appId2));
Assert.That(binding2.IpPort, Is.EqualTo(ipPort2));
Assert.That(binding2.EndPoint, Is.EqualTo(ipPort2));
Assert.That(binding2.StoreName, Is.EqualTo(StoreName.AuthRoot.ToString()));
Assert.That(binding2.Thumbprint, Is.EqualTo(s_testingCertThumbprint));
Assert.That(binding2.Options.DoNotPassRequestsToRawFilters, Is.EqualTo(false));
Expand All @@ -143,7 +143,7 @@ public async Task QueryAll()
[Test]
public async Task AddWithDefaultOptions()
{
IPEndPoint ipPort = await GetEndpointWithFreeRandomPort();
BindingEndPoint ipPort = await GetIpEndpointWithFreeRandomPort();
var appId = Guid.NewGuid();

var configuration = new CertificateBindingConfiguration();
Expand Down Expand Up @@ -173,7 +173,7 @@ public async Task AddWithDefaultOptions()
[Test]
public async Task AddWithNonDefaultOptions()
{
IPEndPoint ipPort = await GetEndpointWithFreeRandomPort();
BindingEndPoint ipPort = await GetIpEndpointWithFreeRandomPort();
var appId = Guid.NewGuid();

var configuration = new CertificateBindingConfiguration();
Expand Down Expand Up @@ -220,7 +220,7 @@ public void DeleteNullCollectionArgument()
void delete()
{
var config = new CertificateBindingConfiguration();
config.Delete((IReadOnlyCollection<IPEndPoint>)null);
config.Delete((IReadOnlyCollection<DnsEndPoint>)null);
}

ArgumentNullException ex = Assert.Throws<ArgumentNullException>(delete);
Expand All @@ -235,13 +235,13 @@ void delete()
public void DeleteEmptyCollectionArgument()
{
var config = new CertificateBindingConfiguration();
config.Delete(Array.Empty<IPEndPoint>());
config.Delete(Array.Empty<BindingEndPoint>());
}

[Test]
public async Task DeleteOne()
{
IPEndPoint ipPort = await GetEndpointWithFreeRandomPort();
BindingEndPoint ipPort = await GetIpEndpointWithFreeRandomPort();
var appId = Guid.NewGuid();

await CertConfigCmd.Add(new CertConfigCmd.Options
Expand All @@ -260,7 +260,7 @@ public async Task DeleteOne()
[Test]
public async Task DeleteMany()
{
IPEndPoint ipPort1 = await GetEndpointWithFreeRandomPort();
BindingEndPoint ipPort1 = await GetIpEndpointWithFreeRandomPort();

var appId1 = Guid.NewGuid();
await CertConfigCmd.Add(new CertConfigCmd.Options
Expand All @@ -270,7 +270,7 @@ public async Task DeleteMany()
appid = appId1,
});

IPEndPoint ipPort2 = await GetEndpointWithFreeRandomPort();
BindingEndPoint ipPort2 = await GetIpEndpointWithFreeRandomPort();

var appId2 = Guid.NewGuid();
await CertConfigCmd.Add(new CertConfigCmd.Options
Expand All @@ -292,7 +292,7 @@ public async Task DeleteMany()
[Test]
public async Task UpdateAsync()
{
IPEndPoint ipPort = await GetEndpointWithFreeRandomPort();
BindingEndPoint ipPort = await GetIpEndpointWithFreeRandomPort();
var appId = Guid.NewGuid();

await CertConfigCmd.Add(new CertConfigCmd.Options
Expand Down Expand Up @@ -387,15 +387,15 @@ private static void DoInLocalMachineCertStores(Action<X509Store> action)
}
}

private static async Task<IPEndPoint> GetEndpointWithFreeRandomPort(string ip = "0.0.0.0")
private static async Task<BindingEndPoint> GetIpEndpointWithFreeRandomPort(string ip = "0.0.0.0")
{
for (int port = 50000; port < 65535; port++)
{
var ipPort = new IPEndPoint(IPAddress.Parse(ip), port);
if (IpEndpointTools.IpEndpointIsAvailableForListening(ipPort))
{
if (!(await CertConfigCmd.IpPortIsPresentInConfig(ipPort)))
return ipPort;
if (!(await CertConfigCmd.IpPortIsPresentInConfig(ipPort.ToBindingEndPoint())))
return ipPort.ToBindingEndPoint();
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/SslCertBinding.Net.Tests/CertificateBindingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class CertificateBindingTests
[Test]
public void ConstructorWithEmptyCertificateThumbprintShouldFailTest()
{
void constructor() => _ = new CertificateBinding(string.Empty, "MY", new IPEndPoint(0, 0), Guid.Empty);
void constructor() => _ = new CertificateBinding(string.Empty, "MY", new IPEndPoint(0, 0).ToBindingEndPoint(), Guid.Empty);

ArgumentException ex = Assert.Throws<ArgumentException>(constructor);
Assert.Multiple(() =>
Expand Down
5 changes: 4 additions & 1 deletion src/SslCertBinding.Net.Tests/IpEndpointTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;

namespace SslCertBinding.Net.Tests
{
public static class IpEndpointTools
internal static class IpEndpointTools
{
public static bool IpEndpointIsAvailableForListening(IPEndPoint ipPort)
{
Expand All @@ -22,4 +23,6 @@ public static IPEndPoint ParseIpEndPoint(string str)
return new IPEndPoint(IPAddress.Parse(ip), int.Parse(port, CultureInfo.InvariantCulture));
}
}


}
Loading

0 comments on commit a0e1b92

Please sign in to comment.