/*
 * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 *
 *  (C) Copyright IBM Corp. 1999 All Rights Reserved.
 *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
 */

package sun.security.krb5;

import sun.security.krb5.internal.*;
import sun.security.krb5.internal.crypto.*;
import sun.security.krb5.internal.rcache.*;
import java.net.InetAddress;
import sun.security.util.*;
import java.io.IOException;

/**
 * This class encapsulates a KRB-AP-REQ that a client sends to a
 * server for authentication.
 */
public class KrbApReq {

    private byte[] obuf;
    private KerberosTime ctime;
    private int cusec;
    private Authenticator authenticator;
    private Credentials creds;
    private APReq apReqMessg;

    private static CacheTable table = new CacheTable();
    private static boolean DEBUG = Krb5.DEBUG;

    // default is address-less tickets
    private boolean KDC_EMPTY_ADDRESSES_ALLOWED = true;

    /**
     * Contructs a AP-REQ message to send to the peer.
     * @param tgsCred the <code>Credentials</code> to be used to construct the
     *          AP Request  protocol message.
     * @param mutualRequired Whether mutual authentication is required
     * @param useSubkey Whether the subkey is to be used to protect this
     *        specific application session. If this is not set then the
     *        session key from the ticket will be used.
     * @throws KrbException for any Kerberos protocol specific error
     * @throws IOException for any IO related errors
     *          (e.g. socket operations)
     */
     /*
     // Not Used
    public KrbApReq(Credentials tgsCred,
                    boolean mutualRequired,
                    boolean useSubKey,
                    boolean useSeqNumber) throws Asn1Exception,
                    KrbCryptoException, KrbException, IOException {

        this(tgsCred, mutualRequired, useSubKey, useSeqNumber, null);
    }
*/

    /**
     * Contructs a AP-REQ message to send to the peer.
     * @param tgsCred the <code>Credentials</code> to be used to construct the
     *          AP Request  protocol message.
     * @param mutualRequired Whether mutual authentication is required
     * @param useSubkey Whether the subkey is to be used to protect this
     *        specific application session. If this is not set then the
     *        session key from the ticket will be used.
     * @param checksum checksum of the the application data that accompanies
     *        the KRB_AP_REQ.
     * @throws KrbException for any Kerberos protocol specific error
     * @throws IOException for any IO related errors
     *          (e.g. socket operations)
     */
     // Used in InitSecContextToken
    public KrbApReq(Credentials tgsCred,
                    boolean mutualRequired,
                    boolean useSubKey,
                    boolean useSeqNumber,
                    Checksum cksum) throws Asn1Exception,
                    KrbCryptoException, KrbException, IOException  {

        APOptions apOptions = (mutualRequired?
                               new APOptions(Krb5.AP_OPTS_MUTUAL_REQUIRED):
                               new APOptions());
        if (DEBUG)
            System.out.println(">>> KrbApReq: APOptions are " + apOptions);

        EncryptionKey subKey = (useSubKey?
                                new EncryptionKey(tgsCred.getSessionKey()):
                                null);

        SeqNumber seqNum = new LocalSeqNumber();

        init(apOptions,
             tgsCred,
             cksum,
             subKey,
             seqNum,
             null,   // AuthorizationData authzData
            KeyUsage.KU_AP_REQ_AUTHENTICATOR);

    }

    /**
     * Contructs a AP-REQ message from the bytes received from the
     * peer.
     * @param message The message received from the peer
     * @param keys <code>EncrtyptionKey</code>s to decrypt the message;
     *       key selected will depend on etype used to encrypte data
     * @throws KrbException for any Kerberos protocol specific error
     * @throws IOException for any IO related errors
     *          (e.g. socket operations)
     */
     // Used in InitSecContextToken (for AP_REQ and not TGS REQ)
    public KrbApReq(byte[] message,
                    EncryptionKey[] keys,
                    InetAddress initiator)
        throws KrbException, IOException {
        obuf = message;
        if (apReqMessg == null)
            decode();
        authenticate(keys, initiator);
    }

