SSLEngine is an attribute of the APR lifecycle listener to initialize the native...
authorfhanik <fhanik@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 19 Oct 2006 16:45:45 +0000 (16:45 +0000)
committerfhanik <fhanik@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 19 Oct 2006 16:45:45 +0000 (16:45 +0000)
All HTTP connectors share an attribute called SSLEnabled with true/false values to turn on SSL at the socket level.
The scheme and secure attributes simply override the request.getScheme and request.isSecure values.

git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk@465675 13f79535-47bb-0310-9956-ffa450edef68

14 files changed:
conf/server.xml
java/org/apache/catalina/core/AprLifecycleListener.java
java/org/apache/catalina/core/LocalStrings.properties
java/org/apache/coyote/http11/Http11AprProcessor.java
java/org/apache/coyote/http11/Http11AprProtocol.java
java/org/apache/coyote/http11/Http11NioProcessor.java
java/org/apache/coyote/http11/Http11NioProtocol.java
java/org/apache/coyote/http11/Http11Protocol.java
java/org/apache/tomcat/util/net/AprEndpoint.java
java/org/apache/tomcat/util/net/NioEndpoint.java
webapps/docs/apr.xml
webapps/docs/changelog.xml
webapps/docs/config/http.xml
webapps/docs/ssl-howto.xml

index 72640dd..7b3c5ae 100644 (file)
@@ -5,7 +5,7 @@
 <Server port="8005" shutdown="SHUTDOWN">
 
   <!--APR library loader. Documentation at /docs/apr.html -->
-  <Listener className="org.apache.catalina.core.AprLifecycleListener" />
+  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
   <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
   <Listener className="org.apache.catalina.core.JasperListener" />
   <!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html -->
index 4292091..fd3cfd2 100644 (file)
@@ -24,6 +24,8 @@ import org.apache.catalina.LifecycleListener;
 import org.apache.catalina.util.StringManager;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
+import java.lang.reflect.InvocationTargetException;
+
 
 
 /**
@@ -56,9 +58,12 @@ public class AprLifecycleListener
     protected static final int RECOMMENDED_PV = 6;
 
 
+    // ---------------------------------------------- Properties
+    protected static String SSLEngine = "on"; //default on
+    protected static boolean sslInitialized = false;
+    
     // ---------------------------------------------- LifecycleListener Methods
 
-
     /**
      * Primary entry point for startup and shutdown events.
      *
@@ -83,6 +88,7 @@ public class AprLifecycleListener
                 minor = clazz.getField("TCN_MINOR_VERSION").getInt(null);
                 patch = clazz.getField("TCN_PATCH_VERSION").getInt(null);
             } catch (Throwable t) {
+                t.printStackTrace();
                 if (!log.isDebugEnabled()) {
                     log.info(sm.getString("aprListener.aprInit", 
                             System.getProperty("java.library.path")));
@@ -109,6 +115,11 @@ public class AprLifecycleListener
                             + REQUIRED_MINOR + "." + RECOMMENDED_PV));
                 }                
             }
+            try {
+                initializeSSL();
+            }catch ( Throwable t ) {
+                log.error(sm.getString("aprListener.sslInit",t.getMessage()),t);
+            }
         } else if (Lifecycle.AFTER_STOP_EVENT.equals(event.getType())) {
             try {
                 String methodName = "terminate";
@@ -125,6 +136,24 @@ public class AprLifecycleListener
         }
 
     }
+    
+    public static synchronized void initializeSSL() 
+        throws ClassNotFoundException,NoSuchMethodException,
+               IllegalAccessException,InvocationTargetException{
+        
+        if ("off".equalsIgnoreCase(SSLEngine) ) return;
+        if ( sslInitialized ) return; //only once per VM
+        String methodName = "initialize";
+        Class paramTypes[] = new Class[1];
+        paramTypes[0] = String.class;
+        Object paramValues[] = new Object[1];
+        paramValues[0] = "on".equalsIgnoreCase(SSLEngine)?null:SSLEngine;
+        Class clazz = Class.forName("org.apache.tomcat.jni.SSL");
+        Method method = clazz.getMethod(methodName, paramTypes);
+        method.invoke(null, paramValues);
+        sslInitialized = true;
+
+    }
 
 
 }
index d57878e..4c81b9d 100644 (file)
@@ -18,6 +18,7 @@ aprListener.aprInit=The Apache Tomcat Native library which allows optimal perfor
 aprListener.tcnInvalid=An incompatible version {0} of the Apache Tomcat Native library is installed, while Tomcat requires version {1} 
 aprListener.tcnVersion=An older version {0} of the Apache Tomcat Native library is installed, while Tomcat recommends version greater then {1}
 aprListener.aprDestroy=Failed shutdown of Apache Portable Runtime
+aprListener.sslInit=Unable to initialize the SSLEngine, failed with message: {0}
 containerBase.addDefaultMapper=Exception configuring default mapper of class {0}
 containerBase.alreadyStarted=Container {0} has already been started
 containerBase.notConfigured=No basic Valve has been configured
index 21e96df..3469bb3 100644 (file)
@@ -102,7 +102,7 @@ public class Http11AprProcessor implements ActionHook {
         response.setOutputBuffer(outputBuffer);
         request.setResponse(response);
         
-        ssl = !"off".equalsIgnoreCase(endpoint.getSSLEngine());
+        ssl = endpoint.isSSLEnabled();
 
         initializeFilters();
 
index 359672e..1975807 100644 (file)
@@ -509,8 +509,8 @@ public class Http11AprProtocol implements ProtocolHandler, MBeanRegistration
     /**
      * SSL engine.
      */
