long clockSkew, ReplayCache replayCache, boolean emptyAddressesAllowed, InetAddress clientAddress,
CipherTextHandler lockBox, KeyUsage authenticatorKeyUsage, boolean isValidate ) throws KerberosException
{
if ( authHeader.getProtocolVersionNumber() != KerberosConstants.KERBEROS_V5 )
{
throw new KerberosException( ErrorType.KRB_AP_ERR_BADVERSION );
}
if ( authHeader.getMessageType() != KerberosMessageType.AP_REQ )
{
throw new KerberosException( ErrorType.KRB_AP_ERR_MSG_TYPE );
}
if ( authHeader.getTicket().getTktVno() != KerberosConstants.KERBEROS_V5 )
{
throw new KerberosException( ErrorType.KRB_AP_ERR_BADVERSION );
}
EncryptionKey ticketKey = null;
if ( authHeader.getOption( ApOptions.USE_SESSION_KEY ) )
{
ticketKey = authHeader.getTicket().getEncTicketPart().getSessionKey();
}
else
{
ticketKey = serverKey;
}
if ( ticketKey == null )
{
// TODO - check server key version number, skvno; requires store
if ( false )
{
throw new KerberosException( ErrorType.KRB_AP_ERR_BADKEYVER );
}
throw new KerberosException( ErrorType.KRB_AP_ERR_NOKEY );
}
EncTicketPart encPart = ( EncTicketPart ) lockBox.unseal( EncTicketPart.class, ticketKey, ticket.getEncPart(),
KeyUsage.NUMBER2 );
ticket.setEncTicketPart( encPart );
Authenticator authenticator = ( Authenticator ) lockBox.unseal( Authenticator.class, ticket.getEncTicketPart().getSessionKey(),
authHeader.getEncPart(), authenticatorKeyUsage );
if ( !authenticator.getClientPrincipal().getName().equals( ticket.getEncTicketPart().getClientPrincipal().getName() ) )
{
throw new KerberosException( ErrorType.KRB_AP_ERR_BADMATCH );
}
if ( ticket.getEncTicketPart().getClientAddresses() != null )
{
if ( !ticket.getEncTicketPart().getClientAddresses().contains( new HostAddress( clientAddress ) ) )
{
throw new KerberosException( ErrorType.KRB_AP_ERR_BADADDR );
}
}
else
{
if ( !emptyAddressesAllowed )
{
throw new KerberosException( ErrorType.KRB_AP_ERR_BADADDR );
}
}
KerberosPrincipal serverPrincipal = ticket.getServerPrincipal();
KerberosPrincipal clientPrincipal = authenticator.getClientPrincipal();
KerberosTime clientTime = authenticator.getClientTime();
int clientMicroSeconds = authenticator.getClientMicroSecond();
if ( replayCache.isReplay( serverPrincipal, clientPrincipal, clientTime, clientMicroSeconds ) )
{
throw new KerberosException( ErrorType.KRB_AP_ERR_REPEAT );
}
replayCache.save( serverPrincipal, clientPrincipal, clientTime, clientMicroSeconds );
if ( !authenticator.getClientTime().isInClockSkew( clockSkew ) )
{
throw new KerberosException( ErrorType.KRB_AP_ERR_SKEW );
}
/*
* "The server computes the age of the ticket: local (server) time minus
* the starttime inside the Ticket. If the starttime is later than the
* current time by more than the allowable clock skew, or if the INVALID
* flag is set in the ticket, the KRB_AP_ERR_TKT_NYV error is returned."
*/
KerberosTime startTime = ( ticket.getEncTicketPart().getStartTime() != null ) ? ticket.getEncTicketPart().getStartTime() : ticket.getEncTicketPart().getAuthTime();
KerberosTime now = new KerberosTime();
boolean isValidStartTime = startTime.lessThan( now );
if ( !isValidStartTime || ( ticket.getEncTicketPart().getFlags().isInvalid() && !isValidate ) )
{
// it hasn't yet become valid
throw new KerberosException( ErrorType.KRB_AP_ERR_TKT_NYV );
}
// TODO - doesn't take into account skew
if ( !ticket.getEncTicketPart().getEndTime().greaterThan( now ) )
{
throw new KerberosException( ErrorType.KRB_AP_ERR_TKT_EXPIRED );
}
authHeader.setOption( ApOptions.MUTUAL_REQUIRED );
return authenticator;