[PATCH 7 of 8] sslutil: allow fingerprints to be specified in [hostsecurity]

Gregory Szorc gregory.szorc at gmail.com
Sun May 29 12:48:33 EDT 2016


On Sat, May 28, 2016 at 7:14 PM, timeless <timeless at gmail.com> wrote:

> Please provide an example of a host with two fingerprints (load balancing
> or incremental rollout)
>

The last added line in config.txt does this.


> On May 28, 2016 4:05 PM, "Gregory Szorc" <gregory.szorc at gmail.com> wrote:
>
>> # HG changeset patch
>> # User Gregory Szorc <gregory.szorc at gmail.com>
>> # Date 1464464256 25200
>> #      Sat May 28 12:37:36 2016 -0700
>> # Node ID 969eddf5985326d5c4fd26da95fa19247339e6a0
>> # Parent  fb7b49629e9c961517f576e8edfdfdc2bdb6d0e9
>> sslutil: allow fingerprints to be specified in [hostsecurity]
>>
>> We introduce the [hostsecurity] config section. It holds per-host
>> security settings.
>>
>> Currently, the section only contains a "fingerprints" option,
>> which behaves like [hostfingerprints] but supports specifying the
>> hashing algorithm.
>>
>> There is still some follow-up work, such as changing some error
>> messages.
>>
>> diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
>> --- a/mercurial/help/config.txt
>> +++ b/mercurial/help/config.txt
>> @@ -971,16 +971,18 @@ environment variables above are passed a
>>
>>  If a Python hook returns a "true" value or raises an exception, this
>>  is treated as a failure.
>>
>>
>>  ``hostfingerprints``
>>  --------------------
>>
>> +(Deprecated. Use ``[hostsecurity]``'s ``fingerprints`` options instead.)
>> +
>>  Fingerprints of the certificates of known HTTPS servers.
>>
>>  A HTTPS connection to a server with a fingerprint configured here will
>>  only succeed if the servers certificate matches the fingerprint.
>>  This is very similar to how ssh known hosts works.
>>
>>  The fingerprint is the SHA-1 hash value of the DER encoded certificate.
>>  Multiple values can be specified (separated by spaces or commas). This
>> can
>> @@ -990,16 +992,49 @@ to a new certificate.
>>  The CA chain and web.cacerts is not used for servers with a fingerprint.
>>
>>  For example::
>>
>>      [hostfingerprints]
>>      hg.intevation.de =
>> fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
>>      hg.intevation.org =
>> fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
>>
>> +``hostsecurity``
>> +----------------
>> +
>> +Used to specify per-host security settings.
>> +
>> +Options in this section have the form ``hostname``:``setting``. This
>> allows
>> +multiple settings to be defined on a per-host basis.
>> +
>> +The following per-host settings can be defined.
>> +
>> +``fingerprints``
>> +    A list of hashes of the DER encoded peer/remote certificate. Values
>> have
>> +    the form ``algorithm``:``fingerprint``. e.g.
>> +
>> ``sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2``.
>> +
>> +    The following algorithms/prefixes are supported: ``sha1``,
>> ``sha256``,
>> +    ``sha512``.
>> +
>> +    Use of ``sha256`` or ``sha512`` is preferred.
>> +
>> +    If a fingerprint is specified, the CA chain is not validated for this
>> +    host and Mercurial will require the remote certificate to match one
>> +    of the fingerprints specified. This means if the server updates its
>> +    certificate, Mercurial will abort until a new fingerprint is defined.
>> +    This can provide stronger security than traditional CA-based
>> validation
>> +    at the expense of convenience.
>> +
>> +For example::
>> +
>> +    [hostsecurity]
>> +    hg.example.com:fingerprints =
>> sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2
>> +    hg2.example.com:fingerprints =
>> sha1:914f1aff87249c09b6859b88b1906d30756491ca,
>> sha1:fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
>> +
>>  ``http_proxy``
>>  --------------
>>
>>  Used to access web-based Mercurial repositories through a HTTP
>>  proxy.
>>
>>  ``host``
>>      Host name and (optional) port of the proxy server, for example
>> diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
>> --- a/mercurial/sslutil.py
>> +++ b/mercurial/sslutil.py
>> @@ -116,16 +116,31 @@ def _hostsettings(ui, hostname):
>>          'certfingerprints': [],
>>          # Path to file containing concatenated CA certs. Used by
>>          # SSLContext.load_verify_locations().
>>          'cafile': None,
>>          # ssl.CERT_* constant used by SSLContext.verify_mode.
>>          'verifymode': None,
>>      }
>>
>> +    # Look for fingerprints in [hostsecurity] section. Value is a list
>> +    # of <alg>:<fingerprint> strings.
>> +    fingerprints = ui.configlist('hostsecurity', '%s:fingerprints' %
>> hostname,
>> +                                 [])
>> +    for fingerprint in fingerprints:
>> +        if not (fingerprint.startswith(('sha1:', 'sha256:', 'sha512:'))):
>> +            raise error.Abort(_('invalid fingerprint for %s: %s') % (
>> +                                hostname, fingerprint),
>> +                              hint=_('must begin with "sha1:",
>> "sha256:", '
>> +                                     'or "sha512:"'))
>> +
>> +        alg, fingerprint = fingerprint.split(':', 1)
>> +        fingerprint = fingerprint.replace(':', '').lower()
>> +        s['certfingerprints'].append((alg, fingerprint))
>> +
>>      # Fingerprints from [hostfingerprints] are always SHA-1.
>>      for fingerprint in ui.configlist('hostfingerprints', hostname, []):
>>          fingerprint = fingerprint.replace(':', '').lower()
>>          s['certfingerprints'].append(('sha1', fingerprint))
>>
>>      # If a host cert fingerprint is defined, it is the only thing that
>>      # matters. No need to validate CA certs.
>>      if s['certfingerprints']:
>> diff --git a/tests/test-https.t b/tests/test-https.t
>> --- a/tests/test-https.t
>> +++ b/tests/test-https.t
>> @@ -277,35 +277,53 @@ Test server cert which no longer is vali
>>    $ cat hg2.pid >> $DAEMON_PIDS
>>    $ hg -R copy-pull pull --config web.cacerts=pub-expired.pem
>> https://localhost:$HGPORT2/
>>    pulling from https://localhost:$HGPORT2/
>>    abort: error: *certificate verify failed* (glob)
>>    [255]
>>
>>  Fingerprints
>>
>> -- works without cacerts
>> +- works without cacerts (hostkeyfingerprints)
>>    $ hg -R copy-pull id https://localhost:$HGPORT/ --insecure --config
>> hostfingerprints.localhost=91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca
>>    5fed3813f7f5
>>
>> +- works without cacerts (hostsecurity)
>> +  $ hg -R copy-pull id https://localhost:$HGPORT/ --config
>> hostsecurity.localhost:fingerprints=sha1:914f1aff87249c09b6859b88b1906d30756491ca
>> +  5fed3813f7f5
>> +
>> +  $ hg -R copy-pull id https://localhost:$HGPORT/ --config
>> hostsecurity.localhost:fingerprints=sha256:62:09:97:2f:97:60:e3:65:8f:12:5d:78:9e:35:a1:36:7a:65:4b:0e:9f:ac:db:c3:bc:6e:b6:a3:c0:16:e0:30
>> +  5fed3813f7f5
>> +
>>  - multiple fingerprints specified and first matches
>>    $ hg --config
>> 'hostfingerprints.localhost=914f1aff87249c09b6859b88b1906d30756491ca,
>> deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/
>> --insecure
>>    5fed3813f7f5
>>
>> +  $ hg --config
>> 'hostsecurity.localhost:fingerprints=sha1:914f1aff87249c09b6859b88b1906d30756491ca,
>> sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id
>> https://localhost:$HGPORT/
>> +  5fed3813f7f5
>> +
>>  - multiple fingerprints specified and last matches
>>    $ hg --config
>> 'hostfingerprints.localhost=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef,
>> 914f1aff87249c09b6859b88b1906d30756491ca' -R copy-pull id https://localhost:$HGPORT/
>> --insecure
>>    5fed3813f7f5
>>
>> +  $ hg --config
>> 'hostsecurity.localhost:fingerprints=sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef,
>> sha1:914f1aff87249c09b6859b88b1906d30756491ca' -R copy-pull id
>> https://localhost:$HGPORT/
>> +  5fed3813f7f5
>> +
>>  - multiple fingerprints specified and none match
>>
>>    $ hg --config
>> 'hostfingerprints.localhost=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef,
>> aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/
>> --insecure
>>    abort: certificate for localhost has unexpected fingerprint
>> 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca
>>    (check hostfingerprint configuration)
>>    [255]
>>
>> +  $ hg --config
>> 'hostsecurity.localhost:fingerprints=sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef,
>> sha1:aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id
>> https://localhost:$HGPORT/
>> +  abort: certificate for localhost has unexpected fingerprint
>> 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca
>> +  (check hostfingerprint configuration)
>> +  [255]
>> +
>>  - fails when cert doesn't match hostname (port is ignored)
>>    $ hg -R copy-pull id https://localhost:$HGPORT1/ --config
>> hostfingerprints.localhost=914f1aff87249c09b6859b88b1906d30756491ca
>>    abort: certificate for localhost has unexpected fingerprint
>> 28:ff:71:bf:65:31:14:23:ad:62:92:b4:0e:31:99:18:fc:83:e3:9b
>>    (check hostfingerprint configuration)
>>    [255]
>>
>>
>>  - ignores that certificate doesn't match hostname
>> _______________________________________________
>> Mercurial-devel mailing list
>> Mercurial-devel at mercurial-scm.org
>> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.mercurial-scm.org/pipermail/mercurial-devel/attachments/20160529/5a5d3df2/attachment.html>


More information about the Mercurial-devel mailing list