errors: introduce SecurityError and use it in a few places
This is part of
https://www.mercurial-scm.org/wiki/ErrorCategoriesPlan. There are
perhaps more errors in `sslutil.py` that should raise `SecurityError`;
I picked the most clear ones to start with.
Differential Revision: https://phab.mercurial-scm.org/D9390
--- a/mercurial/error.py Mon Nov 23 16:05:03 2020 -0800
+++ b/mercurial/error.py Mon Nov 23 16:20:02 2020 -0800
@@ -216,6 +216,14 @@
"""
+class SecurityError(Abort):
+ """Indicates that some aspect of security failed.
+
+ Examples: Bad server credentials, expired local credentials for network
+ filesystem, mismatched GPG signature, DoS protection.
+ """
+
+
class HookLoadError(Abort):
"""raised when loading a hook fails, aborting an operation
--- a/mercurial/scmutil.py Mon Nov 23 16:05:03 2020 -0800
+++ b/mercurial/scmutil.py Mon Nov 23 16:20:02 2020 -0800
@@ -228,6 +228,8 @@
detailed_exit_code = 20
elif isinstance(inst, error.ConfigError):
detailed_exit_code = 30
+ elif isinstance(inst, error.SecurityError):
+ detailed_exit_code = 150
elif isinstance(inst, error.CanceledError):
detailed_exit_code = 250
ui.error(inst.format())
--- a/mercurial/sslutil.py Mon Nov 23 16:05:03 2020 -0800
+++ b/mercurial/sslutil.py Mon Nov 23 16:20:02 2020 -0800
@@ -470,7 +470,7 @@
# closed
# - see http://bugs.python.org/issue13721
if not sslsocket.cipher():
- raise error.Abort(_(b'ssl connection failed'))
+ raise error.SecurityError(_(b'ssl connection failed'))
sslsocket._hgstate = {
b'caloaded': caloaded,
@@ -736,10 +736,10 @@
peercert = sock.getpeercert(True)
peercert2 = sock.getpeercert()
except AttributeError:
- raise error.Abort(_(b'%s ssl connection error') % host)
+ raise error.SecurityError(_(b'%s ssl connection error') % host)
if not peercert:
- raise error.Abort(
+ raise error.SecurityError(
_(b'%s certificate error: no certificate received') % host
)
@@ -801,7 +801,7 @@
else:
section = b'hostsecurity'
nice = b'%s:%s' % (hash, fmtfingerprint(peerfingerprints[hash]))
- raise error.Abort(
+ raise error.SecurityError(
_(b'certificate for %s has unexpected fingerprint %s')
% (host, nice),
hint=_(b'check %s configuration') % section,
@@ -810,7 +810,7 @@
# Security is enabled but no CAs are loaded. We can't establish trust
# for the cert so abort.
if not sock._hgstate[b'caloaded']:
- raise error.Abort(
+ raise error.SecurityError(
_(
b'unable to verify security of %s (no loaded CA certificates); '
b'refusing to connect'
@@ -826,7 +826,7 @@
msg = _verifycert(peercert2, shost)
if msg:
- raise error.Abort(
+ raise error.SecurityError(
_(b'%s certificate error: %s') % (host, msg),
hint=_(
b'set hostsecurity.%s:certfingerprints=%s '
--- a/tests/test-https.t Mon Nov 23 16:05:03 2020 -0800
+++ b/tests/test-https.t Mon Nov 23 16:20:02 2020 -0800
@@ -125,7 +125,7 @@
$ hg clone https://localhost:$HGPORT/ copy-pull $DISABLECACERTS
abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect
(see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error or set hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e to trust this server)
- [255]
+ [150]
$ hg clone --insecure https://localhost:$HGPORT/ copy-pull
warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
@@ -160,7 +160,7 @@
pulling from https://localhost:$HGPORT/
abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect
(see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error or set hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e to trust this server)
- [255]
+ [150]
$ hg pull --insecure
pulling from https://localhost:$HGPORT/
@@ -227,7 +227,7 @@
pulling from https://*:$HGPORT/ (glob)
abort: $LOCALIP certificate error: certificate is for localhost (glob)
(set hostsecurity.$LOCALIP:certfingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e config setting or use --insecure to connect insecurely)
- [255]
+ [150]
$ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub.pem" \
> https://$LOCALIP:$HGPORT/ --insecure
pulling from https://*:$HGPORT/ (glob)
@@ -319,18 +319,18 @@
$ hg --config 'hostfingerprints.localhost=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ --insecure
abort: certificate for localhost has unexpected fingerprint ec:d8:7c:d6:b3:86:d0:4f:c1:b8:b4:1c:9d:8f:5e:16:8e:ef:1c:03
(check hostfingerprint configuration)
- [255]
+ [150]
$ hg --config 'hostsecurity.localhost:fingerprints=sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, sha1:aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/
abort: certificate for localhost has unexpected fingerprint sha1:ec:d8:7c:d6:b3:86:d0:4f:c1:b8:b4:1c:9d:8f:5e:16:8e:ef:1c:03
(check hostsecurity configuration)
- [255]
+ [150]
- fails when cert doesn't match hostname (port is ignored)
$ hg -R copy-pull id https://localhost:$HGPORT1/ --config hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03
abort: certificate for localhost has unexpected fingerprint f4:2f:5a:0c:3e:52:5b:db:e7:24:a8:32:1d:18:97:6d:69:b5:87:84
(check hostfingerprint configuration)
- [255]
+ [150]
- ignores that certificate doesn't match hostname
--- a/tests/test-patchbomb-tls.t Mon Nov 23 16:05:03 2020 -0800
+++ b/tests/test-patchbomb-tls.t Mon Nov 23 16:20:02 2020 -0800
@@ -73,7 +73,7 @@
(verifying remote certificate)
abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect
(see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error or set hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e to trust this server)
- [255]
+ [150]
With global certificates: