can I hide the Acceptable client certificate CA names? - ssl

Today someone asked me if it was possible to hide the "Acceptable client certificate" list in the SSL connection information. Spontaneously, my answer was no, but according to the RFC it seems to possible.
openssl s_client -connect www.test170.com:443 -state
[...]
Acceptable client certificate CA names
/C=FR/ST=DPT/L=CITY/O=COMPANY/CN=CA_own
[...]
The idea is to hide this informations and let client send the good certificats.
((...These distinguished names may specify a desired distinguished name
If the certificate_authorities list is empty, then the client MAY
send any certificate of the appropriate ClientCertificateType,
unless there is some external arrangement to the contrary.))
Someone know how I can hide these informations?
The servers are running with apache2.2 and 2.4.
I try to play with SSLCADNRequestPath path_empty_file but for now it doesn't work.

Related

LDAPS Microsoft Active Directory Multiple Certificates RFC6125

We have an Microsoft Active Directory Domain with a large pool of domain controllers (DC) that are are setup with LDAP. These are all setup with LDAPS and uses Certificate Services via a template to setup a certificate with the domain name (i.e. test.corp) in the Subject Alternate Name (SAN) for the LDAPS server to serve.
Since these are DC's, DNS is setup in a pool for each these systems to respond to requests to test.corp in a round robin fashion.
Each of these DC's have multiple templates and multiple certificates in the Local Computer\Personal Certificate Store.
Upon testing, using a nodejs module, ldapjs when making a LDAPS request using the domain name, test.corp we notice that a handful of servers fail with the following message:
Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match
certificate's altnames: Host: test.corp. is not in the cert's
altnames: othername:, DNS:.test.corp
As we investigated we found that these handful of LDAPS servers are serving the incorrect certificate. We determined this by using the following command
openssl s_client -connect .test.corp:636
If you take the certificate section of the output and put it in a file and use a tool such as the Certificate manager or certutil to read the file, you can see the certificate is not the correct one. (It does not have the domain "test.corp" SAN). We also verified this by comparing the Serial Numbers
As we investigated, since we have DC's that have multiple certificates in the Local Computer\Personal Certificate store, we came across the following article:
https://social.technet.microsoft.com/wiki/contents/articles/2980.ldap-over-ssl-ldaps-certificate.aspx
It suggests putting the certificate from the local computer\Personal certificate store to the Active Directory Domain Service\Personal store. We followed the steps outlined but we found the same results.
Upon further investigation, it was suggested to use a tool called ldp or adsiedit. We then proceeded to use these tools and spoofed the local machine's host file we were doing the test from, to point the domain (test.corp) to the ip's of one of the DC's that are giving us trouble. After a restart to clear any cache we tested the "ldp" and "adsiedit" tools to connect to test.corp. These systems did not report any errors.
We found this odd, we then ran the openssl command to see what certificate it was serving from this same system and we found it was still serving the incorrect certificate.
Upon further research, it appears that the "ldp" upon selecting the SSL checkbox and "adsiedit" tools were not compliant with RFC6125, specifically B.3
https://www.rfc-editor.org/rfc/rfc6125#appendix-B.3
, which basically states the identity of the certificate must match the identity of the request otherwise the handshake would fail. This identity verification is done by using the certificate common name (CN) or the SAN.
Based on this appears the tools "ldp" and "adsiedit" are not conforming to the RFC6125 standard.
All this to say, we need to first fix the handful of domain controllers that are serving the correct certificate. We are open to suggestions since we have been working on this problem for the past few months. Second, is there a way to get the MS tools in question to work to the RFC6125 standard?
This has been moved to:
https://serverfault.com/questions/939515/ldaps-microsoft-active-directory-multiple-certificates-rfc6125
RFC6125 specifically states that it does not supersede existing RFCs. LDAP cert handling is defined in RFC4513. Outside of that, RFC6125 has significant flaws. See also https://bugzilla.redhat.com/show_bug.cgi?id=1740070#c26
LDP will supposedly validate the SSL against the client store if you toggle the ssl checkbox on the connection screen.
That said, I'm not surprised that neither it nor ADSI edit enforce that part of the standard given they are often used to configure or repair broken configurations. Out of the box and without Certificate Services they use self signed certs on LDAPS. I would wager 80% of DCs never get a proper certificate for LDAP. If they enforced it most wouldn't be able to connect. A better design decision would have been to toggle off the validation.
I use a similar openssl command to verify my own systems. I think it's superior to LDP even if LDP were to validate the certificate. To save you some effort, I would suggest using this variant of the openssl command:
echo | openssl s_client -connect .test.corp:636 2>/dev/null | openssl x509 -noout -dates -issuer -subject -text
That should save you having to output to a file and having to read it with other tools.
I've found LDAPS on AD to be a huge pain for the exact reasons you describe. It just seems to pick up the first valid cert it can find. If you've already added it to the AD DS personal store, I'm not sure where else to suggest you go other than removing some of tother certs from the DCs computer store.

