Package edu.mit.jgss

Source Code of edu.mit.jgss.GSSContextImpl

/*
* Copyright (C) 2012 by the Massachusetts Institute of Technology.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
*   notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
*   notice, this list of conditions and the following disclaimer in
*   the documentation and/or other materials provided with the
*   distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package edu.mit.jgss;

import org.ietf.jgss.GSSException;
import org.ietf.jgss.Oid;
import org.ietf.jgss.GSSName;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.ChannelBinding;
import org.ietf.jgss.MessageProp;
import org.ietf.jgss.GSSContext;

import edu.mit.jgss.swig.*;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class GSSContextImpl implements GSSContext {
   
    /* representing our underlying SWIG-wrapped gss_ctx_id_t object */
    private gss_ctx_id_t_desc internGSSCtx = new gss_ctx_id_t_desc();
   
    /* has this context been destroyed? */
    private boolean invalid = false;

    /* context state */
    private enum State { UNINIT, INPROG, DONE, DISPOSED }

    /* variables set during context creation */
    private GSSCredentialImpl credential = null;
    private GSSCredentialImpl delegCredential = null;
    private GSSNameImpl targetName = null;
    private GSSNameImpl srcName = null;
    private OidImpl mech = null;

    /* create a ChannelBinding equal to GSS_C_NO_CHANNEL_BINDINGS */
    private ChannelBindingImpl channelBinding = new ChannelBindingImpl(null,
            null, null);

    /* use default lifetime at first - note that we store the lifetime as a
     * long because native gssapi uses unsigned ints, whereas Java has no such
     * thing. Thus, we use the larger datatype to imitate an unsigned int. */
    private long lifetime = convertLifetime(GSSContext.DEFAULT_LIFETIME);

    /* state flags */
    private boolean requestCredDeleg   = false;
    private boolean requestMutualAuth  = false;
    private boolean requestReplayDet   = false;
    private boolean requestSequenceDet = false;
    private boolean requestConf        = false;
    private boolean requestInteg       = false;
    private boolean requestAnonymity   = false;
    private boolean isProtReady        = false;
    private boolean isTransferable     = false;

    /* designates if context is initiator or acceptor */
    private boolean initiator = false;

    /* keep track of context state */
    private State ctxState = State.UNINIT;

    /* create context on the initiator side */
    public GSSContextImpl(GSSName peer, Oid mech, GSSCredential myCred,
            int lifetime) throws GSSException {
       
        if (peer != null) {
            this.targetName = (GSSNameImpl)peer;
        } else {
            throw new GSSException(GSSException.BAD_NAME);
        }

        if (mech == null) {
            /* default native mech = gss_mech_krb5 */
            this.mech = new OidImpl("1.2.840.113554.1.2.2");
        } else {
            this.mech = new OidImpl(mech.toString());
        }

        if (myCred != null) {
            this.credential = (GSSCredentialImpl) myCred;
            this.srcName = (GSSNameImpl) myCred.getName();
        } else {
            /* create GSS_C_NO_CREDENTIAL */
            this.credential =  new GSSCredentialImpl();
            this.credential.setInternGSSCred(null);
        }

        if (lifetime >= 0) {
            this.lifetime = convertLifetime(lifetime);
        }

        this.invalid = false;
        this.initiator = true;
    }

    /* create context on the acceptor side
     *
     * If null is passed in for myCred, we should set up a default
     * acceptor principal using:
     *
     * credential = GSS_C_NO_CREDENTIAL,
     * channelBinding = GSS_C_NO_CHANNEL_BINDINGS,
     * srcName = GSS_C_NO_NAME,
     * targetName = ?
     */
    public GSSContextImpl(GSSCredential myCred) throws GSSException {

        if (myCred != null) {

            credential = (GSSCredentialImpl) myCred;
            targetName = (GSSNameImpl) myCred.getName();
           
        } else {

            /* create GSS_C_NO_CREDENTIAL */
            credential =  new GSSCredentialImpl();
            credential.setInternGSSCred(null);

            /* create GSS_C_NO_NAME */
            srcName = new GSSNameImpl();
            srcName.setInternGSSName(null);

        }

        this.invalid = false;
        this.initiator = false;
    }

    /* create context from exported inter-process token */
    public GSSContextImpl(byte[] interProcessToken) throws GSSException {

        long maj_status = 0;
        long[] min_status = {0};

        gss_name_t_desc src_name = new gss_name_t_desc();
        gss_name_t_desc targ_name = new gss_name_t_desc();
        gss_buffer_desc sname = new gss_buffer_desc();
        gss_buffer_desc tname = new gss_buffer_desc();
        gss_OID_desc mechanism = new gss_OID_desc();
        gss_OID_desc name_type = new gss_OID_desc();
        long[] lifetime = {0};
        long[] context_flags = {0};
        int[] is_local = {0};
        int[] is_open = {0};
       
        gss_buffer_desc processToken = new gss_buffer_desc();
        gsswrapper.setDescArray(processToken, interProcessToken);
        processToken.setLength(interProcessToken.length);

        /* import context from token */
        maj_status = gsswrapper.gss_import_sec_context(min_status,
                processToken, this.internGSSCtx);

        if (maj_status != gsswrapper.GSS_S_COMPLETE) {
            throw new GSSExceptionImpl((int) maj_status, (int) min_status[0]);
        }

        /* get information about context */
        maj_status = gsswrapper.gss_inquire_context(min_status,
                this.internGSSCtx, src_name, targ_name, lifetime,
                mechanism, context_flags, is_local, is_open);

        if (maj_status != gsswrapper.GSS_S_COMPLETE) {
            throw new GSSExceptionImpl((int) maj_status, (int) min_status[0]);
        }

        /* store src name */
        maj_status = gsswrapper.gss_display_name(min_status, src_name,
                sname, name_type);

        if (maj_status != gsswrapper.GSS_S_COMPLETE) {
            throw new GSSExceptionImpl((int) maj_status, (int) min_status[0]);
        } else {
            srcName = new GSSNameImpl();
            srcName.setInternGSSName(src_name);
        }

        /* store target name */
        maj_status = gsswrapper.gss_display_name(min_status, targ_name,
                tname, name_type);

        if (maj_status != gsswrapper.GSS_S_COMPLETE) {
            throw new GSSExceptionImpl((int) maj_status, (int) min_status[0]);
        } else {
            targetName = new GSSNameImpl();
            targetName.setInternGSSName(targ_name);
        }

        /* store additional context information in GSSContext object */
        mech = new OidImpl(mechanism.toDotString());
        this.lifetime = lifetime[0];
        setReturnedFlags(context_flags[0]);

        if (is_open[0] == 1) {
            this.ctxState = State.DONE;
        }
        this.invalid = false;

        /* free native structures */
        gsswrapper.gss_release_buffer(min_status, sname);
        gsswrapper.gss_release_buffer(min_status, tname);
        gsswrapper.gss_release_buffer(min_status, processToken);

    }

    public byte[] initSecContext(byte[] inputBuf, int offset, int len)
        throws GSSException {

        int ret = 0;
       
        ByteArrayInputStream bis = new ByteArrayInputStream(inputBuf,
                offset, len);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        ret = initSecContext(bis, bos);
        return bos.toByteArray();
    }

    /*
     * returns the number of bytes written to the OutpuStream, or 0 if
     * none need to be written
     */
    public int initSecContext(InputStream inStream, OutputStream outStream)
        throws GSSException {

        int ret              = 0;
        long maj_status      = 0;
        long[] min_status    = {0};
        long[] actual_flags  = {0};
        long[] time_rec      = {0};
        byte[] inputTokArray = null;;
        byte[] temp_token;
        gss_ctx_id_t_desc context_tmp;
        gss_OID_desc actual_mech_type = new gss_OID_desc();
        gss_buffer_desc outputToken = new gss_buffer_desc();
        gss_buffer_desc inputToken = new gss_buffer_desc();
        ByteArrayOutputStream outTok = new ByteArrayOutputStream();

        /* setup temporary context */
        if (ctxState == State.UNINIT) {
            context_tmp = gsswrapper.GSS_C_NO_CONTEXT;
        } else {
            context_tmp = internGSSCtx;
        }

        /* setup output token */
        outputToken.setLength(0);
        outputToken.setValue(null);

        try {
            if (inStream.available() > 0) {

                /* retrieve token header to get token length */
                DerHeader tokHeader = DerUtil.getHeader(inStream);

                /* put our header bytes back */
                outTok.write(tokHeader.getBytes());

                /* copy over the rest of our input token */
                for (int i = 0; i < tokHeader.getLength(); i++) {
                    outTok.write(inStream.read());
                }
            }

        } catch (IOException e) {
            /* I/O Error occurred when reading InputStream */
            throw new GSSException(GSSException.FAILURE);
        }
      
        /* read token -> byte array -> gss_buffer_desc for native gssapi */
        inputTokArray = outTok.toByteArray();
        if (inputTokArray != null && inputTokArray.length > 0) {
            gsswrapper.setDescArray(inputToken, inputTokArray);
            inputToken.setLength(inputTokArray.length);
        }

        /* get requested flags */
        long requestedFlags = getRequestedFlags();

        maj_status = gsswrapper.gss_init_sec_context(min_status,
                credential.getInternGSSCred(),
                context_tmp,
                targetName.getInternGSSName(),
                mech.getNativeOid(),
                requestedFlags,
                lifetime,
                channelBinding.getNativeChannelBindings(),
                inputToken,
                actual_mech_type,
                outputToken,
                actual_flags,
                time_rec);

        if (maj_status == gsswrapper.GSS_S_CONTINUE_NEEDED) {
            /* gss_init_sec_context needs to be called again with output
               token from gss_accept_sec_context. */
            ctxState = State.INPROG;
        } else if (maj_status != gsswrapper.GSS_S_COMPLETE) {
            throw new GSSExceptionImpl((int) maj_status, (int) min_status[0]);
        } else {
            ctxState = State.DONE;
        }

        /* save native context */
        internGSSCtx = context_tmp;

        /* set some context variables */
        this.lifetime = (int) time_rec[0];
        mech = new OidImpl(actual_mech_type.toDotString());
        setReturnedFlags(actual_flags[0]);

        /* set our context as an initiator */
        this.initiator = true;

        /* place output token into OutputStream */
        if (outputToken.getLength() > 0) {
            temp_token = new byte[(int) outputToken.getLength()];
            temp_token = gsswrapper.getDescArray(outputToken);
            try {
                outStream.write(temp_token);
            } catch (IOException e) {
                throw new GSSException(GSSException.FAILURE);
            }
            ret = temp_token.length;
        } else {
            ret = 0;
        }

        /* release native structures */
        gsswrapper.gss_release_buffer(min_status, outputToken);
        gsswrapper.gss_release_buffer(min_status, inputToken);

        return ret;

    } /* end initSecContext() */

    public byte[] acceptSecContext(byte[] inTok, int offset, int len)
        throws GSSException{

        ByteArrayInputStream bis = new ByteArrayInputStream(inTok,
                offset, len);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        acceptSecContext(bis, bos);

        if (bos.size() > 0) {
            return bos.toByteArray();
        } else {
            return null;
        }

    } /* end acceptSecContext() */

    public void acceptSecContext(InputStream inStream, OutputStream outStream)
        throws GSSException {

        long maj_status     = 0;
        long requestedFlags = 0;
        long[] min_status   = {0};
        long[] actual_flags = {0};
        long[] time_rec     = {0};
        byte[] inputTokArray;
        gss_ctx_id_t_desc context_tmp;
        gss_OID_desc actual_mech_type = new gss_OID_desc();
        gss_buffer_desc outputToken = new gss_buffer_desc();
        gss_buffer_desc inputToken = new gss_buffer_desc();
        gss_cred_id_t_desc delegatedCred = new gss_cred_id_t_desc();
        ByteArrayOutputStream outTok = new ByteArrayOutputStream();

        /* setup temporary context */
        if (ctxState == State.UNINIT) {
            context_tmp = gsswrapper.GSS_C_NO_CONTEXT;
        } else {
            context_tmp = internGSSCtx;
        }

        /* if srcName is null, set it up */
        if (srcName == null) {
            srcName = new GSSNameImpl();
            srcName.setInternGSSName(null);
        }

        /* setup output token */
        outputToken.setLength(0);
        outputToken.setValue(null);

        try {
            if (inStream.available() > 0) {

                /* retrieve token header to get token length */
                DerHeader tokHeader = DerUtil.getHeader(inStream);

                /* put our header bytes back */
                outTok.write(tokHeader.getBytes());

                /* copy over the rest of the input token */
                for (int i = 0; i < tokHeader.getLength(); i++) {
                    outTok.write(inStream.read());
                }
            }

        } catch (IOException e) {
            /* I/O Error occurred when reading InputStream */
            throw new GSSException(GSSException.FAILURE);
        }

        /* read token into byte array, gss_buffer_desc for native gssapi */
        inputTokArray = outTok.toByteArray();
        if (inputTokArray != null && inputTokArray.length > 0) {
            gsswrapper.setDescArray(inputToken, inputTokArray);
            inputToken.setLength(inputTokArray.length);
        }

        requestedFlags = getRequestedFlags();

        maj_status = gsswrapper.gss_accept_sec_context(min_status,
                context_tmp,
                credential.getInternGSSCred(),
                inputToken,
                channelBinding.getNativeChannelBindings(),
                srcName.getInternGSSName(),
                actual_mech_type,
                outputToken,
                actual_flags,
                time_rec,
                delegatedCred);

        if (maj_status == gsswrapper.GSS_S_CONTINUE_NEEDED) {
            ctxState = State.INPROG;
        } else if (maj_status != gsswrapper.GSS_S_COMPLETE) {
            throw new GSSExceptionImpl((int)maj_status, (int)min_status[0]);
        } else {
            ctxState = State.DONE;
        }

        /* set context */
        internGSSCtx = context_tmp;

        /* save some context variables */
        this.lifetime = time_rec[0];
        mech = new OidImpl(actual_mech_type.toDotString());
        setReturnedFlags(actual_flags[0]);

        if (delegCredential == null)
            delegCredential = new GSSCredentialImpl();
        delegCredential.setInternGSSCred(delegatedCred);
       
        /* set our context as an acceptor */
        this.initiator = false;

        /* place output token into OutputStream */
        if (outputToken.getLength() > 0) {
            byte[] temp_token = new byte[(int) outputToken.getLength()];
            temp_token = gsswrapper.getDescArray(outputToken);
            try {
                outStream.write(temp_token);
            } catch (IOException e) {
                throw new GSSException(GSSException.FAILURE);
            }
        }

        /* release native structures */
        gsswrapper.gss_release_buffer(min_status, outputToken);
        gsswrapper.gss_release_buffer(min_status, inputToken);
        gsswrapper.gss_release_cred(min_status, delegatedCred);

    } /* end acceptSecContext() */

    public boolean isEstablished() {

        if (ctxState == State.DONE)
            return true;
        return false;

    }

    /**
     * Deletes one end of the security context, also deleting local data
     * structures associated with the security context. This needs to be
     * called on both initiator and acceptor sides to close both ends of
     * the security context.
     */
    public void dispose() throws GSSException {
       
        if (!invalid) {

            long maj_status   = 0;
            long[] min_status = {0};
            gss_buffer_desc output_token = gsswrapper.GSS_C_NO_BUFFER;

            maj_status = gsswrapper.gss_delete_sec_context(min_status,
                    this.internGSSCtx,
                    output_token);

            if (maj_status != gsswrapper.GSS_S_COMPLETE) {
                throw new GSSExceptionImpl((int) maj_status,
                        (int) min_status[0]);
            }
            gsswrapper.gss_release_buffer(min_status, output_token);

            if (mech != null)
                mech.freeOid();

            if (srcName != null)
                srcName.freeGSSName();

            if (targetName != null)
                targetName.freeGSSName();

            if (delegCredential != null)
                delegCredential.freeGSSCredential();

            this.invalid = true;
            ctxState = State.DISPOSED;
            srcName = null;
            targetName = null;
            credential = null;
            delegCredential = null;
        }

    } /* end dispose() */

    public int getWrapSizeLimit(int qop, boolean confReq, int maxTokenSize)
        throws GSSException {

        long maj_status   = 0;
        long[] min_status = {0};
        long[] max_size   = {0};
        int conf_req      = 0;

        if(confReq)
            conf_req = 1;

        maj_status = gsswrapper.gss_wrap_size_limit(min_status,
                this.internGSSCtx, conf_req, (long) qop,
                (long) maxTokenSize, max_size);

        if (maj_status != gsswrapper.GSS_S_COMPLETE) {
            throw new GSSExceptionImpl((int) maj_status, (int) min_status[0]);
        }

        return (int)max_size[0];

    } /* end getWrapSizeLimit() */

    public byte[] wrap(byte[] inBuf, int offset, int len, MessageProp msgProp)
        throws GSSException {

       ByteArrayInputStream bis = new ByteArrayInputStream(inBuf, offset, len);
       ByteArrayOutputStream bos = new ByteArrayOutputStream();

       wrap(bis, bos, msgProp);

       return bos.toByteArray();

    } /* end wrap() */

    public void wrap(InputStream inStream, OutputStream outStream,
            MessageProp msgProp) throws GSSException {

        int conf_req      = 0;
        int numBytes      = 0;
        int[] state       = {0};
        long maj_status   = 0;
        long[] min_status = {0};
        byte[] inMsg, temp_msg;
        gss_buffer_desc outputMsg = new gss_buffer_desc();
        gss_buffer_desc inputMsg = new gss_buffer_desc();
        ByteArrayOutputStream inMsgTmp = new ByteArrayOutputStream();

        try {

            /* grab the msg byte[] from inputStream */
            numBytes = inStream.available();
            inMsg = new byte[numBytes];
            for (int i = 0; i < numBytes; i++) {
                inMsgTmp.write(inStream.read());
            }

        } catch (IOException e) {
            throw new GSSException(GSSException.FAILURE);
        }
        inMsg = inMsgTmp.toByteArray();

        /* copy input message to gss_buffer_desc for native wrap() */
        if (inMsg != null) {
            gsswrapper.setDescArray(inputMsg, inMsg);
            inputMsg.setLength(inMsg.length);
        }

        /* determine requested level of confidentiality and integrity */
        if (msgProp.getPrivacy())
            conf_req = 1;

        maj_status = gsswrapper.gss_wrap(min_status, this.internGSSCtx,
                conf_req, msgProp.getQOP(), inputMsg, state, outputMsg);

        if (maj_status != gsswrapper.GSS_S_COMPLETE) {
            throw new GSSExceptionImpl((int) maj_status, (int) min_status[0]);
        }
       
        /* set the actual privacy state applied for caller to use */
        if (state[0] == 0) {
            msgProp.setPrivacy(false);
        } else {
            msgProp.setPrivacy(true);
        }

        /* get the byte[] from our outputMsg, copy back to OutputStream */
        if (outputMsg.getLength() > 0) {
            temp_msg = new byte[(int) outputMsg.getLength()];
            temp_msg = gsswrapper.getDescArray(outputMsg);
            try {
                outStream.write(temp_msg);
            } catch (IOException e) {
                throw new GSSException(GSSException.FAILURE);
            }
        }

        /* release native structures */
        gsswrapper.gss_release_buffer(min_status, outputMsg);
        gsswrapper.gss_release_buffer(min_status, inputMsg);
       
    } /* end wrap() */

    public byte[] unwrap(byte[] inBuf, int offset, int len,
            MessageProp msgProp) throws GSSException {

        ByteArrayInputStream bis = new ByteArrayInputStream(inBuf, offset, len);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        unwrap(bis, bos, msgProp);

        return bos.toByteArray();

    } /* end unwrap() */

    public void unwrap(InputStream inStream, OutputStream outStream,
            MessageProp msgProp) throws GSSException {

        int numBytes      = 0;
        int[] conf_state  = {0};
        long maj_status   = 0;
        long[] min_status = {0};
        long[] qop_state  = {0};
        byte[] inMsg;
        boolean tokDup    = false;
        boolean tokOld    = false;
        boolean tokUnseq  = false;
        boolean tokGap    = false;
        gss_buffer_desc outputMsg = new gss_buffer_desc();
        gss_buffer_desc inputMsg = new gss_buffer_desc();
        ByteArrayOutputStream inMsgTmp = new ByteArrayOutputStream();

        try {

            /* grab the msg byte[] from inputStream */
            numBytes = inStream.available();
            inMsg = new byte[numBytes];
            for (int i = 0; i < numBytes; i++) {
                inMsgTmp.write(inStream.read());
            }

        } catch (IOException e) {
            throw new GSSException(GSSException.FAILURE);
        }
        inMsg = inMsgTmp.toByteArray();

        /* copy input message to gss_buffer_desc for native unwrap() */
        if (inMsg != null) {
            gsswrapper.setDescArray(inputMsg, inMsg);
            inputMsg.setLength(inMsg.length);
        }

        maj_status = gsswrapper.gss_unwrap(min_status, this.internGSSCtx,
                inputMsg, outputMsg, conf_state, qop_state);

        if (maj_status != gsswrapper.GSS_S_COMPLETE) {
            throw new GSSExceptionImpl((int) maj_status, (int) min_status[0]);
        } else {

            /* set supplementary info */
            if ((maj_status & gsswrapper.GSS_S_DUPLICATE_TOKEN) != 0)
                tokDup =  true;
            if ((maj_status & gsswrapper.GSS_S_OLD_TOKEN) != 0)
                tokOld =  true;
            if ((maj_status & gsswrapper.GSS_S_UNSEQ_TOKEN) != 0)
                tokUnseq =  true;
            if ((maj_status & gsswrapper.GSS_S_GAP_TOKEN) != 0)
                tokGap =  true;

            msgProp.setSupplementaryStates(tokDup, tokOld, tokUnseq, tokGap,
                    (int)min_status[0], "");
        }

        /* set the actual privacy and conf state applied for caller to use */
        if (conf_state[0] == 0) {
            msgProp.setPrivacy(false);
        } else {
            msgProp.setPrivacy(true);
        }

        msgProp.setQOP((int) qop_state[0]);

        /* get the byte[] from our outputMsg, copy back to OutputStream */
        if (outputMsg.getLength() > 0) {
            byte[] temp_msg = new byte[(int) outputMsg.getLength()];
            temp_msg = gsswrapper.getDescArray(outputMsg);
            gsswrapper.gss_release_buffer(min_status, outputMsg);
            try {
                outStream.write(temp_msg);
            } catch (IOException e) {
                throw new GSSException(GSSException.FAILURE);
            }
        }

        /* release native structures */
        gsswrapper.gss_release_buffer(min_status, outputMsg);
        gsswrapper.gss_release_buffer(min_status, inputMsg);

    } /* end unwrap() */

    public byte[] getMIC(byte[] inMsg, int offset, int len,
            MessageProp msgProp) throws GSSException {

        ByteArrayInputStream bis = new ByteArrayInputStream(inMsg, offset, len);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        getMIC(bis, bos, msgProp);

        return bos.toByteArray();

    } /* end getMIC() */

    public void getMIC(InputStream inStream, OutputStream outStream,
            MessageProp msgProp) throws GSSException {
      
        int numBytes      = 0;
        int desiredQOP    = 0;
        long maj_status   = 0;
        long[] min_status = {0};
        byte[] inMsg;
        gss_buffer_desc outputMsg = new gss_buffer_desc();
        gss_buffer_desc inputMsg = new gss_buffer_desc();
        ByteArrayOutputStream inMsgTmp = new ByteArrayOutputStream();

        try {

            /* grab the msg byte[] from InputStream */
            numBytes = inStream.available();
            inMsg = new byte[numBytes];
            for (int i = 0; i < numBytes; i++) {
                inMsgTmp.write(inStream.read());
            }
        } catch (IOException e) {
            throw new GSSException(GSSException.FAILURE);
        }
        inMsg = inMsgTmp.toByteArray();

        /* copy input message to gss_buffer_desc for native function */
        if (inMsg != null) {
            gsswrapper.setDescArray(inputMsg, inMsg);
            inputMsg.setLength(inMsg.length);
        }

        /* set default QOP if msgProp is null */
        if (msgProp != null)
            desiredQOP = msgProp.getQOP();

        maj_status = gsswrapper.gss_get_mic(min_status, this.internGSSCtx,
                msgProp.getQOP(), inputMsg, outputMsg);

        if (maj_status != gsswrapper.GSS_S_COMPLETE) {
            throw new GSSExceptionImpl((int) maj_status, (int) min_status[0]);
        }

        /* get the byte[] from our outputMsg, copy back to OutputStream */
        if (outputMsg.getLength() > 0) {
            byte[] temp_msg = new byte[(int) outputMsg.getLength()];
            temp_msg = gsswrapper.getDescArray(outputMsg);
            try {
                outStream.write(temp_msg);
            } catch (IOException e) {
                throw new GSSException(GSSException.FAILURE);
            }
        }

        /* release native structures */
        gsswrapper.gss_release_buffer(min_status, outputMsg);
        gsswrapper.gss_release_buffer(min_status, inputMsg);

    } /* end getMIC() */

    public void verifyMIC(byte[] inTok, int tokOffset, int tokLen,
            byte[] inMsg, int msgOffset, int msgLen,
            MessageProp msgProp) throws GSSException {

        ByteArrayInputStream tis = new ByteArrayInputStream(inTok,
                tokOffset, tokLen);
        ByteArrayInputStream mis = new ByteArrayInputStream(inMsg,
                msgOffset, msgLen);

        verifyMIC(tis, mis, msgProp);

    } /* end verifyMIC() */

    public void verifyMIC(InputStream tokStream, InputStream msgStream,
            MessageProp msgProp) throws GSSException {

        int numBytes;
        long maj_status   = 0;
        long[] min_status = {0};
        long[] qop_state  = {0};
        byte[] inTok, inMsg;
        boolean tokDup    = false;
        boolean tokOld    = false;
        boolean tokUnseq  = false;
        boolean tokGap    = false;
        gss_buffer_desc inputTok = new gss_buffer_desc();
        gss_buffer_desc inputMsg = new gss_buffer_desc();
        ByteArrayOutputStream inTokTmp = new ByteArrayOutputStream();
        ByteArrayOutputStream inMsgTmp = new ByteArrayOutputStream();

        try {

            /* grab the token byte[] from tokStream */
            numBytes = tokStream.available();
            inTok = new byte[numBytes];
            for (int i = 0; i < numBytes; i++) {
                inTokTmp.write(tokStream.read());
            }

            /* grab the msg byte[] from msgStream */
            numBytes = msgStream.available();
            inMsg = new byte[numBytes];
            for (int i = 0; i < numBytes; i++) {
                inMsgTmp.write(msgStream.read());
            }

        } catch (IOException e) {
            throw new GSSException(GSSException.FAILURE);
        }

        inTok = inTokTmp.toByteArray();
        inMsg = inMsgTmp.toByteArray();

        /* copy input token to gss_buffer_desc */
        if (inTok != null) {
            gsswrapper.setDescArray(inputTok, inTok);
            inputTok.setLength(inTok.length);
        }

        /* copy input msg to gss_buffer_desc */
        if (inMsg != null) {
            gsswrapper.setDescArray(inputMsg, inMsg);
            inputMsg.setLength(inMsg.length);
        }

        maj_status = gsswrapper.gss_verify_mic(min_status,
                this.internGSSCtx, inputMsg, inputTok, qop_state);

        if (maj_status != gsswrapper.GSS_S_COMPLETE) {
            throw new GSSExceptionImpl((int) maj_status, (int) min_status[0]);
        } else {

            /* save supplementary info */
            if ((maj_status & gsswrapper.GSS_S_DUPLICATE_TOKEN) != 0)
                tokDup = true;
            if ((maj_status & gsswrapper.GSS_S_OLD_TOKEN) != 0)
                tokOld = true;
            if ((maj_status & gsswrapper.GSS_S_UNSEQ_TOKEN) != 0)
                tokUnseq = true;
            if ((maj_status & gsswrapper.GSS_S_GAP_TOKEN) != 0)
                tokGap = true;

            msgProp.setSupplementaryStates(tokDup, tokOld, tokUnseq, tokGap,
                    (int) min_status[0], "");
        }

        /* save qop */
        msgProp.setQOP((int) qop_state[0]);

        /* release native structures */
        gsswrapper.gss_release_buffer(min_status, inputTok);
        gsswrapper.gss_release_buffer(min_status, inputMsg);

    } /* end verifyMIC() */

    public byte[] export() throws GSSException {

        long maj_status   = 0;
        long[] min_status = {0};
        byte[] outTok     = null;
        gss_buffer_desc outputToken = new gss_buffer_desc();

        maj_status = gsswrapper.gss_export_sec_context(min_status,
                this.internGSSCtx,
                outputToken);

        if (maj_status != gsswrapper.GSS_S_COMPLETE) {
            throw new GSSExceptionImpl((int) maj_status, (int) min_status[0]);
        }

        if (outputToken.getLength() > 0) {
            outTok = new byte[(int) outputToken.getLength()];
            outTok = gsswrapper.getDescArray(outputToken);
        }

        /* release native structures */
        gsswrapper.gss_release_buffer(min_status, outputToken);

        return outTok;

    } /* end export() */

    public void requestMutualAuth(boolean state) throws GSSException {
        if (ctxState == State.UNINIT && initiator)
            requestMutualAuth = true;
    }

    public void requestReplayDet(boolean state) throws GSSException {
        if (ctxState == State.UNINIT && initiator)
            requestReplayDet = true;
    }

    public void requestSequenceDet(boolean state) throws GSSException {
        if (ctxState == State.UNINIT && initiator)
            requestSequenceDet = true;
    }

    public void requestCredDeleg(boolean state) throws GSSException {
        if (ctxState == State.UNINIT && initiator)
            requestCredDeleg = true;
    }

    public void requestAnonymity(boolean state) throws GSSException {
        if (ctxState == State.UNINIT && initiator)
            requestAnonymity = true;
    }

    public void requestConf(boolean state) throws GSSException {
        if (ctxState == State.UNINIT && initiator)
            requestConf = true;
    }

    public void requestInteg(boolean state) throws GSSException {
        if (ctxState == State.UNINIT && initiator)
            requestInteg = true;
    }

    public void requestLifetime(int lifetime) throws GSSException {
        if (ctxState == State.UNINIT && initiator)
            this.lifetime = lifetime;
    }

    public void setChannelBinding(ChannelBinding cb) throws GSSException {
        if (ctxState == State.UNINIT)
            channelBinding = (ChannelBindingImpl) cb;
    }

    public boolean getCredDelegState() {
        return requestCredDeleg;
    }

    public boolean getMutualAuthState() {
        return requestMutualAuth;
    }

    public boolean getReplayDetState() {
        return requestReplayDet;
    }

    public boolean getSequenceDetState() {
        return requestSequenceDet;
    }

    public boolean getAnonymityState() {
        return requestAnonymity;
    }

    public boolean isTransferable() throws GSSException {
        if (ctxState == State.DONE)
            return isTransferable;
        return false;
    }

    public boolean isProtReady() {
        return isProtReady;
    }

    public boolean getConfState() {
        return requestConf;
    }

    public boolean getIntegState() {
        return requestInteg;
    }

    public int getLifetime() {
        if (lifetime == gsswrapper.GSS_C_INDEFINITE) {
            return GSSContext.INDEFINITE_LIFETIME;
        }
        return (int) lifetime;
    }

    public GSSName getSrcName() {
        if (ctxState == State.DONE || isProtReady())
            return srcName;
        return null;
    }

    public GSSName getTargName() {
        if (ctxState == State.DONE || isProtReady())
            return targetName;
        return null;
    }

    public Oid getMech() throws GSSException {
        return mech;
    }

    public GSSCredential getDelegCred() throws GSSException {
        if (ctxState == State.DONE) {
            return delegCredential;
        }
        return null;
    }

    public boolean isInitiator() throws GSSException {
        if (ctxState == State.INPROG || ctxState == State.DONE)
            return initiator;
        return false;
    }

    private long getRequestedFlags() {
   
        long requestedFlags = 0;

        if (requestCredDeleg)
            requestedFlags ^= gsswrapper.GSS_C_DELEG_FLAG;
        if (requestMutualAuth)
            requestedFlags ^= gsswrapper.GSS_C_MUTUAL_FLAG;
        if (requestReplayDet)
            requestedFlags ^= gsswrapper.GSS_C_REPLAY_FLAG;
        if (requestSequenceDet)
            requestedFlags ^= gsswrapper.GSS_C_SEQUENCE_FLAG;
        if (requestConf)
            requestedFlags ^= gsswrapper.GSS_C_CONF_FLAG;
        if (requestInteg)
            requestedFlags ^= gsswrapper.GSS_C_INTEG_FLAG;
        if (requestAnonymity)
            requestedFlags ^= gsswrapper.GSS_C_ANON_FLAG;

        return requestedFlags;

    } /* end getRequestedFlags() */

    private void setReturnedFlags(long retFlags) {

        /* since request*() methods are only valid before context
           creation, we'll just re-use those variables to indicate the
           current flags of the established context as well */

        // clear current flag values
        requestAnonymity = false;
        requestConf = false;
        requestCredDeleg = false;
        requestInteg = false;
        requestMutualAuth = false;
        requestReplayDet = false;
        requestSequenceDet = false;
        isProtReady = false;
        isTransferable = false;

        // set the new flags
        if ((retFlags & gsswrapper.GSS_C_ANON_FLAG) != 0)
            requestAnonymity = true;
        if ((retFlags & gsswrapper.GSS_C_CONF_FLAG) != 0)
            requestConf = true;
        if ((retFlags & gsswrapper.GSS_C_DELEG_FLAG) != 0)
            requestCredDeleg = true;
        if ((retFlags & gsswrapper.GSS_C_INTEG_FLAG) != 0)
            requestInteg = true;
        if ((retFlags & gsswrapper.GSS_C_MUTUAL_FLAG) != 0)
            requestMutualAuth = true;
        if ((retFlags & gsswrapper.GSS_C_REPLAY_FLAG) != 0)
            requestReplayDet = true;
        if ((retFlags & gsswrapper.GSS_C_SEQUENCE_FLAG) != 0)
            requestSequenceDet = true;
        if ((retFlags & gsswrapper.GSS_C_PROT_READY_FLAG) != 0)
            isProtReady = true;
        if ((retFlags & gsswrapper.GSS_C_TRANS_FLAG) != 0)
            isTransferable = true;

    } /* end setReturnedFlags() */

    private long convertLifetime(int smLife) {

        if (smLife == GSSContext.INDEFINITE_LIFETIME) {
            return gsswrapper.GSS_C_INDEFINITE;
        }

        return (long) smLife;

    } /* end convertLifetime() */

TOP

Related Classes of edu.mit.jgss.GSSContextImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.