    /**
     * Contructs a AP-REQ message from the bytes received from the
     * peer.
     * @param value The <code>DerValue</code> that contains the
     *              DER enoded AP-REQ protocol message
     * @param keys <code>EncrtyptionKey</code>s to decrypt the message;
     *
     * @throws KrbException for any Kerberos protocol specific error
     * @throws IOException for any IO related errors
     *          (e.g. socket operations)
     */
     /*
    public KrbApReq(DerValue value, EncryptionKey[] key, InetAddress initiator)
        throws KrbException, IOException {
        obuf = value.toByteArray();
        if (apReqMessg == null)
            decode(value);
        authenticate(keys, initiator);
    }

    KrbApReq(APOptions options,
             Credentials tgs_creds,
             Checksum cksum,
             EncryptionKey subKey,
             SeqNumber seqNumber,
             AuthorizationData authorizationData)
        throws KrbException, IOException {
        init(options, tgs_creds, cksum, subKey, seqNumber, authorizationData);
    }
*/

     /** used by KrbTgsReq **/
    KrbApReq(APOptions apOptions,
             Ticket ticket,
             EncryptionKey key,
             Realm crealm,
             PrincipalName cname,
             Checksum cksum,
             KerberosTime ctime,
             EncryptionKey subKey,
             SeqNumber seqNumber,
        AuthorizationData authorizationData)
        throws Asn1Exception, IOException,
               KdcErrException, KrbCryptoException {

        init(apOptions, ticket, key, crealm, cname,
             cksum, ctime, subKey, seqNumber, authorizationData,
            KeyUsage.KU_PA_TGS_REQ_AUTHENTICATOR);

    }

    private void init(APOptions options,
                      Credentials tgs_creds,
                      Checksum cksum,
                      EncryptionKey subKey,
                      SeqNumber seqNumber,
                      AuthorizationData authorizationData,
        int usage)
        throws KrbException, IOException {

        ctime = new KerberosTime(KerberosTime.NOW);
        init(options,
             tgs_creds.ticket,
             tgs_creds.key,
             tgs_creds.client.getRealm(),
             tgs_creds.client,
             cksum,
             ctime,
             subKey,
             seqNumber,
             authorizationData,
            usage);
    }

    private void init(APOptions apOptions,
                      Ticket ticket,
                      EncryptionKey key,
                      Realm crealm,
                      PrincipalName cname,
                      Checksum cksum,
                      KerberosTime ctime,
                      EncryptionKey subKey,
                      SeqNumber seqNumber,
                      AuthorizationData authorizationData,
        int usage)
        throws Asn1Exception, IOException,
               KdcErrException, KrbCryptoException {

        createMessage(apOptions, ticket, key, crealm, cname,
                      cksum, ctime, subKey, seqNumber, authorizationData,
            usage);
        obuf = apReqMessg.asn1Encode();
    }


    void decode() throws KrbException, IOException {
        DerValue encoding = new DerValue(obuf);
        decode(encoding);
    }

    void decode(DerValue encoding) throws KrbException, IOException {
        apReqMessg = null;
        try {
            apReqMessg = new APReq(encoding);
        } catch (Asn1Exception e) {
            apReqMessg = null;
            KRBError err = new KRBError(encoding);
            String errStr = err.getErrorString();
            String eText;
            if (errStr.charAt(errStr.length() - 1) == 0)
                eText = errStr.substring(0, errStr.length() - 1);
            else
                eText = errStr;
            KrbException ke = new KrbException(err.getErrorCode(), eText);
            ke.initCause(e);
            throw ke;
        }
    }

