directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From erodrig...@apache.org
Subject svn commit: rev 51808 - incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc
Date Sat, 02 Oct 2004 16:52:35 GMT
Author: erodriguez
Date: Sat Oct  2 09:52:35 2004
New Revision: 51808

Added:
   incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/AuthenticationService.java
   incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/DefaultConfig.java
   incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/KdcDispatcher.java
   incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/KerberosException.java
   incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/RealmException.java
   incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/TicketGrantingService.java
Log:
core kerberos services and dispatcher

Added: incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/AuthenticationService.java
==============================================================================
--- (empty file)
+++ incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/AuthenticationService.java
Sat Oct  2 09:52:35 2004
@@ -0,0 +1,248 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.kerberos.kdc;
+
+import org.apache.kerberos.crypto.*;
+import org.apache.kerberos.io.encoder.*;
+import org.apache.kerberos.messages.*;
+import org.apache.kerberos.messages.components.*;
+import org.apache.kerberos.messages.value.*;
+import org.apache.kerberos.util.keytab.*;
+
+public class AuthenticationService {
+	
+	private KeyList _keytab;
+	
+	public AuthenticationService(KeyList keytab) {
+		_keytab = keytab;
+	}
+	
+	public AuthenticationReply getReplyFor(KdcRequest request) throws KeytabException, KerberosException
{
+		
+		Realm realm = request.getRealm();
+		
+		PrincipalName client = request.getCname();
+		client.setRealm(realm);
+		EncryptionKey clientKey = _keytab.getEncryptionKey(client);
+		
+		PrincipalName server = request.getSname();
+		server.setRealm(realm);
+		EncryptionKey serverKey = _keytab.getEncryptionKey(server);
+		
+		verifyPreAuthentication(request, client);
+		
+		Ticket ticket = getTicket(request);
+		encryptTicketPart(ticket, serverKey);		
+		AuthenticationReply reply = getAuthenticationReply(request, ticket);
+		encryptReplyPart(reply, clientKey);
+		System.out.print("Got request from client " + client.toString() + " ");
+		System.out.println("for access to " + server.toString());
+		return reply;
+	}
+	
+	// TODO - currently no support for pre-auth; requires server store support
+	private void verifyPreAuthentication(KdcRequest request, PrincipalName client) {
+		/*
+		if(client.pa_enc_timestamp_required and
+		   pa_enc_timestamp not present) then
+		        error_out(KDC_ERR_PREAUTH_REQUIRED(PA_ENC_TIMESTAMP));
+		endif
+		*/
+		
+		/*
+		if(pa_enc_timestamp present) then
+		        decrypt req.padata-value into decrypted_enc_timestamp
+		                using client.key;
+		                using auth_hdr.authenticator.subkey;
+		        if (decrypt_error()) then
+		                error_out(KRB_AP_ERR_BAD_INTEGRITY);
+		        if(decrypted_enc_timestamp is not within allowable
+		                skew) then error_out(KDC_ERR_PREAUTH_FAILED);
+		        endif
+		        if(decrypted_enc_timestamp and usec is replay)
+		                error_out(KDC_ERR_PREAUTH_FAILED);
+		        endif
+		        add decrypted_enc_timestamp and usec to replay cache;
+		endif
+		*/
+		
+		/*
+		 	if (LocalConfig.DEFAULT_PA_ENC_TIMESTAMP_REQUIRED) {
+			byte[] encTimeStamp = CryptoService.getEncryptedTimestamp(key, new Date());
+			if (key != null) {
+				paData = new PreAuthenticationData[1];
+				paData[0] = new PreAuthenticationData(PreAuthenticationData.PA_ENC_TIMESTAMP, encTimeStamp);
+			}
+		}
+		 */
+	}
+	
+	// TODO - client and server parameters; requires store
+	private Ticket getTicket(KdcRequest request) throws KerberosException {
+		
+		Ticket newTicket = new Ticket();
+		newTicket.setTicketVersionNumber(LocalConfig.TICKET_VNO);
+		
+		newTicket.setServerName(request.getSname());
+		newTicket.setRealm(request.getRealm());
+		
+		if(request.getKdcOptions().get(KdcOptions.FORWARDABLE))
+			newTicket.getFlags().set(TicketFlags.FORWARDABLE);
+		
+		if(request.getKdcOptions().get(KdcOptions.PROXIABLE))
+			newTicket.getFlags().set(TicketFlags.PROXIABLE);
+		
+		if(request.getKdcOptions().get(KdcOptions.ALLOW_POSTDATE))
+			newTicket.getFlags().set(TicketFlags.MAY_POSTDATE);
+		
+		if(request.getKdcOptions().get(KdcOptions.RENEW) ||
+				request.getKdcOptions().get(KdcOptions.VALIDATE) ||
+				request.getKdcOptions().get(KdcOptions.PROXY) ||
+				request.getKdcOptions().get(KdcOptions.FORWARDED) ||
+				request.getKdcOptions().get(KdcOptions.ENC_TKT_IN_SKEY))
+			throw KerberosException.KDC_ERR_BADOPTION;
+		
+		newTicket.setSessionKey(CryptoService.getNewSessionKey());
+		newTicket.setClientName(request.getCname());
+		newTicket.setClientRealm(request.getRealm());
+		newTicket.setTransitedEncoding(new TransitedEncoding());
+		
+		KerberosTime now = new KerberosTime();
+		newTicket.setAuthtime(now);
+	
+		if(request.getKdcOptions().get(KdcOptions.POSTDATED)) {
+			// TODO - possibly allow req.from range
+			if (!LocalConfig.KDC_POSTDATE_ALLOWED)
+				throw KerberosException.KDC_ERR_POLICY;
+			newTicket.setFlag(TicketFlags.INVALID);
+			newTicket.setStartTime(request.getFrom());
+		}
+	
+	long till = 0;
+	if (request.getTill().getTime() == 0)
+	        till = Long.MAX_VALUE;
+	else
+	        till = request.getTill().getTime();
+	/*
+	new_tkt.endtime := min(till,
+	                      new_tkt.starttime+client.max_life,
+	                      new_tkt.starttime+server.max_life,
+	                      new_tkt.starttime+max_life_for_realm);
+	*/
+	long endTime = Math.min(now.getTime() + LocalConfig.DEFAULT_MAXIMUM_TICKET_LIFETIME, till);
+	newTicket.setEndTime(new KerberosTime(endTime));
+
+	long tempRtime = 0;
+	if (request.getKdcOptions().get(KdcOptions.RENEWABLE_OK) &&
+			request.getTill().greaterThan(newTicket.getEndTime())) {
+		request.getKdcOptions().set(KdcOptions.RENEWABLE);
+		tempRtime = request.getTill().getTime();
+	}
+	
+	/*
+	if (req.kdc-options.RENEWABLE is set) then
+	        set new_tkt.flags.RENEWABLE;
+	        new_tkt.renew-till := min(rtime,
+	        new_tkt.starttime+client.max_rlife,
+	        new_tkt.starttime+server.max_rlife,
+	        new_tkt.starttime+max_rlife_for_realm);
+	else
+	        omit new_tkt.renew-till;
+	endif
+	*/
+	if (tempRtime == 0)
+			tempRtime = Long.MAX_VALUE;
+		else
+			tempRtime = request.getRtime().getTime();
+
+		if (request.getKdcOptions().get(KdcOptions.RENEWABLE)) {
+			newTicket.getFlags().set(TicketFlags.RENEWABLE);
+			long renewTill = Math.min(newTicket.getStartTime().getTime()
+					+ LocalConfig.DEFAULT_MAXIMUM_RENEWABLE_LIFETIME, tempRtime);
+			newTicket.setRenewTill(new KerberosTime(renewTill));
+		}
+
+		if (request.getAddresses() != null)
+			newTicket.setClientAddresses(request.getAddresses());
+		return newTicket;
+	}
+	
+	// TODO - support multiple encryption types
+	private void encryptTicketPart(Ticket ticket, EncryptionKey serverKey) {
+		EncTicketPartEncoder encoder = new EncTicketPartEncoder();
+
+		try {
+			byte[] plainText = encoder.encode(ticket);
+			
+			CryptoService enc = new CryptoService();
+			
+			EncryptedData cipherText = enc.getEncryptedData(serverKey, plainText);
+			
+			ticket.setEncPart(cipherText);
+			
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+	
+	// TODO - support multiple encryption types
+	private void encryptReplyPart(AuthenticationReply reply, EncryptionKey clientKey) {
+		EncAsRepPartEncoder encoder = new EncAsRepPartEncoder();
+		try {
+			byte[] plainText = encoder.encode(reply);
+			
+			CryptoService enc = new CryptoService();
+			
+			EncryptedData cipherText = enc.getEncryptedData(clientKey, plainText);
+
+			reply.setEncPart(cipherText);
+			
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+	
+	private AuthenticationReply getAuthenticationReply(KdcRequest request, Ticket ticket) {
+		AuthenticationReply reply = new AuthenticationReply();
+		
+		reply.setCname(request.getCname());
+		reply.setCrealm(request.getRealm());
+		reply.setTicket(ticket);
+		reply.setKey(ticket.getSessionKey());
+		
+		// TODO - fetch lastReq for this client; requires store
+		reply.setLastRequest(new LastRequest());
+		// TODO	- resp.key-expiration := client.expiration; requires store
+		
+		reply.setNonce(request.getNonce());
+		
+		reply.setFlags(ticket.getFlags());
+		reply.setAuthTime(ticket.getAuthtime());
+		reply.setStartTime(ticket.getStartTime());
+		reply.setEndTime(ticket.getEndTime());
+		
+		if (ticket.getFlags().get(TicketFlags.RENEWABLE))
+			reply.setRenewTill(ticket.getRenewTill());
+		
+		reply.setServerRealm(ticket.getRealm());
+		reply.setServerName(ticket.getServerName());
+		reply.setClientAddresses(ticket.getClientAddresses());
+		
+		return reply;
+	}
+}
+

Added: incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/DefaultConfig.java
==============================================================================
--- (empty file)
+++ incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/DefaultConfig.java
Sat Oct  2 09:52:35 2004
@@ -0,0 +1,86 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.kerberos.kdc;
+
+import org.apache.kerberos.crypto.encryption.*;
+import org.apache.kerberos.kdc.replay.*;
+import org.apache.kerberos.messages.value.*;
+import org.apache.kerberos.util.keytab.*;
+
+public class DefaultConfig {
+	
+    // Default inet port
+	public static final int KDC_INET_DEFAULT_PORT   = 88;
+    // Default server name
+	public static final String TGS_DEFAULT_SRV_NAME = "krbtgt";
+	// Default NT
+	public static final int TGS_DEFAULT_NT          = PrincipalName.KRB_NT_SRV_INST;
+	
+    public static final ReplayCache REPLAY_CACHE    = new InMemoryReplayCache();
+    
+    // Default encryption type
+	public static final EncryptionType DEFAULT_ETYPE        = EncryptionType.DES_CBC_MD5;
+
+    // Default encryption type list 
+	public static final EncryptionType[] DEFAULT_ETYPE_LIST = { EncryptionType.DES_CBC_MD5,
+			EncryptionType.DES_CBC_MD4,	EncryptionType.DES_CBC_CRC
+	};
+	
+	// Time constants
+	public static final long MINUTE                             = 60 * 1000;
+	public static final long DAY                                = 24 * 60 * MINUTE;
+	public static final long WEEK                               = 7 * DAY;
+    // Default allowable clock skew
+	public static final long DEFAULT_ALLOWABLE_CLOCKSKEW        = 5 * MINUTE;
+    // Default minimum lifetime
+	public static final long DEFAULT_MINIMUM_LIFETIME           = 5 * MINUTE;
+    // Default maximum renewable lifetime
+	public static final long DEFAULT_MAXIMUM_RENEWABLE_LIFETIME = 1 * WEEK;
+    // Default maximum ticket lifetime
+	public static final long DEFAULT_MAXIMUM_TICKET_LIFETIME    = 1 * DAY;
+	
+	// Site specific values
+    // Whether to allow empty address 
+	public static final boolean DEFAULT_EMPTY_ADDRESSES_ALLOWED    = true;
+    // Whether forwarding is allowed
+	public static final boolean DEFAULT_FORWARDABLE_ALLOWED        = true;
+    // Whether to allow proxy
+	public static final boolean DEFAULT_PROXIABLE_ALLOWED          = true;
+    // Whether to allow postdated credentials
+	public static final boolean DEFAULT_POSTDATE_ALLOWED           = true;
+    // Whether to allow renewable credentials
+	public static final boolean DEFAULT_RENEWABLE_ALLOWED          = true;
+    // DEFAULT_PA_ENC_TIMESTAMP_REQUIRED = true
+	public static final boolean DEFAULT_PA_ENC_TIMESTAMP_REQUIRED  = true;
+    // DEFAULT_AP_EMPTY_ADDRESSES_ALLOWED = true
+	public static final boolean DEFAULT_AP_EMPTY_ADDRESSES_ALLOWED = true;
+	
+	// Protocol constants and associated values
+    // Transited encoding type - Domain x500 compress
+	public static final int DOMAIN_X500_COMPRESS = 1;
+
+    // Kerberos protocol version number
+	public static final int PVNO              = 5;
+    // Authenticator version number
+	public static final int AUTHENTICATOR_VNO = 5;
+    // Ticket version number
+	public static final int TICKET_VNO        = 5;
+    // Default keytab version number
+	public static final int KT_VNO            = Keytab.VNO_2;
+	
+}
+

Added: incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/KdcDispatcher.java
==============================================================================
--- (empty file)
+++ incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/KdcDispatcher.java
Sat Oct  2 09:52:35 2004
@@ -0,0 +1,94 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.kerberos.kdc;
+
+import org.apache.kerberos.io.decoder.*;
+import org.apache.kerberos.io.encoder.*;
+import org.apache.kerberos.kdc.replay.*;
+import org.apache.kerberos.messages.*;
+import org.apache.kerberos.util.*;
+import org.apache.kerberos.util.keytab.*;
+
+import java.io.*;
+
+public class KdcDispatcher {
+	
+	private static final byte AS_REQ  = (byte) 0x6A;
+	private static final byte AS_REP  = (byte) 0x6B;
+	private static final byte TGS_REQ = (byte) 0x6C;
+	private static final byte TGS_REP = (byte) 0x6D;
+	
+	private static final ReplayCache replay = LocalConfig.REPLAY_CACHE;
+	
+	private static final KdcRequestDecoder decoder = new KdcRequestDecoder();
+	private static final KdcReplyEncoder   encoder = new KdcReplyEncoder();
+	
+	private AuthenticationService _authService;
+	private TicketGrantingService _tgsService;
+	private KeyList _store;
+	
+	public KdcDispatcher(KeyList store) {
+		_store       = store;
+		_authService = new AuthenticationService(_store);
+		_tgsService  = new TicketGrantingService(_store, replay);
+	}
+	
+	public byte[] dispatch(byte[] requestBytes) throws IOException, KerberosException, KeytabException
{
+		
+		TestUtils.hexdump(requestBytes);
+		
+		ByteArrayInputStream  input  = new ByteArrayInputStream(requestBytes);
+		ByteArrayOutputStream output = new ByteArrayOutputStream();
+		
+		KdcRequest request = decoder.decode(input);
+
+		byte messageType = requestBytes[0];
+		
+		switch (messageType) {
+			
+			case AS_REQ:
+				// generate the reply
+				AuthenticationReply authReply = _authService.getReplyFor(request);
+				// ASN1 encode the reply
+				encoder.encode(authReply, output);
+	    		
+				break;
+			
+			case TGS_REQ:
+				// generate the reply
+				TicketGrantReply ticketReply = _tgsService.getReplyFor(request);
+				// ASN1 encode the reply
+				encoder.encode(ticketReply, output);
+				
+	    		break;
+	    		
+	    	case AS_REP:
+	    	case TGS_REP:
+	    		throw new IOException("We should not be receiving reply messages");
+	    		
+			default:
+				System.out.println("Message received with tag " + messageType);
+		}
+		
+		byte[] replyBytes = output.toByteArray();
+		
+		TestUtils.hexdump(replyBytes);
+		
+		return replyBytes;
+	}
+}
+

Added: incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/KerberosException.java
==============================================================================
--- (empty file)
+++ incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/KerberosException.java
Sat Oct  2 09:52:35 2004
@@ -0,0 +1,175 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.kerberos.kdc;
+
+public class KerberosException extends Exception {
+
+	public static final KerberosException KDC_ERR_NONE = new KerberosException(0,
+			"No error");
+	public static final KerberosException KDC_ERR_NAME_EXP = new KerberosException(1,
+			"Client's entry in database expired");
+	public static final KerberosException KDC_ERR_SERVICE_EXP = new KerberosException(2,
+			"Server's entry in database has expired");
+	public static final KerberosException KDC_ERR_BAD_PVNO = new KerberosException(3,
+			"Requested protocol version number not supported");
+	public static final KerberosException KDC_ERR_C_OLD_MAST_KVNO = new KerberosException(4,
+			"Client's key encrypted in old master key");
+	public static final KerberosException KDC_ERR_S_OLD_MAST_KVNO = new KerberosException(5,
+			"Server's key encrypted in old master key");
+	public static final KerberosException KDC_ERR_C_PRINCIPAL_UNKNOWN = new KerberosException(6,
+			"Client not found in Kerberos database");
+	public static final KerberosException KDC_ERR_S_PRINCIPAL_UNKNOWN = new KerberosException(7,
+			"Server not found in Kerberos database");
+	public static final KerberosException KDC_ERR_PRINCIPAL_NOT_UNIQUE = new KerberosException(8,
+			"Multiple principal entries in database");
+	public static final KerberosException KDC_ERR_NULL_KEY = new KerberosException(9,
+			"The client or server has a null key");
+	public static final KerberosException KDC_ERR_CANNOT_POSTDATE = new KerberosException(10,
+			"Ticket not eligible for postdating");
+	public static final KerberosException KDC_ERR_NEVER_VALID = new KerberosException(11,
+			"Requested start time is later than end time");
+	public static final KerberosException KDC_ERR_POLICY = new KerberosException(12,
+			"KDC policy rejects request");
+	public static final KerberosException KDC_ERR_BADOPTION = new KerberosException(13,
+			"KDC cannot accommodate requested option");
+	public static final KerberosException KDC_ERR_ETYPE_NOSUPP = new KerberosException(14,
+			"KDC has no support for encryption type");
+	public static final KerberosException KDC_ERR_SUMTYPE_NOSUPP = new KerberosException(15,
+			"KDC has no support for checksum type");
+	public static final KerberosException KDC_ERR_PADATA_TYPE_NOSUPP = new KerberosException(16,
+			"KDC has no support for padata type");
+	public static final KerberosException KDC_ERR_TRTYPE_NOSUPP = new KerberosException(17,
+			"KDC has no support for transitedEncoding type");
+	public static final KerberosException KDC_ERR_CLIENT_REVOKED = new KerberosException(18,
+			"Clients credentials have been revoked");
+	public static final KerberosException KDC_ERR_SERVICE_REVOKED = new KerberosException(19,
+			"Credentials for server have been revoked");
+	public static final KerberosException KDC_ERR_TGT_REVOKED = new KerberosException(20,
+			"TGT has been revoked");
+	public static final KerberosException KDC_ERR_CLIENT_NOTYET = new KerberosException(21,
+			"Client not yet valid - try again later");
+	public static final KerberosException KDC_ERR_SERVICE_NOTYET = new KerberosException(22,
+			"Server not yet valid - try again later");
+	public static final KerberosException KDC_ERR_KEY_EXPIRED = new KerberosException(23,
+			"Password has expired - change password to reset");
+	public static final KerberosException KDC_ERR_PREAUTH_FAILED = new KerberosException(24,
+			"Pre-authentication information was invalid");
+	public static final KerberosException KDC_ERR_PREAUTH_REQUIRED = new KerberosException(25,
+			"Additional pre-authentication required");
+	public static final KerberosException KDC_ERR_SERVER_NOMATCH = new KerberosException(26,
+			"Requested server and ticket don't match");
+	public static final KerberosException KDC_ERR_MUST_USE_USER2USER = new KerberosException(27,
+			"Server valid for user2user only");
+	public static final KerberosException KDC_ERR_PATH_NOT_ACCEPTED = new KerberosException(28,
+			"KDC Policy rejects transitedEncoding path");
+	public static final KerberosException KDC_ERR_SVC_UNAVAILABLE = new KerberosException(29,
+			"A service is not available");
+	public static final KerberosException KRB_AP_ERR_BAD_INTEGRITY = new KerberosException(31,
+			"Integrity check on decrypted field failed");
+	public static final KerberosException KRB_AP_ERR_TKT_EXPIRED = new KerberosException(32,
+			"Ticket expired");
+	public static final KerberosException KRB_AP_ERR_TKT_NYV = new KerberosException(33,
+			"Ticket not yet valid");
+	public static final KerberosException KRB_AP_ERR_REPEAT = new KerberosException(34,
+			"Request is a replay");
+	public static final KerberosException KRB_AP_ERR_NOT_US = new KerberosException(35,
+			"The ticket isn't for us");
+	public static final KerberosException KRB_AP_ERR_BADMATCH = new KerberosException(36,
+			"Ticket and authenticator don't match");
+	public static final KerberosException KRB_AP_ERR_SKEW = new KerberosException(37,
+			"Clock skew too great");
+	public static final KerberosException KRB_AP_ERR_BADADDR = new KerberosException(38,
+			"Incorrect net address");
+	public static final KerberosException KRB_AP_ERR_BADVERSION = new KerberosException(39,
+			"Protocol version mismatch");
+	public static final KerberosException KRB_AP_ERR_MSG_TYPE = new KerberosException(40,
+			"Invalid msg type");
+	public static final KerberosException KRB_AP_ERR_MODIFIED = new KerberosException(41,
+			"Message stream modified");
+	public static final KerberosException KRB_AP_ERR_BADORDER = new KerberosException(42,
+			"Message out of order");
+	public static final KerberosException KRB_AP_ERR_BADKEYVER = new KerberosException(44,
+			"Specified version of key is not available");
+	public static final KerberosException KRB_AP_ERR_NOKEY = new KerberosException(45,
+			"Service key not available");
+	public static final KerberosException KRB_AP_ERR_MUT_FAIL = new KerberosException(46,
+			"Mutual authentication failed");
+	public static final KerberosException KRB_AP_ERR_BADDIRECTION = new KerberosException(47,
+			"Incorrect message direction");
+	public static final KerberosException KRB_AP_ERR_METHOD = new KerberosException(48,
+			"Alternative authentication method required");
+	public static final KerberosException KRB_AP_ERR_BADSEQ = new KerberosException(49,
+			"Incorrect sequence number in message");
+	public static final KerberosException KRB_AP_ERR_INAPP_CKSUM = new KerberosException(50,
+			"Inappropriate type of checksum in message");
+	public static final KerberosException KRB_ERR_GENERIC = new KerberosException(60,
+			"Generic error (description in e-text)");
+	public static final KerberosException KRB_ERR_FIELD_TOOLONG = new KerberosException(61,
+			"Field is too long for this implementation");
+	public static final KerberosException KRB_ERR_CLIENT_NOT_TRUSTED = new KerberosException(62,
+			"Client is not trusted");
+	public static final KerberosException KRB_ERR_KDC_NOT_TRUSTED = new KerberosException(63,
+			"KDC is not trusted");
+	public static final KerberosException KRB_ERR_INVALID_SIG = new KerberosException(64,
+			"Signature is invalid");
+	public static final KerberosException KRB_ERR_KEY_TOO_WEAK = new KerberosException(65,
+			"Key too weak");
+	public static final KerberosException KRB_ERR_CERTIFICATE_MISMATCH = new KerberosException(66,
+			"Certificates do not match");
+	public static final KerberosException KRB_AP_ERR_NO_TGT = new KerberosException(67,
+			"No tgt for user-to-user authentication");
+	public static final KerberosException KRB_ERR_WRONG_REALM = new KerberosException(68,
+			"Wrong realm");
+	public static final KerberosException KRB_AP_ERR_USER_TO_USER_REQUIRED = new KerberosException(
+			69, "User-to-user authentication required");
+	public static final KerberosException KRB_ERR_CANT_VERIFY_CERTIFICATE = new KerberosException(
+			70, "Can't verify certificate");
+	public static final KerberosException KRB_ERR_INVALID_CERTIFICATE = new KerberosException(71,
+			"Invalid certificate");
+	public static final KerberosException KRB_ERR_REVOKED_CERTIFICATE = new KerberosException(72,
+			"Revoked certificate");
+	public static final KerberosException KRB_ERR_REVOCATION_STATUS_UNKNOWN = new KerberosException(
+			73, "Revocation status unknown");
+	public static final KerberosException KRB_ERR_REVOCATION_STATUS_UNAVAILABLE = new KerberosException(
+			74, "Revocation status unavailable");
+	public static final KerberosException KRB_ERR_CLIENT_NAME_MISMATCH = new KerberosException(75,
+			"Client names do not match");
+	public static final KerberosException KRB_ERR_KDC_NAME_MISMATCH = new KerberosException(76,
+			"KDC names do not match");
+
+	public String toString() {
+		return _fName;
+	}
+	
+	public int getOrdinal() {
+		return _fOrdinal;
+	}
+
+	/// PRIVATE /////
+	private final String _fName;
+	private final int    _fOrdinal;
+
+	/**
+	 * Private constructor prevents construction outside of this class.
+	 */
+	private KerberosException(int ordinal, String name) {
+		super(name);
+		_fOrdinal = ordinal;
+		_fName    = name;
+	}
+}
+

Added: incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/RealmException.java
==============================================================================
--- (empty file)
+++ incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/RealmException.java
Sat Oct  2 09:52:35 2004
@@ -0,0 +1,49 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.kerberos.kdc;
+
+public class RealmException extends Exception {
+
+	public static final RealmException REALM_ILLEGAL_CHAR = new RealmException(600,
+			"Illegal character in realm name; one of: '/', ':'");
+
+	public static final RealmException REALM_NULL_NAME = new RealmException(601,
+			"Null realm name");
+	
+	
+	public String toString() {
+		return _fName;
+	}
+	
+	public int getOrdinal() {
+		return _fOrdinal;
+	}
+
+	/// PRIVATE /////
+	private final String _fName;
+	private final int    _fOrdinal;
+
+	/**
+	 * Private constructor prevents construction outside of this class.
+	 */
+	private RealmException(int ordinal, String name) {
+		super(name);
+		_fOrdinal = ordinal;
+		_fName    = name;
+	}
+}
+

Added: incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/TicketGrantingService.java
==============================================================================
--- (empty file)
+++ incubator/directory/kerberos/trunk/source/main/org/apache/kerberos/kdc/TicketGrantingService.java
Sat Oct  2 09:52:35 2004
@@ -0,0 +1,566 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.kerberos.kdc;
+
+import org.apache.kerberos.crypto.*;
+import org.apache.kerberos.crypto.checksum.*;
+import org.apache.kerberos.crypto.encryption.*;
+import org.apache.kerberos.io.decoder.*;
+import org.apache.kerberos.io.encoder.*;
+import org.apache.kerberos.kdc.replay.*;
+import org.apache.kerberos.messages.*;
+import org.apache.kerberos.messages.components.*;
+import org.apache.kerberos.messages.value.*;
+import org.apache.kerberos.util.keytab.*;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * RFC 1510 A.6.  KRB_TGS_REQ verification and KRB_TGS_REP generation
+ */
+public class TicketGrantingService {
+	
+	private KeyList     _keytab;
+	private ReplayCache _replayCache;
+	
+	public TicketGrantingService(KeyList keytab, ReplayCache replay) {
+		_keytab      = keytab;
+		_replayCache = replay;
+	}
+	
+	public TicketGrantReply getReplyFor(KdcRequest request) throws KerberosException, IOException,
KeytabException {
+		
+		System.out.println("Got request from " + request.getCname() + "@" + request.getRealm());
+		
+		ApplicationRequest authHeader = getAuthHeader(request);
+		
+		Ticket tgt = authHeader.getTicket();
+		
+		Authenticator authenticator = verifyApReq(authHeader, tgt);
+		
+		verifyTicket(authHeader, request);
+		
+		Realm realm = tgt.getRealm();
+		
+		verifyBodyChecksum(authenticator.getChecksum(), request);
+		
+		EncryptionKey serverKey = getServerKey(request);
+		
+		EncryptionKey sessionKey = CryptoService.getNewSessionKey();
+		
+		EncryptionType eType = CryptoService.getBestEncryptionType(request.getEType());
+		
+		Ticket newTicket = getNewTicket(request, tgt, realm, sessionKey, authenticator);
+		
+		processTimes(request, newTicket, tgt);
+		
+		processTransited(newTicket, tgt);
+		
+		encryptTicketPart(newTicket, serverKey, request);
+		
+		TicketGrantReply reply = getReply(tgt, newTicket, sessionKey, request);
+		
+		if (authenticator.getSubSessionKey() != null) {
+			System.out.println("Using authenticator sub session key.");
+			EncryptionKey subKey = authenticator.getSubSessionKey();
+			encryptReplyPart(reply, subKey);
+		} else {
+			System.out.println("Using session key.");
+			encryptReplyPart(reply, tgt.getSessionKey());
+		}
+		
+		return reply;
+	}
+	
+	/* 
+	 * Reading the application request requires first determining the server
+	 * for which a ticket was issued, and choosing the correct key for decryption.
+	 * The name of the server appears in the plaintext part of the ticket.
+	 */
+	private ApplicationRequest getAuthHeader(KdcRequest request) throws KerberosException, IOException
{
+		
+		if (request.getPaData()[0].getDataType() != PreAuthenticationData.PA_TGS_REQ)
+			throw KerberosException.KDC_ERR_PADATA_TYPE_NOSUPP;
+		
+		byte[] undecodedAuthHeader = request.getPaData()[0].getDataValue();
+		ApplicationRequestDecoder decoder = new ApplicationRequestDecoder();
+		ApplicationRequest authHeader = decoder.decode(undecodedAuthHeader);
+		
+		return authHeader;
+	}
+	
+	// RFC 1510 A.10.  KRB_AP_REQ verification
+	private Authenticator verifyApReq(ApplicationRequest authHeader, Ticket tgt)
+			throws KerberosException, IOException, KeytabException {
+		
+		if (authHeader.getProtocolVersionNumber() != 5)
+			throw KerberosException.KRB_AP_ERR_BADVERSION;
+		if (authHeader.getMessageType() != MessageType.KRB_AP_REQ)
+			throw KerberosException.KRB_AP_ERR_MSG_TYPE;
+		if (authHeader.getTicket().getTicketVersionNumber() != 5)
+			throw KerberosException.KRB_AP_ERR_BADVERSION;
+		
+		// TODO - support multiple encryption types
+		EncryptionKey serverKey = null;
+		if (authHeader.getOption(ApOptions.USE_SESSION_KEY)) {
+			serverKey = authHeader.getTicket().getSessionKey();
+		} else {
+			PrincipalName server = tgt.getServerName();
+			server.setRealm(tgt.getRealm());
+			serverKey = _keytab.getEncryptionKey(server);
+		}
+		if (serverKey == null) {
+			// TODO - check server key version number, skvno; requires store
+			if (false)
+				throw KerberosException.KRB_AP_ERR_BADKEYVER;
+			
+			throw KerberosException.KRB_AP_ERR_NOKEY;
+		}
+		
+		CryptoService enc = new CryptoService();
+		
+		try {
+			byte[] decTicketPart = enc.decrypt(serverKey, tgt.getEncPart());
+
+			EncTicketPartDecoder ticketPartDecoder = new EncTicketPartDecoder();
+			EncTicketPart encPart = ticketPartDecoder.decode(decTicketPart);
+			tgt.setEncTicketPart(encPart);
+		} catch (KerberosException ke) {
+			throw KerberosException.KRB_AP_ERR_BAD_INTEGRITY;
+		}
+		
+		Authenticator authenticator;
+		
+		try {
+			byte[] decAuthenticator = enc.decrypt(tgt.getSessionKey(), authHeader.getEncPart());
+			AuthenticatorDecoder authDecoder = new AuthenticatorDecoder();
+			authenticator = authDecoder.decode(decAuthenticator);
+		} catch (KerberosException ke) {
+			throw KerberosException.KRB_AP_ERR_BAD_INTEGRITY;
+		}
+		
+		if (!authenticator.getClientName().equals(tgt.getClientName()) &&
+				!authenticator.getClientRealm().equals(tgt.getClientRealm()))
+			throw KerberosException.KRB_AP_ERR_BADMATCH;
+		
+		// TODO - need to get at IP Address for sender
+		if (tgt.getClientAddresses() != null) {
+			// if (sender_address(packet) is not in decr_ticket.caddr)
+            //    then error_out(KRB_AP_ERR_BADADDR);
+		}
+        else {
+        	// if (application requires addresses) then
+            //    error_out(KRB_AP_ERR_BADADDR);
+        }
+		
+		if(_replayCache.isReplay(authenticator.getClientTime(), authenticator.getClientName(),
+				authenticator.getClientRealm())) {
+			throw KerberosException.KRB_AP_ERR_REPEAT;
+		}
+        
+		_replayCache.save(authenticator.getClientTime(), authenticator.getClientName(),
+				authenticator.getClientRealm());
+		
+		if (!authenticator.getClientTime().isInClockSkew())
+			throw KerberosException.KRB_AP_ERR_SKEW;
+		
+		if (tgt.getStartTime() != null && !tgt.getStartTime().isInClockSkew() ||
+				tgt.getFlag(TicketFlags.INVALID))
+				// it hasn't yet become valid
+                throw KerberosException.KRB_AP_ERR_TKT_NYV;
+		
+		// TODO - doesn't take into account skew
+		if (!tgt.getEndTime().greaterThan(new KerberosTime()))
+            throw KerberosException.KRB_AP_ERR_TKT_EXPIRED;
+		
+		authHeader.setOption(ApOptions.MUTUAL_REQUIRED);
+		
+		return authenticator;
+	}
+	
+	/* 
+	 * Note that the realm in which the Kerberos server is operating is determined by
+	 * the instance from the ticket-granting ticket.  The realm in the ticket-granting
+	 * ticket is the realm under which the ticket granting ticket was issued.  It is
+	 * possible for a single Kerberos server to support more than one realm.
+	 */
+	private void verifyTicket(ApplicationRequest authHeader, KdcRequest request)
+			throws KerberosException {
+		
+		Ticket tgt = authHeader.getTicket();
+		if (!tgt.getRealm().toString().equals(LocalConfig.KDC_PRIMARY_REALM) &&
+				!tgt.getServerName().equals(request.getSname()))
+			throw KerberosException.KRB_AP_ERR_NOT_US;
+	}
+	
+	// TODO - configurable checksum
+	private void verifyBodyChecksum(Checksum authChecksum, KdcRequest request)
+			throws KerberosException {
+		
+		if (authChecksum == null)
+			throw KerberosException.KRB_AP_ERR_INAPP_CKSUM;
+		
+		/*
+		if (auth_hdr.authenticator.cksum type is not supported) then
+        	error_out(KDC_ERR_SUMTYPE_NOSUPP);
+		endif
+		*/
+
+		/*
+		if (auth_hdr.authenticator.cksum is not both collision-proof and keyed)  then
+			error_out(KRB_AP_ERR_INAPP_CKSUM);
+		endif
+		*/
+		
+		KdcReqBodyEncoder encoder = new KdcReqBodyEncoder();
+		byte[] bytes = null;
+		try {
+			bytes = encoder.encode(request);
+		} catch (IOException ioe) {
+			ioe.printStackTrace();
+		}
+		
+		ChecksumEngine digester = CryptoService.getInstance(ChecksumType.RSA_MD5);
+		Checksum newChecksum = new Checksum(digester.checksumType(), digester.calculateChecksum(bytes));
+		
+		boolean equal = newChecksum.equals(authChecksum);
+		
+		if (!equal)
+			throw KerberosException.KRB_AP_ERR_MODIFIED;
+	}
+	
+	private EncryptionKey getServerKey(KdcRequest request) throws KerberosException {
+		
+		EncryptionKey serverKey = null;
+		// TODO - allow lookup with realm
+		try {
+			PrincipalName server = request.getSname();
+			server.setRealm(request.getRealm());
+			System.out.println(server);
+			serverKey = _keytab.getEncryptionKey(server);
+		} catch (KeytabException ke) {
+			/*
+			if (!server) then
+			        if (is_foreign_tgt_name(server)) then
+			                server := best_intermediate_tgs(server);
+			        else
+			                // no server in Database
+			                error_out(KDC_ERR_S_PRINCIPAL_UNKNOWN);
+			        endif
+			endif
+			*/
+			throw KerberosException.KDC_ERR_S_PRINCIPAL_UNKNOWN;
+		}
+		return serverKey;
+	}
+	
+	private Ticket getNewTicket(KdcRequest request, Ticket tgt,
+			Realm realm, EncryptionKey sessionKey, Authenticator authenticator)
+			throws KerberosException {
+
+		Ticket newTicket = new Ticket();
+		newTicket.setTicketVersionNumber(LocalConfig.TICKET_VNO);
+		newTicket.setServerName(request.getSname());
+		newTicket.setRealm(realm);
+		
+		/* 
+		 * Note that local policy may affect the processing of any of these flags.
+		 * For example, some realms may refuse to issue renewable tickets
+		 */
+		newTicket.setClientAddresses(tgt.getClientAddresses());
+		
+		processFlags(request, tgt, newTicket);
+		
+		newTicket.setSessionKey(sessionKey);
+		newTicket.setClientRealm(tgt.getClientRealm());
+		newTicket.setClientName(tgt.getClientName());
+		
+		AuthorizationData authData = processAuthorizationData(request, authenticator, tgt);
+		newTicket.setAuthorizationData(authData);
+		
+		return newTicket;
+	}
+	
+	private void processFlags(KdcRequest request, Ticket tgt, Ticket newTicket) 
+			throws KerberosException {
+		
+		if (request.getOption(KdcOptions.FORWARDABLE)) {
+			if (!tgt.getFlag(TicketFlags.FORWARDABLE))
+				throw KerberosException.KDC_ERR_BADOPTION;
+			newTicket.setFlag(TicketFlags.FORWARDABLE);
+		}
+
+		if (request.getOption(KdcOptions.FORWARDED)) {
+			if (!tgt.getFlag(TicketFlags.FORWARDABLE))
+				throw KerberosException.KDC_ERR_BADOPTION;
+			newTicket.setFlag(TicketFlags.FORWARDED);
+			newTicket.setClientAddresses(request.getAddresses());
+			// reply.setClientAddresses(request.getClientAddresses()); moved to getReply
+		}
+		
+		if (tgt.getFlag(TicketFlags.FORWARDED))
+			newTicket.setFlag(TicketFlags.FORWARDED);
+
+		if (request.getOption(KdcOptions.PROXIABLE)) {
+			if (!tgt.getFlag(TicketFlags.PROXIABLE))
+				throw KerberosException.KDC_ERR_BADOPTION;
+			newTicket.setFlag(TicketFlags.PROXIABLE);
+		}
+		
+		if (request.getOption(KdcOptions.PROXY)) {
+			if (!tgt.getFlag(TicketFlags.PROXIABLE))
+				throw KerberosException.KDC_ERR_BADOPTION;
+			newTicket.setFlag(TicketFlags.PROXY);
+			newTicket.setClientAddresses(request.getAddresses());
+			// reply.setClientAddresses(request.getClientAddresses()); moved to getReply
+		}
+		
+		if (request.getOption(KdcOptions.ALLOW_POSTDATE)) {
+			if (!tgt.getFlag(TicketFlags.MAY_POSTDATE))
+				throw KerberosException.KDC_ERR_BADOPTION;
+			newTicket.setFlag(TicketFlags.MAY_POSTDATE);
+		}
+		
+		if (request.getOption(KdcOptions.POSTDATED)) {
+			if (!tgt.getFlag(TicketFlags.MAY_POSTDATE))
+				throw KerberosException.KDC_ERR_BADOPTION;
+			newTicket.setFlag(TicketFlags.POSTDATED);
+			newTicket.setFlag(TicketFlags.INVALID);
+			
+			if (!LocalConfig.KDC_POSTDATE_ALLOWED)
+				throw KerberosException.KDC_ERR_POLICY;
+			
+			newTicket.setStartTime(request.getFrom());
+		}
+
+		if (request.getOption(KdcOptions.VALIDATE)) {
+			if (!tgt.getFlag(TicketFlags.INVALID))
+				throw KerberosException.KDC_ERR_POLICY;
+			if (tgt.getStartTime().greaterThan(new KerberosTime()))
+				throw KerberosException.KRB_AP_ERR_TKT_NYV;
+			/*
+	        if (check_hot_list(tgt)) then
+            	error_out(KRB_AP_ERR_REPEAT);
+	        endif
+	        */
+			
+			// TODO - tkt = tgt;
+			newTicket.clearFlag(TicketFlags.INVALID);
+		}
+
+		if (request.getOption(KdcOptions.RESERVED) ||
+				request.getOption(KdcOptions.RENEWABLE) ||
+				request.getOption(KdcOptions.RENEWABLE_OK))
+				throw KerberosException.KRB_AP_ERR_TKT_NYV;
+	}
+	
+	private void processTimes(KdcRequest request, Ticket newTicket, Ticket tgt)
+			throws KerberosException {
+		
+		KerberosTime now = new KerberosTime();
+		
+		newTicket.setAuthtime(tgt.getAuthtime());
+		
+		if (request.getOption(KdcOptions.RENEW)) {
+			/* 
+			 * Note that if the endtime has already passed, the ticket would have been
+			 * rejected in the initial authentication stage, so there is no need to check again here
+			 */          
+			if (!tgt.getFlag(TicketFlags.RENEWABLE))
+				throw KerberosException.KDC_ERR_BADOPTION;
+			if (tgt.getRenewTill().greaterThan(now))
+				throw KerberosException.KRB_AP_ERR_TKT_EXPIRED;
+			
+			newTicket = tgt;
+			
+			newTicket.setStartTime(now);
+			long oldLife = tgt.getEndTime().getTime() - tgt.getStartTime().getTime();
+			newTicket.setEndTime(new KerberosTime(Math.min(tgt.getRenewTill().getTime(), newTicket.getStartTime().getTime()
+ oldLife)));
+		} else {
+			newTicket.setStartTime(now);
+			KerberosTime till;
+			if (request.getTill().isZero())
+				till = KerberosTime.INFINITY;
+			else
+				till = request.getTill();
+			
+			// TODO - config; requires store
+			/*
+            new_tkt.starttime+client.max_life,
+            new_tkt.starttime+server.max_life,
+            */
+			List minimizer = new ArrayList();
+			minimizer.add(till);
+			minimizer.add(new KerberosTime(newTicket.getStartTime().getTime() + LocalConfig.KDC_MAXIMUM_TICKET_LIFETIME));
+			minimizer.add(tgt.getEndTime());
+			newTicket.setEndTime((KerberosTime)Collections.min(minimizer));
+			
+			if (request.getOption(KdcOptions.RENEWABLE_OK) &&
+					newTicket.getEndTime().lessThan(request.getTill()) &&
+					tgt.getFlag(TicketFlags.RENEWABLE)) {
+                // we set the RENEWABLE option for later processing                     
     
+				request.setOption(KdcOptions.RENEWABLE);
+				long rtime = Math.min(request.getTill().getTime(), tgt.getRenewTill().getTime());
+				request.setRtime(new KerberosTime(rtime));
+			}
+		}
+		
+		KerberosTime rtime;
+		if (request.getRtime() != null && request.getRtime().isZero())
+			rtime = KerberosTime.INFINITY;
+		else
+			rtime = request.getRtime();
+		
+		if (request.getOption(KdcOptions.RENEWABLE) &&
+				tgt.getFlag(TicketFlags.RENEWABLE)) {
+			newTicket.setFlag(TicketFlags.RENEWABLE);
+			
+			/*
+	        new_tkt.starttime+client.max_rlife,
+	        new_tkt.starttime+server.max_rlife,
+	        */
+			// TODO - client and server configurable; requires store 
+			List minimizer = new ArrayList();
+			minimizer.add(rtime);
+			minimizer.add(new KerberosTime(newTicket.getStartTime().getTime() + LocalConfig.DEFAULT_MAXIMUM_RENEWABLE_LIFETIME));
+			minimizer.add(tgt.getRenewTill());
+			newTicket.setRenewTill((KerberosTime)Collections.min(minimizer));
+		}
+	}
+	
+	private AuthorizationData processAuthorizationData(KdcRequest request,
+			Authenticator authHeader, Ticket tgt) throws KerberosException {
+
+		AuthorizationData authData = null;
+
+		if (request.getEncAuthorizationData() != null) {
+			try {
+				CryptoService enc = new CryptoService();
+				byte[] decryptedAuthData = enc.decrypt(authHeader.getSubSessionKey(),
+						request.getEncAuthorizationData());
+				AuthorizationDataDecoder decoder = new AuthorizationDataDecoder();
+				authData = decoder.decode(decryptedAuthData);
+			} catch (KerberosException e) {
+				throw KerberosException.KRB_AP_ERR_BAD_INTEGRITY;
+			} catch (IOException ioe) {
+				throw KerberosException.KRB_AP_ERR_BAD_INTEGRITY;
+			}
+
+			AuthorizationData ticketData = tgt.getAuthorizationData();
+			authData.add(ticketData);
+		}
+		
+		return authData;
+	}
+	
+	/*
+	if (realm_tgt_is_for(tgt) := tgt.realm) then
+	        // tgt issued by local realm
+	        new_tkt.transited := tgt.transited;
+	else
+	        // was issued for this realm by some other realm
+	        if (tgt.transited.tr-type not supported) then
+	                error_out(KDC_ERR_TRTYPE_NOSUPP);
+	        endif
+	        new_tkt.transited := compress_transited(tgt.transited + tgt.realm)
+	endif
+	*/
+	private void processTransited(Ticket newTicket, Ticket tgt) {
+		// TODO - currently no transited support other than local
+		newTicket.setTransitedEncoding(tgt.getTransitedEncoding());
+	}
+	
+	// TODO - support multiple encryption types, this is hardwired for DES_CBC_MD5
+	private void encryptTicketPart(Ticket newTicket, EncryptionKey serverKey, KdcRequest request)
+			throws KerberosException {
+		
+		byte[] encodedTicket;
+		
+		EncTicketPartEncoder encoder = new EncTicketPartEncoder();
+		try {
+			encodedTicket = encoder.encode(newTicket);
+		} catch (IOException ioe) {
+			// TODO - figure out right error for ASN.1 generation error
+			throw KerberosException.KRB_ERR_GENERIC;
+		}
+		
+		CryptoService enc = new CryptoService();
+		
+		if (request.getOption(KdcOptions.ENC_TKT_IN_SKEY)) {
+			/*
+			if (server not specified) then
+				server = req.second_ticket.client;
+			endif
+			if ((req.second_ticket is not a TGT) or
+				(req.second_ticket.client != server)) then
+				error_out(KDC_ERR_POLICY);
+			endif
+			new_tkt.enc-part := encrypt OCTET STRING
+				using etype_for_key(second-ticket.key), second-ticket.key;
+			*/
+		} else {
+			
+			EncryptedData cipherText = enc.getEncryptedData(serverKey, encodedTicket);
+			
+			newTicket.setEncPart(cipherText);
+		}
+	}
+	
+	// TODO - support multiple encryption types, this is hardwired for DES_CBC_MD5
+	private void encryptReplyPart(TicketGrantReply reply, EncryptionKey key) {
+		EncTgsRepPartEncoder encoder = new EncTgsRepPartEncoder();
+		try {
+			byte[] plainText = encoder.encode(reply);
+			
+			CryptoService enc = new CryptoService();
+			
+			EncryptedData cipherText = enc.getEncryptedData(key, plainText);
+
+			reply.setEncPart(cipherText);
+			
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+	
+	private TicketGrantReply getReply(Ticket tgt, Ticket newTicket,
+			EncryptionKey sessionKey, KdcRequest request) {
+		
+		TicketGrantReply reply = new TicketGrantReply();
+		reply.setCrealm(tgt.getClientRealm());
+		reply.setCname(tgt.getClientName());
+		reply.setTicket(newTicket);
+		reply.setKey(sessionKey);
+		reply.setNonce(request.getNonce());
+		// TODO - resp.last-req := fetch_last_request_info(client); requires store
+		reply.setLastRequest(new LastRequest());
+		reply.setFlags(newTicket.getFlags());
+		reply.setClientAddresses(newTicket.getClientAddresses());
+		reply.setAuthTime(newTicket.getAuthtime());
+		reply.setStartTime(newTicket.getStartTime());
+		reply.setEndTime(newTicket.getEndTime());
+		reply.setServerName(newTicket.getServerName());
+		reply.setServerRealm(newTicket.getRealm());
+		
+		if (newTicket.getFlag(TicketFlags.RENEWABLE))
+			reply.setRenewTill(newTicket.getRenewTill());
+		
+		return reply;
+	}
+}
+

Mime
View raw message