You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by tr...@apache.org on 2005/10/13 18:09:28 UTC

svn commit: r320792 - in /directory/network: branches/0.7/src/java/org/apache/mina/io/filter/SSLFilter.java trunk/src/java/org/apache/mina/filter/SSLFilter.java

Author: trustin
Date: Thu Oct 13 09:09:18 2005
New Revision: 320792

URL: http://svn.apache.org/viewcvs?rev=320792&view=rev
Log:
Fixed StartTLS race condition (DIRMINA-85) by providing an attribute key that disables encryption temporarilly.


Modified:
    directory/network/branches/0.7/src/java/org/apache/mina/io/filter/SSLFilter.java
    directory/network/trunk/src/java/org/apache/mina/filter/SSLFilter.java

Modified: directory/network/branches/0.7/src/java/org/apache/mina/io/filter/SSLFilter.java
URL: http://svn.apache.org/viewcvs/directory/network/branches/0.7/src/java/org/apache/mina/io/filter/SSLFilter.java?rev=320792&r1=320791&r2=320792&view=diff
==============================================================================
--- directory/network/branches/0.7/src/java/org/apache/mina/io/filter/SSLFilter.java (original)
+++ directory/network/branches/0.7/src/java/org/apache/mina/io/filter/SSLFilter.java Thu Oct 13 09:09:18 2005
@@ -40,17 +40,53 @@
  * <p>
  * This filter logs debug information in {@link Level#FINEST} using {@link Logger}.
  * 
+ * <h2>Implementing StartTLS</h2>
+ * <p>
+ * You can use {@link #DISABLE_ENCRYPTION_ONCE} attribute to implement StartTLS:
+ * <pre>
+ * public void messageReceived(ProtocolSession session, Object message) {
+ *    if (message instanceof MyStartTLSRequest) {
+ *        // Insert SSLFilter to get ready for handshaking
+ *        IoSession ioSession = ((IoProtocolSession) session).getIoSession();
+ *        ioSession.getFilterChain().addLast(sslFilter);
+ *
+ *        // Disable encryption temporarilly.
+ *        // This attribute will be removed by SSLFilter
+ *        // inside the Session.write() call below.
+ *        session.setAttribute(SSLFilter.DISABLE_ENCRYPTION_ONCE, Boolean.TRUE);
+ *
+ *        // Write StartTLSResponse which won't be encrypted.
+ *        session.write(new MyStartTLSResponse(OK));
+ *        
+ *        // Now DISABLE_ENCRYPTION_ONCE attribute is cleared.
+ *        assert session.getAttribute(SSLFilter.DISABLE_ENCRYPTION_ONCE) == null;
+ *    }
+ * }
+ * </pre>
+ * 
  * @author The Apache Directory Project (dev@directory.apache.org)
  * @version $Rev$, $Date$
  */
 public class SSLFilter extends IoFilterAdapter
 {
     /**
-     * Session attribute key that stores underlying {@link SSLSession}
+     * A session attribute key that stores underlying {@link SSLSession}
      * for each session.
      */
     public static final String SSL_SESSION = SSLFilter.class.getName() + ".SSLSession";
     
+    /**
+     * A session attribute key that makes next one write request bypass
+     * this filter (not encrypting the data).  This is a marker attribute,
+     * which means that you can put whatever as its value. ({@link Boolean#TRUE}
+     * is preferred.)  The attribute is automatically removed from the session
+     * attribute map as soon as {@link IoSession#write(Object)} is invoked,
+     * and therefore should be put again if you want to make more messages
+     * bypass this filter.  This is especially useful when you implement
+     * StartTLS.   
+     */
+    public static final String DISABLE_ENCRYPTION_ONCE = SSLFilter.class.getName() + ".DisableEncryptionOnce";
+    
     private static final String SSL_HANDLER = SSLFilter.class.getName() + ".SSLHandler";
 
     private static final Logger log = Logger.getLogger( SSLFilter.class.getName() );
@@ -300,7 +336,16 @@
 
     public void filterWrite( NextFilter nextFilter, IoSession session, ByteBuffer buf, Object marker ) throws SSLException
     {
-
+        // Don't encrypt the data if encryption is disabled.
+        if( session.getAttribute(DISABLE_ENCRYPTION_ONCE) != null )
+        {
+            // Remove the marker attribute because it is temporary.
+            session.removeAttribute(DISABLE_ENCRYPTION_ONCE);
+            nextFilter.filterWrite( session, buf, marker );
+            return;
+        }
+        
+        // Otherwise, encrypt the buffer.
         SSLHandler handler = createSSLSessionHandler( nextFilter, session );
         if( log.isLoggable( Level.FINEST ) )
         {

Modified: directory/network/trunk/src/java/org/apache/mina/filter/SSLFilter.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/filter/SSLFilter.java?rev=320792&r1=320791&r2=320792&view=diff
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/filter/SSLFilter.java (original)
+++ directory/network/trunk/src/java/org/apache/mina/filter/SSLFilter.java Thu Oct 13 09:09:18 2005
@@ -40,17 +40,53 @@
  * <p>
  * This filter logs debug information in {@link Level#FINEST} using {@link Logger}.
  * 
+ * <h2>Implementing StartTLS</h2>
+ * <p>
+ * You can use {@link #DISABLE_ENCRYPTION_ONCE} attribute to implement StartTLS:
+ * <pre>
+ * public void messageReceived(IoSession session, Object message) {
+ *    if (message instanceof MyStartTLSRequest) {
+ *        // Insert SSLFilter to get ready for handshaking
+ *        session.getFilterChain().addFirst(sslFilter);
+ *
+ *        // Disable encryption temporarilly.
+ *        // This attribute will be removed by SSLFilter
+ *        // inside the Session.write() call below.
+ *        session.setAttribute(SSLFilter.DISABLE_ENCRYPTION_ONCE, Boolean.TRUE);
+ *
+ *        // Write StartTLSResponse which won't be encrypted.
+ *        session.write(new MyStartTLSResponse(OK));
+ *        
+ *        // Now DISABLE_ENCRYPTION_ONCE attribute is cleared.
+ *        assert session.getAttribute(SSLFilter.DISABLE_ENCRYPTION_ONCE) == null;
+ *    }
+ * }
+ * </pre>
+ * 
+ * 
  * @author The Apache Directory Project (dev@directory.apache.org)
  * @version $Rev$, $Date$
  */
 public class SSLFilter extends IoFilterAdapter
 {
     /**
-     * Session attribute key that stores underlying {@link SSLSession}
+     * A session attribute key that stores underlying {@link SSLSession}
      * for each session.
      */
     public static final String SSL_SESSION = SSLFilter.class.getName() + ".SSLSession";
     
+    /**
+     * A session attribute key that makes next one write request bypass
+     * this filter (not encrypting the data).  This is a marker attribute,
+     * which means that you can put whatever as its value. ({@link Boolean#TRUE}
+     * is preferred.)  The attribute is automatically removed from the session
+     * attribute map as soon as {@link IoSession#write(Object)} is invoked,
+     * and therefore should be put again if you want to make more messages
+     * bypass this filter.  This is especially useful when you implement
+     * StartTLS.   
+     */
+    public static final String DISABLE_ENCRYPTION_ONCE = SSLFilter.class.getName() + ".DisableEncryptionOnce";
+    
     private static final String SSL_HANDLER = SSLFilter.class.getName() + ".SSLHandler";
 
     private static final Logger log = Logger.getLogger( SSLFilter.class.getName() );
@@ -295,6 +331,16 @@
 
     public void filterWrite( NextFilter nextFilter, IoSession session, WriteRequest writeRequest ) throws SSLException
     {
+        // Don't encrypt the data if encryption is disabled.
+        if( session.getAttribute(DISABLE_ENCRYPTION_ONCE) != null )
+        {
+            // Remove the marker attribute because it is temporary.
+            session.removeAttribute(DISABLE_ENCRYPTION_ONCE);
+            nextFilter.filterWrite( session, writeRequest );
+            return;
+        }
+        
+        // Otherwise, encrypt the buffer.
         ByteBuffer buf = ( ByteBuffer ) writeRequest.getMessage();
 
         SSLHandler handler = createSSLSessionHandler( nextFilter, session );