LDAPS - forcing what client certificate gets presented first - ssl

Hey everyone and thanks in advance for any feedback you might have on this.
Got a web application that is trying to authenticate an AD user via LDAPS. The application server in this case being the client and a DC with LDAPS being the server, during TLS handshake, client certificate authentication is requested by the DC and this process takes quite a long time to complete as it seems it is trying to iterate over each certificate that has "Client Authentication" enabled (and there are quite a few of them to go over).
Is there any way on the client (the web app server running Windows) to "force" or "suggest" what certificate gets presented first? If not, is there any way on the server (the DC with LDAPS enabled) to specify that the server only wants to see certificates from a specific CA?
I have had a look into TLS negotiation documentation and so far was not able to find an answer to this question.

The LdapConnection class has a SessionOptions property allowing to set a handler named QueryClientCertificate which can then return a certificate to use.

Related

Certificates, install in local machine before calling a service

I am trying to wrap my head around certificates and any help is appreciated. So far this is what I understand, please correct me if I am wrong.
When using the browser when I navigate to the https site the browser downloads the certificate(without the private key) and then continues to send the data over https?
I have come across some sites (especially when developing) that require you to install the certificate on the local machine before making a service call. What is the purpose here and how does it work?
I have also seen some scenarios where you need to install the certificate on the client machine for authentication purposes for example if you are using an email client, how does this work?
When using the browser when I navigate to the https site the browser downloads the certificate(without the private key) and then continues to send the data over https?
No, the browser and the server stablish a SSL/TLS secure channel with a symmetric encryption key. During the handshake process the server presents the https certificate and digitally signs some data with the private key as a proof of authenticity.
I have come across some sites (especially when developing) that require you to install the certificate on the local machine before making a service call. What is the purpose here and how does it work?
The client must trust the server certificate. Usually it has a list with the Certification Authorities for which certificates are accepted. For other certificates is needed to add them to the trust list. If not, the communication will be rejected
I have also seen some scenarios where you need to install the certificate on the client machine for authentication purposes for example if you are using an email client, how does this work?
Probably the same case as the previous one. Also the public part of the certificate of a user can be used to encrypt a message for him

How secure is the https connection if the client not passes certificate

We have a web server running on linux machine where we configured 'SSLVerifyClient' as 'require' in ssl.conf file.
Does this needs client who is utilizing the service from web browser(like firefox or chrome) needs a certificate.
If yes, then it is not possible to distribute client certificate to every user as there can be some thousands of users, how to overcome this problem.
If no, then how the data passed over network is secure? I know that certificate helps in encrypting data so that no one who don't have certificate can read data.
Please help me in clarifying my doubts
If you don't use client certificate, the https connection is still safe:
Only the client and the server can read/write the content
The identity of the server is assured by a certificate authority
Client certificate only give you client authentication in the beginning of the connection. To encrypt the data, the public key of the server is used in the beginning (See public key encryption).
If you identify the client with cookies set after login/password submit, it is still safe: you have identify the client.
When SSLVerifyClient is set to require, the client MUST pass a client certificate. You would generate these via OpenSSL, and sign them with a certificate authority that you install via SSLCACertificateFile.
How you distribute those certificates is an issue you'll have to solve yourself.

2 Way SSL - Client Certificate Not Sent To Server

