FileDocCategorySizeDatePackage
KerberosTicket.javaAPI DocJava SE 6 API22698Tue Jun 10 00:26:28 BST 2008javax.security.auth.kerberos

KerberosTicket

public class KerberosTicket extends Object implements Destroyable, Refreshable, Serializable
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 1510).

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}.

It might be necessary for the application to be granted a {@link javax.security.auth.PrivateCredentialPermission 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 {@link javax.security.auth.kerberos.ServicePermission 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.

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
version
1.21, 07/27/06
since
1.4

Fields Summary
private static final long
serialVersionUID
private static final int
FORWARDABLE_TICKET_FLAG
private static final int
FORWARDED_TICKET_FLAG
private static final int
PROXIABLE_TICKET_FLAG
private static final int
PROXY_TICKET_FLAG
private static final int
POSTDATED_TICKET_FLAG
private static final int
RENEWABLE_TICKET_FLAG
private static final int
INITIAL_TICKET_FLAG
private static final int
NUM_FLAGS
private byte[]
asn1Encoding
ASN.1 DER Encoding of the Ticket as defined in the Kerberos Protocol Specification RFC1510.
private KeyImpl
sessionKey
KeyImpl is serialized by writing out the ASN1 Encoded bytes of the encryption key. The ASN1 encoding is defined in RFC1510 and as follows:
EncryptionKey ::= SEQUENCE {
keytype[0] INTEGER,
keyvalue[1] OCTET STRING
}
private boolean[]
flags
Ticket Flags as defined in the Kerberos Protocol Specification RFC1510.
private Date
authTime
Time of initial authentication
private Date
startTime
Time after which the ticket is valid.
private Date
endTime
Time after which the ticket will not be honored. (its expiration time).
private Date
renewTill
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.
private KerberosPrincipal
client
Client that owns the service ticket
private KerberosPrincipal
server
The service for which the ticket was issued.
private InetAddress[]
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.
private transient boolean
destroyed
Constructors Summary
public KerberosTicket(byte[] asn1Encoding, KerberosPrincipal client, KerberosPrincipal server, byte[] sessionKey, int keyType, boolean[] flags, Date authTime, Date startTime, Date endTime, Date renewTill, InetAddress[] clientAddresses)
Constructs a 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.


                                                                                                                                                                                                                                                                         
       
			  
			  
			  
			  
			  
			  
			  
			  
			  
			   
       
	init(asn1Encoding, client, server, sessionKey, keyType, flags,
	    authTime, startTime, endTime, renewTill, clientAddresses);
    
Methods Summary
public voiddestroy()
Destroys the ticket and destroys any sensitive information stored in it.

	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;
	}
    
public booleanequals(java.lang.Object other)
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.

param
other the Object to compare to
return
true if the specified object is equal to this KerberosTicket, false otherwise. NOTE: Returns false if either of the KerberosTicket objects has been destroyed.
since
1.6


	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.getSessionKey()) ||
                !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;
    
public final java.util.DategetAuthTime()
Returns the time that the client was authenticated.

return
the time that the client was authenticated or null if not set.

	return (authTime == null) ? null : new Date(authTime.getTime());
    
public final javax.security.auth.kerberos.KerberosPrincipalgetClient()
Returns the client principal associated with this ticket.

return
the client principal.

	return client;
    
public final java.net.InetAddress[]getClientAddresses()
Returns a list of addresses from where the ticket can be used.

return
ths list of addresses or null, if the field was not provided.

	return (clientAddresses == null? 
		null: (InetAddress[]) clientAddresses.clone());
    
public final byte[]getEncoded()
Returns an ASN.1 encoding of the entire ticket.

return
an ASN.1 encoding of the entire ticket.

	if (destroyed)
	    throw new IllegalStateException("This ticket is no longer valid");
	return (byte[]) asn1Encoding.clone();
    
public final java.util.DategetEndTime()
Returns the expiration time for this ticket's validity period.

return
the expiration time for this ticket's validity period.

	return endTime;
    
public final boolean[]getFlags()
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.

	return (flags == null? null: (boolean[]) flags.clone());
    
public final java.util.DategetRenewTill()
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.

	return (renewTill == null) ? null: new Date(renewTill.getTime());
    
