Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SslStream fails to authenticate in .NET 7.0 but works in .NET 6.0 #83455

Closed
lini opened this issue Mar 15, 2023 · 7 comments · Fixed by #83480
Closed

SslStream fails to authenticate in .NET 7.0 but works in .NET 6.0 #83455

lini opened this issue Mar 15, 2023 · 7 comments · Fixed by #83480
Assignees
Milestone

Comments

@lini
Copy link

lini commented Mar 15, 2023

Description

I have an app targeting .NET 6.0, which uses a SslStream to establish a TLS connection to a remote server and transfer data through it. After I updated the app to .NET 7.0, the AuthenticateAsClientAsync() call started to throw an exception in some cases:

Unhandled exception. System.AggregateException: One or more errors occurred. ( Received an unexpected EOF or 0 bytes from the transport stream.)
 ---> System.IO.IOException:  Received an unexpected EOF or 0 bytes from the transport stream.
   at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
   at System.Net.Security.SslStream.ReceiveBlobAsync[TIOAdapter](CancellationToken cancellationToken)
   at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)

Nothing else is changed in the app, except the TargetFramework value - with .NET 6.0 it works, with .NET 7.0 it fails.

I also tested the app on other OS and there were NO exceptions there (Windows 11 22H2, macOS Ventura, Ubuntu 22)

Reproduction Steps

Execute the following code from a console app targeting .NET 7.0 on Windows 10:

using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;


var targetHost = "lh3.googleusercontent.com";
var ip = Dns.Resolve(targetHost); // resolves to 142.250.186.129
Socket baseSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
baseSocket.Connect(new IPEndPoint(ip.AddressList[0], 443));
Stream strmNet = new NetworkStream(baseSocket, false);
var httpsStream = new SslStream(strmNet, false);
var appProtocols = new List<SslApplicationProtocol>() { SslApplicationProtocol.Http2, SslApplicationProtocol.Http11 };
var oAcceptedProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;
var opt = new SslClientAuthenticationOptions()
{
    TargetHost = targetHost,
    ClientCertificates = null,
    EnabledSslProtocols = oAcceptedProtocols,
    CertificateRevocationCheckMode = X509RevocationMode.NoCheck,
    ApplicationProtocols = appProtocols
};

var ct = new CancellationToken(false);
httpsStream.AuthenticateAsClientAsync(opt, ct).Wait();
Console.WriteLine("Stream is authenticated? " + httpsStream.IsAuthenticated.ToString());

Expected behavior

AuthenticateAsClientAsync should not throw an exception when trying to authenticate.

Actual behavior

The code throws an exception:

Unhandled exception. System.AggregateException: One or more errors occurred. ( Received an unexpected EOF or 0 bytes from the transport stream.)

Regression?

Yes, the code worked fine on .NET 6.0

Known Workarounds

No workaround at the moment :(

Configuration

Failing on:
OS version: Windows 10 x64 22H2
.NET version: 7.0.201

Works on
OS version: Windows 11 x64 22H2, macOS Ventura, Ubuntu 22.04
.NET version: 6.0.100 and 7.0.201

Other information

No response

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Mar 15, 2023
@ghost
Copy link

ghost commented Mar 15, 2023

Tagging subscribers to this area: @dotnet/ncl, @vcsjones
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

I have an app targeting .NET 6.0, which uses a SslStream to establish a TLS connection to a remote server and transfer data through it. After I updated the app to .NET 7.0, the AuthenticateAsClientAsync() call started to throw an exception in some cases:

Unhandled exception. System.AggregateException: One or more errors occurred. ( Received an unexpected EOF or 0 bytes from the transport stream.)
 ---> System.IO.IOException:  Received an unexpected EOF or 0 bytes from the transport stream.
   at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
   at System.Net.Security.SslStream.ReceiveBlobAsync[TIOAdapter](CancellationToken cancellationToken)
   at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)

