1 /*
2  * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /*
25  * @test
26  * @bug 6659990 8147772
27  * @summary test the immutability of the Date fields in KerberosTicket class,
28  *          serialization, and behavior after being destroyed.
29  * @ignore Must set up KDC and setup Kerberos configuration file
30  */
31 
32 import java.lang.reflect.InvocationTargetException;
33 import java.lang.reflect.Method;
34 import java.lang.reflect.Modifier;
35 import java.util.Date;
36 import java.io.*;
37 import javax.security.auth.RefreshFailedException;
38 import javax.security.auth.kerberos.KerberosPrincipal;
39 import javax.security.auth.kerberos.KerberosTicket;
40 import java.util.Base64;
41 
42 public class KerberosTixDateTest {
43 
44     // Serialized KerberosTicket from JDK6 (encoded in BASE64)
45     // Note: the KerberosTicket object is created using the same values as
46     // the KerberosTicket 't' in main(). Deserialization should succeed
47     // and the deserialized object should equal to 't'.
48     static String serializedKerberosTix =
49 "rO0ABXNyACtqYXZheC5zZWN1cml0eS5hdXRoLmtlcmJlcm9zLktlcmJlcm9zVGlja2V0ZqGBbXB3" +
50 "w7sCAApbAAxhc24xRW5jb2Rpbmd0AAJbQkwACGF1dGhUaW1ldAAQTGphdmEvdXRpbC9EYXRlO0wA" +
51 "BmNsaWVudHQAMExqYXZheC9zZWN1cml0eS9hdXRoL2tlcmJlcm9zL0tlcmJlcm9zUHJpbmNpcGFs" +
52 "O1sAD2NsaWVudEFkZHJlc3Nlc3QAF1tMamF2YS9uZXQvSW5ldEFkZHJlc3M7TAAHZW5kVGltZXEA" +
53 "fgACWwAFZmxhZ3N0AAJbWkwACXJlbmV3VGlsbHEAfgACTAAGc2VydmVycQB+AANMAApzZXNzaW9u" +
54 "S2V5dAAmTGphdmF4L3NlY3VyaXR5L2F1dGgva2VyYmVyb3MvS2V5SW1wbDtMAAlzdGFydFRpbWVx" +
55 "AH4AAnhwdXIAAltCrPMX+AYIVOACAAB4cAAAAARhc24xc3IADmphdmEudXRpbC5EYXRlaGqBAUtZ" +
56 "dBkDAAB4cHcIAAAAAAC8YU54c3IALmphdmF4LnNlY3VyaXR5LmF1dGgua2VyYmVyb3MuS2VyYmVy" +
57 "b3NQcmluY2lwYWyZp31dDx4zKQMAAHhwdXEAfgAIAAAAEzARoAMCAQGhCjAIGwZjbGllbnR1cQB+" +
58 "AAgAAAAVGxNKTEFCUy5TRkJBWS5TVU4uQ09NeHBxAH4AC3VyAAJbWlePIDkUuF3iAgAAeHAAAAAg" +
59 "AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxAH4AC3NxAH4ADHVxAH4ACAAAABMwEaAD" +
60 "AgEBoQowCBsGc2VydmVydXEAfgAIAAAAFRsTSkxBQlMuU0ZCQVkuU1VOLkNPTXhzcgAkamF2YXgu" +
61 "c2VjdXJpdHkuYXV0aC5rZXJiZXJvcy5LZXlJbXBskoOG6DyvS9cDAAB4cHVxAH4ACAAAABUwE6AD" +
62         "AgEBoQwECnNlc3Npb25LZXl4cQB+AAs=";
63 
main(String[] args)64     public static void main(String[] args) throws Exception {
65         byte[] asn1Bytes = "asn1".getBytes();
66         KerberosPrincipal client = new KerberosPrincipal("client");
67         KerberosPrincipal server = new KerberosPrincipal("server");
68         byte[] keyBytes = "sessionKey".getBytes();
69         long originalTime = 12345678L;
70         Date inDate = new Date(originalTime);
71         boolean[] flags = new boolean[9];
72         flags[8] = true; // renewable
73         KerberosTicket t = new KerberosTicket(asn1Bytes, client, server,
74                 keyBytes, 1 /*keyType*/, flags, inDate /*authTime*/,
75                 inDate /*startTime*/, inDate /*endTime*/,
76                 inDate /*renewTill*/, null /*clientAddresses*/);
77         inDate.setTime(0); // for testing the constructor
78 
79         testDateImmutability(t, originalTime);
80         testS11nCompatibility(t); // S11n: Serialization
81         testDestroy(t);
82     }
83 
checkTime(KerberosTicket kt, long timeValue)84     private static void checkTime(KerberosTicket kt, long timeValue) {
85         if (kt.getAuthTime().getTime() != timeValue) {
86             throw new RuntimeException("authTime check fails!");
87         }
88         if (kt.getStartTime().getTime() != timeValue) {
89             throw new RuntimeException("startTime check fails!");
90         }
91         if (kt.getEndTime().getTime() != timeValue) {
92             throw new RuntimeException("endTime check fails!");
93         }
94         if (kt.getRenewTill().getTime() != timeValue) {
95             throw new RuntimeException("renewTill check fails!");
96         }
97     }
98 
testDateImmutability(KerberosTicket t, long origTime)99     private static void testDateImmutability(KerberosTicket t, long origTime)
100         throws Exception {
101         // test the constructor
102         System.out.println("Testing constructor...");
103         checkTime(t, origTime);
104 
105         // test the getAuth/Start/EndTime() & getRenewTill() methods
106         System.out.println("Testing getAuth/Start/EndTime() & getRenewTill()...");
107         t.getAuthTime().setTime(0);
108         t.getStartTime().setTime(0);
109         t.getEndTime().setTime(0);
110         t.getRenewTill().setTime(0);
111         checkTime(t, origTime);
112 
113         System.out.println("DateImmutability Test Passed");
114     }
115 
checkEqualsAndHashCode(byte[] bytes, KerberosTicket t)116     private static void checkEqualsAndHashCode(byte[] bytes, KerberosTicket t)
117         throws IOException, ClassNotFoundException {
118         ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
119         KerberosTicket deserializedTicket = (KerberosTicket)
120                 (new ObjectInputStream(bais).readObject());
121         if (!deserializedTicket.equals(t)) {
122             throw new RuntimeException("equals() check fails!");
123         }
124         if (deserializedTicket.hashCode() != t.hashCode()) {
125             throw new RuntimeException("hashCode() check fails!");
126         }
127     }
128 
testS11nCompatibility(KerberosTicket t)129     private static void testS11nCompatibility(KerberosTicket t)
130         throws Exception {
131 
132         System.out.println("Testing against KerberosTicket from JDK6...");
133         byte[] serializedBytes =
134             Base64.getMimeDecoder().decode(serializedKerberosTix);
135         checkEqualsAndHashCode(serializedBytes, t);
136 
137         System.out.println("Testing against KerberosTicket from current rel...");
138         ByteArrayOutputStream baos = new ByteArrayOutputStream();
139         new ObjectOutputStream(baos).writeObject(t);
140         checkEqualsAndHashCode(baos.toByteArray(), t);
141 
142         System.out.println("S11nCompatibility Test Passed");
143     }
144 
testDestroy(KerberosTicket t)145     private static void testDestroy(KerberosTicket t) throws Exception {
146         t.destroy();
147         if (!t.isDestroyed()) {
148             throw new RuntimeException("ticket should have been destroyed");
149         }
150         // Although these methods are meaningless, they can be called
151         for (Method m: KerberosTicket.class.getDeclaredMethods()) {
152             if (Modifier.isPublic(m.getModifiers())
153                     && m.getParameterCount() == 0) {
154                 System.out.println("Testing " + m.getName() + "...");
155                 try {
156                     m.invoke(t);
157                 } catch (InvocationTargetException e) {
158                     Throwable cause = e.getCause();
159                     if (cause instanceof RefreshFailedException ||
160                             cause instanceof IllegalStateException) {
161                         // this is OK
162                     } else {
163                         throw e;
164                     }
165                 }
166             }
167         }
168         System.out.println("Destroy Test Passed");
169     }
170 }
171