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.buffer.ChannelBuffer;
20 import org.jboss.netty.buffer.ChannelBufferInputStream;
21
22 import javax.net.ssl.SSLContext;
23 import javax.net.ssl.SSLException;
24 import javax.net.ssl.SSLSessionContext;
25 import javax.net.ssl.TrustManagerFactory;
26 import javax.security.auth.x500.X500Principal;
27 import java.io.File;
28 import java.security.KeyStore;
29 import java.security.cert.CertificateFactory;
30 import java.security.cert.X509Certificate;
31 import java.util.ArrayList;
32 import java.util.Collections;
33 import java.util.List;
34
35
36
37
38 public final class JdkSslClientContext extends JdkSslContext {
39
40 private final SSLContext ctx;
41 private final List<String> nextProtocols;
42
43
44
45
46 public JdkSslClientContext() throws SSLException {
47 this(null, null, null, null, null, 0, 0);
48 }
49
50
51
52
53
54
55
56 public JdkSslClientContext(File certChainFile) throws SSLException {
57 this(certChainFile, null);
58 }
59
60
61
62
63
64
65
66
67 public JdkSslClientContext(TrustManagerFactory trustManagerFactory) throws SSLException {
68 this(null, trustManagerFactory);
69 }
70
71
72
73
74
75
76
77
78
79
80 public JdkSslClientContext(File certChainFile, TrustManagerFactory trustManagerFactory) throws SSLException {
81 this(null, certChainFile, trustManagerFactory, null, null, 0, 0);
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103 public JdkSslClientContext(
104 SslBufferPool bufPool, File certChainFile, TrustManagerFactory trustManagerFactory,
105 Iterable<String> ciphers, Iterable<String> nextProtocols,
106 long sessionCacheSize, long sessionTimeout) throws SSLException {
107
108 super(bufPool, ciphers);
109
110 if (nextProtocols != null && nextProtocols.iterator().hasNext()) {
111 if (!JettyNpnSslEngine.isAvailable()) {
112 throw new SSLException("NPN/ALPN unsupported: " + nextProtocols);
113 }
114
115 List<String> nextProtoList = new ArrayList<String>();
116 for (String p: nextProtocols) {
117 if (p == null) {
118 break;
119 }
120 nextProtoList.add(p);
121 }
122 this.nextProtocols = Collections.unmodifiableList(nextProtoList);
123 } else {
124 this.nextProtocols = Collections.emptyList();
125 }
126
127 try {
128 if (certChainFile == null) {
129 ctx = SSLContext.getInstance(PROTOCOL);
130 if (trustManagerFactory == null) {
131 ctx.init(null, null, null);
132 } else {
133 trustManagerFactory.init((KeyStore) null);
134 ctx.init(null, trustManagerFactory.getTrustManagers(), null);
135 }
136 } else {
137 KeyStore ks = KeyStore.getInstance("JKS");
138 ks.load(null, null);
139 CertificateFactory cf = CertificateFactory.getInstance("X.509");
140
141 for (ChannelBuffer buf: PemReader.readCertificates(certChainFile)) {
142 X509Certificate cert = (X509Certificate) cf.generateCertificate(new ChannelBufferInputStream(buf));
143 X500Principal principal = cert.getSubjectX500Principal();
144 ks.setCertificateEntry(principal.getName("RFC2253"), cert);
145 }
146
147
148 if (trustManagerFactory == null) {
149 trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
150 }
151 trustManagerFactory.init(ks);
152
153
154 ctx = SSLContext.getInstance(PROTOCOL);
155 ctx.init(null, trustManagerFactory.getTrustManagers(), null);
156 }
157
158 SSLSessionContext sessCtx = ctx.getClientSessionContext();
159 if (sessionCacheSize > 0) {
160 sessCtx.setSessionCacheSize((int) Math.min(sessionCacheSize, Integer.MAX_VALUE));
161 }
162 if (sessionTimeout > 0) {
163 sessCtx.setSessionTimeout((int) Math.min(sessionTimeout, Integer.MAX_VALUE));
164 }
165 } catch (Exception e) {
166 throw new SSLException("failed to initialize the server-side SSL context", e);
167 }
168 }
169
170 @Override
171 public boolean isClient() {
172 return true;
173 }
174
175 @Override
176 public List<String> nextProtocols() {
177 return nextProtocols;
178 }
179
180 @Override
181 public SSLContext context() {
182 return ctx;
183 }
184 }