-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
crypto/x509: darwin only loads system.root keychain should also load system keychain #16532
Comments
I suspect this is a dup of #14514 which was fixed for Go 1.7. Can you verify? |
I don't see any difference using 1.7rc3, here's my example:
The certificate sent by googleapis is intercepted by our corporate mitm server and a substitute certificate is generated and signed by our internal enterprise intermediate CA SSL which is in turn signed by the internal enterprise CA Root. The program fails with this error:
If I connect my mac to an outside network (such as Starbucks WIFI) the program runs successfully. |
The code quoted is for toolchains without cgo. Do you have cgo? It could well be that the fix you suggest is correct, which would be great. I didn't find that file when I was working on https://codereview.appspot.com/22020045, and I experienced the exact same problem at the time, with a corp cert. |
@jostockley, could you answer Josh's question? Are you using cgo? |
This was a while ago now, so I tried my test again. I'm using go installed on my Mac using homebrew.
|
When you filed a bug, the issue template requested that you paste the output of |
So that is what the (go env) meant. It might be better if it said explicity to run the go env command.
|
Okay, so you have cgo. I guess the next question is whether the changes during Go 1.8 helped this or not. Could you try Go 1.8beta2? https://golang.org/dl/#go1.8beta2
|
Problem still exists:
|
I don't know much about this stuff, but if you wanted to experiment, the relevant code is in crypto/x509/root_cgo_darwin.go. One place to go sniffing might be the list of security domains we respect. |
Correct me if I'm wrong, but if you're not building against C, cgo won't be used (even if CGO_ENABLED=1) -- on darwin at least. A local test with CGO_ENABLED=0 and CGO_ENABLED=1 yields an identical binary. The non-cgo cert code only looks at SystemRoots on darwin. It's missing the System and login keychains. I dealt with this issue a lot at a previous employer (they did the same MITM-thing). For awhile we got away with adding the certs to the System Roots keychain, but newer versions of macOS prevent this. After that we just started using our own tls.Config. Having said that, I honestly think this may be as simple as appending the missing paths to the I'd be happy to make a CL if this seems sane to everyone. |
I too just ran into this issue in mac os el capitan. The only place I can add a self signed cert is in
and
Adding a cert using
results in So i think the above two keychains also need to be included. Or at the very least, the users login keychain but i don't know how difficult that would be. I'm not a go expert or a c expert so i'm just guessing here. |
I did some more testing this morning. The non-cgo solution is pretty simple and I can confirm it works, I can add a cert to the login.keychain on Sierra, trust it, and have it validate on an https request. Un-trust it and it doesn't, etc.. The same for the System keychain. With cgo enabled, however, I'm getting |
The current implementation of loadSystemRoots does not load all required (trusted) certificates in both the cgo and nocgo paths. In the nocgo path, certificates are simply not loaded from the login or System keychains. In the cgo path, certificates whos Subject doesn't match the Issuer, are ignored. This is problematic in the case of a enterprise environment with their own intermediate CAs. In this case: the issuer is a separate root, which may be loaded, but the intermediate is ignored. A TLS handshake may not include the intermediate cert, leading to an error. This change adds the System and login keychain files to the nocgo path, and removes the restriction on Issuer and Subject name matching in the cgo path. Fixes golang#16532 Change-Id: I4786d6696b338c7e0e0c7806e5d0383f99d2db89
Hmm. I can't seem to recreate this. I added the cert to my login keychain and System keychain and trusted both. Curl works as expected and so does Safari. then i built my go binary with
This is my go env
The build is successful but here's the result
Maybe one of the packages i'm importing is using cgo and that could cause it? i'll try just a plain old get of a page on that site. edit: ok. figured out that certs with IP addresses are only validated using IP SAN certs. In my case, I'm screwed with getting this to work because I can't change the certificate but at least it's a problem on my end :) |
Just an update, I'm pretty confident that I have a fix ready for both cgo and nocgo. I'm attempting to validate that it fixes the issue in these environments. I'll make a CL once I can validate it. @bradfitz in the cgo code path, it looks to be that the Issuer and Subject-match check doesn't account for environments with intermediate CAs that need to be on the chain. That's the general idea anyway; the CL commit will have a more detailed explanation/example once I "mail" it. As for the nocgo: that code simply doesn't load the System and login keychains currently. @jostockley would you be able to help validate the fix? If anyone behind a MITM-type proxy would like to try validating, I made a gist to try to make validation simple as possible: If you follow the script, it gets go 1.8, clones the fix, builds it, and runs an http.Get in go, printing the results of each. When it's done, if all goes well, you should see:
Meaning with 1.8 it should get a cert issue with both cgo/nocgo and with the fix, a successful https request for both. |
@mastercactapus thanks for working on this! When you mail the CLs, please mail separate CLs for the cgo and non-cgo paths. A good reviewer would be [email protected], and please CC me. |
@mastercactapus I ran your test script and here's the result:
Not what I expected. I also tried my original test case and with your fix my test passes, without you fix my test fails. So that indicates that you fix works at least for my test case. |
CL https://golang.org/cl/36941 mentions this issue. |
CL https://golang.org/cl/36942 mentions this issue. |
The current implementation ignores certificates that exist in the login and System keychains. This change adds the missing System and login keychain files to the `/usr/bin/security` command in `execSecurityRoots`. If the current user cannot be obtained, the login keychain is ignored. Refs golang#16532 Change-Id: I8594a6b8940c58df8a8015b274fa45c39e18862c
Hi, any news on this issue? |
I think @quentinmit has reviewed some related code in the past. Quentin? |
The current implementation ignores certs wherein the Subject does not match the Issuer. An example of where this causes issue is an enterprise environment with intermediate CAs. In this case, the issuer is separate (and may be loaded) but the intermediate is ignored. A TLS handshake that does not include the intermediate cert would then fail with an untrusted error in Go. On other platforms (darwin-nocgo included), all trusted certs are loaded and accepted reguardless of Subject/Issuer names. This change removes the Subject/Issuer name-matching restriction of certificates, allowing all trusted certs to be loaded on darwin (cgo). Refs golang#16532 Change-Id: I451e929588f8911892be6bdc2143d0799363c5f8
The current implementation ignores certs wherein the Subject does not match the Issuer. An example of where this causes issue is an enterprise environment with intermediate CAs. In this case, the issuer is separate (and may be loaded) but the intermediate is ignored. A TLS handshake that does not include the intermediate cert would then fail with an untrusted error in Go. On other platforms (darwin-nocgo included), all trusted certs are loaded and accepted reguardless of Subject/Issuer names. This change removes the Subject/Issuer name-matching restriction of certificates when trustAsRoot is set, allowing all trusted certs to be loaded on darwin (cgo). Refs golang#16532 Change-Id: I451e929588f8911892be6bdc2143d0799363c5f8
The current implementation ignores certificates that exist in the login and System keychains. This change adds the missing System and login keychain files to the `/usr/bin/security` command in `execSecurityRoots`. If the current user cannot be obtained, the login keychain is ignored. Refs golang#16532 Change-Id: I8594a6b8940c58df8a8015b274fa45c39e18862c
The current implementation ignores certificates that exist in the login and System keychains. This change adds the missing System and login keychain files to the `/usr/bin/security` command in `execSecurityRoots`. If the current user cannot be obtained, the login keychain is ignored. Refs #16532 Change-Id: I8594a6b8940c58df8a8015b274fa45c39e18862c Reviewed-on: https://go-review.googlesource.com/36941 Run-TryBot: Emmanuel Odeke <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
The current implementation ignores certs wherein the Subject does not match the Issuer. An example of where this causes issue is an enterprise environment with intermediate CAs. In this case, the issuer is separate (and may be loaded) but the intermediate is ignored. A TLS handshake that does not include the intermediate cert would then fail with an untrusted error in Go. On other platforms (darwin-nocgo included), all trusted certs are loaded and accepted reguardless of Subject/Issuer names. This change removes the Subject/Issuer name-matching restriction of certificates when trustAsRoot is set, allowing all trusted certs to be loaded on darwin (cgo). Refs golang#16532 Change-Id: I451e929588f8911892be6bdc2143d0799363c5f8
Change https://golang.org/cl/57830 mentions this issue: |
golang.org/cl/36941 enabled loading of all trusted certs on darwin for the non-cgo execSecurityRoots. The corresponding cgo version golang.org/cl/36942 for systemRootsPool has not been merged yet. This tests fails reliably on some darwin systems: --- FAIL: TestSystemRoots (1.28s) root_darwin_test.go:31: cgo sys roots: 353.552363ms root_darwin_test.go:32: non-cgo sys roots: 921.85297ms root_darwin_test.go:44: got 169 roots root_darwin_test.go:44: got 455 roots root_darwin_test.go:73: insufficient overlap between cgo and non-cgo roots; want at least 227, have 168 FAIL FAIL crypto/x509 2.445s Updates #16532 Updates #21416 Change-Id: I52c2c847651fb3621fdb6ab858ebe8e28894c201 Reviewed-on: https://go-review.googlesource.com/57830 Run-TryBot: Martin Möhrmann <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Joe Tsai <[email protected]>
Change https://golang.org/cl/64851 mentions this issue: |
Change https://golang.org/cl/70847 mentions this issue: |
golang.org/cl/36941 enabled loading of all trusted certs on darwin for the non-cgo execSecurityRoots. The corresponding cgo version golang.org/cl/36942 for systemRootsPool has not been merged yet. This tests fails reliably on some darwin systems: --- FAIL: TestSystemRoots (1.28s) root_darwin_test.go:31: cgo sys roots: 353.552363ms root_darwin_test.go:32: non-cgo sys roots: 921.85297ms root_darwin_test.go:44: got 169 roots root_darwin_test.go:44: got 455 roots root_darwin_test.go:73: insufficient overlap between cgo and non-cgo roots; want at least 227, have 168 FAIL FAIL crypto/x509 2.445s Updates #16532 Updates #21416 Change-Id: I52c2c847651fb3621fdb6ab858ebe8e28894c201 Reviewed-on: https://go-review.googlesource.com/57830 Run-TryBot: Martin Möhrmann <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Joe Tsai <[email protected]> Reviewed-on: https://go-review.googlesource.com/70847 Run-TryBot: Russ Cox <[email protected]> Reviewed-by: Martin Möhrmann <[email protected]>
I believe this is fixed by https://go-review.googlesource.com/c/go/+/36942 which lacked the magic "Fixes" word. |
The current implementation ignores certs wherein the Subject does not match the Issuer. An example of where this causes issue is an enterprise environment with intermediate CAs. In this case, the issuer is separate (and may be loaded) but the intermediate is ignored. A TLS handshake that does not include the intermediate cert would then fail with an untrusted error in Go. On other platforms (darwin-nocgo included), all trusted certs are loaded and accepted reguardless of Subject/Issuer names. This change removes the Subject/Issuer name-matching restriction of certificates when trustAsRoot is set, allowing all trusted certs to be loaded on darwin (cgo). Refs #16532 Change-Id: I451e929588f8911892be6bdc2143d0799363c5f8 Reviewed-on: https://go-review.googlesource.com/36942 Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
Please answer these questions before submitting your issue. Thanks!
go version
)?1.6
go env
)?amd64 darwin El Capitan
I am trying to run minikube start on a mac running el capitan. I am inside my corporate network and they have a TLS man-in-the-middle box between the internal network and the internet so that when a TLS connection is made to an internet site, it generates an SSL certificate signed by the corporate root CA. This is installed in my Mac in the system keychain since it is not possible to install trusted CA root certs in the system.root keychain. However, in src/crypto/x509/root_darwin.go I see this:
I believe the code should also load certificates from /System/Library/Keychains/SystemCACertificates.keychain
so as to pick up any user installed root certificates.
The text was updated successfully, but these errors were encountered: