1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.ssl;
17
18 import io.netty.internal.tcnative.SSL;
19 import io.netty.internal.tcnative.SSLContext;
20 import io.netty.internal.tcnative.SniHostNameMatcher;
21 import io.netty.util.internal.PlatformDependent;
22 import io.netty.util.internal.logging.InternalLogger;
23 import io.netty.util.internal.logging.InternalLoggerFactory;
24
25 import java.security.KeyStore;
26 import java.security.PrivateKey;
27 import java.security.cert.X509Certificate;
28 import javax.net.ssl.KeyManagerFactory;
29 import javax.net.ssl.SSLException;
30 import javax.net.ssl.TrustManagerFactory;
31 import javax.net.ssl.X509ExtendedKeyManager;
32 import javax.net.ssl.X509ExtendedTrustManager;
33 import javax.net.ssl.X509KeyManager;
34 import javax.net.ssl.X509TrustManager;
35
36 import static io.netty.util.internal.ObjectUtil.checkNotNull;
37
38
39
40
41
42
43
44
45
46 public final class ReferenceCountedOpenSslServerContext extends ReferenceCountedOpenSslContext {
47 private static final InternalLogger logger =
48 InternalLoggerFactory.getInstance(ReferenceCountedOpenSslServerContext.class);
49 private static final byte[] ID = {'n', 'e', 't', 't', 'y'};
50 private final OpenSslServerSessionContext sessionContext;
51 private final OpenSslKeyMaterialManager keyMaterialManager;
52
53 ReferenceCountedOpenSslServerContext(
54 X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
55 X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
56 Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
57 long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls,
58 boolean enableOcsp) throws SSLException {
59 this(trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory, ciphers,
60 cipherFilter, toNegotiator(apn), sessionCacheSize, sessionTimeout, clientAuth, protocols, startTls,
61 enableOcsp);
62 }
63
64 private ReferenceCountedOpenSslServerContext(
65 X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
66 X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
67 Iterable<String> ciphers, CipherSuiteFilter cipherFilter, OpenSslApplicationProtocolNegotiator apn,
68 long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls,
69 boolean enableOcsp) throws SSLException {
70 super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_SERVER, keyCertChain,
71 clientAuth, protocols, startTls, enableOcsp, true);
72
73 boolean success = false;
74 try {
75 ServerContext context = newSessionContext(this, ctx, engineMap, trustCertCollection, trustManagerFactory,
76 keyCertChain, key, keyPassword, keyManagerFactory);
77 sessionContext = context.sessionContext;
78 keyMaterialManager = context.keyMaterialManager;
79 success = true;
80 } finally {
81 if (!success) {
82 release();
83 }
84 }
85 }
86
87 @Override
88 public OpenSslServerSessionContext sessionContext() {
89 return sessionContext;
90 }
91
92 @Override
93 OpenSslKeyMaterialManager keyMaterialManager() {
94 return keyMaterialManager;
95 }
96
97 static final class ServerContext {
98 OpenSslServerSessionContext sessionContext;
99 OpenSslKeyMaterialManager keyMaterialManager;
100 }
101
102 static ServerContext newSessionContext(ReferenceCountedOpenSslContext thiz, long ctx, OpenSslEngineMap engineMap,
103 X509Certificate[] trustCertCollection,
104 TrustManagerFactory trustManagerFactory,
105 X509Certificate[] keyCertChain, PrivateKey key,
106 String keyPassword, KeyManagerFactory keyManagerFactory)
107 throws SSLException {
108 ServerContext result = new ServerContext();
109 try {
110 SSLContext.setVerify(ctx, SSL.SSL_CVERIFY_NONE, VERIFY_DEPTH);
111 if (!OpenSsl.useKeyManagerFactory()) {
112 if (keyManagerFactory != null) {
113 throw new IllegalArgumentException(
114 "KeyManagerFactory not supported");
115 }
116 checkNotNull(keyCertChain, "keyCertChain");
117
118 setKeyMaterial(ctx, keyCertChain, key, keyPassword);
119 } else {
120
121
122 if (keyManagerFactory == null) {
123 keyManagerFactory = buildKeyManagerFactory(
124 keyCertChain, key, keyPassword, keyManagerFactory);
125 }
126 X509KeyManager keyManager = chooseX509KeyManager(keyManagerFactory.getKeyManagers());
127 result.keyMaterialManager = useExtendedKeyManager(keyManager) ?
128 new OpenSslExtendedKeyMaterialManager(
129 (X509ExtendedKeyManager) keyManager, keyPassword) :
130 new OpenSslKeyMaterialManager(keyManager, keyPassword);
131 }
132 } catch (Exception e) {
133 throw new SSLException("failed to set certificate and key", e);
134 }
135 try {
136 if (trustCertCollection != null) {
137 trustManagerFactory = buildTrustManagerFactory(trustCertCollection, trustManagerFactory);
138 } else if (trustManagerFactory == null) {
139
140 trustManagerFactory = TrustManagerFactory.getInstance(
141 TrustManagerFactory.getDefaultAlgorithm());
142 trustManagerFactory.init((KeyStore) null);
143 }
144
145 final X509TrustManager manager = chooseTrustManager(trustManagerFactory.getTrustManagers());
146
147
148
149
150
151
152
153
154 if (useExtendedTrustManager(manager)) {
155 SSLContext.setCertVerifyCallback(ctx,
156 new ExtendedTrustManagerVerifyCallback(engineMap, (X509ExtendedTrustManager) manager));
157 } else {
158 SSLContext.setCertVerifyCallback(ctx, new TrustManagerVerifyCallback(engineMap, manager));
159 }
160
161 X509Certificate[] issuers = manager.getAcceptedIssuers();
162 if (issuers != null && issuers.length > 0) {
163 long bio = 0;
164 try {
165 bio = toBIO(issuers);
166 if (!SSLContext.setCACertificateBio(ctx, bio)) {
167 throw new SSLException("unable to setup accepted issuers for trustmanager " + manager);
168 }
169 } finally {
170 freeBio(bio);
171 }
172 }
173
174 if (PlatformDependent.javaVersion() >= 8) {
175
176
177
178
179 SSLContext.setSniHostnameMatcher(ctx, new OpenSslSniHostnameMatcher(engineMap));
180 }
181 } catch (SSLException e) {
182 throw e;
183 } catch (Exception e) {
184 throw new SSLException("unable to setup trustmanager", e);
185 }
186
187 result.sessionContext = new OpenSslServerSessionContext(thiz);
188 result.sessionContext.setSessionIdContext(ID);
189 return result;
190 }
191
192 private static final class TrustManagerVerifyCallback extends AbstractCertificateVerifier {
193 private final X509TrustManager manager;
194
195 TrustManagerVerifyCallback(OpenSslEngineMap engineMap, X509TrustManager manager) {
196 super(engineMap);
197 this.manager = manager;
198 }
199
200 @Override
201 void verify(ReferenceCountedOpenSslEngine engine, X509Certificate[] peerCerts, String auth)
202 throws Exception {
203 manager.checkClientTrusted(peerCerts, auth);
204 }
205 }
206
207 private static final class ExtendedTrustManagerVerifyCallback extends AbstractCertificateVerifier {
208 private final X509ExtendedTrustManager manager;
209
210 ExtendedTrustManagerVerifyCallback(OpenSslEngineMap engineMap, X509ExtendedTrustManager manager) {
211 super(engineMap);
212 this.manager = manager;
213 }
214
215 @Override
216 void verify(ReferenceCountedOpenSslEngine engine, X509Certificate[] peerCerts, String auth)
217 throws Exception {
218 manager.checkClientTrusted(peerCerts, auth, engine);
219 }
220 }
221
222 private static final class OpenSslSniHostnameMatcher implements SniHostNameMatcher {
223 private final OpenSslEngineMap engineMap;
224
225 OpenSslSniHostnameMatcher(OpenSslEngineMap engineMap) {
226 this.engineMap = engineMap;
227 }
228
229 @Override
230 public boolean match(long ssl, String hostname) {
231 ReferenceCountedOpenSslEngine engine = engineMap.get(ssl);
232 if (engine != null) {
233 return engine.checkSniHostnameMatch(hostname);
234 }
235 logger.warn("No ReferenceCountedOpenSslEngine found for SSL pointer: {}", ssl);
236 return false;
237 }
238 }
239 }