Wednesday, 2 October 2013

OpenSSL s_client and Python SSL module disagree on the certificate for a hostname

OpenSSL s_client and Python SSL module disagree on the certificate for a
hostname

I'm having an odd problem. It looks like OpenSSL's "s_client" tool doesn't
like my AppEngine application's SSL certificate to the point of not even
acknowledging it ("no peer certificate is available"), but Python's SSL
module reports the issuer, date range, serial number, subjects, etc.., as
if there was no problem at all.
I'd assume that there is some subtle misconfiguration with my SSL
certificate, but, as AppEngine provides a very simple wizard for uploading
certificates, saying that there is a misconfiguration is to say that
Google's functionality is broken... Which I doubt is the case.
I'd love some insight into this if someone else has experienced it.
s_client:
openssl s_client -connect www.abc.com:443
s_client output:
CONNECTED(00000003)
3073997000:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake
failure:s23_lib.c:177:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 225 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---
Python 3.3 test script:
import socket
from ssl import wrap_socket, CERT_NONE, PROTOCOL_SSLv23
from ssl import SSLContext # Modern SSL?
from ssl import HAS_SNI # Has SNI?
from pprint import pprint
# Stole this from "requests" package.
def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None,
ca_certs=None, server_hostname=None,
ssl_version=None):
context = SSLContext(ssl_version)
context.verify_mode = cert_reqs
if ca_certs:
try:
context.load_verify_locations(ca_certs)
# Py32 raises IOError
# Py33 raises FileNotFoundError
except Exception as e: # Reraise as SSLError
raise SSLError(e)
if certfile:
# FIXME: This block needs a test.
context.load_cert_chain(certfile, keyfile)
if HAS_SNI: # Platform-specific: OpenSSL with enabled SNI
return context.wrap_socket(sock, server_hostname=server_hostname)
return context.wrap_socket(sock)
hostname = 'www.abc.com'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((hostname, 443))
sslSocket = ssl_wrap_socket(s,
ssl_version=2,
cert_reqs=2,
ca_certs='/usr/local/lib/python3.3/dist-packages/requests/cacert.pem',
server_hostname=hostname)
pprint(sslSocket.getpeercert())
s.close()
Test script output:
{'issuer': ((('countryName', 'US'),),
(('organizationName', 'GeoTrust, Inc.'),),
(('commonName', 'RapidSSL CA'),)),
'notAfter': 'Oct 2 20:01:20 2014 GMT',
'notBefore': 'Sep 29 02:17:38 2013 GMT',
'serialNumber': '0E45AF',
'subject': ((('serialNumber', 'd3tVuFeMunyn/gFFucMFHgZ2iBihdthR'),),
(('organizationalUnitName', 'GT22884059'),),
(('organizationalUnitName',
'See www.rapidssl.com/resources/cps (c)13'),),
(('organizationalUnitName',
'Domain Control Validated - RapidSSL(R)'),),
(('commonName', 'www.abc.com'),)),
'subjectAltName': (('DNS', 'www.abc.com'),
('DNS', 'abc.com')),
'version': 3}

No comments:

Post a Comment