Simulate expiring SSL certificate

I'm looking for a service online, able to simulate an expiring SSL certificate. I know about badssl.com, but that only seems to include an expired certificate. What I'm looking to do is to call an endpoint with a certificate expiring in something like 5 days. Possible?
I do not know about an online service tailored to your needs (you could also try to contact badssl.com and ask them if they would be willing to add your test case, as it may profit others too), but locally you can run openssl s_server and configure it to use any local certificate you would have created to be in the situation you need to test.
From its manual:
The s_server command implements a generic SSL/TLS server which listens for connections on a given port using SSL/TLS.
and:
s_server can be used to debug SSL clients. To accept connections from a web browser the command:
openssl s_server -accept 443 -www
can be used for example.
Otherwise, if you are outside of the world wide web world:
If a connection request is established with an SSL client and neither the -www nor the -WWW option has been used then normally any data received from the client is displayed and any key presses will be sent to the client.
(and follows a list of special keys for special operations).

PJSIP TLS verify error (PJSIP_TLS_ECERTVERIF)

I have recently started to develop a tiny SIP softphone application using the PJ Project and GTK+. My main goal was to create a softphone which supports both TLS and SRTP encryption (and MWI). However I have got stuck right at the part where the library registers an account because the application has failed to verify the server when I asked it for it.
I thought that I misunderstood something while I was coding as I'm a newbie but today I've just tested the library using the PJSUA application which was attached in the source code and it could register my SIP account unless I've started the program with the --tls-verify-server flag.
To make it clear I've created for Asterisk my own certificate authority, keys and certificate and I've installed the CA to my machine.
I must note that this setup works with a commercial software, it can verify the certificate without any problem.
The PJSUA flags I've used:
--use-tls
--tls-ca-file /etc/ssl/certs/ca-certificates.crt
--id=sip:u-kuklinistvan1#kingdom.info.tm;transport=tls
--registrar=sip:kingdom.info.tm;transport=tls
--realm=kingdom.info.tm
--username=u-kuklinistvan1
--password=xxxxxx
--use-srtp=2
--mwi
--tls-verify-server
It says(please follow the link for the long version):
19:21:44.728 pjsua_app.c TLS cert verification result of [94.21.11.229:5061] : The server identity does not match to any identities specified in the certificate
...which could not be true as OpenSSL itself accepts the certificate:
openssl s_client -CAfile /etc/ssl/certs/ca-certificates.crt -connect kingdom.info.tm:5061
(click here for the rest)
Verify return code: 0 (ok)
Extra information
I connect PJSUA as endpoint to registrar by hostname kingdom.info.tm.
Is it possible that I've encountered a bug or I just don't understand something?
Thank you for your help!
... does not match to any identities specified in the certificate
... which could be not true as OpenSSL itself accepts the certificate: ... openssl s_client ...
The error messages refers to checking the identity against the certificate, i.e. the hostname you provide against the names in the certificate (subject alternative names, common name). openssl s_client does not do any identity checks but only checks for a valid trust chain.
Looking at the certificate provided by the server it actually contains contain a common name for kingdom.info.tm. But from the error message it looks that it expects the IP address: TLS cert verification result of [94.21.11.229:5061]: .... Did you specify the SIP URL of the peer with an IP address?

Certificate Validation is SSL Handshake using memcmp or Strcmp?