I'm have an application deployed to salesforce on the force.com platform,
which I'm trying to configure a 2 way SSL for.
I.e.
I want that for each request sent to from SF to my server, a client certificate will be sent.
I did the necessary configurations on SF for the certificate to be sent, but I'm still getting 403.7 from the server, which means: forbidden, client certificate required.
I installed wireshark on the server, captured traffic to see the 2 way ssl handshake, and I'm trying to find in the server hello message where it tells the client the trusted CAs from which a client certificate should correspond, but I'm having difficulties finding it.
I suspect that's why the client does not send the certificate.
Can anyone point me to where in the server hello I should look? Or perhaps in another packet capture?
Thanks in advance.
Client Key Exchange record:
Here, the server sends its Certificate Request message and the client sends its Certificate message in response, but that message contains 0 certificates.
Typically, this happens when the client was unable to select a client certificate to use. Either it's not configured properly to make use of any certificate, or it can't find one that is issued by one of the acceptable CAs.
Look at the Certificate Request packet and check its certificate_authorities list. This is a list of the CA Distinguished Names (DNs) that the server is willing to accept.
One way or another, the client will need to find a client certificate with which it can build a chain towards of those DNs. In the simplest case, a client certificate issued by such a DN is available. Otherwise, the client could have to build a chain from a client cert to such a DN, it would need to have the necessary intermediate CA certificates to do so. (How this is done depends on the client's configuration mechanisms.)
If intermediate CA certificates are necessary and not available on the client side, you may need to configure your server to accept them and advertise them in the Certificate Request too.
Added a screenshot of the handshake captures. can you please point me to where I should be looking? –
See packet #31. It contains the Certificate Request. Also packet #33 contains the certificate from the client, so the reason is not the client does not send the certificate, but instead that the server either does not like the certificate because the validation failed or because the certificate is not sufficient as authorization for the requested resource. You might get more information from the servers log.
Not sure if this will help anyone else, but for our case of this issue everything was working when running locally in Visual Studio and in IIS, but when deployed to a real server, we were hitting a certificate issue during 2-way SSL as described above and verified in Wireshark.
Anyway, on that server we have also have a .NET 4.7.2 Console application which was calling the same API and everything was working fine.
But, our .NET 4.7.2 web API calls were failing. It appears that when the same code was running inside IIS the cert was not available during the SSL negotiation. (although it loaded fine)
Our solution at this point was to modify the following call to include the 3rd parameter.
certificate = new X509Certificate2(certificatepath, Password, X509KeyStorageFlags.MachineKeySet);
By default X509Certificate2 uses the UserKeySet option, so perhaps the application pool user or another thread in IIS (?) was having trouble accessing the cert for the negotiation.
Here are a couple of the related pages that I found useful during my research:
https://paulstovell.com/x509certificate2/
https://github.com/dotnet/runtime/issues/23437

Does LDAP over SSL require a cert on the client?

I am trying to resolve a problem whereby trying to set a users password over LDAP is failing because of an access denied error - even though I am authenticating against the AD with an admin user.
An answer found in stackoverflow says that either I have to run the IIS user as the admin user (which does work) or i should connect to LDAP via SSL.
I cant go with the first option because I am using Elastic Beanstalk which will create and terminate instances so i cant change/set the user that IIS will be running as. So I am trying to use the LDAP over SSL idea.
My question is does that still require that the client itself also have a certificate installed in order to establish trust with the Domain controller? Or does this work just by installing a cert on the Domain controller and allowing the connection over SSL?
If it requires a certificate on the client then I have the same problem as i cant install anything on the client server other than the deployed app since Beanstalk is going to recereate and terminate that instance at will.
So does LDAPS require a cert on the client?
Is there a better way to solve my problem given the infrastructure i am using?
So does LDAPS require a cert on the client?
no, LDAPS do not require client certificate. Domain controller certificate is sufficient to utilize LDAPS. More details about LDAPS and certificate requirement: LDAP over SSL (LDAPS) Certificate
trying to set a users password over LDAP is failing because of an access denied error
there might be over9000 reasons why you receive this message. You need to check whether you are successfully authenticated on DC, if yes, check whether you have permissions and privileges (especially, if UAC is enabled). I would set up audit policies (on failed user password changes) and check Security eventlog to figure out what is going wrong.
No.
For openldap, I achieved this by adding this line to ldap.conf. But be aware of that, when you do that, your connections will be open to attacks like man-in-the-middle or any other.
TLS_REQCERT never
This is what I found using trial and error approach:
Actually, LDAPS server always asks for client certificate. You can verify that by turning on SCHANNEL log and observing the following message:
If there is no client authentication certificate than LDAPS connection still succeeds, i.e. no client authentication certificate is required indeed. But if you have some invalid client authentication certificate (in my case it was an expired cert installed long ago by a third party app) the connection will fail w/o any error or warning in SCHANNEL log on the client side. It took me a while to figure this out.
Yes of corse your client need a certificate to allow ladps communication betwen
him and de server.
According to
windowsitpro.com:
As an option, you can use LDAPS for client authentication -- but doing so requires that you also install a client authentication certificate on each of your clients."

Verify what client authentication certificates are sent to server?

Is there a way in browser or through some tool to see what SSL certificate (client authentication) was sent to server in request?
I'd start with something like Burp Suite (Free Edition). It's a darn good proxy for... lots of things.
If your server negotiates the client certificate during the initial handshake (without renegotiation), you should be able to see it using Wireshark: you should see a Certificate message coming from the client (not the one coming from the server), after a Certificate Request message sent by the server.
If renegotiation is used, this is more complicated.
SSL MITM tools (like Fiddler) won't be of any help, since they perform their own handshakes. Such tools can be configured to fool the client into believing they are the real server, by having the client trust their fake server certificate (a trust setting the user can generally set on the client). However, this doesn't work on when using a client certificate, unless the tool performing the handshake (the SSL MITM tool in this case) was handling the client certificate itself. Otherwise the verification message at the end (which the server uses to verify that the client has the private key for the client certificate) would fail. Some of these tools can indeed be configured with a client certificate, but you need to set them up with the corresponding private key: in this case you would know which client certificate was used.
Another way to check would be to check what the browser itself does. How to do it may depend on the browser. Environment variables like SSLDEBUG might be of interest when using Firefox.