mercurial/sslutil.py
author Augie Fackler <augie@google.com>
Sun, 04 Mar 2018 21:16:36 -0500
changeset 36747 4c71a26a4009
parent 36746 25798cf7dc9d
child 37084 f0b6fbea00cf
permissions -rw-r--r--
sslutil: some more forcebytes() on some exception messages At this point, test-https.t no longer dumps tracebacks everywhere. Instead, we get some results that look like we're not adequately finding things in hg's configuration, which should be manageable (if somewhat annoying to find and fix.) Differential Revision: https://phab.mercurial-scm.org/D2690
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
     1
# sslutil.py - SSL handling for mercurial
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
     2
#
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
     3
# Copyright 2005, 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
     4
# Copyright 2006, 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br>
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
     5
# Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
     6
#
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
     7
# This software may be used and distributed according to the terms of the
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
     8
# GNU General Public License version 2 or any later version.
25977
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25432
diff changeset
     9
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25432
diff changeset
    10
from __future__ import absolute_import
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    11
29341
0d83ad967bf8 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents: 29334
diff changeset
    12
import hashlib
25977
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25432
diff changeset
    13
import os
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
    14
import re
25977
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25432
diff changeset
    15
import ssl
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25432
diff changeset
    16
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25432
diff changeset
    17
from .i18n import _
28577
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28525
diff changeset
    18
