001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.vfs;
030:
031: import com.caucho.config.ConfigException;
032: import com.caucho.util.L10N;
033:
034: import javax.annotation.PostConstruct;
035: import javax.crypto.*;
036: import javax.net.ssl.KeyManagerFactory;
037: import javax.net.ssl.SSLContext;
038: import javax.net.ssl.SSLServerSocket;
039: import javax.net.ssl.SSLServerSocketFactory;
040: import java.io.IOException;
041: import java.io.InputStream;
042: import java.net.InetAddress;
043: import java.net.ServerSocket;
044: import java.util.logging.*;
045: import java.security.*;
046: import java.security.cert.Certificate;
047:
048: import java.net.*;
049:
050: /**
051: * Abstract socket to handle both normal sockets and bin/resin sockets.
052: */
053: public class JsseSSLFactory implements SSLFactory {
054: private static final Logger log = Logger
055: .getLogger(JsseSSLFactory.class.getName());
056:
057: private static final L10N L = new L10N(JsseSSLFactory.class);
058:
059: private Path _keyStoreFile;
060: private String _alias;
061: private String _password;
062: private String _verifyClient;
063: private String _keyStoreType = "jks";
064: private String _keyManagerFactory = "SunX509";
065: private String _sslContext = "TLS";
066:
067: private KeyStore _keyStore;
068:
069: /**
070: * Creates a ServerSocket factory without initializing it.
071: */
072: public JsseSSLFactory() {
073: }
074:
075: /**
076: * Sets the key store
077: */
078: public void setKeyStoreFile(Path keyStoreFile) {
079: _keyStoreFile = keyStoreFile;
080: }
081:
082: /**
083: * Returns the certificate file.
084: */
085: public Path getKeyStoreFile() {
086: return _keyStoreFile;
087: }
088:
089: /**
090: * Sets the password.
091: */
092: public void setPassword(String password) {
093: _password = password;
094: }
095:
096: /**
097: * Returns the key file.
098: */
099: public String getPassword() {
100: return _password;
101: }
102:
103: /**
104: * Sets the certificate alias
105: */
106: public void setAlias(String alias) {
107: _alias = alias;
108: }
109:
110: /**
111: * Returns the alias.
112: */
113: public String getAlias() {
114: return _alias;
115: }
116:
117: /**
118: * Sets the verifyClient.
119: */
120: public void setVerifyClient(String verifyClient) {
121: _verifyClient = verifyClient;
122: }
123:
124: /**
125: * Returns the key file.
126: */
127: public String getVerifyClient() {
128: return _verifyClient;
129: }
130:
131: /**
132: * Sets the key-manager-factory
133: */
134: public void setKeyManagerFactory(String keyManagerFactory) {
135: _keyManagerFactory = keyManagerFactory;
136: }
137:
138: /**
139: * Sets the ssl-context
140: */
141: public void setSSLContext(String sslContext) {
142: _sslContext = sslContext;
143: }
144:
145: /**
146: * Sets the key-store
147: */
148: public void setKeyStoreType(String keyStore) {
149: _keyStoreType = keyStore;
150: }
151:
152: /**
153: * Initialize
154: */
155: @PostConstruct
156: public void init() throws ConfigException, IOException,
157: GeneralSecurityException {
158: if (_keyStoreFile != null && _password == null)
159: throw new ConfigException(L
160: .l("'password' is required for JSSE."));
161: if (_password != null && _keyStoreFile == null)
162: throw new ConfigException(L
163: .l("'key-store-file' is required for JSSE."));
164:
165: if (_alias != null && _keyStoreFile == null)
166: throw new ConfigException(L
167: .l("'alias' requires a key store for JSSE."));
168:
169: if (_keyStoreFile == null)
170: return;
171:
172: _keyStore = KeyStore.getInstance(_keyStoreType);
173:
174: InputStream is = _keyStoreFile.openRead();
175: try {
176: _keyStore.load(is, _password.toCharArray());
177: } finally {
178: is.close();
179: }
180:
181: if (_alias != null) {
182: Key key = _keyStore.getKey(_alias, _password.toCharArray());
183:
184: if (key == null)
185: throw new ConfigException(
186: L
187: .l(
188: "JSSE alias '{0}' does not have a corresponding key.",
189: _alias));
190:
191: Certificate[] certChain = _keyStore
192: .getCertificateChain(_alias);
193:
194: if (certChain == null)
195: throw new ConfigException(
196: L
197: .l(
198: "JSSE alias '{0}' does not have a corresponding certificate chain.",
199: _alias));
200:
201: _keyStore = KeyStore.getInstance(_keyStoreType);
202: _keyStore.load(null, _password.toCharArray());
203:
204: _keyStore.setKeyEntry(_alias, key, _password.toCharArray(),
205: certChain);
206: }
207: }
208:
209: /**
210: * Creates the SSL ServerSocket.
211: */
212: public QServerSocket create(InetAddress host, int port)
213: throws IOException, GeneralSecurityException {
214: SSLServerSocketFactory factory = null;
215:
216: SSLContext sslContext = SSLContext.getInstance(_sslContext);
217:
218: if (_keyStore != null) {
219: KeyManagerFactory kmf = KeyManagerFactory
220: .getInstance(_keyManagerFactory);
221:
222: kmf.init(_keyStore, _password.toCharArray());
223:
224: sslContext.init(kmf.getKeyManagers(), null, null);
225:
226: factory = sslContext.getServerSocketFactory();
227: } else {
228: factory = createAnonymousFactory();
229:
230: ServerSocket ss;
231: ss = factory.createServerSocket(8666, 100);
232:
233: Socket s = ss.accept();
234: System.out.println(s);
235: }
236:
237: ServerSocket serverSocket;
238:
239: int listen = 100;
240:
241: if (host == null)
242: serverSocket = factory.createServerSocket(port, listen);
243: else
244: serverSocket = factory.createServerSocket(port, listen,
245: host);
246:
247: SSLServerSocket sslServerSocket = (SSLServerSocket) serverSocket;
248:
249: if ("required".equals(_verifyClient))
250: sslServerSocket.setNeedClientAuth(true);
251:
252: /*
253: boolean hasRestriction = false;
254: ArrayList<String> protocols = new ArrayList();
255: if (node.getBoolean("tls1", true)) {
256: protocols.add("TLSv1");
257: protocols.add("TLS");
258: }
259: else
260: hasRestriction = true;
261:
262: if (node.getBoolean("ssl2", true)) {
263: protocols.add("SSLv2");
264: }
265: else
266: hasRestriction = true;
267:
268: if (node.getBoolean("ssl3", true)) {
269: protocols.add("SSLv3");
270: }
271: else
272: hasRestriction = true;
273:
274: if (hasRestriction)
275: sslServerSocket.setEnabledProtocols((String []) protocols.toArray(new String[protocols.size()]));
276: */
277:
278: return new QServerSocketWrapper(serverSocket);
279: }
280:
281: private SSLServerSocketFactory createAnonymousFactory()
282: throws IOException, GeneralSecurityException {
283: throw new ConfigException(L
284: .l("jsse-ssl requires a 'key-store-file'"));
285:
286: /*
287: KeyManagerFactory kmf
288: = KeyManagerFactory.getInstance(_keyManagerFactory);
289:
290: KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
291:
292: ks.load(null, "password".toCharArray());
293:
294: KeyPairGenerator gen = null;
295:
296: try {
297: gen = KeyPairGenerator.getInstance("DSA");
298: } catch (Exception e) {
299: log.log(Level.FINEST, e.toString(), e);
300: }
301:
302: try {
303: if (gen == null)
304: gen = KeyPairGenerator.getInstance("DiffieHellman");
305: } catch (Exception e) {
306: log.log(Level.FINEST, e.toString(), e);
307: }
308:
309: if (gen == null)
310: throw new ConfigException(L.l("Cannot generate anonymous certificate"));
311:
312: KeyPair pair = gen.generateKeyPair();
313:
314: PrivateKey privateKey = pair.getPrivate();
315: PublicKey publicKey = pair.getPublic();
316:
317: ks.setKeyEntry("anonymous", privateKey,
318: "key-password".toCharArray(), null);
319:
320: kmf.init(ks, "key-password".toCharArray());
321:
322: // sslContext.init(kmf.getKeyManagers(), null, null);
323:
324: SSLServerSocketFactory factory;
325:
326: factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
327:
328: return factory;
329: */
330: }
331:
332: /**
333: * Creates the SSL ServerSocket.
334: */
335: public QServerSocket bind(QServerSocket ss) throws ConfigException,
336: IOException, GeneralSecurityException {
337: throw new ConfigException(L.l("jsse is not allowed here"));
338: }
339: }
|