Path: blob/master/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java
67792 views
/*1* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.jgss.spnego;2627import java.io.*;28import java.security.Provider;29import org.ietf.jgss.*;30import sun.security.action.GetBooleanAction;31import sun.security.jgss.*;32import sun.security.jgss.spi.*;33import sun.security.util.*;3435/**36* Implements the mechanism specific context class for SPNEGO37* GSS-API mechanism38*39* @author Seema Malkani40* @since 1.641*/42public class SpNegoContext implements GSSContextSpi {4344/*45* The different states that this context can be in.46*/47private static final int STATE_NEW = 1;48private static final int STATE_IN_PROCESS = 2;49private static final int STATE_DONE = 3;50private static final int STATE_DELETED = 4;5152private int state = STATE_NEW;5354/*55* Optional features that the application can set and their default56* values.57*/58private boolean credDelegState = false;59private boolean mutualAuthState = true;60private boolean replayDetState = true;61private boolean sequenceDetState = true;62private boolean confState = true;63private boolean integState = true;64private boolean delegPolicyState = false;6566private GSSNameSpi peerName = null;67private GSSNameSpi myName = null;68private SpNegoCredElement myCred = null;6970private GSSContext mechContext = null;71private byte[] DER_mechTypes = null;7273private int lifetime;74private ChannelBinding channelBinding;75private boolean initiator;7677// the underlying negotiated mechanism78private Oid internal_mech = null;7980// the SpNegoMechFactory that creates this context81private final SpNegoMechFactory factory;8283// debug property84static final boolean DEBUG = GetBooleanAction85.privilegedGetProperty("sun.security.spnego.debug");8687/**88* Constructor for SpNegoContext to be called on the context initiator's89* side.90*/91public SpNegoContext(SpNegoMechFactory factory, GSSNameSpi peerName,92GSSCredentialSpi myCred,93int lifetime) throws GSSException {9495if (peerName == null)96throw new IllegalArgumentException("Cannot have null peer name");97if ((myCred != null) && !(myCred instanceof SpNegoCredElement)) {98throw new IllegalArgumentException("Wrong cred element type");99}100this.peerName = peerName;101this.myCred = (SpNegoCredElement) myCred;102this.lifetime = lifetime;103this.initiator = true;104this.factory = factory;105}106107/**108* Constructor for SpNegoContext to be called on the context acceptor's109* side.110*/111public SpNegoContext(SpNegoMechFactory factory, GSSCredentialSpi myCred)112throws GSSException {113if ((myCred != null) && !(myCred instanceof SpNegoCredElement)) {114throw new IllegalArgumentException("Wrong cred element type");115}116this.myCred = (SpNegoCredElement) myCred;117this.initiator = false;118this.factory = factory;119}120121/**122* Constructor for SpNegoContext to import a previously exported context.123*/124public SpNegoContext(SpNegoMechFactory factory, byte [] interProcessToken)125throws GSSException {126throw new GSSException(GSSException.UNAVAILABLE,127-1, "GSS Import Context not available");128}129130/**131* Requests that confidentiality be available.132*/133public final void requestConf(boolean value) throws GSSException {134if (state == STATE_NEW && isInitiator())135confState = value;136}137138/**139* Is confidentiality available?140*/141public final boolean getConfState() {142return confState;143}144145/**146* Requests that integrity be available.147*/148public final void requestInteg(boolean value) throws GSSException {149if (state == STATE_NEW && isInitiator())150integState = value;151}152153/**154* Requests that deleg policy be respected.155*/156public final void requestDelegPolicy(boolean value) throws GSSException {157if (state == STATE_NEW && isInitiator())158delegPolicyState = value;159}160161/**162* Is integrity available?163*/164public final boolean getIntegState() {165return integState;166}167168/**169* Is deleg policy respected?170*/171public final boolean getDelegPolicyState() {172if (isInitiator() && mechContext != null &&173mechContext instanceof GSSContextImpl &&174(state == STATE_IN_PROCESS || state == STATE_DONE)) {175return ((GSSContextImpl)mechContext).getDelegPolicyState();176} else {177return delegPolicyState;178}179}180181/**182* Requests that credential delegation be done during context183* establishment.184*/185public final void requestCredDeleg(boolean value) throws GSSException {186if (state == STATE_NEW && isInitiator())187credDelegState = value;188}189190/**191* Is credential delegation enabled?192*/193public final boolean getCredDelegState() {194if (isInitiator() && mechContext != null &&195(state == STATE_IN_PROCESS || state == STATE_DONE)) {196return mechContext.getCredDelegState();197} else {198return credDelegState;199}200}201202/**203* Requests that mutual authentication be done during context204* establishment. Since this is fromm the client's perspective, it205* essentially requests that the server be authenticated.206*/207public final void requestMutualAuth(boolean value) throws GSSException {208if (state == STATE_NEW && isInitiator()) {209mutualAuthState = value;210}211}212213/**214* Is mutual authentication enabled? Since this is from the client's215* perspective, it essentially meas that the server is being216* authenticated.217*/218public final boolean getMutualAuthState() {219return mutualAuthState;220}221222/**223* Returns the mechanism oid.224*225* @return the Oid of this context226*/227public final Oid getMech() {228if (isEstablished()) {229return getNegotiatedMech();230}231return (SpNegoMechFactory.GSS_SPNEGO_MECH_OID);232}233234public final Oid getNegotiatedMech() {235return (internal_mech);236}237238public final Provider getProvider() {239return SpNegoMechFactory.PROVIDER;240}241242public final void dispose() throws GSSException {243mechContext = null;244state = STATE_DELETED;245}246247/**248* Tests if this is the initiator side of the context.249*250* @return boolean indicating if this is initiator (true)251* or target (false)252*/253public final boolean isInitiator() {254return initiator;255}256257/**258* Tests if the context can be used for per-message service.259* Context may allow the calls to the per-message service260* functions before being fully established.261*262* @return boolean indicating if per-message methods can263* be called.264*/265public final boolean isProtReady() {266return (state == STATE_DONE);267}268269/**270* Initiator context establishment call. This method may be271* required to be called several times. A CONTINUE_NEEDED return272* call indicates that more calls are needed after the next token273* is received from the peer.274*275* @param is contains the token received from the peer. On the276* first call it will be ignored.277* @return any token required to be sent to the peer278* It is responsibility of the caller to send the token279* to its peer for processing.280* @exception GSSException281*/282@Deprecated(since="11")283public final byte[] initSecContext(InputStream is, int mechTokenSize)284throws GSSException {285286byte[] retVal = null;287NegTokenInit initToken = null;288byte[] mechToken = null;289int errorCode = GSSException.FAILURE;290291if (DEBUG) {292System.out.println("Entered SpNego.initSecContext with " +293"state=" + printState(state));294}295if (!isInitiator()) {296throw new GSSException(GSSException.FAILURE, -1,297"initSecContext on an acceptor GSSContext");298}299300try {301if (state == STATE_NEW) {302state = STATE_IN_PROCESS;303304errorCode = GSSException.NO_CRED;305306// determine available mech set307Oid[] mechList = getAvailableMechs();308DER_mechTypes = getEncodedMechs(mechList);309310// pull out first mechanism311internal_mech = mechList[0];312313// get the token for first mechanism314mechToken = GSS_initSecContext(null);315316errorCode = GSSException.DEFECTIVE_TOKEN;317// generate SPNEGO token318initToken = new NegTokenInit(DER_mechTypes, getContextFlags(),319mechToken, null);320if (DEBUG) {321System.out.println("SpNegoContext.initSecContext: " +322"sending token of type = " +323SpNegoToken.getTokenName(initToken.getType()));324}325// get the encoded token326retVal = initToken.getEncoded();327328} else if (state == STATE_IN_PROCESS) {329330errorCode = GSSException.FAILURE;331if (is == null) {332throw new GSSException(errorCode, -1,333"No token received from peer!");334}335336errorCode = GSSException.DEFECTIVE_TOKEN;337byte[] server_token = new byte[is.available()];338SpNegoToken.readFully(is, server_token);339if (DEBUG) {340System.out.println("SpNegoContext.initSecContext: " +341"process received token = " +342SpNegoToken.getHexBytes(server_token));343}344345// read the SPNEGO token346// token will be validated when parsing347NegTokenTarg targToken = new NegTokenTarg(server_token);348349if (DEBUG) {350System.out.println("SpNegoContext.initSecContext: " +351"received token of type = " +352SpNegoToken.getTokenName(targToken.getType()));353}354355// pull out mechanism356internal_mech = targToken.getSupportedMech();357if (internal_mech == null) {358// return with failure359throw new GSSException(errorCode, -1,360"supported mechanism from server is null");361}362363// get the negotiated result364SpNegoToken.NegoResult negoResult = null;365int result = targToken.getNegotiatedResult();366switch (result) {367case 0:368negoResult = SpNegoToken.NegoResult.ACCEPT_COMPLETE;369state = STATE_DONE;370break;371case 1:372negoResult = SpNegoToken.NegoResult.ACCEPT_INCOMPLETE;373state = STATE_IN_PROCESS;374break;375case 2:376negoResult = SpNegoToken.NegoResult.REJECT;377state = STATE_DELETED;378break;379default:380state = STATE_DONE;381break;382}383384errorCode = GSSException.BAD_MECH;385386if (negoResult == SpNegoToken.NegoResult.REJECT) {387throw new GSSException(errorCode, -1,388internal_mech.toString());389}390391errorCode = GSSException.DEFECTIVE_TOKEN;392393if ((negoResult == SpNegoToken.NegoResult.ACCEPT_COMPLETE) ||394(negoResult == SpNegoToken.NegoResult.ACCEPT_INCOMPLETE)) {395396// pull out the mechanism token397byte[] accept_token = targToken.getResponseToken();398if (accept_token == null) {399if (!isMechContextEstablished()) {400// return with failure401throw new GSSException(errorCode, -1,402"mechanism token from server is null");403}404} else {405mechToken = GSS_initSecContext(accept_token);406}407// verify MIC408if (!GSSUtil.useMSInterop()) {409byte[] micToken = targToken.getMechListMIC();410if (!verifyMechListMIC(DER_mechTypes, micToken)) {411throw new GSSException(errorCode, -1,412"verification of MIC on MechList Failed!");413}414}415if (isMechContextEstablished()) {416state = STATE_DONE;417retVal = mechToken;418if (DEBUG) {419System.out.println("SPNEGO Negotiated Mechanism = "420+ internal_mech + " " +421GSSUtil.getMechStr(internal_mech));422}423} else {424// generate SPNEGO token425initToken = new NegTokenInit(null, null,426mechToken, null);427if (DEBUG) {428System.out.println("SpNegoContext.initSecContext:" +429" continue sending token of type = " +430SpNegoToken.getTokenName(initToken.getType()));431}432// get the encoded token433retVal = initToken.getEncoded();434}435}436437} else {438// XXX Use logging API439if (DEBUG) {440System.out.println(state);441}442}443if (DEBUG) {444if (retVal != null) {445System.out.println("SNegoContext.initSecContext: " +446"sending token = " + SpNegoToken.getHexBytes(retVal));447}448}449} catch (GSSException e) {450GSSException gssException =451new GSSException(errorCode, -1, e.getMessage());452gssException.initCause(e);453throw gssException;454} catch (IOException e) {455GSSException gssException =456new GSSException(GSSException.FAILURE, -1, e.getMessage());457gssException.initCause(e);458throw gssException;459}460461return retVal;462}463464465/**466* Acceptor's context establishment call. This method may be467* required to be called several times. A CONTINUE_NEEDED return468* call indicates that more calls are needed after the next token469* is received from the peer.470*471* @param is contains the token received from the peer.472* @return any token required to be sent to the peer473* It is responsibility of the caller to send the token474* to its peer for processing.475* @exception GSSException476*/477@Deprecated(since="11")478public final byte[] acceptSecContext(InputStream is, int mechTokenSize)479throws GSSException {480481byte[] retVal = null;482SpNegoToken.NegoResult negoResult;483boolean valid = true;484485if (DEBUG) {486System.out.println("Entered SpNegoContext.acceptSecContext with " +487"state=" + printState(state));488}489490if (isInitiator()) {491throw new GSSException(GSSException.FAILURE, -1,492"acceptSecContext on an initiator " +493"GSSContext");494}495try {496if (state == STATE_NEW) {497state = STATE_IN_PROCESS;498499// read data500byte[] token = new byte[is.available()];501SpNegoToken.readFully(is, token);502if (DEBUG) {503System.out.println("SpNegoContext.acceptSecContext: " +504"receiving token = " +505SpNegoToken.getHexBytes(token));506}507508// read the SPNEGO token509// token will be validated when parsing510NegTokenInit initToken = new NegTokenInit(token);511512if (DEBUG) {513System.out.println("SpNegoContext.acceptSecContext: " +514"received token of type = " +515SpNegoToken.getTokenName(initToken.getType()));516}517518Oid[] mechList = initToken.getMechTypeList();519DER_mechTypes = initToken.getMechTypes();520if (DER_mechTypes == null) {521valid = false;522}523524/*525* Select the best match between the list of mechs526* that the initiator requested and the list that527* the acceptor will support.528*/529Oid[] supported_mechSet = getAvailableMechs();530Oid mech_wanted =531negotiate_mech_type(supported_mechSet, mechList);532if (mech_wanted == null) {533valid = false;534}535// save the desired mechanism536internal_mech = mech_wanted;537538// get the token for mechanism539byte[] accept_token;540541if (mechList[0].equals(mech_wanted) ||542(GSSUtil.isKerberosMech(mechList[0]) &&543GSSUtil.isKerberosMech(mech_wanted))) {544// get the mechanism token545if (DEBUG && !mech_wanted.equals(mechList[0])) {546System.out.println("SpNegoContext.acceptSecContext: " +547"negotiated mech adjusted to " + mechList[0]);548}549byte[] mechToken = initToken.getMechToken();550if (mechToken == null) {551throw new GSSException(GSSException.FAILURE, -1,552"mechToken is missing");553}554accept_token = GSS_acceptSecContext(mechToken);555mech_wanted = mechList[0];556} else {557accept_token = null;558}559560// verify MIC561if (!GSSUtil.useMSInterop() && valid) {562valid = verifyMechListMIC(DER_mechTypes,563initToken.getMechListMIC());564}565566// determine negotiated result status567if (valid) {568if (isMechContextEstablished()) {569negoResult = SpNegoToken.NegoResult.ACCEPT_COMPLETE;570state = STATE_DONE;571// now set the context flags for acceptor572setContextFlags();573// print the negotiated mech info574if (DEBUG) {575System.out.println("SPNEGO Negotiated Mechanism = "576+ internal_mech + " " +577GSSUtil.getMechStr(internal_mech));578}579} else {580negoResult = SpNegoToken.NegoResult.ACCEPT_INCOMPLETE;581state = STATE_IN_PROCESS;582}583} else {584negoResult = SpNegoToken.NegoResult.REJECT;585state = STATE_DELETED;586throw new GSSException(GSSException.FAILURE);587}588589if (DEBUG) {590System.out.println("SpNegoContext.acceptSecContext: " +591"mechanism wanted = " + mech_wanted);592System.out.println("SpNegoContext.acceptSecContext: " +593"negotiated result = " + negoResult);594}595596// generate SPNEGO token597NegTokenTarg targToken = new NegTokenTarg(negoResult.ordinal(),598mech_wanted, accept_token, null);599if (DEBUG) {600System.out.println("SpNegoContext.acceptSecContext: " +601"sending token of type = " +602SpNegoToken.getTokenName(targToken.getType()));603}604// get the encoded token605retVal = targToken.getEncoded();606607} else if (state == STATE_IN_PROCESS) {608// read data609byte[] token = new byte[is.available()];610SpNegoToken.readFully(is, token);611if (DEBUG) {612System.out.println("SpNegoContext.acceptSecContext: " +613"receiving token = " +614SpNegoToken.getHexBytes(token));615}616617// read the SPNEGO token618// token will be validated when parsing619NegTokenTarg inputToken = new NegTokenTarg(token);620621if (DEBUG) {622System.out.println("SpNegoContext.acceptSecContext: " +623"received token of type = " +624SpNegoToken.getTokenName(inputToken.getType()));625}626627// read the token628byte[] client_token = inputToken.getResponseToken();629byte[] accept_token = GSS_acceptSecContext(client_token);630if (accept_token == null) {631valid = false;632}633634// determine negotiated result status635if (valid) {636if (isMechContextEstablished()) {637negoResult = SpNegoToken.NegoResult.ACCEPT_COMPLETE;638state = STATE_DONE;639} else {640negoResult = SpNegoToken.NegoResult.ACCEPT_INCOMPLETE;641state = STATE_IN_PROCESS;642}643} else {644negoResult = SpNegoToken.NegoResult.REJECT;645state = STATE_DELETED;646throw new GSSException(GSSException.FAILURE);647}648649// generate SPNEGO token650NegTokenTarg targToken = new NegTokenTarg(negoResult.ordinal(),651null, accept_token, null);652if (DEBUG) {653System.out.println("SpNegoContext.acceptSecContext: " +654"sending token of type = " +655SpNegoToken.getTokenName(targToken.getType()));656}657// get the encoded token658retVal = targToken.getEncoded();659660} else {661// XXX Use logging API662if (DEBUG) {663System.out.println("AcceptSecContext: state = " + state);664}665}666if (DEBUG) {667System.out.println("SpNegoContext.acceptSecContext: " +668"sending token = " + SpNegoToken.getHexBytes(retVal));669}670} catch (IOException e) {671GSSException gssException =672new GSSException(GSSException.FAILURE, -1, e.getMessage());673gssException.initCause(e);674throw gssException;675}676677if (state == STATE_DONE) {678// now set the context flags for acceptor679setContextFlags();680}681return retVal;682}683684/**685* obtain the available mechanisms686*/687private Oid[] getAvailableMechs() {688if (myCred != null) {689Oid[] mechs = new Oid[1];690mechs[0] = myCred.getInternalMech();691return mechs;692} else {693return factory.availableMechs;694}695}696697/**698* get the DER encoded MechList699*/700private byte[] getEncodedMechs(Oid[] mechSet)701throws IOException, GSSException {702703DerOutputStream mech = new DerOutputStream();704for (int i = 0; i < mechSet.length; i++) {705byte[] mechType = mechSet[i].getDER();706mech.write(mechType);707}708// insert in SEQUENCE709DerOutputStream mechTypeList = new DerOutputStream();710mechTypeList.write(DerValue.tag_Sequence, mech);711byte[] encoded = mechTypeList.toByteArray();712return encoded;713}714715/**716* get the context flags717*/718private BitArray getContextFlags() {719BitArray out = new BitArray(7);720721if (getCredDelegState()) out.set(0, true);722if (getMutualAuthState()) out.set(1, true);723if (getReplayDetState()) out.set(2, true);724if (getSequenceDetState()) out.set(3, true);725if (getConfState()) out.set(5, true);726if (getIntegState()) out.set(6, true);727728return out;729}730731// Only called on acceptor side. On the initiator side, most flags732// are already set at request. For those that might get chanegd,733// state from mech below is used.734private void setContextFlags() {735736if (mechContext != null) {737// default for cred delegation is false738if (mechContext.getCredDelegState()) {739credDelegState = true;740}741// default for the following are true742if (!mechContext.getMutualAuthState()) {743mutualAuthState = false;744}745if (!mechContext.getReplayDetState()) {746replayDetState = false;747}748if (!mechContext.getSequenceDetState()) {749sequenceDetState = false;750}751if (!mechContext.getIntegState()) {752integState = false;753}754if (!mechContext.getConfState()) {755confState = false;756}757}758}759760/**761* generate MIC on mechList. Not used at the moment.762*/763/*private byte[] generateMechListMIC(byte[] mechTypes)764throws GSSException {765766// sanity check the required input767if (mechTypes == null) {768if (DEBUG) {769System.out.println("SpNegoContext: no MIC token included");770}771return null;772}773774// check if mechanism supports integrity775if (!mechContext.getIntegState()) {776if (DEBUG) {777System.out.println("SpNegoContext: no MIC token included" +778" - mechanism does not support integrity");779}780return null;781}782783// compute MIC on DER encoded mechanism list784byte[] mic = null;785try {786MessageProp prop = new MessageProp(0, true);787mic = getMIC(mechTypes, 0, mechTypes.length, prop);788if (DEBUG) {789System.out.println("SpNegoContext: getMIC = " +790SpNegoToken.getHexBytes(mic));791}792} catch (GSSException e) {793mic = null;794if (DEBUG) {795System.out.println("SpNegoContext: no MIC token included" +796" - getMIC failed : " + e.getMessage());797}798}799return mic;800}*/801802/**803* verify MIC on MechList804*/805private boolean verifyMechListMIC(byte[] mechTypes, byte[] token)806throws GSSException {807808// sanity check the input809if (token == null) {810if (DEBUG) {811System.out.println("SpNegoContext: no MIC token validation");812}813return true;814}815816// check if mechanism supports integrity817if (!mechContext.getIntegState()) {818if (DEBUG) {819System.out.println("SpNegoContext: no MIC token validation" +820" - mechanism does not support integrity");821}822return true;823}824825// now verify the token826boolean valid = false;827try {828MessageProp prop = new MessageProp(0, true);829verifyMIC(token, 0, token.length, mechTypes,8300, mechTypes.length, prop);831valid = true;832} catch (GSSException e) {833valid = false;834if (DEBUG) {835System.out.println("SpNegoContext: MIC validation failed! " +836e.getMessage());837}838}839return valid;840}841842/**843* call gss_init_sec_context for the corresponding underlying mechanism844*/845private byte[] GSS_initSecContext(byte[] token) throws GSSException {846byte[] tok = null;847848if (mechContext == null) {849// initialize mech context850GSSName serverName =851factory.manager.createName(peerName.toString(),852peerName.getStringNameType(), internal_mech);853GSSCredential cred = null;854if (myCred != null) {855// create context with provided credential856cred = new GSSCredentialImpl(factory.manager,857myCred.getInternalCred());858}859mechContext =860factory.manager.createContext(serverName,861internal_mech, cred, GSSContext.DEFAULT_LIFETIME);862mechContext.requestConf(confState);863mechContext.requestInteg(integState);864mechContext.requestCredDeleg(credDelegState);865mechContext.requestMutualAuth(mutualAuthState);866mechContext.requestReplayDet(replayDetState);867mechContext.requestSequenceDet(sequenceDetState);868mechContext.setChannelBinding(channelBinding);869if (mechContext instanceof GSSContextImpl) {870((GSSContextImpl)mechContext).requestDelegPolicy(871delegPolicyState);872}873}874875// pass token876if (token != null) {877tok = token;878} else {879tok = new byte[0];880}881882// pass token to mechanism initSecContext883byte[] init_token = mechContext.initSecContext(tok, 0, tok.length);884885return init_token;886}887888/**889* call gss_accept_sec_context for the corresponding underlying mechanism890*/891private byte[] GSS_acceptSecContext(byte[] token) throws GSSException {892893if (mechContext == null) {894// initialize mech context895GSSCredential cred = null;896if (myCred != null) {897// create context with provided credential898cred = new GSSCredentialImpl(factory.manager,899myCred.getInternalCred());900}901mechContext = factory.manager.createContext(cred);902mechContext.setChannelBinding(channelBinding);903}904905// pass token to mechanism acceptSecContext906byte[] accept_token =907mechContext.acceptSecContext(token, 0, token.length);908909return accept_token;910}911912/**913* This routine compares the received mechset to the mechset that914* this server can support. It looks sequentially through the mechset915* and the first one that matches what the server can support is916* chosen as the negotiated mechanism. If one is found, negResult917* is set to ACCEPT_COMPLETE, otherwise we return NULL and negResult918* is set to REJECT.919*/920private static Oid negotiate_mech_type(Oid[] supported_mechSet,921Oid[] mechSet) {922for (int i = 0; i < supported_mechSet.length; i++) {923for (int j = 0; j < mechSet.length; j++) {924if (mechSet[j].equals(supported_mechSet[i])) {925if (DEBUG) {926System.out.println("SpNegoContext: " +927"negotiated mechanism = " + mechSet[j]);928}929return (mechSet[j]);930}931}932}933return null;934}935936public final boolean isEstablished() {937return (state == STATE_DONE);938}939940public final boolean isMechContextEstablished() {941if (mechContext != null) {942return mechContext.isEstablished();943} else {944if (DEBUG) {945System.out.println("The underlying mechanism context has " +946"not been initialized");947}948return false;949}950}951952public final byte [] export() throws GSSException {953throw new GSSException(GSSException.UNAVAILABLE, -1,954"GSS Export Context not available");955}956957/**958* Sets the channel bindings to be used during context959* establishment.960*/961public final void setChannelBinding(ChannelBinding channelBinding)962throws GSSException {963this.channelBinding = channelBinding;964}965966final ChannelBinding getChannelBinding() {967return channelBinding;968}969970/*971* Anonymity is a little different in that after an application972* requests anonymity it will want to know whether the mechanism973* can support it or not, prior to sending any tokens across for974* context establishment. Since this is from the initiator's975* perspective, it essentially requests that the initiator be976* anonymous.977*/978public final void requestAnonymity(boolean value) throws GSSException {979// Ignore silently. Application will check back with980// getAnonymityState.981}982983// RFC 2853 actually calls for this to be called after context984// establishment to get the right answer, but that is985// incorrect. The application may not want to send over any986// tokens if anonymity is not available.987public final boolean getAnonymityState() {988return false;989}990991/**992* Requests the desired lifetime. Can only be used on the context993* initiator's side.994*/995public void requestLifetime(int lifetime) throws GSSException {996if (state == STATE_NEW && isInitiator())997this.lifetime = lifetime;998}9991000/**1001* The lifetime remaining for this context.1002*/1003public final int getLifetime() {1004if (mechContext != null) {1005return mechContext.getLifetime();1006} else {1007return GSSContext.INDEFINITE_LIFETIME;1008}1009}10101011public final boolean isTransferable() throws GSSException {1012return false;1013}10141015/**1016* Requests that sequence checking be done on the GSS wrap and MIC1017* tokens.1018*/1019public final void requestSequenceDet(boolean value) throws GSSException {1020if (state == STATE_NEW && isInitiator())1021sequenceDetState = value;1022}10231024/**1025* Is sequence checking enabled on the GSS Wrap and MIC tokens?1026* We enable sequence checking if replay detection is enabled.1027*/1028public final boolean getSequenceDetState() {1029return sequenceDetState || replayDetState;1030}10311032/**1033* Requests that replay detection be done on the GSS wrap and MIC1034* tokens.1035*/1036public final void requestReplayDet(boolean value) throws GSSException {1037if (state == STATE_NEW && isInitiator())1038replayDetState = value;1039}10401041/**1042* Is replay detection enabled on the GSS wrap and MIC tokens?1043* We enable replay detection if sequence checking is enabled.1044*/1045public final boolean getReplayDetState() {1046return replayDetState || sequenceDetState;1047}10481049public final GSSNameSpi getTargName() throws GSSException {1050// fill-in the GSSName1051// get the peer name for the mechanism1052if (mechContext != null) {1053GSSNameImpl targName = (GSSNameImpl)mechContext.getTargName();1054peerName = targName.getElement(internal_mech);1055return peerName;1056} else {1057if (DEBUG) {1058System.out.println("The underlying mechanism context has " +1059"not been initialized");1060}1061return null;1062}1063}10641065public final GSSNameSpi getSrcName() throws GSSException {1066// fill-in the GSSName1067// get the src name for the mechanism1068if (mechContext != null) {1069GSSNameImpl srcName = (GSSNameImpl)mechContext.getSrcName();1070myName = srcName.getElement(internal_mech);1071return myName;1072} else {1073if (DEBUG) {1074System.out.println("The underlying mechanism context has " +1075"not been initialized");1076}1077return null;1078}1079}10801081/**1082* Returns the delegated credential for the context. This1083* is an optional feature of contexts which not all1084* mechanisms will support. A context can be requested to1085* support credential delegation by using the <b>CRED_DELEG</b>.1086* This is only valid on the acceptor side of the context.1087* @return GSSCredentialSpi object for the delegated credential1088* @exception GSSException1089* @see GSSContext#getCredDelegState1090*/1091public final GSSCredentialSpi getDelegCred() throws GSSException {1092if (state != STATE_IN_PROCESS && state != STATE_DONE)1093throw new GSSException(GSSException.NO_CONTEXT);1094if (mechContext != null) {1095GSSCredentialImpl delegCred =1096(GSSCredentialImpl)mechContext.getDelegCred();1097if (delegCred == null) {1098return null;1099}1100// determine delegated cred element usage1101boolean initiate = false;1102if (delegCred.getUsage() == GSSCredential.INITIATE_ONLY) {1103initiate = true;1104}1105GSSCredentialSpi mechCred =1106delegCred.getElement(internal_mech, initiate);1107SpNegoCredElement cred = new SpNegoCredElement(mechCred);1108return cred.getInternalCred();1109} else {1110throw new GSSException(GSSException.NO_CONTEXT, -1,1111"getDelegCred called in invalid state!");1112}1113}11141115public final int getWrapSizeLimit(int qop, boolean confReq,1116int maxTokSize) throws GSSException {1117if (mechContext != null) {1118return mechContext.getWrapSizeLimit(qop, confReq, maxTokSize);1119} else {1120throw new GSSException(GSSException.NO_CONTEXT, -1,1121"getWrapSizeLimit called in invalid state!");1122}1123}11241125public final byte[] wrap(byte inBuf[], int offset, int len,1126MessageProp msgProp) throws GSSException {1127if (mechContext != null) {1128return mechContext.wrap(inBuf, offset, len, msgProp);1129} else {1130throw new GSSException(GSSException.NO_CONTEXT, -1,1131"Wrap called in invalid state!");1132}1133}11341135@Deprecated(since="11")1136public final void wrap(InputStream is, OutputStream os,1137MessageProp msgProp) throws GSSException {1138if (mechContext != null) {1139mechContext.wrap(is, os, msgProp);1140} else {1141throw new GSSException(GSSException.NO_CONTEXT, -1,1142"Wrap called in invalid state!");1143}1144}11451146public final byte[] unwrap(byte inBuf[], int offset, int len,1147MessageProp msgProp)1148throws GSSException {1149if (mechContext != null) {1150return mechContext.unwrap(inBuf, offset, len, msgProp);1151} else {1152throw new GSSException(GSSException.NO_CONTEXT, -1,1153"UnWrap called in invalid state!");1154}1155}11561157@Deprecated(since="11")1158public final void unwrap(InputStream is, OutputStream os,1159MessageProp msgProp) throws GSSException {1160if (mechContext != null) {1161mechContext.unwrap(is, os, msgProp);1162} else {1163throw new GSSException(GSSException.NO_CONTEXT, -1,1164"UnWrap called in invalid state!");1165}1166}11671168public final byte[] getMIC(byte []inMsg, int offset, int len,1169MessageProp msgProp)1170throws GSSException {1171if (mechContext != null) {1172return mechContext.getMIC(inMsg, offset, len, msgProp);1173} else {1174throw new GSSException(GSSException.NO_CONTEXT, -1,1175"getMIC called in invalid state!");1176}1177}11781179@Deprecated(since="11")1180public final void getMIC(InputStream is, OutputStream os,1181MessageProp msgProp) throws GSSException {1182if (mechContext != null) {1183mechContext.getMIC(is, os, msgProp);1184} else {1185throw new GSSException(GSSException.NO_CONTEXT, -1,1186"getMIC called in invalid state!");1187}1188}11891190public final void verifyMIC(byte []inTok, int tokOffset, int tokLen,1191byte[] inMsg, int msgOffset, int msgLen,1192MessageProp msgProp)1193throws GSSException {1194if (mechContext != null) {1195mechContext.verifyMIC(inTok, tokOffset, tokLen, inMsg, msgOffset,1196msgLen, msgProp);1197} else {1198throw new GSSException(GSSException.NO_CONTEXT, -1,1199"verifyMIC called in invalid state!");1200}1201}12021203@Deprecated(since="11")1204public final void verifyMIC(InputStream is, InputStream msgStr,1205MessageProp msgProp) throws GSSException {1206if (mechContext != null) {1207mechContext.verifyMIC(is, msgStr, msgProp);1208} else {1209throw new GSSException(GSSException.NO_CONTEXT, -1,1210"verifyMIC called in invalid state!");1211}1212}12131214private static String printState(int state) {1215switch (state) {1216case STATE_NEW:1217return ("STATE_NEW");1218case STATE_IN_PROCESS:1219return ("STATE_IN_PROCESS");1220case STATE_DONE:1221return ("STATE_DONE");1222case STATE_DELETED:1223return ("STATE_DELETED");1224default:1225return ("Unknown state " + state);1226}1227}12281229/**1230* Retrieve attribute of the context for {@code type}.1231*/1232public Object inquireSecContext(String type)1233throws GSSException {1234if (mechContext == null) {1235throw new GSSException(GSSException.NO_CONTEXT, -1,1236"Underlying mech not established.");1237}1238if (mechContext instanceof GSSContextImpl) {1239return ((GSSContextImpl)mechContext).inquireSecContext(type);1240} else {1241throw new GSSException(GSSException.BAD_MECH, -1,1242"inquireSecContext not supported by underlying mech.");1243}1244}1245}1246124712481249