golang / go

The Go programming language

Home Page:https://go.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

crypto/x509: root_darwin.go does not include trusted root certificates from System/Login keychains

mwielgoszewski opened this issue · comments

  1. Tested on go version go1.6 darwin/amd64 and go version go1.5.3 darwin/amd64.
  2. OS X Yosemite, OS X El Capitan
  3. I attempted to connect to a TLS service with a certificate signed by an internal, enterprise certificate authority. The CA certificate was added to the System keychain.
  4. I expected to be able to connect to the TLS service without any issue as the certificate is signed by a CA I trust.
  5. The program failed to connect to the TLS service, because the CA certificate that issued the certificate is not installed in the SystemRootCertificates.keychain that Go loads trusted roots from.

On OS X Yosemite, this issue can be mitigated by installing the certificate into SystemRootCertificates.keychain via /usr/bin/security from the terminal:

sudo security add-trusted-cert -k /System/Library/Keychains/SystemRootCertificates.keychain <certificate>

However, on El Capitan this is no longer possible without turning off security protections enabled by Apple.

execSecurityRoots should try to load additional certificates from the System keychain located at /Library/Keychains/System.keychain, and the Login keychain (~/Library/Keychains/login.keychain).

This bug makes distributing Go clients (especially 3rd-party developed) difficult in organizations with an internal PKI.

Currently Golang uses security find-certificate command to get a dump of everything that is inside /System/Library/Keychains/SystemRootCertificates.keychain which contains all system-wide root certificates.

Obviously we may simply run security find-certificate multiple times and grab certificates from all three (System Roots, System and login) chains but the last chain login does not actually require root privilege to modify and only applies to the user that is currently logged in.

Look at what we are doing with Linux and BSD, in those OSes we have been importing certificates from only trusted locations (means you need root privilege to change them) we might want to include only /Library/Keychains/System.keychain but not ~/Library/Keychains/login.keychain since the previous one needs root privilege to change and is not affected by SIP.

Just my thought.

That sounds pretty reasonable, though other suggestions (i.e., #14022, #3905) indicate the Golang project is considering following OpenSSL's conventions by looking up SSL_CA_CERT_FILE or SSL_CA_CERT_PATH environment variables pointing to to a stack of certificates or directory of certificates respectively. Unless the same considerations are made when loading certificates (e.g., ensure only root can write to that path, and all its parent directories), I don't see a reason to single out OS X.

Yeah I can see your point, it seems unnecessary to limit the current user from using his/her own keychain as a trusted storage.

Also note that if the target machine has cgo available, root_cgo_darwin.go will be used instead which in turn uses the SecTrustCopyAnchorCertificates() function to obtain a list of all trusted roots. On my machine that function returned 192 certs and does not appears to be including those ones from login or System. The returned certs seems to came from /System/Library/Keychains/X509Anchors as documented by Apple and is not necessarily the same as what's inside /System/Library/Keychains/SystemRootCertificates.keychain.

I have a potential fix here:
https://github.com/hinman/go/commit/e3e9ebf21b8f949d9b3eaed95e61640e3430ad27

I'll work on https://golang.org/doc/contribute.html if no one else has a proposed solution.

Basically I'm copying all the trusted certificates from the System, Admin & User domains and then filtering out all the ones where the subject and issuer names don't match (not a root CA or self signed cert).

CL https://golang.org/cl/20351 mentions this issue.

Hello friends! As you might have guessed from the above linked-issue noise - I made a package today to work around this issue in Packer and Terraform.

I'm hoping to convert the basic strategy into a Go patch soon, but in the meantime you can check out the package here: https://github.com/hashicorp/go-rootcerts

Hi folks - great to see @hinman's patch landing, thank you for that work!

Because it's a cgo-only solution, this does not solve the problem for our use case. I'm not sure what the intent of this particular issue is - should a cgo-free story here be a separate issue or should this one be reopened?

New bug.

@phinze Yeah, I'm in the same boat. The cgo only solution doesn't work for me.

@grep-awesome This issue is closed. Please open a new issue or discuss this in a forum (https://golang.org/wiki/Questions).

Change https://golang.org/cl/227037 mentions this issue: crypto/x509: use Security.framework without cgo for roots on macOS