[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