Patchwork D9390: errors: introduce SecurityError and use it in a few places

login
register
mail settings
Submitter phabricator
Date Nov. 24, 2020, 6:07 p.m.
Message ID <differential-rev-PHID-DREV-gyugcpzc7zjhv6p3gx5j-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/47669/
State Superseded
Headers show

Comments

phabricator - Nov. 24, 2020, 6:07 p.m.
martinvonz created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  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.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D9390

AFFECTED FILES
  mercurial/error.py
  mercurial/scmutil.py
  mercurial/sslutil.py
  tests/test-https.t
  tests/test-patchbomb-tls.t

CHANGE DETAILS




To: martinvonz, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/tests/test-patchbomb-tls.t b/tests/test-patchbomb-tls.t
--- a/tests/test-patchbomb-tls.t
+++ b/tests/test-patchbomb-tls.t
@@ -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:
 
diff --git a/tests/test-https.t b/tests/test-https.t
--- a/tests/test-https.t
+++ b/tests/test-https.t
@@ -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
diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
--- a/mercurial/sslutil.py
+++ b/mercurial/sslutil.py
@@ -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 '
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -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())
diff --git a/mercurial/error.py b/mercurial/error.py
--- a/mercurial/error.py
+++ b/mercurial/error.py
@@ -212,6 +212,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