Elaine K
Elaine K

Reputation: 517

Client/Server SSL certificate ignored/forbidden with Require SSL set in IIS 7.5

I have created a website that I want to be able to access using a smart card so I have enabled SSL on the site. When I am logged in remotely to the server and access the site on the https port using the smart card everything works fine. I receive my prompt and the site loads. However, if I try to access the same site, using the same card from a client pc then I receive the 403 Forbidden error.

Settings on the server(IIS 7.5) I have implemented or verified: 

1) Site is bound to specific port (not 443) with a type of https and a certificate that has a friendly name. 
2) SSL settings: Require SSL is checked, Require client certificates is selected (note: if I set it to accept, the site will load for the client but it never prompts for credentials) 
3) I have verified that when Require client certificates is set to accept, that the certificate it recognizes in the browser is the correct one (e.g. myserver.com) but as I said then I don't receive the prompt for credentials
4) Anonymous Authentication is enabled, all others disabled
5) applicationhost.config file set the following in location -> system.webserver -> security: 
     a) sslFlags = "Ssl, SslNegotiateCert, SslRequireCert"
     b) under authentication set iisClientCertificateMappingAuthentication to true
6) I have confirmed the necessary certificates exist in the Trusted Root and Personal folders for the Local Computer account. 


Settings for the client: 

1) I have confirmed the necessary certificates exist and match what the server has in the Trusted Root and Personal folders for the Local Computer account.
2) I have checked that the certificate chain in the browser does not show any errors going down the chain in both IE and Chrome

I created a self-signed certificate and added it to all the certificate stores on the server and the client and received the same behavior.

Using OpenSSL I have achieved the following results:

openssl s_client -connect myserver.com -CAfile c:\certs\godaddy.pem  -servername myserver.com

Loading 'screen' into random state - done
CONNECTED(00000160) 
depth=2 C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", CN = Go D
addy Root Certificate Authority - G2
verify return:1
depth=1 C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", OU = http
://certs.godaddy.com/repository/, CN = Go Daddy Secure Certificate Authority - G
2
verify return:1
depth=0 OU = Domain Control Validated, CN = *.myserver.com
verify return:1
---
Certificate chain
 0 s:/OU=Domain Control Validated/CN=*.myserver.com
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.c
om/repository//CN=Go Daddy Secure Certificate Authority - G2
 1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.c
om/repository//CN=Go Daddy Secure Certificate Authority - G2
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./CN=Go Daddy Root Certific
ate Authority - G2
---
Server certificate
-----BEGIN CERTIFICATE-----
...29u1FZGXZnMUZCW5rlmZrkCAiBwDAB0/2t6BhyGh0JxydLWrRzJAZhW33KIem7IC...
-----END CERTIFICATE-----

subject=/OU=Domain Control Validated/CN=*.myserver.com
issuer=/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy
.com/repository//CN=Go Daddy Secure Certificate Authority - G2
---
No client certificate CA names sent
---
SSL handshake has read 2713 bytes and written 673 bytes
---
New, TLSv1/SSLv3, Cipher is AES128-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES128-SHA
    Session-ID: *** edited ***

    Session-ID-ctx:
    Master-Key: *** edited ***
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1439825381
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
read:errno=10054

The OpenSSL results has one section that says 'No client certificate CA names sent' and before I added the -CAfile option I was getting the Verify 20 error unable to get local issuer certificate.

UPDATE to OpenSSL results:

Figured out how to use the debug feature and from what I can see here, it seems to negotiate SSL correctly and with the correct certificate as long as I pass in the CAfile path.

openssl s_client -connect myserver.com:10168 -state -debug -CAfile c:\certs\godaddy.pem  -servername myserver

SSL_connect:SSLv2/v3 write client hello A
SSL_connect:SSLv3 read server hello A
depth=2 C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", CN = Go Daddy Root Certificate Authority - G2
verify return:1
depth=1 C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", OU = http://certs.godaddy.com/repository/, CN = Go Daddy Secure Certificate 

