Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Use unencoded hostname in user-facing properties/params
  • Loading branch information
rzikm committed Apr 21, 2023
commit a5c124bfa45e523d2f62deb89de0ea6e28bf23f7
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@ internal static string NormalizeHostName(string? targetHost)
// RFC 6066 section 3 says to exclude trailing dot from fully qualified DNS hostname
targetHost = targetHost.TrimEnd('.');

// RFC 6066 forbids IP literals
if (IsValidAddress(targetHost))
{
return string.Empty;
}

try
{
return s_idnMapping.GetAscii(targetHost);
Expand All @@ -46,8 +40,15 @@ internal static string NormalizeHostName(string? targetHost)

// Simplified version of IPAddressParser.Parse to avoid allocations and dependencies.
// It purposely ignores scopeId as we don't really use so we do not need to map it to actual interface id.
private static unsafe bool IsValidAddress(ReadOnlySpan<char> ipSpan)
internal static unsafe bool IsValidAddress(string? hostname)
{
if (string.IsNullOrEmpty(hostname))
{
return false;
}

ReadOnlySpan<char> ipSpan = hostname.AsSpan();

int end = ipSpan.Length;

if (ipSpan.Contains(':'))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ internal void UpdateOptions(SslClientAuthenticationOptions sslClientAuthenticati
IsServer = false;
RemoteCertRequired = true;
CertificateContext = sslClientAuthenticationOptions.ClientCertificateContext;
TargetHost = TargetHostNameHelper.NormalizeHostName(sslClientAuthenticationOptions.TargetHost);

// RFC 6066 forbids IP literals
TargetHost = TargetHostNameHelper.IsValidAddress(sslClientAuthenticationOptions.TargetHost)
? string.Empty
: sslClientAuthenticationOptions.TargetHost ?? string.Empty;

// Client specific options.
CertificateRevocationCheckMode = sslClientAuthenticationOptions.CertificateRevocationCheckMode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -844,10 +844,11 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan<byte> inputBuffer, ref byte
}
else
{
string hostName = TargetHostNameHelper.NormalizeHostName(_sslAuthenticationOptions.TargetHost);
status = SslStreamPal.InitializeSecurityContext(
ref _credentialsHandle!,
ref _securityContext,
_sslAuthenticationOptions.TargetHost,
hostName,
inputBuffer,
ref result,
_sslAuthenticationOptions);
Expand All @@ -863,7 +864,7 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan<byte> inputBuffer, ref byte
status = SslStreamPal.InitializeSecurityContext(
ref _credentialsHandle!,
ref _securityContext,
_sslAuthenticationOptions.TargetHost,
hostName,
ReadOnlySpan<byte>.Empty,
ref result,
_sslAuthenticationOptions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ await WithVirtualConnection(async (server, client) =>
await TaskTimeoutExtensions.WhenAllOrAnyFailed(new[] { clientJob, server.AuthenticateAsServerAsync(options, CancellationToken.None) });

Assert.Equal(1, timesCallbackCalled);
Assert.Equal(hostName, server.TargetHostName);
Assert.Equal(hostName, client.TargetHostName);
},
(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) =>
{
Expand Down Expand Up @@ -200,6 +202,7 @@ await TestConfiguration.WhenAllOrAnyFailedWithTimeout(
server.AuthenticateAsServerAsync(serverOptions, default));

Assert.Equal(string.Empty, server.TargetHostName);
Assert.Equal(string.Empty, client.TargetHostName);
}

[Theory]
Expand Down Expand Up @@ -320,10 +323,10 @@ private async Task WithVirtualConnection(Func<SslStream, SslStream, Task> server

public static IEnumerable<object[]> HostNameData()
{
yield return new object[] { "a" };
yield return new object[] { "test" };
// yield return new object[] { "a" };
// yield return new object[] { "test" };
// max allowed hostname length is 63
yield return new object[] { new string('a', 63) };
// yield return new object[] { new string('a', 63) };
yield return new object[] { "\u017C\u00F3\u0142\u0107 g\u0119\u015Bl\u0105 ja\u017A\u0144. \u7EA2\u70E7. \u7167\u308A\u713C\u304D" };
}
}
Expand Down