Last modified by Pascal Robert on 2007/09/03 19:33

Show last authors
1 == Francis Labrie ==
2
3 Sometimes, it's would be useful to relax the Java security manager to allow connection to secure HTTP server using self-signed certificate, especially during development phase. To avoid Java exception on HTTPS connection, it's possible to add self signed certificate to the Java trusted X509 certificate repository using Java keystore command line tool:
4
5 {{noformat}}
6
7 % cd /Library/Java/Home/lib/security
8 % sudo keytool -import -keystore cacerts -alias anAlias -file aCertificate
9
10 {{/noformat}}
11
12 (The default password for the "cacerts" keystore is "changeit")
13
14 But this can be painful, even more if the application must be tested with various servers using self-signed or bad defined certificate. And if a server is using a certificate with a hostname different from the one you use to test it, it will still fail.
15
16 It's also possible to change the {{code language="none"}}TrustManager{{/code}} and {{code language="none"}}HostnameVerifier{{/code}} in Java code, but the API did change from JDK 1.3 and 1.4. Unfortunately, the old deprecated {{code language="none"}}"com.sun.net.ssl"{{/code}} package is still available, making setting of a custom {{code language="none"}}TrustManager{{/code}} and {{code language="none"}}HostnameVerifier{{/code}} a bit difficult.
17
18 So I've created an utility class that allow relaxing of the SSL trust rules. Simply add it to a package, an application or a framework, and call:
19
20 * {{code language="none"}}SSLUtilities.trustAllHostnames(){{/code}} to turn off the default hostname verification on HTTPS connection;
21 * {{code language="none"}}SSLUtilities.trustAllHttpsCertificates(){{/code}} to turn off the default certificate validation on HTTPS connection.
22
23 {{code 0="java" title="SSLUtilities.java"}}
24
25 import java.security.GeneralSecurityException;
26 import java.security.SecureRandom;
27 import java.security.cert.X509Certificate;
28 import javax.net.ssl.HostnameVerifier;
29 import javax.net.ssl.HttpsURLConnection;
30 import javax.net.ssl.SSLContext;
31 import javax.net.ssl.TrustManager;
32 import javax.net.ssl.X509TrustManager;
33
34 /**
35 * This class provide various static methods that relax X509 certificate and
36 * hostname verification while using the SSL over the HTTP protocol.
37 *
38 * @author Francis Labrie
39 */
40 public final class SSLUtilities {
41
42 /**
43 * Hostname verifier for the Sun's deprecated API.
44 *
45 * @deprecated see {@link #_hostnameVerifier}.
46 */
47 private static com.sun.net.ssl.HostnameVerifier __hostnameVerifier;
48 /**
49 * Thrust managers for the Sun's deprecated API.
50 *
51 * @deprecated see {@link #_trustManagers}.
52 */
53 private static com.sun.net.ssl.TrustManager[] __trustManagers;
54 /**
55 * Hostname verifier.
56 */
57 private static HostnameVerifier _hostnameVerifier;
58 /**
59 * Thrust managers.
60 */
61 private static TrustManager[] _trustManagers;
62
63
64 /**
65 * Set the default Hostname Verifier to an instance of a fake class that
66 * trust all hostnames. This method uses the old deprecated API from the
67 * <code>com.sun.ssl</code> package.
68 *
69 * @deprecated see {@link #_trustAllHostnames()}.
70 */
71 private static void __trustAllHostnames() {
72 // Create a trust manager that does not validate certificate chains
73 if(__hostnameVerifier == null) {
74 __hostnameVerifier = new _FakeHostnameVerifier();
75 } // if
76 // Install the all-trusting host name verifier
77 com.sun.net.ssl.HttpsURLConnection.
78 setDefaultHostnameVerifier(__hostnameVerifier);
79 } // __trustAllHttpsCertificates
80
81 /**
82 * Set the default X509 Trust Manager to an instance of a fake class that
83 * trust all certificates, even the self-signed ones. This method uses the
84 * old deprecated API from the <code>com.sun.ssl</code> package.
85 *
86 * @deprecated see {@link #_trustAllHttpsCertificates()}.
87 */
88 private static void __trustAllHttpsCertificates() {
89 com.sun.net.ssl.SSLContext context;
90
91 // Create a trust manager that does not validate certificate chains
92 if(__trustManagers == null) {
93 __trustManagers = new com.sun.net.ssl.TrustManager[]
94 {new _FakeX509TrustManager()};
95 } // if
96 // Install the all-trusting trust manager
97 try {
98 context = com.sun.net.ssl.SSLContext.getInstance("SSL");
99 context.init(null, __trustManagers, new SecureRandom());
100 } catch(GeneralSecurityException gse) {
101 throw new IllegalStateException(gse.getMessage());
102 } // catch
103 com.sun.net.ssl.HttpsURLConnection.
104 setDefaultSSLSocketFactory(context.getSocketFactory());
105 } // __trustAllHttpsCertificates
106
107 /**
108 * Return <code>true</code> if the protocol handler property <code>java.
109 * protocol.handler.pkgs</code> is set to the Sun's <code>com.sun.net.ssl.
110 * internal.www.protocol</code> deprecated one, <code>false</code>
111 * otherwise.
112 *
113 * @return <code>true</code> if the protocol handler
114 * property is set to the Sun's deprecated one, <code>false</code>
115 * otherwise.
116 */
117 private static boolean isDeprecatedSSLProtocol() {
118 return("com.sun.net.ssl.internal.www.protocol".equals(System.
119 getProperty("java.protocol.handler.pkgs")));
120 } // isDeprecatedSSLProtocol
121
122 /**
123 * Set the default Hostname Verifier to an instance of a fake class that
124 * trust all hostnames.
125 */
126 private static void _trustAllHostnames() {
127 // Create a trust manager that does not validate certificate chains
128 if(_hostnameVerifier == null) {
129 _hostnameVerifier = new FakeHostnameVerifier();
130 } // if
131 // Install the all-trusting host name verifier:
132 HttpsURLConnection.setDefaultHostnameVerifier(_hostnameVerifier);
133 } // _trustAllHttpsCertificates
134
135 /**
136 * Set the default X509 Trust Manager to an instance of a fake class that
137 * trust all certificates, even the self-signed ones.
138 */
139 private static void _trustAllHttpsCertificates() {
140 SSLContext context;
141
142 // Create a trust manager that does not validate certificate chains
143 if(_trustManagers == null) {
144 _trustManagers = new TrustManager[] {new FakeX509TrustManager()};
145 } // if
146 // Install the all-trusting trust manager:
147 try {
148 context = SSLContext.getInstance("SSL");
149 context.init(null, _trustManagers, new SecureRandom());
150 } catch(GeneralSecurityException gse) {
151 throw new IllegalStateException(gse.getMessage());
152 } // catch
153 HttpsURLConnection.setDefaultSSLSocketFactory(context.
154 getSocketFactory());
155 } // _trustAllHttpsCertificates
156
157 /**
158 * Set the default Hostname Verifier to an instance of a fake class that
159 * trust all hostnames.
160 */
161 public static void trustAllHostnames() {
162 // Is the deprecated protocol setted?
163 if(isDeprecatedSSLProtocol()) {
164 __trustAllHostnames();
165 } else {
166 _trustAllHostnames();
167 } // else
168 } // trustAllHostnames
169
170 /**
171 * Set the default X509 Trust Manager to an instance of a fake class that
172 * trust all certificates, even the self-signed ones.
173 */
174 public static void trustAllHttpsCertificates() {
175 // Is the deprecated protocol setted?
176 if(isDeprecatedSSLProtocol()) {
177 __trustAllHttpsCertificates();
178 } else {
179 _trustAllHttpsCertificates();
180 } // else
181 } // trustAllHttpsCertificates
182
183 /**
184 * This class implements a fake hostname verificator, trusting any host
185 * name. This class uses the old deprecated API from the <code>com.sun.
186 * ssl</code> package.
187 *
188 * @author Francis Labrie
189 *
190 * @deprecated see {@link SSLUtilities.FakeHostnameVerifier}.
191 */
192 public static class _FakeHostnameVerifier
193 implements com.sun.net.ssl.HostnameVerifier {
194
195 /**
196 * Always return <code>true</code>, indicating that the host name is an
197 * acceptable match with the server's authentication scheme.
198 *
199 * @param hostname the host name.
200 * @param session the SSL session used on the connection to
201 * host.
202 * @return the <code>true</code> boolean value
203 * indicating the host name is trusted.
204 */
205 public boolean verify(String hostname, String session) {
206 return(true);
207 } // verify
208 } // _FakeHostnameVerifier
209
210
211 /**
212 * This class allow any X509 certificates to be used to authenticate the
213 * remote side of a secure socket, including self-signed certificates. This
214 * class uses the old deprecated API from the <code>com.sun.ssl</code>
215 * package.
216 *
217 * @author Francis Labrie
218 *
219 * @deprecated see {@link SSLUtilities.FakeX509TrustManager}.
220 */
221 public static class _FakeX509TrustManager
222 implements com.sun.net.ssl.X509TrustManager {
223
224 /**
225 * Empty array of certificate authority certificates.
226 */
227 private static final X509Certificate[] _AcceptedIssuers =
228 new X509Certificate[] {};
229
230
231 /**
232 * Always return <code>true</code>, trusting for client SSL
233 * <code>chain</code> peer certificate chain.
234 *
235 * @param chain the peer certificate chain.
236 * @return the <code>true</code> boolean value
237 * indicating the chain is trusted.
238 */
239 public boolean isClientTrusted(X509Certificate[] chain) {
240 return(true);
241 } // checkClientTrusted
242
243 /**
244 * Always return <code>true</code>, trusting for server SSL
245 * <code>chain</code> peer certificate chain.
246 *
247 * @param chain the peer certificate chain.
248 * @return the <code>true</code> boolean value
249 * indicating the chain is trusted.
250 */
251 public boolean isServerTrusted(X509Certificate[] chain) {
252 return(true);
253 } // checkServerTrusted
254
255 /**
256 * Return an empty array of certificate authority certificates which
257 * are trusted for authenticating peers.
258 *
259 * @return a empty array of issuer certificates.
260 */
261 public X509Certificate[] getAcceptedIssuers() {
262 return(_AcceptedIssuers);
263 } // getAcceptedIssuers
264 } // _FakeX509TrustManager
265
266
267 /**
268 * This class implements a fake hostname verificator, trusting any host
269 * name.
270 *
271 * @author Francis Labrie
272 */
273 public static class FakeHostnameVerifier implements HostnameVerifier {
274
275 /**
276 * Always return <code>true</code>, indicating that the host name is
277 * an acceptable match with the server's authentication scheme.
278 *
279 * @param hostname the host name.
280 * @param session the SSL session used on the connection to
281 * host.
282 * @return the <code>true</code> boolean value
283 * indicating the host name is trusted.
284 */
285 public boolean verify(String hostname,
286 javax.net.ssl.SSLSession session) {
287 return(true);
288 } // verify
289 } // FakeHostnameVerifier
290
291
292 /**
293 * This class allow any X509 certificates to be used to authenticate the
294 * remote side of a secure socket, including self-signed certificates.
295 *
296 * @author Francis Labrie
297 */
298 public static class FakeX509TrustManager implements X509TrustManager {
299
300 /**
301 * Empty array of certificate authority certificates.
302 */
303 private static final X509Certificate[] _AcceptedIssuers =
304 new X509Certificate[] {};
305
306
307 /**
308 * Always trust for client SSL <code>chain</code> peer certificate
309 * chain with any <code>authType</code> authentication types.
310 *
311 * @param chain the peer certificate chain.
312 * @param authType the authentication type based on the client
313 * certificate.
314 */
315 public void checkClientTrusted(X509Certificate[] chain,
316 String authType) {
317 } // checkClientTrusted
318
319 /**
320 * Always trust for server SSL <code>chain</code> peer certificate
321 * chain with any <code>authType</code> exchange algorithm types.
322 *
323 * @param chain the peer certificate chain.
324 * @param authType the key exchange algorithm used.
325 */
326 public void checkServerTrusted(X509Certificate[] chain,
327 String authType) {
328 } // checkServerTrusted
329
330 /**
331 * Return an empty array of certificate authority certificates which
332 * are trusted for authenticating peers.
333 *
334 * @return a empty array of issuer certificates.
335 */
336 public X509Certificate[] getAcceptedIssuers() {
337 return(_AcceptedIssuers);
338 } // getAcceptedIssuers
339 } // FakeX509TrustManager
340 } // SSLUtilities
341
342 {{/code}}
343
344 Category:WebObjects