/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.kerberos;
import java.io.*;
import java.util.Date;
import java.util.Arrays;
import java.net.InetAddress;
import javax.crypto.SecretKey;
import javax.security.auth.Refreshable;
import javax.security.auth.Destroyable;
import javax.security.auth.RefreshFailedException;
import javax.security.auth.DestroyFailedException;
import sun.security.util.HexDumpEncoder;
This class encapsulates a Kerberos ticket and associated
information as viewed from the client's point of view. It captures all
information that the Key Distribution Center (KDC) sends to the client
in the reply message KDC-REP defined in the Kerberos Protocol
Specification (RFC 4120).
All Kerberos JAAS login modules that authenticate a user to a KDC should use this class. Where available, the login module might even read this information from a ticket cache in the operating system instead of directly communicating with the KDC. During the commit phase of the JAAS authentication process, the JAAS login module should instantiate this class and store the instance in the private credential set of a Subject
.
It might be necessary for the application to be granted a
PrivateCredentialPermission
if it needs to access a KerberosTicket
instance from a Subject
. This permission is not needed when the application depends on the default JGSS Kerberos mechanism to access the KerberosTicket
. In that case, however, the application will need an appropriate ServicePermission
.
Note that this class is applicable to both ticket granting tickets and
other regular service tickets. A ticket granting ticket is just a
special case of a more generalized service ticket.
Author: Mayank Upadhyay See Also: Implementation Note: The JAAS login module in the JDK reference implementation destroys
all tickets after logout. Since: 1.4
/**
* This class encapsulates a Kerberos ticket and associated
* information as viewed from the client's point of view. It captures all
* information that the Key Distribution Center (KDC) sends to the client
* in the reply message KDC-REP defined in the Kerberos Protocol
* Specification (<a href=http://www.ietf.org/rfc/rfc4120.txt>RFC 4120</a>).
* <p>
* All Kerberos JAAS login modules that authenticate a user to a KDC should
* use this class. Where available, the login module might even read this
* information from a ticket cache in the operating system instead of
* directly communicating with the KDC. During the commit phase of the JAAS
* authentication process, the JAAS login module should instantiate this
* class and store the instance in the private credential set of a
* {@link javax.security.auth.Subject Subject}.<p>
*
* It might be necessary for the application to be granted a
* {@link javax.security.auth.PrivateCredentialPermission
* PrivateCredentialPermission} if it needs to access a {@code KerberosTicket}
* instance from a {@code Subject}. This permission is not needed when the
* application depends on the default JGSS Kerberos mechanism to access the
* {@code KerberosTicket}. In that case, however, the application will need an
* appropriate
* {@link javax.security.auth.kerberos.ServicePermission ServicePermission}.
* <p>
* Note that this class is applicable to both ticket granting tickets and
* other regular service tickets. A ticket granting ticket is just a
* special case of a more generalized service ticket.
*
* @implNote The JAAS login module in the JDK reference implementation destroys
* all tickets after logout.
*
* @see javax.security.auth.Subject
* @see javax.security.auth.PrivateCredentialPermission
* @see javax.security.auth.login.LoginContext
* @see org.ietf.jgss.GSSCredential
* @see org.ietf.jgss.GSSManager
*
* @author Mayank Upadhyay
* @since 1.4
*/
public class KerberosTicket implements Destroyable, Refreshable,
java.io.Serializable {
private static final long serialVersionUID = 7395334370157380539L;
// XXX Make these flag indices public
private static final int FORWARDABLE_TICKET_FLAG = 1;
private static final int FORWARDED_TICKET_FLAG = 2;
private static final int PROXIABLE_TICKET_FLAG = 3;
private static final int PROXY_TICKET_FLAG = 4;
private static final int POSTDATED_TICKET_FLAG = 6;
private static final int RENEWABLE_TICKET_FLAG = 8;
private static final int INITIAL_TICKET_FLAG = 9;
private static final int NUM_FLAGS = 32;
ASN.1 DER Encoding of the Ticket as defined in the
Kerberos Protocol Specification RFC4120.
@serial
/**
*
* ASN.1 DER Encoding of the Ticket as defined in the
* Kerberos Protocol Specification RFC4120.
*
* @serial
*/
private byte[] asn1Encoding;
KeyImpl
is serialized by writing out the ASN1 Encoded bytes of the encryption key. The ASN1 encoding is defined in RFC4120 and as follows: EncryptionKey ::= SEQUENCE {
keytype [0] Int32 -- actually encryption type --,
keyvalue [1] OCTET STRING
}
@serial
/**
*{@code KeyImpl} is serialized by writing out the ASN1 Encoded bytes
* of the encryption key. The ASN1 encoding is defined in RFC4120 and as
* follows:
* <pre>
* EncryptionKey ::= SEQUENCE {
* keytype [0] Int32 -- actually encryption type --,
* keyvalue [1] OCTET STRING
* }
* </pre>
*
* @serial
*/
private KeyImpl sessionKey;
Ticket Flags as defined in the Kerberos Protocol Specification RFC4120.
@serial
/**
*
* Ticket Flags as defined in the Kerberos Protocol Specification RFC4120.
*
* @serial
*/
private boolean[] flags;
Time of initial authentication
@serial
/**
*
* Time of initial authentication
*
* @serial
*/
private Date authTime;
Time after which the ticket is valid.
@serial
/**
*
* Time after which the ticket is valid.
* @serial
*/
private Date startTime;
Time after which the ticket will not be honored. (its expiration time).
@serial
/**
*
* Time after which the ticket will not be honored. (its expiration time).
*
* @serial
*/
private Date endTime;
For renewable Tickets it indicates the maximum endtime that may be
included in a renewal. It can be thought of as the absolute expiration
time for the ticket, including all renewals. This field may be null
for tickets that are not renewable.
@serial
/**
*
* For renewable Tickets it indicates the maximum endtime that may be
* included in a renewal. It can be thought of as the absolute expiration
* time for the ticket, including all renewals. This field may be null
* for tickets that are not renewable.
*
* @serial
*/
private Date renewTill;
Client that owns the service ticket
@serial
/**
*
* Client that owns the service ticket
*
* @serial
*/
private KerberosPrincipal client;
The service for which the ticket was issued.
@serial
/**
*
* The service for which the ticket was issued.
*
* @serial
*/
private KerberosPrincipal server;
The addresses from where the ticket may be used by the client.
This field may be null when the ticket is usable from any address.
@serial
/**
*
* The addresses from where the ticket may be used by the client.
* This field may be null when the ticket is usable from any address.
*
* @serial
*/
private InetAddress[] clientAddresses;
private transient boolean destroyed = false;
Constructs a KerberosTicket
using credentials information that a client either receives from a KDC or reads from a cache. Params: - asn1Encoding – the ASN.1 encoding of the ticket as defined by
the Kerberos protocol specification.
- client – the client that owns this service
ticket
- server – the service that this ticket is for
- sessionKey – the raw bytes for the session key that must be
used to encrypt the authenticator that will be sent to the server
- keyType – the key type for the session key as defined by the
Kerberos protocol specification.
- flags – the ticket flags. Each element in this array indicates
the value for the corresponding bit in the ASN.1 BitString that
represents the ticket flags. If the number of elements in this array
is less than the number of flags used by the Kerberos protocol,
then the missing flags will be filled in with false.
- authTime – the time of initial authentication for the client
- startTime – the time after which the ticket will be valid. This
may be null in which case the value of authTime is treated as the
startTime.
- endTime – the time after which the ticket will no longer be
valid
- renewTill – an absolute expiration time for the ticket,
including all renewal that might be possible. This field may be null
for tickets that are not renewable.
- clientAddresses – the addresses from where the ticket may be
used by the client. This field may be null when the ticket is usable
from any address.
/**
* Constructs a {@code KerberosTicket} using credentials information that a
* client either receives from a KDC or reads from a cache.
*
* @param asn1Encoding the ASN.1 encoding of the ticket as defined by
* the Kerberos protocol specification.
* @param client the client that owns this service
* ticket
* @param server the service that this ticket is for
* @param sessionKey the raw bytes for the session key that must be
* used to encrypt the authenticator that will be sent to the server
* @param keyType the key type for the session key as defined by the
* Kerberos protocol specification.
* @param flags the ticket flags. Each element in this array indicates
* the value for the corresponding bit in the ASN.1 BitString that
* represents the ticket flags. If the number of elements in this array
* is less than the number of flags used by the Kerberos protocol,
* then the missing flags will be filled in with false.
* @param authTime the time of initial authentication for the client
* @param startTime the time after which the ticket will be valid. This
* may be null in which case the value of authTime is treated as the
* startTime.
* @param endTime the time after which the ticket will no longer be
* valid
* @param renewTill an absolute expiration time for the ticket,
* including all renewal that might be possible. This field may be null
* for tickets that are not renewable.
* @param clientAddresses the addresses from where the ticket may be
* used by the client. This field may be null when the ticket is usable
* from any address.
*/
public KerberosTicket(byte[] asn1Encoding,
KerberosPrincipal client,
KerberosPrincipal server,
byte[] sessionKey,
int keyType,
boolean[] flags,
Date authTime,
Date startTime,
Date endTime,
Date renewTill,
InetAddress[] clientAddresses) {
init(asn1Encoding, client, server, sessionKey, keyType, flags,
authTime, startTime, endTime, renewTill, clientAddresses);
}
private void init(byte[] asn1Encoding,
KerberosPrincipal client,
KerberosPrincipal server,
byte[] sessionKey,
int keyType,
boolean[] flags,
Date authTime,
Date startTime,
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");
}
this.asn1Encoding = asn1Encoding.clone();
if (client == null) {
throw new IllegalArgumentException("Client name in ticket"
+ " cannot be null");
}
this.client = client;
if (server == null) {
throw new IllegalArgumentException("Server name in ticket"
+ " cannot be null");
}
this.server = server;
// Caller needs to make sure `sessionKey` will not be null
this.sessionKey = sessionKey;
if (flags != null) {
if (flags.length >= NUM_FLAGS) {
this.flags = flags.clone();
} else {
this.flags = new boolean[NUM_FLAGS];
// Fill in whatever we have
for (int i = 0; i < flags.length; i++) {
this.flags[i] = flags[i];
}
}
} else {
this.flags = new boolean[NUM_FLAGS];
}
if (this.flags[RENEWABLE_TICKET_FLAG]) {
if (renewTill == null) {
throw new IllegalArgumentException("The renewable period "
+ "end time cannot be null for renewable tickets.");
}
this.renewTill = new Date(renewTill.getTime());
}
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 = new Date(endTime.getTime());
if (clientAddresses != null) {
this.clientAddresses = clientAddresses.clone();
}
}
Returns the client principal associated with this ticket.
Returns: the client principal, or null
if destroyed.
/**
* Returns the client principal associated with this ticket.
*
* @return the client principal, or {@code null} if destroyed.
*/
public final KerberosPrincipal getClient() {
return client;
}
Returns the service principal associated with this ticket.
Returns: the service principal, or null
if destroyed.
/**
* Returns the service principal associated with this ticket.
*
* @return the service principal, or {@code null} if destroyed.
*/
public final KerberosPrincipal getServer() {
return server;
}
Returns the session key associated with this ticket. The return value is always a EncryptionKey
object. Throws: - IllegalStateException – if this ticket is destroyed
Returns: the session key.
/**
* Returns the session key associated with this ticket. The return value
* is always a {@link EncryptionKey} object.
*
* @return the session key.
* @throws IllegalStateException if this ticket is destroyed
*/
public final SecretKey getSessionKey() {
if (destroyed) {
throw new IllegalStateException("This ticket is no longer valid");
}
return new EncryptionKey(
sessionKey.getEncoded(), sessionKey.getKeyType());
}
Returns the key type of the session key associated with this
ticket as defined by the Kerberos Protocol Specification.
Throws: - IllegalStateException – if this ticket is destroyed
See Also: Returns: the key type of the session key associated with this
ticket.
/**
* Returns the key type of the session key associated with this
* ticket as defined by the Kerberos Protocol Specification.
*
* @return the key type of the session key associated with this
* ticket.
* @throws IllegalStateException if this ticket is destroyed
*
* @see #getSessionKey()
*/
public final int getSessionKeyType() {
if (destroyed) {
throw new IllegalStateException("This ticket is no longer valid");
}
return sessionKey.getKeyType();
}
Determines if this ticket is forwardable.
Returns: true if this ticket is forwardable, or false if not forwardable
or destroyed.
/**
* Determines if this ticket is forwardable.
*
* @return true if this ticket is forwardable, or false if not forwardable
* or destroyed.
*/
public final boolean isForwardable() {
return flags == null? false: flags[FORWARDABLE_TICKET_FLAG];
}
Determines if this ticket had been forwarded or was issued based on
authentication involving a forwarded ticket-granting ticket.
Returns: true if this ticket had been forwarded or was issued based on
authentication involving a forwarded ticket-granting ticket,
or false otherwise or destroyed.
/**
* Determines if this ticket had been forwarded or was issued based on
* authentication involving a forwarded ticket-granting ticket.
*
* @return true if this ticket had been forwarded or was issued based on
* authentication involving a forwarded ticket-granting ticket,
* or false otherwise or destroyed.
*/
public final boolean isForwarded() {
return flags == null? false: flags[FORWARDED_TICKET_FLAG];
}
Determines if this ticket is proxiable.
Returns: true if this ticket is proxiable, or false if not proxiable
or destroyed.
/**
* Determines if this ticket is proxiable.
*
* @return true if this ticket is proxiable, or false if not proxiable
* or destroyed.
*/
public final boolean isProxiable() {
return flags == null? false: flags[PROXIABLE_TICKET_FLAG];
}
Determines is this ticket is a proxy-ticket.
Returns: true if this ticket is a proxy-ticket, or false if not
a proxy-ticket or destroyed.
/**
* Determines is this ticket is a proxy-ticket.
*
* @return true if this ticket is a proxy-ticket, or false if not
* a proxy-ticket or destroyed.
*/
public final boolean isProxy() {
return flags == null? false: flags[PROXY_TICKET_FLAG];
}
Determines is this ticket is post-dated.
Returns: true if this ticket is post-dated, or false if not post-dated
or destroyed.
/**
* Determines is this ticket is post-dated.
*
* @return true if this ticket is post-dated, or false if not post-dated
* or destroyed.
*/
public final boolean isPostdated() {
return flags == null? false: flags[POSTDATED_TICKET_FLAG];
}
Determines is this ticket is renewable. If so, the
refresh
method can be called, assuming the validity period for renewing is not already over. Returns: true if this ticket is renewable, or false if not renewable
or destroyed.
/**
* Determines is this ticket is renewable. If so, the {@link #refresh()
* refresh} method can be called, assuming the validity period for
* renewing is not already over.
*
* @return true if this ticket is renewable, or false if not renewable
* or destroyed.
*/
public final boolean isRenewable() {
return flags == null? false: flags[RENEWABLE_TICKET_FLAG];
}
Determines if this ticket was issued using the Kerberos AS-Exchange
protocol, and not issued based on some ticket-granting ticket.
Returns: true if this ticket was issued using the Kerberos AS-Exchange
protocol, or false if not issued this way or destroyed.
/**
* Determines if this ticket was issued using the Kerberos AS-Exchange
* protocol, and not issued based on some ticket-granting ticket.
*
* @return true if this ticket was issued using the Kerberos AS-Exchange
* protocol, or false if not issued this way or destroyed.
*/
public final boolean isInitial() {
return flags == null? false: flags[INITIAL_TICKET_FLAG];
}
Returns the flags associated with this ticket. Each element in the
returned array indicates the value for the corresponding bit in the
ASN.1 BitString that represents the ticket flags.
Returns: the flags associated with this ticket, or null
if destroyed.
/**
* Returns the flags associated with this ticket. Each element in the
* returned array indicates the value for the corresponding bit in the
* ASN.1 BitString that represents the ticket flags.
*
* @return the flags associated with this ticket, or {@code null}
* if destroyed.
*/
public final boolean[] getFlags() {
return (flags == null? null: flags.clone());
}
Returns the time that the client was authenticated.
Returns: the time that the client was authenticated or null
if the field is not set or this ticket is destroyed.
/**
* Returns the time that the client was authenticated.
*
* @return the time that the client was authenticated
* or {@code null} if the field is not set or
* this ticket is destroyed.
*/
public final java.util.Date getAuthTime() {
return (authTime == null) ? null : (Date)authTime.clone();
}
Returns the start time for this ticket's validity period.
Returns: the start time for this ticket's validity period or null
if the field is not set or this ticket is destroyed.
/**
* Returns the start time for this ticket's validity period.
*
* @return the start time for this ticket's validity period
* or {@code null} if the field is not set or
* this ticket is destroyed.
*/
public final java.util.Date getStartTime() {
return (startTime == null) ? null : (Date)startTime.clone();
}
Returns the expiration time for this ticket's validity period.
Returns: the expiration time for this ticket's validity period, or null
if destroyed.
/**
* Returns the expiration time for this ticket's validity period.
*
* @return the expiration time for this ticket's validity period,
* or {@code null} if destroyed.
*/
public final java.util.Date getEndTime() {
return (endTime == null) ? null : (Date) endTime.clone();
}
Returns the latest expiration time for this ticket, including all
renewals. This will return a null value for non-renewable tickets.
Returns: the latest expiration time for this ticket, or null
if destroyed.
/**
* Returns the latest expiration time for this ticket, including all
* renewals. This will return a null value for non-renewable tickets.
*
* @return the latest expiration time for this ticket, or {@code null}
* if destroyed.
*/
public final java.util.Date getRenewTill() {
return (renewTill == null) ? null: (Date)renewTill.clone();
}
Returns a list of addresses from where the ticket can be used.
Returns: the list of addresses, or null
if the field was not provided or this ticket is destroyed.
/**
* Returns a list of addresses from where the ticket can be used.
*
* @return the list of addresses, or {@code null} if the field was not
* provided or this ticket is destroyed.
*/
public final java.net.InetAddress[] getClientAddresses() {
return (clientAddresses == null) ? null: clientAddresses.clone();
}
Returns an ASN.1 encoding of the entire ticket.
Throws: - IllegalStateException – if this ticket is destroyed
Returns: an ASN.1 encoding of the entire ticket. A new byte
array is returned each time this method is called.
/**
* Returns an ASN.1 encoding of the entire ticket.
*
* @return an ASN.1 encoding of the entire ticket. A new byte
* array is returned each time this method is called.
* @throws IllegalStateException if this ticket is destroyed
*/
public final byte[] getEncoded() {
if (destroyed) {
throw new IllegalStateException("This ticket is no longer valid");
}
return asn1Encoding.clone();
}
Determines if this ticket is still current.
Returns: true if this ticket is still current, or false if not current
or destroyed.
/**
* Determines if this ticket is still current.
*
* @return true if this ticket is still current, or false if not current
* or destroyed.
*/
public boolean isCurrent() {
return endTime == null? false: (System.currentTimeMillis() <= endTime.getTime());
}
Extends the validity period of this ticket. The ticket will contain
a new session key if the refresh operation succeeds. The refresh
operation will fail if the ticket is not renewable or the latest
allowable renew time has passed. Any other error returned by the
KDC will also cause this method to fail.
Note: This method is not synchronized with the accessor
methods of this object. Hence callers need to be aware of multiple
threads that might access this and try to renew it at the same
time.
Throws: - IllegalStateException – if this ticket is destroyed
- RefreshFailedException – if the ticket is not renewable, or
the latest allowable renew time has passed, or the KDC returns some
error.
See Also:
/**
* Extends the validity period of this ticket. The ticket will contain
* a new session key if the refresh operation succeeds. The refresh
* operation will fail if the ticket is not renewable or the latest
* allowable renew time has passed. Any other error returned by the
* KDC will also cause this method to fail.
*
* Note: This method is not synchronized with the accessor
* methods of this object. Hence callers need to be aware of multiple
* threads that might access this and try to renew it at the same
* time.
*
* @throws IllegalStateException if this ticket is destroyed
* @throws RefreshFailedException if the ticket is not renewable, or
* the latest allowable renew time has passed, or the KDC returns some
* error.
*
* @see #isRenewable()
* @see #getRenewTill()
*/
public void refresh() throws RefreshFailedException {
if (destroyed) {
throw new RefreshFailedException("A destroyed ticket "
+ "cannot be renewd.");
}
if (!isRenewable()) {
throw new RefreshFailedException("This ticket is not renewable");
}
if (System.currentTimeMillis() > getRenewTill().getTime()) {
throw new RefreshFailedException("This ticket is past "
+ "its last renewal time.");
}
Throwable e = null;
sun.security.krb5.Credentials krb5Creds = null;
try {
krb5Creds = new sun.security.krb5.Credentials(asn1Encoding,
client.getName(),
server.getName(),
sessionKey.getEncoded(),
sessionKey.getKeyType(),
flags,
authTime,
startTime,
endTime,
renewTill,
clientAddresses);
krb5Creds = krb5Creds.renew();
} catch (sun.security.krb5.KrbException krbException) {
e = krbException;
} catch (java.io.IOException ioException) {
e = ioException;
}
if (e != null) {
RefreshFailedException rfException
= new RefreshFailedException("Failed to renew Kerberos Ticket "
+ "for client " + client
+ " and server " + server
+ " - " + e.getMessage());
rfException.initCause(e);
throw rfException;
}
/*
* In case multiple threads try to refresh it at the same time.
*/
synchronized (this) {
try {
this.destroy();
} catch (DestroyFailedException dfException) {
// Squelch it since we don't care about the old ticket.
}
init(krb5Creds.getEncoded(),
new KerberosPrincipal(krb5Creds.getClient().getName()),
new KerberosPrincipal(krb5Creds.getServer().getName(),
KerberosPrincipal.KRB_NT_SRV_INST),
krb5Creds.getSessionKey().getBytes(),
krb5Creds.getSessionKey().getEType(),
krb5Creds.getFlags(),
krb5Creds.getAuthTime(),
krb5Creds.getStartTime(),
krb5Creds.getEndTime(),
krb5Creds.getRenewTill(),
krb5Creds.getClientAddresses());
destroyed = false;
}
}
Destroys the ticket and destroys any sensitive information stored in
it.
/**
* Destroys the ticket and destroys any sensitive information stored in
* it.
*/
public void destroy() throws DestroyFailedException {
if (!destroyed) {
Arrays.fill(asn1Encoding, (byte) 0);
client = null;
server = null;
sessionKey.destroy();
flags = null;
authTime = null;
startTime = null;
endTime = null;
renewTill = null;
clientAddresses = null;
destroyed = true;
}
}
Determines if this ticket has been destroyed.
/**
* Determines if this ticket has been destroyed.
*/
public boolean isDestroyed() {
return destroyed;
}
Returns an informative textual representation of this KerberosTicket
. Returns: an informative textual representation of this KerberosTicket
.
/**
* Returns an informative textual representation of this {@code KerberosTicket}.
*
* @return an informative textual representation of this {@code KerberosTicket}.
*/
public String toString() {
if (destroyed) {
return "Destroyed KerberosTicket";
}
StringBuilder caddrString = new StringBuilder();
if (clientAddresses != null) {
for (int i = 0; i < clientAddresses.length; i++) {
caddrString.append("clientAddresses[" + i + "] = " +
clientAddresses[i].toString());
}
}
return ("Ticket (hex) = " + "\n" +
(new HexDumpEncoder()).encodeBuffer(asn1Encoding) + "\n" +
"Client Principal = " + client.toString() + "\n" +
"Server Principal = " + server.toString() + "\n" +
"Session Key = " + sessionKey.toString() + "\n" +
"Forwardable Ticket " + flags[FORWARDABLE_TICKET_FLAG] + "\n" +
"Forwarded Ticket " + flags[FORWARDED_TICKET_FLAG] + "\n" +
"Proxiable Ticket " + flags[PROXIABLE_TICKET_FLAG] + "\n" +
"Proxy Ticket " + flags[PROXY_TICKET_FLAG] + "\n" +
"Postdated Ticket " + flags[POSTDATED_TICKET_FLAG] + "\n" +
"Renewable Ticket " + flags[RENEWABLE_TICKET_FLAG] + "\n" +
"Initial Ticket " + flags[INITIAL_TICKET_FLAG] + "\n" +
"Auth Time = " + String.valueOf(authTime) + "\n" +
"Start Time = " + String.valueOf(startTime) + "\n" +
"End Time = " + endTime.toString() + "\n" +
"Renew Till = " + String.valueOf(renewTill) + "\n" +
"Client Addresses " +
(clientAddresses == null ? " Null " : caddrString.toString() +
"\n"));
}
Returns a hash code for this KerberosTicket
. Returns: a hash code for this KerberosTicket
. Since: 1.6
/**
* Returns a hash code for this {@code KerberosTicket}.
*
* @return a hash code for this {@code KerberosTicket}.
* @since 1.6
*/
public int hashCode() {
int result = 17;
if (isDestroyed()) {
return result;
}
result = result * 37 + Arrays.hashCode(getEncoded());
result = result * 37 + endTime.hashCode();
result = result * 37 + client.hashCode();
result = result * 37 + server.hashCode();
result = result * 37 + sessionKey.hashCode();
// authTime may be null
if (authTime != null) {
result = result * 37 + authTime.hashCode();
}
// startTime may be null
if (startTime != null) {
result = result * 37 + startTime.hashCode();
}
// renewTill may be null
if (renewTill != null) {
result = result * 37 + renewTill.hashCode();
}
// clientAddress may be null, the array's hashCode is 0
result = result * 37 + Arrays.hashCode(clientAddresses);
return result * 37 + Arrays.hashCode(flags);
}
Compares the specified object with this KerberosTicket
for equality. Returns true if the given object is also a KerberosTicket
and the two KerberosTicket
instances are equivalent. A destroyed KerberosTicket
object is only equal to itself. Params: - other – the object to compare to
Returns: true if the specified object is equal to this KerberosTicket
, false otherwise. Since: 1.6
/**
* Compares the specified object with this {@code KerberosTicket} for equality.
* Returns true if the given object is also a
* {@code KerberosTicket} and the two
* {@code KerberosTicket} instances are equivalent.
* A destroyed {@code KerberosTicket} object is only equal to itself.
*
* @param other the object to compare to
* @return true if the specified object is equal to this {@code KerberosTicket},
* false otherwise.
* @since 1.6
*/
public boolean equals(Object other) {
if (other == this) {
return true;
}
if (! (other instanceof KerberosTicket)) {
return false;
}
KerberosTicket otherTicket = ((KerberosTicket) other);
if (isDestroyed() || otherTicket.isDestroyed()) {
return false;
}
if (!Arrays.equals(getEncoded(), otherTicket.getEncoded()) ||
!endTime.equals(otherTicket.getEndTime()) ||
!server.equals(otherTicket.getServer()) ||
!client.equals(otherTicket.getClient()) ||
!sessionKey.equals(otherTicket.sessionKey) ||
!Arrays.equals(clientAddresses, otherTicket.getClientAddresses()) ||
!Arrays.equals(flags, otherTicket.getFlags())) {
return false;
}
// authTime may be null
if (authTime == null) {
if (otherTicket.getAuthTime() != null) {
return false;
}
} else {
if (!authTime.equals(otherTicket.getAuthTime())) {
return false;
}
}
// startTime may be null
if (startTime == null) {
if (otherTicket.getStartTime() != null) {
return false;
}
} else {
if (!startTime.equals(otherTicket.getStartTime())) {
return false;
}
}
if (renewTill == null) {
if (otherTicket.getRenewTill() != null) {
return false;
}
} else {
if (!renewTill.equals(otherTicket.getRenewTill())) {
return false;
}
}
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);
}
}
}