1385 lines · 48.8 KB · Java
RawDownload
/* * 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.