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".
--- 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