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 }