org.apache.avalon.cornerstone.blocks.sockets
Class TLSSocketFactory

java.lang.Object
  extended by org.apache.avalon.framework.logger.AbstractLogEnabled
      extended by org.apache.avalon.cornerstone.blocks.sockets.AbstractTLSSocketFactory
          extended by org.apache.avalon.cornerstone.blocks.sockets.TLSSocketFactory
All Implemented Interfaces:
org.apache.avalon.cornerstone.services.sockets.SocketFactory, org.apache.avalon.framework.activity.Initializable, org.apache.avalon.framework.configuration.Configurable, org.apache.avalon.framework.context.Contextualizable, org.apache.avalon.framework.logger.LogEnabled

public class TLSSocketFactory
extends AbstractTLSSocketFactory
implements org.apache.avalon.cornerstone.services.sockets.SocketFactory, org.apache.avalon.framework.context.Contextualizable, org.apache.avalon.framework.configuration.Configurable, org.apache.avalon.framework.activity.Initializable

Manufactures TLS client sockets. Configuration element inside a SocketManager would look like:

  <factory name="secure"
            class="org.apache.avalon.cornerstone.blocks.sockets.TLSSocketFactory" >
   <ssl-factory /> <!-- see SSLFactoryBuilder -->
   <timeout> 0 </timeout>
   <!-- if the value is greater than zero, a read() call on the
           InputStream associated with this Socket will block for only this
           amount of time in milliseconds. Default value is 0. -->
   <verify-server-identity>true|false</verify-server-identity>
   <!-- whether or not the server identity should be verified.
           Defaults to false. -->
 </factory>
 

Server identity verification currently includes only comparing the certificate Common Name received with the host name in the passed address. Identity verification requires that SSL handshake is completed for the socket, so it takes longer to get a verified socket (and won't play well with non-blocking application like SEDA).

Another thing to keep in mind when using identity verification is that InetAddress objects for the remote hosts should be built using InetAddress.getByName(java.lang.String) with the host name (matching the certificate CN) as the argument. Failure to do so may cause relatively costly DNS lookups and false rejections caused by inconsistencies between forward and reverse resolution.

Author:
Peter Donald, Federico Barbieri, Charles Benett, Harish Prabandham, Costin Manolache, Craig McClanahan, Andrei Ivanov, Greg Steuck

Field Summary
private  javax.net.ssl.SSLSocketFactory m_factory
           
private  boolean m_verifyServerIdentity
           
 
Fields inherited from class org.apache.avalon.cornerstone.blocks.sockets.AbstractTLSSocketFactory
m_socketTimeOut
 
Constructor Summary
TLSSocketFactory()
           
 
Method Summary
private  java.lang.StringBuffer bytesToString(byte[] data)
           
 void configure(org.apache.avalon.framework.configuration.Configuration configuration)
          Configures the factory.
 java.net.Socket createSocket(java.net.InetAddress address, int port)
          Creates a socket connected to the specified remote address.
 java.net.Socket createSocket(java.net.InetAddress address, int port, java.net.InetAddress localAddress, int localPort)
          Creates a socket and connected to the specified remote address originating from specified local address.
private  java.lang.String getCN(java.lang.String DN)
          Extracts the Common Name from the given Distinguished Name.
private  java.net.Socket initSocket(java.net.Socket socket)
          Performs the unconditional part of socket initialization that applies to all Sockets.
private  javax.net.ssl.SSLSocket sslWrap(java.net.Socket bareSocket, java.net.InetAddress address, int port)
          Wraps an ssl socket over an existing socket and compares the host name from the address to the common name in the server certificate.
protected  void visitBuilder(SSLFactoryBuilder builder)
          The child factories have to use an instance of SSLFactoryBuilder to obtain their factories.
 
Methods inherited from class org.apache.avalon.cornerstone.blocks.sockets.AbstractTLSSocketFactory
contextualize, initialize
 
Methods inherited from class org.apache.avalon.framework.logger.AbstractLogEnabled
enableLogging, getLogger, setupLogger, setupLogger, setupLogger
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 
Methods inherited from interface org.apache.avalon.framework.context.Contextualizable
contextualize
 
Methods inherited from interface org.apache.avalon.framework.activity.Initializable
initialize
 

Field Detail

m_factory

private javax.net.ssl.SSLSocketFactory m_factory

m_verifyServerIdentity

private boolean m_verifyServerIdentity
Constructor Detail

TLSSocketFactory

public TLSSocketFactory()
Method Detail

configure

public void configure(org.apache.avalon.framework.configuration.Configuration configuration)
               throws org.apache.avalon.framework.configuration.ConfigurationException
Configures the factory.

Specified by:
configure in interface org.apache.avalon.framework.configuration.Configurable
Overrides:
configure in class AbstractTLSSocketFactory
Parameters:
configuration - the Configuration
Throws:
org.apache.avalon.framework.configuration.ConfigurationException - if an error occurs

visitBuilder

protected void visitBuilder(SSLFactoryBuilder builder)
Description copied from class: AbstractTLSSocketFactory
The child factories have to use an instance of SSLFactoryBuilder to obtain their factories. So they are given an instance when it's ready. Another alternative was to have the SSLFactoryBuilder export buildContext method, but that would mean SSLContext which is deep in Sun guts will be aired in 3-4 classes instead of 1.

Specified by:
visitBuilder in class AbstractTLSSocketFactory

initSocket

private java.net.Socket initSocket(java.net.Socket socket)
                            throws java.io.IOException
Performs the unconditional part of socket initialization that applies to all Sockets.

Throws:
java.io.IOException

sslWrap

private javax.net.ssl.SSLSocket sslWrap(java.net.Socket bareSocket,
                                        java.net.InetAddress address,
                                        int port)
                                 throws java.io.IOException
Wraps an ssl socket over an existing socket and compares the host name from the address to the common name in the server certificate.

Parameters:
bareSocket - plain socket connected to the server
address - destination of the bareSocket
port - destination of the bareSocket
Returns:
SSL socket wrapped around original socket with server identity verified
Throws:
java.io.IOException

bytesToString

private java.lang.StringBuffer bytesToString(byte[] data)

getCN

private java.lang.String getCN(java.lang.String DN)
Extracts the Common Name from the given Distinguished Name. Normally CN is the first part of the DN. If you know of a more direct way to determine the CN, please let us know.

Returns:
the common name or null if DN is malformed

createSocket

public java.net.Socket createSocket(java.net.InetAddress address,
                                    int port)
                             throws java.io.IOException
Creates a socket connected to the specified remote address.

Specified by:
createSocket in interface org.apache.avalon.cornerstone.services.sockets.SocketFactory
Parameters:
address - the remote address
port - the remote port
Returns:
the socket
Throws:
java.io.IOException - if an error occurs

createSocket

public java.net.Socket createSocket(java.net.InetAddress address,
                                    int port,
                                    java.net.InetAddress localAddress,
                                    int localPort)
                             throws java.io.IOException
Creates a socket and connected to the specified remote address originating from specified local address.

Specified by:
createSocket in interface org.apache.avalon.cornerstone.services.sockets.SocketFactory
Parameters:
address - the remote address
port - the remote port
localAddress - the local address
localPort - the local port
Returns:
the socket
Throws:
java.io.IOException - if an error occurs