package jacorb.security.level2;

import java.io.*;
import java.net.*;
import java.util.*;

import java.security.*;
import java.security.cert.*;

import org.omg.SecurityLevel2.*;
import org.omg.Security.*;

import jacorb.util.Environment;

import jacorb.security.util.*;

/**
 * PrincipalAuthenticatorImpl
 * 
 * This simple authenticator just retrieves X.509v3 certificates
 * from a Java key store
 *
 * @author Gerald Brose
 * $Id: PrincipalAuthenticatorImpl.java,v 1.8 2000/09/18 13:54:59 noffke Exp $
 */

public class PrincipalAuthenticatorImpl
    extends jacorb.orb.LocalityConstrainedObject
    implements org.omg.SecurityLevel2.PrincipalAuthenticator
{  
    private org.omg.CORBA.ORB orb = null;
    private LoginData loginData = null;
    private KeyStore keyStore = null;

    private SecAttributeManager attrib_mgr = null;
    
    public PrincipalAuthenticatorImpl(org.omg.CORBA.ORB orb)
    {
    	this.orb = orb;

        loginData = new LoginData();
    	loginData.keyStoreLocation = Environment.keyStore();
        loginData.storePassphrase = 
            Environment.getProperty("jacorb.security.keystore_password");
        attrib_mgr = SecAttributeManager.getInstance();
    }  

    public int[] get_supported_authen_methods(java.lang.String mechanism)
    {
	return new int[]{0};
    }

    public AuthenticationStatus authenticate(int method, 
                                             String mechanism, 
                                             String security_name, //user name
                                             byte[] auth_data, //  passwd
                                             SecAttribute[] privileges, 
                                             CredentialsHolder creds, 
                                             OpaqueHolder continuation_data, 
                                             OpaqueHolder auth_specific_data
                                             )
    {
	jacorb.util.Debug.output(3,"starting authentication");
	try 
	{	
	    registerProvider();

            loginData.alias = security_name;

            if ( auth_data == null )
            {
                loginData.password = null;
            }
            else
            {
                loginData.password = new String( auth_data );
            }

            //            LoginWindow lw = null; // for user login
//              if (( loginData.keyStoreLocation == null ) || 
//                  ( loginData.storePassphrase == null ) ||
//                  ( loginData.alias == null ) || 
//                  ( loginData.password == null ))
//              {
//                     lw = new LoginWindow( 
//                                        "Login", 
//                                        loginData,
//                                        loginData.keyStoreLocation,
//                                        loginData.storePassphrase,
//                                        loginData.alias,
//                                        loginData.password );
//              }
//              lw.finalize();


            try
            {
              if ( loginData.keyStoreLocation == null ) 
              {
                  System.out.print("Please enter key store file name: ");
                  loginData.keyStoreLocation = (new BufferedReader(new InputStreamReader(System.in))).readLine();
              }

              if ( loginData.storePassphrase == null ) 
              {
                  System.out.print("Please enter store pass phrase: ");
                  loginData.storePassphrase = (new BufferedReader(new InputStreamReader(System.in))).readLine();
              }

              if ( loginData.alias == null ) 
              {
                  System.out.print("Please enter alias  name: ");
                  loginData.alias = (new BufferedReader(new InputStreamReader(System.in))).readLine();
              }

              if ( loginData.password == null ) 
              {
                  System.out.print("Please enter password: ");
                  loginData.password = (new BufferedReader(new InputStreamReader(System.in))).readLine();
              }
            }
            catch( Exception e )
            {}
              

            if (( loginData.keyStoreLocation == null ) || 
                ( loginData.storePassphrase == null ) ||
                ( loginData.alias == null ) || 
                ( loginData.password == null ))
            {
                return AuthenticationStatus.SecAuthFailure;
            }

            keyStore = KeyStoreUtil.getKeyStore (loginData.keyStoreLocation, 
                                                 loginData.storePassphrase.toCharArray());

            X509Certificate[] cert_chain = (X509Certificate[]) 
                keyStore.getCertificateChain( loginData.alias );

            PrivateKey priv_key = (PrivateKey) 
                keyStore.getKey ( loginData.alias, 
                                  loginData.password.toCharArray() );

            KeyAndCert k_a_c = new KeyAndCert( priv_key, cert_chain );

            AttributeType type = new AttributeType
                ( new ExtensibleFamily( (short) 0,
                                        (short) 1 ),
                  AccessId.value );


            //only considering AccessId attributes
            for( int i = 0; i < privileges.length; i++ )
            {
                if( privileges[i].attribute_type.attribute_family.family_definer != 0 ||
                    privileges[i].attribute_type.attribute_family.family != 1 ||
                    privileges[i].attribute_type.attribute_type != AccessId.value)
                {
                    throw new RuntimeException("Cannot handle security attribute.");
                }
                privileges[i]  = attrib_mgr.createCertAttribute( k_a_c,
                                                                 type );
            }

        
            CredentialsImpl credsImpl = 
                new CredentialsImpl( privileges,
                                     AuthenticationStatus.SecAuthSuccess,
                                     InvocationCredentialsType.SecOwnCredentials);

            credsImpl.accepting_options_supported( Environment.supportedBySSL() );
            credsImpl.accepting_options_required( Environment.requiredBySSL() );
            credsImpl.invocation_options_supported( Environment.supportedBySSL() );
            credsImpl.invocation_options_required( Environment.requiredBySSL() );

            creds.value = credsImpl;

            jacorb.util.Debug.output(3,"authentication succeeded");

            return AuthenticationStatus.SecAuthSuccess;
	}
	catch (Exception e) 
	{
	    jacorb.util.Debug.output(2,e);

	    return org.omg.Security.AuthenticationStatus.SecAuthFailure;
	}
    }

    /** 
     * not implemented
     */
  
    public AuthenticationStatus continue_authentication(
							byte[] response_data, 
							Credentials creds, 
							OpaqueHolder continuation_data, 
							OpaqueHolder auth_specific_data)
    {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }


    private void registerProvider()
    {
        iaik.security.provider.IAIK.addAsProvider();

        jacorb.util.Debug.output(3, "added Provider IAIK" );
    }

    public KeyStore getKeyStore()
    {
        return keyStore;
    }

    public void close()
    {
        jacorb.util.Debug.output(3, "PrincipalAuthenticator closing." );
        keyStore = null;
        attrib_mgr = null;
        java.security.Security.removeProvider( "iaik.security.provider.IAIK" );
    }

    public void finalize()
    { 
        close();
    }

}




