Reputation: 11324
I want to check if an hostname and a port according to a SSL certificate. I created this function :
@staticmethod
def common_name_check(hostname, port):
try:
ctx = ssl.create_default_context()
s = ctx.wrap_socket(socket.socket(), server_hostname=hostname)
s.connect((hostname, int(port)))
cert = s.getpeercert()
ssl.match_hostname(cert, hostname)
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, fname, exc_tb.tb_lineno)
return False
else:
return True
My problem is : When a certificate is expired the verification failed. But the exception is ambiguous :
<class 'ssl.SSLError'>
I can't know if error is due to certificate expired or bad common name
How can I only check if hostname/port is valid for certificate ?
Upvotes: 3
Views: 5502
Reputation: 1
I'm using something like this. certfile is PEM format. Not quite the same, as I'm comparing against a certificate file..
# Check if the certificate commonName is a match to MYSTRING
certpath = 'c:\cert.cer'
from cryptography import x509
from cryptography.hazmat.backends import default_backend
cfile = open(certpath,"r")
cert_file = cfile.read()
cert = x509.load_pem_x509_certificate(cert_file, default_backend())
for fields in cert.subject:
current = str(fields.oid)
if "commonName" in current:
if fields.value == MYSTRING:
print 'certificate (' + fields.value + ') matches'
else:
print 'certificate (' + fields.value + ') does NOT match'
Upvotes: 0
Reputation: 1205
Exactly. SSL Error is too generic. I struggled with this too. So you might want to checkout this link.
Verifying SSL certificates in python
Here is a code only answer.
from OpenSSL import SSL
from socket import socket
context = SSL.Context(SSL.TLSv1_METHOD) # Use TLS Method
context.set_options(SSL.OP_NO_SSLv2) # Don't accept SSLv2
context.set_verify(SSL.VERIFY_NONE, callback)
context.load_verify_locations(ca_file, ca_path)
host = "google.com"
port = 443 #ssl
sock = socket()
ssl_sock = SSL.Connection(context, sock)
ssl_sock.connect((host, port))
ssl_sock.do_handshake()
def callback(self, conn, certificate, err, depth, valid):
# err here is the error code ([List of error codes and what they mean][2].
if err == 62:
print("HOSTNAME MISMATCH!!!")
Upvotes: 1