You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by co...@apache.org on 2017/07/24 11:50:48 UTC

[07/18] directory-kerby git commit: Revert "Refactoring the package and structure"

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/96494e9a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssTokenV2.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssTokenV2.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssTokenV2.java
deleted file mode 100644
index 5220900..0000000
--- a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssTokenV2.java
+++ /dev/null
@@ -1,282 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- *
- */
-package org.apache.kerby.kerberos.kerb.gss.impl;
-
-import org.ietf.jgss.GSSException;
-import org.ietf.jgss.MessageProp;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.security.MessageDigest;
-
-/**
- * This class implements the token formats defined in RFC 4121.
- */
-abstract class GssTokenV2 extends GssTokenBase {
-    public static final int CONFOUNDER_SIZE = 16;
-    public static final int TOKEN_HEADER_SIZE = 16;
-    private static final int OFFSET_EC = 4;
-    private static final int OFFSET_RRC = 6;
-
-    // context states
-    private boolean isInitiator = true;
-    private boolean acceptorSubKey = false;
-    private boolean confState = true;
-    private int sequenceNumber;
-
-    // token data
-    protected int tokenType;
-    private byte[] header = new byte[TOKEN_HEADER_SIZE];
-    protected byte[] tokenData;
-
-    protected byte[] checkSum;
-    private int ec;
-    private int rrc;
-
-    static final int KG_USAGE_ACCEPTOR_SEAL = 22;
-    static final int KG_USAGE_ACCEPTOR_SIGN = 23;
-    static final int KG_USAGE_INITIATOR_SEAL = 24;
-    static final int KG_USAGE_INITIATOR_SIGN = 25;
-    private int keyUsage;
-
-    private static final int FLAG_SENT_BY_ACCEPTOR = 1;
-    private static final int FLAG_SEALED = 2;
-    private static final int FLAG_ACCEPTOR_SUBKEY = 4;
-
-    protected GssEncryptor encryptor;
-
-
-    // Create a new token
-    GssTokenV2(int tokenType, GssContext context) throws GSSException {
-        initialize(tokenType, context, false);
-    }
-
-    private void initialize(int tokenType, GssContext context, boolean reconstruct) throws GSSException {
-        this.tokenType = tokenType;
-        this.isInitiator = context.isInitiator();
-        this.acceptorSubKey = context.getKeyComesFrom() == GssContext.ACCEPTOR_SUBKEY;
-        this.confState = context.getConfState();
-
-        boolean usageFlag = reconstruct ? !this.isInitiator : this.isInitiator;
-        if (tokenType == TOKEN_WRAP_V2) {
-            keyUsage = usageFlag ? KG_USAGE_INITIATOR_SEAL : KG_USAGE_ACCEPTOR_SEAL;
-        } else if (tokenType == TOKEN_MIC_V2) {
-            keyUsage = usageFlag ? KG_USAGE_INITIATOR_SIGN : KG_USAGE_ACCEPTOR_SIGN;
-        }
-
-        encryptor = context.getGssEncryptor();
-
-        if (!reconstruct) {
-            this.sequenceNumber = context.incMySequenceNumber();
-        }
-    }
-
-    // Reconstruct token from bytes received
-    GssTokenV2(int tokenType, GssContext context,
-               MessageProp prop, byte[] token, int offset, int len) throws GSSException {
-        this(tokenType, context, prop, new ByteArrayInputStream(token, offset, len));
-    }
-
-    // Reconstruct token from input stream
-    GssTokenV2(int tokenType, GssContext context,
-               MessageProp prop, InputStream is) throws GSSException {
-        initialize(tokenType, context, true);
-
-        if (!confState) {
-            prop.setPrivacy(false);
-        }
-
-        reconstructTokenHeader(prop, is);
-
-        int minSize;
-        if (tokenType == TOKEN_WRAP_V2 && prop.getPrivacy()) {
-            minSize = CONFOUNDER_SIZE + TOKEN_HEADER_SIZE + encryptor.getCheckSumSize();
-        } else {
-            minSize = encryptor.getCheckSumSize();
-        }
-
-        try {
-            int tokenLen = is.available();
-
-            if (tokenType == TOKEN_MIC_V2) {
-                tokenLen = minSize;
-                tokenData = new byte[tokenLen];
-                is.read(tokenData);
-            } else {
-                if (tokenLen >= minSize) {
-                    tokenData = new byte[tokenLen];
-                    is.read(tokenData);
-                } else {
-                    throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1, "Invalid token length");
-                }
-            }
-
-            if (tokenType == TOKEN_WRAP_V2) {
-                tokenData = rotate(tokenData);
-            }
-
-            if (tokenType == TOKEN_MIC_V2
-                    || tokenType == TOKEN_WRAP_V2 && !prop.getPrivacy()) {
-                int checksumLen = encryptor.getCheckSumSize();
-
-                if (tokenType != TOKEN_MIC_V2 && checksumLen != ec) {
-                    throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1, "Invalid EC");
-                }
-
-                checkSum = new byte[checksumLen];
-                System.arraycopy(tokenData, tokenLen - checksumLen, checkSum, 0, checksumLen);
-            }
-        } catch (IOException e) {
-            throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1, "Invalid token");
-        }
-    }
-
-    private byte[] rotate(byte[] data) {
-        int dataLen = data.length;
-        if (rrc % dataLen != 0) {
-            rrc = rrc % dataLen;
-            byte[] newBytes = new byte[dataLen];
-
-            System.arraycopy(data, rrc, newBytes, 0, dataLen - rrc);
-            System.arraycopy(data, 0, newBytes, dataLen - rrc, rrc);
-            data = newBytes;
-        }
-        return data;
-    }
-
-    public int getKeyUsage() {
-        return keyUsage;
-    }
-
-    public void generateCheckSum(MessageProp prop, byte[] data, int offset, int len) throws GSSException {
-        // generate token header
-        createTokenHeader(prop.getPrivacy());
-
-        if (tokenType == TOKEN_MIC_V2
-                || !prop.getPrivacy() && tokenType == TOKEN_WRAP_V2) {
-            checkSum = getCheckSum(data, offset, len);
-        }
-
-        if (!prop.getPrivacy() && tokenType == TOKEN_WRAP_V2) {
-            header[4] = (byte) (checkSum.length >>> 8);
-            header[5] = (byte) (checkSum.length & 0xFF);
-        }
-    }
-
-    public byte[] getCheckSum(byte[] data, int offset, int len) throws GSSException {
-        int confidentialFlag = header[2] & 2;
-        if (confidentialFlag == 0 && tokenType == TOKEN_WRAP_V2) {
-            header[4] = 0;
-            header[5] = 0;
-            header[6] = 0;
-            header[7] = 0;
-        }
-        return encryptor.calculateCheckSum(header, data, offset, len, keyUsage);
-    }
-
-    public boolean verifyCheckSum(byte[] data, int offset, int len) throws GSSException {
-        byte[] dataCheckSum = getCheckSum(data, offset, len);
-        return MessageDigest.isEqual(checkSum, dataCheckSum);
-    }
-
-    // Create a new header
-    private void createTokenHeader(boolean privacy) {
-        header[0] = (byte) (tokenType >>> 8);
-        header[1] = (byte) tokenType;
-
-        int flags = isInitiator ? 0 : FLAG_SENT_BY_ACCEPTOR;
-        flags |= privacy && tokenType != TOKEN_MIC_V2 ? FLAG_SEALED : 0;
-        flags |= acceptorSubKey ? FLAG_ACCEPTOR_SUBKEY : 0;
-
-        header[2] = (byte) (flags & 0xFF);
-        header[3] = (byte) 0xFF;
-
-        if (tokenType == TOKEN_WRAP_V2) {
-            header[4] = (byte) 0;
-            header[5] = (byte) 0;
-            header[6] = (byte) 0;
-            header[7] = (byte) 0;
-        } else if (tokenType == TOKEN_MIC_V2) {
-            header[4] = (byte) 0xFF;
-            header[5] = (byte) 0xFF;
-            header[6] = (byte) 0xFF;
-            header[7] = (byte) 0xFF;
-        }
-        writeBigEndian(header, 12, sequenceNumber);
-    }
-
-    // Reconstruct a token header
-    private void reconstructTokenHeader(MessageProp prop, InputStream is) throws GSSException {
-        try {
-            if (is.read(header, 0, header.length) != header.length) {
-                throw new GSSException(GSSException.FAILURE, -1, "Token header can not be read");
-            }
-            int tokenIDRecv = (((int) header[0]) << 8) + header[1];
-            if (tokenIDRecv != tokenType) {
-                throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
-                        "Token ID should be " + tokenType + " instead of " + tokenIDRecv);
-            }
-
-            int senderFlag = isInitiator ? FLAG_SENT_BY_ACCEPTOR : 0;
-            int senderFlagRecv = header[2] & FLAG_SENT_BY_ACCEPTOR;
-            if (senderFlagRecv != senderFlag) {
-                throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1, "Invalid acceptor flag");
-            }
-
-            int confFlagRecv = header[2] & FLAG_SEALED;
-            if (confFlagRecv == FLAG_SEALED && tokenType == TOKEN_WRAP_V2) {
-                prop.setPrivacy(true);
-            } else {
-                prop.setPrivacy(false);
-            }
-
-            if (tokenType == TOKEN_WRAP_V2) {
-                if (header[3] != (byte) 0xFF) {
-                    throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1, "Invalid token filler");
-                }
-
-                ec = readBigEndian(header, OFFSET_EC, 2);
-                rrc = readBigEndian(header, OFFSET_RRC, 2);
-            } else if (tokenType == TOKEN_MIC_V2) {
-                for (int i = 3; i < 8; i++) {
-                    if ((header[i] & 0xFF) != 0xFF) {
-                        throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1, "Invalid token filler");
-                    }
-                }
-            }
-
-            prop.setQOP(0);
-            sequenceNumber = readBigEndian(header, 0, 8);
-        } catch (IOException e) {
-            throw new GSSException(GSSException.FAILURE, -1, "Phrase token header failed");
-        }
-    }
-
-    public int encodeHeader(byte[] buf, int offset) {
-        System.arraycopy(header, 0, buf, offset, TOKEN_HEADER_SIZE);
-        return TOKEN_HEADER_SIZE;
-    }
-
-    public void encodeHeader(OutputStream os) throws IOException {
-        os.write(header);
-    }
-}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/96494e9a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssUtil.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssUtil.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssUtil.java
deleted file mode 100644
index 372abcb..0000000
--- a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssUtil.java
+++ /dev/null
@@ -1,386 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- *
- */
-package org.apache.kerby.kerberos.kerb.gss.impl;
-
-import org.apache.kerby.kerberos.kerb.KrbException;
-import org.apache.kerby.kerberos.kerb.client.KrbClientBase;
-import org.apache.kerby.kerberos.kerb.type.KerberosTime;
-import org.apache.kerby.kerberos.kerb.type.ad.AuthorizationData;
-import org.apache.kerby.kerberos.kerb.type.ad.AuthorizationDataEntry;
-import org.apache.kerby.kerberos.kerb.type.base.EncryptionKey;
-import org.apache.kerby.kerberos.kerb.type.base.HostAddress;
-import org.apache.kerby.kerberos.kerb.type.base.HostAddresses;
-import org.apache.kerby.kerberos.kerb.type.base.PrincipalName;
-import org.apache.kerby.kerberos.kerb.type.kdc.EncAsRepPart;
-import org.apache.kerby.kerberos.kerb.type.kdc.EncKdcRepPart;
-import org.apache.kerby.kerberos.kerb.type.kdc.EncTgsRepPart;
-import org.apache.kerby.kerberos.kerb.type.ticket.KrbTicket;
-import org.apache.kerby.kerberos.kerb.type.ticket.SgtTicket;
-import org.apache.kerby.kerberos.kerb.type.ticket.TgtTicket;
-import org.apache.kerby.kerberos.kerb.type.ticket.Ticket;
-import org.apache.kerby.kerberos.kerb.type.ticket.TicketFlags;
-import org.ietf.jgss.GSSException;
-import sun.security.jgss.GSSCaller;
-
-import javax.crypto.SecretKey;
-import javax.security.auth.kerberos.KerberosKey;
-import javax.security.auth.kerberos.KerberosPrincipal;
-import javax.security.auth.kerberos.KerberosTicket;
-import java.io.File;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.Date;
-import java.util.List;
-
-/**
- * Some utility functions to translate types between GSS and Kerby
- */
-public class GssUtil {
-    private static final int KERBEROS_TICKET_NUM_FLAGS = 32;  // KerberosTicket.NUM_LENGTH
-
-    /**
-     * Construct TgtTicket from info contained in KerberosTicket
-     * @param kerberosTicket
-     * @return
-     * @throws GSSException
-     */
-    public static TgtTicket getTgtTicketFromKerberosTicket(KerberosTicket kerberosTicket) throws GSSException {
-        String clientName = kerberosTicket.getClient().getName();
-        PrincipalName clientPrincipal = new PrincipalName(clientName);
-
-        byte[] asn1Encoded = kerberosTicket.getEncoded();
-        Ticket ticket = getTicketFromAsn1Encoded(asn1Encoded);
-
-        EncAsRepPart encAsRepPart = new EncAsRepPart();
-        fillEncKdcRepPart(encAsRepPart, kerberosTicket);
-
-        TgtTicket tgt = new TgtTicket(ticket, encAsRepPart, clientPrincipal);
-        return tgt;
-    }
-
-    /**
-     *  Init encKdcRepPart members with info from kerberosTicket
-     * @param encKdcRepPart
-     * @param kerberosTicket
-     */
-    public static void fillEncKdcRepPart(EncKdcRepPart encKdcRepPart, KerberosTicket kerberosTicket) {
-        String clientName = kerberosTicket.getClient().getName();
-        PrincipalName clientPrincipal = new PrincipalName(clientName);
-
-        SecretKey secretKey = kerberosTicket.getSessionKey();
-        int keyType = kerberosTicket.getSessionKeyType();
-        EncryptionKey key = new EncryptionKey(keyType, secretKey.getEncoded());
-        encKdcRepPart.setKey(key);
-
-        encKdcRepPart.setSname(clientPrincipal);
-        Date authTimeDate = kerberosTicket.getAuthTime();
-        if (authTimeDate != null) {
-            encKdcRepPart.setAuthTime(new KerberosTime(authTimeDate.getTime()));
-        }
-        Date startTimeDate = kerberosTicket.getStartTime();
-        if (startTimeDate != null) {
-            encKdcRepPart.setStartTime(new KerberosTime(startTimeDate.getTime()));
-        }
-        KerberosTime endTime = new KerberosTime(kerberosTicket.getEndTime().getTime());
-        encKdcRepPart.setEndTime(endTime);
-
-
-        InetAddress[] clientAddresses = kerberosTicket.getClientAddresses();
-        HostAddresses hostAddresses = null;
-        if (clientAddresses != null) {
-            hostAddresses = new HostAddresses();
-            for (InetAddress iAddr : clientAddresses) {
-                hostAddresses.add(new HostAddress(iAddr));
-            }
-        }
-        encKdcRepPart.setCaddr(hostAddresses);
-
-        boolean[] tf = kerberosTicket.getFlags();
-        TicketFlags ticketFlags = getTicketFlags(tf);
-        encKdcRepPart.setFlags(ticketFlags);
-
-
-        /* encKdcRepPart.setKeyExpiration();
-        encKdcRepPart.setLastReq();
-        encKdcRepPart.setNonce(); */
-
-        Date renewTillDate = kerberosTicket.getRenewTill();
-        KerberosTime renewTill = renewTillDate == null ? null : new KerberosTime(renewTillDate.getTime());
-        encKdcRepPart.setRenewTill(renewTill);
-
-        String serverRealm = kerberosTicket.getServer().getRealm();
-        encKdcRepPart.setSrealm(serverRealm);
-    }
-
-    /**
-     * Generate TicketFlags instance from flags
-     * @param flags each item in flags identifies an bit setted or not
-     * @return
-     */
-    public static TicketFlags getTicketFlags(boolean[] flags) {
-        if (flags == null || flags.length != KERBEROS_TICKET_NUM_FLAGS) {
-            return null;
-        }
-        int value = 0;
-        for (boolean flag : flags) {
-            value = (value << 1) + (flag ? 1 : 0);
-        }
-        return new TicketFlags(value);
-    }
-
-    /**
-     * Decode each flag in ticketFlags into an boolean array
-     * @param ticketFlags
-     * @return
-     */
-    public static boolean[] ticketFlagsToBooleans(TicketFlags ticketFlags) {
-        boolean[] ret = new boolean[KERBEROS_TICKET_NUM_FLAGS];
-        int value = ticketFlags.getFlags();
-        for (int i = 0; i < KERBEROS_TICKET_NUM_FLAGS; i++) {
-            ret[KERBEROS_TICKET_NUM_FLAGS - i - 1] = (value & 0x1) != 0;
-            value = value >> 1;
-        }
-        return ret;
-    }
-
-    /**
-     * Construct a Ticket from bytes encoded by Asn1
-     * @param encoded
-     * @return
-     * @throws GSSException
-     */
-    public static Ticket getTicketFromAsn1Encoded(byte[] encoded) throws GSSException {
-        Ticket ticket = new Ticket();
-        ByteBuffer byteBuffer = ByteBuffer.wrap(encoded);
-        try {
-            ticket.decode(byteBuffer);
-            return ticket;
-        } catch (IOException e) {
-            throw new GSSException(GSSException.FAILURE, -1, e.getMessage());
-        }
-    }
-
-    /**
-     * Scan current context for SgtTicket
-     * @param client
-     * @param service
-     * @return
-     */
-    public static SgtTicket getSgtCredentialFromContext(GSSCaller caller, String client, String service)
-            throws GSSException {
-        KerberosTicket ticket = CredUtils.getKerberosTicketFromContext(caller, client, service);
-        return getSgtTicketFromKerberosTicket(ticket);
-    }
-
-    /**
-     * Construct a SgtTicket from KerberosTicket
-     * @param kerberosTicket
-     * @return
-     * @throws GSSException
-     */
-    public static SgtTicket getSgtTicketFromKerberosTicket(KerberosTicket kerberosTicket) throws GSSException {
-        if (kerberosTicket == null) {
-            return null;
-        }
-
-        Ticket ticket = getTicketFromAsn1Encoded(kerberosTicket.getEncoded());
-
-        EncTgsRepPart encTgsRepPart = new EncTgsRepPart();
-        fillEncKdcRepPart(encTgsRepPart, kerberosTicket);
-
-        SgtTicket sgt = new SgtTicket(ticket, encTgsRepPart);
-        return sgt;
-    }
-
-    /**
-     *  Apply SgtTicket by sending TGS_REQ to KDC
-     * @param ticket
-     * @param service
-     * @return
-     */
-    public static SgtTicket applySgtCredential(KerberosTicket ticket, String service) throws GSSException {
-        TgtTicket tgt = getTgtTicketFromKerberosTicket(ticket);
-        return applySgtCredential(tgt, service);
-    }
-
-    public static SgtTicket applySgtCredential(TgtTicket tgt, String server) throws GSSException {
-        KrbClientBase client = getKrbClient();
-
-        SgtTicket sgt = null;
-        try {
-            client.init();
-            sgt = client.requestSgt(tgt, server);
-            return sgt;
-        } catch (KrbException e) {
-            throw new GSSException(GSSException.FAILURE, -1, e.getMessage());
-        }
-    }
-
-    public static KerberosTicket convertKrbTicketToKerberosTicket(KrbTicket krbTicket, String clientName)
-            throws GSSException {
-        byte[] asn1Encoding;
-        try {
-            asn1Encoding = krbTicket.getTicket().encode();
-        } catch (IOException e) {
-            throw new GSSException(GSSException.FAILURE, -1, e.getMessage());
-        }
-
-        byte[] sessionKey = krbTicket.getSessionKey().getKeyData();
-        int keyType = krbTicket.getSessionKey().getKeyType().getValue();
-
-        EncKdcRepPart encKdcRepPart = krbTicket.getEncKdcRepPart();
-        KerberosPrincipal client = new KerberosPrincipal(clientName);
-
-        PrincipalName serverPrinc = krbTicket.getTicket().getSname();
-        String serverName = serverPrinc.getName() + "@" + krbTicket.getTicket().getRealm();
-        KerberosPrincipal server = new KerberosPrincipal(serverName, serverPrinc.getNameType().getValue());
-
-        TicketFlags ticketFlags = encKdcRepPart.getFlags();
-        boolean[] flags = ticketFlagsToBooleans(ticketFlags);
-
-        Date authTime = new Date(encKdcRepPart.getAuthTime().getTime());
-        Date startTime = new Date(encKdcRepPart.getStartTime().getTime());
-        Date endTime = new Date(encKdcRepPart.getEndTime().getTime());
-        Date renewTill = new Date(encKdcRepPart.getRenewTill().getTime());
-
-        InetAddress[] clientAddresses = null;
-        List<HostAddress> hostAddresses = encKdcRepPart.getCaddr().getElements();
-        if (hostAddresses != null) {
-            int i = 0;
-            clientAddresses = new InetAddress[hostAddresses.size()];
-            for (HostAddress hostAddr : hostAddresses) {
-                try {
-                    InetAddress iAddr = InetAddress.getByAddress(hostAddr.getAddress());
-                    clientAddresses[i++] = iAddr;
-                } catch (UnknownHostException e) {
-                    throw new GSSException(GSSException.FAILURE, -1, "Bad client address");
-                }
-            }
-        }
-
-        KerberosTicket ticket = new KerberosTicket(
-                asn1Encoding,
-                client,
-                server,
-                sessionKey,
-                keyType,
-                flags,
-                authTime,
-                startTime,
-                endTime,
-                renewTill,
-                clientAddresses
-        );
-        return ticket;
-    }
-
-    public static KrbClientBase getKrbClient() {
-        KrbClientBase client;
-        try {
-            File confSpecified = new File(getSystemProperty("java.security.krb5.conf"));
-            if (confSpecified != null) {
-                client = new KrbClientBase(confSpecified);
-            } else {
-                client = new KrbClientBase();   // get configure file from environment variable or default path
-            }
-
-            return client;
-        } catch (KrbException e) {
-            return null;
-        }
-    }
-
-    public static EncryptionKey[] convertKerberosKeyToEncryptionKey(KerberosKey[] krbKeys) {
-        if (krbKeys == null) {
-            return null;
-        }
-        EncryptionKey[] keys = new EncryptionKey[krbKeys.length];
-        int i = 0;
-        for (KerberosKey krbKey : krbKeys) {
-            keys[i++] = new EncryptionKey(krbKey.getKeyType(), krbKey.getEncoded());
-        }
-        return keys;
-    }
-
-    /**
-     * Filter out an appropriate KerberosKey from krbKeys and generate a
-     * EncryptionKey accordingly
-     *
-     * @param krbKeys
-     * @param encType
-     * @param kvno
-     * @return
-     */
-    public static EncryptionKey getEncryptionKey(KerberosKey[] krbKeys, int encType, int kvno) {
-        if (krbKeys == null) {
-            return null;
-        }
-        for (KerberosKey krbKey : krbKeys) {
-            if (krbKey.getKeyType() == encType && krbKey.getVersionNumber() == kvno && !krbKey.isDestroyed()) {
-                return new EncryptionKey(krbKey.getKeyType(), krbKey.getEncoded());
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Get value of predefined system property
-     * @param name
-     * @return
-     */
-    private static String getSystemProperty(String name) {
-        if (name == null) {
-            return null;
-        }
-
-        final String propertyName = name;
-        try {
-            return AccessController.doPrivileged(
-                    new PrivilegedExceptionAction<String>() {
-                        public String run() {
-                            return System.getProperty(propertyName);
-                        }
-                    });
-        } catch (PrivilegedActionException e) {
-            return null;    // ignored
-        }
-    }
-
-    public static com.sun.security.jgss.AuthorizationDataEntry[]
-    kerbyAuthorizationDataToJgssAuthorizationDataEntries(AuthorizationData authData) {
-        if (authData == null) {
-            return null;
-        }
-        List<AuthorizationDataEntry> kerbyEntries = authData.getElements();
-        com.sun.security.jgss.AuthorizationDataEntry[] entries =
-                new com.sun.security.jgss.AuthorizationDataEntry[kerbyEntries.size()];
-        for (int i = 0; i < kerbyEntries.size(); i++) {
-            entries[i] = new com.sun.security.jgss.AuthorizationDataEntry(
-                    kerbyEntries.get(i).getAuthzType().getValue(),
-                    kerbyEntries.get(i).getAuthzData());
-        }
-        return entries;
-    }
-}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/96494e9a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/MicTokenV1.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/MicTokenV1.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/MicTokenV1.java
deleted file mode 100644
index 63baa6b..0000000
--- a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/MicTokenV1.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- *
- */
-package org.apache.kerby.kerberos.kerb.gss.impl;
-
-import org.ietf.jgss.GSSException;
-import org.ietf.jgss.MessageProp;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-public class MicTokenV1 extends GssTokenV1 {
-    public MicTokenV1(GssContext context,
-                       byte[] inMsg,
-                       int msgOffset,
-                       int msgLength,
-                       MessageProp messageProp) throws GSSException {
-        super(TOKEN_MIC_V1, context);
-        calcPrivacyInfo(messageProp, null, inMsg, msgOffset, msgLength, 0);
-    }
-
-    // This is called to construct MicToken from MicToken bytes
-    MicTokenV1(GssContext context,
-               MessageProp messageProp,
-               byte[] inToken,
-               int tokenOffset,
-               int tokenLength) throws GSSException {
-        super(TOKEN_MIC_V1, context, messageProp, inToken, tokenOffset, tokenLength);
-    }
-
-    public int getMic(byte[] outToken, int offset) throws GSSException, IOException {
-        byte[] data = getMic();
-        System.arraycopy(data, 0, outToken, offset, data.length);
-        return data.length;
-    }
-
-    /**
-     * Get bytes for this Mic token
-     * @return
-     */
-    public byte[] getMic() throws GSSException {
-        ByteArrayOutputStream os = new ByteArrayOutputStream(64);
-        getMic(os);
-        return os.toByteArray();
-    }
-
-    public void getMic(OutputStream os) throws GSSException {
-        try {
-            encodeHeader(os);
-        } catch (IOException e) {
-            throw new GSSException(GSSException.FAILURE, -1, "Error in output MicTokenV1 bytes:" + e.getMessage());
-        }
-    }
-
-    public void verify(InputStream is) throws GSSException {
-        byte[] data;
-        try {
-            data = new byte[is.available()];
-            is.read(data);
-        } catch (IOException e) {
-            throw new GSSException(GSSException.FAILURE, -1,
-                    "Read plain data for MicTokenV1 error:" + e.getMessage());
-        }
-        verify(data, 0, data.length);
-    }
-
-    public void verify(byte[] data, int offset, int len) throws GSSException {
-        verifyToken(null, data, offset, len, 0);
-    }
-
-    protected int getTokenSizeWithoutGssHeader() {
-        return getTokenHeaderSize();
-    }
-}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/96494e9a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/MicTokenV2.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/MicTokenV2.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/MicTokenV2.java
deleted file mode 100644
index 2441823..0000000
--- a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/MicTokenV2.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- *
- */
-package org.apache.kerby.kerberos.kerb.gss.impl;
-
-import org.ietf.jgss.GSSException;
-import org.ietf.jgss.MessageProp;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class MicTokenV2 extends GssTokenV2 {
-    private MessageProp prop;
-
-    // This is called to construct MicToken from user input
-    MicTokenV2(GssContext context,
-             byte[] inMsg,
-             int msgOffset,
-             int msgLength,
-             MessageProp messageProp) throws GSSException {
-        super(TOKEN_MIC_V2, context);
-
-        prop = messageProp;
-        if (prop == null) {
-            prop = new MessageProp(0, false);
-        }
-
-        generateCheckSum(prop, inMsg, msgOffset, msgLength);
-    }
-
-    // This is called to construct MicToken from MicToken bytes
-    MicTokenV2(GssContext context,
-             MessageProp messageProp,
-             byte[] inToken,
-             int tokenOffset,
-             int tokenLength) throws GSSException {
-        super(TOKEN_MIC_V2, context, messageProp, inToken, tokenOffset, tokenLength);
-        this.prop = messageProp;
-    }
-
-    public int getMic(byte[] outToken, int offset) {
-        encodeHeader(outToken, offset);
-        System.arraycopy(checkSum, 0, outToken, TOKEN_HEADER_SIZE + offset, checkSum.length);
-        return TOKEN_HEADER_SIZE + checkSum.length;
-    }
-
-    /**
-     * Get bytes for this Mic token
-     * @return
-     */
-    public byte[] getMic() {
-        byte[] ret = new byte[TOKEN_HEADER_SIZE + checkSum.length];
-        getMic(ret, 0);
-        return ret;
-    }
-
-    public void getMic(OutputStream os) throws GSSException {
-        try {
-            encodeHeader(os);
-            os.write(checkSum);
-        } catch (IOException e) {
-            throw new GSSException(GSSException.FAILURE, -1, "Output MicTokenV2 error:" + e.getMessage());
-        }
-    }
-
-    /**
-     * Calculate the checksum for inMsg and compare with it with this token, throw GssException if not equal
-     * @param inMsg
-     * @param msgOffset
-     * @param msgLen
-     * @throws GSSException
-     */
-    public void verify(byte[] inMsg, int msgOffset, int msgLen) throws GSSException {
-        if (!verifyCheckSum(inMsg, msgOffset, msgLen)) {
-            throw new GSSException(GSSException.BAD_MIC, -1, "Corrupt MIC token");
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/96494e9a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/WrapTokenV1.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/WrapTokenV1.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/WrapTokenV1.java
deleted file mode 100644
index 03395bb..0000000
--- a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/WrapTokenV1.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- *
- */
-package org.apache.kerby.kerberos.kerb.gss.impl;
-
-import org.apache.kerby.kerberos.kerb.crypto.util.Random;
-import org.ietf.jgss.GSSException;
-import org.ietf.jgss.MessageProp;
-import sun.security.jgss.GSSHeader;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-public class WrapTokenV1 extends GssTokenV1 {
-    public static final int CONFOUNDER_SIZE = 8;
-
-    private boolean privacy;
-
-    private byte[] inData;
-    private int inOffset;
-    private int inLen;
-
-    private int paddingLen;
-    private byte[] confounder;
-    private int tokenBodyLen;
-
-    private byte[] bodyData;
-    private int bodyOffset;
-    private int bodyLen;
-
-    // for reconstruct
-    private int rawDataLength;
-    private byte[] rawData;
-    private int rawDataOffset;
-
-
-    // Generate wrap token according user data
-    public WrapTokenV1(GssContext context,
-                       byte[] inMsg,
-                       int msgOffset,
-                       int msgLength,
-                       MessageProp prop) throws GSSException {
-        super(TOKEN_WRAP_V1, context);
-
-        paddingLen = getPaddingLength(msgLength);
-        confounder = Random.makeBytes(CONFOUNDER_SIZE);
-        tokenBodyLen = CONFOUNDER_SIZE + msgLength + paddingLen;
-
-        calcPrivacyInfo(prop, confounder, inMsg, msgOffset, msgLength, paddingLen);
-
-        if (!context.getConfState()) {
-            prop.setPrivacy(false);
-        }
-        privacy = prop.getPrivacy();
-        inData = inMsg;
-        inOffset = msgOffset;
-        inLen = msgLength;
-    }
-
-    // Reconstruct a token from token bytes
-    public WrapTokenV1(GssContext context, MessageProp prop,
-                       byte[] token, int offset, int len) throws GSSException {
-        super(TOKEN_WRAP_V1, context, prop, token, offset, len);
-        // adjust the offset to the beginning of the body
-        bodyData = token;
-        bodyOffset = offset + reconHeaderLen;
-        bodyLen = len - reconHeaderLen;
-        getRawData(prop);
-    }
-
-    // Reconstruct a token from token bytes stream
-    public WrapTokenV1(GssContext context, MessageProp prop, InputStream is) throws GSSException {
-        super(TOKEN_WRAP_V1, context, prop, is);
-        byte[] token;
-        int len;
-        try {
-            len = is.available();
-            token = new byte[len];
-            is.read(token);
-        } catch (IOException e) {
-            throw new GSSException(GSSException.FAILURE, -1, "Read wrap token V1 error:" + e.getMessage());
-        }
-        bodyData = token;
-        bodyOffset = 0;
-        bodyLen = len;
-        getRawData(prop);
-    }
-
-    private void getRawData(MessageProp prop) throws GSSException {
-        privacy = prop.getPrivacy();
-        tokenBodyLen = getGssHeader().getMechTokenLength() - getTokenHeaderSize();
-
-        if (bodyLen < tokenBodyLen) {
-            throw new GSSException(GSSException.FAILURE, -1, "Insufficient data for Wrap token V1");
-        }
-
-        if (privacy) {
-            rawData = encryptor.encryptTokenV1(null, bodyData, bodyOffset, tokenBodyLen, 0,
-                    encryptor.isArcFourHmac() ? getPlainSequenceBytes() : null, false);
-            paddingLen = rawData[rawData.length - 1];
-            rawDataOffset = CONFOUNDER_SIZE;
-        } else {
-            rawData = bodyData;
-            paddingLen = bodyData[bodyOffset + tokenBodyLen - 1];
-            rawDataOffset = bodyOffset + CONFOUNDER_SIZE;
-        }
-        rawDataLength = tokenBodyLen - CONFOUNDER_SIZE - paddingLen;
-
-        verifyToken(null, rawData, rawDataOffset - CONFOUNDER_SIZE, tokenBodyLen, 0);
-    }
-
-    // Get plain text data from token data bytes
-    public byte[] unwrap() throws GSSException {
-        byte[] ret = new byte[rawDataLength];
-        System.arraycopy(rawData, rawDataOffset, ret, 0, rawDataLength);
-        return ret;
-    }
-
-    public void unwrap(OutputStream os) throws GSSException {
-        try {
-            os.write(rawData, rawDataOffset, rawDataLength);
-        } catch (IOException e) {
-            throw new GSSException(GSSException.FAILURE, -1,
-                    "Error in output wrap token v1 data bytes:" + e.getMessage());
-        }
-    }
-
-    public byte[] wrap() throws GSSException {
-        ByteArrayOutputStream os = new ByteArrayOutputStream(getTokenSizeWithoutGssHeader() + inLen + 64);
-        wrap(os);
-        return os.toByteArray();
-    }
-
-    public void wrap(OutputStream os) throws GSSException {
-        try {
-            encodeHeader(os);
-            if (privacy) {
-                byte[] enc = encryptor.encryptTokenV1(confounder, inData, inOffset, inLen, paddingLen,
-                        encryptor.isArcFourHmac() ? getPlainSequenceBytes() : null, true);
-                os.write(enc);
-            } else {
-                os.write(confounder);
-                os.write(inData, inOffset, inLen);
-                os.write(getPaddingBytes(paddingLen));
-            }
-        } catch (IOException e) {
-            throw new GSSException(GSSException.FAILURE, -1, "Error in output wrap token v1 bytes:" + e.getMessage());
-        }
-    }
-
-    protected int getTokenSizeWithoutGssHeader() {
-        return tokenBodyLen + getTokenHeaderSize();
-    }
-
-    private int getPaddingLength(int dataLen) {
-        if (encryptor.isArcFourHmac()) {
-            return 1;
-        }
-        return 8 - (dataLen % 8);
-    }
-
-    private byte[] getPaddingBytes(int len) {
-        byte[] ret = new byte[len];
-        int i = 0;
-        while (i < len) {
-            ret[i++] = (byte) len;
-        }
-        return ret;
-    }
-
-    public static int getMsgSizeLimit(int qop, boolean confReq, int maxTokSize, GssEncryptor encryptor)
-            throws GSSException {
-        return GSSHeader.getMaxMechTokenSize(objId, maxTokSize)
-                - encryptor.getCheckSumSize()
-                - TOKEN_HEADER_COMM_SIZE - TOKEN_HEADER_SEQ_SIZE
-                - CONFOUNDER_SIZE - 8;
-    }
-}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/96494e9a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/WrapTokenV2.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/WrapTokenV2.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/WrapTokenV2.java
deleted file mode 100644
index 8f4cae4..0000000
--- a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/WrapTokenV2.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- *
- */
-package org.apache.kerby.kerberos.kerb.gss.impl;
-
-import org.apache.kerby.kerberos.kerb.Message;
-import org.ietf.jgss.GSSException;
-import org.ietf.jgss.MessageProp;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-
-public class WrapTokenV2 extends GssTokenV2 {
-    private MessageProp prop;
-
-    // Generate a token from user input data
-    WrapTokenV2(GssContext context,
-              byte[] data,
-              int dataOffset,
-              int dataLength,
-              MessageProp messageProp) throws GSSException {
-        super(TOKEN_WRAP_V2, context);
-
-        prop = messageProp;
-
-        if (prop.getQOP() != 0) {
-            prop.setQOP(0);
-        }
-
-        if (!context.getConfState()) {
-            prop.setPrivacy(false);
-        }
-
-        generateCheckSum(prop, data, dataOffset, dataLength);
-
-        if (prop.getPrivacy()) {
-            byte[] toProcess = new byte[dataLength + TOKEN_HEADER_SIZE];
-            System.arraycopy(data, dataOffset, toProcess, 0, dataLength);
-            encodeHeader(toProcess, dataLength);
-
-            tokenData = encryptor.encryptData(toProcess, getKeyUsage());
-        } else {
-            tokenData = data; // keep it for now
-        }
-    }
-
-    /**
-     * Get bytes of the token
-     * @return
-     */
-    public byte[] wrap() {
-        int dataSize = tokenData.length;
-        int ckSize = checkSum == null ? 0 : checkSum.length;
-        byte[] ret = new byte[TOKEN_HEADER_SIZE + dataSize + ckSize];
-        encodeHeader(ret, 0);
-        System.arraycopy(tokenData, 0, ret, TOKEN_HEADER_SIZE, dataSize);
-        if (ckSize > 0) {
-            System.arraycopy(checkSum, 0, ret, TOKEN_HEADER_SIZE + dataSize, ckSize);
-        }
-        return ret;
-    }
-
-    public void wrap(OutputStream os) throws GSSException {
-        try {
-            encodeHeader(os);
-            os.write(tokenData);
-            int ckSize = checkSum == null ? 0 : checkSum.length;
-            if (ckSize > 0) {
-                os.write(checkSum);
-            }
-        } catch (IOException e) {
-            throw new GSSException(GSSException.FAILURE, -1, "Output token error:" + e.getMessage());
-        }
-    }
-
-    // Reconstruct a token from token bytes
-    public WrapTokenV2(GssContext context, MessageProp prop, byte[] token, int offset, int len) throws GSSException {
-        super(TOKEN_WRAP_V2, context, prop, token, offset, len);
-        this.prop = prop;
-    }
-
-    // Reconstruct a token from token bytes stream
-    public WrapTokenV2(GssContext context, MessageProp prop, InputStream is) throws GSSException {
-        super(TOKEN_WRAP_V2, context, prop, is);
-        this.prop = prop;
-    }
-
-    /**
-     * Get plain text data from token bytes
-     * @param outBuffer
-     * @param offset
-     * @return plain text contained in the wrap token
-     * @throws GSSException
-     */
-    public byte[] unwrap(byte[] outBuffer, int offset) throws GSSException {
-        int lenToCopy;
-        if (prop.getPrivacy()) {
-            byte[] plainText = encryptor.decryptData(tokenData, getKeyUsage());
-            lenToCopy = plainText.length - TOKEN_HEADER_SIZE;
-            if (outBuffer == null) {
-                outBuffer = new byte[lenToCopy];
-                offset = 0;
-            }
-            System.arraycopy(plainText, 0, outBuffer, offset, lenToCopy);
-        } else {
-            lenToCopy = tokenData.length - encryptor.getCheckSumSize();
-            if (outBuffer == null) {
-                outBuffer = new byte[lenToCopy];
-                offset = 0;
-            }
-            System.arraycopy(tokenData, 0, outBuffer, offset, lenToCopy);
-
-            if (!verifyCheckSum(outBuffer, offset, lenToCopy)) {
-                throw new GSSException(GSSException.BAD_MIC, -1, "Corrupt token checksum");
-            }
-        }
-        return outBuffer;
-    }
-
-    public byte[] unwrap() throws GSSException {
-        return unwrap(null, 0);
-    }
-
-    public void unwrap(OutputStream os) throws GSSException {
-        byte[] data = unwrap();
-        try {
-            os.write(data);
-        } catch (IOException e) {
-            throw new GSSException(GSSException.FAILURE, -1, "Output token error:" + e.getMessage());
-        }
-    }
-
-    public static int getMsgSizeLimit(int qop, boolean confReq, int maxTokSize, GssEncryptor encryptor)
-            throws GSSException {
-        if (confReq) {
-            return maxTokSize - encryptor.getCheckSumSize() - TOKEN_HEADER_SIZE * 2 - CONFOUNDER_SIZE;
-        } else {
-            return maxTokSize - encryptor.getCheckSumSize() - TOKEN_HEADER_SIZE;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/96494e9a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/KerbyMechFactory.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/KerbyMechFactory.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/KerbyMechFactory.java
new file mode 100644
index 0000000..adacb27
--- /dev/null
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/KerbyMechFactory.java
@@ -0,0 +1,149 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.kerby.kerberos.kerb.gssapi;
+
+import org.apache.kerby.kerberos.kerb.gssapi.krb5.KerbyAcceptCred;
+import org.apache.kerby.kerberos.kerb.gssapi.krb5.KerbyContext;
+import org.apache.kerby.kerberos.kerb.gssapi.krb5.KerbyCredElement;
+import org.apache.kerby.kerberos.kerb.gssapi.krb5.KerbyInitCred;
+import org.apache.kerby.kerberos.kerb.gssapi.krb5.KerbyNameElement;
+import org.ietf.jgss.GSSCredential;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.GSSName;
+import org.ietf.jgss.Oid;
+import sun.security.jgss.GSSCaller;
+import sun.security.jgss.spi.GSSContextSpi;
+import sun.security.jgss.spi.GSSCredentialSpi;
+import sun.security.jgss.spi.GSSNameSpi;
+import sun.security.jgss.spi.MechanismFactory;
+
+import java.security.Provider;
+
+/**
+ * Kerby Kerberos V5 plugin for JGSS
+ */
+public class KerbyMechFactory implements MechanismFactory {
+    private static final Provider PROVIDER =
+            new org.apache.kerby.kerberos.kerb.gssapi.Provider();
+
+    private static final String KRB5_OID_STRING = "1.2.840.113554.1.2.2";
+    private static final Oid KRB5_OID = createOid(KRB5_OID_STRING);
+
+    private static Oid[] nameTypes =
+            new Oid[] {
+                    GSSName.NT_USER_NAME,
+                    GSSName.NT_EXPORT_NAME,
+                    GSSName.NT_HOSTBASED_SERVICE
+            };
+
+    private final GSSCaller caller;
+
+    public Oid getMechanismOid() {
+        return KRB5_OID;
+    }
+
+    public Provider getProvider() {
+        return PROVIDER;
+    }
+
+    public Oid[] getNameTypes() throws GSSException {
+        return nameTypes;
+    }
+
+    public KerbyMechFactory(GSSCaller caller) {
+        this.caller = caller;
+    }
+
+    public GSSNameSpi getNameElement(String nameStr, Oid nameType)
+            throws GSSException {
+        return KerbyNameElement.getInstance(nameStr, nameType);
+    }
+
+    public GSSNameSpi getNameElement(byte[] name, Oid nameType)
+            throws GSSException {
+        return KerbyNameElement.getInstance(name.toString(), nameType);
+    }
+
+    // Used by initiator
+    public GSSContextSpi getMechanismContext(GSSNameSpi peer,
+                                             GSSCredentialSpi myInitiatorCred,
+                                             int lifetime) throws GSSException {
+        if (peer != null && !(peer instanceof KerbyNameElement)) {
+            peer = KerbyNameElement.getInstance(peer.toString(), peer.getStringNameType());
+        }
+        if (myInitiatorCred == null) {
+            myInitiatorCred = getCredentialElement(null, lifetime, 0, GSSCredential.INITIATE_ONLY);
+        }
+        return new KerbyContext(caller, (KerbyNameElement) peer, (KerbyInitCred) myInitiatorCred, lifetime);
+    }
+
+    public GSSContextSpi getMechanismContext(GSSCredentialSpi myAcceptorCred)
+            throws GSSException {
+        if (myAcceptorCred == null) {
+            myAcceptorCred = getCredentialElement(null, 0,
+                    GSSCredential.INDEFINITE_LIFETIME, GSSCredential.ACCEPT_ONLY);
+        }
+        return new KerbyContext(caller, (KerbyAcceptCred) myAcceptorCred);
+    }
+
+    // Reconstruct from previously exported context
+    public GSSContextSpi getMechanismContext(byte[] exportedContext)
+            throws GSSException {
+       return new KerbyContext(caller, exportedContext);
+    }
+
+    public GSSCredentialSpi getCredentialElement(GSSNameSpi name,
+                                                 int initLifetime,
+                                                 int acceptLifetime,
+                                                 int usage)
+            throws GSSException {
+        if (name != null && !(name instanceof KerbyNameElement)) {
+            name = KerbyNameElement.getInstance(name.toString(), name.getStringNameType());
+        }
+
+        KerbyCredElement credElement;
+
+        if (usage == GSSCredential.INITIATE_ONLY) {
+            credElement = KerbyInitCred.getInstance(caller, (KerbyNameElement) name, initLifetime);
+        } else if (usage == GSSCredential.ACCEPT_ONLY) {
+            credElement = KerbyAcceptCred.getInstance(caller, (KerbyNameElement) name, acceptLifetime);
+        } else if (usage == GSSCredential.INITIATE_AND_ACCEPT) {
+            throw new GSSException(GSSException.FAILURE, -1, "Unsupported usage mode: INITIATE_AND_ACCEPT");
+        } else {
+            throw new GSSException(GSSException.FAILURE, -1, "Unknown usage mode: " + usage);
+        }
+
+        return credElement;
+    }
+
+    private static Oid createOid(String oidStr) {
+        Oid retVal;
+        try {
+            retVal = new Oid(oidStr);
+        } catch (GSSException e) {
+            retVal = null;
+        }
+        return retVal;
+    }
+
+    public static Oid getOid() {
+        return KRB5_OID;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/96494e9a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/Provider.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/Provider.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/Provider.java
new file mode 100644
index 0000000..ad3a614
--- /dev/null
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/Provider.java
@@ -0,0 +1,46 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.kerby.kerberos.kerb.gssapi;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Proivder is used to register the implementation of gssapi mechanism into the system
+ */
+public final class Provider extends java.security.Provider {
+    private static final long serialVersionUID = 3787378212107821987L;
+    private static final String INFO = "Kerby GssApi Provider";
+    private static final String MECHANISM_GSSAPI = "GssApiMechanism.1.2.840.113554.1.2.2";
+    private static final String MECHANISM_GSSAPI_CLASS = "org.apache.kerby.kerberos.kerb.gssapi.KerbyMechFactory";
+
+    public Provider() {
+        super("KerbyGssApi", 0.01d, INFO);
+
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+
+                put(MECHANISM_GSSAPI, MECHANISM_GSSAPI_CLASS);
+
+                return null;
+            }
+        });
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/96494e9a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/CredUtils.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/CredUtils.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/CredUtils.java
new file mode 100644
index 0000000..f7ddc31
--- /dev/null
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/CredUtils.java
@@ -0,0 +1,89 @@
+package org.apache.kerby.kerberos.kerb.gssapi.krb5;
+
+import org.ietf.jgss.GSSException;
+import sun.security.jgss.GSSCaller;
+
+import javax.security.auth.Subject;
+import javax.security.auth.kerberos.*;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Set;
+
+/**
+ * Utility functions to deal with credentials in Context
+ */
+public class CredUtils {
+
+    public static <T> Set<T> getContextPrivateCredentials(Class<T> credentialType, AccessControlContext acc) {
+        Subject subject = Subject.getSubject(acc);
+        Set<T> creds = subject.getPrivateCredentials(credentialType);
+        return creds;
+    }
+
+    public static <T> Set<T> getContextCredentials(final Class<T> credentialType) throws GSSException {
+        final AccessControlContext acc = AccessController.getContext();
+        try {
+            return AccessController.doPrivileged(
+                    new PrivilegedExceptionAction<Set<T>>() {
+                        public Set<T> run() throws Exception {
+                            return CredUtils.getContextPrivateCredentials(credentialType, acc);
+                        }
+                    });
+        } catch (PrivilegedActionException e) {
+            throw new GSSException(GSSException.NO_CRED, -1, "Get credential from context failed");
+        }
+    }
+
+    public static KerberosTicket getKerberosTicketFromContext(GSSCaller caller,
+                                                              final String clientName,
+                                                              final String serverName) throws GSSException {
+        Set<KerberosTicket> tickets = getContextCredentials(KerberosTicket.class);
+        for (KerberosTicket ticket : tickets) {
+            if (ticket.isCurrent() && (serverName == null || ticket.getServer().getName().equals(serverName))
+                    && (clientName == null || ticket.getClient().getName().equals(clientName))) {
+                return ticket;
+            }
+        }
+        return null;
+    }
+
+    public static KeyTab getKeyTabFromContext(KerberosPrincipal principal) throws GSSException {
+        Set<KeyTab> tabs = getContextCredentials(KeyTab.class);
+        for (KeyTab tab : tabs) {
+            KerberosKey[] keys = tab.getKeys(principal);
+            if (keys != null && keys.length > 0) {
+                return tab;
+            }
+        }
+        return null;
+    }
+
+    public static void addCredentialToSubject(final KerberosTicket ticket) throws GSSException {
+        final AccessControlContext acc = AccessController.getContext();
+
+        final Subject subject = AccessController.doPrivileged(
+                new java.security.PrivilegedAction<Subject>() {
+                    public Subject run() {
+                        return Subject.getSubject(acc);
+                    }
+                });
+
+        AccessController.doPrivileged(
+                new java.security.PrivilegedAction<Void>() {
+                    public Void run() {
+                        subject.getPrivateCredentials().add(ticket);
+                        return null;
+                    }
+                });
+    }
+
+    public static void checkPrincipalPermission(String principalName, String action) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            ServicePermission sp = new ServicePermission(principalName, action);
+            sm.checkPermission(sp);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/96494e9a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyAcceptCred.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyAcceptCred.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyAcceptCred.java
new file mode 100644
index 0000000..a7331fa
--- /dev/null
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyAcceptCred.java
@@ -0,0 +1,72 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.kerby.kerberos.kerb.gssapi.krb5;
+
+
+import org.ietf.jgss.GSSException;
+import sun.security.jgss.GSSCaller;
+
+import javax.security.auth.kerberos.KerberosKey;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.auth.kerberos.KeyTab;
+
+public final class KerbyAcceptCred extends KerbyCredElement {
+
+    private final KeyTab keyTab;
+
+    public static KerbyAcceptCred getInstance(final GSSCaller caller,
+                                              KerbyNameElement name, int lifeTime) throws GSSException {
+
+        KerberosPrincipal princ = new KerberosPrincipal(name.getPrincipalName().getName(),
+                name.getPrincipalName().getNameType().getValue());
+        KeyTab keyTab = CredUtils.getKeyTabFromContext(princ);
+
+        if (keyTab == null) {
+            throw new GSSException(GSSException.NO_CRED, -1,
+                    "Failed to find any Kerberos credential for " + name.getPrincipalName().getName());
+        }
+
+        return new KerbyAcceptCred(caller, name, keyTab, lifeTime);
+    }
+
+    private KerbyAcceptCred(GSSCaller caller, KerbyNameElement name, KeyTab keyTab, int lifeTime) {
+        super(caller, name);
+        this.keyTab = keyTab;
+        this.accLifeTime = lifeTime;
+    }
+
+    public boolean isInitiatorCredential() throws GSSException {
+        return false;
+    }
+
+    public boolean isAcceptorCredential() throws GSSException {
+        return true;
+    }
+
+    public KeyTab getKeyTab() {
+        return this.keyTab;
+    }
+
+    public KerberosKey[] getKeys() {
+        KerberosPrincipal princ = new KerberosPrincipal(name.getPrincipalName().getName(),
+                name.getPrincipalName().getNameType().getValue());
+        return keyTab.getKeys(princ);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/96494e9a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyContext.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyContext.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyContext.java
new file mode 100644
index 0000000..5395afd
--- /dev/null
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyContext.java
@@ -0,0 +1,673 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.kerby.kerberos.kerb.gssapi.krb5;
+
+import com.sun.security.jgss.InquireType;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.gssapi.KerbyMechFactory;
+import org.apache.kerby.kerberos.kerb.request.ApRequest;
+import org.apache.kerby.kerberos.kerb.response.ApResponse;
+import org.apache.kerby.kerberos.kerb.type.ad.AuthorizationData;
+import org.apache.kerby.kerberos.kerb.type.ap.ApRep;
+import org.apache.kerby.kerberos.kerb.type.ap.ApReq;
+import org.apache.kerby.kerberos.kerb.type.ap.Authenticator;
+import org.apache.kerby.kerberos.kerb.type.base.EncryptionKey;
+import org.apache.kerby.kerberos.kerb.type.base.PrincipalName;
+import org.apache.kerby.kerberos.kerb.type.kdc.EncKdcRepPart;
+import org.apache.kerby.kerberos.kerb.type.ticket.EncTicketPart;
+import org.apache.kerby.kerberos.kerb.type.ticket.SgtTicket;
+import org.apache.kerby.kerberos.kerb.type.ticket.TicketFlags;
+import org.ietf.jgss.ChannelBinding;
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.MessageProp;
+import org.ietf.jgss.Oid;
+import sun.security.jgss.GSSCaller;
+import sun.security.jgss.spi.GSSContextSpi;
+import sun.security.jgss.spi.GSSCredentialSpi;
+import sun.security.jgss.spi.GSSNameSpi;
+
+import javax.security.auth.kerberos.KerberosTicket;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.security.Provider;
+
+@SuppressWarnings("PMD")
+public class KerbyContext implements GSSContextSpi {
+
+    private static final int STATE_NONE = 0;
+    private static final int STATE_ESTABLISHING = 1;
+    private static final int STATE_ESTABLISHED = 2;
+    private static final int STATE_DESTROYED = 3;
+
+    private static final byte[] MSG_AP_REQ = {(byte) 0x1, (byte) 0};
+    private static final byte[] MSG_AP_REP = {(byte) 0x2, (byte) 0};
+
+    private int ctxState = STATE_NONE;
+
+    private final GSSCaller caller;
+    private KerbyCredElement myCred;
+    private boolean initiator;
+    private KerbyNameElement myName;
+    private KerbyNameElement peerName;
+    private int lifeTime;
+    private ChannelBinding channelBinding;
+
+    private boolean mutualAuth  = true;
+    private boolean replayDet  = true;
+    private boolean sequenceDet  = true;
+    private boolean credDeleg  = false;
+    private boolean confState  = true;
+    private boolean integState  = true;
+    private boolean delegPolicy = false;
+
+    public static final int INVALID_KEY = 0;
+    public static final int SESSION_KEY = 1;
+    public static final int INITIATOR_SUBKEY = 2;
+    public static final int ACCEPTOR_SUBKEY = 4;
+    private int keyComesFrom = INVALID_KEY;
+
+    private EncryptionKey sessionKey;   // used between client and app server
+    private TicketFlags ticketFlags;
+    private ApReq outApReq;
+
+    private KerbyGssEncryptor gssEncryptor;
+
+    // Called on initiator's side.
+    public KerbyContext(GSSCaller caller, KerbyNameElement peerName, KerbyCredElement myCred,
+                        int lifeTime)
+            throws GSSException {
+        if (peerName == null) {
+            throw new IllegalArgumentException("Cannot have null peer name");
+        }
+
+        this.caller = caller;
+        this.peerName = peerName;
+        this.myCred = myCred;
+        this.lifeTime = lifeTime;
+        this.initiator = true;
+
+        mySequenceNumberLock = new Object();
+        peerSequenceNumberLock = new Object();
+    }
+
+    public KerbyContext(GSSCaller caller, KerbyAcceptCred myCred)
+            throws GSSException {
+        this.caller = caller;
+        this.myCred = myCred;
+        this.initiator = false;
+
+        mySequenceNumberLock = new Object();
+        peerSequenceNumberLock = new Object();
+    }
+
+    public KerbyContext(GSSCaller caller, byte[] interProcessToken)
+            throws GSSException {
+        throw new GSSException(GSSException.UNAVAILABLE, -1, "Unsupported feature");
+    }
+
+    public Provider getProvider() {
+        return new org.apache.kerby.kerberos.kerb.gssapi.Provider();
+    }
+
+    public void requestLifetime(int lifeTime) throws GSSException {
+        if (ctxState == STATE_NONE && isInitiator()) {
+            this.lifeTime = lifeTime;
+        }
+    }
+
+    public void requestMutualAuth(boolean state) throws GSSException {
+        if (ctxState == STATE_NONE && isInitiator()) {
+            mutualAuth  = state;
+        }
+    }
+
+    public void requestReplayDet(boolean state) throws GSSException {
+        if (ctxState == STATE_NONE && isInitiator()) {
+            replayDet = state;
+        }
+    }
+
+    public void requestSequenceDet(boolean state) throws GSSException {
+        if (ctxState == STATE_NONE && isInitiator()) {
+            replayDet = state;
+        }
+    }
+
+    public void requestCredDeleg(boolean state) throws GSSException {
+        if (ctxState == STATE_NONE && isInitiator() && myCred == null) {
+            credDeleg  = state;
+        }
+    }
+
+    public void requestAnonymity(boolean state) throws GSSException {
+        // anonymous context not supported
+    }
+
+    public void requestConf(boolean state) throws GSSException {
+        if (ctxState == STATE_NONE && isInitiator()) {
+            confState = state;
+        }
+    }
+
+    public void requestInteg(boolean state) throws GSSException {
+        if (ctxState == STATE_NONE && isInitiator()) {
+            integState = state;
+        }
+    }
+
+    public void requestDelegPolicy(boolean state) throws GSSException {
+        if (ctxState == STATE_NONE && isInitiator()) {
+            delegPolicy = state;
+        }
+    }
+
+    public void setChannelBinding(ChannelBinding cb) throws GSSException {
+        this.channelBinding = cb;
+    }
+
+    public boolean getCredDelegState() {
+        return credDeleg;
+    }
+
+    public boolean getMutualAuthState() {
+        return mutualAuth;
+    }
+
+    public boolean getReplayDetState() {
+        return replayDet || sequenceDet;
+    }
+
+    public boolean getSequenceDetState() {
+        return sequenceDet;
+    }
+
+    public boolean getAnonymityState() {
+        return false;
+    }
+
+    public boolean getDelegPolicyState() {
+        return delegPolicy;
+    }
+
+    public boolean isTransferable() throws GSSException {
+        return false;
+    }
+
+    public boolean isProtReady() {
+        return ctxState == STATE_ESTABLISHED;
+    }
+
+    public boolean isInitiator() {
+        return initiator;
+    }
+
+    public boolean getConfState() {
+        return confState;
+    }
+
+    public boolean getIntegState() {
+        return integState;
+    }
+
+    public int getLifetime() {
+        return GSSContext.INDEFINITE_LIFETIME;
+    }
+
+    public boolean isEstablished() {
+        return ctxState == STATE_ESTABLISHED;
+    }
+
+    public GSSNameSpi getSrcName() throws GSSException {
+        return isInitiator() ? myName : peerName;
+    }
+
+    public GSSNameSpi getTargName() throws GSSException {
+        return !isInitiator() ? myName : peerName;
+    }
+
+    public Oid getMech() throws GSSException {
+        return KerbyMechFactory.getOid();
+    }
+
+    public GSSCredentialSpi getDelegCred() throws GSSException {
+        throw new GSSException(GSSException.FAILURE, -1, "API not implemented");  // TODO:
+    }
+
+    public byte[] initSecContext(InputStream is, int mechTokenSize)
+            throws GSSException {
+        if (!isInitiator()) {
+            throw new GSSException(GSSException.FAILURE, -1, "initSecContext called on acceptor");
+        }
+
+        byte[] ret = null;
+
+        if (ctxState == STATE_NONE) {
+
+            if (!myCred.isInitiatorCredential()) {
+                throw new GSSException(GSSException.NO_CRED, -1, "No TGT available");
+            }
+
+            // check if service ticket already exists
+            // if not, prepare to get it through TGS_REQ
+            SgtTicket sgtTicket = null;
+            String serviceName = peerName.getPrincipalName().getName();
+            myName = (KerbyNameElement) myCred.getName();
+            PrincipalName clientPrincipal = myName.getPrincipalName();
+
+            sgtTicket = KerbyUtil.getSgtCredentialFromContext(caller, clientPrincipal.getName(), serviceName);
+
+            if (sgtTicket == null) {
+                sgtTicket = KerbyUtil.applySgtCredential(((KerbyInitCred) myCred).ticket, serviceName);
+
+                // add this service credential to context
+                final KerberosTicket ticket =
+                        KerbyUtil.convertKrbTicketToKerberosTicket(sgtTicket, myName.getPrincipalName().getName());
+                CredUtils.addCredentialToSubject(ticket);
+            }
+
+            ApRequest apRequest = new ApRequest(clientPrincipal, sgtTicket);
+            try {
+                outApReq = apRequest.getApReq();
+            } catch (KrbException e) {
+                throw new GSSException(GSSException.FAILURE, -1, "Generate ApReq failed: " + e.getMessage());
+            }
+            setupInitiatorContext(sgtTicket, apRequest);
+            try {
+                ByteBuffer outBuffer = ByteBuffer.allocate(outApReq.encodingLength() + 2);
+                outBuffer.put(MSG_AP_REQ);
+                outApReq.encode(outBuffer);
+                outBuffer.flip();
+                ret = outBuffer.array();
+            } catch (IOException e) {
+                throw new GSSException(GSSException.FAILURE, -1, "Generate ApReq bytes failed: " + e.getMessage());
+            }
+
+            ctxState = STATE_ESTABLISHING;
+            if (!getMutualAuthState()) {
+                gssEncryptor = new KerbyGssEncryptor(getSessionKey());
+                ctxState = STATE_ESTABLISHED;
+            }
+
+        } else if (ctxState == STATE_ESTABLISHING) {
+            verifyServerToken(is, mechTokenSize);
+            gssEncryptor = new KerbyGssEncryptor(getSessionKey());
+            outApReq = null;
+            ctxState = STATE_ESTABLISHED;
+        }
+        return ret;
+    }
+
+    private void setupInitiatorContext(SgtTicket sgt, ApRequest apRequest) throws GSSException {
+        EncKdcRepPart encKdcRepPart = sgt.getEncKdcRepPart();
+        TicketFlags ticketFlags = encKdcRepPart.getFlags();
+        setTicketFlags(ticketFlags);
+
+        setAuthTime(encKdcRepPart.getAuthTime().toString());
+
+        Authenticator auth;
+        try {
+            auth = apRequest.getApReq().getAuthenticator();
+        } catch (KrbException e) {
+            throw new GSSException(GSSException.FAILURE, -1, "ApReq failed in Initiator");
+        }
+        setMySequenceNumber(auth.getSeqNumber());
+
+        EncryptionKey subKey = auth.getSubKey();
+        if (subKey != null) {
+            setSessionKey(subKey, KerbyContext.INITIATOR_SUBKEY);
+        } else {
+            setSessionKey(sgt.getSessionKey(), KerbyContext.SESSION_KEY);
+        }
+
+        if (!getMutualAuthState()) {
+            setPeerSequenceNumber(0);
+        }
+    }
+
+    /**
+     * Verify the AP_REP from server and set context accordingly
+     * @param is
+     * @param mechTokenSize
+     * @return
+     * @throws GSSException
+     * @throws IOException
+     */
+    private void verifyServerToken(InputStream is, int mechTokenSize)
+            throws GSSException {
+        byte[] token;
+        ApRep apRep;
+        try {
+            if (!(is.read() == MSG_AP_REP[0] && is.read() == MSG_AP_REP[1])) {
+                throw new GSSException(GSSException.FAILURE, -1, "Invalid ApRep message ID");
+            }
+            token = new byte[mechTokenSize - MSG_AP_REP.length];
+            is.read(token);
+            apRep = new ApRep();
+            apRep.decode(token);
+        } catch (IOException e) {
+            throw new GSSException(GSSException.FAILURE, -1, "Invalid ApRep " + e.getMessage());
+        }
+
+        try {
+            ApResponse.validate(getSessionKey(), apRep, outApReq);
+        } catch (KrbException e) {
+            throw new GSSException(GSSException.UNAUTHORIZED, -1, "ApRep verification failed");
+        }
+
+        EncryptionKey key = apRep.getEncRepPart().getSubkey();
+        if (key != null) {
+            setSessionKey(key, ACCEPTOR_SUBKEY);
+        }
+
+        int seqNum = apRep.getEncRepPart().getSeqNumber();
+        setPeerSequenceNumber(seqNum == -1 ? 0 : seqNum);
+    }
+
+    public byte[] acceptSecContext(InputStream is, int mechTokenSize)
+            throws GSSException {
+        byte[] ret = null;
+
+        if (isInitiator()) {
+            throw new GSSException(GSSException.FAILURE, -1, "acceptSecContext called on initiator");
+        }
+
+        if (ctxState == STATE_NONE) {
+            ctxState = STATE_ESTABLISHING;
+            if (!myCred.isAcceptorCredential()) {
+                throw new GSSException(GSSException.FAILURE, -1, "No acceptor credential available");
+            }
+
+            KerbyAcceptCred acceptCred = (KerbyAcceptCred) myCred;
+            CredUtils.checkPrincipalPermission(
+                    ((KerbyNameElement) acceptCred.getName()).getPrincipalName().getName(), "accept");
+
+            if (getMutualAuthState()) {
+                ret = verifyClientToken(acceptCred, is, mechTokenSize);
+            }
+
+            gssEncryptor = new KerbyGssEncryptor(getSessionKey());
+
+            myCred = null;
+            ctxState = STATE_ESTABLISHED;
+        }
+
+        return ret;
+    }
+
+    private byte[] verifyClientToken(KerbyAcceptCred acceptCred, InputStream is, int mechTokenSize)
+            throws GSSException {
+        byte[] token;
+        ApReq apReq;
+        try {
+            if (!(is.read() == MSG_AP_REQ[0] && is.read() == MSG_AP_REQ[1])) {
+                throw new GSSException(GSSException.FAILURE, -1, "Invalid ApReq message ID");
+            }
+
+            token = new byte[mechTokenSize - MSG_AP_REQ.length];
+            is.read(token);
+            apReq = new ApReq();
+            apReq.decode(token);
+        } catch (IOException e) {
+            throw new GSSException(GSSException.UNAUTHORIZED, -1, "ApReq invalid:" + e.getMessage());
+        }
+
+        int kvno = apReq.getTicket().getEncryptedEncPart().getKvno();
+        int encryptType = apReq.getTicket().getEncryptedEncPart().getEType().getValue();
+
+        // Get server key from credential
+        EncryptionKey serverKey = KerbyUtil.getEncryptionKey(acceptCred.getKeys(), encryptType, kvno);
+        if (serverKey == null) {
+            throw new GSSException(GSSException.FAILURE, -1, "Server key not found");
+        }
+
+        try {
+            ApRequest.validate(serverKey, apReq, channelBinding.getInitiatorAddress(), 5 * 60 * 1000);
+        } catch (KrbException e) {
+            throw new GSSException(GSSException.UNAUTHORIZED, -1, "ApReq verification failed: " + e.getMessage());
+        }
+
+        ApResponse apResponse = new ApResponse(apReq);
+        ApRep apRep;
+        try {
+            apRep = apResponse.getApRep();
+        } catch (KrbException e) {
+            throw new GSSException(GSSException.UNAUTHORIZED, -1, "Generate ApRep failed");
+        }
+
+        EncTicketPart apReqTicketEncPart = apReq.getTicket().getEncPart();
+
+        EncryptionKey ssKey = apReqTicketEncPart.getKey();
+        Authenticator auth = apReq.getAuthenticator();
+        EncryptionKey subKey = auth.getSubKey();
+
+        if (subKey != null) {
+            setSessionKey(subKey, INITIATOR_SUBKEY);
+        } else {
+            setSessionKey(ssKey, SESSION_KEY);
+        }
+
+        // initial seqNumber
+        int seqNumber = auth.getSeqNumber();
+        setMySequenceNumber(seqNumber);
+        // initial authtime, tktflags, authdata,
+        setAuthTime(apReqTicketEncPart.getAuthTime().toString());
+        setTicketFlags(apReqTicketEncPart.getFlags());
+        setAuthData(apReqTicketEncPart.getAuthorizationData());
+
+        byte[] ret = null;
+        try {
+            ByteBuffer outBuffer = ByteBuffer.allocate(apRep.encodingLength() + 2);
+            outBuffer.put(MSG_AP_REP);
+            apRep.encode(outBuffer);
+            outBuffer.flip();
+            ret = outBuffer.array();
+        } catch (IOException e) {
+            throw new GSSException(GSSException.FAILURE, -1, "Generate ApRep bytes failed:" + e.getMessage());
+        }
+        return ret;
+    }
+
+    public int getWrapSizeLimit(int qop, boolean confReq, int maxTokSize)
+            throws GSSException {
+        if (gssEncryptor.isV2()) {
+            return WrapTokenV2.getMsgSizeLimit(qop, confReq, maxTokSize, gssEncryptor);
+        } else {
+            return WrapTokenV1.getMsgSizeLimit(qop, confReq, maxTokSize, gssEncryptor);
+        }
+    }
+
+    public void wrap(InputStream is, OutputStream os, MessageProp msgProp)
+            throws GSSException {
+        if (ctxState != STATE_ESTABLISHED) {
+            throw new GSSException(GSSException.NO_CONTEXT, -1, "Context invalid for wrap");
+        }
+        if (gssEncryptor.isV2()) {
+             WrapTokenV2 token = new WrapTokenV2(this, inBuf, 0, len, msgProp);
+             token.wrap(os);
+        } else {
+             WrapTokenV1 token = new WrapTokenV1(this, inBuf, 0, len, msgProp);
+             token.wrap(os);
+        }
+    }
+
+    public byte[] wrap(byte[] inBuf, int offset, int len,
+                       MessageProp msgProp) throws GSSException {
+        if (ctxState != STATE_ESTABLISHED) {
+            throw new GSSException(GSSException.NO_CONTEXT, -1, "Context invalid for wrap");
+        }
+        byte[] ret;
+        if (gssEncryptor.isV2()) {
+             WrapTokenV2 token = new WrapTokenV2(this, inBuf, offset, len, msgProp);
+             ret = token.wrap();
+        } else {
+             WrapTokenV1 token = new WrapTokenV1(this, inBuf, offset, len, msgProp);
+             ret = token.wrap();
+        }
+        return ret;
+    }
+
+    public void unwrap(InputStream is, OutputStream os,
+                       MessageProp msgProp) throws GSSException {
+        if (gssEncryptor.isV2()) {
+            WrapTokenV2 token = new WrapTokenV2(this, msgProp, is);
+            token.unwrap(os);
+        } else {
+            WrapTokenV1 token = new WrapTokenV1(this, msgProp, is);
+            token.unwrap(os);
+        }
+    }
+
+    public byte[] unwrap(byte[] inBuf, int offset, int len,
+                         MessageProp msgProp) throws GSSException {
+        if (ctxState != STATE_ESTABLISHED) {
+            throw new GSSException(GSSException.NO_CONTEXT, -1, "Context invalid for unwrap");
+        }
+        byte[] ret;
+        if (gssEncryptor.isV2()) {
+             WrapTokenV2 token = new WrapTokenV2(this, msgProp, inBuf, offset, len);
+             ret = token.unwrap();
+        } else {
+            WrapTokenV1 token = new WrapTokenV1(this, msgProp, inBuf, offset, len);
+            ret = token.unwrap();
+        }
+        return ret;
+    }
+
+    public void getMIC(InputStream is, OutputStream os,
+                       MessageProp msgProp)
+            throws GSSException {
+    }
+
+    public byte[] getMIC(byte[] inMsg, int offset, int len,
+                         MessageProp msgProp) throws GSSException {
+        return null; // TODO: to be implemented
+    }
+
+    public void verifyMIC(InputStream is, InputStream msgStr,
+                          MessageProp msgProp) throws GSSException {
+    }
+
+    public void verifyMIC(byte[]inTok, int tokOffset, int tokLen,
+                          byte[] inMsg, int msgOffset, int msgLen,
+                          MessageProp msgProp) throws GSSException {
+    }
+
+    public byte[] export() throws GSSException {
+        throw new GSSException(GSSException.UNAVAILABLE, -1, "Unsupported export method");
+    }
+
+    public void dispose() throws GSSException {
+        ctxState = STATE_DESTROYED;
+        setSessionKey(null, 0);
+        peerName = null;
+        myCred = null;
+        myName = null;
+    }
+
+
+    private String authTime;
+    private void setAuthTime(String authTime) {
+        this.authTime = authTime;
+    }
+
+    public Object inquireSecContext(InquireType type) throws GSSException {
+        if (ctxState != STATE_ESTABLISHED) {
+            throw new GSSException(GSSException.NO_CONTEXT, -1, "Invalid context");
+        }
+
+        switch (type) {
+            case KRB5_GET_SESSION_KEY:
+                return getSessionKey();
+            case KRB5_GET_TKT_FLAGS:
+                return KerbyUtil.ticketFlagsToBooleans(ticketFlags);
+            case KRB5_GET_AUTHZ_DATA:
+                if (isInitiator()) {
+                    throw new GSSException(GSSException.UNAVAILABLE, -1,
+                            "Authorization data not available for initiator");
+                } else {
+                    return KerbyUtil.kerbyAuthorizationDataToJgssAuthorizationDataEntries(authData);
+                }
+            case KRB5_GET_AUTHTIME:
+                return authTime;
+        }
+        throw new GSSException(GSSException.UNAVAILABLE, -1, "Unsupported inquire type");
+    }
+
+
+    // functions not belong to SPI
+    private void setSessionKey(EncryptionKey encryptionKey, int keyComesFrom) {
+        this.sessionKey = encryptionKey;
+        this.keyComesFrom = keyComesFrom;
+    }
+
+    public int getKeyComesFrom() {
+        return keyComesFrom;
+    }
+
+    private EncryptionKey getSessionKey() {
+        return sessionKey;
+    }
+
+    private void setTicketFlags(TicketFlags ticketFlags) {
+        this.ticketFlags = ticketFlags;
+    }
+
+    private AuthorizationData authData;
+    private void setAuthData(AuthorizationData authData) {
+        this.authData = authData;
+    }
+
+
+    private int mySequenceNumber;
+    private int peerSequenceNumber;
+    private Object mySequenceNumberLock;
+    private Object peerSequenceNumberLock;
+
+    public void setMySequenceNumber(int sequenceNumber) {
+        synchronized (mySequenceNumberLock) {
+            mySequenceNumber = sequenceNumber;
+        }
+    }
+
+    public int incMySequenceNumber() {
+        synchronized (mySequenceNumberLock) {
+            return mySequenceNumber++;
+        }
+    }
+
+    public void setPeerSequenceNumber(int sequenceNumber) {
+        synchronized (peerSequenceNumberLock) {
+            peerSequenceNumber = sequenceNumber;
+        }
+    }
+
+    public int incPeerSequenceNumber() {
+        synchronized (peerSequenceNumberLock) {
+            return peerSequenceNumber++;
+        }
+    }
+
+    public KerbyGssEncryptor getGssEncryptor() {
+        return gssEncryptor;
+    }
+}