[PATCH 1 of 7 V5] sslutil: implement wrapserversocket()
Gregory Szorc
gregory.szorc at gmail.com
Fri Jul 15 17:13:59 UTC 2016
# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1468552459 25200
# Thu Jul 14 20:14:19 2016 -0700
# Node ID a5eec9ca2cf0945fc972e063354fd972563a66a5
# Parent 99d9188b9d45039a06c65fa7dda36a12d08369c2
sslutil: implement wrapserversocket()
wrapsocket() is heavily tailored towards client use. In preparation
for converting the built-in server to use sslutil (as opposed to
the ssl module directly), we add wrapserversocket() for wrapping
a socket to be used on servers.
diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
--- a/mercurial/sslutil.py
+++ b/mercurial/sslutil.py
@@ -330,16 +330,62 @@ def wrapsocket(sock, keyfile, certfile,
'caloaded': caloaded,
'hostname': serverhostname,
'settings': settings,
'ui': ui,
}
return sslsocket
+def wrapserversocket(sock, ui, certfile=None, keyfile=None, cafile=None,
+ requireclientcert=False):
+ """Wrap a socket for use by servers.
+
+ ``certfile`` and ``keyfile`` specify the files containing the certificate's
+ public and private keys, respectively. Both keys can be defined in the same
+ file via ``certfile`` (the private key must come first in the file).
+
+ ``cafile`` defines the path to certificate authorities.
+
+ ``requireclientcert`` specifies whether to require client certificates.
+
+ Typically ``cafile`` is only defined if ``requireclientcert`` is true.
+ """
+ if modernssl:
+ # We /could/ use create_default_context() here since it doesn't load
+ # CAs when configured for client auth.
+ sslcontext = SSLContext(ssl.PROTOCOL_SSLv23)
+ # SSLv2 and SSLv3 are broken. Ban them outright.
+ sslcontext.options |= OP_NO_SSLv2 | OP_NO_SSLv3
+ # Prevent CRIME
+ sslcontext.options |= getattr(ssl, 'OP_NO_COMPRESSION', 0)
+ # Improve forward secrecy.
+ sslcontext.options |= getattr(ssl, 'OP_SINGLE_DH_USE', 0)
+ sslcontext.options |= getattr(ssl, 'OP_SINGLE_ECDH_USE', 0)
+
+ # Use the list of more secure ciphers if found in the ssl module.
+ if util.safehasattr(ssl, '_RESTRICTED_SERVER_CIPHERS'):
+ sslcontext.options |= getattr(ssl, 'OP_CIPHER_SERVER_PREFERENCE', 0)
+ sslcontext.set_ciphers(ssl._RESTRICTED_SERVER_CIPHERS)
+ else:
+ sslcontext = SSLContext(ssl.PROTOCOL_TLSv1)
+
+ if requireclientcert:
+ sslcontext.verify_mode = ssl.CERT_REQUIRED
+ else:
+ sslcontext.verify_mode = ssl.CERT_NONE
+
+ if certfile or keyfile:
+ sslcontext.load_cert_chain(certfile=certfile, keyfile=keyfile)
+
+ if cafile:
+ sslcontext.load_verify_locations(cafile=cafile)
+
+ return sslcontext.wrap_socket(sock, server_side=True)
+
class wildcarderror(Exception):
"""Represents an error parsing wildcards in DNS name."""
def _dnsnamematch(dn, hostname, maxwildcards=1):
"""Match DNS names according RFC 6125 section 6.4.3.
This code is effectively copied from CPython's ssl._dnsname_match.
More information about the Mercurial-devel
mailing list