jdk/src/share/classes/sun/security/krb5/internal/KerberosTime.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
child 5615 3d77087a5a6c
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     3  *
       
     4  * This code is free software; you can redistribute it and/or modify it
       
     5  * under the terms of the GNU General Public License version 2 only, as
       
     6  * published by the Free Software Foundation.  Sun designates this
       
     7  * particular file as subject to the "Classpath" exception as provided
       
     8  * by Sun in the LICENSE file that accompanied this code.
       
     9  *
       
    10  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    13  * version 2 for more details (a copy is included in the LICENSE file that
       
    14  * accompanied this code).
       
    15  *
       
    16  * You should have received a copy of the GNU General Public License version
       
    17  * 2 along with this work; if not, write to the Free Software Foundation,
       
    18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    19  *
       
    20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    21  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    22  * have any questions.
       
    23  */
       
    24 
       
    25 /*
       
    26  *
       
    27  *  (C) Copyright IBM Corp. 1999 All Rights Reserved.
       
    28  *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
       
    29  */
       
    30 
       
    31 package sun.security.krb5.internal;
       
    32 
       
    33 import java.util.TimeZone;
       
    34 import sun.security.util.*;
       
    35 import sun.security.krb5.Config;
       
    36 import sun.security.krb5.KrbException;
       
    37 import sun.security.krb5.Asn1Exception;
       
    38 import java.util.Date;
       
    39 import java.util.GregorianCalendar;
       
    40 import java.util.Calendar;
       
    41 import java.io.IOException;
       
    42 
       
    43 /**
       
    44  * Implements the ASN.1 KerberosTime type.
       
    45  *
       
    46  * <xmp>
       
    47  * KerberosTime    ::= GeneralizedTime -- with no fractional seconds
       
    48  * </xmp>
       
    49  *
       
    50  * The timestamps used in Kerberos are encoded as GeneralizedTimes. A
       
    51  * KerberosTime value shall not include any fractional portions of the
       
    52  * seconds.  As required by the DER, it further shall not include any
       
    53  * separators, and it shall specify the UTC time zone (Z).
       
    54  *
       
    55  * <p>
       
    56  * This definition reflects the Network Working Group RFC 4120
       
    57  * specification available at
       
    58  * <a href="http://www.ietf.org/rfc/rfc4120.txt">
       
    59  * http://www.ietf.org/rfc/rfc4120.txt</a>.
       
    60  */
       
    61 
       
    62 public class KerberosTime implements Cloneable {
       
    63 
       
    64     private long kerberosTime; // milliseconds since epoch, a Date.getTime() value
       
    65     private static long syncTime;
       
    66     private static boolean DEBUG = Krb5.DEBUG;
       
    67 
       
    68     public static final boolean NOW = true;
       
    69     public static final boolean UNADJUSTED_NOW = false;
       
    70 
       
    71     //defaults to zero instead of now; use setNow() for current time
       
    72     public KerberosTime() {
       
    73         kerberosTime = 0;
       
    74     }
       
    75 
       
    76     public KerberosTime(long time) {
       
    77         kerberosTime = time;
       
    78     }
       
    79 
       
    80 
       
    81     public Object clone() {
       
    82         return new KerberosTime(kerberosTime);
       
    83     }
       
    84 
       
    85     // This constructor is used in the native code
       
    86     // src/windows/native/sun/security/krb5/NativeCreds.c
       
    87     public KerberosTime(String time) throws Asn1Exception {
       
    88         kerberosTime = toKerberosTime(time);
       
    89     }
       
    90 
       
    91     /**
       
    92      * Constructs a KerberosTime object.
       
    93      * @param encoding a DER-encoded data.
       
    94      * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
       
    95      * @exception IOException if an I/O error occurs while reading encoded data.
       
    96      */
       
    97     public KerberosTime(DerValue encoding) throws Asn1Exception, IOException {
       
    98         GregorianCalendar calendar = new GregorianCalendar();
       
    99         Date temp = encoding.getGeneralizedTime();
       
   100         kerberosTime = temp.getTime();
       
   101     }
       
   102 
       
   103     private static long toKerberosTime(String time) throws Asn1Exception {
       
   104         // this method only used by KerberosTime class.
       
   105 
       
   106         // ASN.1 GeneralizedTime format:
       
   107 
       
   108         // "19700101000000Z"
       
   109         //  |   | | | | | |
       
   110         //  0   4 6 8 | | |
       
   111         //           10 | |
       
   112         //                         12 |
       
   113         //                           14
       
   114 
       
   115         if (time.length() != 15)
       
   116             throw new Asn1Exception(Krb5.ASN1_BAD_TIMEFORMAT);
       
   117         if (time.charAt(14) != 'Z')
       
   118             throw new Asn1Exception(Krb5.ASN1_BAD_TIMEFORMAT);
       
   119         int year = Integer.parseInt(time.substring(0, 4));
       
   120         Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
       
   121         calendar.clear(); // so that millisecond is zero
       
   122         calendar.set(year,
       
   123                      Integer.parseInt(time.substring(4, 6)) - 1,
       
   124                      Integer.parseInt(time.substring(6, 8)),
       
   125                      Integer.parseInt(time.substring(8, 10)),
       
   126                      Integer.parseInt(time.substring(10, 12)),
       
   127                      Integer.parseInt(time.substring(12, 14)));
       
   128 
       
   129         //The Date constructor assumes the setting are local relative
       
   130         //and converts the time to UTC before storing it.  Since we
       
   131         //want the internal representation to correspond to local
       
   132         //and not UTC time we subtract the UTC time offset.
       
   133         return (calendar.getTime().getTime());
       
   134 
       
   135     }
       
   136 
       
   137     // should be moved to sun.security.krb5.util class
       
   138     public static String zeroPad(String s, int length) {
       
   139         StringBuffer temp = new StringBuffer(s);
       
   140         while (temp.length() < length)
       
   141             temp.insert(0, '0');
       
   142         return temp.toString();
       
   143     }
       
   144 
       
   145     public KerberosTime(Date time) {
       
   146         kerberosTime = time.getTime(); // (time.getTimezoneOffset() * 60000L);
       
   147     }
       
   148 
       
   149     public KerberosTime(boolean initToNow) {
       
   150         if (initToNow) {
       
   151             Date temp = new Date();
       
   152             setTime(temp);
       
   153         }
       
   154         else
       
   155             kerberosTime = 0;
       
   156     }
       
   157 
       
   158     /**
       
   159      * Returns a string representation of KerberosTime object.
       
   160      * @return a string representation of this object.
       
   161      */
       
   162     public String toGeneralizedTimeString() {
       
   163         Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
       
   164         calendar.clear();
       
   165 
       
   166         calendar.setTimeInMillis(kerberosTime);
       
   167         return zeroPad(Integer.toString(calendar.get(Calendar.YEAR)), 4) +
       
   168             zeroPad(Integer.toString(calendar.get(Calendar.MONTH) + 1), 2) +
       
   169             zeroPad(Integer.toString(calendar.get(Calendar.DAY_OF_MONTH)), 2) +
       
   170             zeroPad(Integer.toString(calendar.get(Calendar.HOUR_OF_DAY)), 2) +
       
   171             zeroPad(Integer.toString(calendar.get(Calendar.MINUTE)), 2) +
       
   172             zeroPad(Integer.toString(calendar.get(Calendar.SECOND)), 2) + 'Z';
       
   173 
       
   174     }
       
   175 
       
   176     /**
       
   177      * Encodes this object to a byte array.
       
   178      * @return a byte array of encoded data.
       
   179      * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
       
   180      * @exception IOException if an I/O error occurs while reading encoded data.
       
   181      */
       
   182     public byte[] asn1Encode() throws Asn1Exception, IOException {
       
   183         DerOutputStream out = new DerOutputStream();
       
   184         out.putGeneralizedTime(this.toDate());
       
   185         return out.toByteArray();
       
   186     }
       
   187 
       
   188     public long getTime() {
       
   189         return kerberosTime;
       
   190     }
       
   191 
       
   192 
       
   193     public void setTime(Date time) {
       
   194         kerberosTime = time.getTime(); // (time.getTimezoneOffset() * 60000L);
       
   195     }
       
   196 
       
   197     public void setTime(long time) {
       
   198         kerberosTime = time;
       
   199     }
       
   200 
       
   201     public Date toDate() {
       
   202         Date temp = new Date(kerberosTime);
       
   203         temp.setTime(temp.getTime());
       
   204         return temp;
       
   205     }
       
   206 
       
   207     public void setNow() {
       
   208         Date temp = new Date();
       
   209         setTime(temp);
       
   210     }
       
   211 
       
   212     public int getMicroSeconds() {
       
   213         Long temp_long = new Long((kerberosTime % 1000L) * 1000L);
       
   214         return temp_long.intValue();
       
   215     }
       
   216 
       
   217     public void setMicroSeconds(int usec) {
       
   218         Integer temp_int = new Integer(usec);
       
   219         long temp_long = temp_int.longValue() / 1000L;
       
   220         kerberosTime = kerberosTime - (kerberosTime % 1000L) + temp_long;
       
   221     }
       
   222 
       
   223     public void setMicroSeconds(Integer usec) {
       
   224         if (usec != null) {
       
   225             long temp_long = usec.longValue() / 1000L;
       
   226             kerberosTime = kerberosTime - (kerberosTime % 1000L) + temp_long;
       
   227         }
       
   228     }
       
   229 
       
   230     public boolean inClockSkew(int clockSkew) {
       
   231         KerberosTime now = new KerberosTime(KerberosTime.NOW);
       
   232 
       
   233         if (java.lang.Math.abs(kerberosTime - now.kerberosTime) >
       
   234             clockSkew * 1000L)
       
   235             return false;
       
   236         return true;
       
   237     }
       
   238 
       
   239     public boolean inClockSkew() {
       
   240         return inClockSkew(getDefaultSkew());
       
   241     }
       
   242 
       
   243     public boolean inClockSkew(int clockSkew, KerberosTime now) {
       
   244         if (java.lang.Math.abs(kerberosTime - now.kerberosTime) >
       
   245             clockSkew * 1000L)
       
   246             return false;
       
   247         return true;
       
   248     }
       
   249 
       
   250     public boolean inClockSkew(KerberosTime time) {
       
   251         return inClockSkew(getDefaultSkew(), time);
       
   252     }
       
   253 
       
   254     public boolean greaterThanWRTClockSkew(KerberosTime time, int clockSkew) {
       
   255         if ((kerberosTime - time.kerberosTime) > clockSkew * 1000L)
       
   256             return true;
       
   257         return false;
       
   258     }
       
   259 
       
   260     public boolean greaterThanWRTClockSkew(KerberosTime time) {
       
   261         return greaterThanWRTClockSkew(time, getDefaultSkew());
       
   262     }
       
   263 
       
   264     public boolean greaterThan(KerberosTime time) {
       
   265         return kerberosTime > time.kerberosTime;
       
   266     }
       
   267 
       
   268     public boolean equals(Object obj) {
       
   269         if (this == obj) {
       
   270             return true;
       
   271         }
       
   272 
       
   273         if (!(obj instanceof KerberosTime)) {
       
   274             return false;
       
   275         }
       
   276 
       
   277         return kerberosTime == ((KerberosTime)obj).kerberosTime;
       
   278     }
       
   279 
       
   280     public int hashCode() {
       
   281         return 37 * 17 + (int)(kerberosTime ^ (kerberosTime >>> 32));
       
   282     }
       
   283 
       
   284     public boolean isZero() {
       
   285         return kerberosTime == 0;
       
   286     }
       
   287 
       
   288     public int getSeconds() {
       
   289         Long temp_long = new Long(kerberosTime / 1000L);
       
   290         return temp_long.intValue();
       
   291     }
       
   292 
       
   293     public void setSeconds(int sec) {
       
   294         Integer temp_int = new Integer(sec);
       
   295         kerberosTime = temp_int.longValue() * 1000L;
       
   296     }
       
   297 
       
   298     /**
       
   299      * Parse (unmarshal) a kerberostime from a DER input stream.  This form
       
   300      * parsing might be used when expanding a value which is part of
       
   301      * a constructed sequence and uses explicitly tagged type.
       
   302      *
       
   303      * @exception Asn1Exception on error.
       
   304      * @param data the Der input stream value, which contains one or more marshaled value.
       
   305      * @param explicitTag tag number.
       
   306      * @param optional indicates if this data field is optional
       
   307      * @return an instance of KerberosTime.
       
   308      *
       
   309      */
       
   310     public static KerberosTime parse(DerInputStream data, byte explicitTag, boolean optional) throws Asn1Exception, IOException {
       
   311         if ((optional) && (((byte)data.peekByte() & (byte)0x1F)!= explicitTag))
       
   312             return null;
       
   313         DerValue der = data.getDerValue();
       
   314         if (explicitTag != (der.getTag() & (byte)0x1F))  {
       
   315             throw new Asn1Exception(Krb5.ASN1_BAD_ID);
       
   316         }
       
   317         else {
       
   318             DerValue subDer = der.getData().getDerValue();
       
   319             return new KerberosTime(subDer);
       
   320         }
       
   321     }
       
   322 
       
   323     public static int getDefaultSkew() {
       
   324         int tdiff = Krb5.DEFAULT_ALLOWABLE_CLOCKSKEW;
       
   325         try {
       
   326             Config c = Config.getInstance();
       
   327             if ((tdiff = c.getDefaultIntValue("clockskew",
       
   328                                               "libdefaults")) == Integer.MIN_VALUE) {   //value is not defined
       
   329                 tdiff = Krb5.DEFAULT_ALLOWABLE_CLOCKSKEW;
       
   330             }
       
   331         } catch (KrbException e) {
       
   332             if (DEBUG) {
       
   333                 System.out.println("Exception in getting clockskew from " +
       
   334                                    "Configuration " +
       
   335                                    "using default value " +
       
   336                                    e.getMessage());
       
   337             }
       
   338         }
       
   339         return tdiff;
       
   340     }
       
   341 
       
   342     public String toString() {
       
   343         return toGeneralizedTimeString();
       
   344     }
       
   345 }