Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/jgss/GSSContextImpl.java
38830 views
/*1* Copyright (c) 2000, 2009, 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;2627import org.ietf.jgss.*;28import sun.security.jgss.spi.*;29import sun.security.util.ObjectIdentifier;30import java.io.InputStream;31import java.io.OutputStream;32import java.io.ByteArrayInputStream;33import java.io.ByteArrayOutputStream;34import java.io.IOException;35import com.sun.security.jgss.*;3637/**38* This class represents the JGSS security context and its associated39* operations. JGSS security contexts are established between40* peers using locally established credentials. Multiple contexts41* may exist simultaneously between a pair of peers, using the same42* or different set of credentials. The JGSS is independent of43* the underlying transport protocols and depends on its callers to44* transport the tokens between peers.45* <p>46* The context object can be thought of as having 3 implicit states:47* before it is established, during its context establishment, and48* after a fully established context exists.49* <p>50* Before the context establishment phase is initiated, the context51* initiator may request specific characteristics desired of the52* established context. These can be set using the set methods. After the53* context is established, the caller can check the actual characteristic54* and services offered by the context using the query methods.55* <p>56* The context establishment phase begins with the first call to the57* initSecContext method by the context initiator. During this phase the58* initSecContext and acceptSecContext methods will produce GSS-API59* authentication tokens which the calling application needs to send to its60* peer. The initSecContext and acceptSecContext methods may61* return a CONTINUE_NEEDED code which indicates that a token is needed62* from its peer in order to continue the context establishment phase. A63* return code of COMPLETE signals that the local end of the context is64* established. This may still require that a token be sent to the peer,65* depending if one is produced by GSS-API. The isEstablished method can66* also be used to determine if the local end of the context has been67* fully established. During the context establishment phase, the68* isProtReady method may be called to determine if the context can be69* used for the per-message operations. This allows implementation to70* use per-message operations on contexts which aren't fully established.71* <p>72* After the context has been established or the isProtReady method73* returns "true", the query routines can be invoked to determine the actual74* characteristics and services of the established context. The75* application can also start using the per-message methods of wrap and76* getMIC to obtain cryptographic operations on application supplied data.77* <p>78* When the context is no longer needed, the application should call79* dispose to release any system resources the context may be using.80* <DL><DT><B>RFC 2078</b>81* <DD>This class corresponds to the context level calls together with82* the per message calls of RFC 2078. The gss_init_sec_context and83* gss_accept_sec_context calls have been made simpler by only taking84* required parameters. The context can have its properties set before85* the first call to initSecContext. The supplementary status codes for the86* per-message operations are returned in an instance of the MessageProp87* class, which is used as an argument in these calls.</dl>88*/89class GSSContextImpl implements ExtendedGSSContext {9091private final GSSManagerImpl gssManager;92private final boolean initiator;9394// private flags for the context state95private static final int PRE_INIT = 1;96private static final int IN_PROGRESS = 2;97private static final int READY = 3;98private static final int DELETED = 4;99100// instance variables101private int currentState = PRE_INIT;102103private GSSContextSpi mechCtxt = null;104private Oid mechOid = null;105private ObjectIdentifier objId = null;106107private GSSCredentialImpl myCred = null;108109private GSSNameImpl srcName = null;110private GSSNameImpl targName = null;111112private int reqLifetime = INDEFINITE_LIFETIME;113private ChannelBinding channelBindings = null;114115private boolean reqConfState = true;116private boolean reqIntegState = true;117private boolean reqMutualAuthState = true;118private boolean reqReplayDetState = true;119private boolean reqSequenceDetState = true;120private boolean reqCredDelegState = false;121private boolean reqAnonState = false;122private boolean reqDelegPolicyState = false;123124/**125* Creates a GSSContextImp on the context initiator's side.126*/127public GSSContextImpl(GSSManagerImpl gssManager, GSSName peer, Oid mech,128GSSCredential myCred, int lifetime)129throws GSSException {130if ((peer == null) || !(peer instanceof GSSNameImpl)) {131throw new GSSException(GSSException.BAD_NAME);132}133if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;134135this.gssManager = gssManager;136this.myCred = (GSSCredentialImpl) myCred; // XXX Check first137reqLifetime = lifetime;138targName = (GSSNameImpl)peer;139this.mechOid = mech;140initiator = true;141}142143/**144* Creates a GSSContextImpl on the context acceptor's side.145*/146public GSSContextImpl(GSSManagerImpl gssManager, GSSCredential myCred)147throws GSSException {148this.gssManager = gssManager;149this.myCred = (GSSCredentialImpl) myCred; // XXX Check first150initiator = false;151}152153/**154* Creates a GSSContextImpl out of a previously exported155* GSSContext.156*157* @see #isTransferable158*/159public GSSContextImpl(GSSManagerImpl gssManager, byte[] interProcessToken)160throws GSSException {161this.gssManager = gssManager;162mechCtxt = gssManager.getMechanismContext(interProcessToken);163initiator = mechCtxt.isInitiator();164this.mechOid = mechCtxt.getMech();165}166167public byte[] initSecContext(byte inputBuf[], int offset, int len)168throws GSSException {169/*170* Size of ByteArrayOutputStream will double each time that extra171* bytes are to be written. Usually, without delegation, a GSS172* initial token containing the Kerberos AP-REQ is between 400 and173* 600 bytes.174*/175ByteArrayOutputStream bos = new ByteArrayOutputStream(600);176ByteArrayInputStream bin =177new ByteArrayInputStream(inputBuf, offset, len);178int size = initSecContext(bin, bos);179return (size == 0? null : bos.toByteArray());180}181182public int initSecContext(InputStream inStream,183OutputStream outStream) throws GSSException {184185if (mechCtxt != null && currentState != IN_PROGRESS) {186throw new GSSExceptionImpl(GSSException.FAILURE,187"Illegal call to initSecContext");188}189190GSSHeader gssHeader = null;191int inTokenLen = -1;192GSSCredentialSpi credElement = null;193boolean firstToken = false;194195try {196if (mechCtxt == null) {197if (myCred != null) {198try {199credElement = myCred.getElement(mechOid, true);200} catch (GSSException ge) {201if (GSSUtil.isSpNegoMech(mechOid) &&202ge.getMajor() == GSSException.NO_CRED) {203credElement = myCred.getElement204(myCred.getMechs()[0], true);205} else {206throw ge;207}208}209}210GSSNameSpi nameElement = targName.getElement(mechOid);211mechCtxt = gssManager.getMechanismContext(nameElement,212credElement,213reqLifetime,214mechOid);215mechCtxt.requestConf(reqConfState);216mechCtxt.requestInteg(reqIntegState);217mechCtxt.requestCredDeleg(reqCredDelegState);218mechCtxt.requestMutualAuth(reqMutualAuthState);219mechCtxt.requestReplayDet(reqReplayDetState);220mechCtxt.requestSequenceDet(reqSequenceDetState);221mechCtxt.requestAnonymity(reqAnonState);222mechCtxt.setChannelBinding(channelBindings);223mechCtxt.requestDelegPolicy(reqDelegPolicyState);224225objId = new ObjectIdentifier(mechOid.toString());226227currentState = IN_PROGRESS;228firstToken = true;229} else {230if (mechCtxt.getProvider().getName().equals("SunNativeGSS") ||231GSSUtil.isSpNegoMech(mechOid)) {232// do not parse GSS header for native provider or SPNEGO233// mech234} else {235// parse GSS header236gssHeader = new GSSHeader(inStream);237if (!gssHeader.getOid().equals((Object) objId))238throw new GSSExceptionImpl239(GSSException.DEFECTIVE_TOKEN,240"Mechanism not equal to " +241mechOid.toString() +242" in initSecContext token");243inTokenLen = gssHeader.getMechTokenLength();244}245}246247byte[] obuf = mechCtxt.initSecContext(inStream, inTokenLen);248249int retVal = 0;250251if (obuf != null) {252retVal = obuf.length;253if (mechCtxt.getProvider().getName().equals("SunNativeGSS") ||254(!firstToken && GSSUtil.isSpNegoMech(mechOid))) {255// do not add GSS header for native provider or SPNEGO256// except for the first SPNEGO token257} else {258// add GSS header259gssHeader = new GSSHeader(objId, obuf.length);260retVal += gssHeader.encode(outStream);261}262outStream.write(obuf);263}264265if (mechCtxt.isEstablished())266currentState = READY;267268return retVal;269270} catch (IOException e) {271throw new GSSExceptionImpl(GSSException.DEFECTIVE_TOKEN,272e.getMessage());273}274}275276public byte[] acceptSecContext(byte inTok[], int offset, int len)277throws GSSException {278279/*280* Usually initial GSS token containing a Kerberos AP-REP is less281* than 100 bytes.282*/283ByteArrayOutputStream bos = new ByteArrayOutputStream(100);284acceptSecContext(new ByteArrayInputStream(inTok, offset, len),285bos);286byte[] out = bos.toByteArray();287return (out.length == 0) ? null : out;288}289290public void acceptSecContext(InputStream inStream,291OutputStream outStream) throws GSSException {292293if (mechCtxt != null && currentState != IN_PROGRESS) {294throw new GSSExceptionImpl(GSSException.FAILURE,295"Illegal call to acceptSecContext");296}297298GSSHeader gssHeader = null;299int inTokenLen = -1;300GSSCredentialSpi credElement = null;301302try {303if (mechCtxt == null) {304// mechOid will be null for an acceptor's context305gssHeader = new GSSHeader(inStream);306inTokenLen = gssHeader.getMechTokenLength();307308/*309* Convert ObjectIdentifier to Oid310*/311objId = gssHeader.getOid();312mechOid = new Oid(objId.toString());313// System.out.println("Entered GSSContextImpl.acceptSecContext"314// + " with mechanism = " + mechOid);315if (myCred != null) {316credElement = myCred.getElement(mechOid, false);317}318319mechCtxt = gssManager.getMechanismContext(credElement,320mechOid);321mechCtxt.setChannelBinding(channelBindings);322323currentState = IN_PROGRESS;324} else {325if (mechCtxt.getProvider().getName().equals("SunNativeGSS") ||326(GSSUtil.isSpNegoMech(mechOid))) {327// do not parse GSS header for native provider and SPNEGO328} else {329// parse GSS Header330gssHeader = new GSSHeader(inStream);331if (!gssHeader.getOid().equals((Object) objId))332throw new GSSExceptionImpl333(GSSException.DEFECTIVE_TOKEN,334"Mechanism not equal to " +335mechOid.toString() +336" in acceptSecContext token");337inTokenLen = gssHeader.getMechTokenLength();338}339}340341byte[] obuf = mechCtxt.acceptSecContext(inStream, inTokenLen);342343if (obuf != null) {344int retVal = obuf.length;345if (mechCtxt.getProvider().getName().equals("SunNativeGSS") ||346(GSSUtil.isSpNegoMech(mechOid))) {347// do not add GSS header for native provider and SPNEGO348} else {349// add GSS header350gssHeader = new GSSHeader(objId, obuf.length);351retVal += gssHeader.encode(outStream);352}353outStream.write(obuf);354}355356if (mechCtxt.isEstablished()) {357currentState = READY;358}359} catch (IOException e) {360throw new GSSExceptionImpl(GSSException.DEFECTIVE_TOKEN,361e.getMessage());362}363}364365public boolean isEstablished() {366if (mechCtxt == null)367return false;368else369return (currentState == READY);370}371372public int getWrapSizeLimit(int qop, boolean confReq,373int maxTokenSize) throws GSSException {374if (mechCtxt != null)375return mechCtxt.getWrapSizeLimit(qop, confReq, maxTokenSize);376else377throw new GSSExceptionImpl(GSSException.NO_CONTEXT,378"No mechanism context yet!");379}380381public byte[] wrap(byte inBuf[], int offset, int len,382MessageProp msgProp) throws GSSException {383if (mechCtxt != null)384return mechCtxt.wrap(inBuf, offset, len, msgProp);385else386throw new GSSExceptionImpl(GSSException.NO_CONTEXT,387"No mechanism context yet!");388}389390public void wrap(InputStream inStream, OutputStream outStream,391MessageProp msgProp) throws GSSException {392if (mechCtxt != null)393mechCtxt.wrap(inStream, outStream, msgProp);394else395throw new GSSExceptionImpl(GSSException.NO_CONTEXT,396"No mechanism context yet!");397}398399public byte [] unwrap(byte[] inBuf, int offset, int len,400MessageProp msgProp) throws GSSException {401if (mechCtxt != null)402return mechCtxt.unwrap(inBuf, offset, len, msgProp);403else404throw new GSSExceptionImpl(GSSException.NO_CONTEXT,405"No mechanism context yet!");406}407408public void unwrap(InputStream inStream, OutputStream outStream,409MessageProp msgProp) throws GSSException {410if (mechCtxt != null)411mechCtxt.unwrap(inStream, outStream, msgProp);412else413throw new GSSExceptionImpl(GSSException.NO_CONTEXT,414"No mechanism context yet!");415}416417public byte[] getMIC(byte []inMsg, int offset, int len,418MessageProp msgProp) throws GSSException {419if (mechCtxt != null)420return mechCtxt.getMIC(inMsg, offset, len, msgProp);421else422throw new GSSExceptionImpl(GSSException.NO_CONTEXT,423"No mechanism context yet!");424}425426public void getMIC(InputStream inStream, OutputStream outStream,427MessageProp msgProp) throws GSSException {428if (mechCtxt != null)429mechCtxt.getMIC(inStream, outStream, msgProp);430else431throw new GSSExceptionImpl(GSSException.NO_CONTEXT,432"No mechanism context yet!");433}434435public void verifyMIC(byte[] inTok, int tokOffset, int tokLen,436byte[] inMsg, int msgOffset, int msgLen,437MessageProp msgProp) throws GSSException {438if (mechCtxt != null)439mechCtxt.verifyMIC(inTok, tokOffset, tokLen,440inMsg, msgOffset, msgLen, msgProp);441else442throw new GSSExceptionImpl(GSSException.NO_CONTEXT,443"No mechanism context yet!");444}445446public void verifyMIC(InputStream tokStream, InputStream msgStream,447MessageProp msgProp) throws GSSException {448if (mechCtxt != null)449mechCtxt.verifyMIC(tokStream, msgStream, msgProp);450else451throw new GSSExceptionImpl(GSSException.NO_CONTEXT,452"No mechanism context yet!");453}454455public byte[] export() throws GSSException {456// Defaults to null to match old behavior457byte[] result = null;458// Only allow context export from native provider since JGSS459// still has not defined its own interprocess token format460if (mechCtxt.isTransferable() &&461mechCtxt.getProvider().getName().equals("SunNativeGSS")) {462result = mechCtxt.export();463}464return result;465}466467public void requestMutualAuth(boolean state) throws GSSException {468if (mechCtxt == null && initiator)469reqMutualAuthState = state;470}471472public void requestReplayDet(boolean state) throws GSSException {473if (mechCtxt == null && initiator)474reqReplayDetState = state;475}476477public void requestSequenceDet(boolean state) throws GSSException {478if (mechCtxt == null && initiator)479reqSequenceDetState = state;480}481482public void requestCredDeleg(boolean state) throws GSSException {483if (mechCtxt == null && initiator)484reqCredDelegState = state;485}486487public void requestAnonymity(boolean state) throws GSSException {488if (mechCtxt == null && initiator)489reqAnonState = state;490}491492public void requestConf(boolean state) throws GSSException {493if (mechCtxt == null && initiator)494reqConfState = state;495}496497public void requestInteg(boolean state) throws GSSException {498if (mechCtxt == null && initiator)499reqIntegState = state;500}501502public void requestLifetime(int lifetime) throws GSSException {503if (mechCtxt == null && initiator)504reqLifetime = lifetime;505}506507public void setChannelBinding(ChannelBinding channelBindings)508throws GSSException {509510if (mechCtxt == null)511this.channelBindings = channelBindings;512513}514515public boolean getCredDelegState() {516if (mechCtxt != null)517return mechCtxt.getCredDelegState();518else519return reqCredDelegState;520}521522public boolean getMutualAuthState() {523if (mechCtxt != null)524return mechCtxt.getMutualAuthState();525else526return reqMutualAuthState;527}528529public boolean getReplayDetState() {530if (mechCtxt != null)531return mechCtxt.getReplayDetState();532else533return reqReplayDetState;534}535536public boolean getSequenceDetState() {537if (mechCtxt != null)538return mechCtxt.getSequenceDetState();539else540return reqSequenceDetState;541}542543public boolean getAnonymityState() {544if (mechCtxt != null)545return mechCtxt.getAnonymityState();546else547return reqAnonState;548}549550public boolean isTransferable() throws GSSException {551if (mechCtxt != null)552return mechCtxt.isTransferable();553else554return false;555}556557public boolean isProtReady() {558if (mechCtxt != null)559return mechCtxt.isProtReady();560else561return false;562}563564public boolean getConfState() {565if (mechCtxt != null)566return mechCtxt.getConfState();567else568return reqConfState;569}570571public boolean getIntegState() {572if (mechCtxt != null)573return mechCtxt.getIntegState();574else575return reqIntegState;576}577578public int getLifetime() {579if (mechCtxt != null)580return mechCtxt.getLifetime();581else582return reqLifetime;583}584585public GSSName getSrcName() throws GSSException {586if (srcName == null) {587srcName = GSSNameImpl.wrapElement588(gssManager, mechCtxt.getSrcName());589}590return srcName;591}592593public GSSName getTargName() throws GSSException {594if (targName == null) {595targName = GSSNameImpl.wrapElement596(gssManager, mechCtxt.getTargName());597}598return targName;599}600601public Oid getMech() throws GSSException {602if (mechCtxt != null) {603return mechCtxt.getMech();604}605return mechOid;606}607608public GSSCredential getDelegCred() throws GSSException {609610if (mechCtxt == null)611throw new GSSExceptionImpl(GSSException.NO_CONTEXT,612"No mechanism context yet!");613GSSCredentialSpi delCredElement = mechCtxt.getDelegCred();614return (delCredElement == null ?615null : new GSSCredentialImpl(gssManager, delCredElement));616}617618public boolean isInitiator() throws GSSException {619return initiator;620}621622public void dispose() throws GSSException {623currentState = DELETED;624if (mechCtxt != null) {625mechCtxt.dispose();626mechCtxt = null;627}628myCred = null;629srcName = null;630targName = null;631}632633// ExtendedGSSContext methods:634635@Override636public Object inquireSecContext(InquireType type) throws GSSException {637SecurityManager security = System.getSecurityManager();638if (security != null) {639security.checkPermission(new InquireSecContextPermission(type.toString()));640}641if (mechCtxt == null) {642throw new GSSException(GSSException.NO_CONTEXT);643}644return mechCtxt.inquireSecContext(type);645}646647@Override648public void requestDelegPolicy(boolean state) throws GSSException {649if (mechCtxt == null && initiator)650reqDelegPolicyState = state;651}652653@Override654public boolean getDelegPolicyState() {655if (mechCtxt != null)656return mechCtxt.getDelegPolicyState();657else658return reqDelegPolicyState;659}660}661662663