/* * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.jgss.krb5; import com.sun.security.jgss.InquireType;import org.ietf.jgss.*;import sun.misc.HexDumpEncoder;import sun.security.jgss.GSSUtil;import sun.security.jgss.GSSCaller;import sun.security.jgss.spi.*;import sun.security.jgss.TokenTracker;import sun.security.krb5.*;import java.io.InputStream;import java.io.OutputStream;import java.io.IOException;import java.security.Provider;import java.security.AccessController;import java.security.AccessControlContext;import java.security.Key;import java.security.PrivilegedExceptionAction;import java.security.PrivilegedActionException;import javax.crypto.Cipher;import javax.security.auth.Subject;import javax.security.auth.kerberos.*; /** * Implements the mechanism specific context class for the Kerberos v5 * GSS-API mechanism. * * @author Mayank Upadhyay * @author Ram Marti * @since 1.4 */class Krb5Context implements GSSContextSpi { /* * The different states that this context can be in. */ private static final int STATE_NEW = 1; private static final int STATE_IN_PROCESS = 2; private static final int STATE_DONE = 3; private static final int STATE_DELETED = 4; private int state = STATE_NEW; /* * Optional features that the application can set and their default * values. */ private boolean credDelegState = false; private boolean mutualAuthState = true; private boolean replayDetState = true; private boolean sequenceDetState = true; private boolean confState = true; private boolean integState = true; private boolean delegPolicyState = false; private int mySeqNumber; private int peerSeqNumber; private TokenTracker peerTokenTracker; private CipherHelper cipherHelper = null; /* * Separate locks for the sequence numbers allow the application to * receive tokens at the same time that it is sending tokens. Note * that the application must synchronize the generation and * transmission of tokens such that tokens are processed in the same * order that they are generated. This is important when sequence * checking of per-message tokens is enabled. */ private Object mySeqNumberLock = new Object(); private Object peerSeqNumberLock = new Object(); private EncryptionKey key; private Krb5NameElement myName; private Krb5NameElement peerName; private int lifetime; private boolean initiator; private ChannelBinding channelBinding; private Krb5CredElement myCred; private Krb5CredElement delegatedCred; // Set only on acceptor side /* DESCipher instance used by the corresponding GSSContext */ private Cipher desCipher = null; // XXX See if the required info from these can be extracted and // stored elsewhere private Credentials serviceCreds; private KrbApReq apReq; final private GSSCaller caller; private static final boolean DEBUG = Krb5Util.DEBUG; /** * Constructor for Krb5Context to be called on the context initiator's * side. */ Krb5Context(GSSCaller caller, Krb5NameElement peerName, Krb5CredElement 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; } /** * Constructor for Krb5Context to be called on the context acceptor's * side. */ Krb5Context(GSSCaller caller, Krb5CredElement myCred) throws GSSException { this.caller = caller; this.myCred = myCred; this.initiator = false; } /** * Constructor for Krb5Context to import a previously exported context. */ public Krb5Context(GSSCaller caller, byte [] interProcessToken) throws GSSException { throw new GSSException(GSSException.UNAVAILABLE, -1, "GSS Import Context not available"); } /** * Method to determine if the context can be exported and then * re-imported. */ public final boolean isTransferable() throws GSSException { return false; } /** * The lifetime remaining for this context. */ public final int getLifetime() { // XXX Return service ticket lifetime return GSSContext.INDEFINITE_LIFETIME; } /* * Methods that may be invoked by the GSS framework in response * to an application request for setting/getting these * properties. * * These can only be called on the initiator side. * * Notice that an application can only request these * properties. The mechanism may or may not support them. The * application must make getXXX calls after context establishment * to see if the mechanism implementations on both sides support * these features. requestAnonymity is an exception where the * application will want to call getAnonymityState prior to sending any * GSS token during context establishment. * * Also note that the requests can only be placed before context * establishment starts. i.e. when state is STATE_NEW */ /** * Requests the desired lifetime. Can only be used on the context * initiator's side. */ public void requestLifetime(int lifetime) throws GSSException { if (state == STATE_NEW && isInitiator()) this.lifetime = lifetime; } /** * Requests that confidentiality be available. */ public final void requestConf(boolean value) throws GSSException { if (state == STATE_NEW && isInitiator()) confState = value; } /** * Is confidentiality available? */ public final boolean getConfState() { return confState; } /** * Requests that integrity be available. */ public final void requestInteg(boolean value) throws GSSException { if (state == STATE_NEW && isInitiator()) integState = value; } /** * Is integrity available? */ public final boolean getIntegState() { return integState; } /** * Requests that credential delegation be done during context * establishment. */ public final void requestCredDeleg(boolean value) throws GSSException { if (state == STATE_NEW && isInitiator()) credDelegState = value; } /** * Is credential delegation enabled? */ public final boolean getCredDelegState() { return credDelegState; } /** * Requests that mutual authentication be done during context * establishment. Since this is fromm the client's perspective, it * essentially requests that the server be authenticated. */ public final void requestMutualAuth(boolean value) throws GSSException { if (state == STATE_NEW && isInitiator()) { mutualAuthState = value; } } /** * Is mutual authentication enabled? Since this is from the client's * perspective, it essentially meas that the server is being * authenticated. */ public final boolean getMutualAuthState() { return mutualAuthState; } /** * Requests that replay detection be done on the GSS wrap and MIC * tokens. */ public final void requestReplayDet(boolean value) throws GSSException { if (state == STATE_NEW && isInitiator()) replayDetState = value; } /** * Is replay detection enabled on the GSS wrap and MIC tokens? * We enable replay detection if sequence checking is enabled. */ public final boolean getReplayDetState() { return replayDetState || sequenceDetState; } /** * Requests that sequence checking be done on the GSS wrap and MIC * tokens. */ public final void requestSequenceDet(boolean value) throws GSSException { if (state == STATE_NEW && isInitiator()) sequenceDetState = value; } /** * Is sequence checking enabled on the GSS Wrap and MIC tokens? * We enable sequence checking if replay detection is enabled. */ public final boolean getSequenceDetState() { return sequenceDetState || replayDetState; } /** * Requests that the deleg policy be respected. */ public final void requestDelegPolicy(boolean value) { if (state == STATE_NEW && isInitiator()) delegPolicyState = value; } /** * Is deleg policy respected? */ public final boolean getDelegPolicyState() { return delegPolicyState; } /* * Anonymity is a little different in that after an application * requests anonymity it will want to know whether the mechanism * can support it or not, prior to sending any tokens across for * context establishment. Since this is from the initiator's * perspective, it essentially requests that the initiator be * anonymous. */ public final void requestAnonymity(boolean value) throws GSSException { // Ignore silently. Application will check back with // getAnonymityState. } // RFC 2853 actually calls for this to be called after context // establishment to get the right answer, but that is // incorrect. The application may not want to send over any // tokens if anonymity is not available. public final boolean getAnonymityState() { return false; } /* * Package private methods invoked by other Krb5 plugin classes. */ /** * Get the context specific DESCipher instance, invoked in * MessageToken.init() */ final CipherHelper getCipherHelper(EncryptionKey ckey) throws GSSException { EncryptionKey cipherKey = null; if (cipherHelper == null) { cipherKey = (getKey() == null) ? ckey: getKey(); cipherHelper = new CipherHelper(cipherKey); } return cipherHelper; } final int incrementMySequenceNumber() { int retVal; synchronized (mySeqNumberLock) { retVal = mySeqNumber; mySeqNumber = retVal + 1; } return retVal; } final void resetMySequenceNumber(int seqNumber) { if (DEBUG) { System.out.println("Krb5Context setting mySeqNumber to: " + seqNumber); } synchronized (mySeqNumberLock) { mySeqNumber = seqNumber; } } final void resetPeerSequenceNumber(int seqNumber) { if (DEBUG) { System.out.println("Krb5Context setting peerSeqNumber to: " + seqNumber); } synchronized (peerSeqNumberLock) { peerSeqNumber = seqNumber; peerTokenTracker = new TokenTracker(peerSeqNumber); } } final void setKey(EncryptionKey key) throws GSSException { this.key = key; // %%% to do: should clear old cipherHelper first cipherHelper = new CipherHelper(key); // Need to use new key } private final EncryptionKey getKey() { return key; } /** * Called on the acceptor side to store the delegated credentials * received in the AcceptSecContextToken. */ final void setDelegCred(Krb5CredElement delegatedCred) { this.delegatedCred = delegatedCred; } /* * While the application can only request the following features, * other classes in the package can call the actual set methods * for them. They are called as context establishment tokens are * received on an acceptor side and the context feature list that * the initiator wants becomes known. */ /* * This method is also called by InitialToken.OverloadedChecksum if the * TGT is not forwardable and the user requested delegation. */ final void setCredDelegState(boolean state) { credDelegState = state; } final void setMutualAuthState(boolean state) { mutualAuthState = state; } final void setReplayDetState(boolean state) { replayDetState = state; } final void setSequenceDetState(boolean state) { sequenceDetState = state; } final void setConfState(boolean state) { confState = state; } final void setIntegState(boolean state) { integState = state; } final void setDelegPolicyState(boolean state) { delegPolicyState = state; } /** * Sets the channel bindings to be used during context * establishment. */ public final void setChannelBinding(ChannelBinding channelBinding) throws GSSException { this.channelBinding = channelBinding; } final ChannelBinding getChannelBinding() { return channelBinding; } /** * Returns the mechanism oid. * * @return the Oid of this context */ public final Oid getMech() { return (Krb5MechFactory.GSS_KRB5_MECH_OID); } /** * Returns the context initiator name. * * @return initiator name * @exception GSSException */ public final GSSNameSpi getSrcName() throws GSSException { return (isInitiator()? myName : peerName); } /** * Returns the context acceptor. * * @return context acceptor(target) name * @exception GSSException */ public final GSSNameSpi getTargName() throws GSSException { return (!isInitiator()? myName : peerName); } /** * Returns the delegated credential for the context. This * is an optional feature of contexts which not all * mechanisms will support. A context can be requested to * support credential delegation by using the <b>CRED_DELEG</b>. * This is only valid on the acceptor side of the context. * @return GSSCredentialSpi object for the delegated credential * @exception GSSException * @see GSSContext#getDelegCredState */ public final GSSCredentialSpi getDelegCred() throws GSSException { if (state != STATE_IN_PROCESS && state != STATE_DONE) throw new GSSException(GSSException.NO_CONTEXT); if (delegatedCred == null)Lines 1–500 of 1385. Load more
/* * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.jgss.krb5; import com.sun.security.jgss.InquireType; import org.ietf.jgss.*; import sun.misc.HexDumpEncoder; import sun.security.jgss.GSSUtil; import sun.security.jgss.GSSCaller; import sun.security.jgss.spi.*; import sun.security.jgss.TokenTracker; import sun.security.krb5.*; import java.io.InputStream; import java.io.OutputStream; import java.io.IOException; import java.security.Provider; import java.security.AccessController; import java.security.AccessControlContext; import java.security.Key; import java.security.PrivilegedExceptionAction; import java.security.PrivilegedActionException; import javax.crypto.Cipher; import javax.security.auth.Subject; import javax.security.auth.kerberos.*; /** * Implements the mechanism specific context class for the Kerberos v5 * GSS-API mechanism. * * @author Mayank Upadhyay * @author Ram Marti * @since 1.4 */ class Krb5Context implements GSSContextSpi { /* * The different states that this context can be in. */ private static final int STATE_NEW = 1; private static final int STATE_IN_PROCESS = 2; private static final int STATE_DONE = 3; private static final int STATE_DELETED = 4; private int state = STATE_NEW; /* * Optional features that the application can set and their default * values. */ private boolean credDelegState = false; private boolean mutualAuthState = true; private boolean replayDetState = true; private boolean sequenceDetState = true; private boolean confState = true; private boolean integState = true; private boolean delegPolicyState = false; private int mySeqNumber; private int peerSeqNumber; private TokenTracker peerTokenTracker; private CipherHelper cipherHelper = null; /* * Separate locks for the sequence numbers allow the application to * receive tokens at the same time that it is sending tokens. Note * that the application must synchronize the generation and * transmission of tokens such that tokens are processed in the same * order that they are generated. This is important when sequence * checking of per-message tokens is enabled. */ private Object mySeqNumberLock = new Object(); private Object peerSeqNumberLock = new Object(); private EncryptionKey key; private Krb5NameElement myName; private Krb5NameElement peerName; private int lifetime; private boolean initiator; private ChannelBinding channelBinding; private Krb5CredElement myCred; private Krb5CredElement delegatedCred; // Set only on acceptor side /* DESCipher instance used by the corresponding GSSContext */ private Cipher desCipher = null; // XXX See if the required info from these can be extracted and // stored elsewhere private Credentials serviceCreds; private KrbApReq apReq; final private GSSCaller caller; private static final boolean DEBUG = Krb5Util.DEBUG; /** * Constructor for Krb5Context to be called on the context initiator's * side. */ Krb5Context(GSSCaller caller, Krb5NameElement peerName, Krb5CredElement 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; } /** * Constructor for Krb5Context to be called on the context acceptor's * side. */ Krb5Context(GSSCaller caller, Krb5CredElement myCred) throws GSSException { this.caller = caller; this.myCred = myCred; this.initiator = false; } /** * Constructor for Krb5Context to import a previously exported context. */ public Krb5Context(GSSCaller caller, byte [] interProcessToken) throws GSSException { throw new GSSException(GSSException.UNAVAILABLE, -1, "GSS Import Context not available"); } /** * Method to determine if the context can be exported and then * re-imported. */ public final boolean isTransferable() throws GSSException { return false; } /** * The lifetime remaining for this context. */ public final int getLifetime() { // XXX Return service ticket lifetime return GSSContext.INDEFINITE_LIFETIME; } /* * Methods that may be invoked by the GSS framework in response * to an application request for setting/getting these * properties. * * These can only be called on the initiator side. * * Notice that an application can only request these * properties. The mechanism may or may not support them. The * application must make getXXX calls after context establishment * to see if the mechanism implementations on both sides support * these features. requestAnonymity is an exception where the * application will want to call getAnonymityState prior to sending any * GSS token during context establishment. * * Also note that the requests can only be placed before context * establishment starts. i.e. when state is STATE_NEW */ /** * Requests the desired lifetime. Can only be used on the context * initiator's side. */ public void requestLifetime(int lifetime) throws GSSException { if (state == STATE_NEW && isInitiator()) this.lifetime = lifetime; } /** * Requests that confidentiality be available. */ public final void requestConf(boolean value) throws GSSException { if (state == STATE_NEW && isInitiator()) confState = value; } /** * Is confidentiality available? */ public final boolean getConfState() { return confState; } /** * Requests that integrity be available. */ public final void requestInteg(boolean value) throws GSSException { if (state == STATE_NEW && isInitiator()) integState = value; } /** * Is integrity available? */ public final boolean getIntegState() { return integState; } /** * Requests that credential delegation be done during context * establishment. */ public final void requestCredDeleg(boolean value) throws GSSException { if (state == STATE_NEW && isInitiator()) credDelegState = value; } /** * Is credential delegation enabled? */ public final boolean getCredDelegState() { return credDelegState; } /** * Requests that mutual authentication be done during context * establishment. Since this is fromm the client's perspective, it * essentially requests that the server be authenticated. */ public final void requestMutualAuth(boolean value) throws GSSException { if (state == STATE_NEW && isInitiator()) { mutualAuthState = value; } } /** * Is mutual authentication enabled? Since this is from the client's * perspective, it essentially meas that the server is being * authenticated. */ public final boolean getMutualAuthState() { return mutualAuthState; } /** * Requests that replay detection be done on the GSS wrap and MIC * tokens. */ public final void requestReplayDet(boolean value) throws GSSException { if (state == STATE_NEW && isInitiator()) replayDetState = value; } /** * Is replay detection enabled on the GSS wrap and MIC tokens? * We enable replay detection if sequence checking is enabled. */ public final boolean getReplayDetState() { return replayDetState || sequenceDetState; } /** * Requests that sequence checking be done on the GSS wrap and MIC * tokens. */ public final void requestSequenceDet(boolean value) throws GSSException { if (state == STATE_NEW && isInitiator()) sequenceDetState = value; } /** * Is sequence checking enabled on the GSS Wrap and MIC tokens? * We enable sequence checking if replay detection is enabled. */ public final boolean getSequenceDetState() { return sequenceDetState || replayDetState; } /** * Requests that the deleg policy be respected. */ public final void requestDelegPolicy(boolean value) { if (state == STATE_NEW && isInitiator()) delegPolicyState = value; } /** * Is deleg policy respected? */ public final boolean getDelegPolicyState() { return delegPolicyState; } /* * Anonymity is a little different in that after an application * requests anonymity it will want to know whether the mechanism * can support it or not, prior to sending any tokens across for * context establishment. Since this is from the initiator's * perspective, it essentially requests that the initiator be * anonymous. */ public final void requestAnonymity(boolean value) throws GSSException { // Ignore silently. Application will check back with // getAnonymityState. } // RFC 2853 actually calls for this to be called after context // establishment to get the right answer, but that is // incorrect. The application may not want to send over any // tokens if anonymity is not available. public final boolean getAnonymityState() { return false; } /* * Package private methods invoked by other Krb5 plugin classes. */ /** * Get the context specific DESCipher instance, invoked in * MessageToken.init() */ final CipherHelper getCipherHelper(EncryptionKey ckey) throws GSSException { EncryptionKey cipherKey = null; if (cipherHelper == null) { cipherKey = (getKey() == null) ? ckey: getKey(); cipherHelper = new CipherHelper(cipherKey); } return cipherHelper; } final int incrementMySequenceNumber() { int retVal; synchronized (mySeqNumberLock) { retVal = mySeqNumber; mySeqNumber = retVal + 1; } return retVal; } final void resetMySequenceNumber(int seqNumber) { if (DEBUG) { System.out.println("Krb5Context setting mySeqNumber to: " + seqNumber); } synchronized (mySeqNumberLock) { mySeqNumber = seqNumber; } } final void resetPeerSequenceNumber(int seqNumber) { if (DEBUG) { System.out.println("Krb5Context setting peerSeqNumber to: " + seqNumber); } synchronized (peerSeqNumberLock) { peerSeqNumber = seqNumber; peerTokenTracker = new TokenTracker(peerSeqNumber); } } final void setKey(EncryptionKey key) throws GSSException { this.key = key; // %%% to do: should clear old cipherHelper first cipherHelper = new CipherHelper(key); // Need to use new key } private final EncryptionKey getKey() { return key; } /** * Called on the acceptor side to store the delegated credentials * received in the AcceptSecContextToken. */ final void setDelegCred(Krb5CredElement delegatedCred) { this.delegatedCred = delegatedCred; } /* * While the application can only request the following features, * other classes in the package can call the actual set methods * for them. They are called as context establishment tokens are * received on an acceptor side and the context feature list that * the initiator wants becomes known. */ /* * This method is also called by InitialToken.OverloadedChecksum if the * TGT is not forwardable and the user requested delegation. */ final void setCredDelegState(boolean state) { credDelegState = state; } final void setMutualAuthState(boolean state) { mutualAuthState = state; } final void setReplayDetState(boolean state) { replayDetState = state; } final void setSequenceDetState(boolean state) { sequenceDetState = state; } final void setConfState(boolean state) { confState = state; } final void setIntegState(boolean state) { integState = state; } final void setDelegPolicyState(boolean state) { delegPolicyState = state; } /** * Sets the channel bindings to be used during context * establishment. */ public final void setChannelBinding(ChannelBinding channelBinding) throws GSSException { this.channelBinding = channelBinding; } final ChannelBinding getChannelBinding() { return channelBinding; } /** * Returns the mechanism oid. * * @return the Oid of this context */ public final Oid getMech() { return (Krb5MechFactory.GSS_KRB5_MECH_OID); } /** * Returns the context initiator name. * * @return initiator name * @exception GSSException */ public final GSSNameSpi getSrcName() throws GSSException { return (isInitiator()? myName : peerName); } /** * Returns the context acceptor. * * @return context acceptor(target) name * @exception GSSException */ public final GSSNameSpi getTargName() throws GSSException { return (!isInitiator()? myName : peerName); } /** * Returns the delegated credential for the context. This * is an optional feature of contexts which not all * mechanisms will support. A context can be requested to * support credential delegation by using the <b>CRED_DELEG</b>. * This is only valid on the acceptor side of the context. * @return GSSCredentialSpi object for the delegated credential * @exception GSSException * @see GSSContext#getDelegCredState */ public final GSSCredentialSpi getDelegCred() throws GSSException { if (state != STATE_IN_PROCESS && state != STATE_DONE) throw new GSSException(GSSException.NO_CONTEXT); if (delegatedCred == null)