Windows – How to use the ‘Client Authentication Issuers’ certificate store on Windows Server 2016

sslwindows

Problem:

We have a web site running on IIS, on Windows Server 2016 server (Server core).

Client certificate authentication is enabled for the website in IIS. When examining the TLS connection traffic to that site (using wireshark) we see a 'Client Request (13)' message that conveys the 'trusted issuers' list to the browser. That list currently contains all of the certificates in the 'Trusted Root Certification Authorities' store (with an certificate 'Intended Purpose' compatible with client auth).

We would like the list to contain only the single root certificate we choose (this happens to be the Origo Root certificate but I don't believe that is relevant to the problem).

To achieve this we have placed the Origo root certificate in the 'Client Authentication Issuers' store, as described in this article:

Overview of TLS – SSL (Schannel SSP)

That certificate is also present in the 'Trusted Root Certification Authorities' store, so that it is trusted on the local machine.

Note. we have also set this registry key (as described in the above article) to enable sending the 'trusted issuers list' to the browser:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel\SendTrustedIssuers = 1 (DWORD)

The server continues to send the full list of certificates from the 'Trusted Root Certification Authorities' store. The server has been rebooted.

I have confirmed that the origo certificate reports as 'trusted' by the server. There are no errors related to this certificate in the in the Windows CAPI2 event log, here:

Application and Services Logs\Microsoft\Windows\CAPI2

Windows version info reported by systeminfo.exe

OS Name:                   Microsoft Windows Server 2016 Standard
OS Version:                10.0.14393 N/A Build 14393

(all available Windows updates are installed)

Best Answer

We were able to get this working in the end. The steps, from the top are:

Create the following registry item:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel\SendTrustedIssuerList = 1 (DWORD)

This is a requirement as of Windows Server 2012, see Overview of TLS - SSL (Schannel SSP). Note that IIS will require a restart to pick up a change in this setting.

Without this setting, the 'trusted issuer providers' list will always be empty.

In addition to this, the netsh config for the site must be correct. E.g. here is the netsh command we currently run to configure https on our internal web servers (with IDs replaced):

netsh http update sslcert hostnameport=mainintegration.qa.focus-internal.co.uk:443 appid="{app-guid}" certhash={certificate-thumbprint} certstorename=WebHosting sslctlstorename=ClientAuthIssuer

The thumbprint refers to the server side ssl cert to use for https. On one occasion the ssl cert was renewed, and thus had a new thumbrint, but this command was not re-run with the new thumbprint. Rather, the IIS UI was used to select the new ssl cert, and this probably caused the additional bits of config in this command to be dropped. Specifically:

sslctlstorename=ClientAuthIssuer

The above link to doc 'Overview of TLS - SSL (Schannel SSP)' says that the ClientAuthIssuer store (appears as 'Client Authentication Issuers' in the certificate manager UI) is used by default, but we have found this not to be the case, and the store needs to be referred to explicitly, as above.

Also note that the 'netsh http update sslcert' command.

From Netsh http commands:

clientcertnegotiation Specifies whether the negotiation of certificate is enabled or disabled. Default is disabled.

We found that not only does client cert negotiation occur with this setting disabled, our web app actually requires it to be disabled. This is because our web app relies on performing https renegotiation (with client certificate at a specific URL within the app, and not the web site as a whole. This may not be typical, so just be aware that settign name is somewhat misleading.

From When do I need “Negotiate Client Certificate” to be set to Enabled?:

IIS has two ways to negotiate TLS:

  • Where the client sends the client certificate in the initial request. This is useful when all resources on the server require TLS client authentication.
  • Where the client doesn't send the client in the initial request, but later after IIS performs a TLS re-negotiation. This is useful when only some resources require TLS client authentication.

The Negotiate Client Certificate setting determines which is used, the first if enabled, and the second if disabled. Here is more from Microsoft's blog (The complete list of changes to make to activate Client Certificate Mapping on IIS using Active Directory):

If this setting is enabled, the client certificate will be sent by the client browser when the initial secure connection with the web-server is negotiated.

If it is disabled, an initial secure connection will be negotiated between the web-server and the browser based on the server certificate, and then the connection will be re-negotiated at the specific URL in our web app that requires (or requests, actually) a client certificate.

Hence, enabling this setting actually prevents the https renegotiation we are relying on, and disabling this does not actually prevent client certificate negotiation!

Note however, that as http2 use increases, this renegotiation approach may become problematic again, at which point we may just move to enable client cert negotiation for the site as a whole.

Miscellaneous Notes

netsh http show sslcert can be used to dump the current https config to check it is as expected. The settings shown are (I think) stored in the registry, here:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters\SslBindingInfo\

The use of Wireshark to inspect https negotiation requires that the browser is configured to dump ssl keys to disk, and Wireshark is configured to look for those keys and use them to decrypt traffic. Details for how to do this are here:

https://wiki.wireshark.org/TLS#TLS_Decryption

I used the [Key log file using per-session secrets (#Using_the_.28Pre.29-Master-Secret)] method, as it does not require access to the ssl cert private keys (which I did not have access to).