Description
Hello everybody.
We faced a problem in our Client – Server (dotnet – dotnet) application connected with certificate validation. Client try to connect Server by SslStream with delivered .pfx certificate. Server checks client’s certificate and accepts or decline connection.
We use SslStream.AuthenticateAsServer() method with RemoteCertificateValidationCallback. If validation fails we return false and expect that client app will close the connection with proper error. But errors are different when Server app runs on Windows and Linux.
If server app runs on Windows Client gets error:
Exception (IOException) with HResult -2146232800 (0x80131620)
InnerException (Win32Exception) with HResult -2147467259 (0x80004005) and NativeErrorCode -2146893017 (0x80090327) which means „An unknown error occurred while processing the certificate” and this is OK.
If server app runs on Linux Client gets error:
Exception (IOException) with HResult -214623280 (0x80131620)
InnerException (SocketException) with HResult -2147467259 (0x80004005) and NativeErrorCode 10054 which means „An existing connection was forcibly closed by the remote host.” and this is not OK.
Client app runs on Windows in both cases.
After some investigations we found out that in our RemoteCertificateValidation() method, paramter X509Chain contains different ChainStatuses for Windows and Linux.
On Windows we have one chain status:
NotSignatureValid with description "The signature of the certificate cannot be verified."
On Linux we have two chain statuses:
PartialChain with description "unable to get local issuer certificate"
HasNotSupportedCriticalExtension with description "unhandled critical extension".
These ChainStatuses are used in .net method SecureChannel.CreateFatalHandshakeAlertToken() which generates alertMessage sent to the client in SslStream.SendAuthResetSignal(). AlertToken is generated on Windows and SentAuthResetSignal() executes line InnerStream.Write() and then throws an exception, but on Linux token is empty (message.Size == 0) and SendAuthResetSignal() only throws an exception (in if’s body).
Client platform:
Windows 10 Pro x64 21H2
.NET SDK 6.0.1 x64
Server platform:
Raspberry PI OS, kernel 5.10
.NET SDK 6.0.1 Arm32
OpenSsl 1.1.1k
Any ideas what can cause this difference?