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.SSLFactory;
21  import nl.altindag.ssl.util.KeyStoreUtils;
22  import nl.altindag.ssl.util.TrustManagerUtils;
23  import org.junit.jupiter.api.BeforeAll;
24  import org.junit.jupiter.api.MethodOrderer;
25  import org.junit.jupiter.api.Order;
26  import org.junit.jupiter.api.Test;
27  import org.junit.jupiter.api.TestMethodOrder;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  
31  import javax.net.ssl.HttpsURLConnection;
32  import javax.net.ssl.SSLSocketFactory;
33  import javax.net.ssl.X509ExtendedTrustManager;
34  import java.io.IOException;
35  import java.net.URL;
36  import java.security.KeyStore;
37  
38  import static nl.altindag.ssl.TestConstants.KEYSTORE_LOCATION;
39  import static org.assertj.core.api.Assertions.assertThat;
40  
41  /**
42   * @author Hakan Altindag
43   */
44  @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
45  class HotSwappableX509ExtendedTrustManagerIT {
46  
47      private static final Logger LOGGER = LoggerFactory.getLogger(HotSwappableX509ExtendedTrustManagerIT.class);
48  
49      private static SSLSocketFactory sslSocketFactory;
50      private static X509ExtendedTrustManager trustManager;
51  
52      @BeforeAll
53      static void setUpSSLSocketFactory() {
54          KeyStore trustStoreWithBadSsl = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + "badssl-truststore.p12", "badssl.com".toCharArray());
55          X509ExtendedTrustManager trustManagerWithBadSsl = TrustManagerUtils.createTrustManager(trustStoreWithBadSsl);
56          trustManager = TrustManagerUtils.createSwappableTrustManager(trustManagerWithBadSsl);
57  
58          SSLFactory sslFactory = SSLFactory.builder()
59                  .withIdentityMaterial(KEYSTORE_LOCATION + "badssl-identity.p12", "badssl.com".toCharArray())
60                  .withTrustMaterial(trustManager)
61                  .build();
62  
63          sslSocketFactory = sslFactory.getSslSocketFactory();
64      }
65  
66      @Test
67      @Order(1)
68      void executeHttpsRequestWithSslSocketFactoryContainingBadSslTrustManager() throws IOException {
69          HttpsURLConnection connection = (HttpsURLConnection) new URL("https://client.badssl.com/").openConnection();
70          connection.setSSLSocketFactory(sslSocketFactory);
71          connection.setRequestMethod("GET");
72  
73          int statusCode = connection.getResponseCode();
74  
75          if (statusCode == 400) {
76              LOGGER.warn("Certificate may have expired and needs to be updated");
77          } else {
78              assertThat(statusCode).isEqualTo(200);
79          }
80      }
81  
82      @Test
83      @Order(2)
84      void executeHttpsRequestWithExistingSslSocketFactoryContainingASwappedUnsafeTrustManager() throws IOException {
85          LogCaptor logCaptor = LogCaptor.forName("nl.altindag.ssl.trustmanager.UnsafeX509ExtendedTrustManager");
86  
87          TrustManagerUtils.swapTrustManager(trustManager, TrustManagerUtils.createUnsafeTrustManager());
88  
89          HttpsURLConnection connection = (HttpsURLConnection) new URL("https://client.badssl.com/").openConnection();
90          connection.setSSLSocketFactory(sslSocketFactory);
91          connection.setRequestMethod("GET");
92  
93          int statusCode = connection.getResponseCode();
94  
95          if (statusCode == 400) {
96              LOGGER.warn("Certificate may have expired and needs to be updated");
97          } else {
98              assertThat(statusCode).isEqualTo(200);
99              assertThat(logCaptor.getLogs()).containsExactly("Accepting the following server certificates without validating: [{CN=*.badssl.com, O=Lucas Garron Torres, L=Walnut Creek, ST=California, C=US},{CN=DigiCert SHA2 Secure Server CA, O=DigiCert Inc, C=US}]");
100         }
101     }
102 
103 }