from . import (
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28525
diff changeset
    19
    error,
35582
72b91f905065 py3: use node.hex(h.digest()) instead of h.hexdigest()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35369
diff changeset
    20
    node,
30639
d524c88511a7 py3: replace os.name with pycompat.osname (part 1 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30332
diff changeset
    21
    pycompat,
28577
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28525
diff changeset
    22
    util,
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28525
diff changeset
    23
)
24291
760a86865f80 ssl: load CA certificates from system's store by default on Python 2.7.9
Yuya Nishihara <yuya@tcha.org>
parents: 24290
diff changeset
    24
28647
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
    25
# Python 2.7.9+ overhauled the built-in SSL/TLS features of Python. It added
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
    26
# support for TLS 1.1, TLS 1.2, SNI, system CA stores, etc. These features are
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
    27
# all exposed via the "ssl" module.
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
    28
#
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
    29
# Depending on the version of Python being used, SSL/TLS support is either
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
    30
# modern/secure or legacy/insecure. Many operations in this module have
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
    31
# separate code paths depending on support in Python.
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
    32
32291
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 32273
diff changeset
    33
configprotocols = {
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
    34
    'tls1.0',
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
    35
    'tls1.1',
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
    36
    'tls1.2',
32291
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 32273
diff changeset
    37
}
26622
9e15286609ae sslutil: expose attribute indicating whether SNI is supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26587
diff changeset
    38
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
    39
hassni = getattr(ssl, 'HAS_SNI', False)
28648
7fc787e5d8ec sslutil: store OP_NO_SSL* constants in module scope
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28647
diff changeset
    40
29601
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
    41
# TLS 1.1 and 1.2 may not be supported if the OpenSSL Python is compiled
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
    42
# against doesn't support them.
32291
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 32273
diff changeset
    43
supportedprotocols = {'tls1.0'}
29601
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
    44
if util.safehasattr(ssl, 'PROTOCOL_TLSv1_1'):
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
    45
    supportedprotocols.add('tls1.1')
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
    46
if util.safehasattr(ssl, 'PROTOCOL_TLSv1_2'):
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
    47
    supportedprotocols.add('tls1.2')
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
    48
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    49
try:
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    50
    # ssl.SSLContext was added in 2.7.9 and presence indicates modern
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    51
    # SSL/TLS features are available.
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    52
    SSLContext = ssl.SSLContext
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    53
    modernssl = True
28650
737863b01d9f sslutil: move _canloaddefaultcerts logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28649
diff changeset
    54
    _canloaddefaultcerts = util.safehasattr(SSLContext, 'load_default_certs')
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    55
except AttributeError:
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    56
    modernssl = False
28650
737863b01d9f sslutil: move _canloaddefaultcerts logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28649
diff changeset
    57
    _canloaddefaultcerts = False
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    58
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    59
    # We implement SSLContext using the interface from the standard library.
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    60
    class SSLContext(object):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    61
        def __init__(self, protocol):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    62
            # From the public interface of SSLContext
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    63
            self.protocol = protocol
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    64
            self.check_hostname = False
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    65
            self.options = 0
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    66
            self.verify_mode = ssl.CERT_NONE
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    67
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    68
            # Used by our implementation.
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    69
            self._certfile = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    70
            self._keyfile = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    71
            self._certpassword = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    72
            self._cacerts = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    73
            self._ciphers = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    74
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    75
        def load_cert_chain(self, certfile, keyfile=None, password=None):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    76
            self._certfile = certfile
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    77
            self._keyfile = keyfile
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    78
            self._certpassword = password
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    79
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    80
        def load_default_certs(self, purpose=None):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    81
            pass
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    82
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    83
        def load_verify_locations(self, cafile=None, capath=None, cadata=None):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    84
            if capath:
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 29341
diff changeset
    85
                raise error.Abort(_('capath not supported'))
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    86
            if cadata:
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 29341
diff changeset
    87
                raise error.Abort(_('cadata not supported'))
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    88
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    89
            self._cacerts = cafile
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    90
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    91
        def set_ciphers(self, ciphers):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    92
            self._ciphers = ciphers
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    93
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    94
        def wrap_socket(self, socket, server_hostname=None, server_side=False):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    95
            # server_hostname is unique to SSLContext.wrap_socket and is used
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    96
            # for SNI in that context. So there's nothing for us to do with it
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    97
            # in this legacy code since we don't support SNI.
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    98
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    99
            args = {
35369
c8ecd96cc357 py3: handle keyword arguments correctly in sslutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34775
diff changeset
   100
                r'keyfile': self._keyfile,
c8ecd96cc357 py3: handle keyword arguments correctly in sslutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34775
diff changeset
   101
                r'certfile': self._certfile,
c8ecd96cc357 py3: handle keyword arguments correctly in sslutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34775
diff changeset
   102
                r'server_side': server_side,
c8ecd96cc357 py3: handle keyword arguments correctly in sslutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34775
diff changeset
   103
                r'cert_reqs': self.verify_mode,
c8ecd96cc357 py3: handle keyword arguments correctly in sslutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34775
diff changeset
   104
                r'ssl_version': self.protocol,
c8ecd96cc357 py3: handle keyword arguments correctly in sslutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34775
diff changeset
   105
                r'ca_certs': self._cacerts,
c8ecd96cc357 py3: handle keyword arguments correctly in sslutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34775
diff changeset
   106
                r'ciphers': self._ciphers,
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
   107
            }
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
   108
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
   109
            return ssl.wrap_socket(socket, **args)
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
   110
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   111
def _hostsettings(ui, hostname):
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   112
    """Obtain security settings for a hostname.
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   113
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   114
    Returns a dict of settings relevant to that hostname.
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   115
    """
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   116
    bhostname = pycompat.bytesurl(hostname)
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   117
    s = {
29288
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   118
        # Whether we should attempt to load default/available CA certs
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   119
        # if an explicit ``cafile`` is not defined.
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   120
        'allowloaddefaultcerts': True,
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   121
        # List of 2-tuple of (hash algorithm, hash).
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   122
        'certfingerprints': [],
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   123
        # Path to file containing concatenated CA certs. Used by
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   124
        # SSLContext.load_verify_locations().
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   125
        'cafile': None,
29287
fbccb334efe7 sslutil: store flag for whether cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29286
diff changeset
   126
        # Whether certificate verification should be disabled.
fbccb334efe7 sslutil: store flag for whether cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29286
diff changeset
   127
        'disablecertverification': False,
29268
f200b58497f1 sslutil: reference appropriate config section in messaging
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29267
diff changeset
   128
        # Whether the legacy [hostfingerprints] section has data for this host.
f200b58497f1 sslutil: reference appropriate config section in messaging
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29267
diff changeset
   129
        'legacyfingerprint': False,
29507
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   130
        # PROTOCOL_* constant to use for SSLContext.__init__.
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   131
        'protocol': None,
29618
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
   132
        # String representation of minimum protocol to be used for UI
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
   133
        # presentation.
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
   134
        'protocolui': None,
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   135
        # ssl.CERT_* constant used by SSLContext.verify_mode.
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   136
        'verifymode': None,
29508
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
   137
        # Defines extra ssl.OP* bitwise options to set.
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
   138
        'ctxoptions': None,
29577
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
   139
        # OpenSSL Cipher List to use (instead of default).
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
   140
        'ciphers': None,
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   141
    }
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   142
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   143
    # Allow minimum TLS protocol to be specified in the config.
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   144
    def validateprotocol(protocol, key):
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   145
        if protocol not in configprotocols:
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   146
            raise error.Abort(
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   147
                _('unsupported protocol from hostsecurity.%s: %s') %
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   148
                (key, protocol),
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   149
                hint=_('valid protocols: %s') %
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   150
                     ' '.join(sorted(configprotocols)))
29507
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   151
29601
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
   152
    # We default to TLS 1.1+ where we can because TLS 1.0 has known
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
   153
    # vulnerabilities (like BEAST and POODLE). We allow users to downgrade to
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
   154
    # TLS 1.0+ via config options in case a legacy server is encountered.
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
   155
    if 'tls1.1' in supportedprotocols:
29560
303e9300772a sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29559
diff changeset
   156
        defaultprotocol = 'tls1.1'
303e9300772a sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29559
diff changeset
   157
    else:
29601
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
   158
        # Let people know they are borderline secure.
29561
1a782fabf80d sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29560
diff changeset
   159
        # We don't document this config option because we want people to see
1a782fabf80d sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29560
diff changeset
   160
        # the bold warnings on the web site.
1a782fabf80d sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29560
diff changeset
   161
        # internal config: hostsecurity.disabletls10warning
1a782fabf80d sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29560
diff changeset
   162
        if not ui.configbool('hostsecurity', 'disabletls10warning'):
1a782fabf80d sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29560
diff changeset
   163
            ui.warn(_('warning: connecting to %s using legacy security '
1a782fabf80d sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29560
diff changeset
   164
                      'technology (TLS 1.0); see '
1a782fabf80d sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29560
diff changeset
   165
                      'https://mercurial-scm.org/wiki/SecureConnections for '
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   166
                      'more info\n') % bhostname)
29560
303e9300772a sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29559
diff changeset
   167
        defaultprotocol = 'tls1.0'
303e9300772a sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29559
diff changeset
   168
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   169
    key = 'minimumprotocol'
29560
303e9300772a sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29559
diff changeset
   170
    protocol = ui.config('hostsecurity', key, defaultprotocol)
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   171
    validateprotocol(protocol, key)
29508
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
   172
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   173
    key = '%s:minimumprotocol' % bhostname
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   174
    protocol = ui.config('hostsecurity', key, protocol)
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   175
    validateprotocol(protocol, key)
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   176
29617
2960ceee1948 sslutil: allow TLS 1.0 when --insecure is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29601
diff changeset
   177
    # If --insecure is used, we allow the use of TLS 1.0 despite config options.
2960ceee1948 sslutil: allow TLS 1.0 when --insecure is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29601
diff changeset
   178
    # We always print a "connection security to %s is disabled..." message when
2960ceee1948 sslutil: allow TLS 1.0 when --insecure is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29601
diff changeset
   179
    # --insecure is used. So no need to print anything more here.
2960ceee1948 sslutil: allow TLS 1.0 when --insecure is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29601
diff changeset
   180
    if ui.insecureconnections:
2960ceee1948 sslutil: allow TLS 1.0 when --insecure is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29601
diff changeset
   181
        protocol = 'tls1.0'
2960ceee1948 sslutil: allow TLS 1.0 when --insecure is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29601
diff changeset
   182
29618
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
   183
    s['protocol'], s['ctxoptions'], s['protocolui'] = protocolsettings(protocol)
29558
a935cd7d51a6 sslutil: prevent CRIME
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29557
diff changeset
   184
29577
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
   185
    ciphers = ui.config('hostsecurity', 'ciphers')
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   186
    ciphers = ui.config('hostsecurity', '%s:ciphers' % bhostname, ciphers)
29577
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
   187
    s['ciphers'] = ciphers
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
   188
29267
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   189
    # Look for fingerprints in [hostsecurity] section. Value is a list
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   190
    # of <alg>:<fingerprint> strings.
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   191
    fingerprints = ui.configlist('hostsecurity', '%s:fingerprints' % bhostname)
29267
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   192
    for fingerprint in fingerprints:
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   193
        if not (fingerprint.startswith(('sha1:', 'sha256:', 'sha512:'))):
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   194
            raise error.Abort(_('invalid fingerprint for %s: %s') % (
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   195
                                bhostname, fingerprint),
29267
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   196
                              hint=_('must begin with "sha1:", "sha256:", '
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   197
                                     'or "sha512:"'))
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   198
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   199
        alg, fingerprint = fingerprint.split(':', 1)
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   200
        fingerprint = fingerprint.replace(':', '').lower()
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   201
        s['certfingerprints'].append((alg, fingerprint))
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   202
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   203
    # Fingerprints from [hostfingerprints] are always SHA-1.
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   204
    for fingerprint in ui.configlist('hostfingerprints', bhostname):
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   205
        fingerprint = fingerprint.replace(':', '').lower()
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   206
        s['certfingerprints'].append(('sha1', fingerprint))
29268
f200b58497f1 sslutil: reference appropriate config section in messaging
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29267
diff changeset
   207
        s['legacyfingerprint'] = True
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   208
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   209
    # If a host cert fingerprint is defined, it is the only thing that
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   210
    # matters. No need to validate CA certs.
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   211
    if s['certfingerprints']:
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   212
        s['verifymode'] = ssl.CERT_NONE
29447
13edc11eb7b7 sslutil: don't load default certificates when they aren't relevant
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29446
diff changeset
   213
        s['allowloaddefaultcerts'] = False
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   214
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   215
    # If --insecure is used, don't take CAs into consideration.
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   216
    elif ui.insecureconnections:
29287
fbccb334efe7 sslutil: store flag for whether cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29286
diff changeset
   217
        s['disablecertverification'] = True
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   218
        s['verifymode'] = ssl.CERT_NONE
29447
13edc11eb7b7 sslutil: don't load default certificates when they aren't relevant
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29446
diff changeset
   219
        s['allowloaddefaultcerts'] = False
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   220
29288
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   221
    if ui.configbool('devel', 'disableloaddefaultcerts'):
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   222
        s['allowloaddefaultcerts'] = False
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   223
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   224
    # If both fingerprints and a per-host ca file are specified, issue a warning
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   225
    # because users should not be surprised about what security is or isn't
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   226
    # being performed.
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   227
    cafile = ui.config('hostsecurity', '%s:verifycertsfile' % bhostname)
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   228
    if s['certfingerprints'] and cafile:
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   229
        ui.warn(_('(hostsecurity.%s:verifycertsfile ignored when host '
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   230
                  'fingerprints defined; using host fingerprints for '
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   231
                  'verification)\n') % bhostname)
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   232
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   233
    # Try to hook up CA certificate validation unless something above
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   234
    # makes it not necessary.
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   235
    if s['verifymode'] is None:
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   236
        # Look at per-host ca file first.
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   237
        if cafile:
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   238
            cafile = util.expandpath(cafile)
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   239
            if not os.path.exists(cafile):
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   240
                raise error.Abort(_('path specified by %s does not exist: %s') %
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   241
                                  ('hostsecurity.%s:verifycertsfile' % (
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   242
                                      bhostname,), cafile))
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   243
            s['cafile'] = cafile
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   244
        else:
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   245
            # Find global certificates file in config.
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   246
            cafile = ui.config('web', 'cacerts')
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   247
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   248
            if cafile:
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   249
                cafile = util.expandpath(cafile)
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   250
                if not os.path.exists(cafile):
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   251
                    raise error.Abort(_('could not find web.cacerts: %s') %
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   252
                                      cafile)
29484
53b7fc7cc2bb sslutil: don't attempt to find default CA certs file when told not to
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29483
diff changeset
   253
            elif s['allowloaddefaultcerts']:
29482
4e72995f6c9c sslutil: change comment and logged message for found ca cert file
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29459
diff changeset
   254
                # CAs not defined in config. Try to find system bundles.
29483
918dce4b8c26 sslutil: pass ui to _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29482
diff changeset
   255
                cafile = _defaultcacerts(ui)
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   256
                if cafile:
29482
4e72995f6c9c sslutil: change comment and logged message for found ca cert file
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29459
diff changeset
   257
                    ui.debug('using %s for CA file\n' % cafile)
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   258
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   259
            s['cafile'] = cafile
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   261
        # Require certificate validation if CA certs are being loaded and
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   262
        # verification hasn't been disabled above.
29288
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   263
        if cafile or (_canloaddefaultcerts and s['allowloaddefaultcerts']):
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   264
            s['verifymode'] = ssl.CERT_REQUIRED
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   265
        else:
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   266
            # At this point we don't have a fingerprint, aren't being
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   267
            # explicitly insecure, and can't load CA certs. Connecting
29411
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
   268
            # is insecure. We allow the connection and abort during
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
   269
            # validation (once we have the fingerprint to print to the
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
   270
            # user).
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   271
            s['verifymode'] = ssl.CERT_NONE
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   272
29507
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   273
    assert s['protocol'] is not None
29508
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
   274
    assert s['ctxoptions'] is not None
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   275
    assert s['verifymode'] is not None
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   276
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   277
    return s
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   278
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   279
def protocolsettings(protocol):
29618
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
   280
    """Resolve the protocol for a config value.
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
   281
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
   282
    Returns a 3-tuple of (protocol, options, ui value) where the first
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
   283
    2 items are values used by SSLContext and the last is a string value
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
   284
    of the ``minimumprotocol`` config option equivalent.
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
   285
    """
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   286
    if protocol not in configprotocols:
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   287
        raise ValueError('protocol value not supported: %s' % protocol)
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   288
29578
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
   289
    # Despite its name, PROTOCOL_SSLv23 selects the highest protocol
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
   290
    # that both ends support, including TLS protocols. On legacy stacks,
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
   291
    # the highest it likely goes is TLS 1.0. On modern stacks, it can
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
   292
    # support TLS 1.2.
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
   293
    #
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
   294
    # The PROTOCOL_TLSv* constants select a specific TLS version
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
   295
    # only (as opposed to multiple versions). So the method for
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
   296
    # supporting multiple TLS versions is to use PROTOCOL_SSLv23 and
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
   297
    # disable protocols via SSLContext.options and OP_NO_* constants.
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
   298
    # However, SSLContext.options doesn't work unless we have the
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
   299
    # full/real SSLContext available to us.
32291
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 32273
diff changeset
   300
    if supportedprotocols == {'tls1.0'}:
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   301
        if protocol != 'tls1.0':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   302
            raise error.Abort(_('current Python does not support protocol '
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   303
                                'setting %s') % protocol,
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   304
                              hint=_('upgrade Python or disable setting since '
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   305
                                     'only TLS 1.0 is supported'))
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   306
29618
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
   307
        return ssl.PROTOCOL_TLSv1, 0, 'tls1.0'
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   308
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   309
    # WARNING: returned options don't work unless the modern ssl module
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   310
    # is available. Be careful when adding options here.
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   311
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   312
    # SSLv2 and SSLv3 are broken. We ban them outright.
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   313
    options = ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   314
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   315
    if protocol == 'tls1.0':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   316
        # Defaults above are to use TLS 1.0+
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   317
        pass
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   318
    elif protocol == 'tls1.1':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   319
        options |= ssl.OP_NO_TLSv1
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   320
    elif protocol == 'tls1.2':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   321
        options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   322
    else:
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   323
        raise error.Abort(_('this should not happen'))
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   324
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   325
    # Prevent CRIME.
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   326
    # There is no guarantee this attribute is defined on the module.
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   327
    options |= getattr(ssl, 'OP_NO_COMPRESSION', 0)
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   328
29618
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
   329
    return ssl.PROTOCOL_SSLv23, options, protocol
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   330
29249
cca59ef27e60 sslutil: move sslkwargs logic into internal function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29248
diff changeset
   331
def wrapsocket(sock, keyfile, certfile, ui, serverhostname=None):
28653
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   332
    """Add SSL/TLS to a socket.
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   333
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   334
    This is a glorified wrapper for ``ssl.wrap_socket()``. It makes sane
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   335
    choices based on what security options are available.
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   336
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   337
    In addition to the arguments supported by ``ssl.wrap_socket``, we allow
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   338
    the following additional arguments:
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   339
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   340
    * serverhostname - The expected hostname of the remote server. If the
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   341
      server (and client) support SNI, this tells the server which certificate
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   342
      to use.
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   343
    """
29224
7424f4294199 sslutil: require serverhostname argument (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29115
diff changeset
   344
    if not serverhostname:
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 29341
diff changeset
   345
        raise error.Abort(_('serverhostname argument is required'))
29224
7424f4294199 sslutil: require serverhostname argument (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29115
diff changeset
   346
33381
3bdbbadddecc sslutil: check for missing certificate and key files (issue5598)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32291
diff changeset
   347
    for f in (keyfile, certfile):
3bdbbadddecc sslutil: check for missing certificate and key files (issue5598)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32291
diff changeset
   348
        if f and not os.path.exists(f):
36747
4c71a26a4009 sslutil: some more forcebytes() on some exception messages
Augie Fackler <augie@google.com>
parents: 36746
diff changeset
   349
            raise error.Abort(
4c71a26a4009 sslutil: some more forcebytes() on some exception messages
Augie Fackler <augie@google.com>
parents: 36746
diff changeset
   350
                _('certificate file (%s) does not exist; cannot connect to %s')
4c71a26a4009 sslutil: some more forcebytes() on some exception messages
Augie Fackler <augie@google.com>
parents: 36746
diff changeset
   351
                % (f, pycompat.bytesurl(serverhostname)),
4c71a26a4009 sslutil: some more forcebytes() on some exception messages
Augie Fackler <augie@google.com>
parents: 36746
diff changeset
   352
                hint=_('restore missing file or fix references '
4c71a26a4009 sslutil: some more forcebytes() on some exception messages
Augie Fackler <augie@google.com>
parents: 36746
diff changeset
   353
                       'in Mercurial config'))
33381
3bdbbadddecc sslutil: check for missing certificate and key files (issue5598)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32291
diff changeset
   354
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   355
    settings = _hostsettings(ui, serverhostname)
29249
cca59ef27e60 sslutil: move sslkwargs logic into internal function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29248
diff changeset
   356
29557
53de8255ec4e sslutil: update comment about create_default_context()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29554
diff changeset
   357
    # We can't use ssl.create_default_context() because it calls
53de8255ec4e sslutil: update comment about create_default_context()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29554
diff changeset
   358
    # load_default_certs() unless CA arguments are passed to it. We want to
53de8255ec4e sslutil: update comment about create_default_context()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29554
diff changeset
   359
    # have explicit control over CA loading because implicitly loading
53de8255ec4e sslutil: update comment about create_default_context()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29554
diff changeset
   360
    # CAs may undermine the user's intent. For example, a user may define a CA
53de8255ec4e sslutil: update comment about create_default_context()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29554
diff changeset
   361
    # bundle with a specific CA cert removed. If the system/default CA bundle
53de8255ec4e sslutil: update comment about create_default_context()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29554
diff changeset
   362
    # is loaded and contains that removed CA, you've just undone the user's
53de8255ec4e sslutil: update comment about create_default_context()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29554
diff changeset
   363
    # choice.
29507
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   364
    sslcontext = SSLContext(settings['protocol'])
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   365
29508
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
   366
    # This is a no-op unless using modern ssl.
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
   367
    sslcontext.options |= settings['ctxoptions']
28651
4827d07073e6 sslutil: always use SSLContext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28650
diff changeset
   368
28848
e330db205b20 sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28653
diff changeset
   369
    # This still works on our fake SSLContext.
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   370
    sslcontext.verify_mode = settings['verifymode']
28848
e330db205b20 sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28653
diff changeset
   371
29577
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
   372
    if settings['ciphers']:
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
   373
        try:
36746
25798cf7dc9d sslutil: sslcontext needs the cipher name as a sysstr
Augie Fackler <augie@google.com>
parents: 36745
diff changeset
   374
            sslcontext.set_ciphers(pycompat.sysstr(settings['ciphers']))
29577
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
   375
        except ssl.SSLError as e:
36747
4c71a26a4009 sslutil: some more forcebytes() on some exception messages
Augie Fackler <augie@google.com>
parents: 36746
diff changeset
   376
            raise error.Abort(
4c71a26a4009 sslutil: some more forcebytes() on some exception messages
Augie Fackler <augie@google.com>
parents: 36746
diff changeset
   377
                _('could not set ciphers: %s') % util.forcebytestr(e.args[0]),
4c71a26a4009 sslutil: some more forcebytes() on some exception messages
Augie Fackler <augie@google.com>
parents: 36746
diff changeset
   378
                hint=_('change cipher string (%s) in config') %
4c71a26a4009 sslutil: some more forcebytes() on some exception messages
Augie Fackler <augie@google.com>
parents: 36746
diff changeset
   379
                settings['ciphers'])
29577
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
   380
28652
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   381
    if certfile is not None:
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   382
        def password():
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   383
            f = keyfile or certfile
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   384
            return ui.getpass(_('passphrase for %s: ') % f, '')
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   385
        sslcontext.load_cert_chain(certfile, keyfile, password)
28848
e330db205b20 sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28653
diff changeset
   386
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   387
    if settings['cafile'] is not None:
29446
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
   388
        try:
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
   389
            sslcontext.load_verify_locations(cafile=settings['cafile'])
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
   390
        except ssl.SSLError as e:
29927
799e36749f1a ssl: handle a difference in SSLError with pypy (issue5348)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29631
diff changeset
   391
            if len(e.args) == 1: # pypy has different SSLError args
799e36749f1a ssl: handle a difference in SSLError with pypy (issue5348)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29631
diff changeset
   392
                msg = e.args[0]
799e36749f1a ssl: handle a difference in SSLError with pypy (issue5348)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29631
diff changeset
   393
            else:
799e36749f1a ssl: handle a difference in SSLError with pypy (issue5348)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29631
diff changeset
   394
                msg = e.args[1]
29446
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
   395
            raise error.Abort(_('error loading CA file %s: %s') % (
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   396
                              settings['cafile'], util.forcebytestr(msg)),
29446
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
   397
                              hint=_('file is empty or malformed?'))
29113
5b9577edf745 sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29112
diff changeset
   398
        caloaded = True
29288
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   399
    elif settings['allowloaddefaultcerts']:
28652
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   400
        # This is a no-op on old Python.
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   401
        sslcontext.load_default_certs()
29288
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   402
        caloaded = True
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   403
    else:
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   404
        caloaded = False
23834
bf07c19b4c82 https: support tls sni (server name indication) for https urls (issue3090)
Alex Orange <crazycasta@gmail.com>
parents: 23069
diff changeset
   405
29449
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   406
    try:
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   407
        sslsocket = sslcontext.wrap_socket(sock, server_hostname=serverhostname)
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   408
    except ssl.SSLError as e:
29449
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   409
        # If we're doing certificate verification and no CA certs are loaded,
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   410
        # that is almost certainly the reason why verification failed. Provide
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   411
        # a hint to the user.
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   412
        # Only modern ssl module exposes SSLContext.get_ca_certs() so we can
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   413
        # only show this warning if modern ssl is available.
31725
c777b12cdc9b sslutil: clarify internal documentation
Matt Harbison <matt_harbison@yahoo.com>
parents: 31290
diff changeset
   414
        # The exception handler is here to handle bugs around cert attributes:
c777b12cdc9b sslutil: clarify internal documentation
Matt Harbison <matt_harbison@yahoo.com>
parents: 31290
diff changeset
   415
        # https://bugs.python.org/issue20916#msg213479.  (See issues5313.)
c777b12cdc9b sslutil: clarify internal documentation
Matt Harbison <matt_harbison@yahoo.com>
parents: 31290
diff changeset
   416
        # When the main 20916 bug occurs, 'sslcontext.get_ca_certs()' is a
c777b12cdc9b sslutil: clarify internal documentation
Matt Harbison <matt_harbison@yahoo.com>
parents: 31290
diff changeset
   417
        # non-empty list, but the following conditional is otherwise True.
29631
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
   418
        try:
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
   419
            if (caloaded and settings['verifymode'] == ssl.CERT_REQUIRED and
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
   420
                modernssl and not sslcontext.get_ca_certs()):
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
   421
                ui.warn(_('(an attempt was made to load CA certificates but '
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
   422
                          'none were loaded; see '
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
   423
                          'https://mercurial-scm.org/wiki/SecureConnections '
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
   424
                          'for how to configure Mercurial to avoid this '
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
   425
                          'error)\n'))
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
   426
        except ssl.SSLError:
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
   427
            pass
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   428
        # Try to print more helpful error messages for known failures.
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   429
        if util.safehasattr(e, 'reason'):
29619
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   430
            # This error occurs when the client and server don't share a
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   431
            # common/supported SSL/TLS protocol. We've disabled SSLv2 and SSLv3
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   432
            # outright. Hopefully the reason for this error is that we require
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   433
            # TLS 1.1+ and the server only supports TLS 1.0. Whatever the
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   434
            # reason, try to emit an actionable warning.
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   435
            if e.reason == 'UNSUPPORTED_PROTOCOL':
29619
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   436
                # We attempted TLS 1.0+.
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   437
                if settings['protocolui'] == 'tls1.0':
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   438
                    # We support more than just TLS 1.0+. If this happens,
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   439
                    # the likely scenario is either the client or the server
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   440
                    # is really old. (e.g. server doesn't support TLS 1.0+ or
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   441
                    # client doesn't support modern TLS versions introduced
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   442
                    # several years from when this comment was written).
32291
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 32273
diff changeset
   443
                    if supportedprotocols != {'tls1.0'}:
29619
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   444
                        ui.warn(_(
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   445
                            '(could not communicate with %s using security '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   446
                            'protocols %s; if you are using a modern Mercurial '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   447
                            'version, consider contacting the operator of this '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   448
                            'server; see '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   449
                            'https://mercurial-scm.org/wiki/SecureConnections '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   450
                            'for more info)\n') % (
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   451
                                serverhostname,
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   452
                                ', '.join(sorted(supportedprotocols))))
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   453
                    else:
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   454
                        ui.warn(_(
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   455
                            '(could not communicate with %s using TLS 1.0; the '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   456
                            'likely cause of this is the server no longer '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   457
                            'supports TLS 1.0 because it has known security '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   458
                            'vulnerabilities; see '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   459
                            'https://mercurial-scm.org/wiki/SecureConnections '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   460
                            'for more info)\n') % serverhostname)
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   461
                else:
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   462
                    # We attempted TLS 1.1+. We can only get here if the client
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   463
                    # supports the configured protocol. So the likely reason is
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   464
                    # the client wants better security than the server can
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   465
                    # offer.
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   466
                    ui.warn(_(
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   467
                        '(could not negotiate a common security protocol (%s+) '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   468
                        'with %s; the likely cause is Mercurial is configured '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   469
                        'to be more secure than the server can support)\n') % (
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   470
                        settings['protocolui'], serverhostname))
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   471
                    ui.warn(_('(consider contacting the operator of this '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   472
                              'server and ask them to support modern TLS '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   473
                              'protocol versions; or, set '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   474
                              'hostsecurity.%s:minimumprotocol=tls1.0 to allow '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   475
                              'use of legacy, less secure protocols when '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   476
                              'communicating with this server)\n') %
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   477
                            serverhostname)
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   478
                    ui.warn(_(
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   479
                        '(see https://mercurial-scm.org/wiki/SecureConnections '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
   480
                        'for more info)\n'))
33494
30f2715be123 sslutil: inform the user about how to fix an incomplete certificate chain
Matt Harbison <matt_harbison@yahoo.com>
parents: 33381
diff changeset
   481
30f2715be123 sslutil: inform the user about how to fix an incomplete certificate chain
Matt Harbison <matt_harbison@yahoo.com>
parents: 33381
diff changeset
   482
            elif (e.reason == 'CERTIFICATE_VERIFY_FAILED' and
34645
75979c8d4572 codemod: use pycompat.iswindows
Jun Wu <quark@fb.com>
parents: 33494
diff changeset
   483
                pycompat.iswindows):
33494
30f2715be123 sslutil: inform the user about how to fix an incomplete certificate chain
Matt Harbison <matt_harbison@yahoo.com>
parents: 33381
diff changeset
   484
30f2715be123 sslutil: inform the user about how to fix an incomplete certificate chain
Matt Harbison <matt_harbison@yahoo.com>
parents: 33381
diff changeset
   485
                ui.warn(_('(the full certificate chain may not be available '
30f2715be123 sslutil: inform the user about how to fix an incomplete certificate chain
Matt Harbison <matt_harbison@yahoo.com>
parents: 33381
diff changeset
   486
                          'locally; see "hg help debugssl")\n'))
29449
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   487
        raise
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   488
28652
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   489
    # check if wrap_socket failed silently because socket had been
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   490
    # closed
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   491
    # - see http://bugs.python.org/issue13721
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   492
    if not sslsocket.cipher():
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   493
        raise error.Abort(_('ssl connection failed'))
29113
5b9577edf745 sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29112
diff changeset
   494
29225
b115eed11780 sslutil: use a dict for hanging hg state off the wrapped socket
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29224
diff changeset
   495
    sslsocket._hgstate = {
b115eed11780 sslutil: use a dict for hanging hg state off the wrapped socket
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29224
diff changeset
   496
        'caloaded': caloaded,
29226
33006bd6a1d7 sslutil: store and use hostname and ui in socket instance
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29225
diff changeset
   497
        'hostname': serverhostname,
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   498
        'settings': settings,
29226
33006bd6a1d7 sslutil: store and use hostname and ui in socket instance
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29225
diff changeset
   499
        'ui': ui,
29225
b115eed11780 sslutil: use a dict for hanging hg state off the wrapped socket
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29224
diff changeset
   500
    }
29113
5b9577edf745 sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29112
diff changeset
   501
28652
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   502
    return sslsocket
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   503
29554
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   504
def wrapserversocket(sock, ui, certfile=None, keyfile=None, cafile=None,
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   505
                     requireclientcert=False):
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   506
    """Wrap a socket for use by servers.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   507
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   508
    ``certfile`` and ``keyfile`` specify the files containing the certificate's
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   509
    public and private keys, respectively. Both keys can be defined in the same
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   510
    file via ``certfile`` (the private key must come first in the file).
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   511
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   512
    ``cafile`` defines the path to certificate authorities.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   513
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   514
    ``requireclientcert`` specifies whether to require client certificates.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   515
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   516
    Typically ``cafile`` is only defined if ``requireclientcert`` is true.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   517
    """
33381
3bdbbadddecc sslutil: check for missing certificate and key files (issue5598)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32291
diff changeset
   518
    # This function is not used much by core Mercurial, so the error messaging
3bdbbadddecc sslutil: check for missing certificate and key files (issue5598)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32291
diff changeset
   519
    # doesn't have to be as detailed as for wrapsocket().
3bdbbadddecc sslutil: check for missing certificate and key files (issue5598)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32291
diff changeset
   520
    for f in (certfile, keyfile, cafile):
3bdbbadddecc sslutil: check for missing certificate and key files (issue5598)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32291
diff changeset
   521
        if f and not os.path.exists(f):
3bdbbadddecc sslutil: check for missing certificate and key files (issue5598)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32291
diff changeset
   522
            raise error.Abort(_('referenced certificate file (%s) does not '
3bdbbadddecc sslutil: check for missing certificate and key files (issue5598)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32291
diff changeset
   523
                                'exist') % f)
3bdbbadddecc sslutil: check for missing certificate and key files (issue5598)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32291
diff changeset
   524
29618
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
   525
    protocol, options, _protocolui = protocolsettings('tls1.0')
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   526
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   527
    # This config option is intended for use in tests only. It is a giant
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   528
    # footgun to kill security. Don't define it.
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   529
    exactprotocol = ui.config('devel', 'serverexactprotocol')
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   530
    if exactprotocol == 'tls1.0':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   531
        protocol = ssl.PROTOCOL_TLSv1
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   532
    elif exactprotocol == 'tls1.1':
29601
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
   533
        if 'tls1.1' not in supportedprotocols:
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
   534
            raise error.Abort(_('TLS 1.1 not supported by this Python'))
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   535
        protocol = ssl.PROTOCOL_TLSv1_1
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   536
    elif exactprotocol == 'tls1.2':
29601
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
   537
        if 'tls1.2' not in supportedprotocols:
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
   538
            raise error.Abort(_('TLS 1.2 not supported by this Python'))
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   539
        protocol = ssl.PROTOCOL_TLSv1_2
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   540
    elif exactprotocol:
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   541
        raise error.Abort(_('invalid value for serverexactprotocol: %s') %
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   542
                          exactprotocol)
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   543
29554
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   544
    if modernssl:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   545
        # We /could/ use create_default_context() here since it doesn't load
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   546
        # CAs when configured for client auth. However, it is hard-coded to
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   547
        # use ssl.PROTOCOL_SSLv23 which may not be appropriate here.
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   548
        sslcontext = SSLContext(protocol)
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   549
        sslcontext.options |= options
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   550
29554
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   551
        # Improve forward secrecy.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   552
        sslcontext.options |= getattr(ssl, 'OP_SINGLE_DH_USE', 0)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   553
        sslcontext.options |= getattr(ssl, 'OP_SINGLE_ECDH_USE', 0)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   554
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   555
        # Use the list of more secure ciphers if found in the ssl module.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   556
        if util.safehasattr(ssl, '_RESTRICTED_SERVER_CIPHERS'):
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   557
            sslcontext.options |= getattr(ssl, 'OP_CIPHER_SERVER_PREFERENCE', 0)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   558
            sslcontext.set_ciphers(ssl._RESTRICTED_SERVER_CIPHERS)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   559
    else:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   560
        sslcontext = SSLContext(ssl.PROTOCOL_TLSv1)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   561
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   562
    if requireclientcert:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   563
        sslcontext.verify_mode = ssl.CERT_REQUIRED
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   564
    else:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   565
        sslcontext.verify_mode = ssl.CERT_NONE
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   566
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   567
    if certfile or keyfile:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   568
        sslcontext.load_cert_chain(certfile=certfile, keyfile=keyfile)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   569
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   570
    if cafile:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   571
        sslcontext.load_verify_locations(cafile=cafile)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   572
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   573
    return sslcontext.wrap_socket(sock, server_side=True)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   574
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   575
class wildcarderror(Exception):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   576
    """Represents an error parsing wildcards in DNS name."""
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   577
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   578
def _dnsnamematch(dn, hostname, maxwildcards=1):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   579
    """Match DNS names according RFC 6125 section 6.4.3.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   580
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   581
    This code is effectively copied from CPython's ssl._dnsname_match.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   582
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   583
    Returns a bool indicating whether the expected hostname matches
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   584
    the value in ``dn``.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   585
    """
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   586
    pats = []
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   587
    if not dn:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   588
        return False
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   589
    dn = pycompat.bytesurl(dn)
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   590
    hostname = pycompat.bytesurl(hostname)
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   591
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   592
    pieces = dn.split('.')
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   593
    leftmost = pieces[0]
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   594
    remainder = pieces[1:]
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   595
    wildcards = leftmost.count('*')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   596
    if wildcards > maxwildcards:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   597
        raise wildcarderror(
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   598
            _('too many wildcards in certificate DNS name: %s') % dn)
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   599
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   600
    # speed up common case w/o wildcards
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   601
    if not wildcards:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   602
        return dn.lower() == hostname.lower()
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   603
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   604
    # RFC 6125, section 6.4.3, subitem 1.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   605
    # The client SHOULD NOT attempt to match a presented identifier in which
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   606
    # the wildcard character comprises a label other than the left-most label.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   607
    if leftmost == '*':
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   608
        # When '*' is a fragment by itself, it matches a non-empty dotless
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   609
        # fragment.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   610
        pats.append('[^.]+')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   611
    elif leftmost.startswith('xn--') or hostname.startswith('xn--'):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   612
        # RFC 6125, section 6.4.3, subitem 3.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   613
        # The client SHOULD NOT attempt to match a presented identifier
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   614
        # where the wildcard character is embedded within an A-label or
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   615
        # U-label of an internationalized domain name.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   616
        pats.append(re.escape(leftmost))
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   617
    else:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   618
        # Otherwise, '*' matches any dotless string, e.g. www*
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   619
        pats.append(re.escape(leftmost).replace(r'\*', '[^.]*'))
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   620
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   621
    # add the remaining fragments, ignore any wildcards
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   622
    for frag in remainder:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   623
        pats.append(re.escape(frag))
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   624
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   625
    pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE)
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   626
    return pat.match(hostname) is not None
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   627
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   628
def _verifycert(cert, hostname):
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   629
    '''Verify that cert (in socket.getpeercert() format) matches hostname.
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   630
    CRLs is not handled.
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   631
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   632
    Returns error message if any problems are found and None on success.
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   633
    '''
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   634
    if not cert:
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   635
        return _('no certificate received')
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   636
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   637
    dnsnames = []
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   638
    san = cert.get('subjectAltName', [])
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   639
    for key, value in san:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   640
        if key == 'DNS':
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   641
            try:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   642
                if _dnsnamematch(value, hostname):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   643
                    return
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   644
            except wildcarderror as e:
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   645
                return util.forcebytestr(e.args[0])
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   646
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   647
            dnsnames.append(value)
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   648
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   649
    if not dnsnames:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   650
        # The subject is only checked when there is no DNS in subjectAltName.
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   651
        for sub in cert.get(r'subject', []):
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   652
            for key, value in sub:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   653
                # According to RFC 2818 the most specific Common Name must
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   654
                # be used.
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   655
                if key == r'commonName':
30332
318a24b52eeb spelling: fixes of non-dictionary words
Mads Kiilerich <madski@unity3d.com>
parents: 30228
diff changeset
   656
                    # 'subject' entries are unicode.
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   657
                    try:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   658
                        value = value.encode('ascii')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   659
                    except UnicodeEncodeError:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   660
                        return _('IDN in certificate not supported')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   661
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   662
                    try:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   663
                        if _dnsnamematch(value, hostname):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   664
                            return
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   665
                    except wildcarderror as e:
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   666
                        return util.forcebytestr(e.args[0])
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   667
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   668
                    dnsnames.append(value)
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   669
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   670
    if len(dnsnames) > 1:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   671
        return _('certificate is for %s') % ', '.join(dnsnames)
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   672
    elif len(dnsnames) == 1:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   673
        return _('certificate is for %s') % dnsnames[0]
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   674
    else:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   675
        return _('no commonName or subjectAltName found in certificate')
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   676
23042
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
   677
def _plainapplepython():
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
   678
    """return true if this seems to be a pure Apple Python that
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
   679
    * is unfrozen and presumably has the whole mercurial module in the file
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
   680
      system
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
   681
    * presumably is an Apple Python that uses Apple OpenSSL which has patches
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
   682
      for using system certificate store CAs in addition to the provided
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
   683
      cacerts file
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
   684
    """
34647
dacfcdd8b94e codemod: use pycompat.isdarwin
Jun Wu <quark@fb.com>
parents: 34645
diff changeset
   685
    if (not pycompat.isdarwin or util.mainfrozen() or
dacfcdd8b94e codemod: use pycompat.isdarwin
Jun Wu <quark@fb.com>
parents: 34645
diff changeset
   686
        not pycompat.sysexecutable):
23042
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
   687
        return False
30669
10b17ed9b591 py3: replace sys.executable with pycompat.sysexecutable
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30641
diff changeset
   688
    exe = os.path.realpath(pycompat.sysexecutable).lower()
23042
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
   689
    return (exe.startswith('/usr/bin/python') or
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
   690
            exe.startswith('/system/library/frameworks/python.framework/'))
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
   691
29500
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   692
_systemcacertpaths = [
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   693
    # RHEL, CentOS, and Fedora
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   694
    '/etc/pki/tls/certs/ca-bundle.trust.crt',
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   695
    # Debian, Ubuntu, Gentoo
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   696
    '/etc/ssl/certs/ca-certificates.crt',
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   697
]
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   698
29483
918dce4b8c26 sslutil: pass ui to _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29482
diff changeset
   699
def _defaultcacerts(ui):
29488
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29487
diff changeset
   700
    """return path to default CA certificates or None.
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29487
diff changeset
   701
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29487
diff changeset
   702
    It is assumed this function is called when the returned certificates
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29487
diff changeset
   703
    file will actually be used to validate connections. Therefore this
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29487
diff changeset
   704
    function may print warnings or debug messages assuming this usage.
29500
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   705
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   706
    We don't print a message when the Python is able to load default
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   707
    CA certs because this scenario is detected at socket connect time.
29488
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29487
diff changeset
   708
    """
30228
b9f7b0c10027 sslutil: guard against broken certifi installations (issue5406)
G?bor Stefanik <gabor.stefanik@nng.com>
parents: 29927
diff changeset
   709
    # The "certifi" Python package provides certificates. If it is installed
b9f7b0c10027 sslutil: guard against broken certifi installations (issue5406)
G?bor Stefanik <gabor.stefanik@nng.com>
parents: 29927
diff changeset
   710
    # and usable, assume the user intends it to be used and use it.
29486
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
   711
    try:
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
   712
        import certifi
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
   713
        certs = certifi.where()
30228
b9f7b0c10027 sslutil: guard against broken certifi installations (issue5406)
G?bor Stefanik <gabor.stefanik@nng.com>
parents: 29927
diff changeset
   714
        if os.path.exists(certs):
b9f7b0c10027 sslutil: guard against broken certifi installations (issue5406)
G?bor Stefanik <gabor.stefanik@nng.com>
parents: 29927
diff changeset
   715
            ui.debug('using ca certificates from certifi\n')
b9f7b0c10027 sslutil: guard against broken certifi installations (issue5406)
G?bor Stefanik <gabor.stefanik@nng.com>
parents: 29927
diff changeset
   716
            return certs
b9f7b0c10027 sslutil: guard against broken certifi installations (issue5406)
G?bor Stefanik <gabor.stefanik@nng.com>
parents: 29927
diff changeset
   717
    except (ImportError, AttributeError):
29486
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
   718
        pass
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
   719
29489
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   720
    # On Windows, only the modern ssl module is capable of loading the system
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   721
    # CA certificates. If we're not capable of doing that, emit a warning
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   722
    # because we'll get a certificate verification error later and the lack
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   723
    # of loaded CA certificates will be the reason why.
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   724
    # Assertion: this code is only called if certificates are being verified.
34645
75979c8d4572 codemod: use pycompat.iswindows
Jun Wu <quark@fb.com>
parents: 33494
diff changeset
   725
    if pycompat.iswindows:
29489
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   726
        if not _canloaddefaultcerts:
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   727
            ui.warn(_('(unable to load Windows CA certificates; see '
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   728
                      'https://mercurial-scm.org/wiki/SecureConnections for '
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   729
                      'how to configure Mercurial to avoid this message)\n'))
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   730
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   731
        return None
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   732
29487
cdcb5747dc88 sslutil: document the Apple OpenSSL cert trick
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29486
diff changeset
   733
    # Apple's OpenSSL has patches that allow a specially constructed certificate
cdcb5747dc88 sslutil: document the Apple OpenSSL cert trick
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29486
diff changeset
   734
    # to load the system CA store. If we're running on Apple Python, use this
cdcb5747dc88 sslutil: document the Apple OpenSSL cert trick
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29486
diff changeset
   735
    # trick.
24288
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
   736
    if _plainapplepython():
31074
2912b06905dc py3: use pycompat.fsencode() to convert __file__ to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30669
diff changeset
   737
        dummycert = os.path.join(
2912b06905dc py3: use pycompat.fsencode() to convert __file__ to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30669
diff changeset
   738
            os.path.dirname(pycompat.fsencode(__file__)), 'dummycert.pem')
24288
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
   739
        if os.path.exists(dummycert):
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
   740
            return dummycert
29107
c8fbfb9163ce sslutil: move code examining _canloaddefaultcerts out of _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29106
diff changeset
   741
29499
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
   742
    # The Apple OpenSSL trick isn't available to us. If Python isn't able to
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
   743
    # load system certs, we're out of luck.
34647
dacfcdd8b94e codemod: use pycompat.isdarwin
Jun Wu <quark@fb.com>
parents: 34645
diff changeset
   744
    if pycompat.isdarwin:
29499
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
   745
        # FUTURE Consider looking for Homebrew or MacPorts installed certs
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
   746
        # files. Also consider exporting the keychain certs to a file during
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
   747
        # Mercurial install.
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
   748
        if not _canloaddefaultcerts:
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
   749
            ui.warn(_('(unable to load CA certificates; see '
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
   750
                      'https://mercurial-scm.org/wiki/SecureConnections for '
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
   751
                      'how to configure Mercurial to avoid this message)\n'))
24291
760a86865f80 ssl: load CA certificates from system's store by default on Python 2.7.9
Yuya Nishihara <yuya@tcha.org>
parents: 24290
diff changeset
   752
        return None
24288
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
   753
29537
5f8b36d5a6ec sslutil: add assertion to prevent accidental CA usage on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29508
diff changeset
   754
    # / is writable on Windows. Out of an abundance of caution make sure
5f8b36d5a6ec sslutil: add assertion to prevent accidental CA usage on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29508
diff changeset
   755
    # we're not on Windows because paths from _systemcacerts could be installed
5f8b36d5a6ec sslutil: add assertion to prevent accidental CA usage on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29508
diff changeset
   756
    # by non-admin users.
34645
75979c8d4572 codemod: use pycompat.iswindows
Jun Wu <quark@fb.com>
parents: 33494
diff changeset
   757
    assert not pycompat.iswindows
29537
5f8b36d5a6ec sslutil: add assertion to prevent accidental CA usage on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29508
diff changeset
   758
29500
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   759
    # Try to find CA certificates in well-known locations. We print a warning
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   760
    # when using a found file because we don't want too much silent magic
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   761
    # for security settings. The expectation is that proper Mercurial
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   762
    # installs will have the CA certs path defined at install time and the
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   763
    # installer/packager will make an appropriate decision on the user's
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   764
    # behalf. We only get here and perform this setting as a feature of
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   765
    # last resort.
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   766
    if not _canloaddefaultcerts:
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   767
        for path in _systemcacertpaths:
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   768
            if os.path.isfile(path):
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   769
                ui.warn(_('(using CA certificates from %s; if you see this '
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   770
                          'message, your Mercurial install is not properly '
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   771
                          'configured; see '
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   772
                          'https://mercurial-scm.org/wiki/SecureConnections '
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   773
                          'for how to configure Mercurial to avoid this '
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   774
                          'message)\n') % path)
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   775
                return path
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   776
29500
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   777
        ui.warn(_('(unable to load CA certificates; see '
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   778
                  'https://mercurial-scm.org/wiki/SecureConnections for '
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   779
                  'how to configure Mercurial to avoid this message)\n'))
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   780
29107
c8fbfb9163ce sslutil: move code examining _canloaddefaultcerts out of _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29106
diff changeset
   781
    return None
24288
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
   782
29286
a05a91a3f120 sslutil: remove "strict" argument from validatesocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29268
diff changeset
   783
def validatesocket(sock):
30332
318a24b52eeb spelling: fixes of non-dictionary words
Mads Kiilerich <madski@unity3d.com>
parents: 30228
diff changeset
   784
    """Validate a socket meets security requirements.
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
   785
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   786
    The passed socket must have been created with ``wrapsocket()``.
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   787
    """
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   788
    shost = sock._hgstate['hostname']
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   789
    host = pycompat.bytesurl(shost)
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   790
    ui = sock._hgstate['ui']
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   791
    settings = sock._hgstate['settings']
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
   792
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   793
    try:
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   794
        peercert = sock.getpeercert(True)
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   795
        peercert2 = sock.getpeercert()
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   796
    except AttributeError:
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   797
        raise error.Abort(_('%s ssl connection error') % host)
24288
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
   798
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   799
    if not peercert:
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   800
        raise error.Abort(_('%s certificate error: '
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   801
                           'no certificate received') % host)
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
   802
29289
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
   803
    if settings['disablecertverification']:
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
   804
        # We don't print the certificate fingerprint because it shouldn't
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
   805
        # be necessary: if the user requested certificate verification be
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
   806
        # disabled, they presumably already saw a message about the inability
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
   807
        # to verify the certificate and this message would have printed the
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
   808
        # fingerprint. So printing the fingerprint here adds little to no
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
   809
        # value.
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
   810
        ui.warn(_('warning: connection security to %s is disabled per current '
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
   811
                  'settings; communication is susceptible to eavesdropping '
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
   812
                  'and tampering\n') % host)
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
   813
        return
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
   814
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   815
    # If a certificate fingerprint is pinned, use it and only it to
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   816
    # validate the remote cert.
29262
dfc4f08aa160 sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29260
diff changeset
   817
    peerfingerprints = {
35582
72b91f905065 py3: use node.hex(h.digest()) instead of h.hexdigest()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35369
diff changeset
   818
        'sha1': node.hex(hashlib.sha1(peercert).digest()),
72b91f905065 py3: use node.hex(h.digest()) instead of h.hexdigest()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35369
diff changeset
   819
        'sha256': node.hex(hashlib.sha256(peercert).digest()),
72b91f905065 py3: use node.hex(h.digest()) instead of h.hexdigest()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35369
diff changeset
   820
        'sha512': node.hex(hashlib.sha512(peercert).digest()),
29262
dfc4f08aa160 sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29260
diff changeset
   821
    }
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
   822
29290
01248c37a68e sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29289
diff changeset
   823
    def fmtfingerprint(s):
01248c37a68e sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29289
diff changeset
   824
        return ':'.join([s[x:x + 2] for x in range(0, len(s), 2)])
01248c37a68e sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29289
diff changeset
   825
01248c37a68e sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29289
diff changeset
   826
    nicefingerprint = 'sha256:%s' % fmtfingerprint(peerfingerprints['sha256'])
28850
3819c349b194 sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28849
diff changeset
   827
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   828
    if settings['certfingerprints']:
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   829
        for hash, fingerprint in settings['certfingerprints']:
29262
dfc4f08aa160 sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29260
diff changeset
   830
            if peerfingerprints[hash].lower() == fingerprint:
29291
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29290
diff changeset
   831
                ui.debug('%s certificate matched fingerprint %s:%s\n' %
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29290
diff changeset
   832
                         (host, hash, fmtfingerprint(fingerprint)))
31290
f819aa9dbbf9 sslutil: issue warning when [hostfingerprint] is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31074
diff changeset
   833
                if settings['legacyfingerprint']:
f819aa9dbbf9 sslutil: issue warning when [hostfingerprint] is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31074
diff changeset
   834
                    ui.warn(_('(SHA-1 fingerprint for %s found in legacy '
f819aa9dbbf9 sslutil: issue warning when [hostfingerprint] is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31074
diff changeset
   835
                              '[hostfingerprints] section; '
32273
2e455cbeac50 sslutil: tweak the legacy [hostfingerprints] warning message
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32247
diff changeset
   836
                              'if you trust this fingerprint, remove the old '
2e455cbeac50 sslutil: tweak the legacy [hostfingerprints] warning message
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32247
diff changeset
   837
                              'SHA-1 fingerprint from [hostfingerprints] and '
2e455cbeac50 sslutil: tweak the legacy [hostfingerprints] warning message
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32247
diff changeset
   838
                              'add the following entry to the new '
2e455cbeac50 sslutil: tweak the legacy [hostfingerprints] warning message
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32247
diff changeset
   839
                              '[hostsecurity] section: %s:fingerprints=%s)\n') %
2e455cbeac50 sslutil: tweak the legacy [hostfingerprints] warning message
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32247
diff changeset
   840
                            (host, host, nicefingerprint))
29291
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29290
diff changeset
   841
                return
28850
3819c349b194 sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28849
diff changeset
   842
29293
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
   843
        # Pinned fingerprint didn't match. This is a fatal error.
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
   844
        if settings['legacyfingerprint']:
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
   845
            section = 'hostfingerprint'
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
   846
            nice = fmtfingerprint(peerfingerprints['sha1'])
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
   847
        else:
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
   848
            section = 'hostsecurity'
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
   849
            nice = '%s:%s' % (hash, fmtfingerprint(peerfingerprints[hash]))
29291
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29290
diff changeset
   850
        raise error.Abort(_('certificate for %s has unexpected '
29293
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
   851
                            'fingerprint %s') % (host, nice),
29291
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29290
diff changeset
   852
                          hint=_('check %s configuration') % section)
28850
3819c349b194 sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28849
diff changeset
   853
29411
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
   854
    # Security is enabled but no CAs are loaded. We can't establish trust
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
   855
    # for the cert so abort.
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   856
    if not sock._hgstate['caloaded']:
29411
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
   857
        raise error.Abort(
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
   858
            _('unable to verify security of %s (no loaded CA certificates); '
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
   859
              'refusing to connect') % host,
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
   860
            hint=_('see https://mercurial-scm.org/wiki/SecureConnections for '
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
   861
                   'how to configure Mercurial to avoid this error or set '
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
   862
                   'hostsecurity.%s:fingerprints=%s to trust this server') %
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
   863
                   (host, nicefingerprint))
29113
5b9577edf745 sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29112
diff changeset
   864
36745
424994a0adfd sslutil: lots of unicode/bytes cleanup
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   865
    msg = _verifycert(peercert2, shost)
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   866
    if msg:
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   867
        raise error.Abort(_('%s certificate error: %s') % (host, msg),
29292
bc5f55493397 sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29291
diff changeset
   868
                         hint=_('set hostsecurity.%s:certfingerprints=%s '
bc5f55493397 sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29291
diff changeset
   869
                                'config setting or use --insecure to connect '
bc5f55493397 sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29291
diff changeset
   870
                                'insecurely') %
bc5f55493397 sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29291
diff changeset
   871
                              (host, nicefingerprint))