Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kill SSL_CERT_FILE (aka fix openssl/curl config) #12748

Closed
wants to merge 1 commit into from

Conversation

layus
Copy link
Member

@layus layus commented Feb 1, 2016

OpenSSL is designed to trust the certificates located in "${openssl}/etc/ssl/cert.pem".
NixOS on the other uses /etc/ssl/certs/ca-certificates.crt as its trusted root CAs.

By symlinking "${openssl}/etc/ssl/cert.pem" to "/etc/ssl/certs/ca-certificates.crt",
we fix all the applications that rely on openssl defaults certificates.
This is not trivial as it includes git, curl, python, php, and more.

Doing this, we can also get rid of the annoying SSL_CERT_FILE previously defined in the global environment.
This variable will revert to being a simple mean to override the default store location.

Using "/etc/ssl/certs/ca-certificates.crt" as the system trusted certificates
is a sensible path already taken in GnuTLS (see #8121).
This is also what is done by other distros like ArchLinux or Debian.

This PR fixes openssl and curl to use the default system trusted certificates.

I tested openssl, curl, git, git-send-email.
Any help is welcome in testing other packages.
We cannot however test everything affected by the removal of the SSL_CERT_FILE environment variable.

Some issues/details remain:

  • We should use some config variable instead of the hardcoded string.
  • That config variable should probably reside in stdenv to account for other OS's/distros.
  • Some packages use SSL_CERT_FILE as a bad mean to a good end.
    Removing nixpkgs/pkgs/development/perl-modules/lwp-protocol-https-cert-file.patch may not be the best thing to do.
  • Maybe split the commit into smaller commits ?

Closes #12628, #8486, #10875, #8247, #8534, #10703
Related #8867, #3382

cc: @edolstra, @vcunat, @zimbatm, @4levels and maybe others.

@mention-bot
Copy link

By analyzing the blame information on this pull request, we identified @edolstra, @wmertens and @bjornfor to be potential reviewers

@vcunat
Copy link
Member

vcunat commented Feb 1, 2016

Using a mass-rebuild config change isn't very good for non-NixOS Linux systems (for Darwin it would be probably fine). I thought we would still honor SSL_CERT_FILE (or a similar variable) and leave it undefined on NixOS.

@layus
Copy link
Member Author

layus commented Feb 1, 2016

My comment about changing the config is mostly about darwin indeed, because @zimbatm mentioned "issues" on darwin (#8486 (comment)) with respect to SSL_CERT_FILE (@zimbatm, would you mind to elaborate ?), and because it may be better to have no configured default path than a security-related symlink pointing to a nonexistent path.

SSL_CERT_FILE is still available if you want to override the default location for openssl, just as the '--cacert' option to curl, the '-CAfile' option to openssl, the '--ca-certificate' option to wget, etc.

However what you suggest is, on top of the default location configured in the binaries themselves, to make all these executables honour the SSL_CERT_FILE env variable.
This is indeed the best way to support non-nixos systems as just one environment variable would allow to ensure that all the nix packages to work consistently even if /etc/ssl/certs/ca-certificates.cert is missing. We should set that variable correctly in '.nix-profile/etc/profile.d/nix.sh' and voilà :-).
May i suggest to give that variable a different name, as SSL_CERT_FILE sounds very specific to openssl ? Maybe NIX_CERT_FILE ?

So, fixing the default path fixes nixos services, and using NIX_CERT_FILE fixes non-nixos distros. I think we need both mechanisms.
However, this requires some extra work, outlined by your comment at https://github.com/NixOS/nixpkgs/pull/8121/files#diff-cff75ddd8906caa1da857c27ce0a660a. There is often only one degree of liberty to setup custom paths.

Do we agree on the following priority order (from low to high precedence):

  • (lowest) Default configured path (/etc/ssl/certs/ca-certificates.crt if stdenv.isLinux, possibly not set otherwise.)
  • NIX_CERT_FILE
  • (highest) custom overriding settings like SSL_CERT_FILE or command line options.

To be "Nix-way compliant", a derivation would then need to default to /etc/ssl/certs/ca-certificates.crt and honour NIX_CERT_FILE.
@vcunat do you agree with this ?

I still think that the default path (/etc/ssl/certs/ca-certificates.crt) should be defined in stdenv, according to the platform/architecture, but independently of the usage of NixOS.


On the other hand, if we agree that /etc/ssl/certs/ca-certificates.crt is stable enough and will not change in the long run, we can add it to systemd.globalEnvironment.
This removes the need to setup a default location in the binaries, and we could focus on fixing packages to honour NIX_CERT_FILE.
This has already been described in #8486, and has the issue that in grows the global dependencies.

@edolstra
Copy link
Member

edolstra commented Feb 2, 2016

One problem is that this creates a source of impurity: a Nix package that uses OpenSSL at build time might access certificates (at build time) that are not explicitly defined as an input, via /etc/ssl/certs. This might be mitigated by having OpenSSL export a setup hook that sets $SSL_CERT_FILE to a non-existent or empty file.

@@ -58,6 +59,9 @@ stdenv.mkDerivation rec {

# remove dependency on Perl at runtime
rm -r $out/etc/ssl/misc $out/bin/c_rehash

# configure the default trust store
${optionalString (defaultCertificate != null) "ln -s ${defaultCertificate} $out/etc/ssl/cert.pem"}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of making a symlink, why not just override X509_CERT_FILE at compile time? And maybe also set X509_CERT_DIR to /etc/ssl/certs.

Also, do we actually want to have this configurable? I can't think of a good reason to change the default.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could override X509_CERT_FILE, but it creates more impurities at build time IIRC.
In this case, we add something at the end of postInstall, this cannot harm much.

I made it configurable because it may not be desirable to have a reference to "/etc/ssl/certs/ca-certificates.crt" on darwin for example. I am not too sure about this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, how does it create more impurity, compared to the symlink?

Regarding Darwin, there is no good default value, so /etc/ssl/certs/ca-certificates.crt is as good as any :-)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, my sentence makes no sense. What I wanted to say is that the symlink add no impurities in the build process because it happens at the end, and does not interfere with the build itself.

@layus
Copy link
Member Author

layus commented Feb 2, 2016

There are diverging needs for nix and NixOS. Plain Nix users want configurability through SSL_CERT_FILE, to use their system-wide trust sore.

NixOS users want their trust store to always default to "/etc/ssl/certs/ca-certificates.crt".

The easy solution, as the path "/etc/ssl/certs/ca-certificates.crt" is not going to change anytime soon, would be to export SSL_CERT_FILE in systemd.globalEnvironment.
However, you outlined that it grows the global store (see #8486).

This solution explores the complete removal of SSL_CERT_FILE, which is a bas idea for Nix users on other systems.

Maybe we need to support sane defaults and SSL_CERT_FILE ?

@@ -16,7 +16,6 @@ stdenv.mkDerivation {
outputs = [ "out" "man" ];

configureFlags =
# FIXME: perhaps use $SSL_CERT_FILE instead
lib.optional stdenv.isLinux "--with-default-trust-store-file=/etc/ssl/certs/ca-certificates.crt"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not re-use ${openssl}/etc/ssl/cert.pem ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because GnuTLS does not depend on OpenSSL, it is another implementation.
That's why we need to agree on a common default store.

@edolstra
Copy link
Member

edolstra commented Feb 3, 2016

Pushed to staging with some changes, thanks!

@butterflya
Copy link
Contributor

ddclient also suffers from this problem with ssl = true:

verify failed SSL connect attempt failed error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants