1 /*
2 * Copyright 1999-2004 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.apache.tomcat.util.net.jsse;
18
19 import java.io.IOException;
20 import java.security.KeyStore;
21 import java.security.SecureRandom;
22 import java.util.Vector;
23
24 import javax.net.ssl.KeyManager;
25 import javax.net.ssl.KeyManagerFactory;
26 import javax.net.ssl.SSLContext;
27 import javax.net.ssl.SSLServerSocket;
28 import javax.net.ssl.SSLSocket;
29 import javax.net.ssl.TrustManager;
30 import javax.net.ssl.TrustManagerFactory;
31 import javax.net.ssl.X509KeyManager;
32
33 import org.apache.tomcat.util.res.StringManager;
34
35 /*
36 1. Make the JSSE's jars available, either as an installed
37 extension (copy them into jre/lib/ext) or by adding
38 them to the Tomcat classpath.
39 2. keytool -genkey -alias tomcat -keyalg RSA
40 Use "changeit" as password ( this is the default we use )
41 */
42
43 /**
44 * SSL server socket factory. It _requires_ a valid RSA key and
45 * JSSE.
46 *
47 * @author Harish Prabandham
48 * @author Costin Manolache
49 * @author Stefan Freyr Stefansson
50 * @author EKR -- renamed to JSSESocketFactory
51 * @author Jan Luehe
52 */
53 public class JSSE14SocketFactory extends JSSESocketFactory {
54
55 private static StringManager sm =
56 StringManager.getManager("org.apache.tomcat.util.net.jsse.res");
57
58 /**
59 * Flag to state that we require client authentication.
60 */
61 protected boolean requireClientAuth = false;
62
63 /**
64 * Flag to state that we would like client authentication.
65 */
66 protected boolean wantClientAuth = false;
67
68 public JSSE14SocketFactory () {
69 super();
70 }
71
72 /**
73 * Reads the keystore and initializes the SSL socket factory.
74 */
75 void init() throws IOException {
76 try {
77
78 String clientAuthStr = (String) attributes.get("clientauth");
79 if("true".equalsIgnoreCase(clientAuthStr) ||
80 "yes".equalsIgnoreCase(clientAuthStr)) {
81 requireClientAuth = true;
82 } else if("want".equalsIgnoreCase(clientAuthStr)) {
83 wantClientAuth = true;
84 }
85
86 // SSL protocol variant (e.g., TLS, SSL v3, etc.)
87 String protocol = (String) attributes.get("protocol");
88 if (protocol == null) {
89 protocol = defaultProtocol;
90 }
91
92 // Certificate encoding algorithm (e.g., SunX509)
93 String algorithm = (String) attributes.get("algorithm");
94 if (algorithm == null) {
95 algorithm = defaultAlgorithm;
96 }
97
98 String keystoreType = (String) attributes.get("keystoreType");
99 if (keystoreType == null) {
100 keystoreType = defaultKeystoreType;
101 }
102
103 String trustAlgorithm = (String)attributes.get("truststoreAlgorithm");
104 if( trustAlgorithm == null ) {
105 trustAlgorithm = algorithm;
106 }
107 // Create and init SSLContext
108 SSLContext context = SSLContext.getInstance(protocol);
109 context.init(getKeyManagers(keystoreType, algorithm,
110 (String) attributes.get("keyAlias")),
111 getTrustManagers(keystoreType, trustAlgorithm),
112 new SecureRandom());
113
114 // create proxy
115 sslProxy = context.getServerSocketFactory();
116
117 // Determine which cipher suites to enable
118 String requestedCiphers = (String)attributes.get("ciphers");
119 enabledCiphers = getEnabledCiphers(requestedCiphers,
120 sslProxy.getSupportedCipherSuites());
121
122 } catch(Exception e) {
123 if( e instanceof IOException )
124 throw (IOException)e;
125 throw new IOException(e.getMessage());
126 }
127 }
128
129 /**
130 * Gets the initialized key managers.
131 */
132 protected KeyManager[] getKeyManagers(String keystoreType,
133 String algorithm,
134 String keyAlias)
135 throws Exception {
136
137 KeyManager[] kms = null;
138
139 String keystorePass = getKeystorePassword();
140
141 KeyStore ks = getKeystore(keystoreType, keystorePass);
142 if (keyAlias != null && !ks.isKeyEntry(keyAlias)) {
143 throw new IOException(sm.getString("jsse.alias_no_key_entry", keyAlias));
144 }
145
146 KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
147 kmf.init(ks, keystorePass.toCharArray());
148
149 kms = kmf.getKeyManagers();
150 if (keyAlias != null) {
151 if (JSSESocketFactory.defaultKeystoreType.equals(keystoreType)) {
152 keyAlias = keyAlias.toLowerCase();
153 }
154 for(int i=0; i<kms.length; i++) {
155 kms[i] = new JSSEKeyManager((X509KeyManager)kms[i], keyAlias);
156 }
157 }
158
159 return kms;
160 }
161
162 /**
163 * Gets the intialized trust managers.
164 */
165 protected TrustManager[] getTrustManagers(String keystoreType, String algorithm)
166 throws Exception {
167
168 TrustManager[] tms = null;
169
170 String truststoreType = (String)attributes.get("truststoreType");
171 if(truststoreType == null) {
172 truststoreType = keystoreType;
173 }
174 KeyStore trustStore = getTrustStore(truststoreType);
175 if (trustStore != null) {
176 TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
177 tmf.init(trustStore);
178 tms = tmf.getTrustManagers();
179 }
180
181 return tms;
182 }
183 protected void setEnabledProtocols(SSLServerSocket socket, String []protocols){
184 if (protocols != null) {
185 socket.setEnabledProtocols(protocols);
186 }
187 }
188
189 protected String[] getEnabledProtocols(SSLServerSocket socket,
190 String requestedProtocols){
191 String[] supportedProtocols = socket.getSupportedProtocols();
192
193 String[] enabledProtocols = null;
194
195 if (requestedProtocols != null) {
196 Vector vec = null;
197 String protocol = requestedProtocols;
198 int index = requestedProtocols.indexOf(',');
199 if (index != -1) {
200 int fromIndex = 0;
201 while (index != -1) {
202 protocol = requestedProtocols.substring(fromIndex, index).trim();
203 if (protocol.length() > 0) {
204 /*
205 * Check to see if the requested protocol is among the
206 * supported protocols, i.e., may be enabled
207 */
208 for (int i=0; supportedProtocols != null
209 && i<supportedProtocols.length; i++) {
210 if (supportedProtocols[i].equals(protocol)) {
211 if (vec == null) {
212 vec = new Vector();
213 }
214 vec.addElement(protocol);
215 break;
216 }
217 }
218 }
219 fromIndex = index+1;
220 index = requestedProtocols.indexOf(',', fromIndex);
221 } // while
222 protocol = requestedProtocols.substring(fromIndex);
223 }
224
225 if (protocol != null) {
226 protocol = protocol.trim();
227 if (protocol.length() > 0) {
228 /*
229 * Check to see if the requested protocol is among the
230 * supported protocols, i.e., may be enabled
231 */
232 for (int i=0; supportedProtocols != null
233 && i<supportedProtocols.length; i++) {
234 if (supportedProtocols[i].equals(protocol)) {
235 if (vec == null) {
236 vec = new Vector();
237 }
238 vec.addElement(protocol);
239 break;
240 }
241 }
242 }
243 }
244
245 if (vec != null) {
246 enabledProtocols = new String[vec.size()];
247 vec.copyInto(enabledProtocols);
248 }
249 }
250
251 return enabledProtocols;
252 }
253
254 protected void configureClientAuth(SSLServerSocket socket){
255 if (wantClientAuth){
256 socket.setWantClientAuth(wantClientAuth);
257 } else {
258 socket.setNeedClientAuth(requireClientAuth);
259 }
260 }
261
262 protected void configureClientAuth(SSLSocket socket){
263 // Per JavaDocs: SSLSockets returned from
264 // SSLServerSocket.accept() inherit this setting.
265 }
266
267 }