You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
SslStream client on Linux incorrectly reports that it is mutually authenticated #40314
When using SslStream.AuthenticateAsClient with a client certificate, IsMutuallyAuthenticated is set to true even if the server did not request a client certificate and the client didn't send one. It should be false, as the client has not authenticated itself to the server (which is the behaviour on Windows).
After the call to AuthenticateAsClient, stream.IsMutuallyAuthenticated is false on Windows but true on Linux.
Configuration
This affects Linux but not Windows (I'm not sure about Mac).
Platform details:
.NET Core 3.1.302
OpenSSL 1.1.1d
Debian 10
Other information
A Wireshark dump verifies that the server doesn't request a client certificate. I can provide the dump file if needed, but I won't make it public because of MAC addresses.
This is not a security vulnerability because it does not affect the authentication of the client to the server or the server to the client. It only makes the client think that it has authenticated itself to the server.
It seems like the code looks for availability of certificate for both sides. As you mentioned, that does not proof that sever actually asked for it. I don't know if OpenSSL has API to track that.
On Linux (and OSx as well), the StartMutualAuthAsAnonymous is false, so the LocalClientCertificate property gets always populated if client certificate was provided by the user. However, OpenSSL does not provide an easy way to check if the client certificate was actually requested by the server. The only way we could find out is to rewrite the code to always use cert callbacks (either using SSL_set_cert_cb or SSL_CTX_set_client_cert_cb) and note down if the callback was called during the handshake process.
#63200 already adds usage of SSL_set_cert_cb to support (.NET-side) certificate selection callback, so I suggest to revisit this issue once that PR is merged and try building on those changes.
Activity
wfurt commentedon Aug 4, 2020
It seems like the code looks for availability of certificate for both sides. As you mentioned, that does not proof that sever actually asked for it. I don't know if OpenSSL has API to track that.
Serg046 commentedon Aug 22, 2020
The flag is false on Windows because of the following line
https://github.com/dotnet/runtime/blob/master/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs#L592
_context.LocalClientCertificateis null if thatclientCertificateis null.Seems the line is not executed on Linux.
rzikm commentedon Jan 10, 2022
The
_context.LocalClientCertificatehappens to be null on Windows becauseSslStreamPal.StartMutualAuthAsAnonymousistrueon Windows, and the client certificate getsnulled at https://github.com/dotnet/runtime/blob/main/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs#L584 the first timeAcquireClientCredentialsis called. If server requests the client certificate, thenAcquireClientCredentialsis called again and full credentials are provided.On Linux (and OSx as well), the
StartMutualAuthAsAnonymousisfalse, so theLocalClientCertificateproperty gets always populated if client certificate was provided by the user. However, OpenSSL does not provide an easy way to check if the client certificate was actually requested by the server. The only way we could find out is to rewrite the code to always use cert callbacks (either usingSSL_set_cert_cborSSL_CTX_set_client_cert_cb) and note down if the callback was called during the handshake process.#63200 already adds usage of
SSL_set_cert_cbto support (.NET-side) certificate selection callback, so I suggest to revisit this issue once that PR is merged and try building on those changes.