/*
 * Copyright (c) 2005, 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.wrapper;

import org.ietf.jgss.*;
import java.security.Provider;
import sun.security.jgss.GSSHeader;
import sun.security.jgss.GSSUtil;
import sun.security.jgss.GSSExceptionImpl;
import sun.security.jgss.spi.*;
import sun.security.util.DerValue;
import sun.security.util.ObjectIdentifier;
import sun.security.jgss.spnego.NegTokenInit;
import sun.security.jgss.spnego.NegTokenTarg;
import javax.security.auth.kerberos.DelegationPermission;
import com.sun.security.jgss.InquireType;
import java.io.*;


/**
 * This class is essentially a wrapper class for the gss_ctx_id_t
 * structure of the native GSS library.
 * @author Valerie Peng
 * @since 1.6
 */
class NativeGSSContext implements GSSContextSpi {

    private static final int GSS_C_DELEG_FLAG = 1;
    private static final int GSS_C_MUTUAL_FLAG = 2;
    private static final int GSS_C_REPLAY_FLAG = 4;
    private static final int GSS_C_SEQUENCE_FLAG = 8;
    private static final int GSS_C_CONF_FLAG = 16;
    private static final int GSS_C_INTEG_FLAG = 32;
    private static final int GSS_C_ANON_FLAG = 64;
    private static final int GSS_C_PROT_READY_FLAG = 128;
    private static final int GSS_C_TRANS_FLAG = 256;

    private static final int NUM_OF_INQUIRE_VALUES = 6;

    private long pContext = 0; // Pointer to the gss_ctx_id_t structure
    private GSSNameElement srcName;
    private GSSNameElement targetName;
    private GSSCredElement cred;
    private boolean isInitiator;
    private boolean isEstablished;
    private Oid actualMech; // Assigned during context establishment

    private ChannelBinding cb;
    private GSSCredElement delegatedCred;
    private int flags;
    private int lifetime = GSSCredential.DEFAULT_LIFETIME;
    private final GSSLibStub cStub;

    private boolean skipDelegPermCheck;
    private boolean skipServicePermCheck;

    // Retrieve the (preferred) mech out of SPNEGO tokens, i.e.
    // NegTokenInit & NegTokenTarg
    private static Oid getMechFromSpNegoToken(byte[] token,
                                              boolean isInitiator)
        throws GSSException {
        Oid mech = null;
        if (isInitiator) {
            GSSHeader header = null;
            try {
                header = new GSSHeader(new ByteArrayInputStream(token));
            } catch (IOException ioe) {
                throw new GSSExceptionImpl(GSSException.FAILURE, ioe);
            }
            int negTokenLen = header.getMechTokenLength();
            byte[] negToken = new byte[negTokenLen];
            System.arraycopy(token, token.length-negTokenLen,
                             negToken, 0, negToken.length);

            NegTokenInit ntok = new NegTokenInit(negToken);
            if (ntok.getMechToken() != null) {
                Oid[] mechList = ntok.getMechTypeList();
                mech = mechList[0];
            }
        } else {
            NegTokenTarg ntok = new NegTokenTarg(token);
            mech = ntok.getSupportedMech();
        }
        return mech;
    }

    // Perform the Service permission check
    private void doServicePermCheck() throws GSSException {
        if (System.getSecurityManager() != null) {
            String action = (isInitiator? "initiate" : "accept");
            // Need to check Service permission for accessing
            // initiator cred for SPNEGO during context establishment
            if (GSSUtil.isSpNegoMech(cStub.getMech()) && isInitiator
                && !isEstablished) {
                if (srcName == null) {
                    // Check by creating default initiator KRB5 cred
                    GSSCredElement tempCred =
                        new GSSCredElement(null, lifetime,
                                           GSSCredential.INITIATE_ONLY,
                                           GSSLibStub.getInstance(GSSUtil.GSS_KRB5_MECH_OID));
                    tempCred.dispose();
                } else {
                    String tgsName = Krb5Util.getTGSName(srcName);
                    Krb5Util.checkServicePermission(tgsName, action);
                }
            }
            String targetStr = targetName.getKrbName();
            Krb5Util.checkServicePermission(targetStr, action);
            skipServicePermCheck = true;
        }
    }

