Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java
38922 views
/*1* Copyright (c) 2003, 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 javax.security.auth.kerberos.KerberosTicket;28import javax.security.auth.kerberos.KerberosKey;29import javax.security.auth.kerberos.KerberosPrincipal;30import javax.security.auth.kerberos.KeyTab;31import javax.security.auth.Subject;32import javax.security.auth.login.LoginException;33import java.security.AccessControlContext;34import sun.security.jgss.GSSUtil;35import sun.security.jgss.GSSCaller;3637import sun.security.krb5.Credentials;38import sun.security.krb5.EncryptionKey;39import sun.security.krb5.KrbException;40import java.io.IOException;41import java.util.ArrayList;42import java.util.List;43import sun.security.krb5.KerberosSecrets;44import sun.security.krb5.PrincipalName;45/**46* Utilities for obtaining and converting Kerberos tickets.47*48*/49public class Krb5Util {5051static final boolean DEBUG =52java.security.AccessController.doPrivileged(53new sun.security.action.GetBooleanAction54("sun.security.krb5.debug")).booleanValue();5556/**57* Default constructor58*/59private Krb5Util() { // Cannot create one of these60}6162/**63* Retrieve the service ticket for serverPrincipal from caller's Subject64* or from Subject obtained by logging in, or if not found, via the65* Ticket Granting Service using the TGT obtained from the Subject.66*67* Caller must have permission to:68* - access and update Subject's private credentials69* - create LoginContext70* - read the auth.login.defaultCallbackHandler security property71*72* NOTE: This method is used by JSSE Kerberos Cipher Suites73*/74public static KerberosTicket getTicketFromSubjectAndTgs(GSSCaller caller,75String clientPrincipal, String serverPrincipal, String tgsPrincipal,76AccessControlContext acc)77throws LoginException, KrbException, IOException {7879// 1. Try to find service ticket in acc subject80Subject accSubj = Subject.getSubject(acc);81KerberosTicket ticket = SubjectComber.find(accSubj,82serverPrincipal, clientPrincipal, KerberosTicket.class);8384if (ticket != null) {85return ticket; // found it86}8788Subject loginSubj = null;89if (!GSSUtil.useSubjectCredsOnly(caller)) {90// 2. Try to get ticket from login91try {92loginSubj = GSSUtil.login(caller, GSSUtil.GSS_KRB5_MECH_OID);93ticket = SubjectComber.find(loginSubj,94serverPrincipal, clientPrincipal, KerberosTicket.class);95if (ticket != null) {96return ticket; // found it97}98} catch (LoginException e) {99// No login entry to use100// ignore and continue101}102}103104// Service ticket not found in subject or login105// Try to get TGT to acquire service ticket106107// 3. Try to get TGT from acc subject108KerberosTicket tgt = SubjectComber.find(accSubj,109tgsPrincipal, clientPrincipal, KerberosTicket.class);110111boolean fromAcc;112if (tgt == null && loginSubj != null) {113// 4. Try to get TGT from login subject114tgt = SubjectComber.find(loginSubj,115tgsPrincipal, clientPrincipal, KerberosTicket.class);116fromAcc = false;117} else {118fromAcc = true;119}120121// 5. Try to get service ticket using TGT122if (tgt != null) {123Credentials tgtCreds = ticketToCreds(tgt);124Credentials serviceCreds = Credentials.acquireServiceCreds(125serverPrincipal, tgtCreds);126if (serviceCreds != null) {127ticket = credsToTicket(serviceCreds);128129// Store service ticket in acc's Subject130if (fromAcc && accSubj != null && !accSubj.isReadOnly()) {131accSubj.getPrivateCredentials().add(ticket);132}133}134}135return ticket;136}137138/**139* Retrieves the ticket corresponding to the client/server principal140* pair from the Subject in the specified AccessControlContext.141*/142static KerberosTicket getServiceTicket(GSSCaller caller,143String clientPrincipal, String serverPrincipal,144AccessControlContext acc) throws LoginException {145146// Try to get ticket from acc's Subject147Subject accSubj = Subject.getSubject(acc);148KerberosTicket ticket =149SubjectComber.find(accSubj, serverPrincipal, clientPrincipal,150KerberosTicket.class);151152return ticket;153}154155/**156* Retrieves the initial TGT corresponding to the client principal157* from the Subject in the specified AccessControlContext.158* If the ticket can not be found in the Subject, and if159* useSubjectCredsOnly is false, then obtain ticket from160* a LoginContext.161*/162static KerberosTicket getInitialTicket(GSSCaller caller,163String clientPrincipal,164AccessControlContext acc) throws LoginException {165166// Try to get ticket from acc's Subject167Subject accSubj = Subject.getSubject(acc);168KerberosTicket ticket =169SubjectComber.find(accSubj, null, clientPrincipal,170KerberosTicket.class);171172// Try to get ticket from Subject obtained from GSSUtil173if (ticket == null && !GSSUtil.useSubjectCredsOnly(caller)) {174Subject subject = GSSUtil.login(caller, GSSUtil.GSS_KRB5_MECH_OID);175ticket = SubjectComber.find(subject,176null, clientPrincipal, KerberosTicket.class);177}178return ticket;179}180181/**182* Retrieves the caller's Subject, or Subject obtained by logging in183* via the specified caller.184*185* Caller must have permission to:186* - access the Subject187* - create LoginContext188* - read the auth.login.defaultCallbackHandler security property189*190* NOTE: This method is used by JSSE Kerberos Cipher Suites191*/192public static Subject getSubject(GSSCaller caller,193AccessControlContext acc) throws LoginException {194195// Try to get the Subject from acc196Subject subject = Subject.getSubject(acc);197198// Try to get Subject obtained from GSSUtil199if (subject == null && !GSSUtil.useSubjectCredsOnly(caller)) {200subject = GSSUtil.login(caller, GSSUtil.GSS_KRB5_MECH_OID);201}202return subject;203}204205/**206* Retrieves the ServiceCreds for the specified server principal from207* the Subject in the specified AccessControlContext. If not found, and if208* useSubjectCredsOnly is false, then obtain from a LoginContext.209*210* NOTE: This method is also used by JSSE Kerberos Cipher Suites211*/212public static ServiceCreds getServiceCreds(GSSCaller caller,213String serverPrincipal, AccessControlContext acc)214throws LoginException {215216Subject accSubj = Subject.getSubject(acc);217ServiceCreds sc = null;218if (accSubj != null) {219sc = ServiceCreds.getInstance(accSubj, serverPrincipal);220}221if (sc == null && !GSSUtil.useSubjectCredsOnly(caller)) {222Subject subject = GSSUtil.login(caller, GSSUtil.GSS_KRB5_MECH_OID);223sc = ServiceCreds.getInstance(subject, serverPrincipal);224}225return sc;226}227228public static KerberosTicket credsToTicket(Credentials serviceCreds) {229EncryptionKey sessionKey = serviceCreds.getSessionKey();230KerberosTicket kt = new KerberosTicket(231serviceCreds.getEncoded(),232new KerberosPrincipal(serviceCreds.getClient().getName()),233new KerberosPrincipal(serviceCreds.getServer().getName(),234KerberosPrincipal.KRB_NT_SRV_INST),235sessionKey.getBytes(),236sessionKey.getEType(),237serviceCreds.getFlags(),238serviceCreds.getAuthTime(),239serviceCreds.getStartTime(),240serviceCreds.getEndTime(),241serviceCreds.getRenewTill(),242serviceCreds.getClientAddresses());243PrincipalName clientAlias = serviceCreds.getClientAlias();244PrincipalName serverAlias = serviceCreds.getServerAlias();245if (clientAlias != null) {246KerberosSecrets.getJavaxSecurityAuthKerberosAccess()247.kerberosTicketSetClientAlias(kt, new KerberosPrincipal(248clientAlias.getName(), clientAlias.getNameType()));249}250if (serverAlias != null) {251KerberosSecrets.getJavaxSecurityAuthKerberosAccess()252.kerberosTicketSetServerAlias(kt, new KerberosPrincipal(253serverAlias.getName(), serverAlias.getNameType()));254}255return kt;256};257258public static Credentials ticketToCreds(KerberosTicket kerbTicket)259throws KrbException, IOException {260KerberosPrincipal clientAlias = KerberosSecrets261.getJavaxSecurityAuthKerberosAccess()262.kerberosTicketGetClientAlias(kerbTicket);263KerberosPrincipal serverAlias = KerberosSecrets264.getJavaxSecurityAuthKerberosAccess()265.kerberosTicketGetServerAlias(kerbTicket);266return new Credentials(267kerbTicket.getEncoded(),268kerbTicket.getClient().getName(),269(clientAlias != null ? clientAlias.getName() : null),270kerbTicket.getServer().getName(),271(serverAlias != null ? serverAlias.getName() : null),272kerbTicket.getSessionKey().getEncoded(),273kerbTicket.getSessionKeyType(),274kerbTicket.getFlags(),275kerbTicket.getAuthTime(),276kerbTicket.getStartTime(),277kerbTicket.getEndTime(),278kerbTicket.getRenewTill(),279kerbTicket.getClientAddresses());280}281282/**283* A helper method to get a sun..KeyTab from a javax..KeyTab284* @param ktab the javax..KeyTab object285* @return the sun..KeyTab object286*/287public static sun.security.krb5.internal.ktab.KeyTab288snapshotFromJavaxKeyTab(KeyTab ktab) {289return KerberosSecrets.getJavaxSecurityAuthKerberosAccess()290.keyTabTakeSnapshot(ktab);291}292293/**294* A helper method to get EncryptionKeys from a javax..KeyTab295* @param ktab the javax..KeyTab object296* @param cname the PrincipalName297* @return the EKeys, never null, might be empty298*/299public static EncryptionKey[] keysFromJavaxKeyTab(300KeyTab ktab, PrincipalName cname) {301return snapshotFromJavaxKeyTab(ktab).readServiceKeys(cname);302}303}304305306