Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/jgss/GSSUtil.java
38830 views
/*1* Copyright (c) 2000, 2017, 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 com.sun.security.auth.callback.TextCallbackHandler;28import javax.security.auth.Subject;29import javax.security.auth.kerberos.KerberosPrincipal;30import javax.security.auth.kerberos.KerberosTicket;31import javax.security.auth.kerberos.KerberosKey;32import org.ietf.jgss.*;33import sun.security.jgss.spi.GSSNameSpi;34import sun.security.jgss.spi.GSSCredentialSpi;35import sun.security.action.GetPropertyAction;36import sun.security.jgss.krb5.Krb5NameElement;37import sun.security.jgss.spnego.SpNegoCredElement;38import java.util.Set;39import java.util.HashSet;40import java.util.Vector;41import java.util.Iterator;42import java.security.AccessController;43import java.security.AccessControlContext;44import java.security.PrivilegedExceptionAction;45import java.security.PrivilegedActionException;46import javax.security.auth.callback.CallbackHandler;47import javax.security.auth.login.LoginContext;48import javax.security.auth.login.LoginException;49import sun.security.action.GetBooleanAction;5051/**52* The GSSUtilImplementation that knows how to work with the internals of53* the GSS-API.54*/55public class GSSUtil {5657public static final Oid GSS_KRB5_MECH_OID =58GSSUtil.createOid("1.2.840.113554.1.2.2");59public static final Oid GSS_KRB5_MECH_OID2 =60GSSUtil.createOid("1.3.5.1.5.2");61public static final Oid GSS_KRB5_MECH_OID_MS =62GSSUtil.createOid("1.2.840.48018.1.2.2");6364public static final Oid GSS_SPNEGO_MECH_OID =65GSSUtil.createOid("1.3.6.1.5.5.2");6667public static final Oid NT_GSS_KRB5_PRINCIPAL =68GSSUtil.createOid("1.2.840.113554.1.2.2.1");6970private static final String DEFAULT_HANDLER =71"auth.login.defaultCallbackHandler";7273static final boolean DEBUG;74static {75DEBUG = (AccessController.doPrivileged76(new GetBooleanAction("sun.security.jgss.debug"))).77booleanValue();78}7980static void debug(String message) {81if (DEBUG) {82assert(message != null);83System.out.println(message);84}85}8687// NOTE: this method is only for creating Oid objects with88// known to be valid <code>oidStr</code> given it ignores89// the GSSException90public static Oid createOid(String oidStr) {91try {92return new Oid(oidStr);93} catch (GSSException e) {94debug("Ignored invalid OID: " + oidStr);95return null;96}97}9899public static boolean isSpNegoMech(Oid oid) {100return (GSS_SPNEGO_MECH_OID.equals(oid));101}102103public static boolean isKerberosMech(Oid oid) {104return (GSS_KRB5_MECH_OID.equals(oid) ||105GSS_KRB5_MECH_OID2.equals(oid) ||106GSS_KRB5_MECH_OID_MS.equals(oid));107108}109110public static String getMechStr(Oid oid) {111if (isSpNegoMech(oid)) {112return "SPNEGO";113} else if (isKerberosMech(oid)) {114return "Kerberos V5";115} else {116return oid.toString();117}118}119120/**121* Note: The current impl only works with Sun's impl of122* GSSName and GSSCredential since it depends on package123* private APIs.124*/125public static Subject getSubject(GSSName name,126GSSCredential creds) {127128HashSet<Object> privCredentials = null;129HashSet<Object> pubCredentials = new HashSet<Object>(); // empty Set130131Set<GSSCredentialSpi> gssCredentials = null;132133Set<KerberosPrincipal> krb5Principals =134new HashSet<KerberosPrincipal>();135136if (name instanceof GSSNameImpl) {137try {138GSSNameSpi ne = ((GSSNameImpl) name).getElement139(GSS_KRB5_MECH_OID);140String krbName = ne.toString();141if (ne instanceof Krb5NameElement) {142krbName =143((Krb5NameElement) ne).getKrb5PrincipalName().getName();144}145KerberosPrincipal krbPrinc = new KerberosPrincipal(krbName);146krb5Principals.add(krbPrinc);147} catch (GSSException ge) {148debug("Skipped name " + name + " due to " + ge);149}150}151152if (creds instanceof GSSCredentialImpl) {153gssCredentials = ((GSSCredentialImpl) creds).getElements();154privCredentials = new HashSet<Object>(gssCredentials.size());155populateCredentials(privCredentials, gssCredentials);156} else {157privCredentials = new HashSet<Object>(); // empty Set158}159debug("Created Subject with the following");160debug("principals=" + krb5Principals);161debug("public creds=" + pubCredentials);162debug("private creds=" + privCredentials);163164return new Subject(false, krb5Principals, pubCredentials,165privCredentials);166167}168169/**170* Populates the set credentials with elements from gssCredentials. At171* the same time, it converts any subclasses of KerberosTicket172* into KerberosTicket instances and any subclasses of KerberosKey into173* KerberosKey instances. (It is not desirable to expose the customer174* to sun.security.jgss.krb5.Krb5InitCredential which extends175* KerberosTicket and sun.security.jgss.krb5.Kbr5AcceptCredential which176* extends KerberosKey.)177*/178private static void populateCredentials(Set<Object> credentials,179Set<?> gssCredentials) {180181Object cred;182183Iterator<?> elements = gssCredentials.iterator();184while (elements.hasNext()) {185186cred = elements.next();187188// Retrieve the internal cred out of SpNegoCredElement189if (cred instanceof SpNegoCredElement) {190cred = ((SpNegoCredElement) cred).getInternalCred();191}192193if (cred instanceof KerberosTicket) {194if (!cred.getClass().getName().equals195("javax.security.auth.kerberos.KerberosTicket")) {196KerberosTicket tempTkt = (KerberosTicket) cred;197cred = new KerberosTicket(tempTkt.getEncoded(),198tempTkt.getClient(),199tempTkt.getServer(),200tempTkt.getSessionKey().getEncoded(),201tempTkt.getSessionKeyType(),202tempTkt.getFlags(),203tempTkt.getAuthTime(),204tempTkt.getStartTime(),205tempTkt.getEndTime(),206tempTkt.getRenewTill(),207tempTkt.getClientAddresses());208}209credentials.add(cred);210} else if (cred instanceof KerberosKey) {211if (!cred.getClass().getName().equals212("javax.security.auth.kerberos.KerberosKey")) {213KerberosKey tempKey = (KerberosKey) cred;214cred = new KerberosKey(tempKey.getPrincipal(),215tempKey.getEncoded(),216tempKey.getKeyType(),217tempKey.getVersionNumber());218}219credentials.add(cred);220} else {221// Ignore non-KerberosTicket and non-KerberosKey elements222debug("Skipped cred element: " + cred);223}224}225}226227/**228* Authenticate using the login module from the specified229* configuration entry.230*231* @param caller the caller of JAAS Login232* @param mech the mech to be used233* @return the authenticated subject234*/235public static Subject login(GSSCaller caller, Oid mech) throws LoginException {236237CallbackHandler cb = null;238if (caller instanceof HttpCaller) {239cb = new sun.net.www.protocol.http.spnego.NegotiateCallbackHandler(240((HttpCaller)caller).info());241} else {242String defaultHandler =243java.security.Security.getProperty(DEFAULT_HANDLER);244// get the default callback handler245if ((defaultHandler != null) && (defaultHandler.length() != 0)) {246cb = null;247} else {248cb = new TextCallbackHandler();249}250}251252// New instance of LoginConfigImpl must be created for each login,253// since the entry name is not passed as the first argument, but254// generated with caller and mech inside LoginConfigImpl255LoginContext lc = new LoginContext("", null, cb,256new LoginConfigImpl(caller, mech));257lc.login();258return lc.getSubject();259}260261/**262* Determines if the application doesn't mind if the mechanism obtains263* the required credentials from outside of the current Subject. Our264* Kerberos v5 mechanism would do a JAAS login on behalf of the265* application if this were the case.266*267* The application indicates this by explicitly setting the system268* property javax.security.auth.useSubjectCredsOnly to false.269*/270public static boolean useSubjectCredsOnly(GSSCaller caller) {271272String propValue = GetPropertyAction.privilegedGetProperty(273"javax.security.auth.useSubjectCredsOnly");274275// Invalid values should be ignored and the default assumed.276if (caller instanceof HttpCaller) {277// Default for HTTP/SPNEGO is false.278return "true".equalsIgnoreCase(propValue);279} else {280// Default for JGSS is true.281return !("false".equalsIgnoreCase(propValue));282}283}284285/**286* Determines the SPNEGO interoperability mode with Microsoft;287* by default it is set to true.288*289* To disable it, the application indicates this by explicitly setting290* the system property sun.security.spnego.interop to false.291*/292public static boolean useMSInterop() {293/*294* Don't use GetBooleanAction because the default value in the JRE295* (when this is unset) has to treated as true.296*/297String propValue = AccessController.doPrivileged(298new GetPropertyAction("sun.security.spnego.msinterop",299"true"));300/*301* This property has to be explicitly set to "false". Invalid302* values should be ignored and the default "true" assumed.303*/304return (!propValue.equalsIgnoreCase("false"));305}306307/**308* Searches the private credentials of current Subject with the309* specified criteria and returns the matching GSSCredentialSpi310* object out of Sun's impl of GSSCredential. Returns null if311* no Subject present or a Vector which contains 0 or more312* matching GSSCredentialSpi objects.313*/314public static <T extends GSSCredentialSpi> Vector<T>315searchSubject(final GSSNameSpi name,316final Oid mech,317final boolean initiate,318final Class<? extends T> credCls) {319debug("Search Subject for " + getMechStr(mech) +320(initiate? " INIT" : " ACCEPT") + " cred (" +321(name == null? "<<DEF>>" : name.toString()) + ", " +322credCls.getName() + ")");323final AccessControlContext acc = AccessController.getContext();324try {325Vector<T> creds =326AccessController.doPrivileged327(new PrivilegedExceptionAction<Vector<T>>() {328public Vector<T> run() throws Exception {329Subject accSubj = Subject.getSubject(acc);330Vector<T> result = null;331if (accSubj != null) {332result = new Vector<T>();333Iterator<GSSCredentialImpl> iterator =334accSubj.getPrivateCredentials335(GSSCredentialImpl.class).iterator();336while (iterator.hasNext()) {337GSSCredentialImpl cred = iterator.next();338debug("...Found cred" + cred);339try {340GSSCredentialSpi ce =341cred.getElement(mech, initiate);342debug("......Found element: " + ce);343if (ce.getClass().equals(credCls) &&344(name == null ||345name.equals((Object) ce.getName()))) {346result.add(credCls.cast(ce));347} else {348debug("......Discard element");349}350} catch (GSSException ge) {351debug("...Discard cred (" + ge + ")");352}353}354} else debug("No Subject");355return result;356}357});358return creds;359} catch (PrivilegedActionException pae) {360debug("Unexpected exception when searching Subject:");361if (DEBUG) pae.printStackTrace();362return null;363}364}365}366367368