KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > winstone > ssl > HttpsListener


1 /*
2  * Copyright 2003-2006 Rick Knowles <winstone-devel at lists sourceforge net>
3  * Distributed under the terms of either:
4  * - the common development and distribution license (CDDL), v1.0; or
5  * - the GNU Lesser General Public License, v2.1 or later
6  */

7 package winstone.ssl;
8
9 import java.io.File JavaDoc;
10 import java.io.FileInputStream JavaDoc;
11 import java.io.IOException JavaDoc;
12 import java.io.InputStream JavaDoc;
13 import java.net.InetAddress JavaDoc;
14 import java.net.ServerSocket JavaDoc;
15 import java.net.Socket JavaDoc;
16 import java.security.KeyStore JavaDoc;
17 import java.security.cert.Certificate JavaDoc;
18 import java.util.Arrays JavaDoc;
19 import java.util.Enumeration JavaDoc;
20 import java.util.Map JavaDoc;
21
22 import javax.net.ssl.KeyManagerFactory;
23 import javax.net.ssl.SSLContext;
24 import javax.net.ssl.SSLServerSocket;
25 import javax.net.ssl.SSLServerSocketFactory;
26 import javax.net.ssl.SSLSession;
27 import javax.net.ssl.SSLSocket;
28
29 import winstone.HostGroup;
30 import winstone.HttpListener;
31 import winstone.Logger;
32 import winstone.ObjectPool;
33 import winstone.WebAppConfiguration;
34 import winstone.WinstoneException;
35 import winstone.WinstoneRequest;
36 import winstone.WinstoneResourceBundle;
37
38 /**
39  * Implements the main listener daemon thread. This is the class that gets
40  * launched by the command line, and owns the server socket, etc.
41  *
42  * @author <a HREF="mailto:rick_knowles@hotmail.com">Rick Knowles</a>
43  * @version $Id: HttpsListener.java,v 1.9 2006/03/09 14:05:59 rickknowles Exp $
44  */

