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