changeset 15812:0cc4ad757c77

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".
author Mads Kiilerich <mads@kiilerich.com>
date Mon, 09 Jan 2012 14:43:15 +0100
parents b9886dde3649
children 3ae04eb5e38a
files mercurial/sslutil.py
diffstat 1 files changed, 9 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- 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