mercurial/sslutil.py
author Gregory Szorc <gregory.szorc@gmail.com>
Thu, 14 Jul 2016 20:47:22 -0700
changeset 29559 7dec5e441bf7
parent 29558 a935cd7d51a6
child 29560 303e9300772a
permissions -rw-r--r--
sslutil: config option to specify TLS protocol version Currently, Mercurial will use TLS 1.0 or newer when connecting to remote servers, selecting the highest TLS version supported by both peers. On older Pythons, only TLS 1.0 is available. On newer Pythons, TLS 1.1 and 1.2 should be available. Security-minded people may want to not take any risks running TLS 1.0 (or even TLS 1.1). This patch gives those people a config option to explicitly control which TLS versions Mercurial should use. By providing this option, one can require newer TLS versions before they are formally deprecated by Mercurial/Python/OpenSSL/etc and lower their security exposure. This option also provides an easy mechanism to change protocol policies in Mercurial. If there is a 0-day and TLS 1.0 is completely broken, we can act quickly without changing much code. Because setting the minimum TLS protocol is something you'll likely want to do globally, this patch introduces a global config option under [hostsecurity] for that purpose. wrapserversocket() has been taught a hidden config option to define the explicit protocol to use. This is queried in this function and not passed as an argument because I don't want to expose this dangerous option as part of the Python API. There is a risk someone could footgun themselves. But the config option is a devel option, has a warning comment, and I doubt most people are using `hg serve` to run a production HTTPS server (I would have something not Mercurial/Python handle TLS). If this is problematic, we can go back to using a custom extension in tests to coerce the server into bad behavior.
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
import sys
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25432
diff changeset
    17
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25432
diff changeset
    18
from .i18n import _
28577
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28525
diff changeset
    19
from . import (
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28525
diff changeset
    20
    error,
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28525
diff changeset
    21
    util,
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28525
diff changeset
    22
)
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
    23
28647
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
    24
# 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
    25
# 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
    26
# 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
    27
#
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
    28
# 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
    29
# 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
    30
# 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
    31
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
    32
configprotocols = set([
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
    33
    'tls1.0',
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
    34
    'tls1.1',
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
    35
    'tls1.2',
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
    36
])
26622
9e15286609ae sslutil: expose attribute indicating whether SNI is supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26587
diff changeset
    37
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
    38
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
    39
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    40
try:
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    41
    # 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
    42
    # SSL/TLS features are available.
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    43
    SSLContext = ssl.SSLContext
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    44
    modernssl = True
28650
737863b01d9f sslutil: move _canloaddefaultcerts logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28649
diff changeset
    45
    _canloaddefaultcerts = util.safehasattr(SSLContext, 'load_default_certs')
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    46
except AttributeError:
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    47
    modernssl = False
28650
737863b01d9f sslutil: move _canloaddefaultcerts logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28649
diff changeset
    48
    _canloaddefaultcerts = False
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    49
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    50
    # 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
    51
    class SSLContext(object):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    52
        # ssl.wrap_socket gained the "ciphers" named argument in 2.7.
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    53
        _supportsciphers = sys.version_info >= (2, 7)
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    54
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    55
        def __init__(self, protocol):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    56
            # From the public interface of SSLContext
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    57
            self.protocol = protocol
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    58
            self.check_hostname = False
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    59
            self.options = 0
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    60
            self.verify_mode = ssl.CERT_NONE
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    61
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    62
            # Used by our implementation.
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    63
            self._certfile = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    64
            self._keyfile = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    65
            self._certpassword = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    66
            self._cacerts = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    67
            self._ciphers = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    68
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    69
        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
    70
            self._certfile = certfile
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    71
            self._keyfile = keyfile
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    72
            self._certpassword = password
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    73
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    74
        def load_default_certs(self, purpose=None):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    75
            pass
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    76
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    77
        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
    78
            if capath:
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 29341
diff changeset
    79
                raise error.Abort(_('capath not supported'))
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    80
            if cadata:
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 29341
diff changeset
    81
                raise error.Abort(_('cadata not supported'))
