| /** |
| * 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 com.sun.security.jgss.InquireType; |
| import org.apache.kerby.kerberos.kerb.KrbException; |
| import org.apache.kerby.kerberos.kerb.gss.GssMechFactory; |
| import org.apache.kerby.kerberos.kerb.gss.KerbyGssProvider; |
| 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 GssContext 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 GssCredElement myCred; |
| private boolean initiator; |
| private GssNameElement myName; |
| private GssNameElement 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 GssEncryptor gssEncryptor; |
| |
| // Called on initiator's side. |
| public GssContext(GSSCaller caller, GssNameElement peerName, GssCredElement 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 GssContext(GSSCaller caller, GssAcceptCred myCred) |
| throws GSSException { |
| this.caller = caller; |
| this.myCred = myCred; |
| this.initiator = false; |
| |
| mySequenceNumberLock = new Object(); |
| peerSequenceNumberLock = new Object(); |
| } |
| |
| public GssContext(GSSCaller caller, byte[] interProcessToken) |
| throws GSSException { |
| throw new GSSException(GSSException.UNAVAILABLE, -1, "Unsupported feature"); |
| } |
| |
| public Provider getProvider() { |
| return new KerbyGssProvider(); |
| } |
| |
| 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 GssMechFactory.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 = (GssNameElement) myCred.getName(); |
| PrincipalName clientPrincipal = myName.getPrincipalName(); |
| |
| sgtTicket = GssUtil.getSgtCredentialFromContext(caller, clientPrincipal.getName(), serviceName); |
| |
| if (sgtTicket == null) { |
| sgtTicket = GssUtil.applySgtCredential(((GssInitCred) myCred).getKerberosTicket(), serviceName); |
| |
| // add this service credential to context |
| final KerberosTicket ticket = |
| GssUtil.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 GssEncryptor(getSessionKey()); |
| ctxState = STATE_ESTABLISHED; |
| } |
| |
| } else if (ctxState == STATE_ESTABLISHING) { |
| verifyServerToken(is, mechTokenSize); |
| gssEncryptor = new GssEncryptor(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, GssContext.INITIATOR_SUBKEY); |
| } else { |
| setSessionKey(sgt.getSessionKey(), GssContext.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"); |
| } |
| |
| GssAcceptCred acceptCred = (GssAcceptCred) myCred; |
| CredUtils.checkPrincipalPermission( |
| ((GssNameElement) acceptCred.getName()).getPrincipalName().getName(), "accept"); |
| |
| if (getMutualAuthState()) { |
| ret = verifyClientToken(acceptCred, is, mechTokenSize); |
| } |
| |
| gssEncryptor = new GssEncryptor(getSessionKey()); |
| |
| myCred = null; |
| ctxState = STATE_ESTABLISHED; |
| } |
| |
| return ret; |
| } |
| |
| private byte[] verifyClientToken(GssAcceptCred 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(); |
| |
| EncryptionKey serverKey = acceptCred.getEncryptionKey(encryptType, kvno); |
| if (serverKey == null) { |
| throw new GSSException(GSSException.FAILURE, -1, "Server key not found"); |
| } |
| peerName = (GssNameElement) acceptCred.getName(); |
| |
| try { |
| ApRequest.validate(serverKey, apReq, |
| channelBinding == null ? null : 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"); |
| } |
| |
| int len; |
| byte[] inBuf; |
| try { |
| len = is.available(); |
| inBuf = new byte[len]; |
| is.read(inBuf); |
| } catch (IOException e) { |
| throw new GSSException(GSSException.FAILURE, -1, "Error when get user data:" + e.getMessage()); |
| } |
| 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 (ctxState != STATE_ESTABLISHED) { |
| throw new GSSException(GSSException.NO_CONTEXT, -1, "Context invalid for unwrap"); |
| } |
| |
| 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 { |
| if (ctxState != STATE_ESTABLISHED) { |
| throw new GSSException(GSSException.NO_CONTEXT, -1, "Context invalid for getMIC"); |
| } |
| |
| try { |
| int len = is.available(); |
| byte[] inMsg = new byte[len]; |
| is.read(inMsg); |
| if (gssEncryptor.isV2()) { |
| MicTokenV2 token = new MicTokenV2(this, inMsg, 0, len, msgProp); |
| token.getMic(os); |
| } else { |
| MicTokenV1 token = new MicTokenV1(this, inMsg, 0, len, msgProp); |
| token.getMic(os); |
| } |
| } catch (IOException e) { |
| throw new GSSException(GSSException.FAILURE, -1, "Error when get user data in getMIC:" + e.getMessage()); |
| } |
| } |
| |
| public byte[] getMIC(byte[] inMsg, int offset, int len, |
| MessageProp msgProp) throws GSSException { |
| if (ctxState != STATE_ESTABLISHED) { |
| throw new GSSException(GSSException.NO_CONTEXT, -1, "Context invalid for getMIC"); |
| } |
| |
| byte[] ret; |
| if (gssEncryptor.isV2()) { |
| MicTokenV2 token = new MicTokenV2(this, inMsg, offset, len, msgProp); |
| ret = token.getMic(); |
| } else { |
| MicTokenV1 token = new MicTokenV1(this, inMsg, offset, len, msgProp); |
| ret = token.getMic(); |
| } |
| return ret; |
| } |
| |
| public void verifyMIC(InputStream is, InputStream msgStr, |
| MessageProp msgProp) throws GSSException { |
| if (ctxState != STATE_ESTABLISHED) { |
| throw new GSSException(GSSException.NO_CONTEXT, -1, "Context invalid for verifyMIC"); |
| } |
| |
| try { |
| int tokLen = is.available(); |
| byte[] inTok = new byte[tokLen]; |
| int msgLen = msgStr.available(); |
| byte[] inMsg = new byte[msgLen]; |
| |
| verifyMIC(inTok, 0, tokLen, inMsg, 0, msgLen, msgProp); |
| } catch (IOException e) { |
| throw new GSSException(GSSException.FAILURE, -1, |
| "Error when get user data in verifyMIC:" + e.getMessage()); |
| } |
| } |
| |
| public void verifyMIC(byte[]inTok, int tokOffset, int tokLen, |
| byte[] inMsg, int msgOffset, int msgLen, |
| MessageProp msgProp) throws GSSException { |
| if (ctxState != STATE_ESTABLISHED) { |
| throw new GSSException(GSSException.NO_CONTEXT, -1, "Context invalid for verifyMIC"); |
| } |
| |
| if (gssEncryptor.isV2()) { |
| MicTokenV2 token = new MicTokenV2(this, msgProp, inTok, tokOffset, tokLen); |
| token.verify(inMsg, msgOffset, msgLen); |
| } else { |
| MicTokenV1 token = new MicTokenV1(this, msgProp, inTok, tokOffset, tokLen); |
| token.verify(inMsg, msgOffset, msgLen); |
| } |
| } |
| |
| 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 GssUtil.ticketFlagsToBooleans(ticketFlags); |
| case KRB5_GET_AUTHZ_DATA: |
| if (isInitiator()) { |
| throw new GSSException(GSSException.UNAVAILABLE, -1, |
| "Authorization data not available for initiator"); |
| } else { |
| return GssUtil.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 GssEncryptor getGssEncryptor() { |
| return gssEncryptor; |
| } |
| } |
| |