remm 2005/07/07 06:38:38 Modified: util/java/org/apache/tomcat/util/net AprEndpoint.java http11/src/java/org/apache/coyote/http11 Http11AprProtocol.java Log: - Add basic SSL support (no cert extraction yet). - Untested. Revision Changes Path 1.58 +160 -37 jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/net/AprEndpoint.java Index: AprEndpoint.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/net/AprEndpoint.java,v retrieving revision 1.57 retrieving revision 1.58 diff -u -r1.57 -r1.58 --- AprEndpoint.java 3 Jul 2005 10:12:51 -0000 1.57 +++ AprEndpoint.java 7 Jul 2005 13:38:38 -0000 1.58 @@ -31,10 +31,12 @@ import org.apache.tomcat.jni.Pool; import org.apache.tomcat.jni.Socket; import org.apache.tomcat.jni.Status; +import org.apache.tomcat.jni.SSL; +import org.apache.tomcat.jni.SSLContext; +import org.apache.tomcat.jni.SSLSocket; import org.apache.tomcat.util.res.StringManager; import org.apache.tomcat.util.threads.ThreadWithAttributes; - /** * APR tailored thread pool, providing the following services: * <ul> @@ -149,6 +151,12 @@ */ protected long serverSockPool = 0; + + /** + * SSL context. + */ + protected long sslContext = 0; + // ------------------------------------------------------------- Properties @@ -205,7 +213,7 @@ * Handling of accepted sockets. */ protected Handler handler = null; - public void setHandler(Handler handler ) { this.handler=handler; } + public void setHandler(Handler handler ) { this.handler = handler; } public Handler getHandler() { return handler; } @@ -325,7 +333,104 @@ */ public int getMinSpareThreads() { return 0; } + + /** + * SSL engine. + */ + protected String SSLEngine = "off"; + public String getSSLEngine() { return SSLEngine; } + public void setSSLEngine(String SSLEngine) { this.SSLEngine = SSLEngine; } + + + /** + * SSL password (if a cert is encrypted, and no password has been provided, a callback + * will ask for a password). + */ + protected String SSLPassword = null; + public String getSSLPassword() { return SSLPassword; } + public void setSSLPassword(String SSLPassword) { this.SSLPassword = SSLPassword; } + + /** + * SSL cipher suite. + */ + protected String SSLCipherSuite = "ALL"; + public String getSSLCipherSuite() { return SSLCipherSuite; } + public void setSSLCipherSuite(String SSLCipherSuite) { this.SSLCipherSuite = SSLCipherSuite; } + + + /** + * SSL certificate file. + */ + protected String SSLCertificateFile = null; + public String getSSLCertificateFile() { return SSLCertificateFile; } + public void setSSLCertificateFile(String SSLCertificateFile) { this.SSLCertificateFile = SSLCertificateFile; } + + + /** + * SSL certificate key file. + */ + protected String SSLCertificateKeyFile = null; + public String getSSLCertificateKeyFile() { return SSLCertificateKeyFile; } + public void setSSLCertificateKeyFile(String SSLCertificateKeyFile) { this.SSLCertificateKeyFile = SSLCertificateKeyFile; } + + + /** + * SSL certificate chain file. + */ + protected String SSLCertificateChainFile = null; + public String getSSLCertificateChainFile() { return SSLCertificateChainFile; } + public void setSSLCertificateChainFile(String SSLCertificateChainFile) { this.SSLCertificateChainFile = SSLCertificateChainFile; } + + + /** + * SSL CA certificate path. + */ + protected String SSLCACertificatePath = null; + public String getSSLCACertificatePath() { return SSLCACertificatePath; } + public void setSSLCACertificatePath(String SSLCACertificatePath) { this.SSLCACertificatePath = SSLCACertificatePath; } + + + /** + * SSL CA certificate file. + */ + protected String SSLCACertificateFile = null; + public String getSSLCACertificateFile() { return SSLCACertificateFile; } + public void setSSLCACertificateFile(String SSLCACertificateFile) { this.SSLCACertificateFile = SSLCACertificateFile; } + + + /** + * SSL CA revocation path. + */ + protected String SSLCARevocationPath = null; + public String getSSLCARevocationPath() { return SSLCARevocationPath; } + public void setSSLCARevocationPath(String SSLCARevocationPath) { this.SSLCARevocationPath = SSLCARevocationPath; } + + + /** + * SSL CA revocation file. + */ + protected String SSLCARevocationFile = null; + public String getSSLCARevocationFile() { return SSLCARevocationFile; } + public void setSSLCARevocationFile(String SSLCARevocationFile) { this.SSLCARevocationFile = SSLCARevocationFile; } + + + /** + * SSL verify client. + */ + protected boolean SSLVerifyClient = false; + public boolean getSSLVerifyClient() { return SSLVerifyClient; } + public void setSSLVerifyClient(boolean SSLVerifyClient) { this.SSLVerifyClient = SSLVerifyClient; } + + + /** + * SSL verify depth. + */ + protected int SSLVerifyDepth = 10; + public int getSSLVerifyDepth() { return SSLVerifyDepth; } + public void setSSLVerifyDepth(int SSLVerifyDepth) { this.SSLVerifyDepth = SSLVerifyDepth; } + + // --------------------------------------------------------- Public Methods @@ -411,8 +516,32 @@ // Delay accepting of new connections until data is available // Only Linux kernels 2.4 + have that implemented // on other platforms this call is noop and will return APR_ENOTIMPL. - Socket.optSet(serverSock, Socket.APR_TCP_DEFER_ACCEPT, 1); - + Socket.optSet(serverSock, Socket.APR_TCP_DEFER_ACCEPT, 1); + + // Initialize SSL if needed + if (!"off".equalsIgnoreCase(SSLEngine)) { + // Initialize SSL + // FIXME: one per VM call ? + if ("on".equalsIgnoreCase(SSLEngine)) { + SSL.initialize(null); + } else { + SSL.initialize(SSLEngine); + } + // Create SSL Context + sslContext = SSLContext.make(rootPool, SSL.SSL_PROTOCOL_SSLV2 | SSL.SSL_PROTOCOL_SSLV3, SSL.SSL_MODE_SERVER); + // List the ciphers that the client is permitted to negotiate + SSLContext.setCipherSuite(sslContext, SSLCipherSuite); + // Load Server key and certificate + SSLContext.setCertificate(sslContext, SSLCertificateFile, SSLCertificateKeyFile, SSLPassword, SSL.SSL_AIDX_RSA); + // Support Client Certificates + SSLContext.setVerify(sslContext, SSLVerifyClient ? 1 : 0, SSLVerifyDepth); + if (SSLCACertificateFile != null) { + SSLContext.setCACertificate(sslContext, SSLCACertificateFile, null); + } + // For now, sendfile is not supported with SSL + useSendfile = false; + } + initialized = true; } @@ -509,6 +638,7 @@ serverSockPool = 0; // Close server socket Socket.close(serverSock); + sslContext = 0; // Close all APR memory pools and resources Pool.destroy(rootPool); rootPool = 0; @@ -559,44 +689,32 @@ /** - * Set options on a newly accepted socket. - * - * @param socket "pointer" to the accepted socket - */ - protected void setSocketOptions(long socket) { - if (soLinger >= 0) - Socket.optSet(socket, Socket.APR_SO_LINGER, soLinger); - if (tcpNoDelay) - Socket.optSet(socket, Socket.APR_TCP_NODELAY, (tcpNoDelay ? 1 : 0)); - if (soTimeout > 0) - Socket.timeoutSet(socket, soTimeout * 1000); - } - - - /** * Process the specified connection. */ - protected boolean processSocket(long socket) { + protected boolean setSocketOptions(long socket) { // Process the connection int step = 1; - boolean result = true; try { // 1: Set socket options: timeout, linger, etc - setSocketOptions(socket); + if (soLinger >= 0) + Socket.optSet(socket, Socket.APR_SO_LINGER, soLinger); + if (tcpNoDelay) + Socket.optSet(socket, Socket.APR_TCP_NODELAY, (tcpNoDelay ? 1 : 0)); + if (soTimeout > 0) + Socket.timeoutSet(socket, soTimeout * 1000); // 2: SSL handshake step = 2; - // FIXME: SSL implementation so that Bill is happy - /* - if (getServerSocketFactory() != null) { - getServerSocketFactory().handshake(s); - } - */ - - // 3: Process the connection - step = 3; - result = getHandler().process(socket); + if (sslContext != 0) { + SSLSocket.attach(sslContext, socket); + if (SSLSocket.handshake(socket) != 0) { + if (log.isDebugEnabled()) { + log.debug(sm.getString("endpoint.err.handshake") + ": " + SSL.getLastError()); + } + return false; + } + } } catch (Throwable t) { if (step == 2) { @@ -607,9 +725,9 @@ log.error(sm.getString("endpoint.err.unexpected"), t); } // Tell to close the socket - result = false; + return false; } - return result; + return true; } @@ -723,7 +841,12 @@ try { long socket = Socket.accept(serverSock); // Hand this socket off to an appropriate processor - workerThread.assign(socket); + if (setSocketOptions(socket)) { + workerThread.assign(socket); + } else { + // Close socket and pool right away + Socket.destroy(socket); + } } catch (Exception e) { log.error(sm.getString("endpoint.accept.fail"), e); } @@ -1011,7 +1134,7 @@ continue; // Process the request from this socket - if (!processSocket(socket)) { + if (!handler.process(socket)) { // Close socket and pool Socket.destroy(socket); socket = 0; @@ -1289,7 +1412,7 @@ } else { // Close the socket since this is // the end of not keep-alive request. - Socket.destroy(state.socket); + Socket.destroy(state.socket); } } } 1.12 +84 -166 jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/Http11AprProtocol.java Index: Http11AprProtocol.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/Http11AprProtocol.java,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- Http11AprProtocol.java 27 Jun 2005 13:44:04 -0000 1.11 +++ Http11AprProtocol.java 7 Jul 2005 13:38:38 -0000 1.12 @@ -18,7 +18,6 @@ import java.net.InetAddress; import java.net.URLEncoder; -import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; @@ -34,8 +33,6 @@ import org.apache.coyote.RequestGroupInfo; import org.apache.coyote.RequestInfo; import org.apache.tomcat.util.net.AprEndpoint; -import org.apache.tomcat.util.net.SSLImplementation; -import org.apache.tomcat.util.net.ServerSocketFactory; import org.apache.tomcat.util.net.AprEndpoint.Handler; import org.apache.tomcat.util.res.StringManager; @@ -113,24 +110,7 @@ public void init() throws Exception { ep.setName(getName()); ep.setHandler(cHandler); - try { - checkSocketFactory(); - } catch( Exception ex ) { - log.error(sm.getString("http11protocol.socketfactory.initerror"), - ex); - throw ex; - } - if( socketFactory!=null ) { - Enumeration attE=attributes.keys(); - while( attE.hasMoreElements() ) { - String key=(String)attE.nextElement(); - Object v=attributes.get( key ); - socketFactory.setAttribute( key, v ); - } - } - - // XXX get domain from registration try { ep.init(); } catch (Exception ex) { @@ -148,8 +128,6 @@ public void start() throws Exception { if( this.domain != null ) { try { - // XXX We should be able to configure it separately - // XXX It should be possible to use a single TP tpOname=new ObjectName (domain + ":" + "type=ThreadPool,name=" + getName()); Registry.getRegistry(null, null) @@ -209,18 +187,13 @@ protected AprEndpoint ep=new AprEndpoint(); protected boolean secure; - protected ServerSocketFactory socketFactory; - protected SSLImplementation sslImplementation; // socket factory attriubtes ( XXX replace with normal setters ) protected Hashtable attributes = new Hashtable(); - protected String socketFactoryName=null; - protected String sslImplementationName=null; private int maxKeepAliveRequests=100; // as in Apache HTTPD server private int timeout = 300000; // 5 minutes as in Apache HTTPD server private int maxSavePostSize = 4 * 1024; private int maxHttpHeaderSize = 4 * 1024; - private String reportedname; private int socketCloseDelay=-1; private boolean disableUploadTimeout = true; private int socketBuffer = 9000; @@ -342,25 +315,6 @@ return ("http-" + encodedAddr + ep.getPort()); } - public String getSocketFactory() { - return socketFactoryName; - } - - public void setSocketFactory( String valueS ) { - socketFactoryName = valueS; - setAttribute("socketFactory", valueS); - } - - public String getSSLImplementation() { - return sslImplementationName; - } - - public void setSSLImplementation( String valueS) { - sslImplementationName = valueS; - setSecure(true); - setAttribute("sslImplementation", valueS); - } - public boolean getTcpNoDelay() { return ep.getTcpNoDelay(); } @@ -467,50 +421,6 @@ setAttribute("soTimeout", "" + i); } - /* - public int getServerSoTimeout() { - return ep.getServerSoTimeout(); - } - - public void setServerSoTimeout( int i ) { - ep.setServerSoTimeout(i); - setAttribute("serverSoTimeout", "" + i); - } - */ - - public String getKeystore() { - return getProperty("keystore"); - } - - public void setKeystore( String k ) { - setAttribute("keystore", k); - } - - public String getKeypass() { - return getProperty("keypass"); - } - - public void setKeypass( String k ) { - attributes.put("keypass", k); - //setAttribute("keypass", k); - } - - public String getKeytype() { - return getProperty("keystoreType"); - } - - public void setKeytype( String k ) { - setAttribute("keystoreType", k); - } - - public String getClientauth() { - return getProperty("clientauth"); - } - - public void setClientauth( String k ) { - setAttribute("clientauth", k); - } - public String getProtocol() { return getProperty("protocol"); } @@ -520,22 +430,6 @@ setAttribute("protocol", k); } - public String getProtocols() { - return getProperty("protocols"); - } - - public void setProtocols(String k) { - setAttribute("protocols", k); - } - - public String getAlgorithm() { - return getProperty("algorithm"); - } - - public void setAlgorithm( String k ) { - setAttribute("algorithm", k); - } - public boolean getSecure() { return secure; } @@ -545,22 +439,6 @@ setAttribute("secure", "" + b); } - public String getCiphers() { - return getProperty("ciphers"); - } - - public void setCiphers(String ciphers) { - setAttribute("ciphers", ciphers); - } - - public String getKeyAlias() { - return getProperty("keyAlias"); - } - - public void setKeyAlias(String keyAlias) { - setAttribute("keyAlias", keyAlias); - } - public int getMaxKeepAliveRequests() { return maxKeepAliveRequests; } @@ -605,14 +483,6 @@ return server; } - - private static ServerSocketFactory string2SocketFactory( String val) - throws ClassNotFoundException, IllegalAccessException, - InstantiationException { - Class chC=Class.forName( val ); - return (ServerSocketFactory)chC.newInstance(); - } - public int getTimeout() { return timeout; } @@ -622,13 +492,91 @@ setAttribute("timeout", "" + timeouts); } - public String getReportedname() { - return reportedname; - } + // -------------------- SSL related properties -------------------- - public void setReportedname( String reportedName) { - reportedname = reportedName; - } + /** + * SSL engine. + */ + public String getSSLEngine() { return ep.getSSLEngine(); } + public void setSSLEngine(String SSLEngine) { ep.setSSLEngine(SSLEngine); } + + + /** + * SSL password (if a cert is encrypted, and no password has been provided, a callback + * will ask for a password). + */ + public String getSSLPassword() { return ep.getSSLPassword(); } + public void setSSLPassword(String SSLPassword) { ep.setSSLPassword(SSLPassword); } + + + /** + * SSL cipher suite. + */ + public String getSSLCipherSuite() { return ep.getSSLCipherSuite(); } + public void setSSLCipherSuite(String SSLCipherSuite) { ep.setSSLCipherSuite(SSLCipherSuite); } + + + /** + * SSL certificate file. + */ + public String getSSLCertificateFile() { return ep.getSSLCertificateFile(); } + public void setSSLCertificateFile(String SSLCertificateFile) { ep.setSSLCertificateFile(SSLCertificateFile); } + + + /** + * SSL certificate key file. + */ + public String getSSLCertificateKeyFile() { return ep.getSSLCertificateKeyFile(); } + public void setSSLCertificateKeyFile(String SSLCertificateKeyFile) { ep.setSSLCertificateKeyFile(SSLCertificateKeyFile); } + + + /** + * SSL certificate chain file. + */ + public String getSSLCertificateChainFile() { return ep.getSSLCertificateChainFile(); } + public void setSSLCertificateChainFile(String SSLCertificateChainFile) { ep.setSSLCertificateChainFile(SSLCertificateChainFile); } + + + /** + * SSL CA certificate path. + */ + public String getSSLCACertificatePath() { return ep.getSSLCACertificatePath(); } + public void setSSLCACertificatePath(String SSLCACertificatePath) { ep.setSSLCACertificatePath(SSLCACertificatePath); } + + + /** + * SSL CA certificate file. + */ + public String getSSLCACertificateFile() { return ep.getSSLCACertificateFile(); } + public void setSSLCACertificateFile(String SSLCACertificateFile) { ep.setSSLCACertificateFile(SSLCACertificateFile); } + + + /** + * SSL CA revocation path. + */ + public String getSSLCARevocationPath() { return ep.getSSLCARevocationPath(); } + public void setSSLCARevocationPath(String SSLCARevocationPath) { ep.setSSLCARevocationPath(SSLCARevocationPath); } + + + /** + * SSL CA revocation file. + */ + public String getSSLCARevocationFile() { return ep.getSSLCARevocationFile(); } + public void setSSLCARevocationFile(String SSLCARevocationFile) { ep.setSSLCARevocationFile(SSLCARevocationFile); } + + + /** + * SSL verify client. + */ + public boolean getSSLVerifyClient() { return ep.getSSLVerifyClient(); } + public void setSSLVerifyClient(boolean SSLVerifyClient) { ep.setSSLVerifyClient(SSLVerifyClient); } + + + /** + * SSL verify depth. + */ + public int getSSLVerifyDepth() { return ep.getSSLVerifyDepth(); } + public void setSSLVerifyDepth(int SSLVerifyDepth) { ep.setSSLVerifyDepth(SSLVerifyDepth); } // -------------------- Connection handler -------------------- @@ -734,36 +682,6 @@ // -------------------- Various implementation classes -------------------- - /** Sanity check and socketFactory setup. - * IMHO it is better to stop the show on a broken connector, - * then leave Tomcat running and broken. - * @exception TomcatException Unable to resolve classes - */ - private void checkSocketFactory() throws Exception { - /* - if (secure) { - try { - // The SSL setup code has been moved into - // SSLImplementation since SocketFactory doesn't - // provide a wide enough interface - sslImplementation = - SSLImplementation.getInstance(sslImplementationName); - socketFactory = sslImplementation.getServerSocketFactory(); - ep.setServerSocketFactory(socketFactory); - } catch (ClassNotFoundException e){ - throw e; - } - } else if (socketFactoryName != null) { - try { - socketFactory = string2SocketFactory(socketFactoryName); - ep.setServerSocketFactory(socketFactory); - } catch(Exception sfex) { - throw sfex; - } - } - */ - } - protected String domain; protected ObjectName oname; protected MBeanServer mserver;
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]