You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
SSLContext.wrap_socket sends SNI Extension when server_hostname is IP #76366
The current implementation of SSLContext.wrap_socket blindly sends whatever is passed in server_hostname in the SNI extension, assuming it's a DNS hostname. RFC6066 describes the SNI TLS extension, and specifically states that 'Literal IPv4 and IPv6 addresses are not permitted in "HostName".' The RFC makes no recommendation on how a server implementation that violates this requirement should behave; Microsoft's kernel HTTP listener (http.sys) chooses to abort the connection if SNI has been enabled. In the http.sys case, SNI is a global setting, currently off by default, but if any registered listener has SNI enabled, the connection abort behavior applies to all listeners.
SSLContext.wrap_socket() should determine whether server_hostname is an IP address before including the SNI extension.
I've submitted a PR to work around this issue in urllib3 (urllib3/urllib3#1287) in the meantime, but would be good to get this fixed, especially if Microsoft decides to enable SNI by default at some point.
2.7 and 3.6 are a bit tricky. There is no platform-compatible way to detect if a string is an IP address. inet_pton() is not available on Windows. I cannot use the OpenSSL parser because it is only available in 1.0.2+. 2.7 and 3.6 still support 0.9.8.
The code works on all platforms with OpenSSL >= 1.0.2. OpenSSL 1.0.1, 0.9.8 and earlier are no longer supported by upstream. Anybody with even marginal interest in secure TLS/SSL should update. Python.org's Windows and macOS binaries are good.
The inet_pton() code in my patch is for those poor souls that are stuck with RHEL 6, CentOS 6, or Ubuntu 14.04. RHEL 7, CentOS 7, and Ubuntu 16.04 have OpenSSL 1.0.2.
The IP address module is slow and hard to use from C code.
New changeset a5c9112 by Christian Heimes (Miss Islington (bot)) in branch '2.7':
[2.7] bpo-32185: Don't send IP in SNI TLS extension (GH-5865) (bpo-5871) a5c9112
The issue has been fixed in 2.7, 3.6-3.8 for OpenSSL >= 1.0.2 or platforms with inet_pton. I didn't bother to fix platforms without inet_pton since OpenSSL 1.0.1 and earlier are no longer support any way.
Activity
nitzmahone commentedon Nov 30, 2017
The current implementation of SSLContext.wrap_socket blindly sends whatever is passed in server_hostname in the SNI extension, assuming it's a DNS hostname. RFC6066 describes the SNI TLS extension, and specifically states that 'Literal IPv4 and IPv6 addresses are not permitted in "HostName".' The RFC makes no recommendation on how a server implementation that violates this requirement should behave; Microsoft's kernel HTTP listener (http.sys) chooses to abort the connection if SNI has been enabled. In the http.sys case, SNI is a global setting, currently off by default, but if any registered listener has SNI enabled, the connection abort behavior applies to all listeners.
SSLContext.wrap_socket() should determine whether server_hostname is an IP address before including the SNI extension.
I've submitted a PR to work around this issue in urllib3 (urllib3/urllib3#1287) in the meantime, but would be good to get this fixed, especially if Microsoft decides to enable SNI by default at some point.
tiran commentedon Nov 30, 2017
Thanks!
3.4 and 3.5 are out of scope. They only receive security fixes.
For 3.7 master...tiran:openssl_check_hostname will take care of the issue
2.7 and 3.6 are a bit tricky. There is no platform-compatible way to detect if a string is an IP address. inet_pton() is not available on Windows. I cannot use the OpenSSL parser because it is only available in 1.0.2+. 2.7 and 3.6 still support 0.9.8.
pitrou commentedon Dec 20, 2017
Actually, you could use the ipaddress module.
pitrou commentedon Dec 20, 2017
By the way, Windows nowadays has inet_pton():
https://msdn.microsoft.com/en-us/library/windows/desktop/cc805844(v=vs.85).aspx
Are there other platforms without it? inet_pton() is part of POSIX.
tiran commentedon Dec 20, 2017
The code works on all platforms with OpenSSL >= 1.0.2. OpenSSL 1.0.1, 0.9.8 and earlier are no longer supported by upstream. Anybody with even marginal interest in secure TLS/SSL should update. Python.org's Windows and macOS binaries are good.
The inet_pton() code in my patch is for those poor souls that are stuck with RHEL 6, CentOS 6, or Ubuntu 14.04. RHEL 7, CentOS 7, and Ubuntu 16.04 have OpenSSL 1.0.2.
The IP address module is slow and hard to use from C code.
tiran commentedon Dec 20, 2017
PS: With OpenSSL >= 1.0.2, inet_pton() is not required.
tiran commentedon Feb 25, 2018
New changeset e9370a4 by Christian Heimes in branch '3.6':
bpo-32185: Don't send IP in SNI TLS extension (bpo-5865)
e9370a4
tiran commentedon Feb 25, 2018
New changeset a5c9112 by Christian Heimes (Miss Islington (bot)) in branch '2.7':
[2.7] bpo-32185: Don't send IP in SNI TLS extension (GH-5865) (bpo-5871)
a5c9112
tiran commentedon Feb 25, 2018
The issue has been fixed in 2.7, 3.6-3.8 for OpenSSL >= 1.0.2 or platforms with inet_pton. I didn't bother to fix platforms without inet_pton since OpenSSL 1.0.1 and earlier are no longer support any way.