001: /*
002: * Copyright 1999-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.tomcat.util.net.jsse;
018:
019: import java.io.IOException;
020: import java.security.KeyStore;
021: import java.security.SecureRandom;
022: import java.util.Vector;
023:
024: import javax.net.ssl.KeyManager;
025: import javax.net.ssl.KeyManagerFactory;
026: import javax.net.ssl.SSLContext;
027: import javax.net.ssl.SSLServerSocket;
028: import javax.net.ssl.SSLSocket;
029: import javax.net.ssl.TrustManager;
030: import javax.net.ssl.TrustManagerFactory;
031: import javax.net.ssl.X509KeyManager;
032:
033: import org.apache.tomcat.util.res.StringManager;
034:
035: /*
036: 1. Make the JSSE's jars available, either as an installed
037: extension (copy them into jre/lib/ext) or by adding
038: them to the Tomcat classpath.
039: 2. keytool -genkey -alias tomcat -keyalg RSA
040: Use "changeit" as password ( this is the default we use )
041: */
042:
043: /**
044: * SSL server socket factory. It _requires_ a valid RSA key and
045: * JSSE.
046: *
047: * @author Harish Prabandham
048: * @author Costin Manolache
049: * @author Stefan Freyr Stefansson
050: * @author EKR -- renamed to JSSESocketFactory
051: * @author Jan Luehe
052: */
053: public class JSSE14SocketFactory extends JSSESocketFactory {
054:
055: private static StringManager sm = StringManager
056: .getManager("org.apache.tomcat.util.net.jsse.res");
057:
058: /**
059: * Flag to state that we require client authentication.
060: */
061: protected boolean requireClientAuth = false;
062:
063: /**
064: * Flag to state that we would like client authentication.
065: */
066: protected boolean wantClientAuth = false;
067:
068: public JSSE14SocketFactory() {
069: super ();
070: }
071:
072: /**
073: * Reads the keystore and initializes the SSL socket factory.
074: */
075: void init() throws IOException {
076: try {
077:
078: String clientAuthStr = (String) attributes
079: .get("clientauth");
080: if ("true".equalsIgnoreCase(clientAuthStr)
081: || "yes".equalsIgnoreCase(clientAuthStr)) {
082: requireClientAuth = true;
083: } else if ("want".equalsIgnoreCase(clientAuthStr)) {
084: wantClientAuth = true;
085: }
086:
087: // SSL protocol variant (e.g., TLS, SSL v3, etc.)
088: String protocol = (String) attributes.get("protocol");
089: if (protocol == null) {
090: protocol = defaultProtocol;
091: }
092:
093: // Certificate encoding algorithm (e.g., SunX509)
094: String algorithm = (String) attributes.get("algorithm");
095: if (algorithm == null) {
096: algorithm = defaultAlgorithm;
097: }
098:
099: String keystoreType = (String) attributes
100: .get("keystoreType");
101: if (keystoreType == null) {
102: keystoreType = defaultKeystoreType;
103: }
104:
105: String trustAlgorithm = (String) attributes
106: .get("truststoreAlgorithm");
107: if (trustAlgorithm == null) {
108: trustAlgorithm = algorithm;
109: }
110: // Create and init SSLContext
111: SSLContext context = SSLContext.getInstance(protocol);
112: context.init(getKeyManagers(keystoreType, algorithm,
113: (String) attributes.get("keyAlias")),
114: getTrustManagers(keystoreType, trustAlgorithm),
115: new SecureRandom());
116:
117: // create proxy
118: sslProxy = context.getServerSocketFactory();
119:
120: // Determine which cipher suites to enable
121: String requestedCiphers = (String) attributes
122: .get("ciphers");
123: if (requestedCiphers != null) {
124: enabledCiphers = getEnabledCiphers(requestedCiphers,
125: sslProxy.getSupportedCipherSuites());
126: }
127:
128: } catch (Exception e) {
129: if (e instanceof IOException)
130: throw (IOException) e;
131: throw new IOException(e.getMessage());
132: }
133: }
134:
135: /**
136: * Gets the initialized key managers.
137: */
138: protected KeyManager[] getKeyManagers(String keystoreType,
139: String algorithm, String keyAlias) throws Exception {
140:
141: KeyManager[] kms = null;
142:
143: String keystorePass = getKeystorePassword();
144:
145: KeyStore ks = getKeystore(keystoreType, keystorePass);
146: if (keyAlias != null && !ks.isKeyEntry(keyAlias)) {
147: throw new IOException(sm.getString(
148: "jsse.alias_no_key_entry", keyAlias));
149: }
150:
151: KeyManagerFactory kmf = KeyManagerFactory
152: .getInstance(algorithm);
153: kmf.init(ks, keystorePass.toCharArray());
154:
155: kms = kmf.getKeyManagers();
156: if (keyAlias != null) {
157: if (JSSESocketFactory.defaultKeystoreType
158: .equals(keystoreType)) {
159: keyAlias = keyAlias.toLowerCase();
160: }
161: for (int i = 0; i < kms.length; i++) {
162: kms[i] = new JSSEKeyManager((X509KeyManager) kms[i],
163: keyAlias);
164: }
165: }
166:
167: return kms;
168: }
169:
170: /**
171: * Gets the intialized trust managers.
172: */
173: protected TrustManager[] getTrustManagers(String keystoreType,
174: String algorithm) throws Exception {
175:
176: TrustManager[] tms = null;
177:
178: String truststoreType = (String) attributes
179: .get("truststoreType");
180: if (truststoreType == null) {
181: truststoreType = keystoreType;
182: }
183: KeyStore trustStore = getTrustStore(truststoreType);
184: if (trustStore != null) {
185: TrustManagerFactory tmf = TrustManagerFactory
186: .getInstance(algorithm);
187: tmf.init(trustStore);
188: tms = tmf.getTrustManagers();
189: }
190:
191: return tms;
192: }
193:
194: protected void setEnabledProtocols(SSLServerSocket socket,
195: String[] protocols) {
196: if (protocols != null) {
197: socket.setEnabledProtocols(protocols);
198: }
199: }
200:
201: protected String[] getEnabledProtocols(SSLServerSocket socket,
202: String requestedProtocols) {
203: String[] supportedProtocols = socket.getSupportedProtocols();
204:
205: String[] enabledProtocols = null;
206:
207: if (requestedProtocols != null) {
208: Vector vec = null;
209: String protocol = requestedProtocols;
210: int index = requestedProtocols.indexOf(',');
211: if (index != -1) {
212: int fromIndex = 0;
213: while (index != -1) {
214: protocol = requestedProtocols.substring(fromIndex,
215: index).trim();
216: if (protocol.length() > 0) {
217: /*
218: * Check to see if the requested protocol is among the
219: * supported protocols, i.e., may be enabled
220: */
221: for (int i = 0; supportedProtocols != null
222: && i < supportedProtocols.length; i++) {
223: if (supportedProtocols[i].equals(protocol)) {
224: if (vec == null) {
225: vec = new Vector();
226: }
227: vec.addElement(protocol);
228: break;
229: }
230: }
231: }
232: fromIndex = index + 1;
233: index = requestedProtocols.indexOf(',', fromIndex);
234: } // while
235: protocol = requestedProtocols.substring(fromIndex);
236: }
237:
238: if (protocol != null) {
239: protocol = protocol.trim();
240: if (protocol.length() > 0) {
241: /*
242: * Check to see if the requested protocol is among the
243: * supported protocols, i.e., may be enabled
244: */
245: for (int i = 0; supportedProtocols != null
246: && i < supportedProtocols.length; i++) {
247: if (supportedProtocols[i].equals(protocol)) {
248: if (vec == null) {
249: vec = new Vector();
250: }
251: vec.addElement(protocol);
252: break;
253: }
254: }
255: }
256: }
257:
258: if (vec != null) {
259: enabledProtocols = new String[vec.size()];
260: vec.copyInto(enabledProtocols);
261: }
262: }
263:
264: return enabledProtocols;
265: }
266:
267: protected void configureClientAuth(SSLServerSocket socket) {
268: if (wantClientAuth) {
269: socket.setWantClientAuth(wantClientAuth);
270: } else {
271: socket.setNeedClientAuth(requireClientAuth);
272: }
273: }
274:
275: protected void configureClientAuth(SSLSocket socket) {
276: // Per JavaDocs: SSLSockets returned from
277: // SSLServerSocket.accept() inherit this setting.
278: }
279:
280: }
|