1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.jboss.netty.handler.ssl;
18
19 import org.jboss.netty.logging.InternalLogger;
20 import org.jboss.netty.logging.InternalLoggerFactory;
21
22 import javax.net.ssl.SSLContext;
23 import javax.net.ssl.SSLEngine;
24 import javax.net.ssl.SSLSessionContext;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.Collections;
28 import java.util.List;
29
30
31
32
33 public abstract class JdkSslContext extends SslContext {
34
35 private static final InternalLogger logger = InternalLoggerFactory.getInstance(JdkSslContext.class);
36
37 static final String PROTOCOL = "TLS";
38 static final String[] PROTOCOLS;
39 static final List<String> DEFAULT_CIPHERS;
40
41 static {
42 SSLContext context;
43 try {
44 context = SSLContext.getInstance(PROTOCOL);
45 context.init(null, null, null);
46 } catch (Exception e) {
47 throw new Error("failed to initialize the default SSL context", e);
48 }
49
50 SSLEngine engine = context.createSSLEngine();
51
52
53 String[] supportedProtocols = engine.getSupportedProtocols();
54 List<String> protocols = new ArrayList<String>();
55 addIfSupported(
56 supportedProtocols, protocols,
57 "TLSv1.2", "TLSv1.1", "TLSv1", "SSLv3");
58
59 if (!protocols.isEmpty()) {
60 PROTOCOLS = protocols.toArray(new String[protocols.size()]);
61 } else {
62 PROTOCOLS = engine.getEnabledProtocols();
63 }
64
65
66 String[] supportedCiphers = engine.getSupportedCipherSuites();
67 List<String> ciphers = new ArrayList<String>();
68 addIfSupported(
69 supportedCiphers, ciphers,
70
71 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
72 "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
73 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
74 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
75 "TLS_RSA_WITH_AES_128_GCM_SHA256",
76 "SSL_RSA_WITH_RC4_128_SHA",
77 "SSL_RSA_WITH_RC4_128_MD5",
78 "TLS_RSA_WITH_AES_128_CBC_SHA",
79 "TLS_RSA_WITH_AES_256_CBC_SHA",
80 "SSL_RSA_WITH_DES_CBC_SHA");
81
82 if (!ciphers.isEmpty()) {
83 DEFAULT_CIPHERS = Collections.unmodifiableList(ciphers);
84 } else {
85
86 DEFAULT_CIPHERS = Collections.unmodifiableList(Arrays.asList(engine.getEnabledCipherSuites()));
87 }
88
89 if (logger.isDebugEnabled()) {
90 logger.debug("Default protocols (JDK): " + PROTOCOLS);
91 logger.debug("Default cipher suites (JDK): " + DEFAULT_CIPHERS);
92 }
93 }
94
95 private static void addIfSupported(String[] supported, List<String> enabled, String... names) {
96 for (String n: names) {
97 for (String s: supported) {
98 if (n.equals(s)) {
99 enabled.add(s);
100 break;
101 }
102 }
103 }
104 }
105
106 private final String[] cipherSuites;
107 private final List<String> unmodifiableCipherSuites;
108
109 JdkSslContext(SslBufferPool bufferPool, Iterable<String> ciphers) {
110 super(bufferPool);
111 cipherSuites = toCipherSuiteArray(ciphers);
112 unmodifiableCipherSuites = Collections.unmodifiableList(Arrays.asList(cipherSuites));
113 }
114
115
116
117
118 public abstract SSLContext context();
119
120
121
122
123 public final SSLSessionContext sessionContext() {
124 if (isServer()) {
125 return context().getServerSessionContext();
126 } else {
127 return context().getClientSessionContext();
128 }
129 }
130
131 @Override
132 public final List<String> cipherSuites() {
133 return unmodifiableCipherSuites;
134 }
135
136 @Override
137 public final long sessionCacheSize() {
138 return sessionContext().getSessionCacheSize();
139 }
140
141 @Override
142 public final long sessionTimeout() {
143 return sessionContext().getSessionTimeout();
144 }
145
146 @Override
147 public final SSLEngine newEngine() {
148 SSLEngine engine = context().createSSLEngine();
149 engine.setEnabledCipherSuites(cipherSuites);
150 engine.setEnabledProtocols(PROTOCOLS);
151 engine.setUseClientMode(isClient());
152 return wrapEngine(engine);
153 }
154
155 @Override
156 public final SSLEngine newEngine(String peerHost, int peerPort) {
157 SSLEngine engine = context().createSSLEngine(peerHost, peerPort);
158 engine.setEnabledCipherSuites(cipherSuites);
159 engine.setEnabledProtocols(PROTOCOLS);
160 engine.setUseClientMode(isClient());
161 return wrapEngine(engine);
162 }
163
164 private SSLEngine wrapEngine(SSLEngine engine) {
165 if (nextProtocols().isEmpty()) {
166 return engine;
167 } else {
168 return new JettyNpnSslEngine(engine, nextProtocols(), isServer());
169 }
170 }
171
172 private static String[] toCipherSuiteArray(Iterable<String> ciphers) {
173 if (ciphers == null) {
174 return DEFAULT_CIPHERS.toArray(new String[DEFAULT_CIPHERS.size()]);
175 } else {
176 List<String> newCiphers = new ArrayList<String>();
177 for (String c: ciphers) {
178 if (c == null) {
179 break;
180 }
181 newCiphers.add(c);
182 }
183 return newCiphers.toArray(new String[newCiphers.size()]);
184 }
185 }
186 }