classification
Title: ssl.get_server_certificate() does not work for IPv6 addresses
Type: enhancement Stage: resolved
Components: Library (Lib) Versions: Python 3.3
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: neologix, pitrou, pwouters, python-dev
Priority: normal Keywords: easy, patch

Created on 2011-04-09 21:18 by pwouters, last changed 2011-04-28 17:26 by pitrou. This issue is now closed.

Files
File name Uploaded Description Edit
ssl_ipv6.diff neologix, 2011-04-28 05:59 patch adding IPv6 support review
is_ipv6_enabled.diff neologix, 2011-04-28 06:00 IPV6_ENABLED support review
Messages (7)
msg133422 - (view) Author: Paul Wouters (pwouters) Date: 2011-04-09 21:18
ssl.get_server_certificate() does not work for IPv6 addresses:

>>> ssl.get_server_certificate( ("2001:888:2003:1004:c2ff:eeff:fe00:133",443))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/ssl.py", line 403, in get_server_certificate
    s.connect(addr)
  File "/usr/lib64/python2.7/ssl.py", line 292, in connect
    socket.connect(self, addr)
  File "/usr/lib64/python2.7/socket.py", line 222, in meth
    return getattr(self._sock,name)(*args)
socket.gaierror: [Errno -9] Address family for hostname not supported
msg133424 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-04-09 21:24
Confirmed. In the meantime, you can connect manually using socket.create_connection():

>>> import ssl, socket
>>> conn = socket.create_connection(("2001:888:2003:1004:c2ff:eeff:fe00:133", 443))
>>> sock = ssl.wrap_socket(conn)
>>> ssl.DER_cert_to_PEM_cert(sock.getpeercert(True))
'-----BEGIN CERTIFICATE-----\nMIID8DCCA1mgAwIBAgICVVUwDQYJKoZIhvcNAQEFBQAwgbExCzAJBgNVBAYTAi0t\nMRIwEAYDVQQIEwlTb21lU3RhdGUxETAPBgNVBAcTCFNvbWVDaXR5MRkwFwYDVQQK\nExBTb21lT3JnYW5pemF0aW9uMR8wHQYDVQQLExZTb21lT3JnYW5pemF0aW9uYWxV\nbml0MRkwFwYDVQQDExB3cC54ZWxlcmFuY2UubmV0MSQwIgYJKoZIhvcNAQkBFhVy\nb290QHdwLnhlbGVyYW5jZS5uZXQwHhcNMTEwNDA4MjM0MzE3WhcNMTIwNDA3MjM0\nMzE3WjCBsTELMAkGA1UEBhMCLS0xEjAQBgNVBAgTCVNvbWVTdGF0ZTERMA8GA1UE\nBxMIU29tZUNpdHkxGTAXBgNVBAoTEFNvbWVPcmdhbml6YXRpb24xHzAdBgNVBAsT\nFlNvbWVPcmdhbml6YXRpb25hbFVuaXQxGTAXBgNVBAMTEHdwLnhlbGVyYW5jZS5u\nZXQxJDAiBgkqhkiG9w0BCQEWFXJvb3RAd3AueGVsZXJhbmNlLm5ldDCBnzANBgkq\nhkiG9w0BAQEFAAOBjQAwgYkCgYEAsLBCgvH5g8ypkuufFQ55BFoWcjpAocsRV+jN\nW5zylXzM7F9/cMyTli757JGRdwL0l+bLPdojdYwKb6XjTWfJonqentBMG6iktLXZ\n66oUQl77UHOyL7XKynmO6wSGFd/qAoA8O5O9IRLPNcD4+NMTQjGSMFPvjnUnOSH2\n8nMVmZUCAwEAAaOCARMwggEPMB0GA1UdDgQWBBRFGGojncjKvGfxjgU8EOapc0Yi\nyjCB3wYDVR0jBIHXMIHUgBRFGGojncjKvGfxjgU8EOapc0YiyqGBt6SBtDCBsTEL\nMAkGA1UEBhMCLS0xEjAQBgNVBAgTCVNvbWVTdGF0ZTERMA8GA1UEBxMIU29tZUNp\ndHkxGTAXBgNVBAoTEFNvbWVPcmdhbml6YXRpb24xHzAdBgNVBAsTFlNvbWVPcmdh\nbml6YXRpb25hbFVuaXQxGTAXBgNVBAMTEHdwLnhlbGVyYW5jZS5uZXQxJDAiBgkq\nhkiG9w0BCQEWFXJvb3RAd3AueGVsZXJhbmNlLm5ldIICVVUwDAYDVR0TBAUwAwEB\n/zANBgkqhkiG9w0BAQUFAAOBgQCnLIAJ8ghuqUUiVOuq6tiRby65dh+7L1ApSp8G\nwusWF/rYugvqUxL1O1vatd1ptyXpoCLM0XzQ5sBtY0yS8IjMON9++Uu+u5IkQ+24\nkwvpgWp3lX8Zuxhbnmym/LGoJq4PgqXl1bsGJ+SIALQ31g7nrNE2HQz1IYRQEj/k\neG8F7g==\n-----END CERTIFICATE-----\n'
msg134618 - (view) Author: Charles-Fran├žois Natali (neologix) * (Python committer) Date: 2011-04-27 21:02
A patch is attached, along with corresponding test.
Notes:
- since I don't have an IPv6 internet connectivity, I could only test it locally
- I chose 'ipv6.google.com' as SSL server for the test. If it's a problem, I can change it for svn.python.org (it'll just take a couple more lines to make sure that we're using IPv6 and not IPv4)
- while writting the test, I needed a way to find whether IPv6 is supported on the current host (socket.has_ipv6 only tells you that the interpreter has been built with IPv6 support, not that the OS has an IPv6 stack enabled). So instead of rewritting what's already done in test_socket, I added a new is_ipv6_enabled function in Lib/test/support.py, and modified test_socket, test_ftplib and test_ssl to use it. This patch (is_ipv6_enabled.diff) must be applied before ssl_ipv6.diff.
msg134622 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-04-27 21:52
Hello,

