Return-Path: Delivered-To: apmail-incubator-directory-cvs-archive@www.apache.org Received: (qmail 71881 invoked from network); 8 Mar 2005 07:34:51 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur-2.apache.org with SMTP; 8 Mar 2005 07:34:51 -0000 Received: (qmail 33109 invoked by uid 500); 8 Mar 2005 07:34:51 -0000 Delivered-To: apmail-incubator-directory-cvs-archive@incubator.apache.org Received: (qmail 33052 invoked by uid 500); 8 Mar 2005 07:34:50 -0000 Mailing-List: contact directory-cvs-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: directory-dev@incubator.apache.org Delivered-To: mailing list directory-cvs@incubator.apache.org Received: (qmail 33038 invoked by uid 99); 8 Mar 2005 07:34:50 -0000 X-ASF-Spam-Status: No, hits=-9.8 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from minotaur.apache.org (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.28) with SMTP; Mon, 07 Mar 2005 23:34:48 -0800 Received: (qmail 71847 invoked by uid 65534); 8 Mar 2005 07:34:47 -0000 Message-ID: <20050308073447.71846.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Mailer: svnmailer-1.0.0-dev Date: Tue, 08 Mar 2005 07:34:47 -0000 Subject: svn commit: r156507 - in incubator/directory/network/mina/trunk: src/examples/org/apache/mina/examples/echoserver/ src/examples/org/apache/mina/examples/echoserver/ssl/ src/java/org/apache/mina/io/filter/ src/test/org/apache/mina/examples/echoserver/ xdocs/ To: directory-cvs@incubator.apache.org From: trustin@apache.org X-Virus-Checked: Checked X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N Author: trustin Date: Mon Mar 7 23:34:43 2005 New Revision: 156507 URL: http://svn.apache.org/viewcvs?view=3Drev&rev=3D156507 Log: Added SSLFilter, its example, and its test. (DIRMINA-11) Added: incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/ssl/ incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/ssl/BogusSSLContextFactory.java (with props) incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/ssl/BogusTrustManagerFactory.java (with props) incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/ssl/SSLServerSocketFactory.java (with props) incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/ssl/SSLSocketFactory.java (with props) incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/ssl/bogus.cert (with props) incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filt= er/SSLByteBufferPool.java (with props) incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filt= er/SSLFilter.java (with props) incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filt= er/SSLHandler.java (with props) Modified: incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/Main.java incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/package.html incubator/directory/network/mina/trunk/src/test/org/apache/mina/example= s/echoserver/Test.java incubator/directory/network/mina/trunk/xdocs/index.xml Modified: incubator/directory/network/mina/trunk/src/examples/org/apache/mi= na/examples/echoserver/Main.java URL: http://svn.apache.org/viewcvs/incubator/directory/network/mina/trunk/s= rc/examples/org/apache/mina/examples/echoserver/Main.java?view=3Ddiff&r1=3D= 156506&r2=3D156507 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/Main.java (original) +++ incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/Main.java Mon Mar 7 23:34:43 2005 @@ -20,20 +20,26 @@ =20 import java.net.InetSocketAddress; =20 +import org.apache.mina.examples.echoserver.ssl.BogusSSLContextFactory; import org.apache.mina.io.IoAcceptor; import org.apache.mina.io.datagram.DatagramAcceptor; import org.apache.mina.io.filter.IoThreadPoolFilter; +import org.apache.mina.io.filter.SSLFilter; import org.apache.mina.io.socket.SocketAcceptor; =20 /** * (Entry point) Echo server *=20 * @author Trustin Lee (trustin@apache.org) - * @version $Rev$, $Date$, + * @version $Rev$, $Date$ */ public class Main { + /** Choose your favorite port number. */ private static final int PORT =3D 8080; + =20 + /** Set this to true if you want to make the server SSL */ + private static final boolean USE_SSL =3D false; =20 public static void main( String[] args ) throws Exception { @@ -47,6 +53,15 @@ // Add thread pool filter // MINA runs in a single thread if you don't add this filter. acceptor.addFilter( Integer.MAX_VALUE, threadPoolFilter ); + + // Add SSL filter if SSL is enabled. + if( USE_SSL ) + { + System.out.println( "SSL is enabled." ); + SSLFilter sslFilter =3D new SSLFilter( BogusSSLContextFactory + .getInstance( true ) ); + acceptor.addFilter( Integer.MAX_VALUE - 1, sslFilter ); + } =20 // Bind acceptor.bind( new InetSocketAddress( PORT ), Modified: incubator/directory/network/mina/trunk/src/examples/org/apache/mi= na/examples/echoserver/package.html URL: http://svn.apache.org/viewcvs/incubator/directory/network/mina/trunk/s= rc/examples/org/apache/mina/examples/echoserver/package.html?view=3Ddiff&r1= =3D156506&r2=3D156507 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/package.html (original) +++ incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/package.html Mon Mar 7 23:34:43 2005 @@ -3,6 +3,6 @@ -Echo server which demonstates low-level I/O layer. +Echo server which demonstates low-level I/O layer and SSL support. Added: incubator/directory/network/mina/trunk/src/examples/org/apache/mina/= examples/echoserver/ssl/BogusSSLContextFactory.java URL: http://svn.apache.org/viewcvs/incubator/directory/network/mina/trunk/s= rc/examples/org/apache/mina/examples/echoserver/ssl/BogusSSLContextFactory.= java?view=3Dauto&rev=3D156507 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/ssl/BogusSSLContextFactory.java (added) +++ incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/ssl/BogusSSLContextFactory.java Mon Mar 7 23:34:43 2005 @@ -0,0 +1,162 @@ +/* + * @(#) $Id$ + * + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli= ed. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.mina.examples.echoserver.ssl; + +import java.io.IOException; +import java.io.InputStream; +import java.security.GeneralSecurityException; +import java.security.KeyStore; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; + +/** + * Factory to create a bougus SSLContext. + * + * @author Per Widerlund (per@minq.se) + * @author Jan Andersson (janne@minq.se) + *=20 + * @version $Rev$, $Date$ + */ +public class BogusSSLContextFactory +{ + + /** + * Protocol to use. + */ + private static final String PROTOCOL =3D "TLS"; + + /** + * Bougus Server certificate keystore file name. + */ + private static final String BOGUS_KEYSTORE =3D "bogus.cert"; + + // NOTE: The keystore was generated using keytool: + // keytool -genkey -alias bogus -keysize 512 -validity 3650 + // -keyalg RSA -dname "CN=3Dbogus.com, OU=3DXXX CA, + // O=3DBogus Inc, L=3DStockholm, S=3DStockholm, C=3DSE" + // -keypass boguspw -storepass boguspw -keystore bogus.cert + + /** + * Bougus keystore password. + */ + private static final char[] BOGUS_PW =3D { 'b', 'o', 'g', 'u', 's', 'p= ', + 'w' }; + + private static SSLContext serverInstance =3D null; + + private static SSLContext clientInstance =3D null; + + /** + * Get SSLContext singleton. + * + * @return SSLContext + * @throws java.security.GeneralSecurityException + * + */ + public static SSLContext getInstance( boolean server ) + throws GeneralSecurityException + { + SSLContext retInstance =3D null; + if( server ) + { + if( serverInstance =3D=3D null ) + { + synchronized( BogusSSLContextFactory.class ) + { + if( serverInstance =3D=3D null ) + { + try + { + serverInstance =3D createBougusServerSSLContex= t(); + } + catch( Exception ioe ) + { + throw new GeneralSecurityException( + "Can't create Server SSLContext:" + io= e ); + } + } + } + } + retInstance =3D serverInstance; + } + else + { + if( clientInstance =3D=3D null ) + { + synchronized( BogusSSLContextFactory.class ) + { + if( clientInstance =3D=3D null ) + { + clientInstance =3D createBougusClientSSLContext(); + } + } + } + retInstance =3D clientInstance; + } + return retInstance; + } + + private static SSLContext createBougusServerSSLContext() + throws GeneralSecurityException, IOException + { + // Create keystore + KeyStore ks =3D KeyStore.getInstance( "JKS" ); + InputStream in =3D null; + try + { + in =3D BogusSSLContextFactory.class + .getResourceAsStream( BOGUS_KEYSTORE ); + ks.load( in, BOGUS_PW ); + } + finally + { + if( in !=3D null ) + { + try + { + in.close(); + } + catch( IOException ignored ) + { + } + } + } + + // Set up key manager factory to use our key store + KeyManagerFactory kmf =3D KeyManagerFactory.getInstance( "SunX509"= ); + kmf.init( ks, BOGUS_PW ); + + // Initialize the SSLContext to work with our key managers. + SSLContext sslContext =3D SSLContext.getInstance( PROTOCOL ); + sslContext.init( kmf.getKeyManagers(), + BogusTrustManagerFactory.X509_MANAGERS, null ); + + return sslContext; + } + + private static SSLContext createBougusClientSSLContext() + throws GeneralSecurityException + { + SSLContext context =3D SSLContext.getInstance( PROTOCOL ); + context.init( null, BogusTrustManagerFactory.X509_MANAGERS, null ); + return context; + } + +} Propchange: incubator/directory/network/mina/trunk/src/examples/org/apache/= mina/examples/echoserver/ssl/BogusSSLContextFactory.java ---------------------------------------------------------------------------= --- svn:keywords =3D HeadURL Id LastChangedBy LastChangedDate LastChangedRe= vision Added: incubator/directory/network/mina/trunk/src/examples/org/apache/mina/= examples/echoserver/ssl/BogusTrustManagerFactory.java URL: http://svn.apache.org/viewcvs/incubator/directory/network/mina/trunk/s= rc/examples/org/apache/mina/examples/echoserver/ssl/BogusTrustManagerFactor= y=2Ejava?view=3Dauto&rev=3D156507 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/ssl/BogusTrustManagerFactory.java (added) +++ incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/ssl/BogusTrustManagerFactory.java Mon Mar 7 23:34:43 2005 @@ -0,0 +1,83 @@ +/* + * @(#) $Id$ + * + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli= ed. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.mina.examples.echoserver.ssl; + +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.ManagerFactoryParameters; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactorySpi; +import javax.net.ssl.X509TrustManager; + +/** + * Bogus trust manager factory. Creates BogusX509TrustManager + * + * @author Per Widerlund (per@minq.se) + * @author Jan Andersson (janne@minq.se) + *=20 + * @version $Rev$, $Date$ + */ +class BogusTrustManagerFactory extends TrustManagerFactorySpi +{ + + static final X509TrustManager X509 =3D new X509TrustManager() + { + public void checkClientTrusted( X509Certificate[] x509Certificates, + String s ) throws CertificateExcept= ion + { + } + + public void checkServerTrusted( X509Certificate[] x509Certificates, + String s ) throws CertificateExcept= ion + { + } + + public X509Certificate[] getAcceptedIssuers() + { + return new X509Certificate[ 0 ]; + } + }; + + static final TrustManager[] X509_MANAGERS =3D new TrustManager[] { X50= 9 }; + + public BogusTrustManagerFactory() + { + } + + protected TrustManager[] engineGetTrustManagers() + { + return X509_MANAGERS; + } + + protected void engineInit( KeyStore keystore ) throws KeyStoreException + { + // noop + } + + protected void engineInit( + ManagerFactoryParameters managerFactoryParam= eters ) + throws InvalidAlgorithmParameterException + { + // noop + } +} Propchange: incubator/directory/network/mina/trunk/src/examples/org/apache/= mina/examples/echoserver/ssl/BogusTrustManagerFactory.java ---------------------------------------------------------------------------= --- svn:keywords =3D HeadURL Id LastChangedBy LastChangedDate LastChangedRe= vision Added: incubator/directory/network/mina/trunk/src/examples/org/apache/mina/= examples/echoserver/ssl/SSLServerSocketFactory.java URL: http://svn.apache.org/viewcvs/incubator/directory/network/mina/trunk/s= rc/examples/org/apache/mina/examples/echoserver/ssl/SSLServerSocketFactory.= java?view=3Dauto&rev=3D156507 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/ssl/SSLServerSocketFactory.java (added) +++ incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/ssl/SSLServerSocketFactory.java Mon Mar 7 23:34:43 2005 @@ -0,0 +1,107 @@ +/* + * @(#) $Id$ + * + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli= ed. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.mina.examples.echoserver.ssl; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.security.GeneralSecurityException; + +import javax.net.ServerSocketFactory; + +/** + * Simple Server Socket factory to create sockets with or without SSL enab= led. + * If SSL enabled a "bougus" SSL Context is used (suitable for test purpos= es) + *=20 + * @version $Rev$, $Date$ + */ +public class SSLServerSocketFactory extends javax.net.ServerSocketFactory +{ + private static boolean sslEnabled =3D false; + + private static javax.net.ServerSocketFactory sslFactory =3D null; + + private static ServerSocketFactory factory =3D null; + + public SSLServerSocketFactory() + { + super(); + } + + public ServerSocket createServerSocket( int port ) throws IOException + { + return new ServerSocket( port ); + } + + public ServerSocket createServerSocket( int port, int backlog ) + throws IOException + { + return new ServerSocket( port, backlog ); + } + + public ServerSocket createServerSocket( int port, int backlog, + InetAddress ifAddress ) + throws IOException + { + return new ServerSocket( port, backlog, ifAddress ); + } + + public static javax.net.ServerSocketFactory getServerSocketFactory() + throws IOException + { + if( isSslEnabled() ) + { + if( sslFactory =3D=3D null ) + { + try + { + sslFactory =3D BogusSSLContextFactory.getInstance( tru= e ) + .getServerSocketFactory(); + } + catch( GeneralSecurityException e ) + { + IOException ioe =3D new IOException( + "could not create SSL socket" ); + ioe.initCause( e ); + throw ioe; + } + } + return sslFactory; + } + else + { + if( factory =3D=3D null ) + { + factory =3D new SSLServerSocketFactory(); + } + return factory; + } + + } + + public static boolean isSslEnabled() + { + return sslEnabled; + } + + public static void setSslEnabled( boolean newSslEnabled ) + { + sslEnabled =3D newSslEnabled; + } +} Propchange: incubator/directory/network/mina/trunk/src/examples/org/apache/= mina/examples/echoserver/ssl/SSLServerSocketFactory.java ---------------------------------------------------------------------------= --- svn:keywords =3D HeadURL Id LastChangedBy LastChangedDate LastChangedRe= vision Added: incubator/directory/network/mina/trunk/src/examples/org/apache/mina/= examples/echoserver/ssl/SSLSocketFactory.java URL: http://svn.apache.org/viewcvs/incubator/directory/network/mina/trunk/s= rc/examples/org/apache/mina/examples/echoserver/ssl/SSLSocketFactory.java?v= iew=3Dauto&rev=3D156507 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/ssl/SSLSocketFactory.java (added) +++ incubator/directory/network/mina/trunk/src/examples/org/apache/mina/exa= mples/echoserver/ssl/SSLSocketFactory.java Mon Mar 7 23:34:43 2005 @@ -0,0 +1,137 @@ +/* + * @(#) $Id$ + * + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli= ed. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.mina.examples.echoserver.ssl; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.security.GeneralSecurityException; + +import javax.net.SocketFactory; + +/** + * Simple Socket factory to create sockets with or without SSL enabled. + * If SSL enabled a "bougus" SSL Context is used (suitable for test purpos= es) + *=20 + * @version $Rev$, $Date$ + */ +public class SSLSocketFactory extends SocketFactory +{ + private static boolean sslEnabled =3D false; + + private static javax.net.ssl.SSLSocketFactory sslFactory =3D null; + + private static javax.net.SocketFactory factory =3D null; + + public SSLSocketFactory() + { + super(); + } + + public Socket createSocket( String arg1, int arg2 ) throws IOException, + UnknownHostException + { + if( isSslEnabled() ) + { + return getSSLFactory().createSocket( arg1, arg2 ); + } + else + { + return new Socket( arg1, arg2 ); + } + } + + public Socket createSocket( String arg1, int arg2, InetAddress arg3, + int arg4 ) throws IOException, + UnknownHostException + { + if( isSslEnabled() ) + { + return getSSLFactory().createSocket( arg1, arg2, arg3, arg4 ); + } + else + { + return new Socket( arg1, arg2, arg3, arg4 ); + } + } + + public Socket createSocket( InetAddress arg1, int arg2 ) + throws IOException + { + if( isSslEnabled() ) + { + return getSSLFactory().createSocket( arg1, arg2 ); + } + else + { + return new Socket( arg1, arg2 ); + } + } + + public Socket createSocket( InetAddress arg1, int arg2, InetAddress ar= g3, + int arg4 ) throws IOException + { + if( isSslEnabled() ) + { + return getSSLFactory().createSocket( arg1, arg2, arg3, arg4 ); + } + else + { + return new Socket( arg1, arg2, arg3, arg4 ); + } + } + + public static javax.net.SocketFactory getSocketFactory() + { + if( factory =3D=3D null ) + { + factory =3D new SSLSocketFactory(); + } + return factory; + } + + private javax.net.ssl.SSLSocketFactory getSSLFactory() + { + if( sslFactory =3D=3D null ) + { + try + { + sslFactory =3D BogusSSLContextFactory.getInstance( false ) + .getSocketFactory(); + } + catch( GeneralSecurityException e ) + { + throw new RuntimeException( "could not create SSL socket",= e ); + } + } + return sslFactory; + } + + public static boolean isSslEnabled() + { + return sslEnabled; + } + + public static void setSslEnabled( boolean newSslEnabled ) + { + sslEnabled =3D newSslEnabled; + } + +} Propchange: incubator/directory/network/mina/trunk/src/examples/org/apache/= mina/examples/echoserver/ssl/SSLSocketFactory.java ---------------------------------------------------------------------------= --- svn:keywords =3D HeadURL Id LastChangedBy LastChangedDate LastChangedRe= vision Added: incubator/directory/network/mina/trunk/src/examples/org/apache/mina/= examples/echoserver/ssl/bogus.cert URL: http://svn.apache.org/viewcvs/incubator/directory/network/mina/trunk/s= rc/examples/org/apache/mina/examples/echoserver/ssl/bogus.cert?view=3Dauto&= rev=3D156507 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D Binary file - no diff available. Propchange: incubator/directory/network/mina/trunk/src/examples/org/apache/= mina/examples/echoserver/ssl/bogus.cert ---------------------------------------------------------------------------= --- svn:mime-type =3D application/octet-stream Added: incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/f= ilter/SSLByteBufferPool.java URL: http://svn.apache.org/viewcvs/incubator/directory/network/mina/trunk/s= rc/java/org/apache/mina/io/filter/SSLByteBufferPool.java?view=3Dauto&rev=3D= 156507 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filt= er/SSLByteBufferPool.java (added) +++ incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filt= er/SSLByteBufferPool.java Mon Mar 7 23:34:43 2005 @@ -0,0 +1,173 @@ +/* + * @(#) $Id$ + * + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli= ed. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.mina.io.filter; + +import java.nio.ByteBuffer; + +import javax.net.ssl.SSLEngine; + +import org.apache.mina.util.Stack; + +/** + * Simple ByteBuffer pool used by SSLHandler. + * ByteBuffers are by default allocated as direct byte buffers. To use non= -direct + * ByteBuffers, set system property mina.sslfilter.directbuffer to false. + * + * @author Jan Andersson (janne@minq.se) + * @version $Rev$, $Date$ + */ +class SSLByteBufferPool +{ + private static final int PACKET_BUFFER_INDEX =3D 0; + + private static final int APPLICATION_BUFFER_INDEX =3D 1; + + private static boolean initiated =3D false; + + private static final String DIRECT_MEMORY_PROP =3D "mina.sslfilter.dir= ectbuffer"; + + private static boolean useDirectAllocatedBuffers =3D true; + + private static int packetBufferSize; + + private static int appBufferSize; + + private static int[] bufferStackSizes; + + private static final Stack[] bufferStacks =3D new Stack[] { new Stack(= ), + new Stack(), = }; + + /** + * Initiate buffer pool and buffer sizes from SSLEngine session. + * + * @param sslEngine SSLEngine + */ + static void initiate( SSLEngine sslEngine ) + { + if( !initiated ) + { + // Use direct allocated memory or not? + String prop =3D System.getProperty( DIRECT_MEMORY_PROP ); + if( prop !=3D null ) + { + useDirectAllocatedBuffers =3D Boolean + .getBoolean( DIRECT_MEMORY_PROP ); + } + // init buffer sizes from SSLEngine + packetBufferSize =3D sslEngine.getSession().getPacketBufferSiz= e(); + appBufferSize =3D sslEngine.getSession().getApplicationBufferS= ize(); + initiateBufferStacks(); + initiated =3D true; + } + } + + /** + * Get bytebuffer with size the size of the largest SSL/TLS packet tha= t may occur + * (as defined by SSLSession). + */ + static ByteBuffer getPacketBuffer() + { + if( !initiated ) + { + throw new IllegalStateException( "Not initialized" ); + } + return get( PACKET_BUFFER_INDEX ); + } + + /** + * Get ByteBuffer with the size of the largest application buffer that= may occur + * (as defined by SSLSession). + */ + static ByteBuffer getApplicationBuffer() + { + if( !initiated ) + { + throw new IllegalStateException( "Not initialized" ); + } + return get( APPLICATION_BUFFER_INDEX ); + } + + /** + * Get the buffer which is capable of the specified size. + */ + private static ByteBuffer get( int idx ) + { + Stack stack =3D bufferStacks[ idx ]; + + ByteBuffer buf; + synchronized( stack ) + { + buf =3D ( ByteBuffer ) stack.pop(); + if( buf =3D=3D null ) + { + buf =3D createBuffer( bufferStackSizes[ idx ] ); + } + } + + buf.clear(); + return buf; + } + + /** + * Returns the specified buffer to buffer pool. + */ + public static void put( ByteBuffer buf ) + { + Stack stack =3D bufferStacks[ getBufferStackIndex( buf.capacity() = ) ]; + synchronized( stack ) + { + stack.push( buf ); + } + } + + private static void initiateBufferStacks() + { + bufferStackSizes =3D new int[ 2 ]; + bufferStackSizes[ PACKET_BUFFER_INDEX ] =3D packetBufferSize; + bufferStackSizes[ APPLICATION_BUFFER_INDEX ] =3D appBufferSize; + } + + private static int getBufferStackIndex( int size ) + { + if( size =3D=3D packetBufferSize ) + return PACKET_BUFFER_INDEX; + if( size =3D=3D appBufferSize ) + return APPLICATION_BUFFER_INDEX; + throw new IllegalArgumentException( "Unknown buffer size: " + size= ); + } + + private static ByteBuffer createBuffer( int capacity ) + { + if( useDirectAllocatedBuffers ) + { + try + { + return ByteBuffer.allocateDirect( capacity ); + } + catch( OutOfMemoryError e ) + { + useDirectAllocatedBuffers =3D false; + System.err + .println( "OutOfMemoryError: No more direct buffer= s available; trying heap buffer instead" ); + } + } + return ByteBuffer.allocate( capacity ); + } + +} Propchange: incubator/directory/network/mina/trunk/src/java/org/apache/mina= /io/filter/SSLByteBufferPool.java ---------------------------------------------------------------------------= --- svn:keywords =3D HeadURL Id LastChangedBy LastChangedDate LastChangedRe= vision Added: incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/f= ilter/SSLFilter.java URL: http://svn.apache.org/viewcvs/incubator/directory/network/mina/trunk/s= rc/java/org/apache/mina/io/filter/SSLFilter.java?view=3Dauto&rev=3D156507 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filt= er/SSLFilter.java (added) +++ incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filt= er/SSLFilter.java Mon Mar 7 23:34:43 2005 @@ -0,0 +1,489 @@ +/* + * @(#) $Id$ + * + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli= ed. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.mina.io.filter; + +import java.lang.reflect.Method; +import java.text.DateFormat; +import java.util.Date; +import java.util.IdentityHashMap; +import java.util.Map; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLHandshakeException; + +import org.apache.mina.common.ByteBuffer; +import org.apache.mina.io.DefaultExceptionMonitor; +import org.apache.mina.io.IoHandler; +import org.apache.mina.io.IoHandlerFilterAdapter; +import org.apache.mina.io.IoSession; + +/** + * An SSL filter that encrypts and decrypts the data exchanged in the sess= ion. + * This filter uses an {@link SSLEngine} which was introduced in Java 5, s= o=20 + * Java version 5 or above is mandatory to use this filter. And please not= e that + * this filter only works for TCP/IP connections. + *

