diff --git a/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java b/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java index 394634249843c6f97a01080fc867126ab44a54c4..62ff07d31cccff2939fa0fc98f5a36ac49463ba9 100644 --- a/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java +++ b/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2008 Sun Microsystems, Inc. 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 @@ -253,7 +253,24 @@ 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"); + init(asn1Encoding, client, server, + new KeyImpl(sessionKey, keyType), flags, authTime, + startTime, endTime, renewTill, clientAddresses); + } + private void init(byte[] asn1Encoding, + KerberosPrincipal client, + KerberosPrincipal server, + KeyImpl sessionKey, + boolean[] flags, + Date authTime, + Date startTime, + Date endTime, + Date renewTill, + InetAddress[] clientAddresses) { if (asn1Encoding == null) throw new IllegalArgumentException("ASN.1 encoding of ticket" + " cannot be null"); @@ -269,10 +286,8 @@ public class KerberosTicket implements Destroyable, Refreshable, + " cannot be null"); this.server = server; - if (sessionKey == null) - throw new IllegalArgumentException("Session key for ticket" - + " cannot be null"); - this.sessionKey = new KeyImpl(sessionKey, keyType); + // Caller needs to make sure `sessionKey` will not be null + this.sessionKey = sessionKey; if (flags != null) { if (flags.length >= NUM_FLAGS) @@ -291,17 +306,22 @@ public class KerberosTicket implements Destroyable, Refreshable, throw new IllegalArgumentException("The renewable period " + "end time cannot be null for renewable tickets."); - this.renewTill = renewTill; + this.renewTill = new Date(renewTill.getTime()); } - this.authTime = authTime; - - this.startTime = (startTime != null? startTime: authTime); + if (authTime != null) { + this.authTime = new Date(authTime.getTime()); + } + if (startTime != null) { + this.startTime = new Date(startTime.getTime()); + } else { + this.startTime = this.authTime; + } if (endTime == null) throw new IllegalArgumentException("End time for ticket validity" + " cannot be null"); - this.endTime = endTime; + this.endTime = new Date(endTime.getTime()); if (clientAddresses != null) this.clientAddresses = clientAddresses.clone(); @@ -440,7 +460,7 @@ public class KerberosTicket implements Destroyable, Refreshable, * or null if not set. */ public final java.util.Date getAuthTime() { - return (authTime == null) ? null : new Date(authTime.getTime()); + return (authTime == null) ? null : (Date)authTime.clone(); } /** @@ -450,7 +470,7 @@ public class KerberosTicket implements Destroyable, Refreshable, * or null if not set. */ public final java.util.Date getStartTime() { - return (startTime == null) ? null : new Date(startTime.getTime()); + return (startTime == null) ? null : (Date)startTime.clone(); } /** @@ -459,7 +479,7 @@ public class KerberosTicket implements Destroyable, Refreshable, * @return the expiration time for this ticket's validity period. */ public final java.util.Date getEndTime() { - return endTime; + return (Date) endTime.clone(); } /** @@ -469,7 +489,7 @@ public class KerberosTicket implements Destroyable, Refreshable, * @return the latest expiration time for this ticket. */ public final java.util.Date getRenewTill() { - return (renewTill == null) ? null: new Date(renewTill.getTime()); + return (renewTill == null) ? null: (Date)renewTill.clone(); } /** @@ -745,4 +765,20 @@ public class KerberosTicket implements Destroyable, Refreshable, return true; } + + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException { + s.defaultReadObject(); + if (sessionKey == null) { + throw new InvalidObjectException("Session key cannot be null"); + } + try { + init(asn1Encoding, client, server, sessionKey, + flags, authTime, startTime, endTime, + renewTill, clientAddresses); + } catch (IllegalArgumentException iae) { + throw (InvalidObjectException) + new InvalidObjectException(iae.getMessage()).initCause(iae); + } + } } diff --git a/test/javax/security/auth/kerberos/KerberosTixDateTest.java b/test/javax/security/auth/kerberos/KerberosTixDateTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2e4ebdef27c6bc9154a8c2aa764266c554889bc7 --- /dev/null +++ b/test/javax/security/auth/kerberos/KerberosTixDateTest.java @@ -0,0 +1,139 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6659990 + * @summary test the immutability of the Date fields in KerberosTicket class. + */ + +import java.net.InetAddress; +import java.util.Date; +import java.io.*; +import javax.security.auth.kerberos.KerberosKey; +import javax.security.auth.kerberos.KerberosPrincipal; +import javax.security.auth.kerberos.KerberosTicket; +import sun.misc.BASE64Decoder; + +public class KerberosTixDateTest { + + // Serialized KerberosTicket from JDK6 (encoded in BASE64) + // Note: the KerberosTicket object is created using the same values as + // the KerberosTicket 't' in main(). Deserialization should succeed + // and the deserialized object should equal to 't'. + static String serializedKerberosTix = +"rO0ABXNyACtqYXZheC5zZWN1cml0eS5hdXRoLmtlcmJlcm9zLktlcmJlcm9zVGlja2V0ZqGBbXB3" + +"w7sCAApbAAxhc24xRW5jb2Rpbmd0AAJbQkwACGF1dGhUaW1ldAAQTGphdmEvdXRpbC9EYXRlO0wA" + +"BmNsaWVudHQAMExqYXZheC9zZWN1cml0eS9hdXRoL2tlcmJlcm9zL0tlcmJlcm9zUHJpbmNpcGFs" + +"O1sAD2NsaWVudEFkZHJlc3Nlc3QAF1tMamF2YS9uZXQvSW5ldEFkZHJlc3M7TAAHZW5kVGltZXEA" + +"fgACWwAFZmxhZ3N0AAJbWkwACXJlbmV3VGlsbHEAfgACTAAGc2VydmVycQB+AANMAApzZXNzaW9u" + +"S2V5dAAmTGphdmF4L3NlY3VyaXR5L2F1dGgva2VyYmVyb3MvS2V5SW1wbDtMAAlzdGFydFRpbWVx" + +"AH4AAnhwdXIAAltCrPMX+AYIVOACAAB4cAAAAARhc24xc3IADmphdmEudXRpbC5EYXRlaGqBAUtZ" + +"dBkDAAB4cHcIAAAAAAC8YU54c3IALmphdmF4LnNlY3VyaXR5LmF1dGgua2VyYmVyb3MuS2VyYmVy" + +"b3NQcmluY2lwYWyZp31dDx4zKQMAAHhwdXEAfgAIAAAAEzARoAMCAQGhCjAIGwZjbGllbnR1cQB+" + +"AAgAAAAVGxNKTEFCUy5TRkJBWS5TVU4uQ09NeHBxAH4AC3VyAAJbWlePIDkUuF3iAgAAeHAAAAAg" + +"AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxAH4AC3NxAH4ADHVxAH4ACAAAABMwEaAD" + +"AgEBoQowCBsGc2VydmVydXEAfgAIAAAAFRsTSkxBQlMuU0ZCQVkuU1VOLkNPTXhzcgAkamF2YXgu" + +"c2VjdXJpdHkuYXV0aC5rZXJiZXJvcy5LZXlJbXBskoOG6DyvS9cDAAB4cHVxAH4ACAAAABUwE6AD" + + "AgEBoQwECnNlc3Npb25LZXl4cQB+AAs="; + + public static void main(String[] args) throws Exception { + byte[] asn1Bytes = "asn1".getBytes(); + KerberosPrincipal client = new KerberosPrincipal("client"); + KerberosPrincipal server = new KerberosPrincipal("server"); + byte[] keyBytes = "sessionKey".getBytes(); + long originalTime = 12345678L; + Date inDate = new Date(originalTime); + boolean[] flags = new boolean[9]; + flags[8] = true; // renewable + KerberosTicket t = new KerberosTicket(asn1Bytes, client, server, + keyBytes, 1 /*keyType*/, flags, inDate /*authTime*/, + inDate /*startTime*/, inDate /*endTime*/, + inDate /*renewTill*/, null /*clientAddresses*/); + inDate.setTime(0); // for testing the constructor + + testDateImmutability(t, originalTime); + testS11nCompatibility(t); // S11n: Serialization + } + + private static void checkTime(KerberosTicket kt, long timeValue) { + if (kt.getAuthTime().getTime() != timeValue) { + throw new RuntimeException("authTime check fails!"); + } + if (kt.getStartTime().getTime() != timeValue) { + throw new RuntimeException("startTime check fails!"); + } + if (kt.getEndTime().getTime() != timeValue) { + throw new RuntimeException("endTime check fails!"); + } + if (kt.getRenewTill().getTime() != timeValue) { + throw new RuntimeException("renewTill check fails!"); + } + } + + private static void testDateImmutability(KerberosTicket t, long origTime) + throws Exception { + // test the constructor + System.out.println("Testing constructor..."); + checkTime(t, origTime); + + // test the getAuth/Start/EndTime() & getRenewTill() methods + System.out.println("Testing getAuth/Start/EndTime() & getRenewTill()..."); + t.getAuthTime().setTime(0); + t.getStartTime().setTime(0); + t.getEndTime().setTime(0); + t.getRenewTill().setTime(0); + checkTime(t, origTime); + + System.out.println("DateImmutability Test Passed"); + } + + private static void checkEqualsAndHashCode(byte[] bytes, KerberosTicket t) + throws IOException, ClassNotFoundException { + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + KerberosTicket deserializedTicket = (KerberosTicket) + (new ObjectInputStream(bais).readObject()); + if (!deserializedTicket.equals(t)) { + throw new RuntimeException("equals() check fails!"); + } + if (deserializedTicket.hashCode() != t.hashCode()) { + throw new RuntimeException("hashCode() check fails!"); + } + } + + private static void testS11nCompatibility(KerberosTicket t) + throws Exception { + + System.out.println("Testing against KerberosTicket from JDK6..."); + byte[] serializedBytes = + new BASE64Decoder().decodeBuffer(serializedKerberosTix); + checkEqualsAndHashCode(serializedBytes, t); + + System.out.println("Testing against KerberosTicket from current rel..."); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new ObjectOutputStream(baos).writeObject(t); + checkEqualsAndHashCode(baos.toByteArray(), t); + + System.out.println("S11nCompatibility Test Passed"); + } +}