sslutil: verify that wrap_socket really wrapped the socket
authorMads Kiilerich <mads@kiilerich.com>
Mon, 09 Jan 2012 14:43:15 +0100
changeset 15812 0cc4ad757c77
parent 15811 b9886dde3649
child 15813 3ae04eb5e38a
sslutil: verify that wrap_socket really wrapped the socket This works around that ssl.wrap_socket silently skips ssl negotiation on sockets that was connected but since then has been reset by the peer but not yet closed at the Python level. That leaves the socket in a state where .getpeercert() fails with an AttributeError on None. See http://bugs.python.org/issue13721 . A call to .cipher() is now used to verify that the wrapping really did succeed. Otherwise it aborts with "ssl connection failed".
mercurial/sslutil.py
--- a/mercurial/sslutil.py	Sun Jan 08 17:46:27 2012 +0100
+++ b/mercurial/sslutil.py	Mon Jan 09 14:43:15 2012 +0100
@@ -13,8 +13,16 @@
 try:
     # avoid using deprecated/broken FakeSocket in python 2.6
     import ssl
-    ssl_wrap_socket = ssl.wrap_socket
     CERT_REQUIRED = ssl.CERT_REQUIRED
+    def ssl_wrap_socket(sock, keyfile, certfile,
+                cert_reqs=ssl.CERT_NONE, ca_certs=None):
+        sslsocket = ssl.wrap_socket(sock, keyfile, certfile,
+                cert_reqs=cert_reqs, ca_certs=ca_certs)
+        # check if wrap_socket failed silently because socket had been closed
+        # - see http://bugs.python.org/issue13721
+        if not sslsocket.cipher():
+            raise util.Abort(_('ssl connection failed'))
+        return sslsocket
 except ImportError:
     CERT_REQUIRED = 2