Python Sockets SSL: certificate verify failed - python

I am attempting to use python sockets to make an Extensible Provisioning Protocol (EPP) request to a domain registrar, which only accepts requests over ssl.
Certificate file: www.myDomain.se.crt
Key File: mydomain.pem
openssl s_client -connect epptestv3.iis.se:700 -cert www.myDomain.se.crt -key mydomain.pem
When I try making request using openssl client I successfully get greeting response from registrar, but when I use following code in python i get ssl certificate error.
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(15)
sock.connect(('epptestv3.iis.se', 700))
sock.settimeout(60) # regular timeout
ssl_keyfile='myDomain.pem'
ssl_certfile='www.myDomain.se.crt'
ssl_ciphers='AES256-GCM-SHA384'
ssl_version=ssl.PROTOCOL_TLSv1_2
sock = ssl.wrap_socket(sock,
ssl_keyfile,
ssl_certfile,
ssl_version=ssl_version,
ciphers=ssl_ciphers,
server_side=False,
cert_reqs=ssl.CERT_REQUIRED,
ca_certs=None
)
After executing script I get following error:
Traceback (most recent call last):
File "server_connect.py", line 54, in <module>
ca_certs=ssl_keyfile
File "/usr/lib/python2.7/ssl.py", line 933, in wrap_socket
ciphers=ciphers)
File "/usr/lib/python2.7/ssl.py", line 601, in __init__
self.do_handshake()
File "/usr/lib/python2.7/ssl.py", line 830, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
Any idea what's wrong here?

From your code:
cert_reqs=ssl.CERT_REQUIRED,
ca_certs=None
From the documentation of wrap_socket:
If the value of this parameter is not CERT_NONE, then the ca_certs parameter must point to a file of CA certificates.
Essentially you are asking in your code to validate the certificate from the server (CERT_REQUIRED) but specify at the same time that you have no trusted root (ca_certs=None). But without trusted root certificates no validation can be done.
Note that changing your code to use CERT_NONE instead would be a bad idea. It would probably work since no certificate validation will be done but it would be open to man in the middle attacks.

Related

SSL error on web request when using CNAME

How do you fix an SSL error caused by a CNAME DNS record?
I have an API hosted on AWS accessible from a URL like https://sd098fs0f98s9f0s.execute-api.us-east-1.amazonaws.com.
To shorten this and rebrand it a little, I setup a CNAME record to map myapi.mydomain.com to sd098fs0f98s9f0s.execute-api.us-east-1.amazonaws.com.
Using the original URL, this simple Python is able to access the API perfectly:
import requests
r = requests.get(url='https://sd098fs0f98s9f0s.execute-api.us-east-1.amazonaws.com')
However, using the new URL:
import requests
r = requests.get(url='https://myapi.mydomain.com')
results in the error:
Traceback (most recent call last):
File ".env/lib/python3.7/site-packages/urllib3/connectionpool.py", line 603, in urlopen
chunked=chunked)
File ".env/lib/python3.7/site-packages/urllib3/connectionpool.py", line 344, in _make_request
self._validate_conn(conn)
File ".env/lib/python3.7/site-packages/urllib3/connectionpool.py", line 843, in _validate_conn
conn.connect()
File ".env/lib/python3.7/site-packages/urllib3/connection.py", line 370, in connect
ssl_context=context)
File ".env/lib/python3.7/site-packages/urllib3/util/ssl_.py", line 355, in ssl_wrap_socket
return context.wrap_socket(sock, server_hostname=server_hostname)
File "/usr/lib/python3.7/ssl.py", line 423, in wrap_socket
session=session
File "/usr/lib/python3.7/ssl.py", line 870, in _create
self.do_handshake()
File "/usr/lib/python3.7/ssl.py", line 1139, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1076)
What's causing this and how do I fix it?
I see that you're using https. The server certificate is issued to specific hostname (Common name attribute). This name has to match the address you're trying to access with HTTPS. If you added DNS CNAME you have to update the certificate. If I recall correctly you have to add CNAME as Alternative Subject Name attribute, so you'll need a new certificate.
The error "WRONG_VERSION_NUMBER" might be somewhat misleading. It means that the server presented a wrong TLS version. In the TLS handshake, client and the server negotiate the TLS version. If the server supports only 1.0 and your client accept only 1.2+ then "WRONG_VERSION_NUMBER" will appear. But it might also happen if the client gets some unexpected data, like a plain HTTP instead of HTTPS. To check what exactly was the unexpected data, you'll have to capture wireshark / tcpdump network traffic logs. I wasted a lot of time debugging wrong_version_number recently. Only after looking at wireshark logs it became clear that it was the China firewall, because we got HTTP Forbidden to the initial Client Hello.

Python urllib2 ssl certificate verify failed error

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

SSL: TLSV1_ALERT_INTERNAL_ERROR when connecting to APNS

