001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *  
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *  
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License. 
018 *  
019 */
020package org.apache.directory.server.kerberos.shared.store;
021
022
023import java.text.ParseException;
024
025import javax.security.auth.kerberos.KerberosKey;
026import javax.security.auth.kerberos.KerberosPrincipal;
027
028import org.apache.directory.server.kerberos.shared.crypto.encryption.CipherTextHandler;
029import org.apache.directory.server.kerberos.shared.crypto.encryption.KeyUsage;
030import org.apache.directory.server.kerberos.shared.crypto.encryption.RandomKeyFactory;
031import org.apache.directory.shared.kerberos.KerberosConstants;
032import org.apache.directory.shared.kerberos.KerberosTime;
033import org.apache.directory.shared.kerberos.codec.types.EncryptionType;
034import org.apache.directory.shared.kerberos.codec.types.PrincipalNameType;
035import org.apache.directory.shared.kerberos.components.EncTicketPart;
036import org.apache.directory.shared.kerberos.components.EncryptedData;
037import org.apache.directory.shared.kerberos.components.EncryptionKey;
038import org.apache.directory.shared.kerberos.components.PrincipalName;
039import org.apache.directory.shared.kerberos.components.TransitedEncoding;
040import org.apache.directory.shared.kerberos.exceptions.KerberosException;
041import org.apache.directory.shared.kerberos.flags.TicketFlag;
042import org.apache.directory.shared.kerberos.flags.TicketFlags;
043import org.apache.directory.shared.kerberos.messages.Ticket;
044
045
046/**
047 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
048 */
049public class TicketFactory
050{
051    /** One day in milliseconds, used for default end time. */
052    private static final int ONE_DAY = 86400000;
053
054    /** One week in milliseconds, used for default renewal period. */
055    private static final int ONE_WEEK = 86400000 * 7;
056
057    private CipherTextHandler cipherTextHandler = new CipherTextHandler();
058
059
060    /**
061     * Returns a server key derived from a server principal and server password.
062     *
063     * @param serverPrincipal
064     * @param serverPassword
065     * @return The server's {@link EncryptionKey}.
066     */
067    public EncryptionKey getServerKey( KerberosPrincipal serverPrincipal, String serverPassword )
068    {
069        KerberosKey serverKerberosKey = new KerberosKey( serverPrincipal, serverPassword.toCharArray(), "DES" );
070        byte[] serverKeyBytes = serverKerberosKey.getEncoded();
071
072        return new EncryptionKey( EncryptionType.DES_CBC_MD5, serverKeyBytes );
073    }
074
075
076    /**
077     * Build the service ticket.  The service ticket contains the session key generated
078     * by the KDC for the client and service to use.  The service will unlock the
079     * authenticator with the session key from the ticket.  The principal in the ticket
080     * must equal the authenticator client principal.
081     * 
082     * If set in the AP Options, the Ticket can also be sealed with the session key.
083     * 
084     * @param clientPrincipal
085     * @param serverPrincipal
086     * @param serverKey 
087     * @return The {@link Ticket}.
088     * @throws KerberosException
089     */
090    public Ticket getTicket( KerberosPrincipal clientPrincipal, KerberosPrincipal serverPrincipal,
091        EncryptionKey serverKey ) throws KerberosException, ParseException
092    {
093        EncTicketPart encTicketPart = new EncTicketPart();
094
095        TicketFlags ticketFlags = new TicketFlags();
096        ticketFlags.setFlag( TicketFlag.RENEWABLE );
097        encTicketPart.setFlags( ticketFlags );
098
099        EncryptionKey sessionKey = RandomKeyFactory.getRandomKey( EncryptionType.DES_CBC_MD5 );
100
101        encTicketPart.setKey( sessionKey );
102        encTicketPart.setCName( new PrincipalName( clientPrincipal.getName(), PrincipalNameType.KRB_NT_PRINCIPAL ) );
103        encTicketPart.setTransited( new TransitedEncoding() );
104        encTicketPart.setAuthTime( new KerberosTime() );
105
106        long now = System.currentTimeMillis();
107        KerberosTime endTime = new KerberosTime( now + ONE_DAY );
108        encTicketPart.setEndTime( endTime );
109
110        KerberosTime renewTill = new KerberosTime( now + ONE_WEEK );
111        encTicketPart.setRenewTill( renewTill );
112
113        EncryptedData encryptedTicketPart = cipherTextHandler.seal( serverKey, encTicketPart,
114            KeyUsage.AS_OR_TGS_REP_TICKET_WITH_SRVKEY );
115
116        Ticket ticket = new Ticket();
117        ticket.setTktVno( KerberosConstants.KERBEROS_V5 );
118        ticket.setSName( new PrincipalName( serverPrincipal.getName(), PrincipalNameType.KRB_NT_PRINCIPAL ) );
119        ticket.setRealm( serverPrincipal.getRealm() );
120        ticket.setEncPart( encryptedTicketPart );
121
122        return ticket;
123    }
124}