package jacorb.security.ssl;

/*
 *        Written for JacORB - a free Java ORB
 *
 *   Copyright (C) 1999  André Benvenuti.
 *
 *   This library is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU Library General Public
 *   License as published by the Free Software Foundation; either
 *   version 2 of the License, or (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *   Library General Public License for more details.
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this library; if not, write to the Free
 *   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/* 
 * We follow the design of socket factories in package javax.net 
 * and javax.net.ssl. Because this package don't the JDK yet we 
 * don't extend its classes, but we are fully compatible.
 *
 * The basic idea is to setup policies related to the sockets being 
 * constructed, in the factory: no special configuration is done in 
 * the code which asks for the sockets.
 * 
 * We will not define an abstract SSLSocketFactory but implement one 
 * using the iSaSiLk packages.
 * The sockets returned to the application have to be subclasses of 
 * java.net.Socket,
 * so we can return sockets of class iaik.security.ssl.Socket.
 * By now we wont directly expose security relevant APIs, but will
 *  probably as we implement Security Objects. 
 * Which factory classes is used will de decide in jacorb.util.Environment 
 * as this is specific to the environment configuration.
 * So the getDefault method could return null if no SSL support at all, 
 * or a factory that encapsulates a particular implementation and take 
 * care of initialising and pass specific parameters. 
 * bnv: just to be sure...
 */

public class SSLServerSocketFactory 
    extends jacorb.util.net.ServerSocketFactory 
{
    private static SSLServerSocketFactory defaultFactory;
    private iaik.security.ssl.SSLServerContext defaultContext;
    private iaik.security.ssl.CipherSuite[] cs;

    public SSLServerSocketFactory() 
    {
	SSLSetup sslSetup = SSLSetup.getDefault ();
	defaultContext = sslSetup.getDefaultSSLServerContext ();
	cs = sslSetup.getCipherSuites();
    }

    /**
     * Returns a server socket which uses all network interfaces on 
     * the host, and is bound to the specified port.
     * Parameters:
     * 	port - the port to listen to
     * Throws:
     * 	java.io.IOException - for networking errors
     */

    public java.net.ServerSocket createServerSocket ( int port )
	throws java.io.IOException
    {
	if ( defaultContext == null ) 
	    throw new java.io.IOException("Cannor support SSL, no default SSL context found!");
	return new iaik.security.ssl.SSLServerSocket ( port, defaultContext );
    }

    /** Returns a server socket which uses all network interfaces 
     * on the host, is bound to a the specified port, and uses the 
     * specified connection backlog. The socket is configured with 
     * the socket options (such as accept timeout) given to this factory.
     * Parameters:
     * 	port - the port to listen to
     * 	backlog - how many connections are queued
     * Throws:
     * 	java.io.IOException - for networking errors
     */

    public java.net.ServerSocket createServerSocket ( int port, int backlog ) 
	throws java.io.IOException
    {
	if ( defaultContext == null ) 
	    throw new java.io.IOException("Cannor support SSL, no default SSL context found!");

	return new iaik.security.ssl.SSLServerSocket ( port, backlog, defaultContext );
    }

    /** 
     * Returns a server socket which uses only the specified network 
     * interface on the local host, is bound to a the specified port, 
     * and uses the specified connection backlog. The socket is 
     * configured with the socket options (such as accept timeout) 
     * given to this factory.
     * Parameters:
     * 	port - the port to listen to
     * 	backlog - how many connections are queued
     * 	ifAddress - the network interface address to use
     * Throws:
     * 	java.io.IOException - for networking errors
     */

    public java.net.ServerSocket createServerSocket ( int port,
						      int backlog,
						      java.net.InetAddress ifAddress
						      )
	throws java.io.IOException	
    {
	if ( defaultContext == null )
	    throw new java.io.IOException("Cannor support SSL, no default SSL context found!");
	return new iaik.security.ssl.SSLServerSocket ( port, backlog, ifAddress, defaultContext );
    }

    /**
     * Returns the default SSL socket factory.
     * If SSL has not been configured for this virtual machine,
     * the factory will be inoperative (reporting instantiation exceptions).
     */

    synchronized public static jacorb.util.net.ServerSocketFactory getDefault()
    {
	if ( defaultFactory == null ) 
	    defaultFactory = new SSLServerSocketFactory ();
	return defaultFactory;
    }

    /**
     * Returns the list of cipher suites which are enabled by 
     * default. Unless a different list is enabled, handshaking 
     * on an SSL connection will use one of these cipher suites.
     * The minimum quality of service for these defaults requires
     * confidentiality protection and server authentication.
     * Returns:
     *	array of the cipher suites enabled by default
     * See Also: 
     */

    public java.lang.String[] getDefaultCipherSuites()
    {
	java.lang.String lst [] = new java.lang.String[ cs.length ];
	for ( int i = 0; i < lst.length; i++ )
	    lst [ i ] = cs[ i ].toString ();
	return lst;
    }

    /**
     * Returns the names of the cipher suites which could be 
     * enabled for use on an SSL connection.
     * Normally, only a subset of these will actually be enabled 
     * by default, since this list may include
     * cipher suites which do not meet quality of service requirements for those defaults.
     * Such cipher suites are useful in specialized applications.
     * Returns:
     * 	an array of cipher suite names
     */

    public java.lang.String[] getSupportedCipherSuites()
    {
	iaik.security.ssl.CipherSuite [] suites = iaik.security.ssl.CipherSuite.getDefault ();
	java.lang.String lst [] = new java.lang.String[ suites.length ];
	for ( int i = 0; i < lst.length; i++ )
	    lst [ i ] = suites[ i ].toString ();
	return lst;
    }

    public static boolean isSSL ( java.net.ServerSocket s )
    { 
	return ( s instanceof iaik.security.ssl.SSLServerSocket); 
    }

    /**
     * Returns a socket layered over an existing socket to a 
     * ServerSocket on the named host, at the given port. This 
     * constructor can be used when tunneling SSL through a proxy. 
     * The host and port refer to the logical destination server. 
     * This socket is configured using the socket options established 
     * for this factory.
     * Parameters:
     *	s - the existing socket
     *	host - the server host
     *	port - the server port
     *	autoClose - close the underlying socket when this socket is closed
     * Throws:
     *	java.io.IOException - if the connection can't be established
     *	java.net.UnknownHostException - if the host is not known
     */

    public java.net.Socket createSocket ( java.net.Socket s,
					  java.lang.String host,
					  int port,
					  boolean autoClose
					  )
	throws java.io.IOException
    {
	// iaik.security.ssl.Socket has no constructor supporting this.
	throw new java.io.IOException ( "Not implemented by this factory" );
    }
}
