Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/krb5/Credentials.java
38830 views
/*1* Copyright (c) 2000, 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*/2425/*26*27* (C) Copyright IBM Corp. 1999 All Rights Reserved.28* Copyright 1997 The Open Group Research Institute. All rights reserved.29*/3031package sun.security.krb5;3233import sun.security.krb5.internal.*;34import sun.security.krb5.internal.ccache.CredentialsCache;35import sun.security.krb5.internal.crypto.EType;36import java.io.IOException;37import java.util.Date;38import java.util.Locale;39import java.net.InetAddress;4041/**42* This class encapsulates the concept of a Kerberos service43* credential. That includes a Kerberos ticket and an associated44* session key.45*/46public class Credentials {4748Ticket ticket;49PrincipalName client;50PrincipalName clientAlias;51PrincipalName server;52PrincipalName serverAlias;53EncryptionKey key;54TicketFlags flags;55KerberosTime authTime;56KerberosTime startTime;57KerberosTime endTime;58KerberosTime renewTill;59HostAddresses cAddr;60AuthorizationData authzData;61private static boolean DEBUG = Krb5.DEBUG;62private static CredentialsCache cache;63static boolean alreadyLoaded = false;64private static boolean alreadyTried = false;6566private Credentials proxy = null;6768public Credentials getProxy() {69return proxy;70}7172public Credentials setProxy(Credentials proxy) {73this.proxy = proxy;74return this;75}7677// Read native ticket with session key type in the given list78private static native Credentials acquireDefaultNativeCreds(int[] eTypes);7980public Credentials(Ticket new_ticket,81PrincipalName new_client,82PrincipalName new_client_alias,83PrincipalName new_server,84PrincipalName new_server_alias,85EncryptionKey new_key,86TicketFlags new_flags,87KerberosTime authTime,88KerberosTime new_startTime,89KerberosTime new_endTime,90KerberosTime renewTill,91HostAddresses cAddr,92AuthorizationData authzData) {93this(new_ticket, new_client, new_client_alias, new_server,94new_server_alias, new_key, new_flags, authTime,95new_startTime, new_endTime, renewTill, cAddr);96this.authzData = authzData;97}9899public Credentials(Ticket new_ticket,100PrincipalName new_client,101PrincipalName new_client_alias,102PrincipalName new_server,103PrincipalName new_server_alias,104EncryptionKey new_key,105TicketFlags new_flags,106KerberosTime authTime,107KerberosTime new_startTime,108KerberosTime new_endTime,109KerberosTime renewTill,110HostAddresses cAddr) {111ticket = new_ticket;112client = new_client;113clientAlias = new_client_alias;114server = new_server;115serverAlias = new_server_alias;116key = new_key;117flags = new_flags;118this.authTime = authTime;119startTime = new_startTime;120endTime = new_endTime;121this.renewTill = renewTill;122this.cAddr = cAddr;123}124125public Credentials(byte[] encoding,126String client,127String clientAlias,128String server,129String serverAlias,130byte[] keyBytes,131int keyType,132boolean[] flags,133Date authTime,134Date startTime,135Date endTime,136Date renewTill,137InetAddress[] cAddrs) throws KrbException, IOException {138this(new Ticket(encoding),139new PrincipalName(client, PrincipalName.KRB_NT_PRINCIPAL),140(clientAlias == null? null : new PrincipalName(clientAlias,141PrincipalName.KRB_NT_PRINCIPAL)),142new PrincipalName(server, PrincipalName.KRB_NT_SRV_INST),143(serverAlias == null? null : new PrincipalName(serverAlias,144PrincipalName.KRB_NT_SRV_INST)),145new EncryptionKey(keyType, keyBytes),146(flags == null? null: new TicketFlags(flags)),147(authTime == null? null: new KerberosTime(authTime)),148(startTime == null? null: new KerberosTime(startTime)),149(endTime == null? null: new KerberosTime(endTime)),150(renewTill == null? null: new KerberosTime(renewTill)),151null); // caddrs are in the encoding at this point152}153154/**155* Acquires a service ticket for the specified service156* principal. If the service ticket is not already available, it157* obtains a new one from the KDC.158*/159/*160public Credentials(Credentials tgt, PrincipalName service)161throws KrbException {162}163*/164165public final PrincipalName getClient() {166return client;167}168169public final PrincipalName getClientAlias() {170return clientAlias;171}172173public final PrincipalName getServer() {174return server;175}176177public final PrincipalName getServerAlias() {178return serverAlias;179}180181public final EncryptionKey getSessionKey() {182return key;183}184185public final Date getAuthTime() {186if (authTime != null) {187return authTime.toDate();188} else {189return null;190}191}192193public final Date getStartTime() {194if (startTime != null)195{196return startTime.toDate();197}198return null;199}200201public final Date getEndTime() {202if (endTime != null)203{204return endTime.toDate();205}206return null;207}208209public final Date getRenewTill() {210if (renewTill != null)211{212return renewTill.toDate();213}214return null;215}216217public final boolean[] getFlags() {218if (flags == null) // Can be in a KRB-CRED219return null;220return flags.toBooleanArray();221}222223public final InetAddress[] getClientAddresses() {224225if (cAddr == null)226return null;227228return cAddr.getInetAddresses();229}230231public final byte[] getEncoded() {232byte[] retVal = null;233try {234retVal = ticket.asn1Encode();235} catch (Asn1Exception e) {236if (DEBUG)237System.out.println(e);238} catch (IOException ioe) {239if (DEBUG)240System.out.println(ioe);241}242return retVal;243}244245public boolean isForwardable() {246return flags.get(Krb5.TKT_OPTS_FORWARDABLE);247}248249public boolean isRenewable() {250return flags.get(Krb5.TKT_OPTS_RENEWABLE);251}252253public Ticket getTicket() {254return ticket;255}256257public TicketFlags getTicketFlags() {258return flags;259}260261public AuthorizationData getAuthzData() {262return authzData;263}264/**265* Checks if the service ticket returned by the KDC has the OK-AS-DELEGATE266* flag set267* @return true if OK-AS_DELEGATE flag is set, otherwise, return false.268*/269public boolean checkDelegate() {270return flags.get(Krb5.TKT_OPTS_DELEGATE);271}272273/**274* Reset TKT_OPTS_DELEGATE to false, called at credentials acquirement275* when one of the cross-realm TGTs does not have the OK-AS-DELEGATE276* flag set. This info must be preservable and restorable through277* the Krb5Util.credsToTicket/ticketToCreds() methods so that even if278* the service ticket is cached it still remembers the cross-realm279* authentication result.280*/281public void resetDelegate() {282flags.set(Krb5.TKT_OPTS_DELEGATE, false);283}284285public Credentials renew() throws KrbException, IOException {286KDCOptions options = new KDCOptions();287options.set(KDCOptions.RENEW, true);288/*289* Added here to pass KrbKdcRep.check:73290*/291options.set(KDCOptions.RENEWABLE, true);292293return new KrbTgsReq(options,294this,295server,296serverAlias,297null, // from298null, // till299null, // rtime300null, // eTypes301cAddr,302null,303null,304null).sendAndGetCreds();305}306307/**308* Returns a TGT for the given client principal from a ticket cache.309*310* @param princ the client principal. A value of null means that the311* default principal name in the credentials cache will be used.312* @param ticketCache the path to the tickets file. A value313* of null will be accepted to indicate that the default314* path should be searched315* @return the TGT credentials or null if none were found. If the tgt316* expired, it is the responsibility of the caller to determine this.317*/318public static Credentials acquireTGTFromCache(PrincipalName princ,319String ticketCache)320throws KrbException, IOException {321322if (ticketCache == null) {323// The default ticket cache on Windows and Mac is not a file.324String os = java.security.AccessController.doPrivileged(325new sun.security.action.GetPropertyAction("os.name"));326if (os.toUpperCase(Locale.ENGLISH).startsWith("WINDOWS") ||327os.toUpperCase(Locale.ENGLISH).contains("OS X")) {328Credentials creds = acquireDefaultCreds();329if (creds == null) {330if (DEBUG) {331System.out.println(">>> Found no TGT's in LSA");332}333return null;334}335if (princ != null) {336if (creds.getClient().equals(princ)) {337if (DEBUG) {338System.out.println(">>> Obtained TGT from LSA: "339+ creds);340}341return creds;342} else {343if (DEBUG) {344System.out.println(">>> LSA contains TGT for "345+ creds.getClient()346+ " not "347+ princ);348}349return null;350}351} else {352if (DEBUG) {353System.out.println(">>> Obtained TGT from LSA: "354+ creds);355}356return creds;357}358}359}360361/*362* Returns the appropriate cache. If ticketCache is null, it is the363* default cache otherwise it is the cache filename contained in it.364*/365CredentialsCache ccache =366CredentialsCache.getInstance(princ, ticketCache);367368if (ccache == null) {369return null;370}371372Credentials tgtCred = ccache.getInitialCreds();373374if (tgtCred == null) {375return null;376}377378if (EType.isSupported(tgtCred.key.getEType())) {379return tgtCred;380} else {381if (DEBUG) {382System.out.println(383">>> unsupported key type found the default TGT: " +384tgtCred.key.getEType());385}386return null;387}388}389390/**391* Acquires default credentials.392* <br>The possible locations for default credentials cache is searched in393* the following order:394* <ol>395* <li> The directory and cache file name specified by "KRB5CCNAME" system.396* property.397* <li> The directory and cache file name specified by "KRB5CCNAME"398* environment variable.399* <li> A cache file named krb5cc_{user.name} at {user.home} directory.400* </ol>401* @return a <code>KrbCreds</code> object if the credential is found,402* otherwise return null.403*/404405// this method is intentionally changed to not check if the caller's406// principal name matches cache file's principal name.407// It assumes that the GSS call has408// the privilege to access the default cache file.409410// This method is only called on Windows and Mac OS X, the native411// acquireDefaultNativeCreds is also available on these platforms.412public static synchronized Credentials acquireDefaultCreds() {413Credentials result = null;414415if (cache == null) {416cache = CredentialsCache.getInstance();417}418if (cache != null) {419Credentials temp = cache.getInitialCreds();420if (temp != null) {421if (DEBUG) {422System.out.println(">>> KrbCreds found the default ticket"423+ " granting ticket in credential cache.");424}425if (EType.isSupported(temp.key.getEType())) {426result = temp;427} else {428if (DEBUG) {429System.out.println(430">>> unsupported key type found the default TGT: " +431temp.key.getEType());432}433}434}435}436if (result == null) {437// Doesn't seem to be a default cache on this system or438// TGT has unsupported encryption type439440if (!alreadyTried) {441// See if there's any native code to load442try {443ensureLoaded();444} catch (Exception e) {445if (DEBUG) {446System.out.println("Can not load credentials cache");447e.printStackTrace();448}449alreadyTried = true;450}451}452if (alreadyLoaded) {453// There is some native code454if (DEBUG) {455System.out.println(">> Acquire default native Credentials");456}457try {458result = acquireDefaultNativeCreds(459EType.getDefaults("default_tkt_enctypes"));460} catch (KrbException ke) {461// when there is no default_tkt_enctypes.462}463}464}465return result;466}467468/**469* Acquires credentials for a specified service using initial credential.470* When the service has a different realm471* from the initial credential, we do cross-realm authentication472* - first, we use the current credential to get473* a cross-realm credential from the local KDC, then use that474* cross-realm credential to request service credential475* from the foreigh KDC.476*477* @param service the name of service principal using format478* components@realm479* @param ccreds client's initial credential.480* @exception IOException if an error occurs in reading the credentials481* cache482* @exception KrbException if an error occurs specific to Kerberos483* @return a <code>Credentials</code> object.484*/485486public static Credentials acquireServiceCreds(String service,487Credentials ccreds)488throws KrbException, IOException {489return CredentialsUtil.acquireServiceCreds(service, ccreds);490}491492public static Credentials acquireS4U2selfCreds(PrincipalName user,493Credentials ccreds) throws KrbException, IOException {494return CredentialsUtil.acquireS4U2selfCreds(user, ccreds);495}496497public static Credentials acquireS4U2proxyCreds(String service,498Ticket second, PrincipalName client, Credentials ccreds)499throws KrbException, IOException {500return CredentialsUtil.acquireS4U2proxyCreds(501service, second, client, ccreds);502}503504public CredentialsCache getCache() {505return cache;506}507508/*509* Prints out debug info.510*/511public static void printDebug(Credentials c) {512System.out.println(">>> DEBUG: ----Credentials----");513System.out.println("\tclient: " + c.client.toString());514if (c.clientAlias != null)515System.out.println("\tclient alias: " + c.clientAlias.toString());516System.out.println("\tserver: " + c.server.toString());517if (c.serverAlias != null)518System.out.println("\tserver alias: " + c.serverAlias.toString());519System.out.println("\tticket: sname: " + c.ticket.sname.toString());520if (c.startTime != null) {521System.out.println("\tstartTime: " + c.startTime.getTime());522}523System.out.println("\tendTime: " + c.endTime.getTime());524System.out.println(" ----Credentials end----");525}526527528static void ensureLoaded() {529java.security.AccessController.doPrivileged(530new java.security.PrivilegedAction<Void> () {531public Void run() {532if (System.getProperty("os.name").contains("OS X")) {533System.loadLibrary("osxkrb5");534} else {535System.loadLibrary("w2k_lsa_auth");536}537return null;538}539});540alreadyLoaded = true;541}542543public String toString() {544StringBuffer buffer = new StringBuffer("Credentials:");545buffer.append( "\n client=").append(client);546if (clientAlias != null)547buffer.append( "\n clientAlias=").append(clientAlias);548buffer.append( "\n server=").append(server);549if (serverAlias != null)550buffer.append( "\n serverAlias=").append(serverAlias);551if (authTime != null) {552buffer.append("\n authTime=").append(authTime);553}554if (startTime != null) {555buffer.append("\n startTime=").append(startTime);556}557buffer.append( "\n endTime=").append(endTime);558buffer.append( "\n renewTill=").append(renewTill);559buffer.append( "\n flags=").append(flags);560buffer.append( "\nEType (skey)=").append(key.getEType());561buffer.append( "\n (tkt key)=").append(ticket.encPart.eType);562return buffer.toString();563}564565public sun.security.krb5.internal.ccache.Credentials toCCacheCreds() {566return new sun.security.krb5.internal.ccache.Credentials(567getClient(), getServer(),568getSessionKey(),569date2kt(getAuthTime()),570date2kt(getStartTime()),571date2kt(getEndTime()),572date2kt(getRenewTill()),573false,574flags,575new HostAddresses(getClientAddresses()),576getAuthzData(),577getTicket(),578null);579}580581private static KerberosTime date2kt(Date d) {582return d == null ? null : new KerberosTime(d);583}584}585586587