diff --git a/src/share/classes/sun/security/krb5/internal/KerberosTime.java b/src/share/classes/sun/security/krb5/internal/KerberosTime.java index 5288d58632d6f7be89fedcddc7a448308565a272..d524a2d1991df3bd8d58a306a33c8b6171e9e2a4 100644 --- a/src/share/classes/sun/security/krb5/internal/KerberosTime.java +++ b/src/share/classes/sun/security/krb5/internal/KerberosTime.java @@ -57,11 +57,20 @@ import java.io.IOException; * specification available at * * http://www.ietf.org/rfc/rfc4120.txt. + * + * The implementation also includes the microseconds info so that the + * same class can be used as a precise timestamp in Authenticator etc. */ public class KerberosTime implements Cloneable { private long kerberosTime; // milliseconds since epoch, a Date.getTime() value + private int microSeconds; // the last three digits of the microsecond value + + // The time when this class is loaded. Used in setNow() + private static final long initMilli = System.currentTimeMillis(); + private static final long initMicro = System.nanoTime() / 1000; + private static long syncTime; private static boolean DEBUG = Krb5.DEBUG; @@ -77,9 +86,13 @@ public class KerberosTime implements Cloneable { kerberosTime = time; } + private KerberosTime(long time, int micro) { + kerberosTime = time; + microSeconds = micro; + } public Object clone() { - return new KerberosTime(kerberosTime); + return new KerberosTime(kerberosTime, microSeconds); } // This constructor is used in the native code @@ -109,8 +122,8 @@ public class KerberosTime implements Cloneable { // | | | | | | | // 0 4 6 8 | | | // 10 | | - // 12 | - // 14 + // 12 | + // 14 if (time.length() != 15) throw new Asn1Exception(Krb5.ASN1_BAD_TIMEFORMAT); @@ -148,11 +161,8 @@ public class KerberosTime implements Cloneable { public KerberosTime(boolean initToNow) { if (initToNow) { - Date temp = new Date(); - setTime(temp); + setNow(); } - else - kerberosTime = 0; } /** @@ -192,10 +202,12 @@ public class KerberosTime implements Cloneable { public void setTime(Date time) { kerberosTime = time.getTime(); // (time.getTimezoneOffset() * 60000L); + microSeconds = 0; } public void setTime(long time) { kerberosTime = time; + microSeconds = 0; } public Date toDate() { @@ -205,16 +217,18 @@ public class KerberosTime implements Cloneable { } public void setNow() { - Date temp = new Date(); - setTime(temp); + long microElapsed = System.nanoTime() / 1000 - initMicro; + setTime(initMilli + microElapsed/1000); + microSeconds = (int)(microElapsed % 1000); } public int getMicroSeconds() { Long temp_long = new Long((kerberosTime % 1000L) * 1000L); - return temp_long.intValue(); + return temp_long.intValue() + microSeconds; } public void setMicroSeconds(int usec) { + microSeconds = usec % 1000; Integer temp_int = new Integer(usec); long temp_long = temp_int.longValue() / 1000L; kerberosTime = kerberosTime - (kerberosTime % 1000L) + temp_long; @@ -222,6 +236,7 @@ public class KerberosTime implements Cloneable { public void setMicroSeconds(Integer usec) { if (usec != null) { + microSeconds = usec.intValue() % 1000; long temp_long = usec.longValue() / 1000L; kerberosTime = kerberosTime - (kerberosTime % 1000L) + temp_long; } @@ -262,7 +277,9 @@ public class KerberosTime implements Cloneable { } public boolean greaterThan(KerberosTime time) { - return kerberosTime > time.kerberosTime; + return kerberosTime > time.kerberosTime || + kerberosTime == time.kerberosTime && + microSeconds > time.microSeconds; } public boolean equals(Object obj) { @@ -274,15 +291,17 @@ public class KerberosTime implements Cloneable { return false; } - return kerberosTime == ((KerberosTime)obj).kerberosTime; + return kerberosTime == ((KerberosTime)obj).kerberosTime && + microSeconds == ((KerberosTime)obj).microSeconds; } public int hashCode() { - return 37 * 17 + (int)(kerberosTime ^ (kerberosTime >>> 32)); + int result = 37 * 17 + (int)(kerberosTime ^ (kerberosTime >>> 32)); + return result * 17 + microSeconds; } public boolean isZero() { - return kerberosTime == 0; + return kerberosTime == 0 && microSeconds == 0; } public int getSeconds() { diff --git a/test/sun/security/krb5/MicroTime.java b/test/sun/security/krb5/MicroTime.java new file mode 100644 index 0000000000000000000000000000000000000000..db8aeac01475f5e13f997d4c5639e500aded9875 --- /dev/null +++ b/test/sun/security/krb5/MicroTime.java @@ -0,0 +1,53 @@ +/* + * Copyright 2010 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 6882687 + * @summary KerberosTime too imprecise + */ + +import sun.security.krb5.internal.KerberosTime; + +public class MicroTime { + public static void main(String[] args) throws Exception { + // We count how many different KerberosTime values + // can be acquired within one second. + KerberosTime t1 = new KerberosTime(true); + KerberosTime last = t1; + int count = 0; + while (true) { + KerberosTime t2 = new KerberosTime(true); + if (t2.getTime() - t1.getTime() > 1000) break; + if (!last.equals(t2)) { + last = t2; + count++; + } + } + // We believe a nice KerberosTime can at least tell the + // difference of 100 musec. + if (count < 10000) { + throw new Exception("What? only " + (1000000/count) + + " musec precision?"); + } + } +}