Commit Graph

13 Commits

Author SHA1 Message Date
Matt Harbison
d41b1d2ec2 sslutil: inform the user about how to fix an incomplete certificate chain
This is a Windows only thing.  Unfortunately, the socket is closed at this point
(so the certificate is unavailable to check the chain).  That means it's printed
out when verification fails as a guess, on the assumption that 1) most of the
time verification won't fail, and 2) sites using expired or certs that are too
new will be rare.  Maybe this is an argument for adding more functionality to
debugssl, to test for problems and print certificate info.  Or maybe it's an
argument for bundling certificates with the Windows builds.  That idea was set
aside when the enhanced SSL code went in last summer, and it looks like there
were issues with using certifi on Windows anyway[1].

This was tested by deleting the certificate out of certmgr.msc > "Third-Party
Root Certification Authorities" > "Certificates", seeing `hg pull` fail (with
the new message), trying this command, and then successfully performing the pull
command.

[1] https://www.mercurial-scm.org/pipermail/mercurial-devel/2016-October/089573.html
2017-07-12 18:37:13 -04:00
Augie Fackler
e5d7bd82c5 cleanup: use $PYTHON to run python in many more tests
Spotted one of these, then wrote a check-code rule that caught them
all. It will be the next change.
2017-06-20 09:45:02 -04:00
Matt Harbison
23c58339ca test-serve: make the 'listening at *' lines optional
The daemonized serve process doesn't print these lines out (see 0c9eeb8c6b87).
I was able to get it to with the following hack:

 diff --git a/mercurial/win32.py b/mercurial/win32.py
 --- a/mercurial/win32.py
 +++ b/mercurial/win32.py
 @@ -418,6 +418,11 @@
          return str(ppid)

  def spawndetached(args):
 +
 +    import subprocess
 +    return subprocess.Popen(args, cwd=pycompat.getcwd(), env=encoding.environ,
 +                            creationflags=subprocess.CREATE_NEW_PROCESS_GROUP).pid
 +
      # No standard library function really spawns a fully detached
      # process under win32 because they allocate pipes or other objects
      # to handle standard streams communications. Passing these objects

However, MSYS translates --prefixes starting with '/' to 'C:/MinGW/msys/1.0',
which changes the output.  The output isn't so important that I want to spend a
bunch of time on this, and risk breaking some subtle behavior of `hg serve -d`
with the more complicated code.
2017-04-02 00:56:52 -04:00
Yuya Nishihara
21edd5907a patchbomb: use modern pager to display -n/--test result (BC)
This should provide more consistent UX, but is a BC because the pager will
no longer be fired up for each message.
2017-02-25 17:27:48 +09:00
Gregory Szorc
6ba507acfc sslutil: more robustly detect protocol support
The Python ssl module conditionally sets the TLS 1.1 and TLS 1.2
constants depending on whether HAVE_TLSv1_2 is defined. Yes, these
are both tied to the same constant (I would think there would be
separate constants for each version). Perhaps support for TLS 1.1
and 1.2 were added at the same time and the assumption is that
OpenSSL either has neither or both. I don't know.

As part of developing this patch, it was discovered that Apple's
/usr/bin/python2.7 does not support TLS 1.1 and 1.2 (only TLS 1.0)!
On OS X 10.11, Apple Python has the modern ssl module including
SSLContext, but it doesn't appear to negotiate TLS 1.1+ nor does
it expose the constants related to TLS 1.1+. Since this code is
doing more robust feature detection (and not assuming modern ssl
implies TLS 1.1+ support), we now get TLS 1.0 warnings when running
on Apple Python. Hence the test changes.

I'm not super thrilled about shipping a Mercurial that always
whines about TLS 1.0 on OS X. We may want a follow-up patch to
suppress this warning.
2016-07-18 11:27:27 -07:00
Gregory Szorc
9f52df0840 sslutil: print a warning when using TLS 1.0 on legacy Python
Mercurial now requires TLS 1.1+ when TLS 1.1+ is supported by the
client. Since we made the decision to require TLS 1.1+ when running
with modern Python versions, it makes sense to do something for
legacy Python versions that only support TLS 1.0.

Feature parity would be to prevent TLS 1.0 connections out of the
box and require a config option to enable them. However, this is
extremely user hostile since Mercurial wouldn't talk to https://
by default in these installations! I can easily see how someone
would do something foolish like use "--insecure" instead - and
that would be worse than allowing TLS 1.0!

This patch takes the compromise position of printing a warning when
performing TLS 1.0 connections when running on old Python
versions. While this warning is no more annoying than the
CA certificate / fingerprint warnings in Mercurial 3.8, we provide
a config option to disable the warning because to many people
upgrading Python to make the warning go away is not an available
recourse (unlike pinning fingerprints is for the CA warning).

The warning appears as optional output in a lot of tests.
2016-07-13 21:49:17 -07:00
Gregory Szorc
a17406014b tests: regenerate x509 test certificates
The old x509 test certificates were using cryptographic settings
that are ancient by today's standards, namely 512 bit RSA keys.
To put things in perspective, browsers have been dropping support
for 1024 bit RSA keys.

I think it is important that tests match the realities of the times.
And 2048 bit RSA keys with SHA-2 hashing are what the world is
moving to.

