/*
 * 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.
 */

package sun.security.jgss.krb5;

import org.ietf.jgss.*;
import javax.security.auth.kerberos.DelegationPermission;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import sun.security.krb5.*;
import sun.security.jgss.HttpCaller;
import sun.security.krb5.internal.Krb5;

abstract class InitialToken extends Krb5Token {

    private static final int CHECKSUM_TYPE = 0x8003;

    private static final int CHECKSUM_LENGTH_SIZE     = 4;
    private static final int CHECKSUM_BINDINGS_SIZE   = 16;
    private static final int CHECKSUM_FLAGS_SIZE      = 4;
    private static final int CHECKSUM_DELEG_OPT_SIZE  = 2;
    private static final int CHECKSUM_DELEG_LGTH_SIZE = 2;

    private static final int CHECKSUM_DELEG_FLAG    = 1;
    private static final int CHECKSUM_MUTUAL_FLAG   = 2;
    private static final int CHECKSUM_REPLAY_FLAG   = 4;
    private static final int CHECKSUM_SEQUENCE_FLAG = 8;
    private static final int CHECKSUM_CONF_FLAG     = 16;
    private static final int CHECKSUM_INTEG_FLAG    = 32;

    private final byte[] CHECKSUM_FIRST_BYTES =
    {(byte)0x10, (byte)0x00, (byte)0x00, (byte)0x00};

    private static final int CHANNEL_BINDING_AF_INET = 2;
    private static final int CHANNEL_BINDING_AF_INET6 = 24;
    private static final int CHANNEL_BINDING_AF_NULL_ADDR = 255;

    private static final int Inet4_ADDRSZ = 4;
    private static final int Inet6_ADDRSZ = 16;

    protected class OverloadedChecksum {

        private byte[] checksumBytes = null;
        private Credentials delegCreds = null;
        private int flags = 0;

        /**
         * Called on the initiator side when creating the
         * InitSecContextToken.
         */
        public OverloadedChecksum(Krb5Context context,
                                  Credentials tgt,
                                  Credentials serviceTicket)
            throws KrbException, IOException, GSSException {

            byte[] krbCredMessage = null;
            int pos = 0;
            int size = CHECKSUM_LENGTH_SIZE + CHECKSUM_BINDINGS_SIZE +
                CHECKSUM_FLAGS_SIZE;

            if (!tgt.isForwardable()) {
                context.setCredDelegState(false);
                context.setDelegPolicyState(false);
            } else if (context.getCredDelegState()) {
                if (context.getDelegPolicyState()) {
                    if (!serviceTicket.checkDelegate()) {
                        // delegation not permitted by server policy, mark it
                        context.setDelegPolicyState(false);
                    }
                }
            } else if (context.getDelegPolicyState()) {
                if (serviceTicket.checkDelegate()) {
                    context.setCredDelegState(true);
                } else {
                    context.setDelegPolicyState(false);
                }
            }

            if (context.getCredDelegState()) {
                KrbCred krbCred = null;
                CipherHelper cipherHelper =
                    context.getCipherHelper(serviceTicket.getSessionKey());
                if (useNullKey(cipherHelper)) {
                    krbCred = new KrbCred(tgt, serviceTicket,
                                              EncryptionKey.NULL_KEY);
                } else {
                    krbCred = new KrbCred(tgt, serviceTicket,
                                    serviceTicket.getSessionKey());
                }
                krbCredMessage = krbCred.getMessage();
                size += CHECKSUM_DELEG_OPT_SIZE +
                        CHECKSUM_DELEG_LGTH_SIZE +
                        krbCredMessage.length;
            }

            checksumBytes = new byte[size];

            checksumBytes[pos++] = CHECKSUM_FIRST_BYTES[0];
            checksumBytes[pos++] = CHECKSUM_FIRST_BYTES[1];
            checksumBytes[pos++] = CHECKSUM_FIRST_BYTES[2];
            checksumBytes[pos++] = CHECKSUM_FIRST_BYTES[3];

            ChannelBinding localBindings = context.getChannelBinding();
            if (localBindings != null) {
                byte[] localBindingsBytes =
                    computeChannelBinding(context.getChannelBinding());
                System.arraycopy(localBindingsBytes, 0,
                             checksumBytes, pos, localBindingsBytes.length);
                //              System.out.println("ChannelBinding hash: "
                //         + getHexBytes(localBindingsBytes));
            }

            pos += CHECKSUM_BINDINGS_SIZE;

            if (context.getCredDelegState())
                flags |= CHECKSUM_DELEG_FLAG;
            if (context.getMutualAuthState())
                flags |= CHECKSUM_MUTUAL_FLAG;
            if (context.getReplayDetState())
                flags |= CHECKSUM_REPLAY_FLAG;
            if (context.getSequenceDetState())
                flags |= CHECKSUM_SEQUENCE_FLAG;
            if (context.getIntegState())
                flags |= CHECKSUM_INTEG_FLAG;
            if (context.getConfState())
                flags |= CHECKSUM_CONF_FLAG;

            byte[] temp = new byte[4];
            writeLittleEndian(flags, temp);
            checksumBytes[pos++] = temp[0];
            checksumBytes[pos++] = temp[1];
            checksumBytes[pos++] = temp[2];
            checksumBytes[pos++] = temp[3];

            if (context.getCredDelegState()) {

                PrincipalName delegateTo =
                    serviceTicket.getServer();
                // Cannot use '\"' instead of "\"" in constructor because
                // it is interpreted as suggested length!
                StringBuffer buf = new StringBuffer("\"");
                buf.append(delegateTo.getName()).append('\"');
                String realm = delegateTo.getRealmAsString();
                buf.append(" \"krbtgt/").append(realm).append('@');
                buf.append(realm).append('\"');
                SecurityManager sm = System.getSecurityManager();
                if (sm != null) {
                    DelegationPermission perm =
                        new DelegationPermission(buf.toString());
                    sm.checkPermission(perm);
                }


                /*
                 * Write 1 in little endian but in two bytes
                 * for DlgOpt
                 */

                checksumBytes[pos++] = (byte)0x01;
                checksumBytes[pos++] = (byte)0x00;

                /*
                 * Write the length of the delegated credential in little
                 * endian but in two bytes for Dlgth
                 */

                if (krbCredMessage.length > 0x0000ffff)
                    throw new GSSException(GSSException.FAILURE, -1,
                        "Incorrect messsage length");

                writeLittleEndian(krbCredMessage.length, temp);
                checksumBytes[pos++] = temp[0];
                checksumBytes[pos++] = temp[1];
                System.arraycopy(krbCredMessage, 0,
                                 checksumBytes, pos, krbCredMessage.length);
            }

        }

