Installing certificate for a specific CA, or understanding why the existing one doesn't work - ssl

I have the following code in Python3.7:
import urllib.request
import urllib.error
import ssl
import certifi
# Create the SSL context
# Was using cafile=certifi.where() before, but copied it inline. Read below
context = ssl.create_default_context(cafile='cacert.pem')
# Prepare the request
request = urllib.request.Request(some_url)
try:
connection = urllib.request.urlopen(request, context=context)
except urllib.error.URLError as e:
print(e)
I've tried several different some_url and I'm getting a problem for a specific one, https://hypelabs.io. Other URLs are working; I tested, for example, https://facebook.com, https://stackoverflow.com, and so on, all working properly. For hypelabs.io I get this instead:
<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1051)>
First thoughts were that the CA was not recognized by the system, and that I needed to install the CA certificate first. I checked the chain in the browser and this is what I found:
However, the COMODO RSA Certification Authority is in all bundle files that I tried (as expected) and in the Keychain as well (I'm using MacOS High Sierra). Notice that the serial numbers match.
The second certificate in the chain is not in the system. I know that the root is enough, but just in case I tried downloading it and adding it to the bundle file, after converting the CRT file to PEM:
Same result. Why is this particular certificate failing? What should I be looking at?

The site is misconfigured and fails to provide a necessary intermediate certificate. The SSLLabs report therefore says:
This server's certificate chain is incomplete. Grade capped to B.
The second certificate in the chain is not in the system. I know that the root is enough, but just in case I tried downloading it and adding it to the bundle file, after converting the CRT file to PEM.
My guess is that you did something wrong here. Given that your description is correct I assume that it does not fully match what you actually did.
I've took the missing certificate with the same fingerprint as can be found here and added it to the list of root CA (taken on Ubuntu from /etc/ssl/certs/ca-certificates.crt. After that access to the site worked without any problems.

Related

Solve boost.asio certificate failed error -without- access to source code, to find out what information Philips Hue Bridge shares

This is a bit of a super duper specific question, but who knows there's someone out there that can help me.
I happen to have Philips Hue Bridge and I would love to know what personal information it is sharing with the outside world. Using tcpdump on my router I figured the Hue Bridge has a rather talkative personality. But because it talks over SSL tunnels, I have no idea what it says. So what I did is I setup a SonicWall with SSL-DPI with a CA, got root access to the Hue Bridge and found the application that does the talking to wws://ws.meethue.com (its called websocketcd). I then replaced the root certificate on the Hue Bridge, adjusted the cipher to match the Sonicwall and now I am stuck due to boost.asio trowing an validation error of my certificate:
error:14090086:lib(20):func(144):reason(134)
For those not too familiar with the error codes, this is what they mean:
lib(20) is ERR_LIB_SSL
func(144) is SSL_F_SSL3_GET_SERVER_CERTIFICATE
reason(134) is SSL_R_CERTIFICATE_VERIFY_FAILED
To verify it's not my SonicWall or certificate that is causing the problem, I executed openssl s_client -connect ws.meethue.com:443 -CAfile ca.pem from the Hue Bridge and that validates the chain perfectly fine, the same way as the original certificate. I also verified that the application is loading my root certificate and cipher correctly (because if change the cipher, I get a cipher error error). Also in my browser, I can visit https://ws.meethue.com without certificate errors. Here's my self made certificate chain, in case someone wants to check it: https://gofile.io/d/5msjoJ (password for download/key 1020304050, it's a temporary key that only exists in my local test env. so it's safe to share ;-)
If websocketcd wasn't a binary file, the problem was super easy to solve using set_verify_mode, but unfortunately it is a binary and that makes life significantly more complicated.
Is there anyone who can give me advice how to make this blob called websocketcd with boost.asio in it accept my root certificate? What I tried too: letting it communicate without ssl and with ssl without encryption (eNULL:aNULL ciphers). I am a bit hesitant to share the blob but for those who have a Hue Bridge too, it's located at /usr/bin/websocketcd.
Perhaps you can use strace (or maybe even ltrace) to spot which certificate paths it is using for root authorities.
If it uses a single file, you might be abel to hack it by replacing it with a CA that verifies your MITM certificate.
Sometimes the file can contain multiple certificates, so worth appending/prepending yours.
If you're in luck, there will be a readdir on a directory containing certificates. If so, you should be able to add your root certificate (in PEM form) there and **remember to run c_rehash on that directory.
For those interested: after some 20hrs, I figured that websocketcd requires a certificate revocation list for each CA in the chain (which do not have to have any revoked serials). These CLRs need to be included in the root CA file that is loaded using the ca-filename argument. I was not aware that Boost Asio could demand that a CLR is present for each CA, but apparently, they (Signify) managed to do so.

Cert unable to be installed in cpanel

I don't know much about this topic, but have a site (shared hosting) and want ssl for it. Got a certificate from letsencrypt (for both www and plain mydomain.com), they verified it successfully, so I put the cert and private key into the ssl config part of cpanel. Cpanel marked the inputs valid but then gave me the following error
The certificate could not be installed on the domain “mydomain.com”.
error Certificate verification failed!
Certificate verification failed:
unable to load certificate
140495454865312:error:0906D064:PEM routines:PEM_read_bio:bad base64 decode:pem_lib.c:812:
I have no idea what this means. Any help would be appreciated.
Got it working by making sure every line was exactly 64 characters long

InstallCert.java crashes server before certificates are retrieved

I have a server running on Dropwizard (i.e. running Jetty for its web server). I'm trying to set up SSL for it.
I have a certificate signed by a CA (specifically Comodo, through Namecheap). I installed the root and intermediate certificates, then installed my own certificate (using the instructions on Comodo's support. Nonetheless, when I attempt to connect to my server for the first time (it boots fine), I get an error: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target (Of course the stack trace is much longer, but that's the root cause.)
I've tried searching this error, and consistently people say it should only happen for self-signed certificates, which mine is not. Nonetheless, I tried downloading the InstallCert.java program that seems to have originated from a (now removed) article on the Sun blog. Specifically I got the degree from this page.
After several (failed) attempts to get it to work by command line (that's a discussion for another time), I eventually got it to run properly. Now the output I get from the program is:
Loading KeyStore C:\Program Files\Java\jdk1.8.0_05\jre\lib\security\cacerts...
Opening connection to localhost:8443...
Starting SSL handshake...
Exception in thread "main" java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:150)
at java.net.SocketInputStream.read(SocketInputStream.java:121)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
at sun.security.ssl.InputRecord.read(InputRecord.java:503)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:954)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1343)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1371)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1355)
at com.aw.ad.util.InstallCert.main(InstallCert.java:98)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Process finished with exit code 1
Meanwhile, if I open the window with my website, it once more delivers the unable to find valid certification path to requested target error and crashed (hence leading to the timeout). In essence, what it seems to me is that InstallCerts (which should fix my SSL problems) is crashing my server due to the SSL issues.
If I try using something like openssl s_client -connect localhost:8443 -showcerts (which was a recommendation I saw somewhere, save the results of that to a .pem file and install that), the same thing happens.
Is there a solution this problem? Am I missing something obvious here?
You might be missing the whole chain of certificates from Comodo root CA to your site's certificate. Examine the keystore that you configured in Dropwizard and see if you have them all. The simplest way is to look for the issuer of your certificate, you need to have the certificate with the same subject, next look for the issuer of that certificate and so forth. To be sure try to chain authority key identifier certificate extension of your certificate with the key fingerprint (key identifier) of the issuer, and the issuer's issuer. If you provide
keytool -list -keystore <your keystore> -rfc
I might be able to help you more...
Added later:
I've managed to reproduce your problem exactly. TL;DR; add:
validateCerts: true
trustStorePath: lyonesgamer.com.keystore
enableCRLDP: true
I created a keystore containing the chain (single entry, 3 certificates, ca, subordinate ca and end entity certificate) and another keystore containing only the two ca certificates as trusted entries. Then I configured keyStorePath, keyStorePassword, trustStorePath and validateCerts: true.
This resulted in:
java.security.cert.CertificateException: Unable to validate certificate: unable to find valid certification path to requested target
After adding -Djava.security.debug=certpath I noticed that revocation checking was failing, and that this in fact was the root cause of certificate chain failure:
certpath: SunCertPathBuilder.depthFirstSearchForward(): validation failed:
java.security.cert.CertPathValidatorException: Could not determine revocation status
Then I remembered that if you do not enable CRL Distribution Point extension usage for the CertPath API you need to specify the CRL yourself. Fortunately Dropwizard has an option to enable the CRLDP: enableCRLDP: true. With it enabled application successfully starts.
Alternatively you could keep the CRL in a file and point crlPath to it.
After all this time, I'd been chasing a rabbit hole. It turned out the problem was that I (rather naively) was testing this on my own computer. Dropwizard's validation saw an error, because the certificate was only valid for my domain, which my personal computer is not a member of. Hence it crashed because it couldn't validate.
I discovered this by turning validateCerts off in my Dropwizard config file (I had thought I'd turned it off already, but apparently not). Dropwizard booted fine and allowed me to connect. When I did, then Firefox gave me an Untrusted Connection error, and clicking on Details gave me the much more useful information:
localhost:8443 uses an invalid security certificate.
The certificate is only valid for the following names: lyonesgamer.com, www.lyonesgamer.com
(Error code: ssl_error_bad_cert_domain)
Thank you, Zoran, very much for trying to help. I'm afraid much of it was in vain.

OpenLDAP: TLS error -8179:Peer's Certificate issuer is not recognized

I'm not familiar with certificates and openldap. I'm trying to port someone elses work from an older OS to CentOS-6 with openldap-2.4.23. On the old OS, an ldap connection worked without issue. Now on CentOS-6, I get the following error when doing a simple bind:
TLS error -8179:Peer's Certificate issuer is not recognized.
My /etc/openldap/ldap.conf has a single line:
TLS_CACERTDIR /etc/openldap/certs
I tried commenting out that line and putting the following into the file but that didn't change the error message I received.
tls_reqcert allow
I also tried putting only the following line in ldap.conf but that didn't change the error. I tried this based on information found in this question.
LDAPTLS_CACERT /etc/ssl/certs/ca-bundle.crt
I copied files into the following directories:
/etc/pki/tls/certs/ca.crt
/etc/pki/tls/certs/server.crt
/etc/pki/tls/private/server.key
I have no choice but to use openldap-2.4.23. Any idea what is causing this error or what I can do to troubleshoot?
Thanks in advance.
SP
As per http://www.zytrax.com/books/ldap/ch6/ldap-conf.html TLS_CACERT should point to the file containing the CA cert that the client will use to verify the certificate. You need to make sure the your servers CA [The CA that signed your server certificate] is present in the file that TLS_CACERT points to[in your case /etc/ssl/certs/ca-bundle.crt.
I had the same error. In my case the reason was, that my client had the wrong certificate in /etc/ipa/ca.crt. To fix this, I just copied /etc/ipa/ca.crt from the KDC server to the client and the error disappeared.
Depending upon the environment, OpenLDAP may completely ignore the value set for TLS_CACERTDIR because evidently GnuTLS doesn't support that type of certificate store.
From the man page for ldap.conf(5)
TLS_CACERTDIR <path>
Specifies the path of a directory that contains Certifi‐
cate Authority certificates in separate individual files.
The TLS_CACERT is always used before TLS_CACERTDIR. This
parameter is ignored with GnuTLS.
In my case, I suspect that GnuTLS is in use, so TLS_CACERTDIR simply does nothing. Using TLS_CACERT pointed to a file containing the certificate of my server's signing CA seems to have done the trick.
I think https://serverfault.com/questions/437546/centos-openldap-cert-trust-issues is a much more complete answer.

Coldfusion: CFHTTP with SSL encrypted Page (https://) - got an error

I'm making an cfhttp to connect to an encrypted page. Seems to work fine for some sites.
I/O Exception: Name in certificate `pro.test.com' does not match host name `go.test.com'
Is there a workaround to trust this certificate even if the host name doesn't match?
Think this is more Java question, and workaround should be affecting the JRE.
Not sure if this will work in your case, but possible solution is to import this certificate into the JRE keystore.
Generic description can be found at Sun website. Though process is pretty simple.
First you should navigate the needed HTTPS URL with your browser and export the cert using SSL properties (don't remember how it is done in IE, but in Firefox something like Security > View cert > Details > Save as -- still not sure because using non-English licalization), any X.509 type should work.
Next you should import it using keytool. Navigate to the current CF JRE's bin, execute the following command (replace arguments with your values) and restart CF:
keytool -keystore <path to keystore> -import -file <path to certificate> -alias <alias>
BTW, there is a UI tool for this, but I haven't used it so can't say if it works fine.
The sites that are probably working have a valid SSL Certificate from a trusted authority.
If you have control of pro.test.com, the preferred answer would be to get a valid cert for pro.test.com installed. But if that is not possible for some reason, I see two other options:
1) Do a try/catch where you try to connect via https, and fall back on http in the event of an SSL error. Obviously this would eliminate encryption for the failed connection.
or
2) Use Sergii's solution to import the key for that site into the Java keystore.
If go.test.com is just a development server, in that case you can create a self-signed certificate and import it into Java keystore. That way you can save up on cost by not paying to CA and get a quicker turnaround to resolve the issue