6659990: KerberosTicket.getEndTime does not copy date (findbugs)
authorvaleriep
Fri, 25 Apr 2008 15:24:48 -0700
changeset 488 5e84e13e8892
parent 487 df198b4170f7
child 489 c5483d665a05
6659990: KerberosTicket.getEndTime does not copy date (findbugs) Reviewed-by: mullan
jdk/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java
jdk/test/javax/security/auth/kerberos/KerberosTixDateTest.java
--- a/jdk/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java	Fri Apr 25 15:19:55 2008 -0700
+++ b/jdk/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java	Fri Apr 25 15:24:48 2008 -0700
@@ -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 @@
                          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 @@
                                               + " 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 @@
                 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 @@
      *         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 @@
      *         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 @@
      * @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 @@
      * @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 @@
 
         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);
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/kerberos/KerberosTixDateTest.java	Fri Apr 25 15:24:48 2008 -0700
@@ -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");
+    }
+}