Intro
I can not find a link on the Internet for this, yet I think some admins would appreciate a relatively simple test to know is this a web site which requires a client certificate to work? The errors generated in a browser may be very generic in these situations. I see many ways to offer help, from a recipe to a tool to some pointers. I’m not yet sure how I want to proceed!
why would a site require a client CERT? Most likely as a form of client authentication.
Pointers for the DIY crowd
Badssl.com plus access to a linux command line – such as using a Raspberry Pi I so often write about – will do it for you guys.
The Client Certificate section of badssl.com has most of what you need. The page is getting big, look for this:
So as a big timesaver badssl.com has created a client certificate for you which you can use to test with. Download it as follows.
Go to your linux prompt and do something like this:
$ wget https://badssl.com/certs/badssl.com‐client.pem
badssl.com has a web page you can test with which only shows success if you access it using a client certificate, https://client.badssl.com/
to see how this works, try to access it the usual way, without supplying a client CERT:
$ curl ‐i ‐k https://client.badssl.com/
HTTP/1.1 400 Bad Request Server: nginx/1.10.3 (Ubuntu) Date: Thu, 20 Jun 2019 17:53:38 GMT Content-Type: text/html Content-Length: 262 Connection: close <html> <head><title>400 No required SSL certificate was sent</title></head> <body bgcolor="white"> <center><h1>400 Bad Request</h1></center> <center>No required SSL certificate was sent</center> <hr><center>nginx/1.10.3 (Ubuntu)</center> </body> </html> |
Now try the same thing, this time using the client CERT you just downloaded:
$ curl ‐v ‐i ‐k ‐E ./badssl.com‐client.pem:badssl.com https://client.badssl.com/
* About to connect() to client.badssl.com port 443 (#0) * Trying 104.154.89.105... connected * Connected to client.badssl.com (104.154.89.105) port 443 (#0) * Initializing NSS with certpath: sql:/etc/pki/nssdb * warning: ignoring value of ssl.verifyhost * skipping SSL peer certificate verification * NSS: client certificate from file * subject: CN=BadSSL Client Certificate,O=BadSSL,L=San Francisco,ST=California,C=US * start date: Nov 16 05:36:33 2017 GMT * expire date: Nov 16 05:36:33 2019 GMT * common name: BadSSL Client Certificate * issuer: CN=BadSSL Client Root Certificate Authority,O=BadSSL,L=San Francisco,ST=California,C=US * SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 * Server certificate: * subject: CN=*.badssl.com,O=Lucas Garron,L=Walnut Creek,ST=California,C=US * start date: Mar 18 00:00:00 2017 GMT * expire date: Mar 25 12:00:00 2020 GMT * common name: *.badssl.com * issuer: CN=DigiCert SHA2 Secure Server CA,O=DigiCert Inc,C=US > GET / HTTP/1.1 > User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2 > Host: client.badssl.com > Accept: */* > < HTTP/1.1 200 OK HTTP/1.1 200 OK < Server: nginx/1.10.3 (Ubuntu) Server: nginx/1.10.3 (Ubuntu) < Date: Thu, 20 Jun 2019 17:59:08 GMT Date: Thu, 20 Jun 2019 17:59:08 GMT < Content-Type: text/html Content-Type: text/html < Content-Length: 662 Content-Length: 662 < Last-Modified: Wed, 12 Jun 2019 15:43:39 GMT Last-Modified: Wed, 12 Jun 2019 15:43:39 GMT < Connection: keep-alive Connection: keep-alive < ETag: "5d011dab-296" ETag: "5d011dab-296" < Cache-Control: no-store Cache-Control: no-store < Accept-Ranges: bytes Accept-Ranges: bytes < <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="shortcut icon" href="/icons/favicon-green.ico"/> <link rel="apple-touch-icon" href="/icons/icon-green.png"/> <title>client.badssl.com</title> <link rel="stylesheet" href="/style.css"> <style>body { background: green; }</style> </head> <body> <div id="content"> <h1 style="font-size: 12vw;"> client.<br>badssl.com </h1> </div> <div id="footer"> This site requires a <a href="https://en.wikipedia.org/wiki/Transport_Layer_Security#Client-authenticated_TLS_handshake">client-authenticated</a> TLS handshake. </div> </body> </html> * Connection #0 to host client.badssl.com left intact * Closing connection #0 |
No more 400 error status – that looks like success to me. Note that we had to provide the password for our client CERT, which they kindly provided as badssl.com
Here’s an example of a real site which requires client CERTs:
$ curl ‐v ‐i ‐k ‐E ./badssl.com‐client.pem:badssl.com https://jp.nissan.biz/
* About to connect() to jp.nissan.biz port 443 (#0) * Trying 150.63.252.1... connected * Connected to jp.nissan.biz (150.63.252.1) port 443 (#0) * Initializing NSS with certpath: sql:/etc/pki/nssdb * warning: ignoring value of ssl.verifyhost * skipping SSL peer certificate verification * NSS: client certificate from file * subject: CN=BadSSL Client Certificate,O=BadSSL,L=San Francisco,ST=California,C=US * start date: Nov 16 05:36:33 2017 GMT * expire date: Nov 16 05:36:33 2019 GMT * common name: BadSSL Client Certificate * issuer: CN=BadSSL Client Root Certificate Authority,O=BadSSL,L=San Francisco,ST=California,C=US * NSS error -12227 * Closing connection #0 * SSL connect error curl: (35) SSL connect error |
OK, so you get an error, but that’s to be expected because our certificate is not one it will accept.
The point is that if you don’t send it a certificate at all, you get a different error:
$ curl ‐v ‐i ‐k https://jp.nissan.biz/
* About to connect() to jp.nissan.biz port 443 (#0) * Trying 150.63.252.1... connected * Connected to jp.nissan.biz (150.63.252.1) port 443 (#0) * Initializing NSS with certpath: sql:/etc/pki/nssdb * warning: ignoring value of ssl.verifyhost * skipping SSL peer certificate verification * NSS: client certificate not found (nickname not specified) * NSS error -12227 * Closing connection #0 curl: (35) NSS: client certificate not found (nickname not specified) |
See that client certificate not found? That is the error we eliminated by supplying a client certificate, albeit one which it will not accept.
what if we have a client certificate but we use the wrong password? Here’s an example of that:
$ curl ‐v ‐i ‐k ‐E ./badssl.com‐client.pem:badpassword https://client.badssl.com/
* About to connect() to client.badssl.com port 443 (#0) * Trying 104.154.89.105... connected * Connected to client.badssl.com (104.154.89.105) port 443 (#0) * Initializing NSS with certpath: sql:/etc/pki/nssdb * warning: ignoring value of ssl.verifyhost * Unable to load client key -8025. * NSS error -8025 * Closing connection #0 curl: (58) Unable to load client key -8025. |
Chrome gives a fairly intelligible error
Possibly to be continued…
Conclusion
We have given a recipe for testing form a linux command line if a web site requires a client certificate or not. thus it could be turned into a program
References and related
My article about ciphers has been popular.
I’ve also used badssl.com for other related tests.
Can you use openssl directly? You’d hope so, but I haven’t had time to explore it… Here are my all-time favorite openssl commands.
https://badssl.com/ – lots of cool tests here. The creators have been really thorough.