WCF: Using Secure Message with Certificate Revokation List checking - wcf

I have an enterprise issued certificate that I want to use to secure a WCF message channel. The certutil program tells me that both the CRL and delta CRL are valid (status = "Verified"). I'm using the sample WCF programs from (https://www.microsoft.com/en-us/download/details.aspx?id=21459); specifically the MessageSecurity.sln test. When I replace the self-signed certificate with the Enterprise CA-generated certificate, I get the error:
The X.509 certificate CN=localhost chain building failed. The certificate that was used has a trust chain that cannot be verified. Replace the certificate or change the certificateValidationMode. The revocation function was unable to check revocation because the revocation server was offline.
Has anyone got message based channels working with anything other than self-signed certificates (i.e. with a valid CRL distribution point)? Any ideas what to try next?

Fun fact! The client maintains a cache of CRLs. After properly configuring the CRL distribution point, the cache with the erroneous CRL locations prevented the WCF sample from running. When it magically started working two days later, I did some digging and found out that the lists are cached. You can clear the lists manually with:
certutil -urlcache crl delete
After using this command I was able to predictably and reliably use my Enterprise CA generated cert to establish Message and TransportWithMessageCredentials channels.

Related

Refresing expired certificates on k8s

I ran into issue with expired certificates on k8s cluster. I am running version 1.6.1 for over a year now, meaning that my certificates expired and I have to renew them.
In newer versions this is already done automatically, but I currently can not upgrade my cluster to higher version, so I have to create certificates manually.
I came across following link, where it is described step-by-step, but I am actually already stuck on creating openssl.cnf file, as I am missing parameters. At the same time, this option is using .pem key, while on cluster currently .crt and .key pairs are used.
Any suggestion how to move forward with this? I have also tried running kubeadm alpha phase certs selfsign command, which created new certificates, yet I am still running into issue that api-server is refusing TSL handshake.
http: TLS handshake error from IP:port: remote error: tls: bad certificate
Thank you and best regards,
Bostjan
There is a detailed guide on how to generate certificates.
While you are following that guide look out for a few gotchas:
Make sure your CA certificate is valid for the period you are trying to extend the other certificates to. The validity of any certificates signed by the CA certificate are also limited by the expiration date of the CA certificate.
If the validity period of the CA certificate itself is too short you are in a pickle. Replacing that certificate will require modifying all kubeconfigs (operators, cluster components).
For the same reason as above, make very sure you don't overwrite the CA key/certificate accidentaly.
When replacing the certificate for the apiserver you will need to restart the apiserver. The apiserver does not reread the certificate automatically.

Where are the Certificate Revocation List (CRL) stores?

As far as I know and as it is mentioned here there are two main technologies for browsers to check the revocation status of a particular certificate: using the Online Certificate Status Protocol (OCSP) or looking up the certificate in a Certificate Revocation List (CRL).
Well, I know that there is some online OCSP servers or the OCSP method and the browser send a request there to check if the incoming certificate is revoked, but I don't have any idea about the CRL.
Where is the CRL? Is it a file in my system that updated after OCSP requests or it is a list in the web server that I'm trying to connect to?
Who updates it?
How do OCSP server check revocation? (I mean how does it update its database of revoked certificates?)
Note that I know I can see a cache of CRL using certutil -urlcache crl in command line. But it is a cache of it! Where is the real file?
Where is CRL? Is it a file in my system that updated after OCSP requests or it is a list in the web server that I'm trying to connect to?
CRL is a list provided by the certificate issuer. The list contains the serial numbers and the reason for revocation of the revoked certificates and is signed by the issuer (or some other directly or indirectly trusted CA). The original CRL file is created and stored at the issuer. It gets provided usually via http/https but other mechanism exists. To know which URL provides the CRL for a specific certificate look at the 'CRL Distribution Points' property of the certificate. Note that lots of certificates issued by the same CA share the same CRL distribution point.
Where the local copy of the CRL is on your system, in which format it is stored there etc depends on the OS, browser, libraries... I doubt that it will be updated based on OCSP responses because OCSP and CRL are independent mechanism to check for revocation and a client usually only uses one of these to check for revocation of specific certificates. But it might use OCSP in some cases and CRL in other cases (where no OCSP is provided).
Who it updates?
It depends. Browsers usually don't use CRL's anymore but moved to OCSP, skip revocation checks completely or moved to some other mechanism like CRLSets. If any other application use CRL for the certificates - it probably depends on the application.
How OCSP server check revocation? (I mean how it update its database of revoked certificates?)
It does not check for revocation. Either the OCSP server is provided by the certificate issuer itself which already has the list of revoked certificates (since the issuer revoked these itself) or in case of OCSP stapling the web server gets the (signed) OCSP response from the issuer and includes it unchanged inside the TLS handshake.
In theory one could build some OCSP proxy which provides OCSP responses based on existing CRL files but since the OCSP responses are signed too this proxy must have a certificate which is explicitly trusted for signing OCSP responses.

Using self-signed SSL certificate works, but CA signed certificate results in handshake alert failure 40 in response to client hello

