Path: blob/master/src/java.security.jgss/share/classes/sun/security/jgss/krb5/SubjectComber.java
67766 views
/*1* Copyright (c) 2002, 2019, 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.krb5;2627import sun.security.krb5.JavaxSecurityAuthKerberosAccess;28import sun.security.krb5.KerberosSecrets;2930import javax.security.auth.kerberos.KerberosTicket;31import javax.security.auth.kerberos.KerberosKey;32import javax.security.auth.Subject;33import javax.security.auth.DestroyFailedException;34import java.util.Iterator;35import java.util.ArrayList;36import java.util.List;37import java.util.Set;38import javax.security.auth.kerberos.KerberosPrincipal;39import javax.security.auth.kerberos.KeyTab;4041/**42* This utility looks through the current Subject and retrieves private43* credentials for the desired client/server principals.44*45* @author Ram Marti46* @since 1.4.247*/4849class SubjectComber {5051private static final boolean DEBUG = Krb5Util.DEBUG;5253/**54* Default constructor55*/56private SubjectComber() { // Cannot create one of these57}5859static <T> T find(Subject subject, String serverPrincipal,60String clientPrincipal, Class<T> credClass) {6162// findAux returns T if oneOnly.63return credClass.cast(findAux(subject, serverPrincipal,64clientPrincipal, credClass, true));65}6667@SuppressWarnings("unchecked") // findAux returns List<T> if !oneOnly.68static <T> List<T> findMany(Subject subject, String serverPrincipal,69String clientPrincipal, Class<T> credClass) {7071return (List<T>)findAux(subject, serverPrincipal, clientPrincipal,72credClass, false);73}7475/**76* Find private credentials for the specified client/server principals77* in the subject. Returns null if the subject is null.78*79* @return the private credentials80*/81// Returns T if oneOnly and List<T> if !oneOnly.82private static <T> Object findAux(Subject subject, String serverPrincipal,83String clientPrincipal, Class<T> credClass, boolean oneOnly) {8485if (subject == null) {86return null;87} else {88List<T> answer = (oneOnly ? null : new ArrayList<T>());8990if (credClass == KeyTab.class) {91Iterator<KeyTab> iterator =92subject.getPrivateCredentials(KeyTab.class).iterator();93while (iterator.hasNext()) {94KeyTab t = iterator.next();95if (serverPrincipal != null && t.isBound()) {96KerberosPrincipal name = t.getPrincipal();97if (name != null) {98if (!serverPrincipal.equals(name.getName())) {99continue;100}101} else {102// legacy bound keytab. although we don't know who103// the bound principal is, it must be in allPrincs104boolean found = false;105for (KerberosPrincipal princ:106subject.getPrincipals(KerberosPrincipal.class)) {107if (princ.getName().equals(serverPrincipal)) {108found = true;109break;110}111}112if (!found) continue;113}114}115// Check passed, we can add now116if (DEBUG) {117System.out.println("Found " + credClass.getSimpleName()118+ " " + t);119}120if (oneOnly) {121return t;122} else {123answer.add(credClass.cast(t));124}125}126} else if (credClass == KerberosKey.class) {127// We are looking for credentials for the serverPrincipal128Iterator<KerberosKey> iterator =129subject.getPrivateCredentials(KerberosKey.class).iterator();130while (iterator.hasNext()) {131KerberosKey t = iterator.next();132String name = t.getPrincipal().getName();133if (serverPrincipal == null || serverPrincipal.equals(name)) {134if (DEBUG) {135System.out.println("Found " +136credClass.getSimpleName() + " for " + name);137}138if (oneOnly) {139return t;140} else {141answer.add(credClass.cast(t));142}143}144}145} else if (credClass == KerberosTicket.class) {146// we are looking for a KerberosTicket credentials147// for client-service principal pair148Set<Object> pcs = subject.getPrivateCredentials();149synchronized (pcs) {150Iterator<Object> iterator = pcs.iterator();151while (iterator.hasNext()) {152Object obj = iterator.next();153if (!(obj instanceof KerberosTicket)) {154continue;155}156@SuppressWarnings("unchecked")157KerberosTicket ticket = (KerberosTicket)obj;158if (DEBUG) {159System.out.println("Found ticket for "160+ ticket.getClient()161+ " to go to "162+ ticket.getServer()163+ " expiring on "164+ ticket.getEndTime());165}166if (!ticket.isCurrent()) {167// let us remove the ticket from the Subject168// Note that both TGT and service ticket will be169// removed upon expiration170if (!subject.isReadOnly()) {171iterator.remove();172try {173ticket.destroy();174if (DEBUG) {175System.out.println("Removed and destroyed "176+ "the expired Ticket \n"177+ ticket);178179}180} catch (DestroyFailedException dfe) {181if (DEBUG) {182System.out.println("Expired ticket not" +183" destroyed successfully. " + dfe);184}185}186}187continue;188}189String serverMatch = findServerMatch(serverPrincipal, ticket);190if (serverMatch != null) {191String clientMatch = findClientMatch(clientPrincipal, ticket);192if (clientMatch != null) {193if (oneOnly) {194return ticket;195} else {196// Record names so that tickets will197// all belong to same principals198if (clientPrincipal == null) {199clientPrincipal = clientMatch;200}201if (serverPrincipal == null) {202serverPrincipal = serverMatch;203}204answer.add(credClass.cast(ticket));205}206}207}208}209}210}211return answer;212}213}214215private static String findServerMatch(String input, KerberosTicket ticket) {216KerberosPrincipal serverAlias = KerberosSecrets217.getJavaxSecurityAuthKerberosAccess()218.kerberosTicketGetServerAlias(ticket);219if (input != null) {220return ((serverAlias != null && input.equals(serverAlias.getName())) ||221input.equals(ticket.getServer().getName()))222? input : null;223} else {224return serverAlias != null225? serverAlias.getName()226: ticket.getServer().getName();227}228}229230private static String findClientMatch(String input, KerberosTicket ticket) {231JavaxSecurityAuthKerberosAccess access = KerberosSecrets232.getJavaxSecurityAuthKerberosAccess();233KerberosPrincipal clientAlias = access.kerberosTicketGetClientAlias(ticket);234KerberosTicket proxy = access.kerberosTicketGetProxy(ticket);235if (input != null) {236return ((clientAlias != null && input.equals(clientAlias.getName())) ||237(proxy != null && input.equals(proxy.getClient().getName())) ||238(proxy == null && input.equals(ticket.getClient().getName())))239? input : null;240} else {241if (clientAlias != null) {242return clientAlias.getName();243} else if (proxy != null) {244return proxy.getClient().getName();245} else {246return ticket.getClient().getName();247}248}249}250}251252253