Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java
38923 views
/*1* Copyright (c) 2005, 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.wrapper;2627import org.ietf.jgss.*;28import java.security.Provider;29import sun.security.jgss.GSSHeader;30import sun.security.jgss.GSSUtil;31import sun.security.jgss.GSSExceptionImpl;32import sun.security.jgss.spi.*;33import sun.security.util.DerValue;34import sun.security.util.ObjectIdentifier;35import sun.security.jgss.spnego.NegTokenInit;36import sun.security.jgss.spnego.NegTokenTarg;37import javax.security.auth.kerberos.DelegationPermission;38import com.sun.security.jgss.InquireType;39import java.io.*;404142/**43* This class is essentially a wrapper class for the gss_ctx_id_t44* structure of the native GSS library.45* @author Valerie Peng46* @since 1.647*/48class NativeGSSContext implements GSSContextSpi {4950private static final int GSS_C_DELEG_FLAG = 1;51private static final int GSS_C_MUTUAL_FLAG = 2;52private static final int GSS_C_REPLAY_FLAG = 4;53private static final int GSS_C_SEQUENCE_FLAG = 8;54private static final int GSS_C_CONF_FLAG = 16;55private static final int GSS_C_INTEG_FLAG = 32;56private static final int GSS_C_ANON_FLAG = 64;57private static final int GSS_C_PROT_READY_FLAG = 128;58private static final int GSS_C_TRANS_FLAG = 256;5960private static final int NUM_OF_INQUIRE_VALUES = 6;6162private long pContext = 0; // Pointer to the gss_ctx_id_t structure63private GSSNameElement srcName;64private GSSNameElement targetName;65private GSSCredElement cred;66private boolean isInitiator;67private boolean isEstablished;68private Oid actualMech; // Assigned during context establishment6970private ChannelBinding cb;71private GSSCredElement delegatedCred;72private int flags;73private int lifetime = GSSCredential.DEFAULT_LIFETIME;74private final GSSLibStub cStub;7576private boolean skipDelegPermCheck;77private boolean skipServicePermCheck;7879// Retrieve the (preferred) mech out of SPNEGO tokens, i.e.80// NegTokenInit & NegTokenTarg81private static Oid getMechFromSpNegoToken(byte[] token,82boolean isInitiator)83throws GSSException {84Oid mech = null;85if (isInitiator) {86GSSHeader header = null;87try {88header = new GSSHeader(new ByteArrayInputStream(token));89} catch (IOException ioe) {90throw new GSSExceptionImpl(GSSException.FAILURE, ioe);91}92int negTokenLen = header.getMechTokenLength();93byte[] negToken = new byte[negTokenLen];94System.arraycopy(token, token.length-negTokenLen,95negToken, 0, negToken.length);9697NegTokenInit ntok = new NegTokenInit(negToken);98if (ntok.getMechToken() != null) {99Oid[] mechList = ntok.getMechTypeList();100mech = mechList[0];101}102} else {103NegTokenTarg ntok = new NegTokenTarg(token);104mech = ntok.getSupportedMech();105}106return mech;107}108109// Perform the Service permission check110private void doServicePermCheck() throws GSSException {111if (System.getSecurityManager() != null) {112String action = (isInitiator? "initiate" : "accept");113// Need to check Service permission for accessing114// initiator cred for SPNEGO during context establishment115if (GSSUtil.isSpNegoMech(cStub.getMech()) && isInitiator116&& !isEstablished) {117if (srcName == null) {118// Check by creating default initiator KRB5 cred119GSSCredElement tempCred =120new GSSCredElement(null, lifetime,121GSSCredential.INITIATE_ONLY,122GSSLibStub.getInstance(GSSUtil.GSS_KRB5_MECH_OID));123tempCred.dispose();124} else {125String tgsName = Krb5Util.getTGSName(srcName);126Krb5Util.checkServicePermission(tgsName, action);127}128}129String targetStr = targetName.getKrbName();130Krb5Util.checkServicePermission(targetStr, action);131skipServicePermCheck = true;132}133}134135// Perform the Delegation permission check136private void doDelegPermCheck() throws GSSException {137SecurityManager sm = System.getSecurityManager();138if (sm != null) {139String targetStr = targetName.getKrbName();140String tgsStr = Krb5Util.getTGSName(targetName);141StringBuffer buf = new StringBuffer("\"");142buf.append(targetStr).append("\" \"");143buf.append(tgsStr).append('\"');144String krbPrincPair = buf.toString();145SunNativeProvider.debug("Checking DelegationPermission (" +146krbPrincPair + ")");147DelegationPermission perm =148new DelegationPermission(krbPrincPair);149sm.checkPermission(perm);150skipDelegPermCheck = true;151}152}153154private byte[] retrieveToken(InputStream is, int mechTokenLen)155throws GSSException {156try {157byte[] result = null;158if (mechTokenLen != -1) {159// Need to add back the GSS header for a complete GSS token160SunNativeProvider.debug("Precomputed mechToken length: " +161mechTokenLen);162GSSHeader gssHeader = new GSSHeader163(new ObjectIdentifier(cStub.getMech().toString()),164mechTokenLen);165ByteArrayOutputStream baos = new ByteArrayOutputStream(600);166167byte[] mechToken = new byte[mechTokenLen];168int len = is.read(mechToken);169assert(mechTokenLen == len);170gssHeader.encode(baos);171baos.write(mechToken);172result = baos.toByteArray();173} else {174// Must be unparsed GSS token or SPNEGO's NegTokenTarg token175assert(mechTokenLen == -1);176DerValue dv = new DerValue(is);177result = dv.toByteArray();178}179SunNativeProvider.debug("Complete Token length: " +180result.length);181return result;182} catch (IOException ioe) {183throw new GSSExceptionImpl(GSSException.FAILURE, ioe);184}185}186187// Constructor for context initiator188NativeGSSContext(GSSNameElement peer, GSSCredElement myCred,189int time, GSSLibStub stub) throws GSSException {190if (peer == null) {191throw new GSSException(GSSException.FAILURE, 1, "null peer");192}193cStub = stub;194cred = myCred;195targetName = peer;196isInitiator = true;197lifetime = time;198199if (GSSUtil.isKerberosMech(cStub.getMech())) {200doServicePermCheck();201if (cred == null) {202cred = new GSSCredElement(null, lifetime,203GSSCredential.INITIATE_ONLY, cStub);204}205srcName = cred.getName();206}207}208209// Constructor for context acceptor210NativeGSSContext(GSSCredElement myCred, GSSLibStub stub)211throws GSSException {212cStub = stub;213cred = myCred;214215if (cred != null) targetName = cred.getName();216217isInitiator = false;218// Defer Service permission check for default acceptor cred219// to acceptSecContext()220if (GSSUtil.isKerberosMech(cStub.getMech()) && targetName != null) {221doServicePermCheck();222}223224// srcName and potentially targetName (when myCred is null)225// will be set in GSSLibStub.acceptContext(...)226}227228// Constructor for imported context229NativeGSSContext(long pCtxt, GSSLibStub stub) throws GSSException {230assert(pContext != 0);231pContext = pCtxt;232cStub = stub;233234// Set everything except cred, cb, delegatedCred235long[] info = cStub.inquireContext(pContext);236if (info.length != NUM_OF_INQUIRE_VALUES) {237throw new RuntimeException("Bug w/ GSSLibStub.inquireContext()");238}239srcName = new GSSNameElement(info[0], cStub);240targetName = new GSSNameElement(info[1], cStub);241isInitiator = (info[2] != 0);242isEstablished = (info[3] != 0);243flags = (int) info[4];244lifetime = (int) info[5];245246// Do Service Permission check when importing SPNEGO context247// just to be safe248Oid mech = cStub.getMech();249if (GSSUtil.isSpNegoMech(mech) || GSSUtil.isKerberosMech(mech)) {250doServicePermCheck();251}252}253254public Provider getProvider() {255return SunNativeProvider.INSTANCE;256}257258public byte[] initSecContext(InputStream is, int mechTokenLen)259throws GSSException {260byte[] outToken = null;261if ((!isEstablished) && (isInitiator)) {262byte[] inToken = null;263// Ignore the specified input stream on the first call264if (pContext != 0) {265inToken = retrieveToken(is, mechTokenLen);266SunNativeProvider.debug("initSecContext=> inToken len=" +267inToken.length);268}269270if (!getCredDelegState()) skipDelegPermCheck = true;271272if (GSSUtil.isKerberosMech(cStub.getMech()) && !skipDelegPermCheck) {273doDelegPermCheck();274}275276long pCred = (cred == null? 0 : cred.pCred);277outToken = cStub.initContext(pCred, targetName.pName,278cb, inToken, this);279SunNativeProvider.debug("initSecContext=> outToken len=" +280(outToken == null ? 0 : outToken.length));281282// Only inspect the token when the permission check283// has not been performed284if (GSSUtil.isSpNegoMech(cStub.getMech()) && outToken != null) {285// WORKAROUND for SEAM bug#6287358286actualMech = getMechFromSpNegoToken(outToken, true);287288if (GSSUtil.isKerberosMech(actualMech)) {289if (!skipServicePermCheck) doServicePermCheck();290if (!skipDelegPermCheck) doDelegPermCheck();291}292}293294if (isEstablished) {295if (srcName == null) {296srcName = new GSSNameElement297(cStub.getContextName(pContext, true), cStub);298}299if (cred == null) {300cred = new GSSCredElement(srcName, lifetime,301GSSCredential.INITIATE_ONLY,302cStub);303}304}305}306return outToken;307}308309public byte[] acceptSecContext(InputStream is, int mechTokenLen)310throws GSSException {311byte[] outToken = null;312if ((!isEstablished) && (!isInitiator)) {313byte[] inToken = retrieveToken(is, mechTokenLen);314SunNativeProvider.debug("acceptSecContext=> inToken len=" +315inToken.length);316long pCred = (cred == null? 0 : cred.pCred);317outToken = cStub.acceptContext(pCred, cb, inToken, this);318SunNativeProvider.debug("acceptSecContext=> outToken len=" +319(outToken == null? 0 : outToken.length));320321if (targetName == null) {322targetName = new GSSNameElement323(cStub.getContextName(pContext, false), cStub);324// Replace the current default acceptor cred now that325// the context acceptor name is available326if (cred != null) cred.dispose();327cred = new GSSCredElement(targetName, lifetime,328GSSCredential.ACCEPT_ONLY, cStub);329}330331// Only inspect token when the permission check has not332// been performed333if (GSSUtil.isSpNegoMech(cStub.getMech()) &&334(outToken != null) && !skipServicePermCheck) {335if (GSSUtil.isKerberosMech(getMechFromSpNegoToken336(outToken, false))) {337doServicePermCheck();338}339}340}341return outToken;342}343344public boolean isEstablished() {345return isEstablished;346}347348public void dispose() throws GSSException {349srcName = null;350targetName = null;351cred = null;352delegatedCred = null;353if (pContext != 0) {354pContext = cStub.deleteContext(pContext);355pContext = 0;356}357}358359public int getWrapSizeLimit(int qop, boolean confReq,360int maxTokenSize)361throws GSSException {362return cStub.wrapSizeLimit(pContext, (confReq? 1:0), qop,363maxTokenSize);364}365366public byte[] wrap(byte[] inBuf, int offset, int len,367MessageProp msgProp) throws GSSException {368byte[] data = inBuf;369if ((offset != 0) || (len != inBuf.length)) {370data = new byte[len];371System.arraycopy(inBuf, offset, data, 0, len);372}373return cStub.wrap(pContext, data, msgProp);374}375public void wrap(byte inBuf[], int offset, int len,376OutputStream os, MessageProp msgProp)377throws GSSException {378try {379byte[] result = wrap(inBuf, offset, len, msgProp);380os.write(result);381} catch (IOException ioe) {382throw new GSSExceptionImpl(GSSException.FAILURE, ioe);383}384}385public int wrap(byte[] inBuf, int inOffset, int len, byte[] outBuf,386int outOffset, MessageProp msgProp)387throws GSSException {388byte[] result = wrap(inBuf, inOffset, len, msgProp);389System.arraycopy(result, 0, outBuf, outOffset, result.length);390return result.length;391}392public void wrap(InputStream inStream, OutputStream outStream,393MessageProp msgProp) throws GSSException {394try {395byte[] data = new byte[inStream.available()];396int length = inStream.read(data);397byte[] token = wrap(data, 0, length, msgProp);398outStream.write(token);399} catch (IOException ioe) {400throw new GSSExceptionImpl(GSSException.FAILURE, ioe);401}402}403404public byte[] unwrap(byte[] inBuf, int offset, int len,405MessageProp msgProp)406throws GSSException {407if ((offset != 0) || (len != inBuf.length)) {408byte[] temp = new byte[len];409System.arraycopy(inBuf, offset, temp, 0, len);410return cStub.unwrap(pContext, temp, msgProp);411} else {412return cStub.unwrap(pContext, inBuf, msgProp);413}414}415public int unwrap(byte[] inBuf, int inOffset, int len,416byte[] outBuf, int outOffset,417MessageProp msgProp) throws GSSException {418byte[] result = null;419if ((inOffset != 0) || (len != inBuf.length)) {420byte[] temp = new byte[len];421System.arraycopy(inBuf, inOffset, temp, 0, len);422result = cStub.unwrap(pContext, temp, msgProp);423} else {424result = cStub.unwrap(pContext, inBuf, msgProp);425}426System.arraycopy(result, 0, outBuf, outOffset, result.length);427return result.length;428}429public void unwrap(InputStream inStream, OutputStream outStream,430MessageProp msgProp) throws GSSException {431try {432byte[] wrapped = new byte[inStream.available()];433int wLength = inStream.read(wrapped);434byte[] data = unwrap(wrapped, 0, wLength, msgProp);435outStream.write(data);436outStream.flush();437} catch (IOException ioe) {438throw new GSSExceptionImpl(GSSException.FAILURE, ioe);439}440}441442public int unwrap(InputStream inStream,443byte[] outBuf, int outOffset,444MessageProp msgProp) throws GSSException {445byte[] wrapped = null;446int wLength = 0;447try {448wrapped = new byte[inStream.available()];449wLength = inStream.read(wrapped);450byte[] result = unwrap(wrapped, 0, wLength, msgProp);451} catch (IOException ioe) {452throw new GSSExceptionImpl(GSSException.FAILURE, ioe);453}454byte[] result = unwrap(wrapped, 0, wLength, msgProp);455System.arraycopy(result, 0, outBuf, outOffset, result.length);456return result.length;457}458459public byte[] getMIC(byte[] in, int offset, int len,460MessageProp msgProp) throws GSSException {461int qop = (msgProp == null? 0:msgProp.getQOP());462byte[] inMsg = in;463if ((offset != 0) || (len != in.length)) {464inMsg = new byte[len];465System.arraycopy(in, offset, inMsg, 0, len);466}467return cStub.getMic(pContext, qop, inMsg);468}469470public void getMIC(InputStream inStream, OutputStream outStream,471MessageProp msgProp) throws GSSException {472try {473int length = 0;474byte[] msg = new byte[inStream.available()];475length = inStream.read(msg);476477byte[] msgToken = getMIC(msg, 0, length, msgProp);478if ((msgToken != null) && msgToken.length != 0) {479outStream.write(msgToken);480}481} catch (IOException ioe) {482throw new GSSExceptionImpl(GSSException.FAILURE, ioe);483}484}485486public void verifyMIC(byte[] inToken, int tOffset, int tLen,487byte[] inMsg, int mOffset, int mLen,488MessageProp msgProp) throws GSSException {489byte[] token = inToken;490byte[] msg = inMsg;491if ((tOffset != 0) || (tLen != inToken.length)) {492token = new byte[tLen];493System.arraycopy(inToken, tOffset, token, 0, tLen);494}495if ((mOffset != 0) || (mLen != inMsg.length)) {496msg = new byte[mLen];497System.arraycopy(inMsg, mOffset, msg, 0, mLen);498}499cStub.verifyMic(pContext, token, msg, msgProp);500}501502public void verifyMIC(InputStream tokStream, InputStream msgStream,503MessageProp msgProp) throws GSSException {504try {505byte[] msg = new byte[msgStream.available()];506int mLength = msgStream.read(msg);507byte[] tok = new byte[tokStream.available()];508int tLength = tokStream.read(tok);509verifyMIC(tok, 0, tLength, msg, 0, mLength, msgProp);510} catch (IOException ioe) {511throw new GSSExceptionImpl(GSSException.FAILURE, ioe);512}513}514515public byte[] export() throws GSSException {516byte[] result = cStub.exportContext(pContext);517pContext = 0;518return result;519}520521private void changeFlags(int flagMask, boolean isEnable) {522if (isInitiator && pContext == 0) {523if (isEnable) {524flags |= flagMask;525} else {526flags &= ~flagMask;527}528}529}530public void requestMutualAuth(boolean state) throws GSSException {531changeFlags(GSS_C_MUTUAL_FLAG, state);532}533public void requestReplayDet(boolean state) throws GSSException {534changeFlags(GSS_C_REPLAY_FLAG, state);535}536public void requestSequenceDet(boolean state) throws GSSException {537changeFlags(GSS_C_SEQUENCE_FLAG, state);538}539public void requestCredDeleg(boolean state) throws GSSException {540changeFlags(GSS_C_DELEG_FLAG, state);541}542public void requestAnonymity(boolean state) throws GSSException {543changeFlags(GSS_C_ANON_FLAG, state);544}545public void requestConf(boolean state) throws GSSException {546changeFlags(GSS_C_CONF_FLAG, state);547}548public void requestInteg(boolean state) throws GSSException {549changeFlags(GSS_C_INTEG_FLAG, state);550}551public void requestDelegPolicy(boolean state) throws GSSException {552// Not supported, ignore553}554public void requestLifetime(int lifetime) throws GSSException {555if (isInitiator && pContext == 0) {556this.lifetime = lifetime;557}558}559public void setChannelBinding(ChannelBinding cb) throws GSSException {560if (pContext == 0) {561this.cb = cb;562}563}564565private boolean checkFlags(int flagMask) {566return ((flags & flagMask) != 0);567}568public boolean getCredDelegState() {569return checkFlags(GSS_C_DELEG_FLAG);570}571public boolean getMutualAuthState() {572return checkFlags(GSS_C_MUTUAL_FLAG);573}574public boolean getReplayDetState() {575return checkFlags(GSS_C_REPLAY_FLAG);576}577public boolean getSequenceDetState() {578return checkFlags(GSS_C_SEQUENCE_FLAG);579}580public boolean getAnonymityState() {581return checkFlags(GSS_C_ANON_FLAG);582}583public boolean isTransferable() throws GSSException {584return checkFlags(GSS_C_TRANS_FLAG);585}586public boolean isProtReady() {587return checkFlags(GSS_C_PROT_READY_FLAG);588}589public boolean getConfState() {590return checkFlags(GSS_C_CONF_FLAG);591}592public boolean getIntegState() {593return checkFlags(GSS_C_INTEG_FLAG);594}595public boolean getDelegPolicyState() {596return false;597}598public int getLifetime() {599return cStub.getContextTime(pContext);600}601public GSSNameSpi getSrcName() throws GSSException {602return srcName;603}604public GSSNameSpi getTargName() throws GSSException {605return targetName;606}607public Oid getMech() throws GSSException {608if (isEstablished && actualMech != null) {609return actualMech;610} else {611return cStub.getMech();612}613}614public GSSCredentialSpi getDelegCred() throws GSSException {615return delegatedCred;616}617public boolean isInitiator() {618return isInitiator;619}620621protected void finalize() throws Throwable {622dispose();623}624625public Object inquireSecContext(InquireType type)626throws GSSException {627throw new GSSException(GSSException.UNAVAILABLE, -1,628"Inquire type not supported.");629}630}631632633