This repository was archived by the owner on Mar 19, 2019. It is now read-only.

Description
When reading a client certificate from a HttpSysServer (WebListener) server the SSL channel is re-negotiated even if the sslcert registration is disabled. This not only results in an undesired behavior of user browser prompting for a certificate even though that is not desired, it also results two requests rather than one. This is VERY problematic for non-idempotent requests such as POST as you get a duplicate POST message.
Ultimately a call to retrieve the client cert ends up calling Request.GetClientCertificateAsync. This in turn calls ClientCertLoader which makes a call to HTTP.SYS API method HttpReceiveClientCertificate. Calling this method causes HTTP.SYS to renegotiate the SSL channel and request a client cert.
Desired behavior
-
If sslcert registration has clientcertnegotiation=disabled and the client has not provided a certificate in its initial SSL connection setup, a request to ITlsConnectionFeature.ClientCertificate should always return NULL and not trigger any re-negotiation of the channel. This would prevent a user from seeing a certificate popup in their browser.
-
If sslcert registration has clientcertnegotiation=disabled but the client explicitly provided a client certificate during the initial SSL connection setup, a request to ITlsConnectionFeature.ClientCertificate should return that certificate.
-
If sslcert registration has clientcertnegotiation=enabled, then a call to ITlsConnectionFeature.ClientCertificate should behave has the system does now and negotiate a certificate with the client.
Recommended Code Changes
One way to accomplish this would be to have Request.GetClientCertificateAsync evaluate first the pSslInfo.pClientCertInfo property of the HTTP_REQUEST structure returned by the call to HttpReceiveHttpRequest. If a certificate has already been provided with the channel, return that certificate. If a certificate is not already there, then check the HTTP.SYS sslcert binding to see if negotiation is enabled before calling ClientCertLoader.
Or provide an additional value when configuring the WebListener through the WebListenerOptions similar to Kestrel's HttpsConnectionFilterOptions.ClientCertificateMode property.