> This patch (is_ipv6_enabled.diff) must be applied before
> ssl_ipv6.diff.

is_ipv6_enabled.diff is fine.
As for ssl_ipv6.diff, it fails on certificate verification:

======================================================================
ERROR: test_get_server_certificate (test.test_ssl.NetworkedTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/antoine/cpython/default/Lib/test/test_ssl.py", line 630, in test_get_server_certificate
    _test_get_server_certificate('ipv6.google.com', 443)
  File "/home/antoine/cpython/default/Lib/test/test_ssl.py", line 622, in _test_get_server_certificate
    pem = ssl.get_server_certificate((host, port), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
  File "/home/antoine/cpython/default/Lib/ssl.py", line 548, in get_server_certificate
    cert_reqs=cert_reqs, ca_certs=ca_certs)
  File "/home/antoine/cpython/default/Lib/ssl.py", line 498, in wrap_socket
    ciphers=ciphers)
  File "/home/antoine/cpython/default/Lib/ssl.py", line 255, in __init__
    raise x
  File "/home/antoine/cpython/default/Lib/ssl.py", line 251, in __init__
    self.do_handshake()
  File "/home/antoine/cpython/default/Lib/ssl.py", line 430, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [Errno 1] _ssl.c:389: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

I think you should simply use ca_certs=None when testing with the Google
host.
msg134648 - (view) Author: Charles-Fran├žois Natali (neologix) * (Python committer) Date: 2011-04-28 05:59
> As for ssl_ipv6.diff, it fails on certificate verification:

Of course.
The new version should fix this (tested on google.com).

> is_ipv6_enabled.diff is fine.

Since IPv6 capability is unlikely to change in the middle of a test, I replaced the function is_ipv6_enabled() by a boolean IPV6_ENABLED. That way, it's closer to socket.has_ipv6, and spares a socket creation/bind/close at each call.
msg134706 - (view) Author: Roundup Robot (python-dev) Date: 2011-04-28 17:24
New changeset 0518f32cb747 by Antoine Pitrou in branch 'default':
Issue #11811: Factor out detection of IPv6 support on the current host
http://hg.python.org/cpython/rev/0518f32cb747

New changeset d3166c359714 by Antoine Pitrou in branch 'default':
Issue #11811: ssl.get_server_certificate() is now IPv6-compatible.  Patch
http://hg.python.org/cpython/rev/d3166c359714
msg134707 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-04-28 17:26
Committed, thank you!
History
Date User Action Args
2011-04-28 17:26:48pitrousetstatus: open -> closed
resolution: fixed
messages: + msg134707

stage: needs patch -> resolved
2011-04-28 17:24:54python-devsetnosy: + python-dev
messages: + msg134706
2011-04-28 06:00:10neologixsetfiles: + is_ipv6_enabled.diff
2011-04-28 05:59:44neologixsetfiles: + ssl_ipv6.diff

messages: + msg134648
2011-04-28 05:56:10neologixsetfiles: - is_ipv6_enabled.diff
2011-04-28 05:55:57neologixsetfiles: - ssl_ipv6.diff
2011-04-27 21:52:10pitrousetmessages: + msg134622
2011-04-27 21:03:21neologixsetfiles: + is_ipv6_enabled.diff
2011-04-27 21:02:29neologixsetfiles: + ssl_ipv6.diff

nosy: + neologix
messages: + msg134618

keywords: + patch
2011-04-09 21:34:59pitrousetkeywords: + easy
components: + Library (Lib)
2011-04-09 21:24:13pitrousetversions: + Python 3.3, - Python 2.7
nosy: + pitrou

messages: + msg133424

stage: needs patch
2011-04-09 21:18:19pwouterscreate