    private void authenticate(EncryptionKey[] keys, InetAddress initiator)
        throws KrbException, IOException {
        int encPartKeyType = apReqMessg.ticket.encPart.getEType();
        Integer kvno = apReqMessg.ticket.encPart.getKeyVersionNumber();
        EncryptionKey dkey = EncryptionKey.findKey(encPartKeyType, kvno, keys);

        if (dkey == null) {
            throw new KrbException(Krb5.API_INVALID_ARG,
                "Cannot find key of appropriate type to decrypt AP REP - " +
                                   EType.toString(encPartKeyType));
        }

        byte[] bytes = apReqMessg.ticket.encPart.decrypt(dkey,
            KeyUsage.KU_TICKET);
        byte[] temp = apReqMessg.ticket.encPart.reset(bytes, true);
        EncTicketPart enc_ticketPart = new EncTicketPart(temp);

        checkPermittedEType(enc_ticketPart.key.getEType());

        byte[] bytes2 = apReqMessg.authenticator.decrypt(enc_ticketPart.key,
            KeyUsage.KU_AP_REQ_AUTHENTICATOR);
        byte[] temp2 = apReqMessg.authenticator.reset(bytes2, true);
        authenticator = new Authenticator(temp2);
        ctime = authenticator.ctime;
        cusec = authenticator.cusec;
        authenticator.ctime.setMicroSeconds(authenticator.cusec);
        authenticator.cname.setRealm(authenticator.crealm);
        apReqMessg.ticket.sname.setRealm(apReqMessg.ticket.realm);
        enc_ticketPart.cname.setRealm(enc_ticketPart.crealm);

        if (!authenticator.cname.equals(enc_ticketPart.cname))
            throw new KrbApErrException(Krb5.KRB_AP_ERR_BADMATCH);

        KerberosTime currTime = new KerberosTime(KerberosTime.NOW);
        if (!authenticator.ctime.inClockSkew(currTime))
            throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);

        // start to check if it is a replay attack.
        AuthTime time =
            new AuthTime(authenticator.ctime.getTime(), authenticator.cusec);
        String client = authenticator.cname.toString();
        if (table.get(time, authenticator.cname.toString()) != null) {
            throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
        } else {
            table.put(client, time, currTime.getTime());
        }

        // check to use addresses in tickets
        if (Config.getInstance().useAddresses()) {
            KDC_EMPTY_ADDRESSES_ALLOWED = false;
        }

        // sender host address
        HostAddress sender = null;
        if (initiator != null) {
            sender = new HostAddress(initiator);
        }

        if (sender != null || !KDC_EMPTY_ADDRESSES_ALLOWED) {
            if (enc_ticketPart.caddr != null) {
                if (sender == null)
                    throw new KrbApErrException(Krb5.KRB_AP_ERR_BADADDR);
                if (!enc_ticketPart.caddr.inList(sender))
                    throw new KrbApErrException(Krb5.KRB_AP_ERR_BADADDR);
            }
        }

        // XXX check for repeated authenticator
        // if found
        //    throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
        // else
        //    save authenticator to check for later

        KerberosTime now = new KerberosTime(KerberosTime.NOW);

        if ((enc_ticketPart.starttime != null &&
             enc_ticketPart.starttime.greaterThanWRTClockSkew(now)) ||
            enc_ticketPart.flags.get(Krb5.TKT_OPTS_INVALID))
            throw new KrbApErrException(Krb5.KRB_AP_ERR_TKT_NYV);

        // if the current time is later than end time by more
        // than the allowable clock skew, throws ticket expired exception.
        if (enc_ticketPart.endtime != null &&
            now.greaterThanWRTClockSkew(enc_ticketPart.endtime)) {
            throw new KrbApErrException(Krb5.KRB_AP_ERR_TKT_EXPIRED);
        }

