1 /*
2 * Copyright 2012 The Netty Project
3 *
4 * The Netty Project licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at:
7 *
8 * http://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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16 package org.jboss.netty.example.securechat;
17
18 import org.jboss.netty.handler.ssl.SslHandler;
19
20 import javax.net.ssl.KeyManager;
21 import javax.net.ssl.KeyManagerFactory;
22 import javax.net.ssl.SSLContext;
23 import javax.net.ssl.SSLEngine;
24 import javax.net.ssl.TrustManager;
25 import java.security.KeyStore;
26 import java.security.SecureRandom;
27 import java.security.Security;
28
29 /**
30 * Creates a bogus {@link SSLContext}. A client-side context created by this
31 * factory accepts any certificate even if it is invalid. A server-side context
32 * created by this factory sends a bogus certificate defined in {@link SecureChatKeyStore}.
33 * <p>
34 * You will have to create your context differently in a real world application.
35 *
36 * <h3>Client Certificate Authentication</h3>
37 *
38 * To enable client certificate authentication:
39 * <ul>
40 * <li>Enable client authentication on the server side by calling
41 * {@link SSLEngine#setNeedClientAuth(boolean)} before creating
42 * {@link SslHandler}.</li>
43 * <li>When initializing an {@link SSLContext} on the client side,
44 * specify the {@link KeyManager} that contains the client certificate as
45 * the first argument of {@link SSLContext#init(KeyManager[], TrustManager[], SecureRandom)}.</li>
46 * <li>When initializing an {@link SSLContext} on the server side,
47 * specify the proper {@link TrustManager} as the second argument of
48 * {@link SSLContext#init(KeyManager[], TrustManager[], SecureRandom)}
49 * to validate the client certificate.</li>
50 * </ul>
51 */
52 public final class SecureChatSslContextFactory {
53
54 private static final String PROTOCOL = "TLS";
55 private static final SSLContext SERVER_CONTEXT;
56 private static final SSLContext CLIENT_CONTEXT;
57
58 static {
59 String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
60 if (algorithm == null) {
61 algorithm = "SunX509";
62 }
63
64 SSLContext serverContext;
65 SSLContext clientContext;
66 try {
67 KeyStore ks = KeyStore.getInstance("JKS");
68 ks.load(SecureChatKeyStore.asInputStream(),
69 SecureChatKeyStore.getKeyStorePassword());
70
71 // Set up key manager factory to use our key store
72 KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
73 kmf.init(ks, SecureChatKeyStore.getCertificatePassword());
74
75 // Initialize the SSLContext to work with our key managers.
76 serverContext = SSLContext.getInstance(PROTOCOL);
77 serverContext.init(kmf.getKeyManagers(), null, null);
78 } catch (Exception e) {
79 throw new Error(
80 "Failed to initialize the server-side SSLContext", e);
81 }
82
83 try {
84 clientContext = SSLContext.getInstance(PROTOCOL);
85 clientContext.init(null, SecureChatTrustManagerFactory.getTrustManagers(), null);
86 } catch (Exception e) {
87 throw new Error(
88 "Failed to initialize the client-side SSLContext", e);
89 }
90
91 SERVER_CONTEXT = serverContext;
92 CLIENT_CONTEXT = clientContext;
93 }
94
95 public static SSLContext getServerContext() {
96 return SERVER_CONTEXT;
97 }
98
99 public static SSLContext getClientContext() {
100 return CLIENT_CONTEXT;
101 }
102
103 private SecureChatSslContextFactory() {
104 // Unused
105 }
106 }