/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you 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 implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License. 
 *  
 */
package org.apache.directory.server.kerberos.kdc;


import java.io.BufferedInputStream;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.PrivilegedAction;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

import org.apache.directory.ldap.client.api.Krb5LoginConfiguration;
import org.apache.directory.server.i18n.I18n;
import org.apache.directory.shared.util.Strings;
import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.GSSName;
import org.ietf.jgss.Oid;


/**
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class KerberosTestUtils
{
    public static char[] getControlDocument( String resource ) throws IOException
    {
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream( resource );

        Reader reader = new InputStreamReader( new BufferedInputStream( is ) );

        CharArrayWriter writer = new CharArrayWriter();

        try
        {
            char[] buf = new char[2048];
            int len = 0;
            while ( len >= 0 )
            {
                len = reader.read( buf );
                if ( len > 0 )
                {
                    writer.write( buf, 0, len );
                }
            }
        }
        finally
        {
            try
            {
                reader.close();
            }
            catch ( IOException ioe )
            {
            }
        }

        char[] isca = writer.toCharArray();
        return isca;
    }


    public static byte[] getBytesFromResource( String resource ) throws IOException
    {
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream( resource );

        BufferedInputStream stream = new BufferedInputStream( is );
        int len = stream.available();
        byte[] bytes = new byte[len];
        stream.read( bytes, 0, len );

        return bytes;
    }


    public static void hexdump( byte[] data )
    {
        hexdump( data, true );
    }


    public static void hexdump( byte[] data, boolean delimit )
    {
        String delimiter = new String( "-------------------------------------------------" );

        if ( delimit )
        {
            System.out.println( delimiter );
        }

        int lineLength = 0;
        for ( int ii = 0; ii < data.length; ii++ )
        {
            System.out.print( byte2hexString( data[ii] ) + " " );
            lineLength++;

            if ( lineLength == 8 )
            {
                System.out.print( "  " );
            }

            if ( lineLength == 16 )
            {
                System.out.println();
                lineLength = 0;
            }
        }

        if ( delimit )
        {
            System.out.println();
            System.out.println( delimiter );
        }
    }

    public static final String[] hex_digit =
        { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };


    public static String byte2hexString( byte x )
    {
        String s = "";
        for ( int ii = 0; ii < 2; ii++ )
        {
            s = hex_digit[( ( ( x ) & 0xff ) & ( 15 << ( ii * 4 ) ) ) >>> ( ii * 4 )] + s;
        }

        return s;
    }


    public static String int2hexString( int x )
    {
        String s = "";
        for ( int ii = 0; ii < 8; ii++ )
        {
            s = hex_digit[( x & ( 15 << ( ii * 4 ) ) ) >>> ( ii * 4 )] + s;
        }

        return s;
    }


    public static String int2binString( int x )
    {
        String s = "";
        for ( int ii = 0; ii < 32; ii++ )
        {
            if ( ( ii > 0 ) && ( ii % 4 == 0 ) )
            {
                s = " " + s;
            }

            s = hex_digit[( x & ( 1 << ii ) ) >>> ii] + s;
        }

        return s;
    }


    public static String long2hexString( long x )
    {
        String s = "";
        for ( int ii = 0; ii < 16; ii++ )
        {
            s = hex_digit[( int ) ( ( x & ( 15L << ( ii * 4 ) ) ) >>> ( ii * 4 ) )] + s;
        }

        return s;
    }


    public static String long2binString( long x )
    {
        String s = "";
        for ( int ii = 0; ii < 64; ii++ )
        {
            if ( ( ii > 0 ) && ( ii % 4 == 0 ) )
            {
                s = " " + s;
            }

            s = hex_digit[( int ) ( ( x & ( 1L << ii ) ) >>> ii )] + s;
        }

        return s;
    }


    public static String byte2hexString( byte[] input )
    {
        return byte2hexString( input, 0, input.length );
    }


    public static String byte2hexString( byte[] input, int offset )
    {
        return byte2hexString( input, offset, input.length );
    }


    public static String byte2hexString( byte[] input, int offset, int length )
    {
        String result = "";
        for ( int ii = 0; ii < length; ii++ )
        {
            if ( ii + offset < input.length )
            {
                result += byte2hexString( input[ii + offset] );
            }
        }

        return result;
    }


    /**
     * Gets the host name for 'localhost' used for Kerberos tests.
     * On Windows 7 and Server 2008 the loopback address 127.0.0.1
     * isn't resolved to localhost by default. In that case we need
     * to use the IP address for the service principal.
     *
     * @return the hostname
     */
    public static String getHostName()
    {
        String hostName;
        try
        {
            InetAddress loopback = InetAddress.getByName( "127.0.0.1" );
            hostName = loopback.getHostName();
        }
        catch ( UnknownHostException e )
        {
            System.err.println( "Can't find loopback address '127.0.0.1', using hostname 'localhost'" );
            hostName = "localhost";
        }
        return hostName;
    }


    /**
     * Obtains a new TGT from KDC.
     * 
     * Possible errors:
     * Bad username:  Client not found in Kerberos database
     * Bad password:  Integrity check on decrypted field failed
     * 
     * @param subject the empty subject
     * @param userName the user name 
     * @param password the password
     * @throws LoginException
     * 
     */
    public static void obtainTGT( Subject subject, String userName, String password ) throws LoginException
    {
        // Use our custom configuration to avoid reliance on external config
        Configuration.setConfiguration( new Krb5LoginConfiguration() );

        // Obtain TGT
        LoginContext lc = new LoginContext( KerberosUdpITest.class.getName(), subject, new
            CallbackHandlerBean( userName, password ) );
        lc.login();
    }

    private static class CallbackHandlerBean implements CallbackHandler
    {
        private String name;
        private String password;


        /**
         * Creates a new instance of CallbackHandlerBean.
         *
         * @param name
         * @param password
         */
        public CallbackHandlerBean( String name, String password )
        {
            this.name = name;
            this.password = password;
        }


        public void handle( Callback[] callbacks ) throws UnsupportedCallbackException, IOException
        {
            for ( Callback callback : callbacks )
            {
                if ( callback instanceof NameCallback )
                {
                    NameCallback nameCallback = ( NameCallback ) callback;
                    nameCallback.setName( name );
                }
                else if ( callback instanceof PasswordCallback )
                {
                    PasswordCallback passwordCallback = ( PasswordCallback ) callback;
                    passwordCallback.setPassword( password.toCharArray() );
                }
                else
                {
                    throw new UnsupportedCallbackException( callback, I18n.err( I18n.ERR_617 ) );
                }
            }
        }
    }


    /**
     * Obtains a Service Ticket from KDC.
     *
     * @param subject the subject, must contain a valid TGT
     * @param userName the user name
     * @param serviceName the service name
     * @param hostName the host name of the service
     * @throws GSSException
     */
    public static void obtainServiceTickets( Subject subject, String userName, String serviceName, String hostName )
        throws GSSException
    {
        ObtainServiceTicketAction action = new ObtainServiceTicketAction( userName, serviceName, hostName );
        GSSException exception = Subject.doAs( subject, action );
        if ( exception != null )
        {
            throw exception;
        }
    }

    private static class ObtainServiceTicketAction implements PrivilegedAction<GSSException>
    {
        private String userName;
        private String serviceName;
        private String hostName;


        public ObtainServiceTicketAction( String userName, String serviceName, String hostName )
        {
            this.userName = userName;
            this.serviceName = serviceName;
            this.hostName = hostName;
        }


        public GSSException run()
        {
            try
            {
                GSSManager manager = GSSManager.getInstance();
                GSSName clientName = manager.createName( userName, GSSName.NT_USER_NAME );
                GSSCredential clientCred = manager.createCredential( clientName,
                    8 * 3600,
                    createKerberosOid(),
                    GSSCredential.INITIATE_ONLY );

                GSSName serverName = manager.createName( serviceName + "@" + hostName, GSSName.NT_HOSTBASED_SERVICE );
                GSSContext context = manager.createContext( serverName,
                    createKerberosOid(),
                    clientCred,
                    GSSContext.DEFAULT_LIFETIME );
                context.requestMutualAuth( true );
                context.requestConf( true );
                context.requestInteg( true );

                context.initSecContext( Strings.EMPTY_BYTES, 0, 0 );

                // byte[] outToken = context.initSecContext( Strings.EMPTY_BYTES, 0, 0 );
                // System.out.println(new BASE64Encoder().encode(outToken));
                context.dispose();

                return null;
            }
            catch ( GSSException gsse )
            {
                return gsse;
            }
        }


        private Oid createKerberosOid() throws GSSException
        {
            return new Oid( "1.2.840.113554.1.2.2" );
        }
    }
}
