|
13 | 13 |
|
14 | 14 | package org.eclipse.paho.client.mqttv3.test; |
15 | 15 |
|
| 16 | +import java.io.FileInputStream; |
16 | 17 | import java.io.IOException; |
17 | 18 | import java.io.InputStream; |
18 | 19 | import java.security.KeyStore; |
19 | 20 | import java.security.SecureRandom; |
20 | | -import java.security.cert.Certificate; |
21 | | -import java.security.cert.CertificateFactory; |
22 | 21 | import java.util.Arrays; |
23 | 22 | import java.util.Enumeration; |
24 | 23 | import java.util.logging.Level; |
25 | 24 | import java.util.logging.Logger; |
26 | | - |
27 | 25 | import javax.net.ssl.SSLContext; |
28 | 26 | import javax.net.ssl.SSLSessionContext; |
29 | 27 | import javax.net.ssl.SSLSocket; |
|
38 | 36 | import org.junit.BeforeClass; |
39 | 37 | import org.junit.Test; |
40 | 38 |
|
41 | | - |
42 | 39 | /** |
43 | 40 | * This test aims to run some basic SSL functionality tests of the MQTT client |
44 | 41 | */ |
45 | 42 |
|
46 | 43 | public class SSLSessionResumptionTest { |
47 | 44 |
|
48 | | - static final Class<?> cclass = SSLSessionResumptionTest.class; |
49 | | - private static final String className = cclass.getName(); |
50 | | - private static final Logger log = Logger.getLogger(className); |
51 | | - |
52 | | - |
53 | | - private static String serverURI; |
54 | | - private static String serverHost; |
55 | | - private static int serverPort; |
56 | | - private static final String certificateName = "iot.eclipse.org.crt"; |
57 | | - |
58 | | - |
59 | | - /** |
60 | | - * @throws Exception |
61 | | - */ |
62 | | - @BeforeClass |
63 | | - public static void setUpBeforeClass() throws Exception { |
64 | | - |
65 | | - try { |
66 | | - String methodName = Utility.getMethodName(); |
67 | | - LoggingUtilities.banner(log, cclass, methodName); |
68 | | - serverURI = "ssl://" + TestProperties.getServerURI().getHost(); |
69 | | - serverHost = TestProperties.getServerURI().getHost(); |
70 | | - serverPort = TestProperties.getServerSSLPort(); |
71 | | - |
72 | | - } |
73 | | - catch (Exception exception) { |
74 | | - log.log(Level.SEVERE, "caught exception:", exception); |
75 | | - throw exception; |
76 | | - } |
77 | | - } |
78 | | - |
79 | | - /** |
80 | | - * This test involves inspecting the SSL debug log |
81 | | - * and the Wireshark capture. |
82 | | - * |
83 | | - * Paho defeats the default SSL session caching which |
84 | | - * allows to have abbreviated SSL handshakes on |
85 | | - * following connections. |
86 | | - * |
87 | | - * @throws Exception |
88 | | - */ |
89 | | - @Test |
90 | | - public void testSSLSessionInvalidated() throws Exception { |
91 | | - //System.setProperty("javax.net.debug", "all"); |
92 | | - |
93 | | - SSLSocketFactory factory = getSocketFactory(certificateName); |
94 | | - |
95 | | - MqttConnectOptions options = new MqttConnectOptions(); |
96 | | - options.setServerURIs(new String[] {serverURI}); |
97 | | - options.setKeepAliveInterval(60); |
98 | | - options.setSocketFactory(factory); |
99 | | - |
100 | | - MqttClient mqttClient = new MqttClient(serverURI, MqttClient.generateClientId()); |
101 | | - |
102 | | - |
103 | | - log.info("Connecting to: " + serverURI); |
104 | | - mqttClient.connect(options); |
105 | | - |
106 | | - Thread.sleep(2000); |
107 | | - |
108 | | - log.info("Disconnetting..."); |
109 | | - mqttClient.disconnect(); |
110 | | - |
111 | | - Thread.sleep(2000); |
112 | | - |
113 | | - log.info("Connecting again... Paho will not be able to perform an abbreviated SSL handshake"); |
114 | | - mqttClient.connect(options); |
115 | | - |
116 | | - Thread.sleep(2000); |
117 | | - |
118 | | - log.info("Disconnetting..."); |
119 | | - mqttClient.disconnect(); |
120 | | - |
121 | | - } |
122 | | - |
123 | | - /** |
124 | | - * This test involves inspecting the SSL debug log |
125 | | - * and the Wireshark capture. |
126 | | - * |
127 | | - * By default, Java caches SSL sessions which |
128 | | - * allows to have abbreviated SSL handshakes on |
129 | | - * following connections. |
130 | | - * |
131 | | - * @throws Exception |
132 | | - */ |
133 | | - @Test |
134 | | - public void testSSLSessionCached() throws Exception { |
135 | | - // System.setProperty("javax.net.debug", "all"); |
136 | | - |
137 | | - SSLSocketFactory factory = getSocketFactory(certificateName); |
138 | | - |
139 | | - |
140 | | - log.info("Do handshake..."); |
141 | | - doHandshake(factory, serverHost, serverPort); |
142 | | - |
143 | | - log.info("Done! Redo handshake... An abbreviated SSL handshake will be performed"); |
144 | | - doHandshake(factory, serverHost, serverPort); |
145 | | - |
146 | | - log.info("Done!"); |
147 | | - } |
148 | | - |
149 | | - private static void doHandshake(SSLSocketFactory factory, String host, int port) { |
150 | | - SSLSocket socket = null; |
151 | | - try { |
152 | | - socket = (SSLSocket) factory.createSocket(host, port); |
153 | | - |
154 | | - socket.startHandshake(); |
155 | | - |
156 | | - SSLSessionContext ctx = socket.getSession().getSessionContext(); |
157 | | - if (ctx != null) { |
158 | | - Enumeration<byte[]> ids = ctx.getIds(); |
159 | | - while (ids.hasMoreElements()) { |
160 | | - byte[] id = ids.nextElement(); |
161 | | - log.info("Session ID: " + Arrays.toString(id)); |
162 | | - log.info("Cypher suite: " + ctx.getSession(id).getCipherSuite()); |
163 | | - } |
164 | | - } else { |
165 | | - log.info("null SSLSessionContext"); |
166 | | - } |
167 | | - } catch (Exception e) { |
168 | | - e.printStackTrace(); |
169 | | - } finally { |
170 | | - if (socket != null) { |
171 | | - try { |
172 | | - socket.close(); |
173 | | - } catch (IOException e) { |
174 | | - e.printStackTrace(); |
| 45 | + static final Class<?> cclass = SSLSessionResumptionTest.class; |
| 46 | + private static final String className = cclass.getName(); |
| 47 | + private static final Logger log = Logger.getLogger(className); |
| 48 | + |
| 49 | + private static String serverURI; |
| 50 | + private static String serverHost; |
| 51 | + private static int serverPort; |
| 52 | + |
| 53 | + /** |
| 54 | + * @throws Exception |
| 55 | + */ |
| 56 | + @BeforeClass |
| 57 | + public static void setUpBeforeClass() throws Exception { |
| 58 | + |
| 59 | + try { |
| 60 | + String methodName = Utility.getMethodName(); |
| 61 | + LoggingUtilities.banner(log, cclass, methodName); |
| 62 | + serverURI = "ssl://" + TestProperties.getServerURI().getHost(); |
| 63 | + serverHost = TestProperties.getServerURI().getHost(); |
| 64 | + serverPort = TestProperties.getServerSSLPort(); |
| 65 | + |
| 66 | + } catch (Exception exception) { |
| 67 | + log.log(Level.SEVERE, "caught exception:", exception); |
| 68 | + throw exception; |
| 69 | + } |
| 70 | + } |
| 71 | + |
| 72 | + /** |
| 73 | + * This test involves inspecting the SSL debug log and the Wireshark |
| 74 | + * capture. |
| 75 | + * |
| 76 | + * Paho defeats the default SSL session caching which allows to have |
| 77 | + * abbreviated SSL handshakes on following connections. |
| 78 | + * |
| 79 | + * @throws Exception |
| 80 | + */ |
| 81 | + @Test |
| 82 | + public void testSSLSessionInvalidated() throws Exception { |
| 83 | + // System.setProperty("javax.net.debug", "all"); |
| 84 | + |
| 85 | + SSLSocketFactory factory = getSocketFactory(); |
| 86 | + |
| 87 | + MqttConnectOptions options = new MqttConnectOptions(); |
| 88 | + options.setServerURIs(new String[] { serverURI }); |
| 89 | + options.setKeepAliveInterval(60); |
| 90 | + options.setSocketFactory(factory); |
| 91 | + |
| 92 | + MqttClient mqttClient = new MqttClient(serverURI, MqttClient.generateClientId()); |
| 93 | + |
| 94 | + log.info("Connecting to: " + serverURI); |
| 95 | + mqttClient.connect(options); |
| 96 | + |
| 97 | + Thread.sleep(2000); |
| 98 | + |
| 99 | + log.info("Disconnetting..."); |
| 100 | + mqttClient.disconnect(); |
| 101 | + |
| 102 | + Thread.sleep(2000); |
| 103 | + |
| 104 | + log.info("Connecting again... Paho will not be able to perform an abbreviated SSL handshake"); |
| 105 | + mqttClient.connect(options); |
| 106 | + |
| 107 | + Thread.sleep(2000); |
| 108 | + |
| 109 | + log.info("Disconnetting..."); |
| 110 | + mqttClient.disconnect(); |
| 111 | + |
| 112 | + } |
| 113 | + |
| 114 | + /** |
| 115 | + * This test involves inspecting the SSL debug log and the Wireshark |
| 116 | + * capture. |
| 117 | + * |
| 118 | + * By default, Java caches SSL sessions which allows to have abbreviated SSL |
| 119 | + * handshakes on following connections. |
| 120 | + * |
| 121 | + * @throws Exception |
| 122 | + */ |
| 123 | + @Test |
| 124 | + public void testSSLSessionCached() throws Exception { |
| 125 | + // System.setProperty("javax.net.debug", "all"); |
| 126 | + |
| 127 | + SSLSocketFactory factory = getSocketFactory(); |
| 128 | + |
| 129 | + log.info("Do handshake..."); |
| 130 | + doHandshake(factory, serverHost, serverPort); |
| 131 | + |
| 132 | + log.info("Done! Redo handshake... An abbreviated SSL handshake will be performed"); |
| 133 | + doHandshake(factory, serverHost, serverPort); |
| 134 | + |
| 135 | + log.info("Done!"); |
| 136 | + } |
| 137 | + |
| 138 | + private static void doHandshake(SSLSocketFactory factory, String host, int port) { |
| 139 | + SSLSocket socket = null; |
| 140 | + try { |
| 141 | + socket = (SSLSocket) factory.createSocket(host, port); |
| 142 | + |
| 143 | + socket.startHandshake(); |
| 144 | + |
| 145 | + SSLSessionContext ctx = socket.getSession().getSessionContext(); |
| 146 | + if (ctx != null) { |
| 147 | + Enumeration<byte[]> ids = ctx.getIds(); |
| 148 | + while (ids.hasMoreElements()) { |
| 149 | + byte[] id = ids.nextElement(); |
| 150 | + log.info("Session ID: " + Arrays.toString(id)); |
| 151 | + log.info("Cypher suite: " + ctx.getSession(id).getCipherSuite()); |
| 152 | + } |
| 153 | + } else { |
| 154 | + log.info("null SSLSessionContext"); |
| 155 | + } |
| 156 | + } catch (Exception e) { |
| 157 | + e.printStackTrace(); |
| 158 | + } finally { |
| 159 | + if (socket != null) { |
| 160 | + try { |
| 161 | + socket.close(); |
| 162 | + } catch (IOException e) { |
| 163 | + e.printStackTrace(); |
| 164 | + } |
175 | 165 | } |
176 | | - } |
177 | | - } |
178 | | - } |
179 | | - |
180 | | - private static SSLSocketFactory getSocketFactory(String certificateName) throws Exception { |
181 | | - InputStream certStream = SSLSessionResumptionTest.class.getClassLoader().getResourceAsStream(certificateName); |
182 | | - CertificateFactory certFactory = CertificateFactory.getInstance("X509"); |
183 | | - Certificate certificate = certFactory.generateCertificate(certStream); |
184 | | - SSLContext sslContext = SSLContext.getInstance("TLS"); |
185 | | - TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); |
186 | | - KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); |
187 | | - keyStore.load(null); |
188 | | - keyStore.setCertificateEntry("alias", certificate); |
189 | | - trustManagerFactory.init(keyStore); |
190 | | - sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom()); |
191 | | - return sslContext.getSocketFactory(); |
192 | | - } |
| 166 | + } |
| 167 | + } |
| 168 | + |
| 169 | + private static SSLSocketFactory getSocketFactory() throws Exception { |
| 170 | + InputStream keyStoreStream = new FileInputStream(TestProperties.getClientKeyStore()); |
| 171 | + SSLContext sslContext = SSLContext.getInstance("TLS"); |
| 172 | + TrustManagerFactory trustManagerFactory = TrustManagerFactory |
| 173 | + .getInstance(TrustManagerFactory.getDefaultAlgorithm()); |
| 174 | + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); |
| 175 | + keyStore.load(keyStoreStream, TestProperties.getClientKeyStorePassword().toCharArray()); |
| 176 | + trustManagerFactory.init(keyStore); |
| 177 | + sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom()); |
| 178 | + return sslContext.getSocketFactory(); |
| 179 | + } |
193 | 180 | } |
0 commit comments