28649
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
            self._cacerts = cafile
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    84
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    85
        def set_ciphers(self, ciphers):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    86
            if not self._supportsciphers:
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 29341
diff changeset
    87
                raise error.Abort(_('setting ciphers 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._ciphers = ciphers
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 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
    92
            # 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
    93
            # 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
    94
            # 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
    95
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    96
            args = {
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    97
                'keyfile': self._keyfile,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    98
                'certfile': self._certfile,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
    99
                'server_side': server_side,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
   100
                'cert_reqs': self.verify_mode,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
   101
                'ssl_version': self.protocol,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
   102
                'ca_certs': self._cacerts,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
   103
            }
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
   104
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
   105
            if self._supportsciphers:
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
   106
                args['ciphers'] = self._ciphers
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
            return ssl.wrap_socket(socket, **args)
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
   109
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   110
def _hostsettings(ui, hostname):
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   111
    """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
   112
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   113
    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
   114
    """
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   115
    s = {
29288
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   116
        # 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
   117
        # 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
   118
        'allowloaddefaultcerts': True,
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   119
        # 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
   120
        'certfingerprints': [],
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   121
        # 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
   122
        # SSLContext.load_verify_locations().
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   123
        'cafile': None,
29287
fbccb334efe7 sslutil: store flag for whether cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29286
diff changeset
   124
        # 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
   125
        'disablecertverification': False,
29268
f200b58497f1 sslutil: reference appropriate config section in messaging
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29267
diff changeset
   126
        # 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
   127
        'legacyfingerprint': False,
29507
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   128
        # PROTOCOL_* constant to use for SSLContext.__init__.
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   129
        'protocol': None,
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   130
        # 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
   131
        'verifymode': None,
29508
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
   132
        # 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
   133
        'ctxoptions': None,
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   134
    }
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   135
29507
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   136
    # Despite its name, PROTOCOL_SSLv23 selects the highest protocol
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   137
    # that both ends support, including TLS protocols. On legacy stacks,
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   138
    # the highest it likely goes is TLS 1.0. On modern stacks, it can
29507
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   139
    # support TLS 1.2.
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   140
    #
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   141
    # The PROTOCOL_TLSv* constants select a specific TLS version
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   142
    # only (as opposed to multiple versions). So the method for
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   143
    # supporting multiple TLS versions is to use PROTOCOL_SSLv23 and
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   144
    # disable protocols via SSLContext.options and OP_NO_* constants.
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   145
    # However, SSLContext.options doesn't work unless we have the
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   146
    # full/real SSLContext available to us.
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   147
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   148
    # 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
   149
    def validateprotocol(protocol, key):
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   150
        if protocol not in configprotocols:
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   151
            raise error.Abort(
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   152
                _('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
   153
                (key, protocol),
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   154
                hint=_('valid protocols: %s') %
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   155
                     ' '.join(sorted(configprotocols)))
29507
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   156
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   157
    key = 'minimumprotocol'
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   158
    # Default to TLS 1.0+ as that is what browsers are currently doing.
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   159
    protocol = ui.config('hostsecurity', key, 'tls1.0')
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   160
    validateprotocol(protocol, key)
29508
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
   161
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   162
    key = '%s:minimumprotocol' % hostname
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   163
    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
   164
    validateprotocol(protocol, key)
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   165
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   166
    s['protocol'], s['ctxoptions'] = protocolsettings(protocol)
29558
a935cd7d51a6 sslutil: prevent CRIME
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29557
diff changeset
   167
29267
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   168
    # 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
   169
    # of <alg>:<fingerprint> strings.
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   170
    fingerprints = ui.configlist('hostsecurity', '%s:fingerprints' % hostname,
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   171
                                 [])
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   172
    for fingerprint in fingerprints:
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   173
        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
   174
            raise error.Abort(_('invalid fingerprint for %s: %s') % (
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   175
                                hostname, fingerprint),
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   176
                              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
   177
                                     'or "sha512:"'))
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   178
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   179
        alg, fingerprint = fingerprint.split(':', 1)
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   180
        fingerprint = fingerprint.replace(':', '').lower()
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   181
        s['certfingerprints'].append((alg, fingerprint))
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
   182
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   183
    # Fingerprints from [hostfingerprints] are always SHA-1.
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   184
    for fingerprint in ui.configlist('hostfingerprints', hostname, []):
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   185
        fingerprint = fingerprint.replace(':', '').lower()
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   186
        s['certfingerprints'].append(('sha1', fingerprint))
29268
f200b58497f1 sslutil: reference appropriate config section in messaging
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29267
diff changeset
   187
        s['legacyfingerprint'] = True
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   188
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   189
    # 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
   190
    # 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
   191
    if s['certfingerprints']:
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   192
        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
   193
        s['allowloaddefaultcerts'] = False
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   194
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   195
    # 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
   196
    elif ui.insecureconnections:
29287
fbccb334efe7 sslutil: store flag for whether cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29286
diff changeset
   197
        s['disablecertverification'] = True
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   198
        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
   199
        s['allowloaddefaultcerts'] = False
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   200
29288
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   201
    if ui.configbool('devel', 'disableloaddefaultcerts'):
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   202
        s['allowloaddefaultcerts'] = False
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   203
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   204
    # 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
   205
    # 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
   206
    # being performed.
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   207
    cafile = ui.config('hostsecurity', '%s:verifycertsfile' % hostname)
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   208
    if s['certfingerprints'] and cafile:
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   209
        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
   210
                  'fingerprints defined; using host fingerprints for '
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   211
                  'verification)\n') % hostname)
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   212
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   213
    # 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
   214
    # makes it not necessary.
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   215
    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
   216
        # 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
   217
        if cafile:
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   218
            cafile = util.expandpath(cafile)
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   219
            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
   220
                raise error.Abort(_('path specified by %s does not exist: %s') %
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   221
                                  ('hostsecurity.%s:verifycertsfile' % hostname,
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   222
                                   cafile))
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   223
            s['cafile'] = cafile
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   224
        else:
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   225
            # 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
   226
            cafile = ui.config('web', 'cacerts')
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   227
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   228
            if cafile:
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   229
                cafile = util.expandpath(cafile)
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   230
                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
   231
                    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
   232
                                      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
   233
            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
   234
                # 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
   235
                cafile = _defaultcacerts(ui)
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   236
                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
   237
                    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
   238
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
   239
            s['cafile'] = cafile
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   240
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   241
        # 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
   242
        # 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
   243
        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
   244
            s['verifymode'] = ssl.CERT_REQUIRED
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   245
        else:
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   246
            # 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
   247
            # 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
   248
            # 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
   249
            # 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
   250
            # user).
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   251
            s['verifymode'] = ssl.CERT_NONE
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   252
29507
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   253
    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
   254
    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
   255
    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
   256
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   257
    return s
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   258
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   259
def protocolsettings(protocol):
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   260
    """Resolve the protocol and context options for a config value."""
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   261
    if protocol not in configprotocols:
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   262
        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
   263
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   264
    # Legacy ssl module only supports up to TLS 1.0. Ideally we'd use
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   265
    # PROTOCOL_SSLv23 and options to disable SSLv2 and SSLv3. However,
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   266
    # SSLContext.options doesn't work in our implementation since we use
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   267
    # a fake SSLContext on these Python versions.
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   268
    if not modernssl:
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   269
        if protocol != 'tls1.0':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   270
            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
   271
                                'setting %s') % protocol,
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   272
                              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
   273
                                     '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
   274
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   275
        return ssl.PROTOCOL_TLSv1, 0
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   276
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   277
    # 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
   278
    # 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
   279
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   280
    # 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
   281
    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
   282
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   283
    if protocol == 'tls1.0':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   284
        # 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
   285
        pass
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   286
    elif protocol == 'tls1.1':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   287
        options |= ssl.OP_NO_TLSv1
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   288
    elif protocol == 'tls1.2':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   289
        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
   290
    else:
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   291
        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
   292
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   293
    # Prevent CRIME.
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   294
    # 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
   295
    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
   296
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   297
    return ssl.PROTOCOL_SSLv23, options
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   298
29249
cca59ef27e60 sslutil: move sslkwargs logic into internal function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29248
diff changeset
   299
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
   300
    """Add SSL/TLS to a socket.
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   301
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   302
    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
   303
    choices based on what security options are available.
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   304
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   305
    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
   306
    the following additional arguments:
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   307
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   308
    * 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
   309
      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
   310
      to use.
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
   311
    """