45 public class HttpsListener extends HttpListener {
46     private static final WinstoneResourceBundle SSL_RESOURCES = new WinstoneResourceBundle("winstone.ssl.LocalStrings");
47     private String JavaDoc keystore;
48     private String JavaDoc password;
49     private String JavaDoc keyManagerType;
50
51     /**
52      * Constructor
53      */

54     public HttpsListener(Map JavaDoc args, ObjectPool objectPool, HostGroup hostGroup) throws IOException JavaDoc {
55         super(args, objectPool, hostGroup);
56         this.keystore = WebAppConfiguration.stringArg(args, getConnectorName()
57                 + "KeyStore", "winstone.ks");
58         this.password = WebAppConfiguration.stringArg(args, getConnectorName()
59                 + "KeyStorePassword", null);
60         this.keyManagerType = WebAppConfiguration.stringArg(args,
61                 getConnectorName() + "KeyManagerType", "SunX509");
62     }
63
64     /**
65      * The default port to use - this is just so that we can override for the
66      * SSL connector.
67      */

68     protected int getDefaultPort() {
69         return -1; // https disabled by default
70
}
71
72     /**
73      * The name to use when getting properties - this is just so that we can
74      * override for the SSL connector.
75      */

76     protected String JavaDoc getConnectorScheme() {
77         return "https";
78     }
79
80     /**
81      * Gets a server socket - this gets as SSL socket instead of the standard
82      * socket returned in the base class.
83      */

84     protected ServerSocket JavaDoc getServerSocket() throws IOException JavaDoc {
85         // Just to make sure it's set before we start
86
SSLContext context = getSSLContext(this.keystore, this.password);
87         SSLServerSocketFactory factory = context.getServerSocketFactory();
88         SSLServerSocket ss = (SSLServerSocket) (this.listenAddress == null ? factory
89                 .createServerSocket(this.listenPort, BACKLOG_COUNT)
90                 : factory.createServerSocket(this.listenPort, BACKLOG_COUNT,
91                         InetAddress.getByName(this.listenAddress)));
92         ss.setEnableSessionCreation(true);
93         return ss;
94     }
95
96     /**
97      * Extracts the relevant socket stuff and adds it to the request object.
98      * This method relies on the base class for everything other than SSL
99      * related attributes
100      */

101     protected void parseSocketInfo(Socket JavaDoc socket, WinstoneRequest req)
102             throws IOException JavaDoc {
103         super.parseSocketInfo(socket, req);
104         if (socket instanceof SSLSocket) {
105             SSLSocket s = (SSLSocket) socket;
106             SSLSession ss = s.getSession();
107             if (ss != null) {
108                 Certificate JavaDoc certChain[] = null;
109                 try {
110                     certChain = ss.getPeerCertificates();
111                 } catch (Throwable JavaDoc err) {/* do nothing */
112                 }
113
114                 if (certChain != null) {
115                     req.setAttribute("javax.servlet.request.X509Certificate",
116                             certChain);
117                     req.setAttribute("javax.servlet.request.cipher_suite", ss
118                             .getCipherSuite());
119                     req.setAttribute("javax.servlet.request.ssl_session",
120                             new String JavaDoc(ss.getId()));
121                     req.setAttribute("javax.servlet.request.key_size",
122                             getKeySize(ss.getCipherSuite()));
123                 }
124             }
125             req.setIsSecure(true);
126         }
127     }
128
129     /**
130      * Just a mapping of key sizes for cipher types. Taken indirectly from the
131      * TLS specs.
132      */

133     private Integer JavaDoc getKeySize(String JavaDoc cipherSuite) {
134         if (cipherSuite.indexOf("_WITH_NULL_") != -1)
135             return new Integer JavaDoc(0);
136         else if (cipherSuite.indexOf("_WITH_IDEA_CBC_") != -1)
137             return new Integer JavaDoc(128);
138         else if (cipherSuite.indexOf("_WITH_RC2_CBC_40_") != -1)
139             return new Integer JavaDoc(40);
140         else if (cipherSuite.indexOf("_WITH_RC4_40_") != -1)
141             return new Integer JavaDoc(40);
142         else if (cipherSuite.indexOf("_WITH_RC4_128_") != -1)
143             return new Integer JavaDoc(128);
144         else if (cipherSuite.indexOf("_WITH_DES40_CBC_") != -1)
145             return new Integer JavaDoc(40);
146         else if (cipherSuite.indexOf("_WITH_DES_CBC_") != -1)
147             return new Integer JavaDoc(56);
148         else if (cipherSuite.indexOf("_WITH_3DES_EDE_CBC_") != -1)
149             return new Integer JavaDoc(168);
150         else
151             return null;
152     }
153
154     /**
155      * Used to get the base ssl context in which to create the server socket.
156      * This is basically just so we can have a custom location for key stores.
157      */

158     public SSLContext getSSLContext(String JavaDoc keyStoreName, String JavaDoc password)
159             throws IOException JavaDoc {
160         try {
161             // Check the key manager factory
162
KeyManagerFactory kmf = KeyManagerFactory.getInstance(this.keyManagerType);
163             
164             File JavaDoc ksFile = new File JavaDoc(keyStoreName);
165             if (!ksFile.exists() || !ksFile.isFile())
166                 throw new WinstoneException(SSL_RESOURCES.getString(
167                         "HttpsListener.KeyStoreNotFound", ksFile.getPath()));
168             InputStream JavaDoc in = new FileInputStream JavaDoc(ksFile);
169             char[] passwordChars = password == null ? null : password.toCharArray();
170             KeyStore JavaDoc ks = KeyStore.getInstance("JKS");
171             ks.load(in, passwordChars);
172             kmf.init(ks, passwordChars);
173             Logger.log(Logger.FULL_DEBUG, SSL_RESOURCES,
174                     "HttpsListener.KeyCount", ks.size() + "");
175             for (Enumeration JavaDoc e = ks.aliases(); e.hasMoreElements();) {
176                 String JavaDoc alias = (String JavaDoc) e.nextElement();
177                 Logger.log(Logger.FULL_DEBUG, SSL_RESOURCES,
178                         "HttpsListener.KeyFound", new String JavaDoc[] { alias,
179                                 ks.getCertificate(alias) + "" });
180             }
181
182             SSLContext context = SSLContext.getInstance("SSL");
183             context.init(kmf.getKeyManagers(), null, null);
184             Arrays.fill(passwordChars, 'x');
185             return context;
186         } catch (IOException JavaDoc err) {
187             throw err;
188         } catch (Throwable JavaDoc err) {
189             throw new WinstoneException(SSL_RESOURCES
190                     .getString("HttpsListener.ErrorGettingContext"), err);
191         }
192     }
193 }
194
Popular Tags