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;
+       }
+}
+

Reply via email to