14
14
import java .security .cert .X509Certificate ;
15
15
import java .util .Collections ;
16
16
import java .util .List ;
17
- import java .util .stream .Collectors ;
18
17
19
18
import static org .hamcrest .CoreMatchers .hasItem ;
20
- import static org .hamcrest .CoreMatchers .is ;
19
+ import static org .hamcrest .CoreMatchers .not ;
21
20
import static org .hamcrest .MatcherAssert .assertThat ;
22
- import static org .hamcrest .Matchers .greaterThan ;
23
21
import static org .jetbrains .nativecerts .NativeCertsTestUtil .ExitCodeHandling ;
24
22
import static org .jetbrains .nativecerts .NativeCertsTestUtil .combineLists ;
25
23
import static org .jetbrains .nativecerts .NativeCertsTestUtil .executeProcess ;
30
28
import static org .jetbrains .nativecerts .NativeCertsTestUtil .getTestCertificatePath ;
31
29
import static org .jetbrains .nativecerts .NativeCertsTestUtil .isManualTestingEnabled ;
32
30
import static org .jetbrains .nativecerts .NativeTrustedRootsInternalUtils .isMac ;
33
- import static org .jetbrains .nativecerts .NativeTrustedRootsInternalUtils .sha1hex ;
34
- import static org .jetbrains .nativecerts .NativeTrustedRootsInternalUtils .sha256hex ;
35
31
import static org .junit .Assert .assertEquals ;
36
32
import static org .junit .Assert .assertFalse ;
37
33
import static org .junit .Assert .assertTrue ;
@@ -97,9 +93,16 @@ public void addRealUserTrustedCertificate_deny() throws Exception {
97
93
public void supportForIntermediateCertificates () throws InterruptedException {
98
94
Assume .assumeTrue (isManualTestingEnabled );
99
95
100
- // add root cert
96
+ Path intermediatePath = getCertificatePath ("/mock-ca/intermediate-ca.pem" );
97
+
98
+ // remove just in case it was not cleaned up before
99
+ removeTrustedCert (getTestCertificatePath ());
100
+ deleteCert ("JVM-NATIVE-TRUSTED-ROOTS-MOCK-INTERMEDIATE-CA" );
101
+
101
102
try {
102
103
Path loginKeyChain = Path .of (System .getProperty ("user.home" ), "Library/Keychains/login.keychain-db" );
104
+
105
+ // add root cert
103
106
List <String > args = List .of (
104
107
"/usr/bin/security" ,
105
108
"add-trusted-cert" ,
@@ -111,33 +114,31 @@ public void supportForIntermediateCertificates() throws InterruptedException {
111
114
Thread .sleep (2000L );
112
115
113
116
// add intermediate cert
114
- args = List .of (
115
- "/usr/bin/security" ,
116
- "add-certificates" ,
117
- "-k" , loginKeyChain .toString (),
118
- getCertificatePath ("/mock-ca/intermediate-ca.pem" ).toString ()
119
- );
120
- executeProcess (args );
117
+ addCertificate (loginKeyChain , intermediatePath );
121
118
122
- // verify certs are trusted
123
- List <X509Certificate > rootsAfter = SecurityFrameworkUtil .getTrustedRoots (SecurityFramework .SecTrustSettingsDomain .user );
119
+ // verify both certs are trusted
120
+ List <X509Certificate > afterAdd = SecurityFrameworkUtil .getTrustedRoots (SecurityFramework .SecTrustSettingsDomain .user );
121
+ List <String > afterAddAliases = afterAdd .stream ().map (crt -> crt .getSubjectX500Principal ().toString ()).toList ();
122
+ assertThat (afterAddAliases , hasItem ("CN=JVM-NATIVE-TRUSTED-ROOTS-MOCK-CA, O=JETBRAINS" ));
123
+ assertThat (afterAddAliases , hasItem ("CN=JVM-NATIVE-TRUSTED-ROOTS-MOCK-INTERMEDIATE-CA, O=JETBRAINS" ));
124
+ assertTrue (verifyCert (intermediatePath , null ));
125
+ assertTrue (verifyCert (getTestCertificatePath (), null ));
126
+
127
+ // remove root cert. Both root and intermediate should disappear
128
+ assertTrue (removeTrustedCert (getTestCertificatePath ()));
129
+ assertFalse (verifyCert (intermediatePath , null ));
130
+ assertFalse (verifyCert (getTestCertificatePath (), null ));
124
131
125
- List <String > aliases = rootsAfter .stream ().map (crt -> crt .getSubjectX500Principal ().toString ())
126
- .collect (Collectors .toList ());
127
- assertThat (aliases , hasItem ("CN=JVM-NATIVE-TRUSTED-ROOTS-MOCK-CA, O=JETBRAINS" ));
128
- assertThat (aliases .size (), is (greaterThan (1 )));
129
- assertThat (aliases , hasItem ("CN=JVM-NATIVE-TRUSTED-ROOTS-MOCK-INTERMEDIATE-CA, O=JETBRAINS" ));
132
+ List <X509Certificate > afterRootRemoval = SecurityFrameworkUtil .getTrustedRoots (SecurityFramework .SecTrustSettingsDomain .user );
133
+ List <String > afterRootRemovalAliases = afterRootRemoval .stream ().map (crt -> crt .getSubjectX500Principal ().toString ()).toList ();
134
+ assertThat (afterRootRemovalAliases , not (hasItem ("CN=JVM-NATIVE-TRUSTED-ROOTS-MOCK-CA, O=JETBRAINS" )));
135
+ assertThat (afterRootRemovalAliases , not (hasItem ("CN=JVM-NATIVE-TRUSTED-ROOTS-MOCK-INTERMEDIATE-CA, O=JETBRAINS" )));
136
+
137
+ // assert cleanup
138
+ assertTrue (deleteCert ("JVM-NATIVE-TRUSTED-ROOTS-MOCK-INTERMEDIATE-CA" ));
130
139
} finally {
131
140
removeTrustedCert (getTestCertificatePath ());
132
-
133
- executeProcess (
134
- List .of (
135
- "/usr/bin/security" ,
136
- "delete-certificate" ,
137
- "-c" , "JVM-NATIVE-TRUSTED-ROOTS-MOCK-INTERMEDIATE-CA" ,
138
- "-t"
139
- )
140
- );
141
+ deleteCert ("JVM-NATIVE-TRUSTED-ROOTS-MOCK-INTERMEDIATE-CA" );
141
142
}
142
143
}
143
144
@@ -149,12 +150,6 @@ private void customUserTrustedCertificateTest(@Nullable String policy, String re
149
150
Path loginKeyChain = Path .of (System .getProperty ("user.home" ), "Library/Keychains/login.keychain-db" );
150
151
assertTrue (Files .isRegularFile (loginKeyChain ));
151
152
152
- byte [] encoded = getTestCertificate ().getEncoded ();
153
- String sha1 = sha1hex (encoded );
154
- String sha256 = sha256hex (encoded );
155
- assertEquals ("c1969052bc9a106a8a7997b84913e1530215ac45" , sha1 );
156
- assertEquals ("63609373bf25769df2a6e64378872d9d2697c48b53408dd1d0e38b2db4397fc6" , sha256 );
157
-
158
153
// cleanup just in case it was imported before
159
154
removeTrustedCert (getTestCertificatePath ());
160
155
@@ -224,4 +219,24 @@ private static boolean removeTrustedCert(Path cert) {
224
219
int rc = executeProcessAndGetExitCode (List .of ("/usr/bin/security" , "remove-trusted-cert" , cert .toAbsolutePath ().toString ()));
225
220
return rc == 0 ;
226
221
}
222
+
223
+ private static void addCertificate (Path loginKeyChain , Path certificatePath ) {
224
+ executeProcess (List .of (
225
+ "/usr/bin/security" ,
226
+ "add-certificates" ,
227
+ "-k" , loginKeyChain .toString (),
228
+ certificatePath .toString ()
229
+ ));
230
+ }
231
+
232
+ private static boolean deleteCert (String commonName ) {
233
+ int rc = executeProcessAndGetExitCode (List .of (
234
+ "/usr/bin/security" ,
235
+ "delete-certificate" ,
236
+ "-c" , commonName ,
237
+ // Also delete user trust settings for this certificate
238
+ "-t"
239
+ ));
240
+ return rc == 0 ;
241
+ }
227
242
}
0 commit comments