My servers APNS notifications recently stopped working and after debugging I found that the SSL python library is throwing the following error when opening a socket:
File "/home/tam/repos/rest/api/tasks/notification_tasks.py", line 17, in apns_socket
self._apns_socket = apns.open_apns_socket()
File "/home/tam/repos/rest/api/utilities/apns.py", line 64, in open_apns_socket
return _apns_create_socket((settings.APNS_HOST, settings.APNS_PORT))
File "/home/tam/repos/rest/api/utilities/apns.py", line 49, in _apns_create_socket
sock.connect(address_tuple)
File "/usr/lib64/python3.5/ssl.py", line 1014, in connect
self._real_connect(addr, False)
File "/usr/lib64/python3.5/ssl.py", line 1005, in _real_connect
self.do_handshake()
File "/usr/lib64/python3.5/ssl.py", line 983, in do_handshake
self._sslobj.do_handshake()
File "/usr/lib64/python3.5/ssl.py", line 628, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: TLSV1_ALERT_INTERNAL_ERROR] tlsv1 alert internal error (_ssl.c:645)
Nothing has changed on the server codewise. I've checked APNS certificates (they haven't expired), and our SSL certificate (also not expired). I'm unsure what else could be causing this error at this point.
Here are the relavent lines of code from apns.py:
def open_apns_socket():
return _apns_create_socket((settings.APNS_HOST, settings.APNS_PORT))
def _apns_create_socket(address_tuple, is_dev=False):
certfile = settings.APS_CERTIFICATE
if not certfile:
raise ImproperlyConfigured('You need to set settings.APNS_CERTIFICATE')
try:
with open(certfile, "r") as f:
f.read()
except Exception as e:
raise ImproperlyConfigured("The APNS certificate file at %r is not readable: %s" % (certfile, e))
ca_certs = settings.APNS_CA_CERTIFICATES
sock = socket.socket()
sock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLSv1, certfile=certfile, ca_certs=ca_certs)
sock.connect(address_tuple)
return sock
APNS_HOST = "gateway.push.apple.com"
APNS_PORT = 2195
This error turned out to be caused by an expired apns certificate on the server.
The server certificate was different from what was in our version control and was not being updated by our deployment software.
Issuing a new certificate solved the problem.

Python ssl server reporting TLSV1_ALERT_UNKNOWN_CA

I have a Python SSL server that uses a self-signed certificate. I start my server like this:
httpd = BaseHTTPServer.HTTPServer(('', 443), MyHTTPHandler)
httpd.socket = ssl.wrap_socket (httpd.socket, certfile='server.pem', server_side=True, cert_reqs=0)
httpd.serve_forever()
I get the following error when I connect using Firefox:
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 51194)
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 295, in _handle_request_noblock
self.process_request(request, client_address)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 321, in process_request
self.finish_request(request, client_address)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 334, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 655, in __init__
self.handle()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/BaseHTTPServer.py", line 340, in handle
self.handle_one_request()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/BaseHTTPServer.py", line 310, in handle_one_request
self.raw_requestline = self.rfile.readline(65537)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 480, in readline
data = self._sock.recv(self._rbufsize)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 734, in recv
return self.read(buflen)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 621, in read
v = self._sslobj.read(len or 1024)
SSLError: [SSL: TLSV1_ALERT_UNKNOWN_CA] tlsv1 alert unknown ca (_ssl.c:1751)
----------------------------------------
I do not see this behavior with Chrome or another client. It only happens on the first connection (complaints about certificate) until I accept the certificate. The exception actually does not cause the program to quit.
Why am I getting an error on the server? How can I avoid the exception?
The TLv1 unknown CA alert is sent by some clients if they cannot verify the certificate of the server because it is signed by an unknown issuer CA. You can avoid this kind of exception if you use a certificate which is already trusted by the client or which can be validated against a root CA of the client (don't forget to include the chain certificates too).
If you cannot avoid this error (for instance because you are using a self-signed certificate) then you have to catch the exception and deal with it by closing the connection. You might need to do this by using handle_request to handle each request by itself and catch exceptions instead of using serve_forever.
I had the same error as you, even though I had a signed certificate from Sectigo. Turns out, you need a certificate chain rather than only your domain's certificate itself.
Source
While referring to this site, and the following video: https://www.youtube.com/watch?v=_YjX7rtiAsk
, I found that I need to create a new file called certificate-chain.pem, and manually/with the help of scripts concatenate (join) three certificates - domain certificate, CA certificate and the USERTrust certificate, one after the other.
Then, in the file you need, point to this certificate bundle/chain. This is a solution which I wept on for 7 hours.

How to connect with SSL to HTTPS server in Python 2.7.10+ and make certificate trusted?

I wan to connect to https server using ssl with certificate verification and host name validation (do not suggest to switch off verification since it working). How to do it with this code?
import ssl
import socket
context = ssl.create_default_context()
context.check_hostname = True
context.verify_mode = ssl.CERT_REQUIRED
conn = context.wrap_socket(socket.socket(socket.AF_INET),
server_hostname='adwords.google.com')
conn.connect(('adwords.google.com', 443))
Instead of connection there is exception:
Traceback (most recent call last):
File "C:/Users/Crezary Wagner/PycharmProjects/learn-adwords/src/03_ssl.py", line 16, in <module>
conn.connect(('adwords.google.com', 443))
File "C:\root\Python27\lib\ssl.py", line 844, in connect
self._real_connect(addr, False)
File "C:\root\Python27\lib\ssl.py", line 835, in _real_connect
self.do_handshake()
File "C:\root\Python27\lib\ssl.py", line 808, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
Process finished with exit code 1
It is clear for me that certificate can not be verified as trusted but how to make this certificate trusted in Python 2.7.10+ and connect?
I want setup it in system not in context if it possible.
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
response = requests.get('https://adwords.google.com', verify=False)
print response.content

Categories

Resources