        /**
         * Called on the acceptor side when reading an InitSecContextToken.
         */
        // XXX Passing in Checksum is not required. byte[] can
        // be passed in if this checksum type denotes a
        // raw_checksum. In that case, make Checksum class krb5
        // internal.
        public OverloadedChecksum(Krb5Context context,
                                  Checksum checksum, EncryptionKey key)
            throws GSSException, KrbException, IOException {

            int pos = 0;

            checksumBytes = checksum.getBytes();

            if ((checksumBytes[0] != CHECKSUM_FIRST_BYTES[0]) ||
                (checksumBytes[1] != CHECKSUM_FIRST_BYTES[1]) ||
                (checksumBytes[2] != CHECKSUM_FIRST_BYTES[2]) ||
                (checksumBytes[3] != CHECKSUM_FIRST_BYTES[3])) {
                throw new GSSException(GSSException.FAILURE, -1,
                        "Incorrect checksum");
            }

            ChannelBinding localBindings = context.getChannelBinding();

            // Ignore remote channel binding info when not requested at
            // local side (RFC 4121 4.1.1.2: the acceptor MAY ignore...).
            //
            // All major krb5 implementors implement this "MAY",
            // and some applications depend on it as a workaround
            // for not having a way to negotiate the use of channel
            // binding -- the initiator application always uses CB
            // and hopes the acceptor will ignore the CB if the
            // acceptor doesn't support CB.
            if (localBindings != null) {
                byte[] remoteBindingBytes = new byte[CHECKSUM_BINDINGS_SIZE];
                System.arraycopy(checksumBytes, 4, remoteBindingBytes, 0,
                                 CHECKSUM_BINDINGS_SIZE);

                byte[] noBindings = new byte[CHECKSUM_BINDINGS_SIZE];
                if (!Arrays.equals(noBindings, remoteBindingBytes)) {
                    byte[] localBindingsBytes =
                        computeChannelBinding(localBindings);
                    if (!Arrays.equals(localBindingsBytes,
                                                remoteBindingBytes)) {
                        throw new GSSException(GSSException.BAD_BINDINGS, -1,
                                               "Bytes mismatch!");
                    }
                } else {
                    throw new GSSException(GSSException.BAD_BINDINGS, -1,
                                           "Token missing ChannelBinding!");
                }
            }

            flags = readLittleEndian(checksumBytes, 20, 4);

            if ((flags & CHECKSUM_DELEG_FLAG) > 0) {

                /*
                 * XXX
                 * if ((checksumBytes[24] != (byte)0x01) &&
                 * (checksumBytes[25] != (byte)0x00))
                 */

                int credLen = readLittleEndian(checksumBytes, 26, 2);
                byte[] credBytes = new byte[credLen];
                System.arraycopy(checksumBytes, 28, credBytes, 0, credLen);

                CipherHelper cipherHelper = context.getCipherHelper(key);
                if (useNullKey(cipherHelper)) {
                    delegCreds =
                        new KrbCred(credBytes, EncryptionKey.NULL_KEY).
                        getDelegatedCreds()[0];
                } else {
                    delegCreds =
                        new KrbCred(credBytes, key).
                        getDelegatedCreds()[0];
                }
            }
        }

        // check if KRB-CRED message should use NULL_KEY for encryption
        private boolean useNullKey(CipherHelper ch) {
            boolean flag = true;
            // for "newer" etypes and RC4-HMAC do not use NULL KEY
            if ((ch.getProto() == 1) || ch.isArcFour()) {
                flag = false;
            }
            return flag;
        }

