Path: blob/master/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java
41161 views
/*1* Copyright (c) 2000, 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.krb5;2627import org.ietf.jgss.*;28import sun.security.jgss.GSSCaller;29import sun.security.jgss.spi.*;30import sun.security.krb5.*;31import javax.security.auth.kerberos.KerberosTicket;32import javax.security.auth.kerberos.KerberosPrincipal;33import java.net.InetAddress;34import java.io.IOException;35import java.util.Date;36import java.security.AccessController;37import java.security.AccessControlContext;38import java.security.PrivilegedExceptionAction;39import java.security.PrivilegedActionException;4041/**42* Implements the krb5 initiator credential element.43*44* @author Mayank Upadhyay45* @author Ram Marti46* @since 1.447*/4849public class Krb5InitCredential50extends KerberosTicket51implements Krb5CredElement {5253private static final long serialVersionUID = 7723415700837898232L;5455@SuppressWarnings("serial") // Not statically typed as Serializable56private Krb5NameElement name;57@SuppressWarnings("serial") // Not statically typed as Serializable58private Credentials krb5Credentials;59public KerberosTicket proxyTicket;6061private Krb5InitCredential(Krb5NameElement name,62byte[] asn1Encoding,63KerberosPrincipal client,64KerberosPrincipal clientAlias,65KerberosPrincipal server,66KerberosPrincipal serverAlias,67byte[] sessionKey,68int keyType,69boolean[] flags,70Date authTime,71Date startTime,72Date endTime,73Date renewTill,74InetAddress[] clientAddresses)75throws GSSException {76super(asn1Encoding,77client,78server,79sessionKey,80keyType,81flags,82authTime,83startTime,84endTime,85renewTill,86clientAddresses);87KerberosSecrets.getJavaxSecurityAuthKerberosAccess()88.kerberosTicketSetClientAlias(this, clientAlias);89KerberosSecrets.getJavaxSecurityAuthKerberosAccess()90.kerberosTicketSetServerAlias(this, serverAlias);91this.name = name;9293try {94// Cache this for later use by the sun.security.krb5 package.95krb5Credentials = new Credentials(asn1Encoding,96client.getName(),97(clientAlias != null ?98clientAlias.getName() : null),99server.getName(),100(serverAlias != null ?101serverAlias.getName() : null),102sessionKey,103keyType,104flags,105authTime,106startTime,107endTime,108renewTill,109clientAddresses);110} catch (KrbException e) {111throw new GSSException(GSSException.NO_CRED, -1,112e.getMessage());113} catch (IOException e) {114throw new GSSException(GSSException.NO_CRED, -1,115e.getMessage());116}117118}119120private Krb5InitCredential(Krb5NameElement name,121Credentials delegatedCred,122byte[] asn1Encoding,123KerberosPrincipal client,124KerberosPrincipal clientAlias,125KerberosPrincipal server,126KerberosPrincipal serverAlias,127byte[] sessionKey,128int keyType,129boolean[] flags,130Date authTime,131Date startTime,132Date endTime,133Date renewTill,134InetAddress[] clientAddresses)135throws GSSException {136super(asn1Encoding,137client,138server,139sessionKey,140keyType,141flags,142authTime,143startTime,144endTime,145renewTill,146clientAddresses);147KerberosSecrets.getJavaxSecurityAuthKerberosAccess()148.kerberosTicketSetClientAlias(this, clientAlias);149KerberosSecrets.getJavaxSecurityAuthKerberosAccess()150.kerberosTicketSetServerAlias(this, serverAlias);151this.name = name;152// A delegated cred does not have all fields set. So do not try to153// creat new Credentials out of the delegatedCred.154this.krb5Credentials = delegatedCred;155}156157static Krb5InitCredential getInstance(GSSCaller caller, Krb5NameElement name,158int initLifetime)159throws GSSException {160161KerberosTicket tgt = getTgt(caller, name, initLifetime);162if (tgt == null)163throw new GSSException(GSSException.NO_CRED, -1,164"Failed to find any Kerberos tgt");165166if (name == null) {167String fullName = tgt.getClient().getName();168name = Krb5NameElement.getInstance(fullName,169Krb5MechFactory.NT_GSS_KRB5_PRINCIPAL);170}171172KerberosPrincipal clientAlias = KerberosSecrets173.getJavaxSecurityAuthKerberosAccess()174.kerberosTicketGetClientAlias(tgt);175KerberosPrincipal serverAlias = KerberosSecrets176.getJavaxSecurityAuthKerberosAccess()177.kerberosTicketGetServerAlias(tgt);178Krb5InitCredential result = new Krb5InitCredential(name,179tgt.getEncoded(),180tgt.getClient(),181clientAlias,182tgt.getServer(),183serverAlias,184tgt.getSessionKey().getEncoded(),185tgt.getSessionKeyType(),186tgt.getFlags(),187tgt.getAuthTime(),188tgt.getStartTime(),189tgt.getEndTime(),190tgt.getRenewTill(),191tgt.getClientAddresses());192result.proxyTicket = KerberosSecrets.getJavaxSecurityAuthKerberosAccess().193kerberosTicketGetProxy(tgt);194return result;195}196197static Krb5InitCredential getInstance(Krb5NameElement name,198Credentials delegatedCred)199throws GSSException {200201EncryptionKey sessionKey = delegatedCred.getSessionKey();202203/*204* all of the following data is optional in a KRB-CRED205* messages. This check for each field.206*/207208PrincipalName cPrinc = delegatedCred.getClient();209PrincipalName cAPrinc = delegatedCred.getClientAlias();210PrincipalName sPrinc = delegatedCred.getServer();211PrincipalName sAPrinc = delegatedCred.getServerAlias();212213KerberosPrincipal client = null;214KerberosPrincipal clientAlias = null;215KerberosPrincipal server = null;216KerberosPrincipal serverAlias = null;217218Krb5NameElement credName = null;219220if (cPrinc != null) {221String fullName = cPrinc.getName();222credName = Krb5NameElement.getInstance(fullName,223Krb5MechFactory.NT_GSS_KRB5_PRINCIPAL);224client = new KerberosPrincipal(fullName);225}226227if (cAPrinc != null) {228clientAlias = new KerberosPrincipal(cAPrinc.getName());229}230231// XXX Compare name to credName232233if (sPrinc != null) {234server =235new KerberosPrincipal(sPrinc.getName(),236KerberosPrincipal.KRB_NT_SRV_INST);237}238239if (sAPrinc != null) {240serverAlias = new KerberosPrincipal(sAPrinc.getName());241}242243return new Krb5InitCredential(credName,244delegatedCred,245delegatedCred.getEncoded(),246client,247clientAlias,248server,249serverAlias,250sessionKey.getBytes(),251sessionKey.getEType(),252delegatedCred.getFlags(),253delegatedCred.getAuthTime(),254delegatedCred.getStartTime(),255delegatedCred.getEndTime(),256delegatedCred.getRenewTill(),257delegatedCred.getClientAddresses());258}259260/**261* Returns the principal name for this credential. The name262* is in mechanism specific format.263*264* @return GSSNameSpi representing principal name of this credential265* @exception GSSException may be thrown266*/267public final GSSNameSpi getName() throws GSSException {268return name;269}270271/**272* Returns the init lifetime remaining.273*274* @return the init lifetime remaining in seconds275* @exception GSSException may be thrown276*/277public int getInitLifetime() throws GSSException {278Date d = getEndTime();279if (d == null) {280return 0;281}282long retVal = d.getTime() - System.currentTimeMillis();283return (int)(retVal/1000);284}285286/**287* Returns the accept lifetime remaining.288*289* @return the accept lifetime remaining in seconds290* @exception GSSException may be thrown291*/292public int getAcceptLifetime() throws GSSException {293return 0;294}295296public boolean isInitiatorCredential() throws GSSException {297return true;298}299300public boolean isAcceptorCredential() throws GSSException {301return false;302}303304/**305* Returns the oid representing the underlying credential306* mechanism oid.307*308* @return the Oid for this credential mechanism309* @exception GSSException may be thrown310*/311public final Oid getMechanism() {312return Krb5MechFactory.GSS_KRB5_MECH_OID;313}314315public final java.security.Provider getProvider() {316return Krb5MechFactory.PROVIDER;317}318319320/**321* Returns a sun.security.krb5.Credentials instance so that it maybe322* used in that package for th Kerberos protocol.323*/324Credentials getKrb5Credentials() {325return krb5Credentials;326}327328/*329* XXX Call to this.refresh() should refresh the locally cached copy330* of krb5Credentials also.331*/332333/**334* Called to invalidate this credential element.335*/336public void dispose() throws GSSException {337try {338destroy();339} catch (javax.security.auth.DestroyFailedException e) {340GSSException gssException =341new GSSException(GSSException.FAILURE, -1,342"Could not destroy credentials - " + e.getMessage());343gssException.initCause(e);344}345}346347// XXX call to this.destroy() should destroy the locally cached copy348// of krb5Credentials and then call super.destroy().349350@SuppressWarnings("removal")351private static KerberosTicket getTgt(GSSCaller caller, Krb5NameElement name,352int initLifetime)353throws GSSException {354355final String clientPrincipal;356357/*358* Find the TGT for the realm that the client is in. If the client359* name is not available, then use the default realm.360*/361if (name != null) {362clientPrincipal = (name.getKrb5PrincipalName()).getName();363} else {364clientPrincipal = null;365}366367final AccessControlContext acc = AccessController.getContext();368369try {370final GSSCaller realCaller = (caller == GSSCaller.CALLER_UNKNOWN)371? GSSCaller.CALLER_INITIATE372: caller;373return AccessController.doPrivileged(374new PrivilegedExceptionAction<KerberosTicket>() {375public KerberosTicket run() throws Exception {376// It's OK to use null as serverPrincipal. TGT is almost377// the first ticket for a principal and we use list.378return Krb5Util.getInitialTicket(379realCaller,380clientPrincipal, acc);381}});382} catch (PrivilegedActionException e) {383GSSException ge =384new GSSException(GSSException.NO_CRED, -1,385"Attempt to obtain new INITIATE credentials failed!" +386" (" + e.getMessage() + ")");387ge.initCause(e.getException());388throw ge;389}390}391392@Override393public GSSCredentialSpi impersonate(GSSNameSpi name) throws GSSException {394try {395Krb5NameElement kname = (Krb5NameElement)name;396Credentials newCred = Credentials.acquireS4U2selfCreds(397kname.getKrb5PrincipalName(), krb5Credentials);398return new Krb5ProxyCredential(this, kname, newCred.getTicket());399} catch (IOException | KrbException ke) {400GSSException ge =401new GSSException(GSSException.FAILURE, -1,402"Attempt to obtain S4U2self credentials failed!");403ge.initCause(ke);404throw ge;405}406}407}408409410