This patch replaces all the x509 certificates with new versions using
modern best practices. In addition, the docs for generating the
keys have been updated, as the existing docs left out a few steps,
namely how to generate certs that were not active yet or expired.
2016-07-12 22:26:04 -07:00
Gregory Szorc
0786299e33 sslutil: try to find CA certficates in well-known locations
Many Linux distros and other Nixen have CA certificates in well-defined
locations. Rather than potentially fail to load any CA certificates at
all (which will always result in a certificate verification failure),
we scan for paths to known CA certificate files and load one if seen.
Because a proper Mercurial install will have the path to the CA
certificate file defined at install time, we print a warning that
the install isn't proper and provide a URL with instructions to
correct things.

We only perform path-based fallback on Pythons that don't know
how to call into OpenSSL to load the default verify locations. This
is because we trust that Python/OpenSSL is properly configured
and knows better than Mercurial. So this new code effectively only
runs on Python <2.7.9 (technically Pythons without the modern ssl
module).
2016-07-06 21:16:00 -07:00
Gregory Szorc
0ede6720a7 sslutil: issue warning when unable to load certificates on OS X
Previously, failure to load system certificates on OS X would lead
to a certificate verify failure and that's it. We now print a warning
message with a URL that will contain information on how to configure
certificates on OS X.

As the inline comment states, there is room to improve here. I think
we could try harder to detect Homebrew and MacPorts installed
certificate files, for example. It's worth noting that Homebrew's
openssl package uses `security find-certificate -a -p` during package
installation to export the system keychain root CAs to
etc/openssl/cert.pem. This is something we could consider adding
to setup.py. We could also encourage packagers to do this. For now,
I'd just like to get this warning (which matches Windows behavior)
landed. We should have time to improve things before release.
2016-07-06 20:46:05 -07:00
Gregory Szorc
2121e65956 tests: better testing of loaded certificates
Tests were failing on systems like RHEL 7 where loading the system
certificates results in CA certs being reported to Python. We add
a feature that detects when we're able to load *and detect* the
loading of system certificates. We update the tests to cover the
3 scenarios:

1) system CAs are loadable and detected
2) system CAs are loadable but not detected
3) system CAs aren't loadable
2016-07-01 19:27:34 -07:00
Gregory Szorc
6adc4b7bac sslutil: emit warning when no CA certificates loaded
If no CA certificates are loaded, that is almost certainly a/the
reason certificate verification fails when connecting to a server.

The modern ssl module in Python 2.7.9+ provides an API to access
the list of loaded CA certificates. This patch emits a warning
on modern Python when certificate verification fails and there are
no loaded CA certificates.

There is no way to detect the number of loaded CA certificates
unless the modern ssl module is present. Hence the differences
in test output depending on whether modern ssl is available.

It's worth noting that a test which specifies a CA file still
renders this warning. That is because the certificate it is loading
is a x509 client certificate and not a CA certificate. This
test could be updated if anyone is so inclined.
2016-06-29 19:43:27 -07:00
Gregory Szorc
aa33fbc73f sslutil: abort when unable to verify peer connection (BC)
Previously, when we connected to a server and were unable to verify
its certificate against a trusted certificate authority we would
issue a warning and continue to connect. This is obviously not
great behavior because the x509 certificate model is based upon
trust of specific CAs. Failure to enforce that trust erodes security.
This behavior was defined several years ago when Python did not
support loading the system trusted CA store (Python 2.7.9's
backports of Python 3's improvements to the "ssl" module enabled
this).

This commit changes behavior when connecting to abort if the peer
certificate can't be validated. With an empty/default Mercurial
configuration, the peer certificate can be validated if Python is
able to load the system trusted CA store. Environments able to load
the system trusted CA store include:

* Python 2.7.9+ on most platforms and installations
* Python 2.7 distributions with a modern ssl module (e.g. RHEL7's
  patched 2.7.5 package)
* Python shipped on OS X

Environments unable to load the system trusted CA store include:

* Python 2.6
* Python 2.7 on many existing Linux installs (because they don't
  ship 2.7.9+ or haven't backported modern ssl module)
* Python 2.7.9+ on some installs where Python is unable to locate
  the system CA store (this is hopefully rare)

Users of these Pythongs will need to configure Mercurial to load the
system CA store using web.cacerts. This should ideally be performed
by packagers (by setting web.cacerts in the global/system hgrc file).
Where Mercurial packagers aren't setting this, the linked URL in the
new abort message can contain instructions for users.

In the future, we may want to add more code for finding the system
CA store. For example, many Linux distributions have the CA store
at well-known locations (such as /etc/ssl/certs/ca-certificates.crt
in the case of Ubuntu). This will enable CA loading to "just work"
on more Python configurations and will be best for our users since
they won't have to change anything after upgrading to a Mercurial
with this patch.

We may also want to consider distributing a trusted CA store with
Mercurial. Although we should think long and hard about that because
most systems have a global CA store and Mercurial should almost
certainly use the same store used by everything else on the system.
2016-06-25 07:26:43 -07:00
Yuya Nishihara
43c2fae1ac tests: add basic tests for SMTP over SSL
SSL handling in mail.py wasn't covered by our test suite, therefore it was
sometimes broken. This patch introduces pretty minimal tests that only cover
the default path. We can extend it later.

Tested with python 2.6.9 and 2.7.11 on Debian sid.
2016-05-27 23:18:38 +09:00