New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ssl.get_server_certificate should use SNI #80257
Comments
The ssl.get_server_certificate function doesn't send SNI information causing an wrong certificate to be sent back by the server (or connection close in some cases). This can be seen when trying to use get_server_certificate against a site behind cloudflare. An example is provided below: $ python3 -V
Python 3.7.2
$ python3 -c "import ssl; print(ssl.get_server_certificate(('www.mx.com',443)))" | openssl x509 -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
89:2a:bc:df:8a:f3:d6:f6:ae:c5:18:5a:78:ec:39:6e
Signature Algorithm: ecdsa-with-SHA256
Issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO ECC Domain Validation Secure Server CA 2
Validity
Not Before: Dec 19 00:00:00 2018 GMT
Not After : Jun 27 23:59:59 2019 GMT
Subject: OU=Domain Control Validated, OU=PositiveSSL Multi-Domain, CN=ssl803013.cloudflaressl.com
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:ff:c1:c3:f1:c0:8a:08:84:ad:e4:25:f6:c3:03:
1f:26:0a:b4:85:e0:65:0e:f5:8b:13:1e:21:b2:54:
94:8c:f3:ce:98:eb:cf:ff:ff:1d:3a:03:22:b1:7c:
5f:13:e5:09:1f:77:b0:e8:ac:bf:e6:6c:ea:cb:57:
df:e1:c8:14:da
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Authority Key Identifier:
keyid:40:09:61:67:F0:BC:83:71:4F:DE:12:08:2C:6F:D4:D4:2B:76:3D:96
.R....d6.......g..P......F0D. ...0....J|..2I..}%.Q.P...Z....g.. ......e....j...Y^.Ti^..........].w.t~..1.3..!..%OBp...^B ..75y..{.V...g..Pv.....H0F.!..1#I..\.....#2...$...X.... As you can see the certificate returned has CN=ssl803013.cloudflaressl.com, the proper certificate has CN=www.mx.com as you can compare with openssl output when SNI is sent: $ openssl s_client -connect www.mx.com:443 -servername www.mx.com
CONNECTED(00000006)
depth=2 C = IE, O = Baltimore, OU = CyberTrust, CN = Baltimore CyberTrust Root
verify return:1
depth=1 C = US, ST = CA, L = San Francisco, O = "CloudFlare, Inc.", CN = CloudFlare Inc ECC CA-2
verify return:1
depth=0 C = US, ST = CA, L = San Francisco, O = "CloudFlare, Inc.", CN = www.mx.com
verify return:1 Certificate chain The problem lies within Lib/ssl.py get_server_certificate function: def get_server_certificate(addr, ssl_version=PROTOCOL_TLS, ca_certs=None):
"""Retrieve the certificate from the server at the specified address,
and return it as a PEM-encoded string.
If 'ca_certs' is specified, validate the server cert against it.
If 'ssl_version' is specified, use it in the connection attempt."""
The wrap_socket function should be called with server_hostname parameter to send the SNI information. |
Thanks! |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: