EncTicketPart encTicketPart = new EncTicketPart();
KerberosConfig config = authContext.getConfig();
// The INITIAL flag indicates that a ticket was issued using the AS protocol.
TicketFlags ticketFlags = new TicketFlags();
encTicketPart.setFlags( ticketFlags );
ticketFlags.setFlag( TicketFlag.INITIAL );
// The PRE-AUTHENT flag indicates that the client used pre-authentication.
if ( authContext.isPreAuthenticated() )
{
ticketFlags.setFlag( TicketFlag.PRE_AUTHENT );
}
if ( request.getKdcReqBody().getKdcOptions().get( KdcOptions.FORWARDABLE ) )
{
if ( !config.isForwardableAllowed() )
{
LOG_KRB.error( "Ticket cannot be generated, because Forwadable is not allowed" );
throw new KerberosException( ErrorType.KDC_ERR_POLICY );
}
ticketFlags.setFlag( TicketFlag.FORWARDABLE );
}
if ( request.getKdcReqBody().getKdcOptions().get( KdcOptions.PROXIABLE ) )
{
if ( !config.isProxiableAllowed() )
{
LOG_KRB.error( "Ticket cannot be generated, because proxyiable is not allowed" );
throw new KerberosException( ErrorType.KDC_ERR_POLICY );
}
ticketFlags.setFlag( TicketFlag.PROXIABLE );
}
if ( request.getKdcReqBody().getKdcOptions().get( KdcOptions.ALLOW_POSTDATE ) )
{
if ( !config.isPostdatedAllowed() )
{
LOG_KRB.error( "Ticket cannot be generated, because Posdate is not allowed" );
throw new KerberosException( ErrorType.KDC_ERR_POLICY );
}
ticketFlags.setFlag( TicketFlag.MAY_POSTDATE );
}
KdcOptions kdcOptions = request.getKdcReqBody().getKdcOptions();
if ( kdcOptions.get( KdcOptions.RENEW )
|| kdcOptions.get( KdcOptions.VALIDATE )
|| kdcOptions.get( KdcOptions.PROXY )
|| kdcOptions.get( KdcOptions.FORWARDED )
|| kdcOptions.get( KdcOptions.ENC_TKT_IN_SKEY ) )
{
String msg = "";
if ( kdcOptions.get( KdcOptions.RENEW ) )
{
msg = "Ticket cannot be generated, as it's a renew";
}
if ( kdcOptions.get( KdcOptions.VALIDATE ) )
{
msg = "Ticket cannot be generated, as it's a validate";
}
if ( kdcOptions.get( KdcOptions.PROXY ) )
{
msg = "Ticket cannot be generated, as it's a proxy";
}
if ( kdcOptions.get( KdcOptions.FORWARDED ) )
{
msg = "Ticket cannot be generated, as it's forwarded";
}
if ( kdcOptions.get( KdcOptions.ENC_TKT_IN_SKEY ) )
{
msg = "Ticket cannot be generated, as it's a user-to-user ";
}
if ( LOG_KRB.isDebugEnabled() )
{
LOG_KRB.debug( msg );
}
throw new KerberosException( ErrorType.KDC_ERR_BADOPTION, msg );
}
EncryptionKey sessionKey = RandomKeyFactory.getRandomKey( authContext.getEncryptionType() );
encTicketPart.setKey( sessionKey );
encTicketPart.setCName( request.getKdcReqBody().getCName() );
encTicketPart.setCRealm( request.getKdcReqBody().getRealm() );
encTicketPart.setTransited( new TransitedEncoding() );
String serverRealm = request.getKdcReqBody().getRealm();
KerberosTime now = new KerberosTime();
encTicketPart.setAuthTime( now );
KerberosTime startTime = request.getKdcReqBody().getFrom();
/*
* "If the requested starttime is absent, indicates a time in the past,
* or is within the window of acceptable clock skew for the KDC and the
* POSTDATE option has not been specified, then the starttime of the
* ticket is set to the authentication server's current time."
*/
if ( startTime == null || startTime.lessThan( now ) || startTime.isInClockSkew( config.getAllowableClockSkew() )
&& !request.getKdcReqBody().getKdcOptions().get( KdcOptions.POSTDATED ) )
{
startTime = now;
}
/*
* "If it indicates a time in the future beyond the acceptable clock skew,
* but the POSTDATED option has not been specified, then the error
* KDC_ERR_CANNOT_POSTDATE is returned."
*/
if ( ( startTime != null ) && startTime.greaterThan( now )
&& !startTime.isInClockSkew( config.getAllowableClockSkew() )
&& !request.getKdcReqBody().getKdcOptions().get( KdcOptions.POSTDATED ) )
{
String msg = "Ticket cannot be generated, as it's in the future and the POSTDATED option is not set in the request";
LOG_KRB.error( msg );
throw new KerberosException( ErrorType.KDC_ERR_CANNOT_POSTDATE, msg );
}
/*
* "Otherwise the requested starttime is checked against the policy of the
* local realm and if the ticket's starttime is acceptable, it is set as
* requested, and the INVALID flag is set in the new ticket."
*/
if ( request.getKdcReqBody().getKdcOptions().get( KdcOptions.POSTDATED ) )
{
if ( !config.isPostdatedAllowed() )
{
String msg = "Ticket cannot be generated, cause issuing POSTDATED tickets is not allowed";
LOG_KRB.error( msg );
throw new KerberosException( ErrorType.KDC_ERR_POLICY, msg );
}
ticketFlags.setFlag( TicketFlag.POSTDATED );
ticketFlags.setFlag( TicketFlag.INVALID );
encTicketPart.setStartTime( startTime );
}
long till = 0;
if ( request.getKdcReqBody().getTill().getTime() == 0 )
{
till = Long.MAX_VALUE;
}
else
{
till = request.getKdcReqBody().getTill().getTime();
}
/*
* The end time is the minimum of (a) the requested till time or (b)
* the start time plus maximum lifetime as configured in policy.
*/
long endTime = Math.min( till, startTime.getTime() + config.getMaximumTicketLifetime() );
KerberosTime kerberosEndTime = new KerberosTime( endTime );
encTicketPart.setEndTime( kerberosEndTime );
/*
* "If the requested expiration time minus the starttime (as determined
* above) is less than a site-determined minimum lifetime, an error
* message with code KDC_ERR_NEVER_VALID is returned."
*/
if ( kerberosEndTime.lessThan( startTime ) )
{
String msg = "Ticket cannot be generated, as the endTime is below the startTime";
LOG_KRB.error( msg );
throw new KerberosException( ErrorType.KDC_ERR_NEVER_VALID, msg );
}
long ticketLifeTime = Math.abs( startTime.getTime() - kerberosEndTime.getTime() );
if ( ticketLifeTime < config.getMinimumTicketLifetime() )
{
String msg = "Ticket cannot be generated, as the Lifetime is too small";
LOG_KRB.error( msg );
throw new KerberosException( ErrorType.KDC_ERR_NEVER_VALID, msg );
}
/*
* "If the requested expiration time for the ticket exceeds what was determined
* as above, and if the 'RENEWABLE-OK' option was requested, then the 'RENEWABLE'
* flag is set in the new ticket, and the renew-till value is set as if the
* 'RENEWABLE' option were requested."
*/
KerberosTime tempRtime = request.getKdcReqBody().getRTime();
if ( request.getKdcReqBody().getKdcOptions().get( KdcOptions.RENEWABLE_OK )
&& request.getKdcReqBody().getTill().greaterThan( kerberosEndTime ) )
{
if ( !config.isRenewableAllowed() )
{
String msg = "Ticket cannot be generated, as the renew date is exceeded";
LOG_KRB.error( msg );
throw new KerberosException( ErrorType.KDC_ERR_POLICY, msg );
}
request.getKdcReqBody().getKdcOptions().set( KdcOptions.RENEWABLE );
tempRtime = request.getKdcReqBody().getTill();
}
if ( request.getKdcReqBody().getKdcOptions().get( KdcOptions.RENEWABLE ) )
{
if ( !config.isRenewableAllowed() )
{
String msg = "Ticket cannot be generated, as Renewable is not allowed";
LOG_KRB.error( msg );
throw new KerberosException( ErrorType.KDC_ERR_POLICY, msg );
}
ticketFlags.setFlag( TicketFlag.RENEWABLE );
if ( tempRtime == null || tempRtime.isZero() )
{
tempRtime = KerberosTime.INFINITY;
}