        public Checksum getChecksum() throws KrbException {
            return new Checksum(checksumBytes, CHECKSUM_TYPE);
        }

        public Credentials getDelegatedCreds() {
            return delegCreds;
        }

        // Only called by acceptor
        public void setContextFlags(Krb5Context context) {
                // default for cred delegation is false
            if ((flags & CHECKSUM_DELEG_FLAG) > 0)
                context.setCredDelegState(true);
                // default for the following are true
            if ((flags & CHECKSUM_MUTUAL_FLAG) == 0) {
                context.setMutualAuthState(false);
            }
            if ((flags & CHECKSUM_REPLAY_FLAG) == 0) {
                context.setReplayDetState(false);
            }
            if ((flags & CHECKSUM_SEQUENCE_FLAG) == 0) {
                context.setSequenceDetState(false);
            }
            if ((flags & CHECKSUM_CONF_FLAG) == 0) {
                context.setConfState(false);
            }
            if ((flags & CHECKSUM_INTEG_FLAG) == 0) {
                context.setIntegState(false);
            }
        }
    }

    private int getAddrType(InetAddress addr) {
        int addressType = CHANNEL_BINDING_AF_NULL_ADDR;

        if (addr instanceof Inet4Address)
            addressType = CHANNEL_BINDING_AF_INET;
        else if (addr instanceof Inet6Address)
            addressType = CHANNEL_BINDING_AF_INET6;
        return (addressType);
    }

    private byte[] getAddrBytes(InetAddress addr) throws GSSException {
        int addressType = getAddrType(addr);
        byte[] addressBytes = addr.getAddress();
        if (addressBytes != null) {
            switch (addressType) {
                case CHANNEL_BINDING_AF_INET:
                    if (addressBytes.length != Inet4_ADDRSZ) {
                        throw new GSSException(GSSException.FAILURE, -1,
                        "Incorrect AF-INET address length in ChannelBinding.");
                    }
                    return (addressBytes);
                case CHANNEL_BINDING_AF_INET6:
                    if (addressBytes.length != Inet6_ADDRSZ) {
                        throw new GSSException(GSSException.FAILURE, -1,
                        "Incorrect AF-INET6 address length in ChannelBinding.");
                    }
                    return (addressBytes);
                default:
                    throw new GSSException(GSSException.FAILURE, -1,
                    "Cannot handle non AF-INET addresses in ChannelBinding.");
            }
        }
        return null;
    }

    private byte[] computeChannelBinding(ChannelBinding channelBinding)
        throws GSSException {

        InetAddress initiatorAddress = channelBinding.getInitiatorAddress();
        InetAddress acceptorAddress = channelBinding.getAcceptorAddress();
        int size = 5*4;

        int initiatorAddressType = getAddrType(initiatorAddress);
        int acceptorAddressType = getAddrType(acceptorAddress);

        byte[] initiatorAddressBytes = null;
        if (initiatorAddress != null) {
            initiatorAddressBytes = getAddrBytes(initiatorAddress);
            size += initiatorAddressBytes.length;
        }

        byte[] acceptorAddressBytes = null;
        if (acceptorAddress != null) {
            acceptorAddressBytes = getAddrBytes(acceptorAddress);
            size += acceptorAddressBytes.length;
        }

        byte[] appDataBytes = channelBinding.getApplicationData();
        if (appDataBytes != null) {
            size += appDataBytes.length;
        }

        byte[] data = new byte[size];

        int pos = 0;

        writeLittleEndian(initiatorAddressType, data, pos);
        pos += 4;

        if (initiatorAddressBytes != null) {
            writeLittleEndian(initiatorAddressBytes.length, data, pos);
            pos += 4;
            System.arraycopy(initiatorAddressBytes, 0,
                             data, pos, initiatorAddressBytes.length);
            pos += initiatorAddressBytes.length;
        } else {
            // Write length 0
            pos += 4;
        }

        writeLittleEndian(acceptorAddressType, data, pos);
        pos += 4;

        if (acceptorAddressBytes != null) {
            writeLittleEndian(acceptorAddressBytes.length, data, pos);
            pos += 4;
            System.arraycopy(acceptorAddressBytes, 0,
                             data, pos, acceptorAddressBytes.length);
            pos += acceptorAddressBytes.length;
        } else {
            // Write length 0
            pos += 4;
        }

        if (appDataBytes != null) {
            writeLittleEndian(appDataBytes.length, data, pos);
            pos += 4;
            System.arraycopy(appDataBytes, 0, data, pos,
                             appDataBytes.length);
            pos += appDataBytes.length;
        } else {
            // Write 0
            pos += 4;
        }

        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            return md5.digest(data);
        } catch (NoSuchAlgorithmException e) {
                throw new GSSException(GSSException.FAILURE, -1,
                                       "Could not get MD5 Message Digest - "
                                       + e.getMessage());
        }
    }

    public abstract byte[] encode() throws IOException;

}
