mercurial/sslutil.py
changeset 29507 97dcdcf75f4f
parent 29501 be68a4445041
child 29508 d65ec41b6384
equal deleted inserted replaced
29506:2550604f5ec7 29507:97dcdcf75f4f
   124         'cafile': None,
   124         'cafile': None,
   125         # Whether certificate verification should be disabled.
   125         # Whether certificate verification should be disabled.
   126         'disablecertverification': False,
   126         'disablecertverification': False,
   127         # Whether the legacy [hostfingerprints] section has data for this host.
   127         # Whether the legacy [hostfingerprints] section has data for this host.
   128         'legacyfingerprint': False,
   128         'legacyfingerprint': False,
       
   129         # PROTOCOL_* constant to use for SSLContext.__init__.
       
   130         'protocol': None,
   129         # ssl.CERT_* constant used by SSLContext.verify_mode.
   131         # ssl.CERT_* constant used by SSLContext.verify_mode.
   130         'verifymode': None,
   132         'verifymode': None,
   131     }
   133     }
       
   134 
       
   135     # Despite its name, PROTOCOL_SSLv23 selects the highest protocol
       
   136     # that both ends support, including TLS protocols. On legacy stacks,
       
   137     # the highest it likely goes in TLS 1.0. On modern stacks, it can
       
   138     # support TLS 1.2.
       
   139     #
       
   140     # The PROTOCOL_TLSv* constants select a specific TLS version
       
   141     # only (as opposed to multiple versions). So the method for
       
   142     # supporting multiple TLS versions is to use PROTOCOL_SSLv23 and
       
   143     # disable protocols via SSLContext.options and OP_NO_* constants.
       
   144     # However, SSLContext.options doesn't work unless we have the
       
   145     # full/real SSLContext available to us.
       
   146     if modernssl:
       
   147         s['protocol'] = ssl.PROTOCOL_SSLv23
       
   148     else:
       
   149         s['protocol'] = ssl.PROTOCOL_TLSv1
   132 
   150 
   133     # Look for fingerprints in [hostsecurity] section. Value is a list
   151     # Look for fingerprints in [hostsecurity] section. Value is a list
   134     # of <alg>:<fingerprint> strings.
   152     # of <alg>:<fingerprint> strings.
   135     fingerprints = ui.configlist('hostsecurity', '%s:fingerprints' % hostname,
   153     fingerprints = ui.configlist('hostsecurity', '%s:fingerprints' % hostname,
   136                                  [])
   154                                  [])
   213             # is insecure. We allow the connection and abort during
   231             # is insecure. We allow the connection and abort during
   214             # validation (once we have the fingerprint to print to the
   232             # validation (once we have the fingerprint to print to the
   215             # user).
   233             # user).
   216             s['verifymode'] = ssl.CERT_NONE
   234             s['verifymode'] = ssl.CERT_NONE
   217 
   235 
       
   236     assert s['protocol'] is not None
   218     assert s['verifymode'] is not None
   237     assert s['verifymode'] is not None
   219 
   238 
   220     return s
   239     return s
   221 
   240 
   222 def wrapsocket(sock, keyfile, certfile, ui, serverhostname=None):
   241 def wrapsocket(sock, keyfile, certfile, ui, serverhostname=None):
   235     if not serverhostname:
   254     if not serverhostname:
   236         raise error.Abort(_('serverhostname argument is required'))
   255         raise error.Abort(_('serverhostname argument is required'))
   237 
   256 
   238     settings = _hostsettings(ui, serverhostname)
   257     settings = _hostsettings(ui, serverhostname)
   239 
   258 
   240     # Despite its name, PROTOCOL_SSLv23 selects the highest protocol
   259     # TODO use ssl.create_default_context() on modernssl.
   241     # that both ends support, including TLS protocols. On legacy stacks,
   260     sslcontext = SSLContext(settings['protocol'])
   242     # the highest it likely goes in TLS 1.0. On modern stacks, it can
   261 
   243     # support TLS 1.2.
       
   244     #
       
   245     # The PROTOCOL_TLSv* constants select a specific TLS version
       
   246     # only (as opposed to multiple versions). So the method for
       
   247     # supporting multiple TLS versions is to use PROTOCOL_SSLv23 and
       
   248     # disable protocols via SSLContext.options and OP_NO_* constants.
       
   249     # However, SSLContext.options doesn't work unless we have the
       
   250     # full/real SSLContext available to us.
       
   251     #
       
   252     # SSLv2 and SSLv3 are broken. We ban them outright.
   262     # SSLv2 and SSLv3 are broken. We ban them outright.
   253     if modernssl:
       
   254         protocol = ssl.PROTOCOL_SSLv23
       
   255     else:
       
   256         protocol = ssl.PROTOCOL_TLSv1
       
   257 
       
   258     # TODO use ssl.create_default_context() on modernssl.
       
   259     sslcontext = SSLContext(protocol)
       
   260 
       
   261     # This is a no-op on old Python.
   263     # This is a no-op on old Python.
   262     sslcontext.options |= OP_NO_SSLv2 | OP_NO_SSLv3
   264     sslcontext.options |= OP_NO_SSLv2 | OP_NO_SSLv3
   263 
   265 
   264     # This still works on our fake SSLContext.
   266     # This still works on our fake SSLContext.
   265     sslcontext.verify_mode = settings['verifymode']
   267     sslcontext.verify_mode = settings['verifymode']