public final javax.security.auth.kerberos.KerberosPrincipalgetServer()
Returns the service principal associated with this ticket.

return
the service principal.

	return server;
    
public final javax.crypto.SecretKeygetSessionKey()
Returns the session key associated with this ticket.

return
the session key.

	if (destroyed)
	    throw new IllegalStateException("This ticket is no longer valid");
	return sessionKey;
    
public final intgetSessionKeyType()
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.
see
#getSessionKey()

	if (destroyed)
	    throw new IllegalStateException("This ticket is no longer valid");
	return sessionKey.getKeyType();
    
public final java.util.DategetStartTime()
Returns the start time for this ticket's validity period.

return
the start time for this ticket's validity period or null if not set.

	return (startTime == null) ? null : new Date(startTime.getTime());
    
public inthashCode()
Returns a hashcode for this KerberosTicket.

return
a hashCode() for the KerberosTicket
since
1.6

        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);
    
private voidinit(byte[] asn1Encoding, javax.security.auth.kerberos.KerberosPrincipal client, javax.security.auth.kerberos.KerberosPrincipal server, byte[] sessionKey, int keyType, boolean[] flags, java.util.Date authTime, java.util.Date startTime, java.util.Date endTime, java.util.Date renewTill, java.net.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;

	if (sessionKey == null)
	   throw new IllegalArgumentException("Session key for ticket"
					      + " cannot be null");
	this.sessionKey = new KeyImpl(sessionKey, keyType);

	if (flags != null) {
	   if (flags.length >= NUM_FLAGS)
		this.flags = (boolean[]) 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 = renewTill;
	}

	this.authTime = authTime;

	this.startTime = (startTime != null? startTime: authTime);

	if (endTime == null)
	   throw new IllegalArgumentException("End time for ticket validity"
					      + " cannot be null");
	this.endTime = endTime;

	if (clientAddresses != null)
	   this.clientAddresses = (InetAddress[]) clientAddresses.clone();
    
public booleanisCurrent()
Determines if this ticket is still current.

	return (System.currentTimeMillis() <= getEndTime().getTime());
    
public booleanisDestroyed()
Determines if this ticket has been destroyed.

	return destroyed;
    
public final booleanisForwardable()
Determines if this ticket is forwardable.

return
true if this ticket is forwardable, false if not.

	return flags[FORWARDABLE_TICKET_FLAG];
    
public final booleanisForwarded()
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, false otherwise.

	return flags[FORWARDED_TICKET_FLAG];
    
public final booleanisInitial()
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, false if not.

	return flags[INITIAL_TICKET_FLAG];
    
public final booleanisPostdated()
Determines is this ticket is post-dated.

return
true if this ticket is post-dated, false if not.

	return flags[POSTDATED_TICKET_FLAG];
    
public final booleanisProxiable()
Determines if this ticket is proxiable.

return
true if this ticket is proxiable, false if not.

	return flags[PROXIABLE_TICKET_FLAG];
    
public final booleanisProxy()
Determines is this ticket is a proxy-ticket.

return
true if this ticket is a proxy-ticket, false if not.

	return flags[PROXY_TICKET_FLAG];
    
public final booleanisRenewable()
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, false if not.

	return flags[RENEWABLE_TICKET_FLAG];
    
public voidrefresh()
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 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
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()


	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.toString(),
						    server.toString(),
						    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()),
		 krb5Creds.getSessionKey().getBytes(), 
		 krb5Creds.getSessionKey().getEType(), 
		 krb5Creds.getFlags(), 
		 krb5Creds.getAuthTime(), 
		 krb5Creds.getStartTime(), 
		 krb5Creds.getEndTime(), 
		 krb5Creds.getRenewTill(), 
		 krb5Creds.getClientAddresses());
	    destroyed = false;
	}
    
public java.lang.StringtoString()

	if (destroyed)
	    throw new IllegalStateException("This ticket is no longer valid");
	StringBuffer caddrBuf = new StringBuffer();
	if (clientAddresses != null) {
	    for (int i = 0; i < clientAddresses.length; i++) {
		caddrBuf.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[RENEWABLE_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 " : caddrBuf.toString() +
		"\n"));