1 7 package winstone.ssl; 8 9 import java.io.File ; 10 import java.io.FileInputStream ; 11 import java.io.IOException ; 12 import java.io.InputStream ; 13 import java.net.InetAddress ; 14 import java.net.ServerSocket ; 15 import java.net.Socket ; 16 import java.security.KeyStore ; 17 import java.security.cert.Certificate ; 18 import java.util.Arrays ; 19 import java.util.Enumeration ; 20 import java.util.Map ; 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 45 public class HttpsListener extends HttpListener { 46 private static final WinstoneResourceBundle SSL_RESOURCES = new WinstoneResourceBundle("winstone.ssl.LocalStrings"); 47 private String keystore; 48 private String password; 49 private String keyManagerType; 50 51 54 public HttpsListener(Map args, ObjectPool objectPool, HostGroup hostGroup) throws IOException { 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 68 protected int getDefaultPort() { 69 return -1; } 71 72 76 protected String getConnectorScheme() { 77 return "https"; 78 } 79 80 84 protected ServerSocket getServerSocket() throws IOException { 85 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 101 protected void parseSocketInfo(Socket socket, WinstoneRequest req) 102 throws IOException { 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 certChain[] = null; 109 try { 110 certChain = ss.getPeerCertificates(); 111 } catch (Throwable err) { 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 (ss.getId())); 121 req.setAttribute("javax.servlet.request.key_size", 122 getKeySize(ss.getCipherSuite())); 123 } 124 } 125 req.setIsSecure(true); 126 } 127 } 128 129 133 private Integer getKeySize(String cipherSuite) { 134 if (cipherSuite.indexOf("_WITH_NULL_") != -1) 135 return new Integer (0); 136 else if (cipherSuite.indexOf("_WITH_IDEA_CBC_") != -1) 137 return new Integer (128); 138 else if (cipherSuite.indexOf("_WITH_RC2_CBC_40_") != -1) 139 return new Integer (40); 140 else if (cipherSuite.indexOf("_WITH_RC4_40_") != -1) 141 return new Integer (40); 142 else if (cipherSuite.indexOf("_WITH_RC4_128_") != -1) 143 return new Integer (128); 144 else if (cipherSuite.indexOf("_WITH_DES40_CBC_") != -1) 145 return new Integer (40); 146 else if (cipherSuite.indexOf("_WITH_DES_CBC_") != -1) 147 return new Integer (56); 148 else if (cipherSuite.indexOf("_WITH_3DES_EDE_CBC_") != -1) 149 return new Integer (168); 150 else 151 return null; 152 } 153 154 158 public SSLContext getSSLContext(String keyStoreName, String password) 159 throws IOException { 160 try { 161 KeyManagerFactory kmf = KeyManagerFactory.getInstance(this.keyManagerType); 163 164 File ksFile = new File (keyStoreName); 165 if (!ksFile.exists() || !ksFile.isFile()) 166 throw new WinstoneException(SSL_RESOURCES.getString( 167 "HttpsListener.KeyStoreNotFound", ksFile.getPath())); 168 InputStream in = new FileInputStream (ksFile); 169 char[] passwordChars = password == null ? null : password.toCharArray(); 170 KeyStore 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 e = ks.aliases(); e.hasMoreElements();) { 176 String alias = (String ) e.nextElement(); 177 Logger.log(Logger.FULL_DEBUG, SSL_RESOURCES, 178 "HttpsListener.KeyFound", new String [] { 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 err) { 187 throw err; 188 } catch (Throwable err) { 189 throw new WinstoneException(SSL_RESOURCES 190 .getString("HttpsListener.ErrorGettingContext"), err); 191 } 192 } 193 } 194 | Popular Tags |