Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Obtain Ceritificate Information from Invalid or Self-Signed Certificate in Python

580 views
Skip to first unread message

Kenneth Buckler

unread,
Apr 3, 2017, 12:15:51 PM4/3/17
to
I'm working on a Python 2.7.13 (Win x64) script to verify SSL certificates,
and alert for problems. Specifically, I'm looking to return the date the
cert expires or did expire. However, I'm running into an issue where the
script will return information only if the certificate is valid.

If the certificate is invalid, I receive a CERTIFICATE_VERIFY_FAILED SSL
error. Normally I would simply use a try/catch when the error is raised and
just alert that the cert is invalid, but the issue here is that the I need
the actual date the certificate expired, or in some cases the cert will be
a self-signed cert, which will be acceptable UNLESS the cert is expired.
I'm dealing with an organization that has thousands of certs, so adding
every single self signed cert to the cert store locally won't be an option.

Per https://docs.python.org/2/library/ssl.html I tried to use
conn._https_verify_certificates(enable=False) to disable certificate
validation, but get an error that the attribute _https_verify_certificates
doesn't exist.

Here is my code so far. I'm sure I'm missing something obvious. Surely
Python can pull the SSL certificate without validating it, right?

import socketimport ssl
def ssl_expiry_datetime(hostname):
ssl_date_fmt = r'%b %d %H:%M:%S %Y %Z'

context = ssl.create_default_context()
conn = context.wrap_socket(
socket.socket(socket.AF_INET),
server_hostname=hostname,
)
# 3 second timeout because Lambda has runtime limitations
conn.settimeout(3.0)
#conn._https_verify_certificates(enable=False)
conn.connect((hostname, 443))
ssl_info = conn.getpeercert()
# parse the string from the certificate into a Python datetime object
return ['notAfter']

myhost = 'www.google.com'
print ssl_expiry_datetime(myhost)

Thanks!

Ken

dieter

unread,
Apr 4, 2017, 1:24:04 AM4/4/17
to
Kenneth Buckler <kenneth...@gmail.com> writes:
> I'm working on a Python 2.7.13 (Win x64) script to verify SSL certificates,
> and alert for problems. Specifically, I'm looking to return the date the
> cert expires or did expire. However, I'm running into an issue where the
> script will return information only if the certificate is valid.

You may need to tell the Python socket library that you are
ready to accept any certificate - even expired ones.

I see below, that you already have tried that
("conn._https_verify_certificates(enable=False)") but it failed.
The reason: "_https_verify_certificates" is a function of the "ssl"
module, not a method of "SSLSocket" instances.
It is used to switch (globally) the behavior for verifying certificates,
not locally for a specific "SSLSocket".

Given the architecture of the "ssl" module (with the component
classes "socket", "SSLContext" and "SSLSocket"), the most likely
place to control the certificate verification is the "SSLContext".
And indeed, it has an attribute "verify_mode" to control this behaviour.


Likely, there is an alternative to disable certificate
verification in your case: the "ssl" module has the function
"get_server_certificate"; you could try to perform a normal
ssl connection and if this fails due to certificate problems,
you could fetch the certificate with the above function and analyse it.

> ...
> Per https://docs.python.org/2/library/ssl.html I tried to use
> conn._https_verify_certificates(enable=False) to disable certificate
> validation, but get an error that the attribute _https_verify_certificates
> doesn't exist.
> ...

0 new messages