-    public String getSSLEngine() { return ep.getSSLEngine(); }
-    public void setSSLEngine(String SSLEngine) { ep.setSSLEngine(SSLEngine); }
+    public boolean isSSLEnabled() { return ep.isSSLEnabled(); }
+    public void setSSLEnabled(boolean SSLEnabled) { ep.setSSLEnabled(SSLEnabled); }
 
 
     /**
index d781149..e87f5f4 100644 (file)
@@ -103,7 +103,7 @@ public class Http11NioProcessor implements ActionHook {
         response.setOutputBuffer(outputBuffer);
         request.setResponse(response);
 
-        ssl = "on".equalsIgnoreCase(endpoint.getSSLEngine());
+        ssl = endpoint.isSSLEnabled();
 
         initializeFilters();
 
index a8ff9e3..0804a68 100644 (file)
@@ -537,8 +537,8 @@ public class Http11NioProtocol implements ProtocolHandler, MBeanRegistration
     public String getCiphers() { return ep.getCiphers();}
     public void setCiphers(String s) { ep.setCiphers(s);}
     
-    public String getSSLEngine() { return ep.getSSLEngine(); }
-    public void setSSLEngine(String SSLEngine) { ep.setSSLEngine(SSLEngine); }
+    public boolean getSSLEnabled() { return ep.isSSLEnabled(); }
+    public void setSSLEnabled(boolean SSLEnabled) { ep.setSSLEnabled(SSLEnabled); }
     
     
 
index 5e83b83..7cebed4 100644 (file)
@@ -146,7 +146,7 @@ public class Http11Protocol
 
         // Verify the validity of the configured socket factory
         try {
-            if ("on".equalsIgnoreCase(getSSLEngine())) {
+            if (isSSLEnabled()) {
                 sslImplementation =
                     SSLImplementation.getInstance(sslImplementationName);
                 socketFactory = sslImplementation.getServerSocketFactory();
@@ -252,9 +252,9 @@ public class Http11Protocol
     public boolean getSecure() { return secure; }
     public void setSecure(boolean b) { secure = b; }
 
-    protected String SSLEngine = "off";
-    public String getSSLEngine() { return SSLEngine;}
-    public void setSSLEngine(String SSLEngine) {this.SSLEngine = SSLEngine;}    
+    protected boolean SSLEnabled = false;
+    public boolean isSSLEnabled() { return SSLEnabled;}
+    public void setSSLEnabled(boolean SSLEnabled) {this.SSLEnabled = SSLEnabled;}    
     
     /**
      * Name of the socket factory.
index bda77e5..f898b92 100644 (file)
@@ -379,9 +379,9 @@ public class AprEndpoint {
     /**
      * SSL engine.
      */
-    protected String SSLEngine = "off";
-    public String getSSLEngine() { return SSLEngine; }
-    public void setSSLEngine(String SSLEngine) { this.SSLEngine = SSLEngine; }
+    protected boolean SSLEnabled = false;
+    public boolean isSSLEnabled() { return SSLEnabled; }
+    public void setSSLEnabled(boolean SSLEnabled) { this.SSLEnabled = SSLEnabled; }
 
 
     /**
@@ -649,14 +649,8 @@ public class AprEndpoint {
         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);
-            }
+        if (SSLEnabled) {
+            
             // SSL protocol
             int value = SSL.SSL_PROTOCOL_ALL;
             if ("SSLv2".equalsIgnoreCase(SSLProtocol)) {
index fc611a0..cccfbba 100644 (file)
@@ -401,9 +401,9 @@ public class NioEndpoint {
     /**
      * SSL engine.
      */
