--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.jgss.krb5;
+
+import org.ietf.jgss.*;
+import sun.security.jgss.GSSCaller;
+import sun.security.jgss.spi.*;
+import sun.security.krb5.*;
+import javax.security.auth.kerberos.KerberosTicket;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import java.net.InetAddress;
+import java.io.IOException;
+import java.util.Date;
+import java.security.AccessController;
+import java.security.AccessControlContext;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+
+/**
+ * Implements the krb5 initiator credential element.
+ *
+ * @author Mayank Upadhyay
+ * @author Ram Marti
+ * @since 1.4
+ */
+
+public class Krb5InitCredential
+ extends KerberosTicket
+ implements Krb5CredElement {
+
+ private static final long serialVersionUID = 7723415700837898232L;
+
+ private Krb5NameElement name;
+ private Credentials krb5Credentials;
+
+ private Krb5InitCredential(Krb5NameElement name,
+ byte[] asn1Encoding,
+ KerberosPrincipal client,
+ KerberosPrincipal server,
+ byte[] sessionKey,
+ int keyType,
+ boolean[] flags,
+ Date authTime,
+ Date startTime,
+ Date endTime,
+ Date renewTill,
+ InetAddress[] clientAddresses)
+ throws GSSException {
+ super(asn1Encoding,
+ client,
+ server,
+ sessionKey,
+ keyType,
+ flags,
+ authTime,
+ startTime,
+ endTime,
+ renewTill,
+ clientAddresses);
+
+ this.name = name;
+
+ try {
+ // Cache this for later use by the sun.security.krb5 package.
+ krb5Credentials = new Credentials(asn1Encoding,
+ client.getName(),
+ server.getName(),
+ sessionKey,
+ keyType,
+ flags,
+ authTime,
+ startTime,
+ endTime,
+ renewTill,
+ clientAddresses);
+ } catch (KrbException e) {
+ throw new GSSException(GSSException.NO_CRED, -1,
+ e.getMessage());
+ } catch (IOException e) {
+ throw new GSSException(GSSException.NO_CRED, -1,
+ e.getMessage());
+ }
+
+ }
+
+ private Krb5InitCredential(Krb5NameElement name,
+ Credentials delegatedCred,
+ byte[] asn1Encoding,
+ KerberosPrincipal client,
+ KerberosPrincipal server,
+ byte[] sessionKey,
+ int keyType,
+ boolean[] flags,
+ Date authTime,
+ Date startTime,
+ Date endTime,
+ Date renewTill,
+ InetAddress[] clientAddresses)
+ throws GSSException {
+ super(asn1Encoding,
+ client,
+ server,
+ sessionKey,
+ keyType,
+ flags,
+ authTime,
+ startTime,
+ endTime,
+ renewTill,
+ clientAddresses);
+
+ this.name = name;
+ // A delegated cred does not have all fields set. So do not try to
+ // creat new Credentials out of the delegatedCred.
+ this.krb5Credentials = delegatedCred;
+ }
+
+ static Krb5InitCredential getInstance(GSSCaller caller, Krb5NameElement name,
+ int initLifetime)
+ throws GSSException {
+
+ KerberosTicket tgt = getTgt(caller, name, initLifetime);
+ if (tgt == null)
+ throw new GSSException(GSSException.NO_CRED, -1,
+ "Failed to find any Kerberos tgt");
+
+ if (name == null) {
+ String fullName = tgt.getClient().getName();
+ name = Krb5NameElement.getInstance(fullName,
+ Krb5MechFactory.NT_GSS_KRB5_PRINCIPAL);
+ }
+
+ return new Krb5InitCredential(name,
+ tgt.getEncoded(),
+ tgt.getClient(),
+ tgt.getServer(),
+ tgt.getSessionKey().getEncoded(),
+ tgt.getSessionKeyType(),
+ tgt.getFlags(),
+ tgt.getAuthTime(),
+ tgt.getStartTime(),
+ tgt.getEndTime(),
+ tgt.getRenewTill(),
+ tgt.getClientAddresses());
+ }
+
+ static Krb5InitCredential getInstance(Krb5NameElement name,
+ Credentials delegatedCred)
+ throws GSSException {
+
+ EncryptionKey sessionKey = delegatedCred.getSessionKey();
+
+ /*
+ * all of the following data is optional in a KRB-CRED
+ * messages. This check for each field.
+ */
+
+ PrincipalName cPrinc = delegatedCred.getClient();
+ PrincipalName sPrinc = delegatedCred.getServer();
+
+ KerberosPrincipal client = null;
+ KerberosPrincipal server = null;
+
+ Krb5NameElement credName = null;
+
+ if (cPrinc != null) {
+ String fullName = cPrinc.getName();
+ credName = Krb5NameElement.getInstance(fullName,
+ Krb5MechFactory.NT_GSS_KRB5_PRINCIPAL);
+ client = new KerberosPrincipal(fullName);
+ }
+
+ // XXX Compare name to credName
+
+ if (sPrinc != null) {
+ server =
+ new KerberosPrincipal(sPrinc.getName(),
+ KerberosPrincipal.KRB_NT_SRV_INST);
+ }
+
+ return new Krb5InitCredential(credName,
+ delegatedCred,
+ delegatedCred.getEncoded(),
+ client,
+ server,
+ sessionKey.getBytes(),
+ sessionKey.getEType(),
+ delegatedCred.getFlags(),
+ delegatedCred.getAuthTime(),
+ delegatedCred.getStartTime(),
+ delegatedCred.getEndTime(),
+ delegatedCred.getRenewTill(),
+ delegatedCred.getClientAddresses());
+ }
+
+ /**
+ * Returns the principal name for this credential. The name
+ * is in mechanism specific format.
+ *
+ * @return GSSNameSpi representing principal name of this credential
+ * @exception GSSException may be thrown
+ */
+ public final GSSNameSpi getName() throws GSSException {
+ return name;
+ }
+
+ /**
+ * Returns the init lifetime remaining.
+ *
+ * @return the init lifetime remaining in seconds
+ * @exception GSSException may be thrown
+ */
+ public int getInitLifetime() throws GSSException {
+ int retVal = 0;
+ Date d = getEndTime();
+ if (d == null) {
+ return 0;
+ }
+ retVal = (int)(d.getTime() - (new Date().getTime()));
+
+ return retVal/1000;
+ }
+
+ /**
+ * Returns the accept lifetime remaining.
+ *
+ * @return the accept lifetime remaining in seconds
+ * @exception GSSException may be thrown
+ */
+ public int getAcceptLifetime() throws GSSException {
+ return 0;
+ }
+
+ public boolean isInitiatorCredential() throws GSSException {
+ return true;
+ }
+
+ public boolean isAcceptorCredential() throws GSSException {
+ return false;
+ }
+
+ /**
+ * Returns the oid representing the underlying credential
+ * mechanism oid.
+ *
+ * @return the Oid for this credential mechanism
+ * @exception GSSException may be thrown
+ */
+ public final Oid getMechanism() {
+ return Krb5MechFactory.GSS_KRB5_MECH_OID;
+ }
+
+ public final java.security.Provider getProvider() {
+ return Krb5MechFactory.PROVIDER;
+ }
+
+
+ /**
+ * Returns a sun.security.krb5.Credentials instance so that it maybe
+ * used in that package for th Kerberos protocol.
+ */
+ Credentials getKrb5Credentials() {
+ return krb5Credentials;
+ }
+
+ /*
+ * XXX Call to this.refresh() should refresh the locally cached copy
+ * of krb5Credentials also.
+ */
+
+ /**
+ * Called to invalidate this credential element.
+ */
+ public void dispose() throws GSSException {
+ try {
+ destroy();
+ } catch (javax.security.auth.DestroyFailedException e) {
+ GSSException gssException =
+ new GSSException(GSSException.FAILURE, -1,
+ "Could not destroy credentials - " + e.getMessage());
+ gssException.initCause(e);
+ }
+ }
+
+ // XXX call to this.destroy() should destroy the locally cached copy
+ // of krb5Credentials and then call super.destroy().
+
+ private static KerberosTicket getTgt(GSSCaller caller, Krb5NameElement name,
+ int initLifetime)
+ throws GSSException {
+
+ final String clientPrincipal;
+
+ /*
+ * Find the TGT for the realm that the client is in. If the client
+ * name is not available, then use the default realm.
+ */
+ if (name != null) {
+ clientPrincipal = (name.getKrb5PrincipalName()).getName();
+ } else {
+ clientPrincipal = null;
+ }
+
+ final AccessControlContext acc = AccessController.getContext();
+
+ try {
+ final GSSCaller realCaller = (caller == GSSCaller.CALLER_UNKNOWN)
+ ? GSSCaller.CALLER_INITIATE
+ : caller;
+ return AccessController.doPrivileged(
+ new PrivilegedExceptionAction<KerberosTicket>() {
+ public KerberosTicket run() throws Exception {
+ // It's OK to use null as serverPrincipal. TGT is almost
+ // the first ticket for a principal and we use list.
+ return Krb5Util.getTicket(
+ realCaller,
+ clientPrincipal, null, acc);
+ }});
+ } catch (PrivilegedActionException e) {
+ GSSException ge =
+ new GSSException(GSSException.NO_CRED, -1,
+ "Attempt to obtain new INITIATE credentials failed!" +
+ " (" + e.getMessage() + ")");
+ ge.initCause(e.getException());
+ throw ge;
+ }
+ }
+
+ @Override
+ public GSSCredentialSpi impersonate(GSSNameSpi name) throws GSSException {
+ try {
+ Krb5NameElement kname = (Krb5NameElement)name;
+ Credentials newCred = Credentials.acquireS4U2selfCreds(
+ kname.getKrb5PrincipalName(), krb5Credentials);
+ return new Krb5ProxyCredential(this, kname, newCred.getTicket());
+ } catch (IOException | KrbException ke) {
+ GSSException ge =
+ new GSSException(GSSException.FAILURE, -1,
+ "Attempt to obtain S4U2self credentials failed!");
+ ge.initCause(ke);
+ throw ge;
+ }
+ }
+}