29224
7424f4294199 sslutil: require serverhostname argument (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29115
diff changeset
   312
    if not serverhostname:
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 29341
diff changeset
   313
        raise error.Abort(_('serverhostname argument is required'))
29224
7424f4294199 sslutil: require serverhostname argument (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29115
diff changeset
   314
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   315
    settings = _hostsettings(ui, serverhostname)
29249
cca59ef27e60 sslutil: move sslkwargs logic into internal function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29248
diff changeset
   316
29557
53de8255ec4e sslutil: update comment about create_default_context()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29554
diff changeset
   317
    # 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
   318
    # 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
   319
    # 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
   320
    # 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
   321
    # 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
   322
    # 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
   323
    # choice.
29507
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   324
    sslcontext = SSLContext(settings['protocol'])
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
   325
29508
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
   326
    # 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
   327
    sslcontext.options |= settings['ctxoptions']
28651
4827d07073e6 sslutil: always use SSLContext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28650
diff changeset
   328
28848
e330db205b20 sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28653
diff changeset
   329
    # 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
   330
    sslcontext.verify_mode = settings['verifymode']
28848
e330db205b20 sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28653
diff changeset
   331
28652
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   332
    if certfile is not None:
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   333
        def password():
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   334
            f = keyfile or certfile
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   335
            return ui.getpass(_('passphrase for %s: ') % f, '')
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   336
        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
   337
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
   338
    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
   339
        try:
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
   340
            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
   341
        except ssl.SSLError as e:
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
   342
            raise error.Abort(_('error loading CA file %s: %s') % (
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
   343
                              settings['cafile'], e.args[1]),
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
   344
                              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
   345
        caloaded = True
29288
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   346
    elif settings['allowloaddefaultcerts']:
28652
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   347
        # 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
   348
        sslcontext.load_default_certs()
29288
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   349
        caloaded = True
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   350
    else:
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
   351
        caloaded = False
23834
bf07c19b4c82 https: support tls sni (server name indication) for https urls (issue3090)
Alex Orange <crazycasta@gmail.com>
parents: 23069
diff changeset
   352
29449
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   353
    try:
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   354
        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
   355
    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
   356
        # 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
   357
        # 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
   358
        # a hint to the user.
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   359
        # 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
   360
        # only show this warning if modern ssl is available.
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   361
        if (caloaded and settings['verifymode'] == ssl.CERT_REQUIRED and
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   362
            modernssl and not sslcontext.get_ca_certs()):
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   363
            ui.warn(_('(an attempt was made to load CA certificates but none '
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   364
                      'were loaded; see '
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   365
                      'https://mercurial-scm.org/wiki/SecureConnections for '
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   366
                      'how to configure Mercurial to avoid this error)\n'))
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   367
        # 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
   368
        if util.safehasattr(e, 'reason'):
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   369
            if e.reason == 'UNSUPPORTED_PROTOCOL':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   370
                ui.warn(_('(could not negotiate a common protocol; see '
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   371
                          'https://mercurial-scm.org/wiki/SecureConnections '
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   372
                          'for how to configure Mercurial to avoid this '
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   373
                          'error)\n'))
29449
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   374
        raise
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
   375
28652
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   376
    # 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
   377
    # closed
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   378
    # - see http://bugs.python.org/issue13721
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   379
    if not sslsocket.cipher():
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   380
        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
   381
29225
b115eed11780 sslutil: use a dict for hanging hg state off the wrapped socket
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29224
diff changeset
   382
    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
   383
        'caloaded': caloaded,
29226
33006bd6a1d7 sslutil: store and use hostname and ui in socket instance
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29225
diff changeset
   384
        'hostname': serverhostname,
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
   385
        'settings': settings,
29226
33006bd6a1d7 sslutil: store and use hostname and ui in socket instance
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29225
diff changeset
   386
        '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
   387
    }
29113
5b9577edf745 sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29112
diff changeset
   388
28652
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
   389
    return sslsocket
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   390
29554
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   391
def wrapserversocket(sock, ui, certfile=None, keyfile=None, cafile=None,
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   392
                     requireclientcert=False):
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   393
    """Wrap a socket for use by servers.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   394
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   395
    ``certfile`` and ``keyfile`` specify the files containing the certificate's
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   396
    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
   397
    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
   398
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   399
    ``cafile`` defines the path to certificate authorities.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   400
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   401
    ``requireclientcert`` specifies whether to require client certificates.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   402
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   403
    Typically ``cafile`` is only defined if ``requireclientcert`` is true.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   404
    """
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   405
    protocol, options = protocolsettings('tls1.0')
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   406
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   407
    # 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
   408
    # 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
   409
    exactprotocol = ui.config('devel', 'serverexactprotocol')
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   410
    if exactprotocol == 'tls1.0':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   411
        protocol = ssl.PROTOCOL_TLSv1
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   412
    elif exactprotocol == 'tls1.1':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   413
        protocol = ssl.PROTOCOL_TLSv1_1
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   414
    elif exactprotocol == 'tls1.2':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   415
        protocol = ssl.PROTOCOL_TLSv1_2
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   416
    elif exactprotocol:
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   417
        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
   418
                          exactprotocol)
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   419
29554
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   420
    if modernssl:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   421
        # 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
   422
        # 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
   423
        # 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
   424
        sslcontext = SSLContext(protocol)
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   425
        sslcontext.options |= options
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
   426
29554
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   427
        # Improve forward secrecy.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   428
        sslcontext.options |= getattr(ssl, 'OP_SINGLE_DH_USE', 0)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   429
        sslcontext.options |= getattr(ssl, 'OP_SINGLE_ECDH_USE', 0)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   430
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   431
        # 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
   432
        if util.safehasattr(ssl, '_RESTRICTED_SERVER_CIPHERS'):
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   433
            sslcontext.options |= getattr(ssl, 'OP_CIPHER_SERVER_PREFERENCE', 0)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   434
            sslcontext.set_ciphers(ssl._RESTRICTED_SERVER_CIPHERS)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   435
    else:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   436
        sslcontext = SSLContext(ssl.PROTOCOL_TLSv1)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   437
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   438
    if requireclientcert:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   439
        sslcontext.verify_mode = ssl.CERT_REQUIRED
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   440
    else:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   441
        sslcontext.verify_mode = ssl.CERT_NONE
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   442
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   443
    if certfile or keyfile:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   444
        sslcontext.load_cert_chain(certfile=certfile, keyfile=keyfile)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   445
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   446
    if cafile:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   447
        sslcontext.load_verify_locations(cafile=cafile)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   448
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   449
    return sslcontext.wrap_socket(sock, server_side=True)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
   450
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   451
class wildcarderror(Exception):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   452
    """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
   453
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   454
def _dnsnamematch(dn, hostname, maxwildcards=1):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   455
    """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
   456
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   457
    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
   458
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   459
    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
   460
    the value in ``dn``.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   461
    """
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   462
    pats = []
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   463
    if not dn:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   464
        return False
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   465
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   466
    pieces = dn.split(r'.')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   467
    leftmost = pieces[0]
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   468
    remainder = pieces[1:]
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   469
    wildcards = leftmost.count('*')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   470
    if wildcards > maxwildcards:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   471
        raise wildcarderror(
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   472
            _('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
   473
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   474
    # 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
   475
    if not wildcards:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   476
        return dn.lower() == hostname.lower()
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   477
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   478
    # 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
   479
    # 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
   480
    # 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
   481
    if leftmost == '*':
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   482
        # 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
   483
        # fragment.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   484
        pats.append('[^.]+')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   485
    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
   486
        # 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
   487
        # 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
   488
        # 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
   489
        # 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
   490
        pats.append(re.escape(leftmost))
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   491
    else:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   492
        # 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
   493
        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
   494
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   495
    # 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
   496
    for frag in remainder:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   497
        pats.append(re.escape(frag))
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   498
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   499
    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
   500
    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
   501
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   502
def _verifycert(cert, hostname):
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   503
    '''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
   504
    CRLs is not handled.
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   505
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   506
    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
   507
    '''
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   508
    if not cert:
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   509
        return _('no certificate received')
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   510
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   511
    dnsnames = []
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   512
    san = cert.get('subjectAltName', [])
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   513
    for key, value in san:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   514
        if key == 'DNS':
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   515
            try:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   516
                if _dnsnamematch(value, hostname):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   517
                    return
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   518
            except wildcarderror as e:
29460
a7d1532b26a1 sslutil: don't access message attribute in exception (issue5285)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29452
diff changeset
   519
                return e.args[0]
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   520
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   521
            dnsnames.append(value)
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   522
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   523
    if not dnsnames:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   524
        # The subject is only checked when there is no DNS in subjectAltName.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   525
        for sub in cert.get('subject', []):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   526
            for key, value in sub:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   527
                # 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
   528
                # be used.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   529
                if key == 'commonName':
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   530
                    # 'subject' entries are unicide.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   531
                    try:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   532
                        value = value.encode('ascii')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   533
                    except UnicodeEncodeError:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   534
                        return _('IDN in certificate not supported')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   535
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   536
                    try:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   537
                        if _dnsnamematch(value, hostname):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   538
                            return
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   539
                    except wildcarderror as e:
29460
a7d1532b26a1 sslutil: don't access message attribute in exception (issue5285)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29452
diff changeset
   540
                        return e.args[0]
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   541
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   542
                    dnsnames.append(value)
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   543
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   544
    if len(dnsnames) > 1:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   545
        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
   546
    elif len(dnsnames) == 1:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   547
        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
   548
    else:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
   549
        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
   550
23042
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
   551
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
   552
    """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
   553
    * 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
   554
      system
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
   555
    * 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
   556
      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
   557
      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
   558
    """
24614
241d98d84aed ssl: resolve symlink before checking for Apple python executable (issue4588)
Yuya Nishihara <yuya@tcha.org>
parents: 24291
diff changeset
   559
    if sys.platform != 'darwin' or util.mainfrozen() or not sys.executable:
23042
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
   560
        return False
24614
241d98d84aed ssl: resolve symlink before checking for Apple python executable (issue4588)
Yuya Nishihara <yuya@tcha.org>
parents: 24291
diff changeset
   561
    exe = os.path.realpath(sys.executable).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
   562
    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
   563
            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
   564
29500
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   565
_systemcacertpaths = [
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   566
    # 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
   567
    '/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
   568
    # Debian, Ubuntu, Gentoo
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   569
    '/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
   570
]
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   571
29483
918dce4b8c26 sslutil: pass ui to _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29482
diff changeset
   572
def _defaultcacerts(ui):
29488
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29487
diff changeset
   573
    """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
   574
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29487
diff changeset
   575
    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
   576
    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
   577
    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
   578
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   579
    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
   580
    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
   581
    """
29486
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
   582
    # The "certifi" Python package provides certificates. If it is installed,
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
   583
    # assume the user intends it to be used and use it.
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
   584
    try:
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
   585
        import certifi
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
   586
        certs = certifi.where()
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
   587
        ui.debug('using ca certificates from certifi\n')
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
   588
        return certs
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
   589
    except ImportError:
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
   590
        pass
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
   591
29489
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   592
    # 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
   593
    # 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
   594
    # 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
   595
    # 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
   596
    # Assertion: this code is only called if certificates are being verified.
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   597
    if os.name == 'nt':
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   598
        if not _canloaddefaultcerts:
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   599
            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
   600
                      '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
   601
                      '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
   602
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   603
        return None
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
   604
29487
cdcb5747dc88 sslutil: document the Apple OpenSSL cert trick
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29486
diff changeset
   605
    # 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
   606
    # 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
   607
    # trick.
24288
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
   608
    if _plainapplepython():
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
   609
        dummycert = os.path.join(os.path.dirname(__file__), 'dummycert.pem')
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
   610
        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
   611
            return dummycert
29107
c8fbfb9163ce sslutil: move code examining _canloaddefaultcerts out of _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29106
diff changeset
   612
29499
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
   613
    # 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
   614
    # load system certs, we're out of luck.
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
   615
    if sys.platform == 'darwin':
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
   616
        # 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
   617
        # 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
   618
        # Mercurial install.
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
   619
        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
   620
            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
   621
                      '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
   622
                      '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
   623
        return None
24288
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
   624
29537
5f8b36d5a6ec sslutil: add assertion to prevent accidental CA usage on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29508
diff changeset
   625
    # / 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
   626
    # 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
   627
    # by non-admin users.
5f8b36d5a6ec sslutil: add assertion to prevent accidental CA usage on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29508
diff changeset
   628
    assert os.name != 'nt'
5f8b36d5a6ec sslutil: add assertion to prevent accidental CA usage on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29508
diff changeset
   629
29500
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   630
    # 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
   631
    # 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
   632
    # 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
   633
    # 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
   634
    # 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
   635
    # 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
   636
    # last resort.
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   637
    if not _canloaddefaultcerts:
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   638
        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
   639
            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
   640
                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
   641
                          '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
   642
                          'configured; see '
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   643
                          '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
   644
                          '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
   645
                          'message)\n') % path)
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   646
                return path
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   647
29500
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
   648
        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
   649
                  '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
   650
                  '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
   651
29107
c8fbfb9163ce sslutil: move code examining _canloaddefaultcerts out of _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29106
diff changeset
   652
    return None
24288
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
   653
29286
a05a91a3f120 sslutil: remove "strict" argument from validatesocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29268
diff changeset
   654
def validatesocket(sock):
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   655
    """Validate a socket meets security requiremnets.
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
   656
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   657
    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
   658
    """
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   659
    host = sock._hgstate['hostname']
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   660
    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
   661
    settings = sock._hgstate['settings']
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
   662
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   663
    try:
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   664
        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
   665
        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
   666
    except AttributeError:
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   667
        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
   668
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   669
    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
   670
        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
   671
                           'no certificate received') % host)
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
   672
29289
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
   673
    if settings['disablecertverification']:
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
   674
        # 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
   675
        # 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
   676
        # 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
   677
        # 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
   678
        # 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
   679
        # value.
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
   680
        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
   681
                  '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
   682
                  '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
   683
        return
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
   684
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   685
    # 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
   686
    # validate the remote cert.
29262
dfc4f08aa160 sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29260
diff changeset
   687
    peerfingerprints = {
29341
0d83ad967bf8 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents: 29334
diff changeset
   688
        'sha1': hashlib.sha1(peercert).hexdigest(),
0d83ad967bf8 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents: 29334
diff changeset
   689
        'sha256': hashlib.sha256(peercert).hexdigest(),
0d83ad967bf8 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents: 29334
diff changeset
   690
        'sha512': hashlib.sha512(peercert).hexdigest(),
29262
dfc4f08aa160 sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29260
diff changeset
   691
    }
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
   692
29290
01248c37a68e sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29289
diff changeset
   693
    def fmtfingerprint(s):
01248c37a68e sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29289
diff changeset
   694
        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
   695
01248c37a68e sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29289
diff changeset
   696
    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
   697
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   698
    if settings['certfingerprints']:
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
   699
        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
   700
            if peerfingerprints[hash].lower() == fingerprint:
29291
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29290
diff changeset
   701
                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
   702
                         (host, hash, fmtfingerprint(fingerprint)))
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29290
diff changeset
   703
                return
28850
3819c349b194 sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28849
diff changeset
   704
29293
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
   705
        # 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
   706
        if settings['legacyfingerprint']:
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
   707
            section = 'hostfingerprint'
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
   708
            nice = fmtfingerprint(peerfingerprints['sha1'])
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
   709
        else:
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
   710
            section = 'hostsecurity'
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
   711
            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
   712
        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
   713
                            'fingerprint %s') % (host, nice),
29291
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29290
diff changeset
   714
                          hint=_('check %s configuration') % section)
28850
3819c349b194 sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28849
diff changeset
   715
29411
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
   716
    # 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
   717
    # 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
   718
    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
   719
        raise error.Abort(
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
   720
            _('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
   721
              'refusing to connect') % host,
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
   722
            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
   723
                   '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
   724
                   '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
   725
                   (host, nicefingerprint))
29113
5b9577edf745 sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29112
diff changeset
   726
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   727
    msg = _verifycert(peercert2, host)
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   728
    if msg:
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
   729
        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
   730
                         hint=_('set hostsecurity.%s:certfingerprints=%s '
bc5f55493397 sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29291
diff changeset
   731
                                '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
   732
                                'insecurely') %
bc5f55493397 sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29291
diff changeset
   733
                              (host, nicefingerprint))