-
Notifications
You must be signed in to change notification settings - Fork 5.7k
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
8347067: Load certificates without explicit trust settings in KeyChainStore #22911
base: master
Are you sure you want to change the base?
8347067: Load certificates without explicit trust settings in KeyChainStore #22911
Conversation
Hi @timja, welcome to this OpenJDK project and thanks for contributing! We do not recognize you as Contributor and need to ensure you have signed the Oracle Contributor Agreement (OCA). If you have not signed the OCA, please follow the instructions. Please fill in your GitHub username in the "Username" field of the application. Once you have signed the OCA, please let us know by writing If you already are an OpenJDK Author, Committer or Reviewer, please click here to open a new issue so that we can record that fact. Please use "Add GitHub user timja" as summary for the issue. If you are contributing this work on behalf of your employer and your employer has signed the OCA, please let us know by writing |
❗ This change is not yet ready to be integrated. |
@@ -411,15 +411,16 @@ static bool loadTrustSettings(JNIEnv *env, | |||
jmethodID jm_listAdd, | |||
jobject *inputTrust) { | |||
CFArrayRef trustSettings; | |||
// Load trustSettings into inputTrust | |||
if (SecTrustSettingsCopyTrustSettings(certRef, domain, &trustSettings) == errSecSuccess && trustSettings != NULL) { | |||
if (*inputTrust == NULL) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved so that the empty ArrayList
is always created
I'm afraid but it looks like this implementation violates the https://developer.apple.com/documentation/security/sectrustsettingscopytrustsettings(_:_:_:) specification. It always creates an empty input trust and fills it with the provided non-null trustSettings. So, the certificate always has at least empty trustSettings. However, according to this specification, two different scenarios should be considered:
The current implementation adds Root certificate to the TrustStore because it has "Always Trust" settings. I think, in this particular case, we need two iterations to add certificates into the trust store. The first iteration will add certificates with non-null trust settings, and the second iteration should verify and add certificates with null trust settings. |
Thanks for the feedback it was very helpful, I had missed the bottom note on https://developer.apple.com/documentation/security/sectrustsettingscopytrustsettings(_:_:_:) before this. I've implemented the recommendation based on the docs in 0052cd0. All my test cases are now passing. I've added a second intermediate CA to my test setup as well although it only uses 1 by default: I've tested by revoking trust along each part of the chain and its behaving correctly now. |
Thank you for this patch. It looks correct now (see my comment about subjCerts above) Is it possible to add jtreg test for this scenario? |
Thanks, will look into that
I'll look at that ~tomorrow
Would it be possible for you to do it on my behalf please? I don't have access |
I've done some research. I think it would only be possible with manual intervention to run it. The certificates could be added to the truststore using but marking the root certificate as trusted would need the user to confirm an OS prompt, https://github.com/JetBrains/jvm-native-trusted-roots#testing, i.e. I need to approve via Touch ID when I make changes to a certs trust level. Does that add value to add a test so someone could run it manually? |
/issue JDK-8347067 |
@alexeybakhtin Only the author (@timja) is allowed to issue the |
/issue JDK-8347067 |
@timja The primary solved issue for a PR is set through the PR title. Since the current title does not contain an issue reference, it will now be updated. |
Yes, I think a manual test is better than nothing. |
import org.junit.jupiter.api.Test; | ||
|
||
/* | ||
* @test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alexeybakhtin quick question on how this should be marked as manual.
I see all tests in https://github.com/openjdk/jdk/blob/master/test/jdk/TEST.groups#L256-L259 are manual ones.
Is this test automatically included in that?
Or should it be added here?
https://github.com/openjdk/jdk/blob/master/test/jdk/TEST.groups#L657
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test should be marked as @run junit/manual
and added to the jdk_security_manual_interactive
part of the TEST.groups
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any idea how I can run the test after making those changes?
The test just gets skipped with:
CONF=release make test TEST=test/jdk/java/security/KeyStore/CheckMacOSKeyChainIntermediateCATrust.java
I've checked through:
https://openjdk.org/jtreg/faq.html#how-do-i-run-only-tests-requiring-manual-intervention
and I saw somewhere mention of passing -manual
but I can't get that to work with make test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was able to run it by setting up jtreg
and avoiding the make test
task.
jtreg.sh -manual test/jdk/java/security/KeyStore/CheckMacOSKeyChainIntermediateCATrust.java
Although it seems it ran anyway without passing manual:
jtreg.sh test/jdk/java/security/KeyStore/CheckMacOSKeyChainIntermediateCATrust.java
Test results: passed: 1
Attaching logs are requested on mailing list, |
(OCA has been signed by my employer, so should be able to move forward soon) |
Webrevs
|
test/jdk/java/security/KeyStore/CheckMacOSKeyChainIntermediateCATrust.java
Outdated
Show resolved
Hide resolved
test/jdk/java/security/KeyStore/CheckMacOSKeyChainIntermediateCATrust.java
Show resolved
Hide resolved
test/jdk/java/security/KeyStore/CheckMacOSKeyChainIntermediateCATrust.java
Outdated
Show resolved
Hide resolved
/reviewers 2 |
@seanjmullan |
This change is significant and should be reviewed by at least 2 Reviewers. |
test/jdk/java/security/KeyStore/CheckMacOSKeyChainIntermediateCATrust.java
Show resolved
Hide resolved
test/jdk/java/security/KeyStore/CheckMacOSKeyChainIntermediateCATrust.java
Outdated
Show resolved
Hide resolved
test/jdk/java/security/KeyStore/CheckMacOSKeyChainIntermediateCATrust.java
Outdated
Show resolved
Hide resolved
test/jdk/java/security/KeyStore/CheckMacOSKeyChainIntermediateCATrust.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the fixes. Looks good to me
Possible to get a second reviewer? potentially @wangweij? Unless @seanjmullan you could suggest someone? |
The change
Without this change intermediate certificates that don't have explicit trust settings are ignored not added to the truststore.
Reproducer
See https://github.com/timja/openjdk-intermediate-ca-reproducer
Without this change the reproducer fails, and with this change it succeeds.
Example failing architecture
Root CA -> Intermediate 1 -> Intermediate 2 -> Leaf
Where:
Previously Root CA would be found but intermediate 1 and 2 would be skipped when verifying trust settings.
Background reading
Rust
see also Rust Lib that is used throughout Rust ecosystem for this:
https://github.com/rustls/rustls-native-certs/blob/efe7b1d77bf6080851486535664d1dc7ef0dea68/src/macos.rs#L39-L58
e.g. in Deno
https://github.com/denoland/deno/pull/11491
where I've verified it is correctly implemented and works in my setupPython
I also looked at the Python implementation for inspiration as well (which also works on my system): https://github.com/sethmlarson/truststore/blob/main/src/truststore/_macos.py
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/22911/head:pull/22911
$ git checkout pull/22911
Update a local copy of the PR:
$ git checkout pull/22911
$ git pull https://git.openjdk.org/jdk.git pull/22911/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 22911
View PR using the GUI difftool:
$ git pr show -t 22911
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/22911.diff
Using Webrev
Link to Webrev Comment