blob: c5f8899c7e91add20312aa5c3853d20d1177e5d0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.server.kerberos.kdc.authentication;
import javax.security.auth.kerberos.KerberosPrincipal;
import org.apache.directory.server.kerberos.kdc.KdcConfiguration;
import org.apache.directory.server.kerberos.shared.crypto.encryption.CipherTextHandler;
import org.apache.directory.server.kerberos.shared.crypto.encryption.EncryptionType;
import org.apache.directory.server.kerberos.shared.crypto.encryption.KeyUsage;
import org.apache.directory.server.kerberos.shared.crypto.encryption.RandomKeyFactory;
import org.apache.directory.server.kerberos.shared.exceptions.KerberosException;
import org.apache.directory.server.kerberos.shared.messages.KdcRequest;
import org.apache.directory.server.kerberos.shared.messages.components.EncTicketPart;
import org.apache.directory.server.kerberos.shared.messages.components.Ticket;
import org.apache.directory.server.kerberos.shared.messages.value.EncryptedData;
import org.apache.directory.server.kerberos.shared.messages.value.EncryptionKey;
import org.apache.directory.server.kerberos.shared.messages.value.KerberosTime;
import org.apache.directory.server.kerberos.shared.messages.value.PrincipalName;
import org.apache.directory.server.kerberos.shared.messages.value.TransitedEncoding;
import org.apache.directory.server.kerberos.shared.messages.value.flags.KdcOption;
import org.apache.directory.server.kerberos.shared.messages.value.flags.TicketFlag;
import org.apache.directory.server.kerberos.shared.messages.value.types.KerberosErrorType;
import org.apache.mina.common.IoSession;
import org.apache.mina.handler.chain.IoHandlerCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
* @version $Rev$, $Date$
*/
public class GenerateTicket implements IoHandlerCommand
{
/** the log for this class */
private static final Logger log = LoggerFactory.getLogger( GenerateTicket.class );
private String contextKey = "context";
public void execute( NextCommand next, IoSession session, Object message ) throws Exception
{
AuthenticationContext authContext = ( AuthenticationContext ) session.getAttribute( getContextKey() );
KdcRequest request = authContext.getRequest();
CipherTextHandler cipherTextHandler = authContext.getCipherTextHandler();
PrincipalName serverPrincipal = request.getServerPrincipalName();
EncryptionType encryptionType = authContext.getEncryptionType();
EncryptionKey serverKey = authContext.getServerEntry().getKeyMap().get( encryptionType );
KerberosPrincipal ticketPrincipal = request.getServerPrincipal();
EncTicketPart ticketPart = new EncTicketPart();
KdcConfiguration config = authContext.getConfig();
// The INITIAL flag indicates that a ticket was issued using the AS protocol.
ticketPart.setFlag( TicketFlag.INITIAL );
// The PRE-AUTHENT flag indicates that the client used pre-authentication.
if ( authContext.isPreAuthenticated() )
{
ticketPart.setFlag( TicketFlag.PRE_AUTHENT );
}
if ( request.getKdcOptions().isFlagSet( KdcOption.FORWARDABLE ) )
{
ticketPart.setFlag( TicketFlag.FORWARDABLE );
}
if ( request.getKdcOptions().isFlagSet( KdcOption.PROXIABLE ) )
{
ticketPart.setFlag( TicketFlag.PROXIABLE );
}
if ( request.getKdcOptions().isFlagSet( KdcOption.ALLOW_POSTDATE ) )
{
ticketPart.setFlag( TicketFlag.MAY_POSTDATE );
}
if ( request.getKdcOptions().isFlagSet( KdcOption.RENEW ) ||
request.getKdcOptions().isFlagSet( KdcOption.VALIDATE ) ||
request.getKdcOptions().isFlagSet( KdcOption.PROXY ) ||
request.getKdcOptions().isFlagSet( KdcOption.FORWARDED ) ||
request.getKdcOptions().isFlagSet( KdcOption.ENC_TKT_IN_SKEY ) )
{
throw new KerberosException( KerberosErrorType.KDC_ERR_BADOPTION );
}
EncryptionKey sessionKey = RandomKeyFactory.getRandomKey( authContext.getEncryptionType() );
ticketPart.setSessionKey( sessionKey );
ticketPart.setClientPrincipal( request.getClientPrincipal() );
ticketPart.setTransitedEncoding( new TransitedEncoding() );
KerberosTime now = new KerberosTime();
ticketPart.setAuthTime( now );
if ( request.getKdcOptions().isFlagSet( KdcOption.POSTDATED ) )
{
// TODO - possibly allow req.from range
if ( !config.isPostdateAllowed() )
{
throw new KerberosException( KerberosErrorType.KDC_ERR_POLICY );
}
ticketPart.setFlag( TicketFlag.INVALID );
ticketPart.setStartTime( request.getFrom() );
}
long till = 0;
if ( request.getTill().getTime() == 0 )
{
till = Long.MAX_VALUE;
}
else
{
till = request.getTill().getTime();
}
long endTime = Math.min( now.getTime() + config.getMaximumTicketLifetime(), till );
KerberosTime kerberosEndTime = new KerberosTime( endTime );
ticketPart.setEndTime( kerberosEndTime );
long tempRenewtime = 0;
if ( request.getKdcOptions().isFlagSet( KdcOption.RENEWABLE_OK ) &&
request.getTill().greaterThan( kerberosEndTime ) )
{
request.getKdcOptions().setFlag( KdcOption.RENEWABLE );
tempRenewtime = request.getTill().getTime();
}
if ( tempRenewtime == 0 || request.getRenewtime() == null )
{
tempRenewtime = request.getTill().getTime();
}
else
{
tempRenewtime = request.getRenewtime().getTime();
}
if ( request.getKdcOptions().isFlagSet( KdcOption.RENEWABLE ) )
{
ticketPart.setFlag( TicketFlag.RENEWABLE );
/*
* 'from' KerberosTime is OPTIONAL
*/
KerberosTime fromTime = request.getFrom();
if ( fromTime == null )
{
fromTime = new KerberosTime();
}
long renewTill = Math.min( fromTime.getTime() + config.getMaximumRenewableLifetime(), tempRenewtime );
ticketPart.setRenewTill( new KerberosTime( renewTill ) );
}
if ( request.getAddresses() != null )
{
ticketPart.setClientAddresses( request.getAddresses() );
}
//EncTicketPart ticketPart = newTicketBody.getEncTicketPart();
EncryptedData encryptedData = cipherTextHandler.seal( serverKey, ticketPart, KeyUsage.NUMBER2 );
Ticket newTicket = new Ticket( ticketPrincipal, encryptedData );
newTicket.setEncTicketPart( ticketPart );
if ( log.isDebugEnabled() )
{
log.debug( "Ticket will be issued for access to {}.", serverPrincipal.toString() );
}
authContext.setTicket( newTicket );
next.execute( session, message );
}
protected String getContextKey()
{
return ( this.contextKey );
}
}