-    protected String SSLEngine = "off";
-    public String getSSLEngine() { return SSLEngine;}
-    public void setSSLEngine(String SSLEngine) {this.SSLEngine = SSLEngine;}
+    protected boolean SSLEnabled = false;
+    public boolean isSSLEnabled() { return SSLEnabled;}
+    public void setSSLEnabled(boolean SSLEnabled) {this.SSLEnabled = SSLEnabled;}
 
     protected boolean secure = false;
     public boolean getSecure() { return secure;}
@@ -509,7 +509,7 @@ public class NioEndpoint {
         }
 
         // Initialize SSL if needed
-        if ("on".equalsIgnoreCase(getSSLEngine())) {
+        if (isSSLEnabled()) {
             // Initialize SSL
             char[] passphrase = getKeystorePass().toCharArray();
 
index ff11887..989c1b9 100644 (file)
 
   </section>
 
+  <section name="APR Lifecycle Listener Configuration">
+    <subsection name="AprLifecycleListener">
+    <attribute name="SSLEngine" required="false">
+    <p>
+      Name of the SSLEngine to use. off: Do not use SSL, on: Use SSL but no specific ENGINE.
+      The default value is on.
+      This initializes the native SSL engine, then enable the use of this engine in the connector 
+      using the <code>SSLEnabled</code> attribute. Example:
+      <source>
+&lt;Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /&gt;
+      </source>
+    </p>
+    </attribute>
+    </subsection>
+  </section>
+
   <section name="APR Connectors Configuration">
 
     <subsection name="HTTP">
     
     <attributes>
 
-    <attribute name="SSLEngine" required="false">
+    <attribute name="SSLEnabled" required="false">
     <p>
-      Name of the SSLEngine to use. off: Do not use SSL, on: Use SSL but no specific ENGINE.
-      The default value is off.
+      Enable SSL on the socket, default value is false. Set this value to true
+      to enable SSL handshake/encryption/decryption in the APR connector.
     </p>
     </attribute>
     <attribute name="SSLProtocol" required="false">
index 6e13b5d..8481b59 100644 (file)
@@ -18,6 +18,9 @@
   <subsection name="Catalina">
     <changelog>
       <add>
+        SSLEngine attribute added to the AprLifecycleListener(fhanik)
+      </add>
+      <add>
         Add API for Comet IO handling (remm, fhanik)
       </add>
       <add>
@@ -38,7 +41,7 @@
   <subsection name="Coyote">
     <changelog>
       <add>
-        SSLEngine attribute required for SSL to be turned on, on all HTTP connectors(fhanik)
+        SSLEnabled attribute required for SSL to be turned on, on all HTTP connectors(fhanik)
       </add>
     </changelog>
   </subsection> 
index 9d5471b..ddbcaa0 100644 (file)
       number specified here.</p>
     </attribute>
 
-    <attribute name="SSLEngine" required="false">
+    <attribute name="SSLEnabled" required="false">
       <p>
       Use this attribute to enable SSL traffic on a connector.
       To turn on SSL handshake/encryption/decryption on a connector
-      set this value to <code>on</code>.
-      The default value is <code>off</code>.
-      When turning this value <code>on</code> you will want to set the 
+      set this value to <code>true</code>.
+      The default value is <code>false</code>.
+      When turning this value <code>true</code> you will want to set the 
       <code>scheme</code> and the <code>secure</code> attributes as well
       to pass the correct <code>request.getScheme()</code> and 
       <code>request.isSecure()</code> values to the servlets
index 47ff1bc..304218d 100644 (file)
@@ -258,6 +258,23 @@ which contains further references for this issue.</p>
 </subsection>
 
 <subsection name="Edit the Tomcat Configuration File">
+<p>If you are using APR, you have the option of configuring an alternative engine to openSSL.
+<source>
+&lt;Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="someengine" /&gt;
+</source>
+The default value is
+<source>
+&lt;Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /&gt;
+</source>
+So to use SSL under APR, make sure the SSLEngine attribute is set to something other than <code>off</code>.
+The default value is <code>on</code> and if you specify another value, it has to be a valid engine name.
+<br/>
+If you haven't compiled in SSL support into your Tomcat Native library, then you can turn this initialization off
+<source>
+&lt;Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="off" /&gt;
+</source>
+
+</p>
 
 <p>The final step is to configure your secure socket in the
 <code>$CATALINA_HOME/conf/server.xml</code> file, where
@@ -272,11 +289,72 @@ file installed with Tomcat.  It will look something like this:</p>
            port="8443" minSpareThreads="5" maxSpareThreads="75"
            enableLookups="true" disableUploadTimeout="true" 
            acceptCount="100"  maxThreads="200"
-           scheme="https" secure="true" SSLEngine="on"
+           scheme="https" secure="true" SSLEnabled="true"
+           keystoreFile="${user.home}/.keystore" keystorePass="changeit"
+           clientAuth="false" sslProtocol="TLS"/&gt;
+--&gt;
+</source>
+<p>
+  The example above will throw an error if you have the APR and the Tomcat Native libraries in your path,
+  as tomcat will try to autoload the APR connector. The APR connector uses different attributes for 
+  SSL keys and certificates. An example of such configuration would be
+<source>
+&lt;-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 --&gt;
+&lt;!--
+&lt;Connector 
+           port="8443" minSpareThreads="5" maxSpareThreads="75"
+           enableLookups="true" disableUploadTimeout="true" 
+           acceptCount="100"  maxThreads="200"
+           scheme="https" secure="true" SSLEnabled="true"
+           SSLCertificateFile="/usr/local/ssl/server.crt" 
+           SSLCertificateKeyFile="/usr/local/ssl/server.pem"
+           clientAuth="false" sslProtocol="TLS"/&gt;
+--&gt;
+</source>
+</p>
+
+<p>
+  To avoid auto configuration you can define which connector to use by specifying a classname 
+  in the protocol attribute.<br/>
+  To define a Java connector, regardless if the APR library is loaded or not do:
+<source>
+&lt;-- Define a blocking Java SSL Coyote HTTP/1.1 Connector on port 8443 --&gt;
+&lt;!--
+&lt;Connector protocol="org.apache.coyote.http11.Http11Protocol"
+           port="8443" minSpareThreads="5" maxSpareThreads="75"
+           enableLookups="true" disableUploadTimeout="true" 
+           acceptCount="100"  maxThreads="200"
+           scheme="https" secure="true" SSLEnabled="true"
+           keystoreFile="${user.home}/.keystore" keystorePass="changeit"
+           clientAuth="false" sslProtocol="TLS"/&gt;
+--&gt;
+&lt;-- Define a non-blocking Java SSL Coyote HTTP/1.1 Connector on port 8443 --&gt;
+&lt;!--
+&lt;Connector protocol="org.apache.coyote.http11.Http11NioProtocol"
+           port="8443" minSpareThreads="5" maxSpareThreads="75"
+           enableLookups="true" disableUploadTimeout="true" 
+           acceptCount="100"  maxThreads="200"
+           scheme="https" secure="true" SSLEnabled="true"
            keystoreFile="${user.home}/.keystore" keystorePass="changeit"
            clientAuth="false" sslProtocol="TLS"/&gt;
 --&gt;
 </source>
+and to specify an APR connector
+<source>
+&lt;-- Define a APR SSL Coyote HTTP/1.1 Connector on port 8443 --&gt;
+&lt;!--
+&lt;Connector protocol="org.apache.coyote.http11.Http11AprProtocol"
+           port="8443" minSpareThreads="5" maxSpareThreads="75"
+           enableLookups="true" disableUploadTimeout="true" 
+           acceptCount="100"  maxThreads="200"
+           scheme="https" secure="true" SSLEnabled="true"
+           SSLCertificateFile="/usr/local/ssl/server.crt" 
+           SSLCertificateKeyFile="/usr/local/ssl/server.pem"
+           clientAuth="false" sslProtocol="TLS"/&gt;
+--&gt;
+</source>
+
+</p>
 
 <p>You will note that the Connector element itself is commented out by default,
 so you will need to remove the comment tags around it.  Then, you can
@@ -318,13 +396,13 @@ values, depending on how you configured your keystore earlier:</p>
         to request a client Certificate, but not fail if one isn't presented.
     </td>
   </tr>
-  <tr><td><code>SSLEngine</code></td>
+  <tr><td><code>SSLEnabled</code></td>
     <td>
       Use this attribute to enable SSL traffic on a connector.
       To turn on SSL handshake/encryption/decryption on a connector
-      set this value to <code>on</code>.
-      The default value is <code>off</code>.
-      When turning this value <code>on</code> you will want to set the 
+      set this value to <code>true</code>.
+      The default value is <code>false</code>.
+      When turning this value <code>true</code> you will want to set the 
       <code>scheme</code> and the <code>secure</code> attributes as well
       to pass the correct <code>request.getScheme()</code> and 
       <code>request.isSecure()</code> values to the servlets