Author: markt Date: Thu Apr 9 15:16:42 2015 New Revision: 1672393 URL: http://svn.apache.org/r1672393 Log: Some initial plumbing for SNI. While Java 8 supports SNI, if you want different certs for different hosts then you have to manually parse the incoming TLS bytes to look for the SNI extension. This makes it 'interesting'. The idea at this point is to do it as part of the handshake. This will require moving the SSLEngine init code to processSNI() - that is the next step. Fix some Java 8 Javadoc issues while I was in the area.
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java Modified: tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java?rev=1672393&r1=1672392&r2=1672393&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java Thu Apr 9 15:16:42 2015 @@ -70,12 +70,21 @@ public class Nio2Channel implements Asyn sc.close(); } + + /** + * Close the connection. + * + * @param force Should the underlying socket be forcibly closed? + * + * @throws IOException If closing the secure channel fails. + */ public void close(boolean force) throws IOException { if (isOpen() || force) { close(); } } + /** * Tells whether or not this channel is open. * Modified: tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java?rev=1672393&r1=1672392&r2=1672393&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java Thu Apr 9 15:16:42 2015 @@ -92,9 +92,17 @@ public class NioChannel implements ByteC getIOChannel().close(); } + /** + * Close the connection. + * + * @param force Should the underlying socket be forcibly closed? + * + * @throws IOException If closing the secure channel fails. + */ public void close(boolean force) throws IOException { if (isOpen() || force ) close(); } + /** * Tells whether or not this channel is open. * Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java?rev=1672393&r1=1672392&r2=1672393&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java Thu Apr 9 15:16:42 2015 @@ -50,6 +50,8 @@ public class SecureNio2Channel extends N protected SSLEngine sslEngine; protected final Nio2Endpoint endpoint; + protected boolean sniComplete = false; + protected boolean handshakeComplete; protected HandshakeStatus handshakeStatus; //gets set by handshake @@ -191,7 +193,8 @@ public class SecureNio2Channel extends N * In the event of a positive value coming back, reregister the selection key for the return values interestOps. * * @return int - 0 if hand shake is complete, otherwise it returns a SelectionKey interestOps value - * @throws IOException + * @throws IOException If an I/O error occurs during the handshake or if the + * handshake fails during wrapping or unwrapping */ @Override public int handshake() throws IOException { @@ -199,8 +202,18 @@ public class SecureNio2Channel extends N } protected int handshakeInternal(boolean async) throws IOException { - if (handshakeComplete) + if (handshakeComplete) { return 0; //we have done our initial handshake + } + + if (!sniComplete) { + int sniResult = processSNI(); + if (sniResult == 0) { + sniComplete = true; + } else { + return sniResult; + } + } SSLEngineResult handshake = null; @@ -290,6 +303,17 @@ public class SecureNio2Channel extends N return handshakeComplete ? 0 : handshakeInternal(async); } + + /* + * Peeks at the initial network bytes to determine if the SNI extension is + * present and, if it is, what host name has been requested. Based on the + * provided host name, configure the SSLEngine for this connection. + */ + private int processSNI() { + return 0; + } + + /** * Force a blocking handshake to take place for this key. * This requires that both network and application buffers have been emptied out prior to this call taking place, or a @@ -452,11 +476,6 @@ public class SecureNio2Channel extends N closed = (!netOutBuffer.hasRemaining() && (handshake.getHandshakeStatus() != HandshakeStatus.NEED_WRAP)); } - /** - * Force a close, can throw an IOException - * @param force boolean - * @throws IOException - */ @Override public void close(boolean force) throws IOException { try { Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java?rev=1672393&r1=1672392&r2=1672393&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java Thu Apr 9 15:16:42 2015 @@ -42,6 +42,8 @@ public class SecureNioChannel extends Ni protected SSLEngine sslEngine; + protected boolean sniComplete = false; + protected boolean handshakeComplete = false; protected HandshakeStatus handshakeStatus; //gets set by handshake @@ -88,23 +90,25 @@ public class SecureNioChannel extends Ni //=========================================================================================== // NIO SSL METHODS //=========================================================================================== + /** * Flush the channel. * * @param block Should a blocking write be used? - * @param s - * @param timeout + * @param s The selector to use for blocking, if null then a busy + * write will be initiated + * @param timeout The timeout for this write operation in milliseconds, + * -1 means no timeout * @return <code>true</code> if the network buffer has been flushed out and * is empty else <code>false</code> - * @throws IOException + * @throws IOException If an I/O error occurs during the operation */ @Override - public boolean flush(boolean block, Selector s, long timeout) - throws IOException { + public boolean flush(boolean block, Selector s, long timeout) throws IOException { if (!block) { flush(netOutBuffer); } else { - pool.write(netOutBuffer, this, s, timeout,block); + pool.write(netOutBuffer, this, s, timeout, block); } return !netOutBuffer.hasRemaining(); } @@ -134,11 +138,23 @@ public class SecureNioChannel extends Ni * @param read boolean - true if the underlying channel is readable * @param write boolean - true if the underlying channel is writable * @return int - 0 if hand shake is complete, otherwise it returns a SelectionKey interestOps value - * @throws IOException + * @throws IOException If an I/O error occurs during the handshake or if the + * handshake fails during wrapping or unwrapping */ @Override public int handshake(boolean read, boolean write) throws IOException { - if ( handshakeComplete ) return 0; //we have done our initial handshake + if (handshakeComplete) { + return 0; //we have done our initial handshake + } + + if (!sniComplete) { + int sniResult = processSNI(); + if (sniResult == 0) { + sniComplete = true; + } else { + return sniResult; + } + } if (!flush(netOutBuffer)) return SelectionKey.OP_WRITE; //we still have data to write @@ -202,6 +218,17 @@ public class SecureNioChannel extends Ni return handshakeComplete?0:(SelectionKey.OP_WRITE|SelectionKey.OP_READ); } + + /* + * Peeks at the initial network bytes to determine if the SNI extension is + * present and, if it is, what host name has been requested. Based on the + * provided host name, configure the SSLEngine for this connection. + */ + private int processSNI() { + return 0; + } + + /** * Force a blocking handshake to take place for this key. * This requires that both network and application buffers have been emptied out prior to this call taking place, or a @@ -373,11 +400,7 @@ public class SecureNioChannel extends Ni closed = (!netOutBuffer.hasRemaining() && (handshake.getHandshakeStatus() != HandshakeStatus.NEED_WRAP)); } - /** - * Force a close, can throw an IOException - * @param force boolean - * @throws IOException - */ + @Override public void close(boolean force) throws IOException { try { --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org