0

I'm trying to connect to an internal site using urlopen. And it's failing repeatedly with SSL error irrespective of providing cafile.

I tried all the various ways explained in the stackoverflow answers. But no luck.

urllib2.urlopen(url,cafile=certifi.where())

Second Way:

context = ssl.create_default_context(cafile=certifi.where())
urllib2.urlopen(url,context=context)

Third Way:

ctx = ssl.create_default_context()
ctx.load_verify_locations(cafile = certifi.where())
urllib2.urlopen(url,context=ctx)

Whichever way, I try, I get the following error.

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "urllib2.py", line 154, in urlopen
    return opener.open(url, data, timeout)
  File "urllib2.py", line 429, in open
    response = self._open(req, data)
  File "urllib2.py", line 447, in _open
    '_open', req)
  File "urllib2.py", line 407, in _call_chain
    result = func(*args)
  File "urllib2.py", line 1241, in https_open
    context=self._context)
  File "urllib2.py", line 1198, in do_open
    raise URLError(err)
urllib2.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:661)>

I've added the entry of CA certificate to the file certifi.where() too. I use the python version 2.7.14.

Could someone tell me whether I miss something here? Or the python version, that I use doesn't support it? Also, let me know the way to debug this, that is, to find out whether there is any issue with the CA certificate.

Thanks.

EDIT: I don't want to opt out SSL verification as suggested in one of the answers in urllib and "SSL: CERTIFICATE_VERIFY_FAILED" Error. The other answer tells me to use cafile with urlopen which doesn't work in my case. I've tried the solutions given in the answers of this question; but no luck.

Also, openssl throws the following error.

[root@host1 ~]# openssl s_client -connect url -CAfile "cacert.pem"
...
Certificate chain
...
Server certificate
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
...
No client certificate CA names sent
...
SSL handshake has read 2098 bytes and written 415 bytes
...
    Verify return code: 2 (unable to get issuer certificate)
---
HTTP/1.0 408 Request Time-out
Cache-Control: no-cache
Connection: close
Content-Type: text/html

<html><body><h1>408 Request Time-out</h1>
Your browser didn't send a complete request in time.
</body></html>
closed
Hema
  • 167
  • 4
  • 15
  • 1
    Possible duplicate of [urllib and "SSL: CERTIFICATE\_VERIFY\_FAILED" Error](https://stackoverflow.com/questions/27835619/urllib-and-ssl-certificate-verify-failed-error) – DYZ Mar 27 '18 at 05:47
  • 1
    @DyZ But the solution given in it doesn't work for me. Also, I don't want to opt out SSL certificate verification. I want to debug and make it work. Any help is appreciated. – Hema Mar 27 '18 at 06:10
  • 1
    My guess is that either not the correct root CA for the internal site was added to the `cafile` or that the server does not sent all required intermediate certificates and thus the certificate chain cannot be created. Unfortunately it is impossible to replicate the problem based on the current information to find out what the problem actually is. – Steffen Ullrich Mar 27 '18 at 06:13
  • @SteffenUllrich Is there any way to find out that the problem is with root CA or intermediate certificate? I'm fine if you can say me a way to find it in Linux CLI too. – Hema Mar 27 '18 at 06:18
  • 2
    @Hema: `openssl s_client -connect domain.test:port -servername domain.test -CAfile your.cafile` shows you the status of the verification with the specific CA file and also shows you the certificate chain send by the server. – Steffen Ullrich Mar 27 '18 at 06:21
  • @SteffenUllrich The openssl command returns "getaddrinfo: Servname not supported for ai_socktype; connect:errno=0". Do you have any idea on this? – Hema Mar 27 '18 at 06:30
  • 1
    @Hema: I have no idea what you've put in as arguments instead of the `domain.test` in my example but it should be of course the domain name and port from the URL - not the full URL (including path and method) but just the domain name and the port (443 if you don't have an explicit port specified in the URL). In other words: not `https://example.com/foo` but `example.com:443`. And for the `-servername` argument only `example.com` (without port). – Steffen Ullrich Mar 27 '18 at 06:36
  • @SteffenUllrich Yes. You are right. Removing `https://` works. Now, it shows the "Server Certificate" followed by the message `SSL handshake has read 2098 bytes and written 415 bytes` followed by `Verify return code: 2 (unable to get issuer certificate)` and timed out. – Hema Mar 27 '18 at 06:47
  • @Hema: Obviously the CA file you use is not sufficient to built the certificate chain as shown by `unable to get issuer certificate`. Only, you neither show the contents of the certificates sent by the server (i.e. you explicitly redact it from the output) and also the contents of the CA file is unknown. Based on this it you've just shown that the same problem happens without Python. But you still did not provide any information which might be useful to find out where exactly the problem is. – Steffen Ullrich Mar 27 '18 at 07:05
  • @SteffenUllrich I installed the certificate chain instead of only the intermediate certificate. But now the openssl error, I face is `Verify return code: 21 (unable to verify the first certificate)` and urlopen error is `Traceback (most recent call last): File "", line 1, in File "/opt/software/lib/python2.7/urllib2.py", line 144, in urlopen capath=capath) File "/opt/software/lib/python2.7/ssl.py", line 450, in create_default_context context.load_verify_locations(cafile, capath, cadata) ssl.SSLError: [X509] PEM lib (_ssl.c:2941) ` – Hema Mar 27 '18 at 16:04
  • There is still no way for me to reproduce what you are actually doing and you deliberately omit any useful information about this. I can understand this since you don't want to publish internal information but this way helping you is not really possible. If you need more help please recreate everything using test certificates and setups you can actually publish to allow somebody else to reproduce your problems. – Steffen Ullrich Mar 27 '18 at 16:47

0 Answers0