Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ public partial class SslStream : System.Net.Security.AuthenticatedStream
public override int ReadTimeout { get { throw null; } set { } }
public virtual System.Security.Cryptography.X509Certificates.X509Certificate? RemoteCertificate { get { throw null; } }
public virtual System.Security.Authentication.SslProtocols SslProtocol { get { throw null; } }
public string TargetHostName { get { throw null; } }
public System.Net.TransportContext TransportContext { get { throw null; } }
public override int WriteTimeout { get { throw null; } set { } }
public void AuthenticateAsClient(System.Net.Security.SslClientAuthenticationOptions sslClientAuthenticationOptions) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ internal SslAuthenticationOptions(SslClientAuthenticationOptions sslClientAuthen
EncryptionPolicy = sslClientAuthenticationOptions.EncryptionPolicy;
IsServer = false;
RemoteCertRequired = true;
TargetHost = sslClientAuthenticationOptions.TargetHost;
TargetHost = sslClientAuthenticationOptions.TargetHost!;

// Client specific options.
CertSelectionDelegate = localCallback;
Expand Down Expand Up @@ -68,7 +68,7 @@ private static SslProtocols FilterOutIncompatibleSslProtocols(SslProtocols proto
}

internal bool AllowRenegotiation { get; set; }
internal string? TargetHost { get; set; }
internal string TargetHost { get; set; }
internal X509CertificateCollection? ClientCertificates { get; set; }
internal List<SslApplicationProtocol>? ApplicationProtocols { get; }
internal bool IsServer { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,14 @@ public virtual int KeyExchangeStrength
}
}

public string TargetHostName
{
get
{
return _sslAuthenticationOptions != null ? _sslAuthenticationOptions.TargetHost : string.Empty;
}
}

//
// Stream contract implementation.
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,70 @@ public async Task SslStream_NestedAuth_Throws()
}
}

[Theory]
[InlineData(false)]
[InlineData(true)]
public async Task SslStreag_TargetHostName_Succeeds(bool useEmptyName)
{
string tagetName = useEmptyName ? string.Empty : Guid.NewGuid().ToString("N");

(Stream clientStream, Stream serverStream) = TestHelper.GetConnectedStreams();
using (clientStream)
using (serverStream)
using (var client = new SslStream(clientStream))
using (var server = new SslStream(serverStream))
using (X509Certificate2 certificate = Configuration.Certificates.GetServerCertificate())
{
SslClientAuthenticationOptions clientOptions = new SslClientAuthenticationOptions() { TargetHost = tagetName };
clientOptions.RemoteCertificateValidationCallback =
(sender, certificate, chain, sslPolicyErrors) =>
{
SslStream stream = (SslStream)sender;
if (useEmptyName)
{
Assert.Equal('?', stream.TargetHostName[0]);
}
else
{
Assert.Equal(tagetName, stream.TargetHostName);
}

return true;
};

SslServerAuthenticationOptions serverOptions = new SslServerAuthenticationOptions();
serverOptions.ServerCertificateSelectionCallback =
(sender, name) =>
{
SslStream stream = (SslStream)sender;
if (useEmptyName)
{
Assert.Equal('?', stream.TargetHostName[0]);
}
else
{
Assert.Equal(tagetName, stream.TargetHostName);
}

return certificate;
};

await TestConfiguration.WhenAllOrAnyFailedWithTimeout(
client.AuthenticateAsClientAsync(clientOptions),
server.AuthenticateAsServerAsync(serverOptions));
if (useEmptyName)
{
Assert.Equal('?', client.TargetHostName[0]);
Assert.Equal('?', server.TargetHostName[0]);
}
else
{
Assert.Equal(tagetName, client.TargetHostName);
Assert.Equal(tagetName, server.TargetHostName);
}
}
}

private static bool ValidateServerCertificate(
object sender,
X509Certificate retrievedServerPublicCertificate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ namespace System.Net.Security
{
public partial class SslStream
{
private class FakeOptions
{
public string TargetHost;
}

private FakeOptions? _sslAuthenticationOptions;

private void ValidateCreateContext(SslClientAuthenticationOptions sslClientAuthenticationOptions, RemoteCertValidationCallback remoteCallback, LocalCertSelectionCallback? localCallback)
{
// Without setting (or using) these members you will get a build exception in the unit test project.
Expand All @@ -35,6 +42,7 @@ private void ValidateParameters(byte[] buffer, int offset, int count)

private void ValidateCreateContext(SslAuthenticationOptions sslAuthenticationOptions)
{
_sslAuthenticationOptions = new FakeOptions() { TargetHost = sslAuthenticationOptions.TargetHost };
}

private ValueTask WriteAsyncInternal<TWriteAdapter>(TWriteAdapter writeAdapter, ReadOnlyMemory<byte> buffer)
Expand Down