You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2005/07/07 15:38:38 UTC

cvs commit: jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11 Http11AprProtocol.java

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: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org