        creds = new Credentials(
                                apReqMessg.ticket,
                                authenticator.cname,
                                apReqMessg.ticket.sname,
                                enc_ticketPart.key,
                                enc_ticketPart.flags,
                                enc_ticketPart.authtime,
                                enc_ticketPart.starttime,
                                enc_ticketPart.endtime,
                                enc_ticketPart.renewTill,
                                enc_ticketPart.caddr,
                                enc_ticketPart.authorizationData);
        if (DEBUG) {
            System.out.println(">>> KrbApReq: authenticate succeed.");
        }
    }

    /**
     * Returns the credentials that are contained in the ticket that
     * is part of this this AP-REP.
     */
    public Credentials getCreds() {
        return creds;
    }

    KerberosTime getCtime() {
        if (ctime != null)
            return ctime;
        return authenticator.ctime;
    }

    int cusec() {
        return cusec;
    }

    APOptions getAPOptions() throws KrbException, IOException {
        if (apReqMessg == null)
            decode();
        if (apReqMessg != null)
            return apReqMessg.apOptions;
        return null;
    }

    /**
     * Returns true if mutual authentication is required and hence an
     * AP-REP will need to be generated.
     * @throws KrbException
     * @throws IOException
     */
    public boolean getMutualAuthRequired() throws KrbException, IOException {
        if (apReqMessg == null)
            decode();
        if (apReqMessg != null)
            return apReqMessg.apOptions.get(Krb5.AP_OPTS_MUTUAL_REQUIRED);
        return false;
    }

    boolean useSessionKey() throws KrbException, IOException {
        if (apReqMessg == null)
            decode();
        if (apReqMessg != null)
            return apReqMessg.apOptions.get(Krb5.AP_OPTS_USE_SESSION_KEY);
        return false;
    }

    /**
     * Returns the optional subkey stored in the Authenticator for
     * this message. Returns null if none is stored.
     */
    public EncryptionKey getSubKey() {
        // XXX Can authenticator be null
        return authenticator.getSubKey();
    }

    /**
     * Returns the optional sequence number stored in the
     * Authenticator for this message. Returns null if none is
     * stored.
     */
    public Integer getSeqNumber() {
        // XXX Can authenticator be null
        return authenticator.getSeqNumber();
    }

    /**
     * Returns the optional Checksum stored in the
     * Authenticator for this message. Returns null if none is
     * stored.
     */
    public Checksum getChecksum() {
        return authenticator.getChecksum();
    }

    /**
     * Returns the ASN.1 encoding that should be sent to the peer.
     */
    public byte[] getMessage() {
        return obuf;
    }

    /**
     * Returns the principal name of the client that generated this
     * message.
     */
    public PrincipalName getClient() {
        return creds.getClient();
    }

    private void createMessage(APOptions apOptions,
                               Ticket ticket,
                               EncryptionKey key,
                               Realm crealm,
                               PrincipalName cname,
                               Checksum cksum,
                               KerberosTime ctime,
                               EncryptionKey subKey,
                               SeqNumber seqNumber,
                               AuthorizationData authorizationData,
        int usage)
        throws Asn1Exception, IOException,
               KdcErrException, KrbCryptoException {

        Integer seqno = null;

        if (seqNumber != null)
            seqno = new Integer(seqNumber.current());

        authenticator =
            new Authenticator(crealm,
                              cname,
                              cksum,
                              ctime.getMicroSeconds(),
                              ctime,
                              subKey,
                              seqno,
                              authorizationData);

        byte[] temp = authenticator.asn1Encode();

        EncryptedData encAuthenticator =
            new EncryptedData(key, temp, usage);

        apReqMessg =
            new APReq(apOptions, ticket, encAuthenticator);
    }

     // Check that key is one of the permitted types
     private static void checkPermittedEType(int target) throws KrbException {
        int[] etypes = EType.getDefaults("permitted_enctypes");
        if (etypes == null) {
            throw new KrbException(
                "No supported encryption types listed in permitted_enctypes");
        }
        if (!EType.isSupported(target, etypes)) {
            throw new KrbException(EType.toString(target) +
                " encryption type not in permitted_enctypes list");
        }
     }
}