    // Perform the Delegation permission check
    private void doDelegPermCheck() throws GSSException {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            String targetStr = targetName.getKrbName();
            String tgsStr = Krb5Util.getTGSName(targetName);
            StringBuffer buf = new StringBuffer("\"");
            buf.append(targetStr).append("\" \"");
            buf.append(tgsStr).append('\"');
            String krbPrincPair = buf.toString();
            SunNativeProvider.debug("Checking DelegationPermission (" +
                                    krbPrincPair + ")");
            DelegationPermission perm =
                new DelegationPermission(krbPrincPair);
            sm.checkPermission(perm);
            skipDelegPermCheck = true;
        }
    }

    private byte[] retrieveToken(InputStream is, int mechTokenLen)
        throws GSSException {
        try {
            byte[] result = null;
            if (mechTokenLen != -1) {
                // Need to add back the GSS header for a complete GSS token
                SunNativeProvider.debug("Precomputed mechToken length: " +
                                         mechTokenLen);
                GSSHeader gssHeader = new GSSHeader
                    (new ObjectIdentifier(cStub.getMech().toString()),
                     mechTokenLen);
                ByteArrayOutputStream baos = new ByteArrayOutputStream(600);

                byte[] mechToken = new byte[mechTokenLen];
                int len = is.read(mechToken);
                assert(mechTokenLen == len);
                gssHeader.encode(baos);
                baos.write(mechToken);
                result = baos.toByteArray();
            } else {
                // Must be unparsed GSS token or SPNEGO's NegTokenTarg token
                assert(mechTokenLen == -1);
                DerValue dv = new DerValue(is);
                result = dv.toByteArray();
            }
            SunNativeProvider.debug("Complete Token length: " +
                                    result.length);
            return result;
        } catch (IOException ioe) {
            throw new GSSExceptionImpl(GSSException.FAILURE, ioe);
        }
    }

    // Constructor for context initiator
    NativeGSSContext(GSSNameElement peer, GSSCredElement myCred,
                     int time, GSSLibStub stub) throws GSSException {
        if (peer == null) {
            throw new GSSException(GSSException.FAILURE, 1, "null peer");
        }
        cStub = stub;
        cred = myCred;
        targetName = peer;
        isInitiator = true;
        lifetime = time;

        if (GSSUtil.isKerberosMech(cStub.getMech())) {
            doServicePermCheck();
            if (cred == null) {
                cred = new GSSCredElement(null, lifetime,
                                          GSSCredential.INITIATE_ONLY, cStub);
            }
            srcName = cred.getName();
        }
    }

    // Constructor for context acceptor
    NativeGSSContext(GSSCredElement myCred, GSSLibStub stub)
        throws GSSException {
        cStub = stub;
        cred = myCred;

        if (cred != null) targetName = cred.getName();

        isInitiator = false;
        // Defer Service permission check for default acceptor cred
        // to acceptSecContext()
        if (GSSUtil.isKerberosMech(cStub.getMech()) && targetName != null) {
            doServicePermCheck();
        }

        // srcName and potentially targetName (when myCred is null)
        // will be set in GSSLibStub.acceptContext(...)
    }

    // Constructor for imported context
    NativeGSSContext(long pCtxt, GSSLibStub stub) throws GSSException {
        assert(pContext != 0);
        pContext = pCtxt;
        cStub = stub;

        // Set everything except cred, cb, delegatedCred
        long[] info = cStub.inquireContext(pContext);
        if (info.length != NUM_OF_INQUIRE_VALUES) {
            throw new RuntimeException("Bug w/ GSSLibStub.inquireContext()");
        }
        srcName = new GSSNameElement(info[0], cStub);
        targetName = new GSSNameElement(info[1], cStub);
        isInitiator = (info[2] != 0);
        isEstablished = (info[3] != 0);
        flags = (int) info[4];
        lifetime = (int) info[5];

        // Do Service Permission check when importing SPNEGO context
        // just to be safe
        Oid mech = cStub.getMech();
        if (GSSUtil.isSpNegoMech(mech) || GSSUtil.isKerberosMech(mech)) {
            doServicePermCheck();
        }
    }

    public Provider getProvider() {
        return SunNativeProvider.INSTANCE;
    }

    public byte[] initSecContext(InputStream is, int mechTokenLen)
        throws GSSException {
        byte[] outToken = null;
        if ((!isEstablished) && (isInitiator)) {
            byte[] inToken = null;
            // Ignore the specified input stream on the first call
            if (pContext != 0) {
                inToken = retrieveToken(is, mechTokenLen);
                SunNativeProvider.debug("initSecContext=> inToken len=" +
                    inToken.length);
            }

            if (!getCredDelegState()) skipDelegPermCheck = true;

            if (GSSUtil.isKerberosMech(cStub.getMech()) && !skipDelegPermCheck) {
                doDelegPermCheck();
            }

            long pCred = (cred == null? 0 : cred.pCred);
            outToken = cStub.initContext(pCred, targetName.pName,
                                         cb, inToken, this);
            SunNativeProvider.debug("initSecContext=> outToken len=" +
                (outToken == null ? 0 : outToken.length));

            // Only inspect the token when the permission check
            // has not been performed
            if (GSSUtil.isSpNegoMech(cStub.getMech()) && outToken != null) {
                // WORKAROUND for SEAM bug#6287358
                actualMech = getMechFromSpNegoToken(outToken, true);

                if (GSSUtil.isKerberosMech(actualMech)) {
                    if (!skipServicePermCheck) doServicePermCheck();
                    if (!skipDelegPermCheck) doDelegPermCheck();
                }
            }

            if (isEstablished) {
                if (srcName == null) {
                    srcName = new GSSNameElement
                        (cStub.getContextName(pContext, true), cStub);
                }
                if (cred == null) {
                    cred = new GSSCredElement(srcName, lifetime,
                                              GSSCredential.INITIATE_ONLY,
                                              cStub);
                }
            }
        }
        return outToken;
    }

    public byte[] acceptSecContext(InputStream is, int mechTokenLen)
        throws GSSException {
        byte[] outToken = null;
        if ((!isEstablished) && (!isInitiator)) {
            byte[] inToken = retrieveToken(is, mechTokenLen);
            SunNativeProvider.debug("acceptSecContext=> inToken len=" +
                                    inToken.length);
            long pCred = (cred == null? 0 : cred.pCred);
            outToken = cStub.acceptContext(pCred, cb, inToken, this);
            SunNativeProvider.debug("acceptSecContext=> outToken len=" +
                                    (outToken == null? 0 : outToken.length));

            if (targetName == null) {
                targetName = new GSSNameElement
                    (cStub.getContextName(pContext, false), cStub);
                // Replace the current default acceptor cred now that
                // the context acceptor name is available
                if (cred != null) cred.dispose();
                cred = new GSSCredElement(targetName, lifetime,
                                          GSSCredential.ACCEPT_ONLY, cStub);
            }

            // Only inspect token when the permission check has not
            // been performed
            if (GSSUtil.isSpNegoMech(cStub.getMech()) &&
                (outToken != null) && !skipServicePermCheck) {
                if (GSSUtil.isKerberosMech(getMechFromSpNegoToken
                                           (outToken, false))) {
                    doServicePermCheck();
                }
            }
        }
        return outToken;
    }

    public boolean isEstablished() {
        return isEstablished;
    }

    public void dispose() throws GSSException {
        srcName = null;
        targetName = null;
        cred = null;
        delegatedCred = null;
        if (pContext != 0) {
            pContext = cStub.deleteContext(pContext);
            pContext = 0;
        }
    }

    public int getWrapSizeLimit(int qop, boolean confReq,
                                int maxTokenSize)
        throws GSSException {
        return cStub.wrapSizeLimit(pContext, (confReq? 1:0), qop,
                                   maxTokenSize);
    }

    public byte[] wrap(byte[] inBuf, int offset, int len,
                       MessageProp msgProp) throws GSSException {
        byte[] data = inBuf;
        if ((offset != 0) || (len != inBuf.length)) {
            data = new byte[len];
            System.arraycopy(inBuf, offset, data, 0, len);
        }
        return cStub.wrap(pContext, data, msgProp);
    }
    public void wrap(byte inBuf[], int offset, int len,
                     OutputStream os, MessageProp msgProp)
        throws GSSException {
        try {
        byte[] result = wrap(inBuf, offset, len, msgProp);
        os.write(result);
        } catch (IOException ioe) {
            throw new GSSExceptionImpl(GSSException.FAILURE, ioe);
        }
    }
    public int wrap(byte[] inBuf, int inOffset, int len, byte[] outBuf,
                    int outOffset, MessageProp msgProp)
        throws GSSException {
        byte[] result = wrap(inBuf, inOffset, len, msgProp);
        System.arraycopy(result, 0, outBuf, outOffset, result.length);
        return result.length;
    }
    public void wrap(InputStream inStream, OutputStream outStream,
                     MessageProp msgProp) throws GSSException {
        try {
            byte[] data = new byte[inStream.available()];
            int length = inStream.read(data);
            byte[] token = wrap(data, 0, length, msgProp);
            outStream.write(token);
        } catch (IOException ioe) {
            throw new GSSExceptionImpl(GSSException.FAILURE, ioe);
        }
    }

    public byte[] unwrap(byte[] inBuf, int offset, int len,
                         MessageProp msgProp)
        throws GSSException {
        if ((offset != 0) || (len != inBuf.length)) {
            byte[] temp = new byte[len];
            System.arraycopy(inBuf, offset, temp, 0, len);
            return cStub.unwrap(pContext, temp, msgProp);
        } else {
            return cStub.unwrap(pContext, inBuf, msgProp);
        }
    }
    public int unwrap(byte[] inBuf, int inOffset, int len,
                      byte[] outBuf, int outOffset,
                      MessageProp msgProp) throws GSSException {
        byte[] result = null;
        if ((inOffset != 0) || (len != inBuf.length)) {
            byte[] temp = new byte[len];
            System.arraycopy(inBuf, inOffset, temp, 0, len);
            result = cStub.unwrap(pContext, temp, msgProp);
        } else {
            result = cStub.unwrap(pContext, inBuf, msgProp);
        }
        System.arraycopy(result, 0, outBuf, outOffset, result.length);
        return result.length;
    }
    public void unwrap(InputStream inStream, OutputStream outStream,
                       MessageProp msgProp) throws GSSException {
        try {
            byte[] wrapped = new byte[inStream.available()];
            int wLength = inStream.read(wrapped);
            byte[] data = unwrap(wrapped, 0, wLength, msgProp);
            outStream.write(data);
            outStream.flush();
        } catch (IOException ioe) {
            throw new GSSExceptionImpl(GSSException.FAILURE, ioe);
        }
    }

    public int unwrap(InputStream inStream,
                      byte[] outBuf, int outOffset,
                      MessageProp msgProp) throws GSSException {
        byte[] wrapped = null;
        int wLength = 0;
        try {
            wrapped = new byte[inStream.available()];
            wLength = inStream.read(wrapped);
            byte[] result = unwrap(wrapped, 0, wLength, msgProp);
        } catch (IOException ioe) {
            throw new GSSExceptionImpl(GSSException.FAILURE, ioe);
        }
        byte[] result = unwrap(wrapped, 0, wLength, msgProp);
        System.arraycopy(result, 0, outBuf, outOffset, result.length);
        return result.length;
    }

    public byte[] getMIC(byte[] in, int offset, int len,
                         MessageProp msgProp) throws GSSException {
        int qop = (msgProp == null? 0:msgProp.getQOP());
        byte[] inMsg = in;
        if ((offset != 0) || (len != in.length)) {
            inMsg = new byte[len];
            System.arraycopy(in, offset, inMsg, 0, len);
        }
        return cStub.getMic(pContext, qop, inMsg);
    }

    public void getMIC(InputStream inStream, OutputStream outStream,
                       MessageProp msgProp) throws GSSException {
        try {
            int length = 0;
            byte[] msg = new byte[inStream.available()];
            length = inStream.read(msg);

            byte[] msgToken = getMIC(msg, 0, length, msgProp);
            if ((msgToken != null) && msgToken.length != 0) {
                outStream.write(msgToken);
            }
        } catch (IOException ioe) {
            throw new GSSExceptionImpl(GSSException.FAILURE, ioe);
        }
    }

    public void verifyMIC(byte[] inToken, int tOffset, int tLen,
                          byte[] inMsg, int mOffset, int mLen,
                          MessageProp msgProp) throws GSSException {
        byte[] token = inToken;
        byte[] msg = inMsg;
        if ((tOffset != 0) || (tLen != inToken.length)) {
            token = new byte[tLen];
            System.arraycopy(inToken, tOffset, token, 0, tLen);
        }
        if ((mOffset != 0) || (mLen != inMsg.length)) {
            msg = new byte[mLen];
            System.arraycopy(inMsg, mOffset, msg, 0, mLen);
        }
        cStub.verifyMic(pContext, token, msg, msgProp);
    }

    public void verifyMIC(InputStream tokStream, InputStream msgStream,
                          MessageProp msgProp) throws GSSException {
        try {
            byte[] msg = new byte[msgStream.available()];
            int mLength = msgStream.read(msg);
            byte[] tok = new byte[tokStream.available()];
            int tLength = tokStream.read(tok);
            verifyMIC(tok, 0, tLength, msg, 0, mLength, msgProp);
        } catch (IOException ioe) {
            throw new GSSExceptionImpl(GSSException.FAILURE, ioe);
        }
    }

    public byte[] export() throws GSSException {
        byte[] result = cStub.exportContext(pContext);
        pContext = 0;
        return result;
    }

    private void changeFlags(int flagMask, boolean isEnable) {
        if (isInitiator && pContext == 0) {
            if (isEnable) {
                flags |= flagMask;
            } else {
                flags &= ~flagMask;
            }
        }
    }
    public void requestMutualAuth(boolean state) throws GSSException {
        changeFlags(GSS_C_MUTUAL_FLAG, state);
    }
    public void requestReplayDet(boolean state) throws GSSException {
        changeFlags(GSS_C_REPLAY_FLAG, state);
    }
    public void requestSequenceDet(boolean state) throws GSSException {
        changeFlags(GSS_C_SEQUENCE_FLAG, state);
    }
    public void requestCredDeleg(boolean state) throws GSSException {
        changeFlags(GSS_C_DELEG_FLAG, state);
    }
    public void requestAnonymity(boolean state) throws GSSException {
        changeFlags(GSS_C_ANON_FLAG, state);
    }
    public void requestConf(boolean state) throws GSSException {
        changeFlags(GSS_C_CONF_FLAG, state);
    }
    public void requestInteg(boolean state) throws GSSException {
        changeFlags(GSS_C_INTEG_FLAG, state);
    }
    public void requestDelegPolicy(boolean state) throws GSSException {
        // Not supported, ignore
    }
    public void requestLifetime(int lifetime) throws GSSException {
        if (isInitiator && pContext == 0) {
            this.lifetime = lifetime;
        }
    }
    public void setChannelBinding(ChannelBinding cb) throws GSSException {
        if (pContext == 0) {
            this.cb = cb;
        }
    }

    private boolean checkFlags(int flagMask) {
        return ((flags & flagMask) != 0);
    }
    public boolean getCredDelegState() {
        return checkFlags(GSS_C_DELEG_FLAG);
    }
    public boolean getMutualAuthState() {
        return checkFlags(GSS_C_MUTUAL_FLAG);
    }
    public boolean getReplayDetState() {
        return checkFlags(GSS_C_REPLAY_FLAG);
    }
    public boolean getSequenceDetState() {
        return checkFlags(GSS_C_SEQUENCE_FLAG);
    }
    public boolean getAnonymityState() {
        return checkFlags(GSS_C_ANON_FLAG);
    }
    public boolean isTransferable() throws GSSException {
        return checkFlags(GSS_C_TRANS_FLAG);
    }
    public boolean isProtReady() {
        return checkFlags(GSS_C_PROT_READY_FLAG);
    }
    public boolean getConfState() {
        return checkFlags(GSS_C_CONF_FLAG);
    }
    public boolean getIntegState() {
        return checkFlags(GSS_C_INTEG_FLAG);
    }
    public boolean getDelegPolicyState() {
        return false;
    }
    public int getLifetime() {
        return cStub.getContextTime(pContext);
    }
    public GSSNameSpi getSrcName() throws GSSException {
        return srcName;
    }
    public GSSNameSpi getTargName() throws GSSException {
        return targetName;
    }
    public Oid getMech() throws GSSException {
        if (isEstablished && actualMech != null) {
            return actualMech;
        } else {
            return cStub.getMech();
        }
    }
    public GSSCredentialSpi getDelegCred() throws GSSException {
        return delegatedCred;
    }
    public boolean isInitiator() {
        return isInitiator;
    }

    protected void finalize() throws Throwable {
        dispose();
    }

    public Object inquireSecContext(InquireType type)
            throws GSSException {
        throw new GSSException(GSSException.UNAVAILABLE, -1,
                "Inquire type not supported.");
    }
}