+ * Jan Andersson kindly contributed this filter for the Apache Directory t= eam. + * We thank him a lot for his significant contribution. + *=20 + * @author Jan Andersson (janne@minq.se) + * @author Trustin Lee (trustin@apache.org) + * @version $Rev$, $Date$ + */ +public class SSLFilter extends IoHandlerFilterAdapter +{ + // SSL Context + private SSLContext sslContext; + + // Map used to map SSLHandler objects per session (key is IoSession) + private Map sslSessionHandlerMap =3D new IdentityHashMap(); + + /** debug interface */ + Debug debug =3D null; + + /** + * Creates a new SSL filter using the specified {@link SSLContext}. + */ + public SSLFilter( SSLContext sslContext ) + { + if( sslContext =3D=3D null ) + { + throw new NullPointerException( "sslContext" ); + } + + this.sslContext =3D sslContext; + } + + /** + * Sets the debug message auditter. + */ + public void setDebug( Debug debug ) + { + if( debug =3D=3D null ) + { + throw new NullPointerException( "debug" ); + } + + if( debug =3D=3D Debug.OFF ) + { + this.debug =3D null; + } + else + { + this.debug =3D debug; + } + } + + /** + * Gets the debug message auditter. + */ + public Debug getDebug() + { + if( debug =3D=3D null ) + { + return Debug.OFF; + } + else + { + return debug; + } + } + + // IoHandlerFilter impl. + + public void sessionOpened( IoHandler nextHandler, IoSession session ) + { + nextHandler.sessionOpened( session ); + // Create an SSL handler + createSSLSessionHandler( session ); + } + + public void sessionClosed( IoHandler nextHandler, IoSession session ) + { + SSLHandler sslHandler =3D getSSLSessionHandler( session ); + if( debug !=3D null ) + { + debug.print( "Closed: " + sslHandler ); + } + if( sslHandler !=3D null ) + { + // Start SSL shutdown process + try + { + // shut down + sslHandler.shutdown(); + + // there might be data to write out here? + writeNetBuffer( session, sslHandler ); + } + catch( SSLException ssle ) + { + nextHandler.exceptionCaught( session, ssle ); + } + finally + { + // notify closed session + nextHandler.sessionClosed( session ); + + // release buffers + sslHandler.release(); + removeSSLSessionHandler( session ); + } + } + } + + public void dataRead( IoHandler nextHandler, IoSession session, + ByteBuffer buf ) + { + SSLHandler sslHandler =3D getSSLSessionHandler( session ); + if( sslHandler !=3D null ) + { + synchronized( sslHandler ) + { + try + { + // forward read encrypted data to SSL handler + sslHandler.dataRead( buf.buf() ); + + // Handle data to be forwarded to application or writt= en to net + handleSSLData( nextHandler, session, sslHandler ); + } + catch( SSLException ssle ) + { + if( !sslHandler.isInitialHandshakeComplete() ) + { + SSLException newSSLE =3D new SSLHandshakeException( + "Initial SSL handshake failed." ); + newSSLE.initCause( ssle ); + ssle =3D newSSLE; + } + + nextHandler.exceptionCaught( session, ssle ); + } + } + } + else + { + nextHandler.dataRead( session, buf ); + } + } + + public void dataWritten( IoHandler nextHandler, IoSession session, + Object marker ) + { + nextHandler.dataWritten( session, marker ); + } + + public ByteBuffer filterWrite( IoSession session, ByteBuffer buf ) + { + + SSLHandler sslHandler =3D getSSLSessionHandler( session ); + if( sslHandler !=3D null ) + { + synchronized( sslHandler ) + { + if( sslHandler.isWritingEncryptedData() ) + { + // data already encrypted; simply return buffer + if( debug !=3D null ) + { + debug.print( " already encrypted: " + buf ); + } + return buf; + } + if( sslHandler.isInitialHandshakeComplete() ) + { + // SSL encrypt + try + { + if( debug !=3D null ) + { + debug.print( "encrypt: " + buf ); + } + sslHandler.encrypt( buf.buf() ); + ByteBuffer encryptedBuffer =3D copy( sslHandler + .getOutNetBuffer() ); + //debug("encrypted data: {0}", encryptedBuffer.get= HexDump()); + return encryptedBuffer; + } + catch( SSLException ssle ) + { + throw new RuntimeException( + "Unexpected SSLException.", ssle ); + } + } + } + } + return buf; + } + + // Utiliities + private void handleSSLData( IoHandler nextHandler, IoSession session, + SSLHandler sslHandler ) throws SSLException + { + // First write encrypted data to be written (if any) + writeNetBuffer( session, sslHandler ); + // handle app. data read (if any) + handleAppDataRead( nextHandler, session, sslHandler ); + } + + private void handleAppDataRead( IoHandler nextHandler, IoSession sessi= on, + SSLHandler sslHandler ) + { + if( debug !=3D null ) + { + debug.print( "appBuffer: " + sslHandler.getAppBuffer() ); + } + if( sslHandler.getAppBuffer().hasRemaining() ) + { + // forward read app data + ByteBuffer readBuffer =3D copy( sslHandler.getAppBuffer() ); + if( debug !=3D null ) + { + debug.print( "app data read: " + readBuffer ); + } + //debug("app data: {0}", readBuffer.getHexDump()); + nextHandler.dataRead( session, readBuffer ); + } + } + + private void writeNetBuffer( IoSession session, SSLHandler sslHandler ) + throws SSLException + { + // first check if any net data needed to be writen + if( !sslHandler.getOutNetBuffer().hasRemaining() ) + { + // no; bail out + return; + } + + // write net data + + // set flag that we are writing encrypted data + // (used in filterWrite() above) + synchronized( sslHandler ) + { + sslHandler.setWritingEncryptedData( true ); + } + + try + { + if( debug !=3D null ) + { + debug.print( "write outNetBuffer: " + + sslHandler.getOutNetBuffer() ); + } + ByteBuffer writeBuffer =3D copy( sslHandler.getOutNetBuffer() = ); + if( debug !=3D null ) + { + debug.print( "session write: " + writeBuffer ); + } + //debug("outNetBuffer (after copy): {0}", sslHandler.getOutNet= Buffer()); + session.write( writeBuffer, null ); + + // loop while more writes required to complete handshake + while( sslHandler.needToCompleteInitialHandshake() ) + { + try + { + sslHandler.continueHandshake(); + } + catch( SSLException ssle ) + { + SSLException newSSLE =3D new SSLHandshakeException( + "Initial SSL handshake failed." ); + newSSLE.initCause( ssle ); + throw newSSLE; + } + if( sslHandler.getOutNetBuffer().hasRemaining() ) + { + if( debug !=3D null ) + { + debug.print( "write outNetBuffer2: " + + sslHandler.getOutNetBuffer() ); + } + ByteBuffer writeBuffer2 =3D copy( sslHandler + .getOutNetBuffer() ); + session.write( writeBuffer2, null ); + } + } + } + finally + { + synchronized( sslHandler ) + { + sslHandler.setWritingEncryptedData( false ); + } + } + } + + /** + * Creates a new Mina byte buffer that is a deep copy of the remaining= bytes + * in the given buffer (between index buf.position() and buf.limit()) + * + * @param src the buffer to copy + * @return the new buffer, ready to read from + */ + private ByteBuffer copy( java.nio.ByteBuffer src ) + { + ByteBuffer copy =3D ByteBuffer.allocate( src.remaining() ); + copy.put( src ); + copy.flip(); + return copy; + } + + // Utilities to mainpulate SSLHandler based on IoSession + + private SSLHandler createSSLSessionHandler( IoSession session ) + { + SSLHandler sslHandler =3D new SSLHandler( this, sslContext ); + synchronized( sslSessionHandlerMap ) + { + sslSessionHandlerMap.put( session, sslHandler ); + } + return sslHandler; + } + + private SSLHandler getSSLSessionHandler( IoSession session ) + { + return ( SSLHandler ) sslSessionHandlerMap.get( session ); + } + + private void removeSSLSessionHandler( IoSession session ) + { + synchronized( sslSessionHandlerMap ) + { + sslSessionHandlerMap.remove( session ); + } + } + + /** + * An interface that users can log debug messages from an {@link SSLFi= lter}. + *=20 + * @author Trustin Lee (trustin@apache.org) + * @version $Rev$, $Date$ + */ + public static interface Debug + { + /** + * This will print out the messages to Commons-Logging or stdout. + */ + static final Debug ON =3D new DebugOn(); + =20 + /** + * This will suppress debug messages. + */ + static final Debug OFF =3D new DebugOff(); + + /** + * Prints out the specified debug messages. + */ + void print( String message ); + } + + private static class DebugOn implements Debug + { + private static final Object log; + + private static final Method debugMethod; + + static + { + Object tempLog =3D null; + Method tempDebugMethod =3D null; + + try + { + Class logCls =3D Class + .forName( "org.apache.commons.logging.Log" ); + Class logFactoryCls =3D Class + .forName( "org.apache.commons.logging.LogFactory" = ); + Method getLogMethod =3D logFactoryCls.getMethod( "getLog", + new Class[] { String.class } ); + tempLog =3D getLogMethod.invoke( null, + new Object[] { DefaultExceptionMonitor.class + .getPackage().getName() } ); + tempDebugMethod =3D logCls.getMethod( "debug", + new Class[] { Object.class } ); + } + catch( Exception e ) + { + tempLog =3D null; + tempDebugMethod =3D null; + } + + log =3D tempLog; + debugMethod =3D tempDebugMethod; + } + + private final DateFormat df =3D DateFormat.getDateTimeInstance( + DateFormat.MEDIUM, DateFormat.MEDIUM ); + + private final Date date =3D new Date(); + + public void print( String message ) + { + if( log =3D=3D null ) + { + logToStdOut( message ); + } + else + { + logToCommonsLogging( message ); + } + } + + private void logToCommonsLogging( String message ) + { + try + { + debugMethod.invoke( log, new Object[] { message } ); + } + catch( Exception e ) + { + logToStdOut( message ); + } + } + + private void logToStdOut( String message ) + { + synchronized( System.out ) + { + date.setTime( System.currentTimeMillis() ); + + System.out.print( '[' ); + System.out.print( df.format( date ) ); + System.out.print( "] [" ); + System.out.print( Thread.currentThread().getName() ); + System.out.print( "] " ); + System.out.println( message ); + } + } + } + + private static class DebugOff implements Debug + { + public void print( String message ) + { + // do nothing + } + } +} Propchange: incubator/directory/network/mina/trunk/src/java/org/apache/mina= /io/filter/SSLFilter.java ---------------------------------------------------------------------------= --- svn:keywords =3D HeadURL Id LastChangedBy LastChangedDate LastChangedRe= vision Added: incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/f= ilter/SSLHandler.java URL: http://svn.apache.org/viewcvs/incubator/directory/network/mina/trunk/s= rc/java/org/apache/mina/io/filter/SSLHandler.java?view=3Dauto&rev=3D156507 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filt= er/SSLHandler.java (added) +++ incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filt= er/SSLHandler.java Mon Mar 7 23:34:43 2005 @@ -0,0 +1,491 @@ +/* + * @(#) $Id$ + * + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli= ed. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.mina.io.filter; + +import java.nio.ByteBuffer; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLException; + +/** + * A helper class using the SSLEngine API to decrypt/encrypt data. + *

+ * Each connection has a SSLEngine that is used through the lifetime of th= e connection. + * We allocate byte buffers for use as the outbound and inbound network bu= ffers. + * These buffers handle all of the intermediary data for the SSL connectio= n=2E To make things easy, + * we'll require outNetBuffer be completely flushed before trying to wrap = any more data. + * + * @author Jan Andersson (janne@minq.se) + * @version $Rev$, $Date$ + */ +class SSLHandler +{ + private final SSLFilter parent; + + private SSLEngine sslEngine; + + /** + * Encrypted data from the net + */ + private ByteBuffer inNetBuffer; + + /** + * Encrypted data to be written to the net + */ + private ByteBuffer outNetBuffer; + + /** + * Applicaton cleartext data to be read by application + */ + private ByteBuffer appBuffer; + + /** + * Empty buffer used during initial handshake and close operations + */ + private static ByteBuffer hsBB =3D ByteBuffer.allocate( 0 ); + + /** + * Handshake status + */ + private SSLEngineResult.HandshakeStatus initialHandshakeStatus; + + /** + * Initial handshake complete? + */ + private boolean initialHandshakeComplete; + + /** + * We have received the shutdown request by our caller, and have + * closed our outbound side. + */ + private boolean shutdown =3D false; + + private boolean closed =3D false; + + private boolean isWritingEncryptedData =3D false; + + /** + * Constuctor. + * + * @param sslc + */ + protected SSLHandler( SSLFilter parent, SSLContext sslc ) + { + this.parent =3D parent; + sslEngine =3D sslc.createSSLEngine(); + sslEngine.setUseClientMode( false ); + initialHandshakeStatus =3D SSLEngineResult.HandshakeStatus.NEED_UN= WRAP; + initialHandshakeComplete =3D false; + + SSLByteBufferPool.initiate( sslEngine ); + + appBuffer =3D SSLByteBufferPool.getApplicationBuffer(); + + inNetBuffer =3D SSLByteBufferPool.getPacketBuffer(); + outNetBuffer =3D SSLByteBufferPool.getPacketBuffer(); + outNetBuffer.position( 0 ); + outNetBuffer.limit( 0 ); + } + + /** + * Indicate that we are writing encrypted data. + * Only used as a flag by IoSSLFiler + */ + public void setWritingEncryptedData( boolean flag ) + { + isWritingEncryptedData =3D flag; + } + + /** + * Check we are writing encrypted data. + */ + public boolean isWritingEncryptedData() + { + return isWritingEncryptedData; + } + + /** + * Check if initial handshake is completed. + */ + public boolean isInitialHandshakeComplete() + { + return initialHandshakeComplete; + } + + /** + * Check if there is any need to complete initial handshake. + */ + public boolean needToCompleteInitialHandshake() + { + return ( initialHandshakeStatus =3D=3D SSLEngineResult.HandshakeSt= atus.NEED_WRAP && !closed ); + } + + /** + * Call when data read from net. Will perform inial hanshake or decryp= t provided + * Buffer. + * Decrytpted data reurned by getAppBuffer(), if any. + * + * @param buf buffer to decrypt + * @throws SSLException on errors + */ + public void dataRead( ByteBuffer buf ) throws SSLException + { + // append buf to inNetBuffer + inNetBuffer.put( buf ); + if( !initialHandshakeComplete ) + { + doHandshake(); + } + else + { + doDecrypt(); + } + } + + /** + * Continue initial SSL handshake. + * + * @throws SSLException on errors + */ + public void continueHandshake() throws SSLException + { + if( parent.debug !=3D null ) + { + parent.debug.print( "continueHandshake()" ); + } + doHandshake(); + } + + /** + * Get decrypted application data. + * + * @return buffer with data + */ + public ByteBuffer getAppBuffer() + { + return appBuffer; + } + + /** + * Get encrypted data to be sent. + * + * @return buffer with data + */ + public ByteBuffer getOutNetBuffer() + { + return outNetBuffer; + } + + /** + * Encrypt provided buffer. Encytpted data reurned by getOutNetBuffer(= )=2E + * + * @param buf data to encrypt + * @throws SSLException on errors + */ + public void encrypt( ByteBuffer buf ) throws SSLException + { + doEncrypt( buf ); + } + + /** + * Start SSL shutdown process + * + * @throws SSLException on errors + */ + public void shutdown() throws SSLException + { + doShutdown(); + } + + /** + * Release allocated ByteBuffers. + */ + public void release() + { + SSLByteBufferPool.put( appBuffer ); + SSLByteBufferPool.put( inNetBuffer ); + SSLByteBufferPool.put( outNetBuffer ); + } + + /** + * Decrypt in net buffer. Result is stored in app buffer. + * + * @throws SSLException + */ + private void doDecrypt() throws SSLException + { + + if( !initialHandshakeComplete ) + { + throw new IllegalStateException(); + } + + if( appBuffer.hasRemaining() ) + { + //still app data in buffer!? + throw new IllegalStateException(); + } + + SSLEngineResult.Status status =3D unwrap(); + if( status !=3D SSLEngineResult.Status.OK + && status !=3D SSLEngineResult.Status.CLOSED ) + { + throw new SSLException( "Unexpected SSLEngineResult: " + statu= s ); + } + } + + private void doEncrypt( ByteBuffer src ) throws SSLException + { + if( !initialHandshakeComplete ) + { + throw new IllegalStateException(); + } + + // The data buffer is (must be) empty, we can reuse the entire buf= fer. + outNetBuffer.clear(); + + SSLEngineResult result =3D sslEngine.wrap( src, outNetBuffer ); + + outNetBuffer.flip(); + + switch( result.getStatus() ) + { + + case OK: + if( result.getHandshakeStatus() =3D=3D SSLEngineResult.Handsha= keStatus.NEED_TASK ) + { + doTasks(); + } + break; + + default: + throw new SSLException( "SSLEngine error during data write: " + + result.getStatus() ); + } + } + + /** + * Perform any handshaking processing. + */ + void doHandshake() throws SSLException + { + + if( parent.debug !=3D null ) + { + parent.debug.print( "doHandshake()" ); + } + while( true ) + { + switch( initialHandshakeStatus ) + { + case FINISHED: + if( parent.debug !=3D null ) + { + parent.debug.print( " initialHandshakeStatus=3DFINISHE= D" ); + } + initialHandshakeComplete =3D true; + return; + case NEED_TASK: + if( parent.debug !=3D null ) + { + parent.debug.print( " initialHandshakeStatus=3DNEED_TA= SK" ); + } + initialHandshakeStatus =3D doTasks(); + break; + case NEED_UNWRAP: + // we need more data read + if( parent.debug !=3D null ) + { + parent.debug + .print( " initialHandshakeStatus=3DNEED_UNWRAP= " ); + } + SSLEngineResult.Status status =3D unwrap(); + if( status =3D=3D SSLEngineResult.Status.BUFFER_UNDERFLOW ) + { + // We need more data + return; + } + break; + case NEED_WRAP: + if( parent.debug !=3D null ) + { + parent.debug.print( " initialHandshakeStatus=3DNEED_WR= AP" ); + } + // First make sure that the out buffer is completely empty= . Since we + // cannot call wrap with data left on the buffer + if( outNetBuffer.hasRemaining() ) + { + if( parent.debug !=3D null ) + { + parent.debug.print( " Still data in out buffer!" ); + } + return; + } + outNetBuffer.clear(); + SSLEngineResult result =3D sslEngine.wrap( hsBB, outNetBuf= fer ); + outNetBuffer.flip(); + initialHandshakeStatus =3D result.getHandshakeStatus(); + // return to allow data on out buffer being sent + // TODO: We might want to send more data immidiatley? + break; + //return; + default: // NOT_HANDSHAKING + throw new IllegalStateException( "Invalid Handshaking Stat= e" + + initialHandshakeStatus ); + } + } + } + + SSLEngineResult.Status unwrap() throws SSLException + { + if( parent.debug !=3D null ) + { + parent.debug.print( "unwrap()" ); + } + // Prepare the application buffer to receive decrypted data + appBuffer.clear(); + + SSLEngineResult res; + do + { + // Prepare the net data for reading. + inNetBuffer.flip(); + + if( parent.debug !=3D null ) + { + parent.debug.print( " inNetBuffer: " + inNetBuffer ); + parent.debug.print( " appBuffer: " + appBuffer ); + } + res =3D sslEngine.unwrap( inNetBuffer, appBuffer ); + if( parent.debug !=3D null ) + { + parent.debug.print( "Unwrap res:" + res ); + } + // prepare to be written again + inNetBuffer.compact(); + + /* + * Could check here for a renegotation, but we're only + * doing a simple read/write, and won't have enough state + * transitions to do a complete handshake, so ignore that + * possibility. + */ + switch( res.getStatus() ) + { + + case BUFFER_UNDERFLOW: + case OK: + if( res.getHandshakeStatus() =3D=3D SSLEngineResult.Handsh= akeStatus.NEED_TASK ) + { + doTasks(); + } + break; + case CLOSED: + if( parent.debug !=3D null ) + { + parent.debug.print( "Closed while unwrapping" ); + } + break; + default: + throw new SSLException( "SSLEngine error during data read:= " + + res.getStatus() ); + } + + } + while( ( inNetBuffer.position() !=3D 0 ) + && res.getStatus() !=3D SSLEngineResult.Status.BUFFER_UNDE= RFLOW ); + + // If we are CLOSED, set flag + if( res.getStatus() =3D=3D SSLEngineResult.Status.CLOSED ) + { + closed =3D true; + } + + // prepare app datat to be read + appBuffer.flip(); + + /* + * The status may be: + * OK - Normal operation + * OVERFLOW - Should never happen since the application buffer is + * sized to hold the maximum packet size. + * UNDERFLOW - Need to read more data from the socket. It's normal. + * CLOSED - The other peer closed the socket. Also normal. + */ + initialHandshakeStatus =3D res.getHandshakeStatus(); + return res.getStatus(); + } + + /** + * Do all the outstanding handshake tasks in the current Thread. + */ + private SSLEngineResult.HandshakeStatus doTasks() + { + if( parent.debug !=3D null ) + { + parent.debug.print( " doTasks()" ); + } + + /* + * We could run this in a separate thread, but I don't see the need + * for this when used from IoSSLFilter.Use thread filters in Mina = instead? + */ + Runnable runnable; + while( ( runnable =3D sslEngine.getDelegatedTask() ) !=3D null ) + { + if( parent.debug !=3D null ) + { + parent.debug.print( " doTask: " + runnable ); + } + runnable.run(); + } + if( parent.debug !=3D null ) + { + parent.debug.print( " doTasks(): " + + sslEngine.getHandshakeStatus() ); + } + return sslEngine.getHandshakeStatus(); + } + + /** + * Begin the shutdown process. + */ + void doShutdown() throws SSLException + { + + if( !shutdown ) + { + sslEngine.closeOutbound(); + shutdown =3D true; + } + + // By RFC 2616, we can "fire and forget" our close_notify + // message, so that's what we'll do here. + + outNetBuffer.clear(); + SSLEngineResult result =3D sslEngine.wrap( hsBB, outNetBuffer ); + if( result.getStatus() !=3D SSLEngineResult.Status.CLOSED ) + { + throw new SSLException( "Improper close state: " + result ); + } + outNetBuffer.flip(); + } +} Propchange: incubator/directory/network/mina/trunk/src/java/org/apache/mina= /io/filter/SSLHandler.java ---------------------------------------------------------------------------= --- svn:keywords =3D HeadURL Id LastChangedBy LastChangedDate LastChangedRe= vision Modified: incubator/directory/network/mina/trunk/src/test/org/apache/mina/e= xamples/echoserver/Test.java URL: http://svn.apache.org/viewcvs/incubator/directory/network/mina/trunk/s= rc/test/org/apache/mina/examples/echoserver/Test.java?view=3Ddiff&r1=3D1565= 06&r2=3D156507 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/directory/network/mina/trunk/src/test/org/apache/mina/example= s/echoserver/Test.java (original) +++ incubator/directory/network/mina/trunk/src/test/org/apache/mina/example= s/echoserver/Test.java Mon Mar 7 23:34:43 2005 @@ -6,15 +6,25 @@ import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; import java.net.SocketTimeoutException; +import java.net.UnknownHostException; + +import javax.net.ServerSocketFactory; +import javax.net.SocketFactory; =20 import junit.framework.TestCase; =20 import org.apache.commons.net.EchoTCPClient; import org.apache.commons.net.EchoUDPClient; +import org.apache.mina.examples.echoserver.ssl.BogusSSLContextFactory; +import org.apache.mina.examples.echoserver.ssl.SSLServerSocketFactory; +import org.apache.mina.examples.echoserver.ssl.SSLSocketFactory; import org.apache.mina.io.IoAcceptor; import org.apache.mina.io.datagram.DatagramAcceptor; import org.apache.mina.io.filter.IoThreadPoolFilter; +import org.apache.mina.io.filter.SSLFilter; import org.apache.mina.io.socket.SocketAcceptor; =20 /** @@ -27,7 +37,7 @@ { private int port; =20 - private IoAcceptor acceptor; + protected IoAcceptor acceptor; =20 private IoAcceptor datagramAcceptor; =20 @@ -57,7 +67,7 @@ // Find an availble test port and bind to it. boolean socketBound =3D false; boolean datagramBound =3D false; - =20 + // Let's start from port #1 to detect possible resource leak // because test will fail in port 1-1023 if user run this test // as a normal user. @@ -122,6 +132,69 @@ public void testTCP() throws Exception { EchoTCPClient client =3D new EchoTCPClient(); + testTCP0( client ); + } + + public void testTCPWithSSL() throws Exception + { + // Add an SSL filter + SSLFilter sslFilter =3D new SSLFilter( BogusSSLContextFactory.getI= nstance( true ) ); + sslFilter.setDebug( SSLFilter.Debug.ON ); + acceptor.addFilter( Integer.MAX_VALUE - 1, sslFilter ); + =20 + // Create a commons-net socket factory + SSLSocketFactory.setSslEnabled(true); + SSLServerSocketFactory.setSslEnabled(true); + org.apache.commons.net.SocketFactory factory =3D new org.apache.co= mmons.net.SocketFactory() { + + private SocketFactory f =3D SSLSocketFactory.getSocketFactory(= ); + private ServerSocketFactory ssf =3D SSLServerSocketFactory.get= ServerSocketFactory(); + + public Socket createSocket( String arg0, int arg1 ) throws Unk= nownHostException, IOException + { + return f.createSocket(arg0, arg1); + } + + public Socket createSocket( InetAddress arg0, int arg1 ) throw= s IOException + { + return f.createSocket(arg0, arg1); + } + + public Socket createSocket( String arg0, int arg1, InetAddress= arg2, int arg3 ) throws UnknownHostException, IOException + { + return f.createSocket(arg0, arg1, arg2, arg3); + } + + public Socket createSocket( InetAddress arg0, int arg1, InetAd= dress arg2, int arg3 ) throws IOException + { + return f.createSocket(arg0, arg1, arg2, arg3); + } + + public ServerSocket createServerSocket( int arg0 ) throws IOEx= ception + { + return ssf.createServerSocket(arg0); + } + + public ServerSocket createServerSocket( int arg0, int arg1 ) t= hrows IOException + { + return ssf.createServerSocket(arg0, arg1); + } + + public ServerSocket createServerSocket( int arg0, int arg1, In= etAddress arg2 ) throws IOException + { + return ssf.createServerSocket(arg0, arg1, arg2); + } + =20 + }; + =20 + // Create a echo client with SSL factory and test it. + EchoTCPClient client =3D new EchoTCPClient(); + client.setSocketFactory( factory ); + testTCP0( client ); + } + =20 + private void testTCP0( EchoTCPClient client ) throws Exception + { client.connect( InetAddress.getLocalHost(), port ); client.setSoTimeout( 3000 ); =20 Modified: incubator/directory/network/mina/trunk/xdocs/index.xml URL: http://svn.apache.org/viewcvs/incubator/directory/network/mina/trunk/x= docs/index.xml?view=3Ddiff&r1=3D156506&r2=3D156507 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/directory/network/mina/trunk/xdocs/index.xml (original) +++ incubator/directory/network/mina/trunk/xdocs/index.xml Mon Mar 7 23:34= :43 2005 @@ -47,7 +47,7 @@ Echo server<= /td> - Low-level I/O layer + Low-level I/O layer and SSL support Server