Mercurial > hg
changeset 26645:2faa7671a4b3
clonebundles: filter on SNI requirement
Server Name Indication (SNI) is commonly used in CDNs and other hosted
environments. Unfortunately, Python <2.7.9 does not support SNI and when
these older Python versions attempt to negotiate TLS to an SNI server,
they raise an opaque error like
"_ssl.c:507: error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert
handshake failure."
We introduce a manifest attribute to denote the URL requires SNI and
have clients without SNI support filter these entries.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Tue, 13 Oct 2015 10:59:41 -0700 |
parents | 74de1c59f71c |
children | 77769354d4ad |
files | hgext/clonebundles.py mercurial/exchange.py tests/test-clonebundles.t |
diffstat | 3 files changed, 53 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/hgext/clonebundles.py Tue Oct 13 11:45:30 2015 -0700 +++ b/hgext/clonebundles.py Tue Oct 13 10:59:41 2015 -0700 @@ -49,6 +49,19 @@ The actual value doesn't impact client behavior beyond filtering: clients will still sniff the bundle type from the header of downloaded files. + +REQUIRESNI + Whether Server Name Indication (SNI) is required to connect to the URL. + SNI allows servers to use multiple certificates on the same IP. It is + somewhat common in CDNs and other hosting providers. Older Python + versions do not support SNI. Defining this attribute enables clients + with older Python versions to filter this entry. + + If this is defined, it is important to advertise a non-SNI fallback + URL or clients running old Python releases may not be able to clone + with the clonebundles facility. + + Value should be "true". """ from mercurial import (
--- a/mercurial/exchange.py Tue Oct 13 11:45:30 2015 -0700 +++ b/mercurial/exchange.py Tue Oct 13 10:59:41 2015 -0700 @@ -12,6 +12,7 @@ import discovery, phases, obsolete, bookmarks as bookmod, bundle2, pushkey import lock as lockmod import streamclone +import sslutil import tags import url as urlmod @@ -1670,6 +1671,11 @@ 'spec: %s\n' % (entry['URL'], str(e))) continue + if 'REQUIRESNI' in entry and not sslutil.hassni: + repo.ui.debug('filtering %s because SNI not supported\n' % + entry['URL']) + continue + newentries.append(entry) return newentries
--- a/tests/test-clonebundles.t Tue Oct 13 11:45:30 2015 -0700 +++ b/tests/test-clonebundles.t Tue Oct 13 10:59:41 2015 -0700 @@ -227,3 +227,37 @@ adding manifests adding file changes added 2 changesets with 2 changes to 2 files + +URLs requiring SNI are filtered in Python <2.7.9 + + $ cp full.hg sni.hg + $ cat > server/.hg/clonebundles.manifest << EOF + > http://localhost:$HGPORT1/sni.hg REQUIRESNI=true + > http://localhost:$HGPORT1/full.hg + > EOF + +#if sslcontext +Python 2.7.9+ support SNI + + $ hg clone -U http://localhost:$HGPORT sni-supported + applying clone bundle from http://localhost:$HGPORT1/sni.hg + adding changesets + adding manifests + adding file changes + added 2 changesets with 2 changes to 2 files + finished applying clone bundle + searching for changes + no changes found +#else +Python <2.7.9 will filter SNI URLs + + $ hg clone -U http://localhost:$HGPORT sni-unsupported + applying clone bundle from http://localhost:$HGPORT1/full.hg + adding changesets + adding manifests + adding file changes + added 2 changesets with 2 changes to 2 files + finished applying clone bundle + searching for changes + no changes found +#endif