Authority - G2
verify return:1
depth=0 OU = Domain Control Validated, CN = *.myserver.com
verify return:1

SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server done A

SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write change cipher spec A

SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL_connect:SSLv3 read finished A
---
Certificate chain
 0 s:/OU=Domain Control Validated/CN=*.myserver.com
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.c
om/repository//CN=Go Daddy Secure Certificate Authority - G2
 1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.c
om/repository//CN=Go Daddy Secure Certificate Authority - G2
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./CN=Go Daddy Root Certific
ate Authority - G2
---
Server certificate
-----BEGIN CERTIFICATE-----

-----END CERTIFICATE-----

subject=/OU=Domain Control Validated/CN=*.myserver.com
issuer=/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy
.com/repository//CN=Go Daddy Secure Certificate Authority - G2
---
No client certificate CA names sent
---
SSL handshake has read 2713 bytes and written 643 bytes
---
New, TLSv1/SSLv3, Cipher is AES128-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES128-SHA
    Session-ID: ***

    Session-ID-ctx:
    Master-Key: ***
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1439919398
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
read from 0x2dd5b0 [0x2f06d3] (5 bytes => -1 (0xFFFFFFFF))
read:errno=10054
write to 0x2dd5b0 [0x2f4c23] (37 bytes => -1 (0xFFFFFFFF))

Additional openssl command:

openssl s_client -connect yourip:443 -prexit

...found on this SO site here did prove that in the list of acceptable certificates names was the Go Daddy Class 2 Certification Authority CA; however, I did not see *.myserver.com. Since *.myserver.com is chained to the Go Daddy Class 2 Certification Authority CA it seems that might be a normal process as indicated by this site here. On my local pc and the server the Go Daddy certificate exists in both the Trusted Root and Intermediate CA folders.

UPDATE - netsh:

I also tried the netsh http add sslcert certhash= appid= clientcertnegotiation=enable which executed sucessfully but did not result in any success.

UPDATE TO WIRESHARK INFO:

If I use Wireshark on my local pc to look at the traffic specifically to the server (display filter is set to search for ip.addr or ssl) I don't see any traffic at all generated by SSL. There's no Client or Server Hello or Certificate entry. I did verify in the first three SYN, SYN/ACK, and ACK packets that the IP addresses and ports were the correct values.

When I run Wireshark on the server I don't see any SSL traffic either specifically coming from my IP address. However, if I run Wireshark and my SSL website directly on the server, the site does resolve, works and prompts for credentials like it should but I discovered that the Certificate id-at-commonName equals a certificate different than I assigned to the site (*.myserver.com) which is *.vo.msecnd.net and belongs according to my research to the Baltimore CyberTrust Root certificate from Microsoft.

UPDATE - Repaired Certificate

Followed the instructions on this site to repair the certificate and rule out it being faulty. I don't have an Entrust cert but the instructions at the bottom work the same.

Why am I not seeing a Client Hello? How can I troubleshoot lack of SSL handshake?

Some SO sites that I have used to try and resolve the issue include:

OpenSSL errno 10054,connection refused

OpenSSL: unable to get local issuer certificate

IIS 7.5 site with SSL fails, site without SSL works

RESOLUTION:

It appears the combination of certificate repair and setting the clientcertnegotiation did the trick but only after I rebooted the server.

Upvotes: 2

Views: 2300

Answers (1)

Erik Oppedijk
Erik Oppedijk

Reputation: 3553

The correct steps are:

  1. Set IIS SSL bindings up correctly
  2. netsh http show sslcert and copy the values

  3. Remove server SSL certificate binding with netsh http delete sslcert

  4. Added server SSL certificate binding with netsh http add sslcert ipport=0.0.0.0:443 certhash=.... appid=.... sslctlstorename=ClientAuthIssuer clientcertnegotiation=enable

  5. Verified that settings were applied with netsh http show sslcert

  6. (Windows 2012 R2 only) Set HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\SendTrustedIssuerList to 1

Upvotes: 1

Related Questions