diff --git a/jdk/src/share/classes/com/sun/security/jgss/ExtendedGSSContext.java b/jdk/src/share/classes/com/sun/security/jgss/ExtendedGSSContext.java
index 2733c7b08f8..0f3a27dfac9 100644
--- a/jdk/src/share/classes/com/sun/security/jgss/ExtendedGSSContext.java
+++ b/jdk/src/share/classes/com/sun/security/jgss/ExtendedGSSContext.java
@@ -36,33 +36,7 @@ import org.ietf.jgss.*;
public interface ExtendedGSSContext extends GSSContext {
/**
* Return the mechanism-specific attribute associated with {@code type}.
- *
- * For each supported attribute type, the type for the output are
- * defined below.
- *
* If there is a security manager, an {@link InquireSecContextPermission} * with the name {@code type.mech} must be granted. Otherwise, this could * result in a {@link SecurityException}.
@@ -97,6 +71,7 @@ public interface ExtendedGSSContext extends GSSContext { * @throws SecurityException if a security manager exists and a proper * {@link InquireSecContextPermission} is not granted. * @see InquireSecContextPermission + * @see InquireType */ public Object inquireSecContext(InquireType type) throws GSSException; diff --git a/jdk/src/share/classes/com/sun/security/jgss/InquireType.java b/jdk/src/share/classes/com/sun/security/jgss/InquireType.java index 9dfc83abf7c..440a85c178f 100644 --- a/jdk/src/share/classes/com/sun/security/jgss/InquireType.java +++ b/jdk/src/share/classes/com/sun/security/jgss/InquireType.java @@ -32,13 +32,38 @@ package com.sun.security.jgss; @jdk.Exported public enum InquireType { /** - * Attribute type for retrieving the session key of an - * established Kerberos 5 security context. + * Attribute type for retrieving the session key of an established + * Kerberos 5 security context. The returned object is an instance of + * {@link java.security.Key}, which has the following properties: + *
+ * + * An EncryptionKey is defined in Section 4.2.9 of the Kerberos Protocol + * Specification (RFC 4120) as: + *
+ * EncryptionKey ::= SEQUENCE {
+ * keytype [0] Int32 -- actually encryption type --,
+ * keyvalue [1] OCTET STRING
+ * }
+ *
+ * The key material of an {@code EncryptionKey} is defined as the value
+ * of the {@code keyValue} above.+ * + * @since 1.9 + */ +public final class EncryptionKey implements SecretKey { + + private static final long serialVersionUID = 9L; + + /** + * {@code KeyImpl} is serialized by writing out the ASN.1 encoded bytes + * of the encryption key. + * + * @serial + */ + final private KeyImpl key; + + private transient boolean destroyed = false; + + /** + * Constructs a {@code EncryptionKey} from the given bytes and + * the key type. + *
+ * The contents of the byte array are copied; subsequent modification of + * the byte array does not affect the newly created key. + * + * @param keyBytes the key material for the key + * @param keyType the key type for the key as defined by the + * Kerberos protocol specification. + * @throws NullPointerException if keyBytes is null + */ + public EncryptionKey(byte[] keyBytes, int keyType) { + key = new KeyImpl(Objects.requireNonNull(keyBytes), keyType); + } + + /** + * Returns the key type for this key. + * + * @return the key type. + * @throws IllegalStateException if the key is destroyed + */ + public int getKeyType() { + // KeyImpl already checked if destroyed + return key.getKeyType(); + } + + /* + * Methods from java.security.Key + */ + + /** + * Returns the standard algorithm name for this key. The algorithm names + * are the encryption type string defined on the IANA + * Kerberos Encryption Type Numbers + * page. + *
+ * This method can return the following value not defined on the IANA page: + *
+ * + * A KRB_CRED message is defined in Section 5.8.1 of the Kerberos Protocol + * Specification (RFC 4120) as: + *
+ * KRB-CRED ::= [APPLICATION 22] SEQUENCE {
+ * pvno [0] INTEGER (5),
+ * msg-type [1] INTEGER (22),
+ * tickets [2] SEQUENCE OF Ticket,
+ * enc-part [3] EncryptedData -- EncKrbCredPart
+ * }
+ * + * + * @since 1.9 + */ +public final class KerberosCredMessage implements Destroyable { + + final private KerberosPrincipal sender; + final private KerberosPrincipal recipient; + final private byte[] message; + + private boolean destroyed = false; + + /** + * Constructs a {@code KerberosCredMessage} object. + *
+ * The contents of the {@code message} argument are copied; subsequent + * modification of the byte array does not affect the newly created object. + * + * @param sender the sender of the message + * @param recipient the recipient of the message + * @param message the DER encoded KRB_CRED message + * @throws NullPointerException if any of sender, recipient + * or message is null + */ + public KerberosCredMessage(KerberosPrincipal sender, + KerberosPrincipal recipient, + byte[] message) { + this.sender = Objects.requireNonNull(sender); + this.recipient = Objects.requireNonNull(recipient); + this.message = Objects.requireNonNull(message).clone(); + } + + /** + * Returns the DER encoded form of the KRB_CRED message. + * + * @return a newly allocated byte array that contains the encoded form + * @throws IllegalStateException if the object is destroyed + */ + public byte[] getEncoded() { + if (destroyed) { + throw new IllegalStateException("This object is no longer valid"); + } + return message.clone(); + } + + /** + * Returns the sender of this message. + * + * @return the sender + * @throws IllegalStateException if the object is destroyed + */ + public KerberosPrincipal getSender() { + if (destroyed) { + throw new IllegalStateException("This object is no longer valid"); + } + return sender; + } + + /** + * Returns the recipient of this message. + * + * @return the recipient + * @throws IllegalStateException if the object is destroyed + */ + public KerberosPrincipal getRecipient() { + if (destroyed) { + throw new IllegalStateException("This object is no longer valid"); + } + return recipient; + } + + /** + * Destroys this object by clearing out the message. + */ + @Override + public void destroy() { + if (!destroyed) { + Arrays.fill(message, (byte)0); + destroyed = true; + } + } + + @Override + public boolean isDestroyed() { + return destroyed; + } + + @Override + public String toString() { + if (destroyed) { + return "Destroyed KerberosCredMessage"; + } else { + return "KRB_CRED from " + sender + " to " + recipient + ":\n" + + Base64.getUrlEncoder().encodeToString(message); + } + } + + @Override + public int hashCode() { + if (isDestroyed()) { + return -1; + } else { + return Objects.hash(sender, recipient, Arrays.hashCode(message)); + } + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (! (other instanceof KerberosCredMessage)) { + return false; + } + + KerberosCredMessage otherMessage = ((KerberosCredMessage) other); + if (isDestroyed() || otherMessage.isDestroyed()) { + return false; + } + + return Objects.equals(sender, otherMessage.sender) + && Objects.equals(recipient, otherMessage.recipient) + && Arrays.equals(message, otherMessage.message); + } +} diff --git a/jdk/src/share/classes/javax/security/auth/kerberos/KerberosKey.java b/jdk/src/share/classes/javax/security/auth/kerberos/KerberosKey.java index a8d12131aaf..b233052f44f 100644 --- a/jdk/src/share/classes/javax/security/auth/kerberos/KerberosKey.java +++ b/jdk/src/share/classes/javax/security/auth/kerberos/KerberosKey.java @@ -27,13 +27,27 @@ package javax.security.auth.kerberos; import java.util.Arrays; import javax.crypto.SecretKey; -import javax.security.auth.Destroyable; import javax.security.auth.DestroyFailedException; /** * This class encapsulates a long term secret key for a Kerberos * principal.
* + * A {@code KerberosKey} object includes an EncryptionKey, a + * {@link KerberosPrincipal} as its owner, and the version number + * of the key.
+ * + * An EncryptionKey is defined in Section 4.2.9 of the Kerberos Protocol + * Specification (RFC 4120) as: + *
+ * EncryptionKey ::= SEQUENCE {
+ * keytype [0] Int32 -- actually encryption type --,
+ * keyvalue [1] OCTET STRING
+ * }
+ *
+ * The key material of a {@code KerberosKey} is defined as the value
+ * of the {@code keyValue} above.+ * * All Kerberos JAAS login modules that obtain a principal's password and * generate the secret key from it should use this class. * Sometimes, such as when authenticating a server in @@ -70,7 +84,7 @@ import javax.security.auth.DestroyFailedException; * @author Mayank Upadhyay * @since 1.4 */ -public class KerberosKey implements SecretKey, Destroyable { +public class KerberosKey implements SecretKey { private static final long serialVersionUID = -4625402278148246993L; @@ -89,15 +103,8 @@ public class KerberosKey implements SecretKey, Destroyable { private final int versionNum; /** - * {@code KeyImpl} is serialized by writing out the ASN1 Encoded bytes + * {@code KeyImpl} is serialized by writing out the ASN.1 encoded bytes * of the encryption key. - * The ASN1 encoding is defined in RFC4120 and as follows: - *
- * EncryptionKey ::= SEQUENCE {
- * keytype [0] Int32 -- actually encryption type --,
- * keyvalue [1] OCTET STRING
- * }
- *
*
* @serial
*/
@@ -111,7 +118,7 @@ public class KerberosKey implements SecretKey, Destroyable {
* key information from a Kerberos "keytab".
*
* @param principal the principal that this secret key belongs to
- * @param keyBytes the raw bytes for the secret key
+ * @param keyBytes the key material for the secret key
* @param keyType the key type for the secret key as defined by the
* Kerberos protocol specification.
* @param versionNum the version number of this secret key
@@ -153,10 +160,12 @@ public class KerberosKey implements SecretKey, Destroyable {
* Returns the principal that this key belongs to.
*
* @return the principal this key belongs to.
+ * @throws IllegalStateException if the key is destroyed
*/
public final KerberosPrincipal getPrincipal() {
- if (destroyed)
+ if (destroyed) {
throw new IllegalStateException("This key is no longer valid");
+ }
return principal;
}
@@ -164,10 +173,12 @@ public class KerberosKey implements SecretKey, Destroyable {
* Returns the key version number.
*
* @return the key version number.
+ * @throws IllegalStateException if the key is destroyed
*/
public final int getVersionNumber() {
- if (destroyed)
+ if (destroyed) {
throw new IllegalStateException("This key is no longer valid");
+ }
return versionNum;
}
@@ -175,10 +186,10 @@ public class KerberosKey implements SecretKey, Destroyable {
* Returns the key type for this long-term key.
*
* @return the key type.
+ * @throws IllegalStateException if the key is destroyed
*/
public final int getKeyType() {
- if (destroyed)
- throw new IllegalStateException("This key is no longer valid");
+ // KeyImpl already checked if destroyed
return key.getKeyType();
}
@@ -201,10 +212,10 @@ public class KerberosKey implements SecretKey, Destroyable {
*
*
* @return the name of the algorithm associated with this key.
+ * @throws IllegalStateException if the key is destroyed
*/
public final String getAlgorithm() {
- if (destroyed)
- throw new IllegalStateException("This key is no longer valid");
+ // KeyImpl already checked if destroyed
return key.getAlgorithm();
}
@@ -212,10 +223,10 @@ public class KerberosKey implements SecretKey, Destroyable {
* Returns the name of the encoding format for this secret key.
*
* @return the String "RAW"
+ * @throws IllegalStateException if the key is destroyed
*/
public final String getFormat() {
- if (destroyed)
- throw new IllegalStateException("This key is no longer valid");
+ // KeyImpl already checked if destroyed
return key.getFormat();
}
@@ -223,16 +234,15 @@ public class KerberosKey implements SecretKey, Destroyable {
* Returns the key material of this secret key.
*
* @return the key material
+ * @throws IllegalStateException if the key is destroyed
*/
public final byte[] getEncoded() {
- if (destroyed)
- throw new IllegalStateException("This key is no longer valid");
+ // KeyImpl already checked if destroyed
return key.getEncoded();
}
/**
- * Destroys this key. A call to any of its other methods after this
- * will cause an IllegalStateException to be thrown.
+ * Destroys this key by clearing out the key material of this secret key.
*
* @throws DestroyFailedException if some error occurs while destorying
* this key.
@@ -253,9 +263,9 @@ public class KerberosKey implements SecretKey, Destroyable {
public String toString() {
if (destroyed) {
- return "Destroyed Principal";
+ return "Destroyed KerberosKey";
}
- return "Kerberos Principal " + principal.toString() +
+ return "Kerberos Principal " + principal +
"Key Version " + versionNum +
"key " + key.toString();
}
@@ -293,8 +303,9 @@ public class KerberosKey implements SecretKey, Destroyable {
*/
public boolean equals(Object other) {
- if (other == this)
+ if (other == this) {
return true;
+ }
if (! (other instanceof KerberosKey)) {
return false;
diff --git a/jdk/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java b/jdk/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java
index da38df976e7..513b49c1fc0 100644
--- a/jdk/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java
+++ b/jdk/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java
@@ -35,9 +35,6 @@ import javax.security.auth.Destroyable;
import javax.security.auth.RefreshFailedException;
import javax.security.auth.DestroyFailedException;
import sun.misc.HexDumpEncoder;
-import sun.security.krb5.EncryptionKey;
-import sun.security.krb5.Asn1Exception;
-import sun.security.util.*;
/**
* This class encapsulates a Kerberos ticket and associated
@@ -253,9 +250,10 @@ public class KerberosTicket implements Destroyable, Refreshable,
Date endTime,
Date renewTill,
InetAddress[] clientAddresses) {
- if (sessionKey == null)
- throw new IllegalArgumentException("Session key for ticket"
- + " cannot be null");
+ if (sessionKey == null) {
+ throw new IllegalArgumentException("Session key for ticket"
+ + " cannot be null");
+ }
init(asn1Encoding, client, server,
new KeyImpl(sessionKey, keyType), flags, authTime,
startTime, endTime, renewTill, clientAddresses);
@@ -271,41 +269,46 @@ public class KerberosTicket implements Destroyable, Refreshable,
Date endTime,
Date renewTill,
InetAddress[] clientAddresses) {
- if (asn1Encoding == null)
- throw new IllegalArgumentException("ASN.1 encoding of ticket"
- + " cannot be null");
+ if (asn1Encoding == null) {
+ throw new IllegalArgumentException("ASN.1 encoding of ticket"
+ + " cannot be null");
+ }
this.asn1Encoding = asn1Encoding.clone();
- if (client == null)
- throw new IllegalArgumentException("Client name in ticket"
- + " cannot be null");
+ if (client == null) {
+ throw new IllegalArgumentException("Client name in ticket"
+ + " cannot be null");
+ }
this.client = client;
- if (server == null)
- throw new IllegalArgumentException("Server name in ticket"
- + " cannot be null");
+ if (server == null) {
+ throw new IllegalArgumentException("Server name in ticket"
+ + " cannot be null");
+ }
this.server = server;
// Caller needs to make sure `sessionKey` will not be null
this.sessionKey = sessionKey;
if (flags != null) {
- if (flags.length >= NUM_FLAGS)
- this.flags = flags.clone();
- else {
+ if (flags.length >= NUM_FLAGS) {
+ this.flags = flags.clone();
+ } else {
this.flags = new boolean[NUM_FLAGS];
// Fill in whatever we have
- for (int i = 0; i < flags.length; i++)
+ for (int i = 0; i < flags.length; i++) {
this.flags[i] = flags[i];
+ }
}
- } else
- this.flags = new boolean[NUM_FLAGS];
+ } else {
+ this.flags = new boolean[NUM_FLAGS];
+ }
if (this.flags[RENEWABLE_TICKET_FLAG]) {
- if (renewTill == null)
- throw new IllegalArgumentException("The renewable period "
+ if (renewTill == null) {
+ throw new IllegalArgumentException("The renewable period "
+ "end time cannot be null for renewable tickets.");
-
+ }
this.renewTill = new Date(renewTill.getTime());
}
@@ -318,13 +321,15 @@ public class KerberosTicket implements Destroyable, Refreshable,
this.startTime = this.authTime;
}
- if (endTime == null)
- throw new IllegalArgumentException("End time for ticket validity"
- + " cannot be null");
+ if (endTime == null) {
+ throw new IllegalArgumentException("End time for ticket validity"
+ + " cannot be null");
+ }
this.endTime = new Date(endTime.getTime());
- if (clientAddresses != null)
- this.clientAddresses = clientAddresses.clone();
+ if (clientAddresses != null) {
+ this.clientAddresses = clientAddresses.clone();
+ }
}
/**
@@ -346,14 +351,17 @@ public class KerberosTicket implements Destroyable, Refreshable,
}
/**
- * Returns the session key associated with this ticket.
+ * Returns the session key associated with this ticket. The return value
+ * is always a {@link EncryptionKey} object.
*
* @return the session key.
*/
public final SecretKey getSessionKey() {
- if (destroyed)
+ if (destroyed) {
throw new IllegalStateException("This ticket is no longer valid");
- return sessionKey;
+ }
+ return new EncryptionKey(
+ sessionKey.getEncoded(), sessionKey.getKeyType());
}
/**
@@ -366,8 +374,9 @@ public class KerberosTicket implements Destroyable, Refreshable,
* @see #getSessionKey()
*/
public final int getSessionKeyType() {
- if (destroyed)
+ if (destroyed) {
throw new IllegalStateException("This ticket is no longer valid");
+ }
return sessionKey.getKeyType();
}
@@ -508,8 +517,9 @@ public class KerberosTicket implements Destroyable, Refreshable,
* @return an ASN.1 encoding of the entire ticket.
*/
public final byte[] getEncoded() {
- if (destroyed)
+ if (destroyed) {
throw new IllegalStateException("This ticket is no longer valid");
+ }
return asn1Encoding.clone();
}
@@ -539,16 +549,17 @@ public class KerberosTicket implements Destroyable, Refreshable,
*/
public void refresh() throws RefreshFailedException {
- if (destroyed)
+ if (destroyed) {
throw new RefreshFailedException("A destroyed ticket "
- + "cannot be renewd.");
-
- if (!isRenewable())
+ + "cannot be renewd.");
+ }
+ if (!isRenewable()) {
throw new RefreshFailedException("This ticket is not renewable");
-
- if (System.currentTimeMillis() > getRenewTill().getTime())
+ }
+ if (System.currentTimeMillis() > getRenewTill().getTime()) {
throw new RefreshFailedException("This ticket is past "
- + "its last renewal time.");
+ + "its last renewal time.");
+ }
Throwable e = null;
sun.security.krb5.Credentials krb5Creds = null;
@@ -634,8 +645,9 @@ public class KerberosTicket implements Destroyable, Refreshable,
}
public String toString() {
- if (destroyed)
- throw new IllegalStateException("This ticket is no longer valid");
+ if (destroyed) {
+ return "Destroyed KerberosTicket";
+ }
StringBuilder caddrString = new StringBuilder();
if (clientAddresses != null) {
for (int i = 0; i < clientAddresses.length; i++) {
@@ -715,8 +727,9 @@ public class KerberosTicket implements Destroyable, Refreshable,
*/
public boolean equals(Object other) {
- if (other == this)
+ if (other == this) {
return true;
+ }
if (! (other instanceof KerberosTicket)) {
return false;
@@ -731,7 +744,7 @@ public class KerberosTicket implements Destroyable, Refreshable,
!endTime.equals(otherTicket.getEndTime()) ||
!server.equals(otherTicket.getServer()) ||
!client.equals(otherTicket.getClient()) ||
- !sessionKey.equals(otherTicket.getSessionKey()) ||
+ !sessionKey.equals(otherTicket.sessionKey) ||
!Arrays.equals(clientAddresses, otherTicket.getClientAddresses()) ||
!Arrays.equals(flags, otherTicket.getFlags())) {
return false;
@@ -739,35 +752,41 @@ public class KerberosTicket implements Destroyable, Refreshable,
// authTime may be null
if (authTime == null) {
- if (otherTicket.getAuthTime() != null)
+ if (otherTicket.getAuthTime() != null) {
return false;
+ }
} else {
- if (!authTime.equals(otherTicket.getAuthTime()))
+ if (!authTime.equals(otherTicket.getAuthTime())) {
return false;
+ }
}
// startTime may be null
if (startTime == null) {
- if (otherTicket.getStartTime() != null)
+ if (otherTicket.getStartTime() != null) {
return false;
+ }
} else {
- if (!startTime.equals(otherTicket.getStartTime()))
+ if (!startTime.equals(otherTicket.getStartTime())) {
return false;
+ }
}
if (renewTill == null) {
- if (otherTicket.getRenewTill() != null)
+ if (otherTicket.getRenewTill() != null) {
return false;
+ }
} else {
- if (!renewTill.equals(otherTicket.getRenewTill()))
+ if (!renewTill.equals(otherTicket.getRenewTill())) {
return false;
+ }
}
return true;
}
private void readObject(ObjectInputStream s)
- throws IOException, ClassNotFoundException {
+ throws IOException, ClassNotFoundException {
s.defaultReadObject();
if (sessionKey == null) {
throw new InvalidObjectException("Session key cannot be null");
diff --git a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java
index 53c13f0894f..abce4c05987 100644
--- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java
@@ -40,11 +40,13 @@ import java.security.Provider;
import java.security.AccessController;
import java.security.AccessControlContext;
import java.security.Key;
-import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
-import javax.crypto.Cipher;
+import java.security.PrivilegedExceptionAction;
import javax.security.auth.Subject;
-import javax.security.auth.kerberos.*;
+import javax.security.auth.kerberos.ServicePermission;
+import javax.security.auth.kerberos.KerberosCredMessage;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.auth.kerberos.KerberosTicket;
import sun.security.krb5.internal.Ticket;
/**
@@ -118,6 +120,7 @@ class Krb5Context implements GSSContextSpi {
// XXX See if the required info from these can be extracted and
// stored elsewhere
+ private Credentials tgt;
private Credentials serviceCreds;
private KrbApReq apReq;
Ticket serviceTicket;
@@ -616,7 +619,6 @@ class Krb5Context implements GSSContextSpi {
"No TGT available");
}
myName = (Krb5NameElement) myCred.getName();
- Credentials tgt;
final Krb5ProxyCredential second;
if (myCred instanceof Krb5InitCredential) {
second = null;
@@ -750,7 +752,6 @@ class Krb5Context implements GSSContextSpi {
// No need to write anything;
// just validate the incoming token
new AcceptSecContextToken(this, serviceCreds, apReq, is);
- serviceCreds = null;
apReq = null;
state = STATE_DONE;
} else {
@@ -1304,6 +1305,9 @@ class Krb5Context implements GSSContextSpi {
public final void dispose() throws GSSException {
state = STATE_DELETED;
delegatedCred = null;
+ tgt = null;
+ serviceCreds = null;
+ key = null;
}
public final Provider getProvider() {
@@ -1424,6 +1428,9 @@ class Krb5Context implements GSSContextSpi {
switch (type) {
case KRB5_GET_SESSION_KEY:
return new KerberosSessionKey(key);
+ case KRB5_GET_SESSION_KEY_EX:
+ return new javax.security.auth.kerberos.EncryptionKey(
+ key.getBytes(), key.getEType());
case KRB5_GET_TKT_FLAGS:
return tktFlags.clone();
case KRB5_GET_AUTHZ_DATA:
@@ -1435,6 +1442,26 @@ class Krb5Context implements GSSContextSpi {
}
case KRB5_GET_AUTHTIME:
return authTime;
+ case KRB5_GET_KRB_CRED:
+ if (!isInitiator()) {
+ throw new GSSException(GSSException.UNAVAILABLE, -1,
+ "KRB_CRED not available on acceptor side.");
+ }
+ KerberosPrincipal sender = new KerberosPrincipal(
+ myName.getKrb5PrincipalName().getName());
+ KerberosPrincipal recipient = new KerberosPrincipal(
+ peerName.getKrb5PrincipalName().getName());
+ try {
+ byte[] krbCred = new KrbCred(tgt, serviceCreds, key)
+ .getMessage();
+ return new KerberosCredMessage(
+ sender, recipient, krbCred);
+ } catch (KrbException | IOException e) {
+ GSSException gsse = new GSSException(GSSException.UNAVAILABLE, -1,
+ "KRB_CRED not generated correctly.");
+ gsse.initCause(e);
+ throw gsse;
+ }
}
throw new GSSException(GSSException.UNAVAILABLE, -1,
"Inquire type not supported.");
@@ -1456,4 +1483,5 @@ class Krb5Context implements GSSContextSpi {
public void setAuthzData(com.sun.security.jgss.AuthorizationDataEntry[] authzData) {
this.authzData = authzData;
}
+
}
diff --git a/jdk/test/javax/security/auth/kerberos/KerberosHashEqualsTest.java b/jdk/test/javax/security/auth/kerberos/KerberosHashEqualsTest.java
index 9578a59547a..7eed2ccf425 100644
--- a/jdk/test/javax/security/auth/kerberos/KerberosHashEqualsTest.java
+++ b/jdk/test/javax/security/auth/kerberos/KerberosHashEqualsTest.java
@@ -33,9 +33,7 @@
import java.net.InetAddress;
import java.util.Date;
-import javax.security.auth.kerberos.KerberosKey;
-import javax.security.auth.kerberos.KerberosPrincipal;
-import javax.security.auth.kerberos.KerberosTicket;
+import javax.security.auth.kerberos.*;
public class KerberosHashEqualsTest {
public static void main(String[] args) throws Exception {
@@ -66,28 +64,67 @@ public class KerberosHashEqualsTest {
k2.destroy();
checkNotSame(k1, k2);
-
- // destroyed keys doesn't equal to each other
checkNotSame(k2, k1);
checkSame(k2, k2);
+ k1.destroy();
+ checkNotSame(k1, k2);
+
+ // Destroyed key has string and hashCode
+ k1.toString(); k1.hashCode();
+
// a little different
+ k1 = new KerberosKey(newKP("A"), "pass".getBytes(), 1, 1);
k2 = new KerberosKey(newKP("B"), "pass".getBytes(), 1, 1);
checkNotSame(k1, k2);
+
k2 = new KerberosKey(newKP("A"), "ssap".getBytes(), 1, 1);
checkNotSame(k1, k2);
+
k2 = new KerberosKey(newKP("A"), "pass".getBytes(), 2, 1);
checkNotSame(k1, k2);
+
k2 = new KerberosKey(newKP("A"), "pass".getBytes(), 1, 2);
checkNotSame(k1, k2);
+ // Null
k1 = new KerberosKey(null, "pass".getBytes(), 1, 2);
checkNotSame(k1, k2); // null to non-null
k2 = new KerberosKey(null, "pass".getBytes(), 1, 2);
checkSame(k1, k2); // null to null
+ // Even key with null principal has a string and hashCode
+ k1.toString(); k1.hashCode();
+
checkNotSame(k1, "Another Object");
+ EncryptionKey e1, e2;
+ e1 = new EncryptionKey("pass".getBytes(), 1);
+ e2 = new EncryptionKey("pass".getBytes(), 1);
+ checkSame(e1, e1); // me to me
+ checkSame(e1, e2); // same
+
+ e2.destroy();
+ checkNotSame(e1, e2);
+ checkNotSame(e2, e1);
+ checkSame(e2, e2);
+
+ e1.destroy();
+ checkNotSame(e1, e2);
+
+ // Destroyed key has string and hashCode
+ e1.toString(); e1.hashCode();
+
+ // a little different
+ e1 = new EncryptionKey("pass".getBytes(), 1);
+ e2 = new EncryptionKey("ssap".getBytes(), 1);
+ checkNotSame(e1, e2);
+
+ e2 = new EncryptionKey("pass".getBytes(), 2);
+ checkNotSame(e1, e2);
+
+ checkNotSame(e1, "Another Object");
+
KerberosTicket t1, t2;
t1 = new KerberosTicket("asn1".getBytes(), newKP("client"), newKP("server"), "pass".getBytes(), 1, new boolean[] {true, true}, new Date(0), new Date(0), new Date(0), new Date(0), null);
t2 = new KerberosTicket("asn1".getBytes(), newKP("client"), newKP("server"), "pass".getBytes(), 1, new boolean[] {true, true}, new Date(0), new Date(0), new Date(0), new Date(0), null);
@@ -120,6 +157,7 @@ public class KerberosHashEqualsTest {
t2.destroy();
checkNotSame(t1, t2);
+ t2.hashCode(); t2.toString();
// destroyed tickets doesn't equal to each other
checkNotSame(t2, t1);
@@ -130,6 +168,37 @@ public class KerberosHashEqualsTest {
checkNotSame(t1, t2); // renewtill is useful
checkNotSame(t1, "Another Object");
+
+ KerberosCredMessage m1, m2;
+ m1 = new KerberosCredMessage(newKP("C"), newKP("S"), "message".getBytes());
+ m2 = new KerberosCredMessage(newKP("C"), newKP("S"), "message".getBytes());
+ checkSame(m1, m1); // me to me
+ checkSame(m1, m2); // same
+
+ m2.destroy();
+ checkNotSame(m1, m2);
+ checkNotSame(m2, m1);
+ checkSame(m2, m2);
+
+ m1.destroy();
+ checkNotSame(m1, m2);
+
+ // Destroyed message has string and hashCode
+ m1.toString(); m1.hashCode();
+
+ // a little different
+ m1 = new KerberosCredMessage(newKP("C"), newKP("S"), "message".getBytes());
+ m2 = new KerberosCredMessage(newKP("A"), newKP("S"), "message".getBytes());
+ checkNotSame(m1, m2);
+
+ m2 = new KerberosCredMessage(newKP("C"), newKP("B"), "message".getBytes());
+ checkNotSame(m1, m2);
+
+ m1 = new KerberosCredMessage(newKP("C"), newKP("S"), "hello".getBytes());
+ checkNotSame(m1, m2);
+
+ checkNotSame(m1, "Another Object");
+
System.out.println("Good!");
}
diff --git a/jdk/test/javax/security/auth/kerberos/KerberosNullsAndDestroyTest.java b/jdk/test/javax/security/auth/kerberos/KerberosNullsAndDestroyTest.java
new file mode 100644
index 00000000000..06bb71cd90b
--- /dev/null
+++ b/jdk/test/javax/security/auth/kerberos/KerberosNullsAndDestroyTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2014, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8043071
+ * @summary Expose session key and KRB_CRED through extended GSS-API
+ */
+
+import javax.security.auth.kerberos.*;
+import java.util.function.Supplier;
+
+public class KerberosNullsAndDestroyTest {
+
+ public static void main(String[] args) throws Exception {
+
+ KerberosPrincipal c = new KerberosPrincipal("me@HERE");
+ KerberosPrincipal s = new KerberosPrincipal("you@THERE");
+
+ // These object constructions should throw NullPointerException
+ checkNPE(() -> new KerberosKey(c, null, 17, 1));
+ checkNPE(() -> new EncryptionKey(null, 17));
+ checkNPE(() -> new KerberosCredMessage(null, s, new byte[1]));
+ checkNPE(() -> new KerberosCredMessage(c, null, new byte[1]));
+ checkNPE(() -> new KerberosCredMessage(c, s, null));
+
+ KerberosKey k1 = new KerberosKey(c, new byte[16], 17, 1);
+ EncryptionKey k2 = new EncryptionKey(new byte[16], 17);
+ KerberosCredMessage m = new KerberosCredMessage(c, s, new byte[1]);
+
+ // These get calls should throw IllegalStateException
+ k1.destroy();
+ checkISE(() -> k1.getAlgorithm());
+ checkISE(() -> k1.getEncoded());
+ checkISE(() -> k1.getFormat());
+ checkISE(() -> k1.getKeyType());
+ checkISE(() -> k1.getPrincipal());
+ checkISE(() -> k1.getVersionNumber());
+
+ k2.destroy();
+ checkISE(() -> k2.getAlgorithm());
+ checkISE(() -> k2.getEncoded());
+ checkISE(() -> k2.getFormat());
+ checkISE(() -> k2.getKeyType());
+
+ m.destroy();
+ checkISE(() -> m.getSender());
+ checkISE(() -> m.getRecipient());
+ checkISE(() -> m.getEncoded());
+ }
+
+ static void checkNPE(Supplier> f) throws Exception {
+ check(f, NullPointerException.class);
+ }
+
+ static void checkISE(Supplier> f) throws Exception {
+ check(f, IllegalStateException.class);
+ }
+
+ static void check(Supplier> f, Class extends Exception> type) throws Exception {
+ try {
+ f.get();
+ } catch (Exception e) {
+ if (e.getClass() != type) {
+ throw e;
+ } else {
+ return;
+ }
+ }
+ throw new Exception("Should fail");
+ }
+}
diff --git a/jdk/test/sun/security/krb5/auto/Context.java b/jdk/test/sun/security/krb5/auto/Context.java
index 715a1ad5978..28395d61295 100644
--- a/jdk/test/sun/security/krb5/auto/Context.java
+++ b/jdk/test/sun/security/krb5/auto/Context.java
@@ -26,9 +26,11 @@ import java.security.Key;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Arrays;
+import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import javax.security.auth.Subject;
+import javax.security.auth.kerberos.KerberosCredMessage;
import javax.security.auth.kerberos.KerberosKey;
import javax.security.auth.kerberos.KerberosTicket;
import javax.security.auth.login.LoginContext;
@@ -86,7 +88,6 @@ public class Context {
/**
* Using the delegated credentials from a previous acceptor
- * @param c
*/
public Context delegated() throws Exception {
Context out = new Context();
@@ -177,7 +178,6 @@ public class Context {
/**
* Logins with username/keytab as an existing Subject. The
* same subject can be used multiple times to simulate multiple logins.
- * @param s existing subject
*/
public static Context fromUserKtab(
String user, String ktab, boolean storeKey) throws Exception {
@@ -411,6 +411,12 @@ public class Context {
Key k = (Key)ex.inquireSecContext(
InquireType.KRB5_GET_SESSION_KEY);
if (k == null) {
+ throw new Exception("(Old) Session key cannot be null");
+ }
+ System.out.println("(Old) Session key is: " + k);
+ Key k2 = (Key)ex.inquireSecContext(
+ InquireType.KRB5_GET_SESSION_KEY_EX);
+ if (k2 == null) {
throw new Exception("Session key cannot be null");
}
System.out.println("Session key is: " + k);
@@ -431,6 +437,19 @@ public class Context {
InquireType.KRB5_GET_AUTHZ_DATA);
System.out.println("AuthzData is: " + Arrays.toString(ad));
}
+ try {
+ KerberosCredMessage tok = (KerberosCredMessage)ex.inquireSecContext(
+ InquireType.KRB5_GET_KRB_CRED);
+ System.out.println("KRB_CRED is " +
+ (tok == null?"not ":"") + "available");
+ if (tok != null) {
+ System.out.println("From " + tok.getSender() + " to "
+ + tok.getRecipient());
+ System.out.println(Base64.getEncoder().encodeToString(tok.getEncoded()));
+ }
+ } catch (Exception e) {
+ System.out.println("KRB_CRED is not available: " + e);
+ }
}
}
}
diff --git a/jdk/test/sun/security/krb5/auto/KerberosHashEqualsTest.java b/jdk/test/sun/security/krb5/auto/KerberosHashEqualsTest.java
deleted file mode 100644
index e7c026dab03..00000000000
--- a/jdk/test/sun/security/krb5/auto/KerberosHashEqualsTest.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) 2005, 2011, 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.
- *
- * 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.
- */
-
-/*
- * @test
- * @bug 4641821
- * @run main/othervm KerberosHashEqualsTest
- * @summary hashCode() and equals() for KerberosKey and KerberosTicket
- */
-
-import java.net.InetAddress;
-import java.util.Date;
-import javax.security.auth.kerberos.KerberosKey;
-import javax.security.auth.kerberos.KerberosPrincipal;
-import javax.security.auth.kerberos.KerberosTicket;
-
-public class KerberosHashEqualsTest {
- public static void main(String[] args) throws Exception {
- new OneKDC(null);
- new KerberosHashEqualsTest().check();
- }
-
- void checkSame(Object o1, Object o2) {
- if(!o1.equals(o2)) {
- throw new RuntimeException("equals() fails");
- }
- if(o1.hashCode() != o2.hashCode()) {
- throw new RuntimeException("hashCode() not same");
- }
- }
-
- void checkNotSame(Object o1, Object o2) {
- if(o1.equals(o2)) {
- throw new RuntimeException("equals() succeeds");
- }
- }
-
- void check() throws Exception {
-
- // The key part:
- // new KerberosKey(principal, bytes, keyType, version)
-
- KerberosKey k1, k2;
- KerberosPrincipal CLIENT = new KerberosPrincipal("client");
- KerberosPrincipal SERVER = new KerberosPrincipal("server");
- byte[] PASS = "pass".getBytes();
-
- k1 = new KerberosKey(CLIENT, PASS, 1, 1);
- k2 = new KerberosKey(CLIENT, PASS, 1, 1);
- checkSame(k1, k1); // me is me
- checkSame(k1, k2); // same
-
- // A destroyed key doesn't equal to any key
- k2.destroy();
- checkNotSame(k1, k2);
- checkNotSame(k2, k1);
- k1.destroy();
- checkNotSame(k1, k2); // even if they are both destroyed
- checkNotSame(k2, k1);
- checkSame(k2, k2);
-
- // a little difference means not equal
- k1 = new KerberosKey(CLIENT, PASS, 1, 1);
- k2 = new KerberosKey(SERVER, PASS, 1, 1);
- checkNotSame(k1, k2); // Different principal name
-
- k2 = new KerberosKey(CLIENT, "ssap".getBytes(), 1, 1);
- checkNotSame(k1, k2); // Different password
-
- k2 = new KerberosKey(CLIENT, PASS, 2, 1);
- checkNotSame(k1, k2); // Different keytype
-
- k2 = new KerberosKey(CLIENT, PASS, 1, 2);
- checkNotSame(k1, k2); // Different version
-
- k2 = new KerberosKey(null, PASS, 1, 2);
- checkNotSame(k1, k2); // null is not non-null
-
- k1 = new KerberosKey(null, PASS, 1, 2);
- checkSame(k1, k2); // null is null
-
- checkNotSame(k1, "Another Object");
-
- // The ticket part:
- // new KerberosTicket(asn1 bytes, client, server, session key, type, flags,
- // auth, start, end, renewUntil times, address)
-
- KerberosTicket t1, t2;
-
- byte[] ASN1 = "asn1".getBytes();
- boolean[] FORWARDABLE = new boolean[] {true, true};
- boolean[] ALLTRUE = new boolean[] {true, true, true, true, true, true, true, true, true, true};
- Date D0 = new Date(0);
-
- t1 = new KerberosTicket(ASN1, CLIENT, SERVER, PASS, 1, FORWARDABLE, D0, D0, D0, D0, null);
- t2 = new KerberosTicket(ASN1, CLIENT, SERVER, PASS, 1, FORWARDABLE, D0, D0, D0, D0, null);
- checkSame(t1, t1);
- checkSame(t1, t2);
-
- // destroyed tickets doesn't equal to each other
- t1.destroy();
- checkNotSame(t1, t2);
- checkNotSame(t2, t1);
-
- t2.destroy();
- checkNotSame(t1, t2); // even if they are both destroyed
- checkNotSame(t2, t1);
-
- checkSame(t2, t2); // unless they are the same object
-
- // a little difference means not equal
- t1 = new KerberosTicket(ASN1, CLIENT, SERVER, PASS, 1, FORWARDABLE, D0, D0, D0, D0, null);
- t2 = new KerberosTicket("asn11".getBytes(), CLIENT, SERVER, PASS, 1, FORWARDABLE, D0, D0, D0, D0, null);
- checkNotSame(t1, t2); // Different ASN1 encoding
-
- t2 = new KerberosTicket(ASN1, new KerberosPrincipal("client1"), SERVER, PASS, 1, FORWARDABLE, D0, D0, D0, D0, null);
- checkNotSame(t1, t2); // Different client
-
- t2 = new KerberosTicket(ASN1, CLIENT, new KerberosPrincipal("server1"), PASS, 1, FORWARDABLE, D0, D0, D0, D0, null);
- checkNotSame(t1, t2); // Different server
-
- t2 = new KerberosTicket(ASN1, CLIENT, SERVER, "pass1".getBytes(), 1, FORWARDABLE, D0, D0, D0, D0, null);
- checkNotSame(t1, t2); // Different session key
-
- t2 = new KerberosTicket(ASN1, CLIENT, SERVER, PASS, 2, FORWARDABLE, D0, D0, D0, D0, null);
- checkNotSame(t1, t2); // Different key type
-
- t2 = new KerberosTicket(ASN1, CLIENT, SERVER, PASS, 1, new boolean[] {true, false}, D0, D0, D0, D0, null);
- checkNotSame(t1, t2); // Different flags, not FORWARDABLE
-
- t2 = new KerberosTicket(ASN1, CLIENT, SERVER, PASS, 1, FORWARDABLE, new Date(1), D0, D0, D0, null);
- checkNotSame(t1, t2); // Different authtime
-
- t2 = new KerberosTicket(ASN1, CLIENT, SERVER, PASS, 1, FORWARDABLE, D0, new Date(1), D0, D0, null);
- checkNotSame(t1, t2); // Different starttime
-
- t2 = new KerberosTicket(ASN1, CLIENT, SERVER, PASS, 1, FORWARDABLE, D0, D0, new Date(1), D0, null);
- checkNotSame(t1, t2); // Different endtime
-
- t2 = new KerberosTicket(ASN1, CLIENT, SERVER, PASS, 1, FORWARDABLE, D0, D0, D0, D0, new InetAddress[2]);
- checkNotSame(t1, t2); // Different client addresses
-
- t2 = new KerberosTicket(ASN1, CLIENT, SERVER, PASS, 1, FORWARDABLE, D0, D0, D0, new Date(1), null);
- t1 = new KerberosTicket(ASN1, CLIENT, SERVER, PASS, 1, FORWARDABLE, D0, D0, D0, new Date(2), null);
- checkSame(t1, t2); // renewtill is ignored when RENEWABLE ticket flag is not set.
-
- t2 = new KerberosTicket(ASN1, CLIENT, SERVER, PASS, 1, ALLTRUE, D0, D0, D0, new Date(1), null);
- t1 = new KerberosTicket(ASN1, CLIENT, SERVER, PASS, 1, ALLTRUE, D0, D0, D0, new Date(2), null);
- checkNotSame(t1, t2); // renewtill is used when RENEWABLE is set.
-
- checkNotSame(t1, "Another Object");
- System.out.println("Good!");
- }
-}
diff --git a/jdk/test/sun/security/krb5/auto/NewInquireTypes.java b/jdk/test/sun/security/krb5/auto/NewInquireTypes.java
new file mode 100644
index 00000000000..0a922468b62
--- /dev/null
+++ b/jdk/test/sun/security/krb5/auto/NewInquireTypes.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8043071
+ * @summary Expose session key and KRB_CRED through extended GSS-API
+ * @compile -XDignore.symbol.file NewInquireTypes.java
+ * @run main/othervm NewInquireTypes
+ */
+
+import com.sun.security.jgss.InquireType;
+import sun.security.jgss.GSSUtil;
+import sun.security.krb5.internal.KRBCred;
+import sun.security.krb5.internal.crypto.KeyUsage;
+
+import javax.security.auth.kerberos.KerberosCredMessage;
+import javax.security.auth.kerberos.EncryptionKey;
+
+public class NewInquireTypes {
+
+ public static void main(String[] args) throws Exception {
+
+ new OneKDC(null).writeJAASConf();
+
+ Context c, s;
+ c = Context.fromJAAS("client");
+ s = Context.fromJAAS("server");
+
+ c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+ s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+
+ Context.handshake(c, s);
+
+ EncryptionKey key = (EncryptionKey)
+ c.x().inquireSecContext(InquireType.KRB5_GET_SESSION_KEY_EX);
+ KerberosCredMessage cred = (KerberosCredMessage)
+ c.x().inquireSecContext(InquireType.KRB5_GET_KRB_CRED);
+
+ // Confirm the KRB_CRED message is encrypted with the session key.
+ new KRBCred(cred.getEncoded()).encPart.decrypt(
+ new sun.security.krb5.EncryptionKey(key.getKeyType(), key.getEncoded()),
+ KeyUsage.KU_ENC_KRB_CRED_PART);
+ }
+}