View Javadoc
1   /*
2    * Copyright 2019-2021 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package nl.altindag.ssl.trustmanager;
18  
19  import nl.altindag.log.LogCaptor;
20  import nl.altindag.ssl.util.KeyStoreUtils;
21  import org.junit.jupiter.api.Test;
22  
23  import javax.net.ssl.SSLEngine;
24  import javax.net.ssl.X509ExtendedTrustManager;
25  import java.net.Socket;
26  import java.security.KeyStore;
27  import java.security.KeyStoreException;
28  import java.security.cert.X509Certificate;
29  
30  import static org.assertj.core.api.Assertions.assertThat;
31  import static org.assertj.core.api.Assertions.assertThatCode;
32  
33  /**
34   * @author Hakan Altindag
35   */
36  class UnsafeX509ExtendedTrustManagerShould {
37  
38      private static final String TRUSTSTORE_FILE_NAME = "truststore.jks";
39      private static final char[] TRUSTSTORE_PASSWORD = new char[] {'s', 'e', 'c', 'r', 'e', 't'};
40      private static final String KEYSTORE_FILE_NAME = "identity.jks";
41      private static final char[] KEYSTORE_PASSWORD = new char[] {'s', 'e', 'c', 'r', 'e', 't'};
42      private static final String KEYSTORE_LOCATION = "keystores-for-unit-tests/";
43  
44      @Test
45      void checkClientTrusted() throws KeyStoreException {
46          LogCaptor logCaptor = LogCaptor.forClass(UnsafeX509ExtendedTrustManager.class);
47  
48          KeyStore trustStore = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD);
49          X509ExtendedTrustManager trustManager = UnsafeX509ExtendedTrustManager.getInstance();
50          X509Certificate[] trustedCerts = KeyStoreTestUtils.getTrustedX509Certificates(trustStore);
51  
52          assertThat(trustManager).isNotNull();
53          assertThat(trustManager.getAcceptedIssuers()).isEmpty();
54          assertThat(trustedCerts).hasSize(1);
55  
56          assertThatCode(() -> trustManager.checkClientTrusted(trustedCerts, "RSA"))
57                  .doesNotThrowAnyException();
58  
59          assertThat(logCaptor.getWarnLogs())
60                  .hasSize(1)
61                  .containsExactly("Accepting the following client certificates without validating: [{CN=*.google.com, O=Google LLC, L=Mountain View, ST=California, C=US}]");
62      }
63  
64      @Test
65      void checkClientTrustedWithSslEngine() throws KeyStoreException {
66          LogCaptor logCaptor = LogCaptor.forClass(UnsafeX509ExtendedTrustManager.class);
67  
68          KeyStore trustStore = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD);
69          X509ExtendedTrustManager trustManager = UnsafeX509ExtendedTrustManager.getInstance();
70          X509Certificate[] trustedCerts = KeyStoreTestUtils.getTrustedX509Certificates(trustStore);
71  
72          assertThat(trustManager).isNotNull();
73          assertThat(trustManager.getAcceptedIssuers()).isEmpty();
74          assertThat(trustedCerts).hasSize(1);
75  
76          assertThatCode(() -> trustManager.checkClientTrusted(trustedCerts, "RSA", (SSLEngine) null))
77                  .doesNotThrowAnyException();
78  
79          assertThat(logCaptor.getWarnLogs())
80                  .hasSize(1)
81                  .contains("Accepting the following client certificates without validating: [{CN=*.google.com, O=Google LLC, L=Mountain View, ST=California, C=US}]");
82      }
83  
84      @Test
85      void checkClientTrustedWithSocket() throws KeyStoreException {
86          LogCaptor logCaptor = LogCaptor.forClass(UnsafeX509ExtendedTrustManager.class);
87  
88          KeyStore trustStore = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD);
89          X509ExtendedTrustManager trustManager = UnsafeX509ExtendedTrustManager.getInstance();
90          X509Certificate[] trustedCerts = KeyStoreTestUtils.getTrustedX509Certificates(trustStore);
91  
92          assertThat(trustManager).isNotNull();
93          assertThat(trustManager.getAcceptedIssuers()).isEmpty();
94          assertThat(trustedCerts).hasSize(1);
95  
96          assertThatCode(() -> trustManager.checkClientTrusted(trustedCerts, "RSA", (Socket) null))
97                  .doesNotThrowAnyException();
98  
99          assertThat(logCaptor.getWarnLogs())
100                 .hasSize(1)
101                 .contains("Accepting the following client certificates without validating: [{CN=*.google.com, O=Google LLC, L=Mountain View, ST=California, C=US}]");
102     }
103 
104     @Test
105     void checkServerTrusted() throws KeyStoreException {
106         LogCaptor logCaptor = LogCaptor.forClass(UnsafeX509ExtendedTrustManager.class);
107 
108         X509Certificate[] trustedCerts = KeyStoreTestUtils.getTrustedX509Certificates(KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + KEYSTORE_FILE_NAME, KEYSTORE_PASSWORD));
109 
110         X509ExtendedTrustManager trustManager = UnsafeX509ExtendedTrustManager.getInstance();
111 
112         assertThat(trustedCerts).hasSize(1);
113         assertThat(trustManager.getAcceptedIssuers()).isEmpty();
114 
115         assertThatCode(() -> trustManager.checkServerTrusted(trustedCerts, "RSA"))
116                 .doesNotThrowAnyException();
117 
118         assertThat(logCaptor.getWarnLogs())
119                 .hasSize(1)
120                 .contains("Accepting the following server certificates without validating: [{CN=Prof Oak, OU=Oak Pokémon Research Lab, O=Oak Pokémon Research Lab, C=Pallet Town}]");
121     }
122 
123     @Test
124     void checkServerTrustedWithSslEngine() throws KeyStoreException {
125         LogCaptor logCaptor = LogCaptor.forClass(UnsafeX509ExtendedTrustManager.class);
126 
127         X509Certificate[] trustedCerts = KeyStoreTestUtils.getTrustedX509Certificates(KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + KEYSTORE_FILE_NAME, KEYSTORE_PASSWORD));
128 
129         X509ExtendedTrustManager trustManager = UnsafeX509ExtendedTrustManager.getInstance();
130 
131         assertThat(trustedCerts).hasSize(1);
132         assertThat(trustManager.getAcceptedIssuers()).isEmpty();
133 
134         assertThatCode(() -> trustManager.checkServerTrusted(trustedCerts, "RSA", (SSLEngine) null))
135                 .doesNotThrowAnyException();
136 
137         assertThat(logCaptor.getWarnLogs())
138                 .hasSize(1)
139                 .contains("Accepting the following server certificates without validating: [{CN=Prof Oak, OU=Oak Pokémon Research Lab, O=Oak Pokémon Research Lab, C=Pallet Town}]");
140     }
141 
142     @Test
143     void checkServerTrustedWitSocket() throws KeyStoreException {
144         LogCaptor logCaptor = LogCaptor.forClass(UnsafeX509ExtendedTrustManager.class);
145 
146         X509Certificate[] trustedCerts = KeyStoreTestUtils.getTrustedX509Certificates(KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + KEYSTORE_FILE_NAME, KEYSTORE_PASSWORD));
147 
148         X509ExtendedTrustManager trustManager = UnsafeX509ExtendedTrustManager.getInstance();
149 
150         assertThat(trustedCerts).hasSize(1);
151         assertThat(trustManager.getAcceptedIssuers()).isEmpty();
152 
153         assertThatCode(() -> trustManager.checkServerTrusted(trustedCerts, "RSA", (Socket) null))
154                 .doesNotThrowAnyException();
155 
156         assertThat(logCaptor.getWarnLogs())
157                 .hasSize(1)
158                 .contains("Accepting the following server certificates without validating: [{CN=Prof Oak, OU=Oak Pokémon Research Lab, O=Oak Pokémon Research Lab, C=Pallet Town}]");
159     }
160 
161     @Test
162     void checkClientTrustedDoesNotLogAnythingWhenDebugLevelIsDisabled() throws KeyStoreException {
163         LogCaptor logCaptor = LogCaptor.forClass(UnsafeX509ExtendedTrustManager.class);
164 
165         KeyStore trustStore = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD);
166         X509ExtendedTrustManager trustManager = UnsafeX509ExtendedTrustManager.getInstance();
167         X509Certificate[] trustedCerts = KeyStoreTestUtils.getTrustedX509Certificates(trustStore);
168 
169         assertThat(trustManager).isNotNull();
170         assertThat(trustManager.getAcceptedIssuers()).isEmpty();
171         assertThat(trustedCerts).hasSize(1);
172 
173         assertThatCode(() -> trustManager.checkClientTrusted(trustedCerts, "RSA"))
174                 .doesNotThrowAnyException();
175 
176         assertThat(logCaptor.getWarnLogs())
177                 .hasSize(1)
178                 .contains("Accepting the following client certificates without validating: [{CN=*.google.com, O=Google LLC, L=Mountain View, ST=California, C=US}]");
179     }
180 
181     @Test
182     void checkClientTrustedWithSslEngineDoesNotLogAnythingWhenDebugLevelIsDisabled() throws KeyStoreException {
183         LogCaptor logCaptor = LogCaptor.forClass(UnsafeX509ExtendedTrustManager.class);
184 
185         KeyStore trustStore = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD);
186         X509ExtendedTrustManager trustManager = UnsafeX509ExtendedTrustManager.getInstance();
187         X509Certificate[] trustedCerts = KeyStoreTestUtils.getTrustedX509Certificates(trustStore);
188 
189         assertThat(trustManager).isNotNull();
190         assertThat(trustManager.getAcceptedIssuers()).isEmpty();
191         assertThat(trustedCerts).hasSize(1);
192 
193         assertThatCode(() -> trustManager.checkClientTrusted(trustedCerts, "RSA", (SSLEngine) null))
194                 .doesNotThrowAnyException();
195 
196         assertThat(logCaptor.getWarnLogs())
197                 .hasSize(1)
198                 .contains("Accepting the following client certificates without validating: [{CN=*.google.com, O=Google LLC, L=Mountain View, ST=California, C=US}]");
199     }
200 
201     @Test
202     void checkClientTrustedWithSocketDoesNotLogAnythingWhenDebugLevelIsDisabled() throws KeyStoreException {
203         LogCaptor logCaptor = LogCaptor.forClass(UnsafeX509ExtendedTrustManager.class);
204 
205         KeyStore trustStore = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD);
206         X509ExtendedTrustManager trustManager = UnsafeX509ExtendedTrustManager.getInstance();
207         X509Certificate[] trustedCerts = KeyStoreTestUtils.getTrustedX509Certificates(trustStore);
208 
209         assertThat(trustManager).isNotNull();
210         assertThat(trustManager.getAcceptedIssuers()).isEmpty();
211         assertThat(trustedCerts).hasSize(1);
212 
213         assertThatCode(() -> trustManager.checkClientTrusted(trustedCerts, "RSA", (Socket) null))
214                 .doesNotThrowAnyException();
215 
216         assertThat(logCaptor.getWarnLogs())
217                 .hasSize(1)
218                 .contains("Accepting the following client certificates without validating: [{CN=*.google.com, O=Google LLC, L=Mountain View, ST=California, C=US}]");
219     }
220 
221     @Test
222     void checkServerTrustedDoesNotLogAnythingWhenDebugLevelIsDisabled() throws KeyStoreException {
223         LogCaptor logCaptor = LogCaptor.forClass(UnsafeX509ExtendedTrustManager.class);
224 
225         X509Certificate[] trustedCerts = KeyStoreTestUtils.getTrustedX509Certificates(KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + KEYSTORE_FILE_NAME, KEYSTORE_PASSWORD));
226 
227         X509ExtendedTrustManager trustManager = UnsafeX509ExtendedTrustManager.getInstance();
228 
229         assertThat(trustedCerts).hasSize(1);
230         assertThat(trustManager.getAcceptedIssuers()).isEmpty();
231 
232         assertThatCode(() -> trustManager.checkServerTrusted(trustedCerts, "RSA"))
233                 .doesNotThrowAnyException();
234 
235         assertThat(logCaptor.getWarnLogs())
236                 .hasSize(1)
237                 .contains("Accepting the following server certificates without validating: [{CN=Prof Oak, OU=Oak Pokémon Research Lab, O=Oak Pokémon Research Lab, C=Pallet Town}]");
238     }
239 
240     @Test
241     void checkServerTrustedWithSslEngineDoesNotLogAnythingWhenDebugLevelIsDisabled() throws KeyStoreException {
242         LogCaptor logCaptor = LogCaptor.forClass(UnsafeX509ExtendedTrustManager.class);
243 
244         X509Certificate[] trustedCerts = KeyStoreTestUtils.getTrustedX509Certificates(KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + KEYSTORE_FILE_NAME, KEYSTORE_PASSWORD));
245 
246         X509ExtendedTrustManager trustManager = UnsafeX509ExtendedTrustManager.getInstance();
247 
248         assertThat(trustedCerts).hasSize(1);
249         assertThat(trustManager.getAcceptedIssuers()).isEmpty();
250 
251         assertThatCode(() -> trustManager.checkServerTrusted(trustedCerts, "RSA", (SSLEngine) null))
252                 .doesNotThrowAnyException();
253 
254         assertThat(logCaptor.getWarnLogs())
255                 .hasSize(1)
256                 .contains("Accepting the following server certificates without validating: [{CN=Prof Oak, OU=Oak Pokémon Research Lab, O=Oak Pokémon Research Lab, C=Pallet Town}]");
257     }
258 
259     @Test
260     void checkServerTrustedWithSocketDoesNotLogAnythingWhenDebugLevelIsDisabled() throws KeyStoreException {
261         LogCaptor logCaptor = LogCaptor.forClass(UnsafeX509ExtendedTrustManager.class);
262 
263         X509Certificate[] trustedCerts = KeyStoreTestUtils.getTrustedX509Certificates(KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + KEYSTORE_FILE_NAME, KEYSTORE_PASSWORD));
264 
265         X509ExtendedTrustManager trustManager = UnsafeX509ExtendedTrustManager.getInstance();
266 
267         assertThat(trustedCerts).hasSize(1);
268         assertThat(trustManager.getAcceptedIssuers()).isEmpty();
269 
270         assertThatCode(() -> trustManager.checkServerTrusted(trustedCerts, "RSA", (Socket) null))
271                 .doesNotThrowAnyException();
272 
273         assertThat(logCaptor.getWarnLogs())
274                 .hasSize(1)
275                 .contains("Accepting the following server certificates without validating: [{CN=Prof Oak, OU=Oak Pokémon Research Lab, O=Oak Pokémon Research Lab, C=Pallet Town}]");
276     }
277 
278 }