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 */
020 package org.apache.directory.server.kerberos.shared.store;
021
022
023 import java.io.IOException;
024 import java.net.InetAddress;
025 import java.util.Date;
026
027 import javax.security.auth.kerberos.KerberosKey;
028 import javax.security.auth.kerberos.KerberosPrincipal;
029 import javax.security.auth.kerberos.KerberosTicket;
030
031 import org.apache.directory.server.kerberos.shared.KerberosConstants;
032 import org.apache.directory.server.kerberos.shared.crypto.encryption.CipherTextHandler;
033 import org.apache.directory.server.kerberos.shared.crypto.encryption.EncryptionType;
034 import org.apache.directory.server.kerberos.shared.crypto.encryption.KeyUsage;
035 import org.apache.directory.server.kerberos.shared.crypto.encryption.RandomKeyFactory;
036 import org.apache.directory.server.kerberos.shared.exceptions.KerberosException;
037 import org.apache.directory.server.kerberos.shared.io.encoder.TicketEncoder;
038 import org.apache.directory.server.kerberos.shared.messages.components.EncTicketPart;
039 import org.apache.directory.server.kerberos.shared.messages.components.EncTicketPartModifier;
040 import org.apache.directory.server.kerberos.shared.messages.components.Ticket;
041 import org.apache.directory.server.kerberos.shared.messages.value.EncryptedData;
042 import org.apache.directory.server.kerberos.shared.messages.value.EncryptionKey;
043 import org.apache.directory.server.kerberos.shared.messages.value.KerberosTime;
044 import org.apache.directory.server.kerberos.shared.messages.value.TransitedEncoding;
045 import org.apache.directory.server.kerberos.shared.messages.value.flags.TicketFlag;
046 import org.apache.directory.server.kerberos.shared.messages.value.flags.TicketFlags;
047
048
049 /**
050 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
051 * @version $Rev$, $Date$
052 */
053 public class TicketFactory
054 {
055 /** One day in milliseconds, used for default end time. */
056 private static final int ONE_DAY = 86400000;
057
058 /** One week in milliseconds, used for default renewal period. */
059 private static final int ONE_WEEK = 86400000 * 7;
060
061 private CipherTextHandler cipherTextHandler = new CipherTextHandler();
062
063
064 /**
065 * Returns a server key derived from a server principal and server password.
066 *
067 * @param serverPrincipal
068 * @param serverPassword
069 * @return The server's {@link EncryptionKey}.
070 */
071 public EncryptionKey getServerKey( KerberosPrincipal serverPrincipal, String serverPassword )
072 {
073 KerberosKey serverKerberosKey = new KerberosKey( serverPrincipal, serverPassword.toCharArray(), "DES" );
074 byte[] serverKeyBytes = serverKerberosKey.getEncoded();
075 EncryptionKey serverKey = new EncryptionKey( EncryptionType.DES_CBC_MD5, serverKeyBytes );
076
077 return serverKey;
078 }
079
080
081 /**
082 * Build the service ticket. The service ticket contains the session key generated
083 * by the KDC for the client and service to use. The service will unlock the
084 * authenticator with the session key from the ticket. The principal in the ticket
085 * must equal the authenticator client principal.
086 *
087 * If set in the AP Options, the Ticket can also be sealed with the session key.
088 *
089 * @param clientPrincipal
090 * @param serverPrincipal
091 * @param serverKey
092 * @return The {@link Ticket}.
093 * @throws KerberosException
094 */
095 public Ticket getTicket( KerberosPrincipal clientPrincipal, KerberosPrincipal serverPrincipal,
096 EncryptionKey serverKey ) throws KerberosException
097 {
098 EncTicketPartModifier encTicketModifier = new EncTicketPartModifier();
099
100 TicketFlags ticketFlags = new TicketFlags();
101 ticketFlags.setFlag( TicketFlag.RENEWABLE );
102 encTicketModifier.setFlags( ticketFlags );
103
104 EncryptionKey sessionKey = RandomKeyFactory.getRandomKey( EncryptionType.DES_CBC_MD5 );
105
106 encTicketModifier.setSessionKey( sessionKey );
107 encTicketModifier.setClientPrincipal( clientPrincipal );
108 encTicketModifier.setTransitedEncoding( new TransitedEncoding() );
109 encTicketModifier.setAuthTime( new KerberosTime() );
110
111 long now = System.currentTimeMillis();
112 KerberosTime endTime = new KerberosTime( now + ONE_DAY );
113 encTicketModifier.setEndTime( endTime );
114
115 KerberosTime renewTill = new KerberosTime( now + ONE_WEEK );
116 encTicketModifier.setRenewTill( renewTill );
117
118 EncTicketPart encTicketPart = encTicketModifier.getEncTicketPart();
119
120 EncryptedData encryptedTicketPart = cipherTextHandler.seal( serverKey, encTicketPart, KeyUsage.NUMBER2 );
121
122 Ticket ticket = new Ticket();
123 ticket.setTktVno( KerberosConstants.KERBEROS_V5 );
124 ticket.setServerPrincipal( serverPrincipal );
125 ticket.setEncPart( encryptedTicketPart );
126
127 ticket.setEncTicketPart( encTicketPart );
128
129 return ticket;
130 }
131
132
133 /**
134 * Convert an Apache Directory Kerberos {@link Ticket} into a {@link KerberosTicket}.
135 *
136 * @param ticket
137 * @return The {@link KerberosTicket}.
138 * @throws IOException
139 */
140 public KerberosTicket getKerberosTicket( Ticket ticket ) throws IOException
141 {
142 byte[] asn1Encoding = TicketEncoder.encodeTicket( ticket );
143
144 KerberosPrincipal client = ticket.getEncTicketPart().getClientPrincipal();
145 KerberosPrincipal server = ticket.getServerPrincipal();
146 byte[] sessionKey = ticket.getEncTicketPart().getSessionKey().getKeyValue();
147 int keyType = ticket.getEncTicketPart().getSessionKey().getKeyType().getOrdinal();
148
149 boolean[] flags = new boolean[32];
150
151 for ( int ii = 0; ii < flags.length; ii++ )
152 {
153 flags[ii] = ticket.getEncTicketPart().getFlags().isFlagSet( ii );
154 }
155
156 Date authTime = ticket.getEncTicketPart().getAuthTime().toDate();
157 Date endTime = ticket.getEncTicketPart().getEndTime().toDate();
158
159 Date startTime = ( ticket.getEncTicketPart().getStartTime() != null ? ticket.getEncTicketPart().getStartTime().toDate() : null );
160
161 Date renewTill = null;
162
163 if ( ticket.getEncTicketPart().getFlags().isRenewable() )
164 {
165 renewTill = ( ticket.getEncTicketPart().getRenewTill() != null ? ticket.getEncTicketPart().getRenewTill().toDate() : null );
166 }
167
168 InetAddress[] clientAddresses = new InetAddress[0];
169
170 return new KerberosTicket( asn1Encoding, client, server, sessionKey, keyType, flags, authTime, startTime,
171 endTime, renewTill, clientAddresses );
172 }
173 }