Path: blob/master/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java
41161 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.wrapper;2627import org.ietf.jgss.*;28import java.security.Provider;29import java.security.Security;30import java.io.IOException;31import sun.security.krb5.Realm;32import sun.security.jgss.GSSUtil;33import sun.security.util.ObjectIdentifier;34import sun.security.util.DerInputStream;35import sun.security.util.DerOutputStream;36import sun.security.jgss.GSSUtil;37import sun.security.jgss.GSSExceptionImpl;38import sun.security.jgss.spi.GSSNameSpi;3940import javax.security.auth.kerberos.ServicePermission;4142/**43* This class is essentially a wrapper class for the gss_name_t44* structure of the native GSS library.45* @author Valerie Peng46* @since 1.647*/4849public class GSSNameElement implements GSSNameSpi {5051long pName = 0; // Pointer to the gss_name_t structure52private String printableName;53private Oid printableType;54private GSSLibStub cStub;5556static final GSSNameElement DEF_ACCEPTOR = new GSSNameElement();5758private static Oid getNativeNameType(Oid nameType, GSSLibStub stub) {59if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType)) {60Oid[] supportedNTs = null;61try {62supportedNTs = stub.inquireNamesForMech();63} catch (GSSException ge) {64if (ge.getMajor() == GSSException.BAD_MECH &&65GSSUtil.isSpNegoMech(stub.getMech())) {66// Workaround known Heimdal issue and retry with KRB567try {68stub = GSSLibStub.getInstance69(GSSUtil.GSS_KRB5_MECH_OID);70supportedNTs = stub.inquireNamesForMech();71} catch (GSSException ge2) {72// Should never happen73SunNativeProvider.debug("Name type list unavailable: " +74ge2.getMajorString());75}76} else {77SunNativeProvider.debug("Name type list unavailable: " +78ge.getMajorString());79}80}81if (supportedNTs != null) {82for (int i = 0; i < supportedNTs.length; i++) {83if (supportedNTs[i].equals(nameType)) return nameType;84}85// Special handling the specified name type86SunNativeProvider.debug("Override " + nameType +87" with mechanism default(null)");88return null; // Use mechanism specific default89}90}91return nameType;92}9394private GSSNameElement() {95printableName = "<DEFAULT ACCEPTOR>";96}9798// Warning: called by NativeUtil.c99GSSNameElement(long pNativeName, GSSLibStub stub) throws GSSException {100assert(stub != null);101if (pNativeName == 0) {102throw new GSSException(GSSException.BAD_NAME);103}104// Note: pNativeName is assumed to be a MN.105pName = pNativeName;106cStub = stub;107setPrintables();108}109110GSSNameElement(byte[] nameBytes, Oid nameType, GSSLibStub stub)111throws GSSException {112assert(stub != null);113if (nameBytes == null) {114throw new GSSException(GSSException.BAD_NAME);115}116cStub = stub;117byte[] name = nameBytes;118119if (nameType != null) {120// Special handling the specified name type if121// necessary122nameType = getNativeNameType(nameType, stub);123124if (GSSName.NT_EXPORT_NAME.equals(nameType)) {125// Need to add back the mech Oid portion (stripped126// off by GSSNameImpl class prior to calling this127// method) for "NT_EXPORT_NAME"128byte[] mechBytes = null;129DerOutputStream dout = new DerOutputStream();130Oid mech = cStub.getMech();131try {132dout.putOID(ObjectIdentifier.of(mech.toString()));133} catch (IOException e) {134throw new GSSExceptionImpl(GSSException.FAILURE, e);135}136mechBytes = dout.toByteArray();137name = new byte[2 + 2 + mechBytes.length + 4 + nameBytes.length];138int pos = 0;139name[pos++] = 0x04;140name[pos++] = 0x01;141name[pos++] = (byte) (mechBytes.length>>>8);142name[pos++] = (byte) mechBytes.length;143System.arraycopy(mechBytes, 0, name, pos, mechBytes.length);144pos += mechBytes.length;145name[pos++] = (byte) (nameBytes.length>>>24);146name[pos++] = (byte) (nameBytes.length>>>16);147name[pos++] = (byte) (nameBytes.length>>>8);148name[pos++] = (byte) nameBytes.length;149System.arraycopy(nameBytes, 0, name, pos, nameBytes.length);150}151}152pName = cStub.importName(name, nameType);153setPrintables();154155@SuppressWarnings("removal")156SecurityManager sm = System.getSecurityManager();157if (sm != null && !Realm.AUTODEDUCEREALM) {158String krbName = getKrbName();159int atPos = krbName.lastIndexOf('@');160if (atPos != -1) {161String atRealm = krbName.substring(atPos);162// getNativeNameType() can modify NT_GSS_KRB5_PRINCIPAL to null163if ((nameType == null164|| nameType.equals(GSSUtil.NT_GSS_KRB5_PRINCIPAL))165&& new String(nameBytes).endsWith(atRealm)) {166// Created from Kerberos name with realm, no need to check167} else {168try {169sm.checkPermission(new ServicePermission(atRealm, "-"));170} catch (SecurityException se) {171// Do not chain the actual exception to hide info172throw new GSSException(GSSException.FAILURE);173}174}175}176}177178SunNativeProvider.debug("Imported " + printableName + " w/ type " +179printableType);180}181182private void setPrintables() throws GSSException {183Object[] printables = null;184printables = cStub.displayName(pName);185assert((printables != null) && (printables.length == 2));186printableName = (String) printables[0];187assert(printableName != null);188printableType = (Oid) printables[1];189if (printableType == null) {190printableType = GSSName.NT_USER_NAME;191}192}193194// Need to be public for GSSUtil.getSubject()195public String getKrbName() throws GSSException {196long mName = 0;197GSSLibStub stub = cStub;198if (!GSSUtil.isKerberosMech(cStub.getMech())) {199stub = GSSLibStub.getInstance(GSSUtil.GSS_KRB5_MECH_OID);200}201mName = stub.canonicalizeName(pName);202Object[] printables2 = stub.displayName(mName);203stub.releaseName(mName);204SunNativeProvider.debug("Got kerberized name: " + printables2[0]);205return (String) printables2[0];206}207208public Provider getProvider() {209return SunNativeProvider.INSTANCE;210}211212public boolean equals(GSSNameSpi other) throws GSSException {213if (!(other instanceof GSSNameElement)) {214return false;215}216return cStub.compareName(pName, ((GSSNameElement)other).pName);217}218219public boolean equals(Object other) {220if (!(other instanceof GSSNameElement)) {221return false;222}223try {224return equals((GSSNameElement) other);225} catch (GSSException ex) {226return false;227}228}229230public int hashCode() {231return Long.hashCode(pName);232}233234public byte[] export() throws GSSException {235byte[] nameVal = cStub.exportName(pName);236237// Need to strip off the mech Oid portion of the exported238// bytes since GSSNameImpl class will subsequently add it.239int pos = 0;240if ((nameVal[pos++] != 0x04) ||241(nameVal[pos++] != 0x01))242throw new GSSException(GSSException.BAD_NAME);243244int mechOidLen = (((0xFF & nameVal[pos++]) << 8) |245(0xFF & nameVal[pos++]));246ObjectIdentifier temp = null;247try {248DerInputStream din = new DerInputStream(nameVal, pos,249mechOidLen);250temp = new ObjectIdentifier(din);251} catch (IOException e) {252throw new GSSExceptionImpl(GSSException.BAD_NAME, e);253}254Oid mech2 = new Oid(temp.toString());255assert(mech2.equals(getMechanism()));256pos += mechOidLen;257int mechPortionLen = (((0xFF & nameVal[pos++]) << 24) |258((0xFF & nameVal[pos++]) << 16) |259((0xFF & nameVal[pos++]) << 8) |260(0xFF & nameVal[pos++]));261if (mechPortionLen < 0) {262throw new GSSException(GSSException.BAD_NAME);263}264byte[] mechPortion = new byte[mechPortionLen];265System.arraycopy(nameVal, pos, mechPortion, 0, mechPortionLen);266return mechPortion;267}268269public Oid getMechanism() {270return cStub.getMech();271}272273public String toString() {274return printableName;275}276277public Oid getStringNameType() {278return printableType;279}280281public boolean isAnonymousName() {282return (GSSName.NT_ANONYMOUS.equals(printableType));283}284285public void dispose() {286if (pName != 0) {287cStub.releaseName(pName);288pName = 0;289}290}291292@SuppressWarnings("deprecation")293protected void finalize() throws Throwable {294dispose();295}296}297298299