1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.common.crypto;
21
22 import static org.hamcrest.MatcherAssert.assertThat;
23 import static org.hamcrest.core.Is.is;
24 import static org.hamcrest.core.IsEqual.equalTo;
25
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.security.KeyStore;
29 import java.security.Security;
30 import java.security.cert.Certificate;
31 import java.security.cert.TrustAnchor;
32 import java.security.cert.X509Certificate;
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.Enumeration;
36 import java.util.List;
37 import java.util.Properties;
38 import java.util.regex.Pattern;
39
40 import org.apache.wss4j.common.ext.WSSecurityException;
41 import org.apache.wss4j.common.util.Loader;
42 import org.junit.jupiter.api.Assertions;
43 import org.junit.jupiter.api.BeforeEach;
44 import org.junit.jupiter.api.Test;
45
46 import static org.junit.jupiter.api.Assertions.assertNotNull;
47 import static org.junit.jupiter.api.Assertions.assertNull;
48 import static org.junit.jupiter.api.Assumptions.assumeFalse;
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 public class NameConstraintsTest {
65 private static final String KEY_ROOT = "keys/nameconstraints/";
66
67 private static final String SELF_SIGNED = KEY_ROOT + "self_signed.p12";
68
69 private static final String ROOT_SIGNED = KEY_ROOT + "root_signed.p12";
70
71 private static final String INTERMEDIATE_SIGNED = KEY_ROOT + "intermediate_signed.p12";
72
73 private static final String KEYSTORE = KEY_ROOT + "nameconstraints.jks";
74
75 private static final char[] PASSWORD = "changeit".toCharArray();
76
77 private static final Pattern SUBJ_PATTERN = Pattern.compile(".*OU=wss4j,O=apache");
78
79 private boolean isIBMJdK = System.getProperty("java.vendor").contains("IBM");
80
81 @BeforeEach
82 public void setup() throws Exception {
83 WSProviderConfig.init();
84 }
85
86 private KeyStore getRootKeyStore() throws Exception {
87 ClassLoader loader = Loader.getClassLoader(NameConstraintsTest.class);
88 KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
89
90 try (InputStream inputStream = Merlin.loadInputStream(loader, KEYSTORE)) {
91 keyStore.load(inputStream, PASSWORD);
92 return keyStore;
93 }
94 }
95
96 private KeyStore getSelfKeyStore() throws Exception {
97 ClassLoader loader = Loader.getClassLoader(NameConstraintsTest.class);
98 KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
99
100 try (InputStream inputStream = loader.getResourceAsStream(SELF_SIGNED)) {
101 keyStore.load(inputStream, PASSWORD);
102 return keyStore;
103 }
104 }
105
106 private X509Certificate[] getTestCertificateChain(String keychainPath) throws Exception {
107 ClassLoader loader = Loader.getClassLoader(NameConstraintsTest.class);
108 KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
109
110 try (InputStream inputStream = loader.getResourceAsStream(keychainPath)) {
111 keystore.load(inputStream, PASSWORD);
112
113
114 Enumeration<String> aliases = keystore.aliases();
115 Certificate[] certificates = keystore.getCertificateChain(aliases.nextElement());
116 assertNotNull(certificates);
117
118 X509Certificate[] x509Certificates = new X509Certificate[certificates.length];
119 System.arraycopy(certificates, 0, x509Certificates, 0, certificates.length);
120
121 return x509Certificates;
122 }
123 }
124
125 @Test
126 public void testNameConstraints() throws Exception {
127 assumeFalse(isIBMJdK);
128
129 Merlin merlin = new Merlin();
130 X509Certificate[] certificates = getTestCertificateChain(INTERMEDIATE_SIGNED);
131
132 assertThat(merlin.getNameConstraints(certificates[0]).length, equalTo(0));
133 assertThat(merlin.getNameConstraints(certificates[1]).length, equalTo(0));
134
135 byte[] nameConstraints = merlin.getNameConstraints(certificates[2]);
136 assertNotNull(nameConstraints);
137 assertThat("Tag byte is wrong", nameConstraints[0], is(DERDecoder.TYPE_SEQUENCE));
138
139 TrustAnchor trustAnchor = new TrustAnchor(certificates[2], nameConstraints);
140 assertThat("TrustAnchor constraints wrong",
141 trustAnchor.getNameConstraints(),
142 equalTo(nameConstraints));
143 }
144
145 @Test
146 public void testNameConstraintsWithKeyStoreUsingMerlin() throws Exception {
147 assumeFalse(isIBMJdK);
148
149 withKeyStoreUsingMerlin(getSelfKeyStore(),
150 getTestCertificateChain(SELF_SIGNED),
151 new Merlin());
152 withKeyStoreUsingMerlin(getRootKeyStore(),
153 getTestCertificateChain(ROOT_SIGNED),
154 new Merlin());
155 withKeyStoreUsingMerlin(getRootKeyStore(),
156 getTestCertificateChain(INTERMEDIATE_SIGNED),
157 new Merlin());
158 }
159
160 @Test
161 public void testNameConstraintsWithTrustStoreUsingMerlin() throws Exception {
162 assumeFalse(isIBMJdK);
163
164 withTrustStoreUsingMerlin(getSelfKeyStore(),
165 getTestCertificateChain(SELF_SIGNED),
166 new Merlin());
167 withTrustStoreUsingMerlin(getRootKeyStore(),
168 getTestCertificateChain(ROOT_SIGNED),
169 new Merlin());
170 withTrustStoreUsingMerlin(getRootKeyStore(),
171 getTestCertificateChain(INTERMEDIATE_SIGNED),
172 new Merlin());
173 }
174
175 @Test
176 public void testNameConstraintsWithKeyStoreUsingMerlinAki() throws Exception {
177 assumeFalse(isIBMJdK);
178
179 withKeyStoreUsingMerlinAKI(getSelfKeyStore(),
180 getTestCertificateChain(SELF_SIGNED),
181 new MerlinAKI());
182 withKeyStoreUsingMerlinAKI(getRootKeyStore(),
183 getTestCertificateChain(ROOT_SIGNED),
184 new MerlinAKI());
185 withKeyStoreUsingMerlinAKI(getRootKeyStore(),
186 getTestCertificateChain(INTERMEDIATE_SIGNED),
187 new MerlinAKI());
188 }
189
190 @Test
191 public void testNameConstraintsWithTrustStoreUsingMerlinAki() throws Exception {
192 assumeFalse(isIBMJdK);
193
194 withTrustStoreUsingMerlinAKI(getSelfKeyStore(),
195 getTestCertificateChain(SELF_SIGNED),
196 new MerlinAKI());
197 withTrustStoreUsingMerlinAKI(getRootKeyStore(),
198 getTestCertificateChain(ROOT_SIGNED),
199 new MerlinAKI());
200 withTrustStoreUsingMerlinAKI(getRootKeyStore(),
201 getTestCertificateChain(INTERMEDIATE_SIGNED),
202 new MerlinAKI());
203 }
204
205 @Test
206 public void testNameConstraintsWithKeyStoreUsingMerlinBc() throws Exception {
207 assumeFalse(isIBMJdK);
208
209 withKeyStoreUsingMerlin(getSelfKeyStore(),
210 getTestCertificateChain(SELF_SIGNED),
211 getMerlinBc());
212 withKeyStoreUsingMerlin(getRootKeyStore(),
213 getTestCertificateChain(ROOT_SIGNED),
214 getMerlinBc());
215 withKeyStoreUsingMerlin(getRootKeyStore(),
216 getTestCertificateChain(INTERMEDIATE_SIGNED),
217 getMerlinBc());
218 }
219
220 @Test
221 public void testNameConstraintsWithTrustStoreUsingMerlinBc() throws Exception {
222 assumeFalse(isIBMJdK);
223
224 withTrustStoreUsingMerlin(getSelfKeyStore(),
225 getTestCertificateChain(SELF_SIGNED),
226 getMerlinBc());
227 withTrustStoreUsingMerlin(getRootKeyStore(),
228 getTestCertificateChain(ROOT_SIGNED),
229 getMerlinBc());
230 withTrustStoreUsingMerlin(getRootKeyStore(),
231 getTestCertificateChain(INTERMEDIATE_SIGNED),
232 getMerlinBc());
233 }
234
235 @Test
236 public void testNameConstraintsWithKeyStoreUsingMerlinAkiBc() throws Exception {
237 assumeFalse(isIBMJdK);
238
239 withKeyStoreUsingMerlinAKI(getSelfKeyStore(),
240 getTestCertificateChain(SELF_SIGNED),
241 getMerlinAkiBc());
242 withKeyStoreUsingMerlinAKI(getRootKeyStore(),
243 getTestCertificateChain(ROOT_SIGNED),
244 getMerlinAkiBc());
245 withKeyStoreUsingMerlinAKI(getRootKeyStore(),
246 getTestCertificateChain(INTERMEDIATE_SIGNED),
247 getMerlinAkiBc());
248 }
249
250 @Test
251 public void testNameConstraintsWithTrustStoreUsingMerlinAkiBc() throws Exception {
252 assumeFalse(isIBMJdK);
253
254 withTrustStoreUsingMerlinAKI(getSelfKeyStore(),
255 getTestCertificateChain(SELF_SIGNED),
256 getMerlinAkiBc());
257 withTrustStoreUsingMerlinAKI(getRootKeyStore(),
258 getTestCertificateChain(ROOT_SIGNED),
259 getMerlinAkiBc());
260 withTrustStoreUsingMerlinAKI(getRootKeyStore(),
261 getTestCertificateChain(INTERMEDIATE_SIGNED),
262 getMerlinAkiBc());
263 }
264
265 @Test
266 public void testNameConstraintsWithKeyStoreUsingMerlinBreaking() throws Exception {
267 assumeFalse(isIBMJdK);
268
269 Properties properties = new Properties();
270 properties.setProperty("org.apache.wss4j.crypto.merlin.cert.provider.nameconstraints",
271 "true");
272
273 Merlin merlin = new Merlin(properties,
274 this.getClass()
275 .getClassLoader(),
276 null);
277
278 Assertions.assertThrows(Exception.class, () -> {
279 withKeyStoreUsingMerlin(getRootKeyStore(), getTestCertificateChain(ROOT_SIGNED), merlin);
280 });
281 }
282
283 @Test
284 public void testNameConstraintsWithKeyStoreUsingMerlinAkiBreaking() throws Exception {
285 assumeFalse(isIBMJdK);
286
287 Properties properties = new Properties();
288 properties.setProperty("org.apache.wss4j.crypto.merlin.cert.provider.nameconstraints",
289 "true");
290
291 MerlinAKI merlin = new MerlinAKI(properties,
292 this.getClass()
293 .getClassLoader(),
294 null);
295
296 Assertions.assertThrows(Exception.class, () -> {
297 withKeyStoreUsingMerlin(getRootKeyStore(), getTestCertificateChain(ROOT_SIGNED), merlin);
298 });
299 }
300
301 @Test
302 public void testNameConstraintsUsingCertificateStore() throws Exception {
303 assumeFalse(isIBMJdK);
304
305 usingCertificateStore(getSelfKeyStore(), getTestCertificateChain(SELF_SIGNED));
306 usingCertificateStore(getRootKeyStore(), getTestCertificateChain(ROOT_SIGNED));
307 usingCertificateStore(getRootKeyStore(), getTestCertificateChain(INTERMEDIATE_SIGNED));
308 }
309
310 private void withKeyStoreUsingMerlin(KeyStore keyStore, X509Certificate[] certificates,
311 Merlin crypto) throws Exception {
312
313 crypto.setKeyStore(keyStore);
314
315 crypto.verifyTrust(certificates, false, Collections.singletonList(SUBJ_PATTERN));
316
317 }
318
319 private void withTrustStoreUsingMerlin(KeyStore keyStore, X509Certificate[] certificates,
320 Merlin crypto) throws Exception {
321
322 crypto.setTrustStore(keyStore);
323
324 crypto.verifyTrust(certificates, false, Collections.singletonList(SUBJ_PATTERN));
325
326 }
327
328 private void withKeyStoreUsingMerlinAKI(KeyStore keyStore, X509Certificate[] certificates,
329 MerlinAKI crypto) throws Exception {
330
331 crypto.setKeyStore(keyStore);
332
333 crypto.verifyTrust(certificates, false, Collections.singletonList(SUBJ_PATTERN));
334
335 }
336
337 private void withTrustStoreUsingMerlinAKI(KeyStore keyStore, X509Certificate[] certificates,
338 MerlinAKI crypto) throws Exception {
339
340 crypto.setTrustStore(keyStore);
341
342 crypto.verifyTrust(certificates, false, Collections.singletonList(SUBJ_PATTERN));
343
344 }
345
346 private void usingCertificateStore(KeyStore keyStore, X509Certificate[] certificates)
347 throws Exception {
348
349 Enumeration<String> aliases = keyStore.aliases();
350 List<X509Certificate> certList = new ArrayList<>();
351 while (aliases.hasMoreElements()) {
352 String alias = aliases.nextElement();
353 certList.add((X509Certificate) keyStore.getCertificate(alias));
354 }
355
356 CertificateStore crypto = new CertificateStore(certList.toArray(new X509Certificate[] {}));
357
358 crypto.verifyTrust(certificates, false, Collections.singletonList(SUBJ_PATTERN));
359
360 }
361
362 private Merlin getMerlinBc() throws WSSecurityException, IOException {
363 Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
364 Properties properties = new Properties();
365 properties.setProperty("org.apache.wss4j.crypto.merlin.cert.provider", "BC");
366 properties.setProperty("org.apache.wss4j.crypto.merlin.cert.provider.nameconstraints",
367 "true");
368
369 return new Merlin(properties,
370 this.getClass()
371 .getClassLoader(),
372 null);
373 }
374
375 private MerlinAKI getMerlinAkiBc() throws WSSecurityException, IOException {
376 Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
377 Properties properties = new Properties();
378 properties.setProperty("org.apache.wss4j.crypto.merlin.cert.provider", "BC");
379 properties.setProperty("org.apache.wss4j.crypto.merlin.cert.provider.nameconstraints",
380 "true");
381
382 return new MerlinAKI(properties,
383 this.getClass()
384 .getClassLoader(),
385 null);
386 }
387 }