Nothing else is changed in the app, except the TargetFramework value - with .NET 6.0 it works, with .NET 7.0 it fails.

I also tested the app on other OS and there were NO exceptions there (Windows 11 22H2, macOS Ventura, Ubuntu 22)

Reproduction Steps

Execute the following code from a console app targeting .NET 7.0 on Windows 10:

using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;


var targetHost = "lh3.googleusercontent.com";
var ip = Dns.Resolve(targetHost); // resolves to 142.250.186.129
Socket baseSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
baseSocket.Connect(new IPEndPoint(ip.AddressList[0], 443));
Stream strmNet = new NetworkStream(baseSocket, false);
var httpsStream = new SslStream(strmNet, false);
var appProtocols = new List<SslApplicationProtocol>() { SslApplicationProtocol.Http2, SslApplicationProtocol.Http11 };
var oAcceptedProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;
var opt = new SslClientAuthenticationOptions()
{
    TargetHost = targetHost,
    ClientCertificates = null,
    EnabledSslProtocols = oAcceptedProtocols,
    CertificateRevocationCheckMode = X509RevocationMode.NoCheck,
    ApplicationProtocols = appProtocols
};

var ct = new CancellationToken(false);
httpsStream.AuthenticateAsClientAsync(opt, ct).Wait();
Console.WriteLine("Stream is authenticated? " + httpsStream.IsAuthenticated.ToString());

Expected behavior

AuthenticateAsClientAsync should not throw an exception when trying to authenticate.

Actual behavior

The code throws an exception:

Unhandled exception. System.AggregateException: One or more errors occurred. ( Received an unexpected EOF or 0 bytes from the transport stream.)

Regression?

Yes, the code worked fine on .NET 6.0

Known Workarounds

No workaround at the moment :(

Configuration

Failing on:
OS version: Windows 10 x64 22H2
.NET version: 7.0.201

Works on
OS version: Windows 11 x64 22H2, macOS Ventura, Ubuntu 22.04
.NET version: 6.0.100 and 7.0.201

Other information

No response

Author: lini
Assignees: -
Labels:

area-System.Net.Security

Milestone: -

@rzikm
Copy link
Member

rzikm commented Mar 15, 2023

Regression -> we should investigate in 8.0

I can reproduce this on Win 11 as well.

@wfurt any ideas what may have caused this? I checked with wireshark and there is basically no difference in client-side packets. Also, it looks like it is the client side which is closing the connection.

@rzikm rzikm removed the untriaged New issue has not been triaged by the area owner label Mar 15, 2023
@rzikm rzikm added this to the 8.0.0 milestone Mar 15, 2023
@rzikm
Copy link
Member

rzikm commented Mar 15, 2023

I got it, it's regression from #64747.

image

What happens is that there is a tiny leftover at the very end of the SslStream._buffer, which prevents us from reading more data. I will put up a PR

@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Mar 15, 2023
@lini
Copy link
Author

lini commented Mar 16, 2023

Thanks for the investigation and confirmation of the issue!
I see that the fix milestone is set to 8.0 - will it be possible to backport it in a 7.0.x release as well so we can get and test it earlier?

@rzikm
Copy link
Member

rzikm commented Mar 16, 2023

I think it is reasonable to expect this to be backported to 7.0.x, as it is potentially breaking lots of users.

@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Mar 17, 2023
@rzikm
Copy link
Member

rzikm commented Mar 17, 2023

Reopening for backport to 7.0

@rzikm rzikm reopened this Mar 17, 2023
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Mar 17, 2023
@karelz karelz modified the milestones: 8.0.0, 7.0.x Mar 17, 2023
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Apr 3, 2023
@karelz
Copy link
Member

karelz commented May 27, 2023

Fixed in main (8.0) in PR #83480 and in 7.0.7 in PR #83574.

@karelz karelz closed this as completed May 27, 2023
@ghost ghost locked as resolved and limited conversation to collaborators Jun 26, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants