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.
Related
I want to connect to an FTPS server containing some not trusted certificate. When I use simple:
lftp -u user hostname
then after dir command there's an error:
ls: Fatal error: Certificate verification: Not trusted
The problem can be solved in lftp by executing the following command:
lftp -e "set ssl:verify-certificate false" -u user hostname
I'm trying to make the same connection in Python, using for example ftplib module:
import ftplib
ftp = ftplib.FTP_TLS()
ftp.connect(hostname, port)
ftp.login(username, password)
ftp.prot_p()
ftp.dir()
But it raises OSError exception:
Traceback (most recent call last):
File "/usr/lib/python3.8/code.py", line 90, in runcode
exec(code, self.locals)
File "<console>", line 1, in <module>
File "/usr/lib/python3.8/ftplib.py", line 558, in dir
self.retrlines(cmd, func)
File "/usr/lib/python3.8/ftplib.py", line 451, in retrlines
with self.transfercmd(cmd) as conn, \
File "/usr/lib/python3.8/ftplib.py", line 382, in transfercmd
return self.ntransfercmd(cmd, rest)[0]
File "/usr/lib/python3.8/ftplib.py", line 783, in ntransfercmd
conn = self.context.wrap_socket(conn,
File "/usr/lib/python3.8/ssl.py", line 500, in wrap_socket
return self.sslsocket_class._create(
File "/usr/lib/python3.8/ssl.py", line 1040, in _create
self.do_handshake()
File "/usr/lib/python3.8/ssl.py", line 1309, in do_handshake
self._sslobj.do_handshake()
OSError: [Errno 0] Error
The problem seems to be similar to te OSError during authenticating to an ftps server with ftplib.FTP_TLS so I also tried to use some other context, like:
import ssl
ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1_2)
ftp = FTP_TLS(context=ctx)
or
ctx = ssl.ssl._create_unverified_context(ssl.PROTOCOL_TLSv1_2)
ftp = FTP_TLS(context=ctx)
But the error is still the same. Any ideas how to disable certificate verification?
It cannot be a certificate problem, as you are getting error only at dir. The connect succeeds.
You get a TLS error when opening FTP data connection. It quite possible that the root cause is that the server require TLS session resumption.
See FTPS with Python ftplib - Session reuse required.
I started to learn python and sockets those days and I made a simple client-server app just to make some tests and it works fine with Python 3.6, but gives me error in the newest version.
Server.py
import socket, ssl
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.verify_mode = ssl.CERT_REQUIRED
context.load_cert_chain(certfile="SSL/server.crt", keyfile="SSL/server.key")
context.load_verify_locations("SSL/client.crt")
bindsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
bindsocket.bind(("127.0.0.1", 65405))
bindsocket.listen(10)
while True:
newsocket, fromaddr = bindsocket.accept()
print(newsocket)
connstream = context.wrap_socket(newsocket, server_side=True)
try:
print(connstream.getpeercert())
finally:
connstream.shutdown(socket.SHUT_RDWR)
connstream.close()
Client.py
import ssl, socket
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
context.load_cert_chain(certfile="SSL/client.crt", keyfile="SSL/client.key")
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
context.load_verify_locations("SSL/server.crt")
conn = context.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), server_hostname="127.0.0.1")
try:
conn.connect(("127.0.0.1", 65405))
conn.sendall(b"aff")
print(conn.getpeercert())
except:
print("não")
finally:
conn.shutdown(socket.SHUT_RDWR)
conn.close()
Error
Traceback (most recent call last):
File "C:/Users/nicol/Desktop/Kyuu/Bot/Kaori/Python/server.py", line 15, in <module>
connstream = context.wrap_socket(newsocket, server_side=True)
File "C:\Users\nicol\AppData\Local\Programs\Python\Python37\lib\ssl.py", line 412, in wrap_socket
session=session
File "C:\Users\nicol\AppData\Local\Programs\Python\Python37\lib\ssl.py", line 853, in _create
self.do_handshake()
File "C:\Users\nicol\AppData\Local\Programs\Python\Python37\lib\ssl.py", line 1117, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: SSLV3_ALERT_BAD_CERTIFICATE] sslv3 alert bad certificate (_ssl.c:1056)
Edit 1
I tried to use ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) and ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT), but I got the same error.
Edit 2
When I use the command "s_client -connect 127.0.0.1:65405 -cert client.pem -key client.pem -CAfile server.crt" in the OpenSSL it works fine
Many old protocols are disabled since Python v3.6, namely
This might happen due server and client run on different python versions (3.6 vs 3.7).
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.
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.
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