Home » openjdk-7 » javax.security » auth » kerberos » [javadoc | source]

    1   /*
    2    * Copyright (c) 2000, 2008, 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.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package javax.security.auth.kerberos;
   27   
   28   import java.io;
   29   import java.util.Date;
   30   import java.util.Arrays;
   31   import java.net.InetAddress;
   32   import javax.crypto.SecretKey;
   33   import javax.security.auth.Refreshable;
   34   import javax.security.auth.Destroyable;
   35   import javax.security.auth.RefreshFailedException;
   36   import javax.security.auth.DestroyFailedException;
   37   import sun.misc.HexDumpEncoder;
   38   import sun.security.krb5.EncryptionKey;
   39   import sun.security.krb5.Asn1Exception;
   40   import sun.security.util;
   41   
   42   /**
   43    * This class encapsulates a Kerberos ticket and associated
   44    * information as viewed from the client's point of view. It captures all
   45    * information that the Key Distribution Center (KDC) sends to the client
   46    * in the reply message KDC-REP defined in the Kerberos Protocol
   47    * Specification (<a href=http://www.ietf.org/rfc/rfc4120.txt>RFC 4120</a>).
   48    * <p>
   49    * All Kerberos JAAS login modules that authenticate a user to a KDC should
   50    * use this class. Where available, the login module might even read this
   51    * information from a ticket cache in the operating system instead of
   52    * directly communicating with the KDC. During the commit phase of the JAAS
   53    * authentication process, the JAAS login module should instantiate this
   54    * class and store the instance in the private credential set of a
   55    * {@link javax.security.auth.Subject Subject}.<p>
   56    *
   57    * It might be necessary for the application to be granted a
   58    * {@link javax.security.auth.PrivateCredentialPermission
   59    * PrivateCredentialPermission} if it needs to access a KerberosTicket
   60    * instance from a Subject. This permission is not needed when the
   61    * application depends on the default JGSS Kerberos mechanism to access the
   62    * KerberosTicket. In that case, however, the application will need an
   63    * appropriate
   64    * {@link javax.security.auth.kerberos.ServicePermission ServicePermission}.
   65    * <p>
   66    * Note that this class is applicable to both ticket granting tickets and
   67    * other regular service tickets. A ticket granting ticket is just a
   68    * special case of a more generalized service ticket.
   69    *
   70    * @see javax.security.auth.Subject
   71    * @see javax.security.auth.PrivateCredentialPermission
   72    * @see javax.security.auth.login.LoginContext
   73    * @see org.ietf.jgss.GSSCredential
   74    * @see org.ietf.jgss.GSSManager
   75    *
   76    * @author Mayank Upadhyay
   77    * @since 1.4
   78    */
   79   public class KerberosTicket implements Destroyable, Refreshable,
   80            java.io.Serializable {
   81   
   82       private static final long serialVersionUID = 7395334370157380539L;
   83   
   84       // XXX Make these flag indices public
   85       private static final int FORWARDABLE_TICKET_FLAG = 1;
   86       private static final int FORWARDED_TICKET_FLAG   = 2;
   87       private static final int PROXIABLE_TICKET_FLAG   = 3;
   88       private static final int PROXY_TICKET_FLAG       = 4;
   89       private static final int POSTDATED_TICKET_FLAG   = 6;
   90       private static final int RENEWABLE_TICKET_FLAG   = 8;
   91       private static final int INITIAL_TICKET_FLAG     = 9;
   92   
   93       private static final int NUM_FLAGS = 32;
   94   
   95       /**
   96        *
   97        * ASN.1 DER Encoding of the Ticket as defined in the
   98        * Kerberos Protocol Specification RFC4120.
   99        *
  100        * @serial
  101        */
  102   
  103       private byte[] asn1Encoding;
  104   
  105       /**
  106        *<code>KeyImpl</code> is serialized by writing out the ASN1 Encoded bytes
  107        * of the encryption key. The ASN1 encoding is defined in RFC4120 and as
  108        * follows:
  109        * <pre>
  110        * EncryptionKey   ::= SEQUENCE {
  111        *          keytype    [0] Int32 -- actually encryption type --,
  112        *          keyvalue   [1] OCTET STRING
  113        * }
  114        * </pre>
  115        *
  116        * @serial
  117        */
  118   
  119       private KeyImpl sessionKey;
  120   
  121       /**
  122        *
  123        * Ticket Flags as defined in the Kerberos Protocol Specification RFC4120.
  124        *
  125        * @serial
  126        */
  127   
  128       private boolean[] flags;
  129   
  130       /**
  131        *
  132        * Time of initial authentication
  133        *
  134        * @serial
  135        */
  136   
  137       private Date authTime;
  138   
  139       /**
  140        *
  141        * Time after which the ticket is valid.
  142        * @serial
  143        */
  144       private Date startTime;
  145   
  146       /**
  147        *
  148        * Time after which the ticket will not be honored. (its expiration time).
  149        *
  150        * @serial
  151        */
  152   
  153       private Date endTime;
  154   
  155       /**
  156        *
  157        * For renewable Tickets it indicates the maximum endtime that may be
  158        * included in a renewal. It can be thought of as the absolute expiration
  159        * time for the ticket, including all renewals. This field may be null
  160        * for tickets that are not renewable.
  161        *
  162        * @serial
  163        */
  164   
  165       private Date renewTill;
  166   
  167       /**
  168        *
  169        * Client that owns the service ticket
  170        *
  171        * @serial
  172        */
  173   
  174       private KerberosPrincipal client;
  175   
  176       /**
  177        *
  178        * The service for which the ticket was issued.
  179        *
  180        * @serial
  181        */
  182   
  183       private KerberosPrincipal server;
  184   
  185       /**
  186        *
  187        * The addresses from where the ticket may be used by the client.
  188        * This field may be null when the ticket is usable from any address.
  189        *
  190        * @serial
  191        */
  192   
  193   
  194       private InetAddress[] clientAddresses;
  195   
  196       private transient boolean destroyed = false;
  197   
  198       /**
  199        * Constructs a KerberosTicket using credentials information that a
  200        * client either receives from a KDC or reads from a cache.
  201        *
  202        * @param asn1Encoding the ASN.1 encoding of the ticket as defined by
  203        * the Kerberos protocol specification.
  204        * @param client the client that owns this service
  205        * ticket
  206        * @param server the service that this ticket is for
  207        * @param sessionKey the raw bytes for the session key that must be
  208        * used to encrypt the authenticator that will be sent to the server
  209        * @param keyType the key type for the session key as defined by the
  210        * Kerberos protocol specification.
  211        * @param flags the ticket flags. Each element in this array indicates
  212        * the value for the corresponding bit in the ASN.1 BitString that
  213        * represents the ticket flags. If the number of elements in this array
  214        * is less than the number of flags used by the Kerberos protocol,
  215        * then the missing flags will be filled in with false.
  216        * @param authTime the time of initial authentication for the client
  217        * @param startTime the time after which the ticket will be valid. This
  218        * may be null in which case the value of authTime is treated as the
  219        * startTime.
  220        * @param endTime the time after which the ticket will no longer be
  221        * valid
  222        * @param renewTill an absolute expiration time for the ticket,
  223        * including all renewal that might be possible. This field may be null
  224        * for tickets that are not renewable.
  225        * @param clientAddresses the addresses from where the ticket may be
  226        * used by the client. This field may be null when the ticket is usable
  227        * from any address.
  228        */
  229       public KerberosTicket(byte[] asn1Encoding,
  230                            KerberosPrincipal client,
  231                            KerberosPrincipal server,
  232                            byte[] sessionKey,
  233                            int keyType,
  234                            boolean[] flags,
  235                            Date authTime,
  236                            Date startTime,
  237                            Date endTime,
  238                            Date renewTill,
  239                            InetAddress[] clientAddresses) {
  240   
  241           init(asn1Encoding, client, server, sessionKey, keyType, flags,
  242               authTime, startTime, endTime, renewTill, clientAddresses);
  243       }
  244   
  245       private void init(byte[] asn1Encoding,
  246                            KerberosPrincipal client,
  247                            KerberosPrincipal server,
  248                            byte[] sessionKey,
  249                            int keyType,
  250                            boolean[] flags,
  251                            Date authTime,
  252                            Date startTime,
  253                            Date endTime,
  254                            Date renewTill,
  255                            InetAddress[] clientAddresses) {
  256           if (sessionKey == null)
  257              throw new IllegalArgumentException("Session key for ticket"
  258                                                 + " cannot be null");
  259           init(asn1Encoding, client, server,
  260                new KeyImpl(sessionKey, keyType), flags, authTime,
  261                startTime, endTime, renewTill, clientAddresses);
  262       }
  263   
  264       private void init(byte[] asn1Encoding,
  265                            KerberosPrincipal client,
  266                            KerberosPrincipal server,
  267                            KeyImpl sessionKey,
  268                            boolean[] flags,
  269                            Date authTime,
  270                            Date startTime,
  271                            Date endTime,
  272                            Date renewTill,
  273                            InetAddress[] clientAddresses) {
  274           if (asn1Encoding == null)
  275              throw new IllegalArgumentException("ASN.1 encoding of ticket"
  276                                                 + " cannot be null");
  277           this.asn1Encoding = asn1Encoding.clone();
  278   
  279           if (client == null)
  280              throw new IllegalArgumentException("Client name in ticket"
  281                                                 + " cannot be null");
  282           this.client = client;
  283   
  284           if (server == null)
  285              throw new IllegalArgumentException("Server name in ticket"
  286                                                 + " cannot be null");
  287           this.server = server;
  288   
  289           // Caller needs to make sure `sessionKey` will not be null
  290           this.sessionKey = sessionKey;
  291   
  292           if (flags != null) {
  293              if (flags.length >= NUM_FLAGS)
  294                   this.flags = flags.clone();
  295              else {
  296                   this.flags = new boolean[NUM_FLAGS];
  297                   // Fill in whatever we have
  298                   for (int i = 0; i < flags.length; i++)
  299                       this.flags[i] = flags[i];
  300              }
  301           } else
  302              this.flags = new boolean[NUM_FLAGS];
  303   
  304           if (this.flags[RENEWABLE_TICKET_FLAG]) {
  305              if (renewTill == null)
  306                   throw new IllegalArgumentException("The renewable period "
  307                          + "end time cannot be null for renewable tickets.");
  308   
  309              this.renewTill = new Date(renewTill.getTime());
  310           }
  311   
  312           if (authTime != null) {
  313               this.authTime = new Date(authTime.getTime());
  314           }
  315           if (startTime != null) {
  316               this.startTime = new Date(startTime.getTime());
  317           } else {
  318               this.startTime = this.authTime;
  319           }
  320   
  321           if (endTime == null)
  322              throw new IllegalArgumentException("End time for ticket validity"
  323                                                 + " cannot be null");
  324           this.endTime = new Date(endTime.getTime());
  325   
  326           if (clientAddresses != null)
  327              this.clientAddresses = clientAddresses.clone();
  328       }
  329   
  330       /**
  331        * Returns the client principal associated with this ticket.
  332        *
  333        * @return the client principal.
  334        */
  335       public final KerberosPrincipal getClient() {
  336           return client;
  337       }
  338   
  339       /**
  340        * Returns the service principal associated with this ticket.
  341        *
  342        * @return the service principal.
  343        */
  344       public final KerberosPrincipal getServer() {
  345           return server;
  346       }
  347   
  348       /**
  349        * Returns the session key associated with this ticket.
  350        *
  351        * @return the session key.
  352        */
  353       public final SecretKey getSessionKey() {
  354           if (destroyed)
  355               throw new IllegalStateException("This ticket is no longer valid");
  356           return sessionKey;
  357       }
  358   
  359       /**
  360        * Returns the key type of the session key associated with this
  361        * ticket as defined by the Kerberos Protocol Specification.
  362        *
  363        * @return the key type of the session key associated with this
  364        * ticket.
  365        *
  366        * @see #getSessionKey()
  367        */
  368       public final int getSessionKeyType() {
  369           if (destroyed)
  370               throw new IllegalStateException("This ticket is no longer valid");
  371           return sessionKey.getKeyType();
  372       }
  373   
  374       /**
  375        * Determines if this ticket is forwardable.
  376        *
  377        * @return true if this ticket is forwardable, false if not.
  378        */
  379       public final boolean isForwardable() {
  380           return flags[FORWARDABLE_TICKET_FLAG];
  381       }
  382   
  383       /**
  384        * Determines if this ticket had been forwarded or was issued based on
  385        * authentication involving a forwarded ticket-granting ticket.
  386        *
  387        * @return true if this ticket had been forwarded or was issued based on
  388        * authentication involving a forwarded ticket-granting ticket,
  389        * false otherwise.
  390        */
  391       public final boolean isForwarded() {
  392           return flags[FORWARDED_TICKET_FLAG];
  393       }
  394   
  395       /**
  396        * Determines if this ticket is proxiable.
  397        *
  398        * @return true if this ticket is proxiable, false if not.
  399        */
  400       public final boolean isProxiable() {
  401           return flags[PROXIABLE_TICKET_FLAG];
  402       }
  403   
  404       /**
  405        * Determines is this ticket is a proxy-ticket.
  406        *
  407        * @return true if this ticket is a proxy-ticket, false if not.
  408        */
  409       public final boolean isProxy() {
  410           return flags[PROXY_TICKET_FLAG];
  411       }
  412   
  413   
  414       /**
  415        * Determines is this ticket is post-dated.
  416        *
  417        * @return true if this ticket is post-dated, false if not.
  418        */
  419       public final boolean isPostdated() {
  420           return flags[POSTDATED_TICKET_FLAG];
  421       }
  422   
  423       /**
  424        * Determines is this ticket is renewable. If so, the {@link #refresh()
  425        * refresh} method can be called, assuming the validity period for
  426        * renewing is not already over.
  427        *
  428        * @return true if this ticket is renewable, false if not.
  429        */
  430       public final boolean isRenewable() {
  431           return flags[RENEWABLE_TICKET_FLAG];
  432       }
  433   
  434       /**
  435        * Determines if this ticket was issued using the Kerberos AS-Exchange
  436        * protocol, and not issued based on some ticket-granting ticket.
  437        *
  438        * @return true if this ticket was issued using the Kerberos AS-Exchange
  439        * protocol, false if not.
  440        */
  441       public final boolean isInitial() {
  442           return flags[INITIAL_TICKET_FLAG];
  443       }
  444   
  445       /**
  446        * Returns the flags associated with this ticket. Each element in the
  447        * returned array indicates the value for the corresponding bit in the
  448        * ASN.1 BitString that represents the ticket flags.
  449        *
  450        * @return the flags associated with this ticket.
  451        */
  452       public final boolean[]  getFlags() {
  453           return (flags == null? null: flags.clone());
  454       }
  455   
  456       /**
  457        * Returns the time that the client was authenticated.
  458        *
  459        * @return the time that the client was authenticated
  460        *         or null if not set.
  461        */
  462       public final java.util.Date getAuthTime() {
  463           return (authTime == null) ? null : (Date)authTime.clone();
  464       }
  465   
  466       /**
  467        * Returns the start time for this ticket's validity period.
  468        *
  469        * @return the start time for this ticket's validity period
  470        *         or null if not set.
  471        */
  472       public final java.util.Date getStartTime() {
  473           return (startTime == null) ? null : (Date)startTime.clone();
  474       }
  475   
  476       /**
  477        * Returns the expiration time for this ticket's validity period.
  478        *
  479        * @return the expiration time for this ticket's validity period.
  480        */
  481       public final java.util.Date getEndTime() {
  482           return (Date) endTime.clone();
  483       }
  484   
  485       /**
  486        * Returns the latest expiration time for this ticket, including all
  487        * renewals. This will return a null value for non-renewable tickets.
  488        *
  489        * @return the latest expiration time for this ticket.
  490        */
  491       public final java.util.Date getRenewTill() {
  492           return (renewTill == null) ? null: (Date)renewTill.clone();
  493       }
  494   
  495       /**
  496        * Returns a list of addresses from where the ticket can be used.
  497        *
  498        * @return ths list of addresses or null, if the field was not
  499        * provided.
  500        */
  501       public final java.net.InetAddress[] getClientAddresses() {
  502           return (clientAddresses == null) ? null: clientAddresses.clone();
  503       }
  504   
  505       /**
  506        * Returns an ASN.1 encoding of the entire ticket.
  507        *
  508        * @return an ASN.1 encoding of the entire ticket.
  509        */
  510       public final byte[] getEncoded() {
  511           if (destroyed)
  512               throw new IllegalStateException("This ticket is no longer valid");
  513           return asn1Encoding.clone();
  514       }
  515   
  516       /** Determines if this ticket is still current.  */
  517       public boolean isCurrent() {
  518           return (System.currentTimeMillis() <= getEndTime().getTime());
  519       }
  520   
  521       /**
  522        * Extends the validity period of this ticket. The ticket will contain
  523        * a new session key if the refresh operation succeeds. The refresh
  524        * operation will fail if the ticket is not renewable or the latest
  525        * allowable renew time has passed. Any other error returned by the
  526        * KDC will also cause this method to fail.
  527        *
  528        * Note: This method is not synchronized with the the accessor
  529        * methods of this object. Hence callers need to be aware of multiple
  530        * threads that might access this and try to renew it at the same
  531        * time.
  532        *
  533        * @throws RefreshFailedException if the ticket is not renewable, or
  534        * the latest allowable renew time has passed, or the KDC returns some
  535        * error.
  536        *
  537        * @see #isRenewable()
  538        * @see #getRenewTill()
  539        */
  540       public void refresh() throws RefreshFailedException {
  541   
  542           if (destroyed)
  543               throw new RefreshFailedException("A destroyed ticket "
  544                                                + "cannot be renewd.");
  545   
  546           if (!isRenewable())
  547               throw new RefreshFailedException("This ticket is not renewable");
  548   
  549           if (System.currentTimeMillis() > getRenewTill().getTime())
  550               throw new RefreshFailedException("This ticket is past "
  551                                                + "its last renewal time.");
  552           Throwable e = null;
  553           sun.security.krb5.Credentials krb5Creds = null;
  554   
  555           try {
  556               krb5Creds = new sun.security.krb5.Credentials(asn1Encoding,
  557                                                       client.toString(),
  558                                                       server.toString(),
  559                                                       sessionKey.getEncoded(),
  560                                                       sessionKey.getKeyType(),
  561                                                       flags,
  562                                                       authTime,
  563                                                       startTime,
  564                                                       endTime,
  565                                                       renewTill,
  566                                                       clientAddresses);
  567               krb5Creds = krb5Creds.renew();
  568           } catch (sun.security.krb5.KrbException krbException) {
  569               e = krbException;
  570           } catch (java.io.IOException ioException) {
  571               e = ioException;
  572           }
  573   
  574           if (e != null) {
  575               RefreshFailedException rfException
  576                   = new RefreshFailedException("Failed to renew Kerberos Ticket "
  577                                                + "for client " + client
  578                                                + " and server " + server
  579                                                + " - " + e.getMessage());
  580               rfException.initCause(e);
  581               throw rfException;
  582           }
  583   
  584           /*
  585            * In case multiple threads try to refresh it at the same time.
  586            */
  587           synchronized (this) {
  588               try {
  589                   this.destroy();
  590               } catch (DestroyFailedException dfException) {
  591                   // Squelch it since we don't care about the old ticket.
  592               }
  593               init(krb5Creds.getEncoded(),
  594                    new KerberosPrincipal(krb5Creds.getClient().getName()),
  595                    new KerberosPrincipal(krb5Creds.getServer().getName(),
  596                                           KerberosPrincipal.KRB_NT_SRV_INST),
  597                    krb5Creds.getSessionKey().getBytes(),
  598                    krb5Creds.getSessionKey().getEType(),
  599                    krb5Creds.getFlags(),
  600                    krb5Creds.getAuthTime(),
  601                    krb5Creds.getStartTime(),
  602                    krb5Creds.getEndTime(),
  603                    krb5Creds.getRenewTill(),
  604                    krb5Creds.getClientAddresses());
  605               destroyed = false;
  606           }
  607       }
  608   
  609       /**
  610        * Destroys the ticket and destroys any sensitive information stored in
  611        * it.
  612        */
  613       public void destroy() throws DestroyFailedException {
  614           if (!destroyed) {
  615               Arrays.fill(asn1Encoding, (byte) 0);
  616               client = null;
  617               server = null;
  618               sessionKey.destroy();
  619               flags = null;
  620               authTime = null;
  621               startTime = null;
  622               endTime = null;
  623               renewTill = null;
  624               clientAddresses = null;
  625               destroyed = true;
  626           }
  627       }
  628   
  629       /**
  630        * Determines if this ticket has been destroyed.
  631        */
  632       public boolean isDestroyed() {
  633           return destroyed;
  634       }
  635   
  636       public String toString() {
  637           if (destroyed)
  638               throw new IllegalStateException("This ticket is no longer valid");
  639           StringBuffer caddrBuf = new StringBuffer();
  640           if (clientAddresses != null) {
  641               for (int i = 0; i < clientAddresses.length; i++) {
  642                   caddrBuf.append("clientAddresses[" + i + "] = " +
  643                                    clientAddresses[i].toString());
  644               }
  645           }
  646           return ("Ticket (hex) = " + "\n" +
  647                    (new HexDumpEncoder()).encodeBuffer(asn1Encoding) + "\n" +
  648                   "Client Principal = " + client.toString() + "\n" +
  649                   "Server Principal = " + server.toString() + "\n" +
  650                   "Session Key = " + sessionKey.toString() + "\n" +
  651                   "Forwardable Ticket " + flags[FORWARDABLE_TICKET_FLAG] + "\n" +
  652                   "Forwarded Ticket " + flags[FORWARDED_TICKET_FLAG] + "\n" +
  653                   "Proxiable Ticket " + flags[PROXIABLE_TICKET_FLAG] + "\n" +
  654                   "Proxy Ticket " + flags[PROXY_TICKET_FLAG] + "\n" +
  655                   "Postdated Ticket " + flags[POSTDATED_TICKET_FLAG] + "\n" +
  656                   "Renewable Ticket " + flags[RENEWABLE_TICKET_FLAG] + "\n" +
  657                   "Initial Ticket " + flags[RENEWABLE_TICKET_FLAG] + "\n" +
  658                   "Auth Time = " + String.valueOf(authTime) + "\n" +
  659                   "Start Time = " + String.valueOf(startTime) + "\n" +
  660                   "End Time = " + endTime.toString() + "\n" +
  661                   "Renew Till = " + String.valueOf(renewTill) + "\n" +
  662                   "Client Addresses " +
  663                   (clientAddresses == null ? " Null " : caddrBuf.toString() +
  664                   "\n"));
  665       }
  666   
  667       /**
  668        * Returns a hashcode for this KerberosTicket.
  669        *
  670        * @return a hashCode() for the <code>KerberosTicket</code>
  671        * @since 1.6
  672        */
  673       public int hashCode() {
  674           int result = 17;
  675           if (isDestroyed()) {
  676               return result;
  677           }
  678           result = result * 37 + Arrays.hashCode(getEncoded());
  679           result = result * 37 + endTime.hashCode();
  680           result = result * 37 + client.hashCode();
  681           result = result * 37 + server.hashCode();
  682           result = result * 37 + sessionKey.hashCode();
  683   
  684           // authTime may be null
  685           if (authTime != null) {
  686               result = result * 37 + authTime.hashCode();
  687           }
  688   
  689           // startTime may be null
  690           if (startTime != null) {
  691               result = result * 37 + startTime.hashCode();
  692           }
  693   
  694           // renewTill may be null
  695           if (renewTill != null) {
  696               result = result * 37 + renewTill.hashCode();
  697           }
  698   
  699           // clientAddress may be null, the array's hashCode is 0
  700           result = result * 37 + Arrays.hashCode(clientAddresses);
  701           return result * 37 + Arrays.hashCode(flags);
  702       }
  703   
  704       /**
  705        * Compares the specified Object with this KerberosTicket for equality.
  706        * Returns true if the given object is also a
  707        * <code>KerberosTicket</code> and the two
  708        * <code>KerberosTicket</code> instances are equivalent.
  709        *
  710        * @param other the Object to compare to
  711        * @return true if the specified object is equal to this KerberosTicket,
  712        * false otherwise. NOTE: Returns false if either of the KerberosTicket
  713        * objects has been destroyed.
  714        * @since 1.6
  715        */
  716       public boolean equals(Object other) {
  717   
  718           if (other == this)
  719               return true;
  720   
  721           if (! (other instanceof KerberosTicket)) {
  722               return false;
  723           }
  724   
  725           KerberosTicket otherTicket = ((KerberosTicket) other);
  726           if (isDestroyed() || otherTicket.isDestroyed()) {
  727               return false;
  728           }
  729   
  730           if (!Arrays.equals(getEncoded(), otherTicket.getEncoded()) ||
  731                   !endTime.equals(otherTicket.getEndTime()) ||
  732                   !server.equals(otherTicket.getServer()) ||
  733                   !client.equals(otherTicket.getClient()) ||
  734                   !sessionKey.equals(otherTicket.getSessionKey()) ||
  735                   !Arrays.equals(clientAddresses, otherTicket.getClientAddresses()) ||
  736                   !Arrays.equals(flags, otherTicket.getFlags())) {
  737               return false;
  738           }
  739   
  740           // authTime may be null
  741           if (authTime == null) {
  742               if (otherTicket.getAuthTime() != null)
  743                   return false;
  744           } else {
  745               if (!authTime.equals(otherTicket.getAuthTime()))
  746                   return false;
  747           }
  748   
  749           // startTime may be null
  750           if (startTime == null) {
  751               if (otherTicket.getStartTime() != null)
  752                   return false;
  753           } else {
  754               if (!startTime.equals(otherTicket.getStartTime()))
  755                   return false;
  756           }
  757   
  758           if (renewTill == null) {
  759               if (otherTicket.getRenewTill() != null)
  760                   return false;
  761           } else {
  762               if (!renewTill.equals(otherTicket.getRenewTill()))
  763                   return false;
  764           }
  765   
  766           return true;
  767       }
  768   
  769       private void readObject(ObjectInputStream s)
  770           throws IOException, ClassNotFoundException {
  771           s.defaultReadObject();
  772           if (sessionKey == null) {
  773              throw new InvalidObjectException("Session key cannot be null");
  774           }
  775           try {
  776               init(asn1Encoding, client, server, sessionKey,
  777                    flags, authTime, startTime, endTime,
  778                    renewTill, clientAddresses);
  779           } catch (IllegalArgumentException iae) {
  780               throw (InvalidObjectException)
  781                   new InvalidObjectException(iae.getMessage()).initCause(iae);
  782           }
  783       }
  784   }

Home » openjdk-7 » javax.security » auth » kerberos » [javadoc | source]