/*
 *  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.shared.kerberos;


import static org.apache.directory.shared.kerberos.codec.types.EncryptionType.DES3_CBC_MD5;
import static org.apache.directory.shared.kerberos.codec.types.EncryptionType.DES3_CBC_SHA1;
import static org.apache.directory.shared.kerberos.codec.types.EncryptionType.DES3_CBC_SHA1_KD;
import static org.apache.directory.shared.kerberos.codec.types.EncryptionType.DES_CBC_CRC;
import static org.apache.directory.shared.kerberos.codec.types.EncryptionType.DES_CBC_MD4;
import static org.apache.directory.shared.kerberos.codec.types.EncryptionType.DES_CBC_MD5;
import static org.apache.directory.shared.kerberos.codec.types.EncryptionType.DES_EDE3_CBC_ENV_OID;
import static org.apache.directory.shared.kerberos.codec.types.EncryptionType.DSAWITHSHA1_CMSOID;
import static org.apache.directory.shared.kerberos.codec.types.EncryptionType.MD5WITHRSAENCRYPTION_CMSOID;
import static org.apache.directory.shared.kerberos.codec.types.EncryptionType.RC2CBC_ENVOID;
import static org.apache.directory.shared.kerberos.codec.types.EncryptionType.RC4_HMAC;
import static org.apache.directory.shared.kerberos.codec.types.EncryptionType.RSAENCRYPTION_ENVOID;
import static org.apache.directory.shared.kerberos.codec.types.EncryptionType.RSAES_OAEP_ENV_OID;
import static org.apache.directory.shared.kerberos.codec.types.EncryptionType.SHA1WITHRSAENCRYPTION_CMSOID;

import java.net.InetAddress;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;

import javax.security.auth.kerberos.KerberosPrincipal;

import org.apache.directory.api.util.Strings;
import org.apache.directory.server.i18n.I18n;
import org.apache.directory.server.kerberos.shared.crypto.encryption.CipherTextHandler;
import org.apache.directory.server.kerberos.shared.crypto.encryption.KeyUsage;
import org.apache.directory.server.kerberos.shared.replay.ReplayCache;
import org.apache.directory.server.kerberos.shared.store.PrincipalStore;
import org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntry;
import org.apache.directory.shared.kerberos.codec.KerberosDecoder;
import org.apache.directory.shared.kerberos.codec.options.ApOptions;
import org.apache.directory.shared.kerberos.codec.types.EncryptionType;
import org.apache.directory.shared.kerberos.components.EncTicketPart;
import org.apache.directory.shared.kerberos.components.EncryptionKey;
import org.apache.directory.shared.kerberos.components.HostAddress;
import org.apache.directory.shared.kerberos.components.PrincipalName;
import org.apache.directory.shared.kerberos.exceptions.ErrorType;
import org.apache.directory.shared.kerberos.exceptions.KerberosException;
import org.apache.directory.shared.kerberos.messages.ApReq;
import org.apache.directory.shared.kerberos.messages.Authenticator;
import org.apache.directory.shared.kerberos.messages.Ticket;


/**
 * An utility class for Kerberos.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class KerberosUtils
{
    /** A constant for integer optional values */
    public static final int NULL = -1;

    /** An empty list of principal names */
    public static final List<String> EMPTY_PRINCIPAL_NAME = new ArrayList<>();

    /** 
     * an order preserved map containing cipher names to the corresponding algorithm 
     * names in the descending order of strength
     */
    private static final Map<String, String> cipherAlgoMap = new LinkedHashMap<>();

    public static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone( "UTC" );

    /** Defines a default date format with a "yyyyMMddHHmmss'Z'" pattern */
    public static final SimpleDateFormat UTC_DATE_FORMAT = new SimpleDateFormat( "yyyyMMddHHmmss'Z'", Locale.ROOT );

    private static final Set<EncryptionType> oldEncTypes = new HashSet<>();

    static
    {
        UTC_DATE_FORMAT.setTimeZone( UTC_TIME_ZONE );

        cipherAlgoMap.put( "rc4", "ArcFourHmac" );
        cipherAlgoMap.put( "aes256", "AES256" );
        cipherAlgoMap.put( "aes128", "AES128" );
        cipherAlgoMap.put( "des3", "DESede" );
        cipherAlgoMap.put( "des", "DES" );

        oldEncTypes.add( DES_CBC_CRC );
        oldEncTypes.add( DES_CBC_MD4 );
        oldEncTypes.add( DES_CBC_MD5 );
        oldEncTypes.add( DES_EDE3_CBC_ENV_OID );
        oldEncTypes.add( DES3_CBC_MD5 );
        oldEncTypes.add( DES3_CBC_SHA1 );
        oldEncTypes.add( DES3_CBC_SHA1_KD );
        oldEncTypes.add( DSAWITHSHA1_CMSOID );
        oldEncTypes.add( MD5WITHRSAENCRYPTION_CMSOID );
        oldEncTypes.add( SHA1WITHRSAENCRYPTION_CMSOID );
        oldEncTypes.add( RC2CBC_ENVOID );
        oldEncTypes.add( RSAENCRYPTION_ENVOID );
        oldEncTypes.add( RSAES_OAEP_ENV_OID );
        oldEncTypes.add( RC4_HMAC );
    }


    /**
     * Parse a KerberosPrincipal instance and return the names. The Principal name
     * is described in RFC 1964 : <br>
     * <br>
     * This name type corresponds to the single-string representation of a<br>
     * Kerberos name.  (Within the MIT Kerberos V5 implementation, such<br>
     * names are parseable with the krb5_parse_name() function.)  The<br>
     * elements included within this name representation are as follows,<br>
     * proceeding from the beginning of the string:<br>
     * <br>
     *  (1) One or more principal name components; if more than one<br>
     *  principal name component is included, the components are<br>
     *  separated by `/`.  Arbitrary octets may be included within<br>
     *  principal name components, with the following constraints and<br>
     *  special considerations:<br>
     * <br>
     *     (1a) Any occurrence of the characters `@` or `/` within a<br>
     *     name component must be immediately preceded by the `\`<br>
     *     quoting character, to prevent interpretation as a component<br>
     *     or realm separator.<br>
     * <br>
     *     (1b) The ASCII newline, tab, backspace, and null characters<br>
     *     may occur directly within the component or may be<br>
     *     represented, respectively, by `\n`, `\t`, `\b`, or `\0`.<br>
     * <br>
     *     (1c) If the `\` quoting character occurs outside the contexts<br>
     *     described in (1a) and (1b) above, the following character is<br>
     *     interpreted literally.  As a special case, this allows the<br>
     *     doubled representation `\\` to represent a single occurrence<br>
     *     of the quoting character.<br>
     * <br>
     *     (1d) An occurrence of the `\` quoting character as the last<br>
     *     character of a component is illegal.<br>
     * <br>
     *  (2) Optionally, a `@` character, signifying that a realm name<br>
     *  immediately follows. If no realm name element is included, the<br>
     *  local realm name is assumed.  The `/` , `:`, and null characters<br>
     *  may not occur within a realm name; the `@`, newline, tab, and<br>
     *  backspace characters may be included using the quoting<br>
     *  conventions described in (1a), (1b), and (1c) above.<br>
     * 
     * @param principal The principal to be parsed
     * @return The names as a List of nameComponent
     * 
     * @throws ParseException if the name is not valid
     */
    public static List<String> getNames( KerberosPrincipal principal ) throws ParseException
    {
        if ( principal == null )
        {
            return EMPTY_PRINCIPAL_NAME;
        }

        String names = principal.getName();

        if ( Strings.isEmpty( names ) )
        {
            // Empty name...
            return EMPTY_PRINCIPAL_NAME;
        }

        return getNames( names );
    }


    /**
     * Parse a PrincipalName and return the names.
     */
    public static List<String> getNames( String principalNames ) throws ParseException
    {
        if ( principalNames == null )
        {
            return EMPTY_PRINCIPAL_NAME;
        }

        List<String> nameComponents = new ArrayList<>();

        // Start the parsing. Another State Machine :)
        char[] chars = principalNames.toCharArray();

        boolean escaped = false;
        boolean done = false;
        int start = 0;
        int pos = 0;

        for ( int i = 0; i < chars.length; i++ )
        {
            pos = i;

            switch ( chars[i] )
            {
                case '\\':
                    escaped = !escaped;
                    break;

                case '/':
                    if ( escaped )
                    {
                        escaped = false;
                    }
                    else
                    {
                        // We have a new name component
                        if ( i - start > 0 )
                        {
                            String nameComponent = new String( chars, start, i - start );
                            nameComponents.add( nameComponent );
                            start = i + 1;
                        }
                        else
                        {
                            throw new ParseException( I18n.err( I18n.ERR_628 ), i );
                        }
                    }

                    break;

                case '@':
                    if ( escaped )
                    {
                        escaped = false;
                    }
                    else
                    {
                        // We have reached the realm : let's get out
                        done = true;
                    }

                    break;

                default:
            }

            if ( done )
            {
                // We have a new name component
                if ( i - start > 0 )
                {
                    String nameComponent = new String( chars, start, i - start );
                    nameComponents.add( nameComponent );
                    start = i + 1;
                }
                else
                {
                    throw new ParseException( I18n.err( I18n.ERR_628 ), i );
                }

                break;
            }
            else if ( i + 1 == chars.length )
            {
                // We have a new name component
                String nameComponent = new String( chars, start, i - start + 1 );
                nameComponents.add( nameComponent );

                break;
            }
        }

        if ( escaped )
        {
            throw new ParseException( I18n.err( I18n.ERR_629 ), pos );
        }

        return nameComponents;
    }


    /**
     * Constructs a KerberosPrincipal from a PrincipalName and an
     * optional realm
     *
     * @param principal The principal name and type
     * @param realm The optional realm
     * 
     * @return A KerberosPrincipal
     */
    public static KerberosPrincipal getKerberosPrincipal( PrincipalName principal, String realm )
    {
        String name = principal.getNameString();

        if ( !Strings.isEmpty( realm ) )
        {
            name += '@' + realm;
        }

        return new KerberosPrincipal( name, principal.getNameType().getValue() );
    }


    /**
     * Get the matching encryption type from the configured types, searching
     * into the requested types. We returns the first we find.
     *
     * @param requestedTypes The client encryption types
     * @param configuredTypes The configured encryption types
     * @return The first matching encryption type.
     */
    public static EncryptionType getBestEncryptionType( Set<EncryptionType> requestedTypes,
        Set<EncryptionType> configuredTypes )
    {
        for ( EncryptionType encryptionType : configuredTypes )
        {
            if ( requestedTypes.contains( encryptionType ) )
            {
                return encryptionType;
            }
        }

        return null;
    }


    /**
     * Build a list of encryptionTypes
     *
     * @param encryptionTypes The encryptionTypes
     * @return A list comma separated of the encryptionTypes
     */
    public static String getEncryptionTypesString( Set<EncryptionType> encryptionTypes )
    {
        StringBuilder sb = new StringBuilder();
        boolean isFirst = true;

        for ( EncryptionType etype : encryptionTypes )
        {
            if ( isFirst )
            {
                isFirst = false;
            }
            else
            {
                sb.append( ", " );
            }

            sb.append( etype );
        }

        return sb.toString();
    }


    public static boolean isKerberosString( byte[] value )
    {
        if ( value == null )
        {
            return false;
        }

        for ( byte b : value )
        {
            if ( ( b < 0x20 ) || ( b > 0x7E ) )
            {
                return false;
            }
        }

        return true;
    }


    public static String getAlgoNameFromEncType( EncryptionType encType )
    {
        String cipherName = Strings.toLowerCaseAscii( encType.getName() );

        for ( String c : cipherAlgoMap.keySet() )
        {
            if ( cipherName.startsWith( c ) )
            {
                return cipherAlgoMap.get( c );
            }
        }

        throw new IllegalArgumentException( "Unknown algorithm name for the encryption type " + encType );
    }


    /**
     * Order a list of EncryptionType in a decreasing strength order
     * 
     * @param etypes The ETypes to order
     * @return A list of ordered ETypes. he strongest is on the left.
     */
    public static Set<EncryptionType> orderEtypesByStrength( Set<EncryptionType> etypes )
    {
        Set<EncryptionType> ordered = new LinkedHashSet<>( etypes.size() );

        for ( String algo : cipherAlgoMap.values() )
        {
            for ( EncryptionType encType : etypes )
            {
                String foundAlgo = getAlgoNameFromEncType( encType );

                if ( algo.equals( foundAlgo ) )
                {
                    ordered.add( encType );
                }
            }
        }

        return ordered;
    }


    /**
     * Get a PrincipalStoreEntry given a principal.  The ErrorType is used to indicate
     * whether any resulting error pertains to a server or client.
     */
    public static PrincipalStoreEntry getEntry( KerberosPrincipal principal, PrincipalStore store, ErrorType errorType )
        throws KerberosException
    {
        PrincipalStoreEntry entry = null;

        try
        {
            entry = store.getPrincipal( principal );
        }
        catch ( Exception e )
        {
            throw new KerberosException( errorType, e );
        }

        if ( entry == null )
        {
            throw new KerberosException( errorType );
        }

        if ( entry.getKeyMap() == null || entry.getKeyMap().isEmpty() )
        {
            throw new KerberosException( ErrorType.KDC_ERR_NULL_KEY );
        }

        return entry;
    }


    /**
         * Verifies an AuthHeader using guidelines from RFC 1510 section A.10., "KRB_AP_REQ verification."
         *
         * @param authHeader
         * @param ticket
         * @param serverKey
         * @param clockSkew
         * @param replayCache
         * @param emptyAddressesAllowed
         * @param clientAddress
         * @param lockBox
         * @param authenticatorKeyUsage
         * @param isValidate
         * @return The authenticator.
         * @throws KerberosException
         */
    public static Authenticator verifyAuthHeader( ApReq authHeader, Ticket ticket, EncryptionKey serverKey,
        long clockSkew, ReplayCache replayCache, boolean emptyAddressesAllowed, InetAddress clientAddress,
        CipherTextHandler lockBox, KeyUsage authenticatorKeyUsage, boolean isValidate ) throws KerberosException
    {
        if ( authHeader.getProtocolVersionNumber() != KerberosConstants.KERBEROS_V5 )
        {
            throw new KerberosException( ErrorType.KRB_AP_ERR_BADVERSION );
        }

        if ( authHeader.getMessageType() != KerberosMessageType.AP_REQ )
        {
            throw new KerberosException( ErrorType.KRB_AP_ERR_MSG_TYPE );
        }

        if ( authHeader.getTicket().getTktVno() != KerberosConstants.KERBEROS_V5 )
        {
            throw new KerberosException( ErrorType.KRB_AP_ERR_BADVERSION );
        }

        EncryptionKey ticketKey = null;

        if ( authHeader.getOption( ApOptions.USE_SESSION_KEY ) )
        {
            ticketKey = authHeader.getTicket().getEncTicketPart().getKey();
        }
        else
        {
            ticketKey = serverKey;
        }

        if ( ticketKey == null )
        {
            // TODO - check server key version number, skvno; requires store
            //            if ( false )
            //            {
            //                throw new KerberosException( ErrorType.KRB_AP_ERR_BADKEYVER );
            //            }

            throw new KerberosException( ErrorType.KRB_AP_ERR_NOKEY );
        }

        byte[] encTicketPartData = lockBox.decrypt( ticketKey, ticket.getEncPart(),
            KeyUsage.AS_OR_TGS_REP_TICKET_WITH_SRVKEY );
        EncTicketPart encPart = KerberosDecoder.decodeEncTicketPart( encTicketPartData );
        ticket.setEncTicketPart( encPart );

        byte[] authenticatorData = lockBox.decrypt( ticket.getEncTicketPart().getKey(), authHeader.getAuthenticator(),
            authenticatorKeyUsage );

        Authenticator authenticator = KerberosDecoder.decodeAuthenticator( authenticatorData );

        if ( !authenticator.getCName().getNameString().equals( ticket.getEncTicketPart().getCName().getNameString() ) )
        {
            throw new KerberosException( ErrorType.KRB_AP_ERR_BADMATCH );
        }

        if ( ticket.getEncTicketPart().getClientAddresses() != null )
        {
            if ( !ticket.getEncTicketPart().getClientAddresses().contains( new HostAddress( clientAddress ) ) )
            {
                throw new KerberosException( ErrorType.KRB_AP_ERR_BADADDR );
            }
        }
        else
        {
            if ( !emptyAddressesAllowed )
            {
                throw new KerberosException( ErrorType.KRB_AP_ERR_BADADDR );
            }
        }

        KerberosPrincipal serverPrincipal = getKerberosPrincipal( ticket.getSName(), ticket.getRealm() );
        KerberosPrincipal clientPrincipal = getKerberosPrincipal( authenticator.getCName(), authenticator.getCRealm() );
        KerberosTime clientTime = authenticator.getCtime();
        int clientMicroSeconds = authenticator.getCusec();

        if ( replayCache != null )
        {
            if ( replayCache.isReplay( serverPrincipal, clientPrincipal, clientTime, clientMicroSeconds ) )
            {
                throw new KerberosException( ErrorType.KRB_AP_ERR_REPEAT );
            }

            replayCache.save( serverPrincipal, clientPrincipal, clientTime, clientMicroSeconds );
        }

        if ( !authenticator.getCtime().isInClockSkew( clockSkew ) )
        {
            throw new KerberosException( ErrorType.KRB_AP_ERR_SKEW );
        }

        /*
         * "The server computes the age of the ticket: local (server) time minus
         * the starttime inside the Ticket.  If the starttime is later than the
         * current time by more than the allowable clock skew, or if the INVALID
         * flag is set in the ticket, the KRB_AP_ERR_TKT_NYV error is returned."
         */
        KerberosTime startTime = ( ticket.getEncTicketPart().getStartTime() != null ) ? ticket.getEncTicketPart()
            .getStartTime() : ticket.getEncTicketPart().getAuthTime();

        KerberosTime now = new KerberosTime();
        boolean isValidStartTime = startTime.lessThan( now );

        if ( !isValidStartTime || ( ticket.getEncTicketPart().getFlags().isInvalid() && !isValidate ) )
        {
            // it hasn't yet become valid
            throw new KerberosException( ErrorType.KRB_AP_ERR_TKT_NYV );
        }

        // TODO - doesn't take into account skew
        if ( !ticket.getEncTicketPart().getEndTime().greaterThan( now ) )
        {
            throw new KerberosException( ErrorType.KRB_AP_ERR_TKT_EXPIRED );
        }

        authHeader.getApOptions().set( ApOptions.MUTUAL_REQUIRED );

        return authenticator;
    }


    /**
     * checks if the given encryption type is *new* (ref sec#3.1.3 of rfc4120)
     *
     * @param eType the encryption type
     * @return true if the encryption type is new, false otherwise
     */
    public static boolean isNewEncryptionType( EncryptionType eType )
    {
        return !oldEncTypes.contains( eType );
    }

    /**
     * Verifies an AuthHeader using guidelines from RFC 1510 section A.10., "KRB_AP_REQ verification."
     *
     * @param authHeader
     * @param ticket
     * @param serverKey
     * @param clockSkew
     * @param replayCache
     * @param emptyAddressesAllowed
     * @param clientAddress
     * @param lockBox
     * @param authenticatorKeyUsage
     * @param isValidate
     * @return The authenticator.
     * @throws KerberosException
     *
    public static Authenticator verifyAuthHeader( ApplicationRequest authHeader, Ticket ticket, EncryptionKey serverKey,
        long clockSkew, ReplayCache replayCache, boolean emptyAddressesAllowed, InetAddress clientAddress,
        CipherTextHandler lockBox, KeyUsage authenticatorKeyUsage, boolean isValidate ) throws KerberosException
    {
        if ( authHeader.getProtocolVersionNumber() != KerberosConstants.KERBEROS_V5 )
        {
            throw new KerberosException( ErrorType.KRB_AP_ERR_BADVERSION );
        }

        if ( authHeader.getMessageType() != KerberosMessageType.AP_REQ )
        {
            throw new KerberosException( ErrorType.KRB_AP_ERR_MSG_TYPE );
        }

        if ( authHeader.getTicket().getTktVno() != KerberosConstants.KERBEROS_V5 )
        {
            throw new KerberosException( ErrorType.KRB_AP_ERR_BADVERSION );
        }

        EncryptionKey ticketKey = null;

        if ( authHeader.getOption( ApOptions.USE_SESSION_KEY ) )
        {
            ticketKey = authHeader.getTicket().getEncTicketPart().getSessionKey();
        }
        else
        {
            ticketKey = serverKey;
        }

        if ( ticketKey == null )
        {
            // TODO - check server key version number, skvno; requires store
            if ( false )
            {
                throw new KerberosException( ErrorType.KRB_AP_ERR_BADKEYVER );
            }

            throw new KerberosException( ErrorType.KRB_AP_ERR_NOKEY );
        }

        EncTicketPart encPart = ( EncTicketPart ) lockBox.unseal( EncTicketPart.class, ticketKey, ticket.getEncPart(),
            KeyUsage.NUMBER2 );
        ticket.setEncTicketPart( encPart );

        Authenticator authenticator = ( Authenticator ) lockBox.unseal( Authenticator.class, ticket.getEncTicketPart().getSessionKey(),
            authHeader.getEncPart(), authenticatorKeyUsage );

        if ( !authenticator.getClientPrincipal().getName().equals( ticket.getEncTicketPart().getClientPrincipal().getName() ) )
        {
            throw new KerberosException( ErrorType.KRB_AP_ERR_BADMATCH );
        }

        if ( ticket.getEncTicketPart().getClientAddresses() != null )
        {
            if ( !ticket.getEncTicketPart().getClientAddresses().contains( new HostAddress( clientAddress ) ) )
            {
                throw new KerberosException( ErrorType.KRB_AP_ERR_BADADDR );
            }
        }
        else
        {
            if ( !emptyAddressesAllowed )
            {
                throw new KerberosException( ErrorType.KRB_AP_ERR_BADADDR );
            }
        }

        KerberosPrincipal serverPrincipal = ticket.getServerPrincipal();
        KerberosPrincipal clientPrincipal = authenticator.getClientPrincipal();
        KerberosTime clientTime = authenticator.getClientTime();
        int clientMicroSeconds = authenticator.getClientMicroSecond();

        if ( replayCache.isReplay( serverPrincipal, clientPrincipal, clientTime, clientMicroSeconds ) )
        {
            throw new KerberosException( ErrorType.KRB_AP_ERR_REPEAT );
        }

        replayCache.save( serverPrincipal, clientPrincipal, clientTime, clientMicroSeconds );

        if ( !authenticator.getClientTime().isInClockSkew( clockSkew ) )
        {
            throw new KerberosException( ErrorType.KRB_AP_ERR_SKEW );
        }

        /*
         * "The server computes the age of the ticket: local (server) time minus
         * the starttime inside the Ticket.  If the starttime is later than the
         * current time by more than the allowable clock skew, or if the INVALID
         * flag is set in the ticket, the KRB_AP_ERR_TKT_NYV error is returned."
         *
        KerberosTime startTime = ( ticket.getEncTicketPart().getStartTime() != null ) ? ticket.getEncTicketPart().getStartTime() : ticket.getEncTicketPart().getAuthTime();

        KerberosTime now = new KerberosTime();
        boolean isValidStartTime = startTime.lessThan( now );

        if ( !isValidStartTime || ( ticket.getEncTicketPart().getFlags().isInvalid() && !isValidate ) )
        {
            // it hasn't yet become valid
            throw new KerberosException( ErrorType.KRB_AP_ERR_TKT_NYV );
        }

        // TODO - doesn't take into account skew
        if ( !ticket.getEncTicketPart().getEndTime().greaterThan( now ) )
        {
            throw new KerberosException( ErrorType.KRB_AP_ERR_TKT_EXPIRED );
        }

        authHeader.setOption( ApOptions.MUTUAL_REQUIRED );

        return authenticator;
    }*/
}
