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/21 15:03:21 UTC

[04/18] directory-kerby git commit: DIRKRB-560 - Implement GSSContextSpi interface. Thanks to Wei Zhou.

DIRKRB-560 - Implement GSSContextSpi interface. Thanks to Wei Zhou.


Project: http://git-wip-us.apache.org/repos/asf/directory-kerby/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-kerby/commit/06024445
Tree: http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/06024445
Diff: http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/06024445

Branch: refs/heads/trunk
Commit: 060244450a7fbf83fd59d7c63068339384aa6d45
Parents: 2c1f222
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Fri Jul 21 14:46:39 2017 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Fri Jul 21 14:47:04 2017 +0100

----------------------------------------------------------------------
 .../kerberos/kerb/gssapi/krb5/KerbyContext.java | 610 +++++++++++++++++++
 .../kerberos/kerb/gssapi/krb5/KerbyUtil.java    |  22 +-
 2 files changed, 623 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/06024445/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..e017683
--- /dev/null
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyContext.java
@@ -0,0 +1,610 @@
+/**
+ *  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.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 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;
+
+    // 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 {
+                ret = outApReq.encode();
+            } catch (IOException e) {
+                throw new GSSException(GSSException.FAILURE, -1, "Generate ApReq bytes failed: " + e.getMessage());
+            }
+
+            ctxState = STATE_ESTABLISHING;
+            if (!getMutualAuthState()) {
+                ctxState = STATE_ESTABLISHED;
+            }
+
+        } else if (ctxState == STATE_ESTABLISHING) {
+            verifyServerToken(is, mechTokenSize);
+            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 = new byte[mechTokenSize];
+        ApRep apRep;
+        try {
+            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);
+            }
+
+            myCred = null;
+            ctxState = STATE_ESTABLISHED;
+        }
+
+        return ret;
+    }
+
+    private byte[] verifyClientToken(KerbyAcceptCred acceptCred, InputStream is, int mechTokenSize)
+            throws GSSException {
+        byte[] token = new byte[mechTokenSize];
+        ApReq apReq;
+        try {
+            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 {
+            ret = apRep.encode();
+        } 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 {
+        return 65536;   // TODO: to be implemented
+    }
+
+    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");
+        }
+        throw new GSSException(GSSException.UNAVAILABLE, -1, "Unsupported method");  // TODO: to be implemented
+    }
+
+    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");
+        }
+        return null; // TODO: to be implemented
+    }
+
+    public void unwrap(InputStream is, OutputStream os,
+                       MessageProp msgProp) throws GSSException {
+        throw new GSSException(GSSException.UNAVAILABLE, -1, "Unsupported method");  // TODO: to be implemented
+    }
+
+    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");
+        }
+        return null; // TODO: to be implemented
+    }
+
+    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++;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/06024445/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyUtil.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyUtil.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyUtil.java
index 61eeb8d..a5abb46 100644
--- a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyUtil.java
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyUtil.java
@@ -38,6 +38,7 @@ 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;
@@ -183,6 +184,18 @@ public class KerbyUtil {
     }
 
     /**
+     * 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
@@ -284,15 +297,6 @@ public class KerbyUtil {
         return ticket;
     }
 
-    public static byte[] getAPRequest(PrincipalName clientPricipal, SgtTicket sgt) throws GSSException {
-        ApRequest apRequest = new ApRequest(clientPricipal, sgt);
-        try {
-            return apRequest.getApReq().encode();
-        } catch (Exception e) {  // IOExcetpion, KrbException
-            throw new GSSException(GSSException.FAILURE, -1, "Generate ApReq failed: " + e.getMessage());
-        }
-    }
-
     public static KrbClientBase getKrbClient() {
         KrbClientBase client;
         try {