use empty server name is client did not specify one (#39671)
authorTomas Weinfurt <tweinfurt@yahoo.com>
Tue, 28 Jul 2020 19:14:04 +0000 (12:14 -0700)
committerGitHub <noreply@github.com>
Tue, 28 Jul 2020 19:14:04 +0000 (12:14 -0700)
* use empty server name

* fix merge

* feedback from review

* add missing file

src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Ssl.cs
src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs
src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs
src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs

index 4401dec..577ee81 100644 (file)
@@ -384,7 +384,7 @@ internal static partial class Interop
             // this code could be removed.
             //
             // It was verified as supporting case invariant match as of 10.12.1 (Sierra).
-            string matchName = s_idnMapping.GetAscii(hostName);
+            string matchName = string.IsNullOrEmpty(hostName) ? string.Empty : s_idnMapping.GetAscii(hostName);
 
             using (SafeCFDateHandle cfNotBefore = CoreFoundation.CFDateCreate(notBefore))
             using (SafeCreateHandle cfHostname = CoreFoundation.CFStringCreateWithCString(matchName))
index 35f2309..4a8695f 100644 (file)
@@ -189,7 +189,7 @@ internal static partial class Interop
                     if (!sslAuthenticationOptions.IsServer)
                     {
                         // The IdnMapping converts unicode input into the IDNA punycode sequence.
-                        string punyCode = s_idnMapping.GetAscii(sslAuthenticationOptions.TargetHost!);
+                        string punyCode = string.IsNullOrEmpty(sslAuthenticationOptions.TargetHost) ? string.Empty : s_idnMapping.GetAscii(sslAuthenticationOptions.TargetHost!);
 
                         // Similar to windows behavior, set SNI on openssl by default for client context, ignore errors.
                         if (!Ssl.SslSetTlsExtHostName(context, punyCode))
index afda3eb..5f3c5cd 100644 (file)
@@ -15,8 +15,6 @@ namespace System.Net.Security
 {
     public partial class SslStream
     {
-        private static int s_uniqueNameInteger = 123;
-
         private SslAuthenticationOptions? _sslAuthenticationOptions;
 
         private int _nestedAuth;
@@ -66,10 +64,6 @@ namespace System.Net.Security
             try
             {
                 _sslAuthenticationOptions = new SslAuthenticationOptions(sslClientAuthenticationOptions, remoteCallback, localCallback);
-                if (_sslAuthenticationOptions.TargetHost!.Length == 0)
-                {
-                    _sslAuthenticationOptions.TargetHost = "?" + Interlocked.Increment(ref s_uniqueNameInteger).ToString(NumberFormatInfo.InvariantInfo);
-                }
                 _context = new SecureChannel(_sslAuthenticationOptions, this);
             }
             catch (Win32Exception e)
@@ -420,12 +414,15 @@ namespace System.Net.Security
                     if (_lastFrame.HandshakeType == TlsHandshakeType.ClientHello)
                     {
                         // SNI if it exist. Even if we could not parse the hello, we can fall-back to default certificate.
-                        _sslAuthenticationOptions!.TargetHost = _lastFrame.TargetName;
+                        if (_lastFrame.TargetName != null)
+                        {
+                            _sslAuthenticationOptions!.TargetHost = _lastFrame.TargetName;
+                        }
 
                         if (_sslAuthenticationOptions.ServerOptionDelegate != null)
                         {
                             SslServerAuthenticationOptions userOptions =
-                                await _sslAuthenticationOptions.ServerOptionDelegate(this, new SslClientHelloInfo(_lastFrame.TargetName, _lastFrame.SupportedVersions),
+                                await _sslAuthenticationOptions.ServerOptionDelegate(this, new SslClientHelloInfo(_sslAuthenticationOptions.TargetHost, _lastFrame.SupportedVersions),
                                                                                     _sslAuthenticationOptions.UserState, adapter.CancellationToken).ConfigureAwait(false);
                             _sslAuthenticationOptions.UpdateOptions(userOptions);
                         }
index fffc62a..46345ba 100644 (file)
@@ -205,7 +205,7 @@ namespace System.Net.Security.Tests
         [InlineData(true)]
         public async Task SslStream_TargetHostName_Succeeds(bool useEmptyName)
         {
-            string tagetName = useEmptyName ? string.Empty : Guid.NewGuid().ToString("N");
+            string targetName = useEmptyName ? string.Empty : Guid.NewGuid().ToString("N");
 
             (Stream clientStream, Stream serverStream) = TestHelper.GetConnectedStreams();
             using (clientStream)
@@ -218,19 +218,12 @@ namespace System.Net.Security.Tests
                 Assert.Equal(string.Empty, client.TargetHostName);
                 Assert.Equal(string.Empty, server.TargetHostName);
 
-                SslClientAuthenticationOptions clientOptions = new SslClientAuthenticationOptions() { TargetHost = tagetName };
+                SslClientAuthenticationOptions clientOptions = new SslClientAuthenticationOptions() { TargetHost = targetName };
                 clientOptions.RemoteCertificateValidationCallback =
                     (sender, certificate, chain, sslPolicyErrors) =>
                     {
                         SslStream stream = (SslStream)sender;
-                        if (useEmptyName)
-                        {
-                            Assert.Equal('?', stream.TargetHostName[0]);
-                        }
-                        else
-                        {
-                            Assert.Equal(tagetName, stream.TargetHostName);
-                        }
+                        Assert.Equal(targetName, stream.TargetHostName);
 
                         return true;
                     };
@@ -240,14 +233,7 @@ namespace System.Net.Security.Tests
                     (sender, name) =>
                     {
                         SslStream stream = (SslStream)sender;
-                        if (useEmptyName)
-                        {
-                            Assert.Equal('?', stream.TargetHostName[0]);
-                        }
-                        else
-                        {
-                            Assert.Equal(tagetName, stream.TargetHostName);
-                        }
+                        Assert.Equal(targetName, stream.TargetHostName);
 
                         return certificate;
                     };
@@ -255,16 +241,8 @@ namespace System.Net.Security.Tests
                 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);
-                }
+                Assert.Equal(targetName, client.TargetHostName);
+                Assert.Equal(targetName, server.TargetHostName);
             }
         }