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");
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
72 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
73 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
74
75 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
76
77 "TLS_RSA_WITH_AES_128_GCM_SHA256",
78 "TLS_RSA_WITH_AES_128_CBC_SHA",
79
80 "TLS_RSA_WITH_AES_256_CBC_SHA",
81 "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
82 "SSL_RSA_WITH_RC4_128_SHA");
83
84 if (!ciphers.isEmpty()) {
85 DEFAULT_CIPHERS = Collections.unmodifiableList(ciphers);
86 } else {
87
88 DEFAULT_CIPHERS = Collections.unmodifiableList(Arrays.asList(engine.getEnabledCipherSuites()));
89 }
90
91 if (logger.isDebugEnabled()) {
92 logger.debug("Default protocols (JDK): " + Arrays.asList(PROTOCOLS));
93 logger.debug("Default cipher suites (JDK): " + DEFAULT_CIPHERS);
94 }
95 }
96
97 private static void addIfSupported(String[] supported, List<String> enabled, String... names) {
98 for (String n: names) {
99 for (String s: supported) {
100 if (n.equals(s)) {
101 enabled.add(s);
102 break;
103 }
104 }
105 }
106 }
107
108 private final String[] cipherSuites;
109 private final List<String> unmodifiableCipherSuites;
110
111 JdkSslContext(SslBufferPool bufferPool, Iterable<String> ciphers) {
112 super(bufferPool);
113 cipherSuites = toCipherSuiteArray(ciphers);
114 unmodifiableCipherSuites = Collections.unmodifiableList(Arrays.asList(cipherSuites));
115 }
116
117
118
119
120 public abstract SSLContext context();
121
122
123
124
125 public final SSLSessionContext sessionContext() {
126 if (isServer()) {
127 return context().getServerSessionContext();
128 } else {
129 return context().getClientSessionContext();
130 }
131 }
132
133 @Override
134 public final List<String> cipherSuites() {
135 return unmodifiableCipherSuites;
136 }
137
138 @Override
139 public final long sessionCacheSize() {
140 return sessionContext().getSessionCacheSize();
141 }
142
143 @Override
144 public final long sessionTimeout() {
145 return sessionContext().getSessionTimeout();
146 }
147
148 @Override
149 public final SSLEngine newEngine() {
150 SSLEngine engine = context().createSSLEngine();
151 engine.setEnabledCipherSuites(cipherSuites);
152 engine.setEnabledProtocols(PROTOCOLS);
153 engine.setUseClientMode(isClient());
154 return wrapEngine(engine);
155 }
156
157 @Override
158 public final SSLEngine newEngine(String peerHost, int peerPort) {
159 SSLEngine engine = context().createSSLEngine(peerHost, peerPort);
160 engine.setEnabledCipherSuites(cipherSuites);
161 engine.setEnabledProtocols(PROTOCOLS);
162 engine.setUseClientMode(isClient());
163 return wrapEngine(engine);
164 }
165
166 private SSLEngine wrapEngine(SSLEngine engine) {
167 if (nextProtocols().isEmpty()) {
168 return engine;
169 } else {
170 return new JettyNpnSslEngine(engine, nextProtocols(), isServer());
171 }
172 }
173
174 private static String[] toCipherSuiteArray(Iterable<String> ciphers) {
175 if (ciphers == null) {
176 return DEFAULT_CIPHERS.toArray(new String[DEFAULT_CIPHERS.size()]);
177 } else {
178 List<String> newCiphers = new ArrayList<String>();
179 for (String c: ciphers) {
180 if (c == null) {
181 break;
182 }
183 newCiphers.add(c);
184 }
185 return newCiphers.toArray(new String[newCiphers.size()]);
186 }
187 }
188 }