So far, I've used openssl, sslyze, keystore utilities, and some of the standard Windows diagnostics commands to try and characterize this problem. The summary is that as soon as I attempt to use a keystore that has the CA signed certificate in it, I get an immediate handshake failure 40 after the client hello. The connection never gets as far as a server hello with the CA cert in place.
On the same machine (Windows Server 2012), if I use a self signed certificate, the connection works as expected.
Openssl shows the handshake failure with the CA certificate in place.
sslyze shows all ciphers rejected with either no ciphers available or TLS / Alert handshake failure.
The fact that this is successful with a self-signed certificate tends to indicate that the "basics" are there, that the client and server have the necessary ciphers and so on to connect, and that server.xml is configured properly.
There were no error messages when importing the certificates, and everything seems to be configured correctly with the CA certs based on keytool checks. There are no error messages given during server start to indicate any problems processing the certificate.
Is there something I should be looking more closely at in regards to the keystore with the CA cert that could cause this complete rejection of the client hello? How would a different keystore or CA certs within aaffect the earliest steps of the handshake?
Thank you for information provided.
I assume that you are talking about a server side certificate and a server side key store, since the error happens at a state where no client certificates are yet involved. If the server is able to send the self-signed certificate to the client, but is not able to send the CA signed certificate to the client, then it must be something wrong with the certificate you are trying to send or that the certificate can not be used together with the ciphers offered by the client.
Since the problem is obviously on the server side you should first check all logs written on the server side for hints what the error might be. Typical problems are non-existing files, wrong files, password protected client key w/o providing a password or that the key does not belong to the certificate.

Browser doesn't apply client certificate: 403.7

I'm trying to set up client certificate authentication. I was able to generate a CA-, server- and client-certificate. As long as I use Fiddler everything works as expected. However, as soon as I start using a browser it doesn't work anymore (HTTP Error 403.7 - Forbidden).
Of course I imported the client certificate in the Personal store and I made sure Client Certificate Negotiation is enabled.
I also tried openssl s_client -connect 127.0.0.1:443 -state -debug but I couldn't really make sense of the result... The only thing what's weird is that my CA doesn't show up in the Acceptable client certificate CA names section.
Anything else I could try?
Update:
I think it doesn't matter but my server certificate is set up for 127.0.0.1. Therefore I'm using https://127.0.0.1/... in my browsers.
Update2:
Using Wireshark I noticed that my servers' response depends on the client:
Fiddler (OK):
Client Hello
Server Hello, Certificate, Server Hello Done
Browser (Not OK):
Client Hello
Server Hello, Change Cipher Spec, Encrypted Handshake Message
Update3:
After enabling clientcertnegotiation the server response is different but still doesn't work:
Server Hello, Certificate
Certificate Request
Certificate, Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message
My self-signed CA doesn't seem to be in the Distinguished Names list...
Update4:
SSL Settings: Checked Require SSL and Client certificates set as Required. Client cert shows up in Personal and the intended purpose is Client Authentication.
I finally found the issue and a workaround:
As mentioned in Update3, Distinguished Names doesn't contain my CA. This is because Distinguished Names has a limit of 2^14 bytes (16384 bytes). Because I do have a lot of CA installed on my machine my CA simply didn't make it in. The TLS standard would allow to send multiple messages but unfortunately Windows doesn't support this!
As mentioned here you have a few possibilities. The simplest one is this:
At your server add a DWORD (not QWORD!) value called SendTrustedIssuerList in your registry under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL and set it to 0. This will prevent your server from sending a list at all, letting the client choose from any installed client certificate.
Unfortunately I couldn't see any traces in the Event Viewer (as reported elsewhere). Therefore the issue wasn't easy to spot (I had to use Wireshark in order to check Distinguished Names).
Use the Accept option instead of the Require option of the "Client certificates" feature.
In IIS Manager, locate the Web application for which you want to change the SSL setting.
In Features View, double-click SSL Settings.
On the SSL Settings page, select the Accept option under Client certificates.
In the Actions pane, click Apply.
More info here
Client certificate should be imported in CurrentUser\My store with private key (i.e. p12 or pfx file usually).
CA certificate should be in LocalMachine\Root store so that IIS trusts all certificates issued by the CA and the CA is trusted for every user on the computer.
CRL issued by the CA should be either available through URL (specified in every end entity certificate that CA issued) or imported in LocalMachine\My store.
NOTE: openssl doesn't use windows certificate store so this will have no efect on openssl s_client -connect 127.0.0.1:443 -state

How to determine a server's list of CA certificates that it will accept from client?

According to https://wiki.jasig.org/display/CASUM/X.509+Certificates,
After the Server sends the certificate that identifies itself, it then can then send a list of names of Certificate Authorities from which it is willing to accept certificates.
I am wondering how to determine what this list is, and how to modify it.
The reason I am asking is that I am getting an infinite redirect between my server and my client after successful validation (i.e., the ticket stage), and I think it has to do with the CAS server not recognizing the CAS client's certificate (the client's certificate is self-signed).
If you want to see what this list is, you can use OpenSSL:
echo "" | openssl s_client -connect your.server:port
This will show various messages regarding the handshake, including the certificates and the list of CAs in the CertificateRequest message.
Ultimately, it's determined by the active X509TrustManager's getAcceptedIssuers() method. By default, this will be the list of Subject DNs of all your trust anchors (that is, the Subject DNs of all the certificates in your trust store).
Your client certificate will have to be verified by the server. This is normally done during the handshake by the trust manager, which (unless tweaked) will build a chain to a known CA (or at least known cert if it's the user cert itself) in the trust store.
Adding your self-signed certificate to your trust store should be sufficient. It doesn't have to be the cacerts file bundled with the JVM, you could make a copy of it and use the trust store settings of Apache Tomcat's connector to set it up.