mercurial/sslutil.py
changeset 29259 ec247e8595f9
parent 29258 6315c1e14f75
child 29260 70bc9912d83d
equal deleted inserted replaced
29258:6315c1e14f75 29259:ec247e8595f9
   112     Returns a dict of settings relevant to that hostname.
   112     Returns a dict of settings relevant to that hostname.
   113     """
   113     """
   114     s = {
   114     s = {
   115         # List of 2-tuple of (hash algorithm, hash).
   115         # List of 2-tuple of (hash algorithm, hash).
   116         'certfingerprints': [],
   116         'certfingerprints': [],
       
   117         # ssl.CERT_* constant used by SSLContext.verify_mode.
       
   118         'verifymode': None,
   117     }
   119     }
   118 
   120 
   119     # Fingerprints from [hostfingerprints] are always SHA-1.
   121     # Fingerprints from [hostfingerprints] are always SHA-1.
   120     for fingerprint in ui.configlist('hostfingerprints', hostname, []):
   122     for fingerprint in ui.configlist('hostfingerprints', hostname, []):
   121         fingerprint = fingerprint.replace(':', '').lower()
   123         fingerprint = fingerprint.replace(':', '').lower()
   122         s['certfingerprints'].append(('sha1', fingerprint))
   124         s['certfingerprints'].append(('sha1', fingerprint))
   123 
   125 
       
   126     # If a host cert fingerprint is defined, it is the only thing that
       
   127     # matters. No need to validate CA certs.
       
   128     if s['certfingerprints']:
       
   129         s['verifymode'] = ssl.CERT_NONE
       
   130 
       
   131     # If --insecure is used, don't take CAs into consideration.
       
   132     elif ui.insecureconnections:
       
   133         s['verifymode'] = ssl.CERT_NONE
       
   134 
       
   135     # TODO assert verifymode is not None once we integrate cacert
       
   136     # checking in this function.
       
   137 
   124     return s
   138     return s
   125 
   139 
   126 def _determinecertoptions(ui, host):
   140 def _determinecertoptions(ui, settings):
   127     """Determine certificate options for a connections.
   141     """Determine certificate options for a connections.
   128 
   142 
   129     Returns a tuple of (cert_reqs, ca_certs).
   143     Returns a tuple of (cert_reqs, ca_certs).
   130     """
   144     """
   131     # If a host key fingerprint is on file, it is the only thing that matters
   145     if settings['verifymode'] == ssl.CERT_NONE:
   132     # and CA certs don't come into play.
       
   133     hostfingerprint = ui.config('hostfingerprints', host)
       
   134     if hostfingerprint:
       
   135         return ssl.CERT_NONE, None
       
   136 
       
   137     # The code below sets up CA verification arguments. If --insecure is
       
   138     # used, we don't take CAs into consideration, so return early.
       
   139     if ui.insecureconnections:
       
   140         return ssl.CERT_NONE, None
   146         return ssl.CERT_NONE, None
   141 
   147 
   142     cacerts = ui.config('web', 'cacerts')
   148     cacerts = ui.config('web', 'cacerts')
   143 
   149 
   144     # If a value is set in the config, validate against a path and load
   150     # If a value is set in the config, validate against a path and load
   179       to use.
   185       to use.
   180     """
   186     """
   181     if not serverhostname:
   187     if not serverhostname:
   182         raise error.Abort('serverhostname argument is required')
   188         raise error.Abort('serverhostname argument is required')
   183 
   189 
   184     cert_reqs, ca_certs = _determinecertoptions(ui, serverhostname)
   190     settings = _hostsettings(ui, serverhostname)
       
   191     cert_reqs, ca_certs = _determinecertoptions(ui, settings)
   185 
   192 
   186     # Despite its name, PROTOCOL_SSLv23 selects the highest protocol
   193     # Despite its name, PROTOCOL_SSLv23 selects the highest protocol
   187     # that both ends support, including TLS protocols. On legacy stacks,
   194     # that both ends support, including TLS protocols. On legacy stacks,
   188     # the highest it likely goes in TLS 1.0. On modern stacks, it can
   195     # the highest it likely goes in TLS 1.0. On modern stacks, it can
   189     # support TLS 1.2.
   196     # support TLS 1.2.
   232         raise error.Abort(_('ssl connection failed'))
   239         raise error.Abort(_('ssl connection failed'))
   233 
   240 
   234     sslsocket._hgstate = {
   241     sslsocket._hgstate = {
   235         'caloaded': caloaded,
   242         'caloaded': caloaded,
   236         'hostname': serverhostname,
   243         'hostname': serverhostname,
   237         'settings': _hostsettings(ui, serverhostname),
   244         'settings': settings,
   238         'ui': ui,
   245         'ui': ui,
   239     }
   246     }
   240 
   247 
   241     return sslsocket
   248     return sslsocket
   242 
   249