Wanted to know about the pros and cons of using either "memcmp" or "strcmp" for validating the certificates exchanged during SSL Handshake.
My code converts the X509 certificates into PEM format and then do the string comparison to validate the certificates.
Are there any issues which are associated with using strcmp OVER memcmp for validating the certificate received during handshake against a verified certificate already placed on the server?
From your description it is hard to know what you do with memcmp or strcmp, but I assume, that you want to check the common name or subject alternative names against the hostname. There were others which used strcmp instead of memcmp for this which resulted in lots of security reports in 2009, see CVE-2009-2408 (firefox), CVE-2009-2702 (KDE), CVE-2009-3767 (OpenLDAP) and some more.

How to tell LDAP SSL server with multiple certificates to return the one that I need?

My simple LDAP java program, using
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, <UserDN>);
env.put(Context.SECURITY_CREDENTIALS, <Password>);
env.put(Context.SECURITY_PROTOCOL, "ssl");
env.put(Context.PROVIDER_URL, "ldaps://<host>:636");
to make LDAP SSL authentication stopped working ever since a 2nd server certificate with the same CN but other details in the subject are different was installed on the server which I don't have access at all.
The program fails when I make the initial context
new InitialDirContext(env);
The error is "Failed to initialize directory context: <host>:636"
It returns the 2nd server certificate when I run
openssl s_client -showcerts -connect <host>:636 </dev/null
that makes me believe that the solution will be to find a way to tell the server which certificate to use.
I search and read a lot of articles on this topic and I have to admit that I am very confused, it is not clear to me if these articles are talking about client certificate or server certificate, or the actions to be taken are for the client side, or server side.
In one article, it says that I can use a custom SSLSocketFactory with the keystore path and
env.put("java.naming.ldap.factory.socket", "com.xxx.MyCustomSSLSocketFactory");
But I don't know the path to the server certificate keystore on the server.
In one Microsoft article, it says the best resolution is to have just one server certificate on the server or to put the server certificate to Active Directory Domain Services (NTDS\Personal) certificate store for LDAPS communications. But I don't have access to the server and the 'fix' to this problem has to be done in my LDAP java program.
In another article, it says to use Server Name Indication (SNI) extension.
So is there a way that I can specify which certificate I want to the server? Or my problem is somewhere else?
Thanks a lot.
Here is the stack trace:
javax.naming.ServiceUnavailableException: <host>:636; socket closed
at com.sun.jndi.ldap.Connection.readReply(Connection.java:419)
at com.sun.jndi.ldap.LdapClient.ldapBind(LdapClient.java:340)
at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:192)
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2694)
at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:293)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:175)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:193)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:136)
at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:66)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
at javax.naming.InitialContext.init(InitialContext.java:223)
at javax.naming.InitialContext.<init>(InitialContext.java:197)
at javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:82)
When I used Jxplorer to run the same test, it gave me the same error.
EJP was right to point out that the issue was that the certificate was not trusted. Many thanks EJP.
When I installed the CA Certificate in %JAVA_HOME%/lib/security/cacerts, Jxplorer worked. My program still failed. I had to add these lines in it to make it work (not sure if I need all of them though ...):
System.setProperty("javax.net.ssl.keyStore",%JAVA_HOME%/lib/security/cacerts);
System.setProperty("javax.net.ssl.trustStore",%JAVA_HOME%/lib/security/cacerts);
System.setProperty("javax.net.ssl.keyStorePassword=changeit);
System.setProperty("javax.net.ssl.trustStorePassword=changeit);
But since the certificate is not trusted in the first place, I simply 'force' our server to trust it, hence this solution is not acceptable. And neither our server nor the LDAP server runs with Java 7. So SNI is out too!
EJP mentioned that I could control the server certificate by restricting the cipher suites or accepted issuers in the client (my webapp), if the server certificates have different algorithms or issuers. The 2 certificates do have different issuers, however, I don't know how to do that and I could not find anything on that neither.
EJP can you please elaborate, or point me to some sites ... ?
If the certificates have different issuers, you can control which certificate you get at the client by controlling which of those issuers is in your truststore. If only one of them is, that's the one you'll get. If they're both there, you get pot luck. Note that if your truststore also contains a common super-issuer, again it's probably pot luck.
The result isn't pot luck if you specify one and only one certificate in the Certificates - Service (Active Directory Domain Service) - NTDS\Personal location in Microsoft Management Console. Contrary to Microsoft docs I've read, though, a domain controller restart seemed to be necessary for the newly specified certificate to 'take hold'.