You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by dr...@apache.org on 2015/01/22 01:56:39 UTC

[15/50] [abbrv] directory-kerberos git commit: Many changes with newname

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/AbstractPreauthPlugin.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/AbstractPreauthPlugin.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/AbstractPreauthPlugin.java
new file mode 100644
index 0000000..17ade95
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/AbstractPreauthPlugin.java
@@ -0,0 +1,91 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.preauth;
+
+import org.apache.kerby.kerberos.kerb.preauth.PaFlags;
+import org.apache.kerby.kerberos.kerb.preauth.PluginRequestContext;
+import org.apache.kerby.kerberos.kerb.preauth.PreauthPluginMeta;
+import org.apache.kerby.kerberos.kerb.server.KdcContext;
+import org.apache.kerby.kerberos.kerb.server.request.KdcRequest;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaData;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaDataEntry;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaDataType;
+
+public class AbstractPreauthPlugin implements KdcPreauth {
+
+    private PreauthPluginMeta pluginMeta;
+
+    public AbstractPreauthPlugin(PreauthPluginMeta meta) {
+        this.pluginMeta = meta;
+    }
+
+    @Override
+    public String getName() {
+        return pluginMeta.getName();
+    }
+
+    public int getVersion() {
+        return pluginMeta.getVersion();
+    }
+
+    public PaDataType[] getPaTypes() {
+        return pluginMeta.getPaTypes();
+    }
+
+    @Override
+    public void initWith(KdcContext kdcContext) {
+
+    }
+
+    @Override
+    public PluginRequestContext initRequestContext(KdcRequest kdcRequest) {
+        return null;
+    }
+
+    @Override
+    public void provideEdata(KdcRequest kdcRequest, PluginRequestContext requestContext,
+            PaData outPaData) throws KrbException {
+
+    }
+
+    @Override
+    public boolean verify(KdcRequest kdcRequest, PluginRequestContext requestContext,
+                          PaDataEntry paData) throws KrbException {
+        return false;
+    }
+
+    @Override
+    public void providePaData(KdcRequest kdcRequest, PluginRequestContext requestContext,
+                              PaData paData) {
+
+    }
+
+    @Override
+    public PaFlags getFlags(KdcRequest kdcRequest, PluginRequestContext requestContext,
+                            PaDataType paType) {
+        return null;
+    }
+
+    @Override
+    public void destroy() {
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/FastContext.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/FastContext.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/FastContext.java
new file mode 100644
index 0000000..736ff01
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/FastContext.java
@@ -0,0 +1,36 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.preauth;
+
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptionKey;
+import org.apache.kerby.kerberos.kerb.spec.fast.FastOptions;
+import org.apache.kerby.kerberos.kerb.spec.fast.KrbFastArmor;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcReq;
+
+public class FastContext {
+
+    public KdcReq fastOuterRequest;
+    public EncryptionKey armorKey;
+    public KrbFastArmor fastArmor;
+    public FastOptions fastOptions;
+    public int nonce;
+    public int fastFlags;
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/KdcPreauth.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/KdcPreauth.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/KdcPreauth.java
new file mode 100644
index 0000000..ee0b247
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/KdcPreauth.java
@@ -0,0 +1,81 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.preauth;
+
+import org.apache.kerby.kerberos.kerb.preauth.PaFlags;
+import org.apache.kerby.kerberos.kerb.preauth.PluginRequestContext;
+import org.apache.kerby.kerberos.kerb.preauth.PreauthPluginMeta;
+import org.apache.kerby.kerberos.kerb.server.KdcContext;
+import org.apache.kerby.kerberos.kerb.server.request.KdcRequest;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaData;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaDataEntry;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaDataType;
+
+/**
+ * KDC side preauth plugin module
+ */
+public interface KdcPreauth extends PreauthPluginMeta {
+
+    /**
+     * Initializing plugin context for each realm
+     */
+    public void initWith(KdcContext context);
+
+    /**
+     * Initializing request context
+     */
+    public PluginRequestContext initRequestContext(KdcRequest kdcRequest);
+
+    /**
+     * Optional: provide pa_data to send to the client as part of the "you need to
+     * use preauthentication" error.
+     */
+    public void provideEdata(KdcRequest kdcRequest, PluginRequestContext requestContext,
+                             PaData outPaData) throws KrbException;
+
+    /**
+     * Optional: verify preauthentication data sent by the client, setting the
+     * TKT_FLG_PRE_AUTH or TKT_FLG_HW_AUTH flag in the enc_tkt_reply's "flags"
+     * field as appropriate.
+     */
+    public boolean verify(KdcRequest kdcRequest, PluginRequestContext requestContext,
+                          PaDataEntry paData) throws KrbException;
+
+    /**
+     * Optional: generate preauthentication response data to send to the client as
+     * part of the AS-REP.
+     */
+    public void providePaData(KdcRequest kdcRequest, PluginRequestContext requestContext,
+                              PaData paData);
+
+    /**
+     * Return PA_REAL if pa_type is a real preauthentication type or PA_INFO if it is
+     * an informational type.
+     */
+    public PaFlags getFlags(KdcRequest kdcRequest, PluginRequestContext requestContext,
+                            PaDataType paType);
+
+    /**
+     * When exiting...
+     */
+    public void destroy();
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthContext.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthContext.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthContext.java
new file mode 100644
index 0000000..551e1b3
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthContext.java
@@ -0,0 +1,44 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.preauth;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PreauthContext {
+    private boolean preauthRequired = true;
+    private List<PreauthHandle> handles = new ArrayList<PreauthHandle>(5);
+
+    public PreauthContext() {
+
+    }
+
+    public boolean isPreauthRequired() {
+        return preauthRequired;
+    }
+
+    public void setPreauthRequired(boolean preauthRequired) {
+        this.preauthRequired = preauthRequired;
+    }
+
+    public List<PreauthHandle> getHandles() {
+        return handles;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthHandle.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthHandle.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthHandle.java
new file mode 100644
index 0000000..2893925
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthHandle.java
@@ -0,0 +1,56 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.preauth;
+
+import org.apache.kerby.kerberos.kerb.preauth.PluginRequestContext;
+import org.apache.kerby.kerberos.kerb.server.request.KdcRequest;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaData;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaDataEntry;
+
+public class PreauthHandle {
+
+    public KdcPreauth preauth;
+    public PluginRequestContext requestContext;
+
+    public PreauthHandle(KdcPreauth preauth) {
+        this.preauth = preauth;
+    }
+
+    public void initRequestContext(KdcRequest kdcRequest) {
+        requestContext = preauth.initRequestContext(kdcRequest);
+    }
+
+    public void provideEdata(KdcRequest kdcRequest, PaData outPaData) throws KrbException {
+        preauth.provideEdata(kdcRequest, requestContext, outPaData);
+    }
+
+    public void verify(KdcRequest kdcRequest, PaDataEntry paData) throws KrbException {
+        preauth.verify(kdcRequest, requestContext, paData);
+    }
+
+    public void providePaData(KdcRequest kdcRequest, PaData paData) {
+        preauth.providePaData(kdcRequest, requestContext, paData);
+    }
+
+    public void destroy() {
+        preauth.destroy();
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthHandler.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthHandler.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthHandler.java
new file mode 100644
index 0000000..262e152
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthHandler.java
@@ -0,0 +1,124 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.preauth;
+
+import org.apache.kerby.kerberos.kerb.server.KdcConfig;
+import org.apache.kerby.kerberos.kerb.server.KdcContext;
+import org.apache.kerby.kerberos.kerb.server.preauth.builtin.EncTsPreauth;
+import org.apache.kerby.kerberos.kerb.server.preauth.builtin.TgtPreauth;
+import org.apache.kerby.kerberos.kerb.server.request.KdcRequest;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaData;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaDataEntry;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaDataType;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PreauthHandler {
+
+    private List<KdcPreauth> preauths;
+
+    /**
+     * Should be called only once, for global
+     */
+    public void init(KdcConfig kdcConfig) {
+        loadPreauthPlugins(kdcConfig);
+    }
+
+    private void loadPreauthPlugins(KdcConfig kdcConfig) {
+        preauths = new ArrayList<KdcPreauth>();
+
+        KdcPreauth preauth = new EncTsPreauth();
+        preauths.add(preauth);
+
+        preauth = new TgtPreauth();
+        preauths.add(preauth);
+    }
+
+    /**
+     * Should be called per realm
+     * @param context
+     */
+    public void initWith(KdcContext context) {
+        for (KdcPreauth preauth : preauths) {
+            preauth.initWith(context);
+        }
+    }
+
+    public PreauthContext preparePreauthContext(KdcRequest kdcRequest) {
+        PreauthContext preauthContext = new PreauthContext();
+
+        KdcContext kdcContext = kdcRequest.getKdcContext();
+        preauthContext.setPreauthRequired(kdcContext.getConfig().isPreauthRequired());
+
+        for (KdcPreauth preauth : preauths) {
+            PreauthHandle handle = new PreauthHandle(preauth);
+            handle.initRequestContext(kdcRequest);
+            preauthContext.getHandles().add(handle);
+        }
+
+        return preauthContext;
+    }
+
+    public void provideEdata(KdcRequest kdcRequest, PaData outPaData) throws KrbException {
+        PreauthContext preauthContext = kdcRequest.getPreauthContext();
+
+        for (PreauthHandle handle : preauthContext.getHandles()) {
+            handle.provideEdata(kdcRequest, outPaData);
+        }
+    }
+
+    public void verify(KdcRequest kdcRequest, PaData paData) throws KrbException {
+        for (PaDataEntry paEntry : paData.getElements()) {
+            PreauthHandle handle = findHandle(kdcRequest, paEntry.getPaDataType());
+            if (handle != null) {
+                handle.verify(kdcRequest, paEntry);
+            }
+        }
+    }
+
+    public void providePaData(KdcRequest kdcRequest, PaData paData) {
+        PreauthContext preauthContext = kdcRequest.getPreauthContext();
+
+        for (PreauthHandle handle : preauthContext.getHandles()) {
+            handle.providePaData(kdcRequest, paData);
+        }
+    }
+
+    private PreauthHandle findHandle(KdcRequest kdcRequest, PaDataType paType) {
+        PreauthContext preauthContext = kdcRequest.getPreauthContext();
+
+        for (PreauthHandle handle : preauthContext.getHandles()) {
+            for (PaDataType pt : handle.preauth.getPaTypes()) {
+                if (pt == paType) {
+                    return handle;
+                }
+            }
+        }
+        return null;
+    }
+
+    public void destroy() {
+        for (KdcPreauth preauth : preauths) {
+            preauth.destroy();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/builtin/EncTsPreauth.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/builtin/EncTsPreauth.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/builtin/EncTsPreauth.java
new file mode 100644
index 0000000..85f8452
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/builtin/EncTsPreauth.java
@@ -0,0 +1,60 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.preauth.builtin;
+
+import org.apache.kerby.kerberos.kerb.KrbErrorCode;
+import org.apache.kerby.kerberos.kerb.codec.KrbCodec;
+import org.apache.kerby.kerberos.kerb.common.EncryptionUtil;
+import org.apache.kerby.kerberos.kerb.preauth.PluginRequestContext;
+import org.apache.kerby.kerberos.kerb.preauth.builtin.EncTsPreauthMeta;
+import org.apache.kerby.kerberos.kerb.server.KdcContext;
+import org.apache.kerby.kerberos.kerb.server.preauth.AbstractPreauthPlugin;
+import org.apache.kerby.kerberos.kerb.server.request.KdcRequest;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptedData;
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptionKey;
+import org.apache.kerby.kerberos.kerb.spec.common.KeyUsage;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaDataEntry;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaEncTsEnc;
+
+public class EncTsPreauth extends AbstractPreauthPlugin {
+
+    public EncTsPreauth() {
+        super(new EncTsPreauthMeta());
+    }
+
+    @Override
+    public boolean verify(KdcRequest kdcRequest, PluginRequestContext requestContext,
+                          PaDataEntry paData) throws KrbException {
+        EncryptedData encData = KrbCodec.decode(paData.getPaDataValue(), EncryptedData.class);
+        EncryptionKey clientKey = kdcRequest.getClientKey(encData.getEType());
+        PaEncTsEnc timestamp = EncryptionUtil.unseal(encData, clientKey,
+                KeyUsage.AS_REQ_PA_ENC_TS, PaEncTsEnc.class);
+
+        KdcContext kdcContext = kdcRequest.getKdcContext();
+        long clockSkew = kdcContext.getConfig().getAllowableClockSkew() * 1000;
+        if (!timestamp.getAllTime().isInClockSkew(clockSkew)) {
+            throw new KrbException(KrbErrorCode.KDC_ERR_PREAUTH_FAILED);
+        }
+
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/builtin/TgtPreauth.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/builtin/TgtPreauth.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/builtin/TgtPreauth.java
new file mode 100644
index 0000000..a60ba7d
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/builtin/TgtPreauth.java
@@ -0,0 +1,45 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.preauth.builtin;
+
+import org.apache.kerby.kerberos.kerb.preauth.PluginRequestContext;
+import org.apache.kerby.kerberos.kerb.preauth.builtin.TgtPreauthMeta;
+import org.apache.kerby.kerberos.kerb.server.preauth.AbstractPreauthPlugin;
+import org.apache.kerby.kerberos.kerb.server.request.KdcRequest;
+import org.apache.kerby.kerberos.kerb.server.request.TgsRequest;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaDataEntry;
+
+public class TgtPreauth extends AbstractPreauthPlugin {
+
+    public TgtPreauth() {
+        super(new TgtPreauthMeta());
+    }
+
+    @Override
+    public boolean verify(KdcRequest kdcRequest, PluginRequestContext requestContext,
+                          PaDataEntry paData) throws KrbException {
+
+        TgsRequest tgsRequest = (TgsRequest) kdcRequest;
+        tgsRequest.verifyAuthenticator(paData);
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitKdcContext.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitKdcContext.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitKdcContext.java
new file mode 100644
index 0000000..9fb9e51
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitKdcContext.java
@@ -0,0 +1,30 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.preauth.pkinit;
+
+import org.apache.kerby.kerberos.kerb.preauth.pkinit.IdentityOpts;
+import org.apache.kerby.kerberos.kerb.preauth.pkinit.PluginOpts;
+
+public class PkinitKdcContext {
+
+    public PluginOpts pluginOpts;
+    public IdentityOpts identityOpts;
+    public String realm;
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitPreauth.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitPreauth.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitPreauth.java
new file mode 100644
index 0000000..c383037
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitPreauth.java
@@ -0,0 +1,93 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.preauth.pkinit;
+
+import org.apache.kerby.kerberos.kerb.codec.KrbCodec;
+import org.apache.kerby.kerberos.kerb.preauth.PluginRequestContext;
+import org.apache.kerby.kerberos.kerb.preauth.pkinit.PkinitPreauthMeta;
+import org.apache.kerby.kerberos.kerb.server.KdcContext;
+import org.apache.kerby.kerberos.kerb.server.preauth.AbstractPreauthPlugin;
+import org.apache.kerby.kerberos.kerb.server.request.KdcRequest;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.spec.common.PrincipalName;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaDataEntry;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaDataType;
+import org.apache.kerby.kerberos.kerb.spec.pa.pkinit.PaPkAsReq;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class PkinitPreauth extends AbstractPreauthPlugin {
+
+    private Map<String, PkinitKdcContext> pkinitContexts;
+
+    public PkinitPreauth() {
+        super(new PkinitPreauthMeta());
+
+        pkinitContexts = new HashMap<String, PkinitKdcContext>(1);
+    }
+
+    @Override
+    public void initWith(KdcContext kdcContext) {
+        super.initWith(kdcContext);
+
+        PkinitKdcContext tmp = new PkinitKdcContext();
+        tmp.realm = kdcContext.getKdcRealm();
+        pkinitContexts.put(kdcContext.getKdcRealm(), tmp);
+    }
+
+    @Override
+    public PluginRequestContext initRequestContext(KdcRequest kdcRequest) {
+        PkinitRequestContext reqCtx = new PkinitRequestContext();
+
+        //reqCtx.updateRequestOpts(pkinitContext.pluginOpts);
+
+        return reqCtx;
+    }
+
+    @Override
+    public boolean verify(KdcRequest kdcRequest, PluginRequestContext requestContext,
+                          PaDataEntry paData) throws KrbException {
+
+        PkinitRequestContext reqCtx = (PkinitRequestContext) requestContext;
+        PkinitKdcContext pkinitContext = findContext(kdcRequest.getServerPrincipal());
+        if (pkinitContext == null) {
+            return false;
+        }
+
+        reqCtx.paType = paData.getPaDataType();
+        if (paData.getPaDataType() == PaDataType.PK_AS_REQ) {
+            PaPkAsReq paPkAsReq = KrbCodec.decode(paData.getPaDataValue(), PaPkAsReq.class);
+            if (paPkAsReq == null) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private PkinitKdcContext findContext(PrincipalName principal) {
+        String realm = principal.getRealm();
+        if (pkinitContexts.containsKey(realm)) {
+            return pkinitContexts.get(realm);
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitRequestContext.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitRequestContext.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitRequestContext.java
new file mode 100644
index 0000000..97ca7c4
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitRequestContext.java
@@ -0,0 +1,30 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.preauth.pkinit;
+
+import org.apache.kerby.kerberos.kerb.preauth.PluginRequestContext;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaDataType;
+import org.apache.kerby.kerberos.kerb.spec.pa.pkinit.AuthPack;
+
+public class PkinitRequestContext implements PluginRequestContext {
+
+    public AuthPack authPack;
+    public PaDataType paType;
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/token/TokenRequestContext.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/token/TokenRequestContext.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/token/TokenRequestContext.java
new file mode 100644
index 0000000..6f0b73d
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/token/TokenRequestContext.java
@@ -0,0 +1,32 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.preauth.token;
+
+import org.apache.kerby.kerberos.kerb.preauth.PluginRequestContext;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaDataType;
+
+public class TokenRequestContext implements PluginRequestContext {
+
+    public boolean doIdentityMatching;
+    public PaDataType paType;
+    public boolean identityInitialized;
+    public boolean identityPrompted;
+    
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/CacheService.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/CacheService.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/CacheService.java
new file mode 100644
index 0000000..dc766d8
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/CacheService.java
@@ -0,0 +1,26 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.replay;
+
+public interface CacheService
+{
+    boolean checkAndCache(RequestRecord request);
+    void clear();
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/ReplayCheckService.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/ReplayCheckService.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/ReplayCheckService.java
new file mode 100644
index 0000000..485621f
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/ReplayCheckService.java
@@ -0,0 +1,25 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.replay;
+
+public interface ReplayCheckService
+{
+    boolean checkReplay(String clientPrincipal, String serverPrincipal, long requestTime, int microseconds);
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/ReplayCheckServiceImpl.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/ReplayCheckServiceImpl.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/ReplayCheckServiceImpl.java
new file mode 100644
index 0000000..822674f
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/ReplayCheckServiceImpl.java
@@ -0,0 +1,40 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.replay;
+
+public class ReplayCheckServiceImpl implements ReplayCheckService
+{
+    private CacheService cacheService;
+
+    public ReplayCheckServiceImpl(CacheService cacheService) {
+        this.cacheService = cacheService;
+    }
+
+    public ReplayCheckServiceImpl() {
+        this(new SimpleCacheService());
+    }
+
+    @Override
+    public boolean checkReplay(String clientPrincipal, String serverPrincipal,
+                               long requestTime, int microseconds) {
+        RequestRecord record = new RequestRecord(clientPrincipal, serverPrincipal, requestTime, microseconds);
+        return cacheService.checkAndCache(record);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/RequestRecord.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/RequestRecord.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/RequestRecord.java
new file mode 100644
index 0000000..3708d18
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/RequestRecord.java
@@ -0,0 +1,58 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.replay;
+
+public class RequestRecord {
+    private String clientPrincipal;
+    private String serverPrincipal;
+    private long requestTime;
+    private int microseconds;
+
+    public RequestRecord(String clientPrincipal, String serverPrincipal, long requestTime, int microseconds) {
+        this.clientPrincipal = clientPrincipal;
+        this.serverPrincipal = serverPrincipal;
+        this.requestTime = requestTime;
+        this.microseconds = microseconds;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        RequestRecord that = (RequestRecord) o;
+
+        if (microseconds != that.microseconds) return false;
+        if (requestTime != that.requestTime) return false;
+        if (!clientPrincipal.equals(that.clientPrincipal)) return false;
+        if (!serverPrincipal.equals(that.serverPrincipal)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = clientPrincipal.hashCode();
+        result = 31 * result + serverPrincipal.hashCode();
+        result = 31 * result + (int) (requestTime ^ (requestTime >>> 32));
+        result = 31 * result + microseconds;
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/SimpleCacheService.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/SimpleCacheService.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/SimpleCacheService.java
new file mode 100644
index 0000000..96d95c1
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/replay/SimpleCacheService.java
@@ -0,0 +1,46 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.replay;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class SimpleCacheService implements CacheService {
+    private Set<RequestRecord> requests;
+
+    public SimpleCacheService() {
+        requests = new HashSet<RequestRecord>();
+    }
+
+    @Override
+    public boolean checkAndCache(RequestRecord request) {
+        if (requests.contains(request)) {
+            return true;
+        } else {
+            requests.add(request);
+        }
+        return false;
+    }
+
+    @Override
+    public void clear() {
+        requests.clear();
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/AsRequest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/AsRequest.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/AsRequest.java
new file mode 100644
index 0000000..5cc6375
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/AsRequest.java
@@ -0,0 +1,91 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.request;
+
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.common.EncryptionUtil;
+import org.apache.kerby.kerberos.kerb.server.KdcContext;
+import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
+import org.apache.kerby.kerberos.kerb.spec.common.*;
+import org.apache.kerby.kerberos.kerb.spec.kdc.*;
+import org.apache.kerby.kerberos.kerb.spec.ticket.Ticket;
+import org.apache.kerby.kerberos.kerb.spec.ticket.TicketFlag;
+
+public class AsRequest extends KdcRequest {
+
+    public AsRequest(AsReq asReq, KdcContext kdcContext) {
+        super(asReq, kdcContext);
+    }
+
+    @Override
+    protected void makeReply() throws KrbException {
+        Ticket ticket = getTicket();
+
+        AsRep reply = new AsRep();
+
+        reply.setCname(getClientEntry().getPrincipal());
+        reply.setCrealm(kdcContext.getServerRealm());
+        reply.setTicket(ticket);
+
+        EncKdcRepPart encKdcRepPart = makeEncKdcRepPart();
+        reply.setEncPart(encKdcRepPart);
+
+        EncryptionKey clientKey = getClientKey();
+        EncryptedData encryptedData = EncryptionUtil.seal(encKdcRepPart,
+                clientKey, KeyUsage.AS_REP_ENCPART);
+        reply.setEncryptedEncPart(encryptedData);
+
+        setReply(reply);
+    }
+
+    protected EncKdcRepPart makeEncKdcRepPart() {
+        KdcReq request = getKdcReq();
+        Ticket ticket = getTicket();
+
+        EncKdcRepPart encKdcRepPart = new EncAsRepPart();
+
+        //session key
+        encKdcRepPart.setKey(ticket.getEncPart().getKey());
+
+        LastReq lastReq = new LastReq();
+        LastReqEntry entry = new LastReqEntry();
+        entry.setLrType(LastReqType.THE_LAST_INITIAL);
+        entry.setLrValue(new KerberosTime());
+        lastReq.add(entry);
+        encKdcRepPart.setLastReq(lastReq);
+
+        encKdcRepPart.setNonce(request.getReqBody().getNonce());
+
+        encKdcRepPart.setFlags(ticket.getEncPart().getFlags());
+        encKdcRepPart.setAuthTime(ticket.getEncPart().getAuthTime());
+        encKdcRepPart.setStartTime(ticket.getEncPart().getStartTime());
+        encKdcRepPart.setEndTime(ticket.getEncPart().getEndTime());
+
+        if (ticket.getEncPart().getFlags().isFlagSet(TicketFlag.RENEWABLE)) {
+            encKdcRepPart.setRenewTill(ticket.getEncPart().getRenewtill());
+        }
+
+        encKdcRepPart.setSname(ticket.getSname());
+        encKdcRepPart.setSrealm(ticket.getRealm());
+        encKdcRepPart.setCaddr(ticket.getEncPart().getClientAddresses());
+
+        return encKdcRepPart;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java
new file mode 100644
index 0000000..de3048c
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java
@@ -0,0 +1,521 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.request;
+
+import org.apache.kerby.kerberos.kerb.KrbErrorCode;
+import org.apache.kerby.kerberos.kerb.codec.KrbCodec;
+import org.apache.kerby.kerberos.kerb.common.EncryptionUtil;
+import org.apache.kerby.kerberos.kerb.crypto.EncryptionHandler;
+import org.apache.kerby.kerberos.kerb.identity.KrbIdentity;
+import org.apache.kerby.kerberos.kerb.server.KdcConfig;
+import org.apache.kerby.kerberos.kerb.server.KdcContext;
+import org.apache.kerby.kerberos.kerb.server.preauth.FastContext;
+import org.apache.kerby.kerberos.kerb.server.preauth.PreauthContext;
+import org.apache.kerby.kerberos.kerb.server.preauth.PreauthHandler;
+import org.apache.kerby.kerberos.kerb.KrbConstant;
+import org.apache.kerby.kerberos.kerb.KrbErrorException;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
+import org.apache.kerby.kerberos.kerb.spec.common.*;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcOption;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcOptions;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcRep;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcReq;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaData;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaDataEntry;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaDataType;
+import org.apache.kerby.kerberos.kerb.spec.ticket.EncTicketPart;
+import org.apache.kerby.kerberos.kerb.spec.ticket.Ticket;
+import org.apache.kerby.kerberos.kerb.spec.ticket.TicketFlag;
+import org.apache.kerby.kerberos.kerb.spec.ticket.TicketFlags;
+
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+import java.util.Date;
+import java.util.List;
+
+public abstract class KdcRequest {
+
+    protected KdcContext kdcContext;
+
+    private Ticket ticket;
+    private boolean isPreAuthenticated;
+    private KdcReq kdcReq;
+    private KdcRep reply;
+    private InetAddress clientAddress;
+    private boolean isTcp;
+    private EncryptionType encryptionType;
+    private EncryptionKey clientKey;
+    private KrbIdentity clientEntry;
+    private KrbIdentity serverEntry;
+    private EncryptionKey serverKey;
+    private KrbIdentity tgsEntry;
+    private PreauthContext preauthContext;
+    private FastContext fastContext;
+    private PrincipalName serverPrincipal;
+
+    public KdcRequest(KdcReq kdcReq, KdcContext kdcContext) {
+        this.kdcReq = kdcReq;
+        this.kdcContext = kdcContext;
+        this.preauthContext = kdcContext.getPreauthHandler()
+                .preparePreauthContext(this);
+        this.fastContext = new FastContext();
+    }
+
+    public KdcContext getKdcContext() {
+        return kdcContext;
+    }
+
+    public PreauthContext getPreauthContext() {
+        return preauthContext;
+    }
+
+    public void process() throws KrbException {
+        checkVersion();
+        checkClient();
+        checkServer();
+        preauth();
+        authenticate();
+        issueTicket();
+        makeReply();
+    }
+
+    public KdcReq getKdcReq() {
+        return kdcReq;
+    }
+
+    public KrbIdentity getTgsEntry() {
+        return tgsEntry;
+    }
+
+    public void setTgsEntry(KrbIdentity tgsEntry) {
+        this.tgsEntry = tgsEntry;
+    }
+
+    public boolean isTcp() {
+        return isTcp;
+    }
+
+    public void isTcp(boolean isTcp) {
+        this.isTcp = isTcp;
+    }
+
+    public KrbMessage getReply() {
+        return reply;
+    }
+
+    public void setReply(KdcRep reply) {
+        this.reply = reply;
+    }
+
+    public InetAddress getClientAddress() {
+        return clientAddress;
+    }
+
+    public void setClientAddress(InetAddress clientAddress) {
+        this.clientAddress = clientAddress;
+    }
+
+    public EncryptionType getEncryptionType() {
+        return encryptionType;
+    }
+
+    public void setEncryptionType(EncryptionType encryptionType) {
+        this.encryptionType = encryptionType;
+    }
+
+    public Ticket getTicket() {
+        return ticket;
+    }
+
+    public void setTicket(Ticket ticket) {
+        this.ticket = ticket;
+    }
+
+    public boolean isPreAuthenticated() {
+        return isPreAuthenticated;
+    }
+
+    public void setPreAuthenticated(boolean isPreAuthenticated) {
+        this.isPreAuthenticated = isPreAuthenticated;
+    }
+
+    public KrbIdentity getServerEntry() {
+        return serverEntry;
+    }
+
+    public void setServerEntry(KrbIdentity serverEntry) {
+        this.serverEntry = serverEntry;
+    }
+
+    public KrbIdentity getClientEntry() {
+        return clientEntry;
+    }
+
+    public void setClientEntry(KrbIdentity clientEntry) {
+        this.clientEntry = clientEntry;
+    }
+
+    public EncryptionKey getClientKey(EncryptionType encType) throws KrbException {
+        return getClientEntry().getKey(encType);
+    }
+
+    public EncryptionKey getClientKey() {
+        return clientKey;
+    }
+
+    public void setClientKey(EncryptionKey clientKey) {
+        this.clientKey = clientKey;
+    }
+
+    public EncryptionKey getServerKey() {
+        return serverKey;
+    }
+
+    public void setServerKey(EncryptionKey serverKey) {
+        this.serverKey = serverKey;
+    }
+
+    public PrincipalName getTgsPrincipal() {
+        PrincipalName result = new PrincipalName(kdcContext.getConfig().getTgsPrincipal());
+        result.setRealm(kdcContext.getKdcRealm());
+        return result;
+    }
+
+    protected abstract void makeReply() throws KrbException;
+
+    protected void checkVersion() throws KrbException {
+        KdcReq request = getKdcReq();
+
+        int kerberosVersion = request.getPvno();
+        if (kerberosVersion != KrbConstant.KRB_V5) {
+            throw new KrbException(KrbErrorCode.KDC_ERR_BAD_PVNO);
+        }
+    }
+
+    protected void checkPolicy() throws KrbException {
+        KrbIdentity entry = getClientEntry();
+
+        if (entry.isDisabled()) {
+            throw new KrbException(KrbErrorCode.KDC_ERR_CLIENT_REVOKED);
+        }
+
+        if (entry.isLocked()) {
+            throw new KrbException(KrbErrorCode.KDC_ERR_CLIENT_REVOKED);
+        }
+
+        if (entry.getExpireTime().lessThan(new Date().getTime())) {
+            throw new KrbException(KrbErrorCode.KDC_ERR_CLIENT_REVOKED);
+        }
+    }
+
+    protected void checkClient() throws KrbException {
+        KdcReq request = getKdcReq();
+
+        PrincipalName clientPrincipal = request.getReqBody().getCname();
+        String clientRealm = request.getReqBody().getRealm();
+        if (clientRealm == null || clientRealm.isEmpty()) {
+            clientRealm = kdcContext.getServerRealm();
+        }
+        clientPrincipal.setRealm(clientRealm);
+
+        KrbIdentity clientEntry = getEntry(clientPrincipal.getName());
+        setClientEntry(clientEntry);
+
+        EncryptionType encType = request.getReqBody().getEtypes().listIterator().next();
+        EncryptionKey clientKey = clientEntry.getKeys().get(encType);
+        setClientKey(clientKey);
+    }
+
+    protected void preauth() throws KrbException {
+        KdcReq request = getKdcReq();
+
+        PaData preAuthData = request.getPaData();
+
+        if (preauthContext.isPreauthRequired()) {
+            if (preAuthData == null || preAuthData.isEmpty()) {
+                KrbError krbError = makePreAuthenticationError(kdcContext);
+                throw new KrbErrorException(krbError);
+            } else {
+                getPreauthHandler().verify(this, preAuthData);
+            }
+        }
+
+        setPreAuthenticated(true);
+    }
+
+    protected void setPreauthRequired(boolean preauthRequired) {
+        preauthContext.setPreauthRequired(preauthRequired);
+    }
+
+    protected boolean isPreauthRequired() {
+        return preauthContext.isPreauthRequired();
+    }
+
+    protected PreauthHandler getPreauthHandler() {
+        return kdcContext.getPreauthHandler();
+    }
+
+    protected void checkEncryptionType() throws KrbException {
+        List<EncryptionType> requestedTypes = getKdcReq().getReqBody().getEtypes();
+
+        EncryptionType bestType = EncryptionUtil.getBestEncryptionType(requestedTypes,
+                kdcContext.getConfig().getEncryptionTypes());
+
+        if (bestType == null) {
+            throw new KrbException(KrbErrorCode.KDC_ERR_ETYPE_NOSUPP);
+        }
+
+        setEncryptionType(bestType);
+    }
+
+    protected void authenticate() throws KrbException {
+        checkEncryptionType();
+        checkPolicy();
+    }
+
+    protected void issueTicket() throws KrbException {
+        KdcReq request = getKdcReq();
+
+        EncryptionType encryptionType = getEncryptionType();
+        EncryptionKey serverKey = getServerEntry().getKeys().get(encryptionType);
+
+        PrincipalName ticketPrincipal = request.getReqBody().getSname();
+
+        EncTicketPart encTicketPart = new EncTicketPart();
+        KdcConfig config = kdcContext.getConfig();
+
+        TicketFlags ticketFlags = new TicketFlags();
+        encTicketPart.setFlags(ticketFlags);
+        ticketFlags.setFlag(TicketFlag.INITIAL);
+
+        if (isPreAuthenticated()) {
+            ticketFlags.setFlag(TicketFlag.PRE_AUTH);
+        }
+
+        if (request.getReqBody().getKdcOptions().isFlagSet(KdcOption.FORWARDABLE)) {
+            if (!config.isForwardableAllowed()) {
+                throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
+            }
+
+            ticketFlags.setFlag(TicketFlag.FORWARDABLE);
+        }
+
+        if (request.getReqBody().getKdcOptions().isFlagSet(KdcOption.PROXIABLE)) {
+            if (!config.isProxiableAllowed()) {
+                throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
+            }
+
+            ticketFlags.setFlag(TicketFlag.PROXIABLE);
+        }
+
+        if (request.getReqBody().getKdcOptions().isFlagSet(KdcOption.ALLOW_POSTDATE)) {
+            if (!config.isPostdatedAllowed()) {
+                throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
+            }
+
+            ticketFlags.setFlag(TicketFlag.MAY_POSTDATE);
+        }
+
+        KdcOptions kdcOptions = request.getReqBody().getKdcOptions();
+
+        EncryptionKey sessionKey = EncryptionHandler.random2Key(getEncryptionType());
+        encTicketPart.setKey(sessionKey);
+
+        encTicketPart.setCname(request.getReqBody().getCname());
+        encTicketPart.setCrealm(request.getReqBody().getRealm());
+
+        TransitedEncoding transEnc = new TransitedEncoding();
+        encTicketPart.setTransited(transEnc);
+        String serverRealm = request.getReqBody().getRealm();
+
+        KerberosTime now = KerberosTime.now();
+        encTicketPart.setAuthTime(now);
+
+        KerberosTime krbStartTime = request.getReqBody().getFrom();
+        if (krbStartTime == null || krbStartTime.lessThan(now) ||
+                krbStartTime.isInClockSkew(config.getAllowableClockSkew())) {
+            krbStartTime = now;
+        }
+        if (krbStartTime.greaterThan(now)
+                && !krbStartTime.isInClockSkew(config.getAllowableClockSkew())
+                && !kdcOptions.isFlagSet(KdcOption.POSTDATED)) {
+            throw new KrbException(KrbErrorCode.KDC_ERR_CANNOT_POSTDATE);
+        }
+
+        if (kdcOptions.isFlagSet(KdcOption.POSTDATED)) {
+            if (!config.isPostdatedAllowed()) {
+                throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
+            }
+
+            ticketFlags.setFlag(TicketFlag.POSTDATED);
+            encTicketPart.setStartTime(krbStartTime);
+        }
+
+        KerberosTime krbEndTime = request.getReqBody().getTill();
+        if (krbEndTime == null) {
+            krbEndTime = krbStartTime.extend(config.getMaximumTicketLifetime() * 1000);
+        } else if (krbStartTime.greaterThan(krbEndTime)) {
+            throw new KrbException(KrbErrorCode.KDC_ERR_NEVER_VALID);
+        }
+        encTicketPart.setEndTime(krbEndTime);
+
+        long ticketLifeTime = Math.abs(krbEndTime.diff(krbStartTime));
+        if (ticketLifeTime < config.getMinimumTicketLifetime()) {
+            throw new KrbException(KrbErrorCode.KDC_ERR_NEVER_VALID);
+        }
+
+        KerberosTime krbRtime = request.getReqBody().getRtime();
+        if (kdcOptions.isFlagSet(KdcOption.RENEWABLE_OK)) {
+            kdcOptions.setFlag(KdcOption.RENEWABLE);
+        }
+        if (kdcOptions.isFlagSet(KdcOption.RENEWABLE)) {
+            if (!config.isRenewableAllowed()) {
+                throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
+            }
+
+            ticketFlags.setFlag(TicketFlag.RENEWABLE);
+
+            if (krbRtime == null) {
+                krbRtime = KerberosTime.NEVER;
+            }
+            KerberosTime allowedMaximumRenewableTime = krbStartTime;
+            allowedMaximumRenewableTime.extend(config.getMaximumRenewableLifetime() * 1000);
+            if (krbRtime.greaterThan(allowedMaximumRenewableTime)) {
+                krbRtime = allowedMaximumRenewableTime;
+            }
+            encTicketPart.setRenewtill(krbRtime);
+        }
+
+        HostAddresses hostAddresses = request.getReqBody().getAddresses();
+        if (hostAddresses == null || hostAddresses.isEmpty()) {
+            if (!config.isEmptyAddressesAllowed()) {
+                throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
+            }
+        } else {
+            encTicketPart.setClientAddresses(hostAddresses);
+        }
+
+        EncryptedData encryptedData = EncryptionUtil.seal(encTicketPart,
+                serverKey, KeyUsage.KDC_REP_TICKET);
+
+        Ticket newTicket = new Ticket();
+        newTicket.setSname(ticketPrincipal);
+        newTicket.setEncryptedEncPart(encryptedData);
+        newTicket.setRealm(serverRealm);
+        newTicket.setEncPart(encTicketPart);
+
+        setTicket(newTicket);
+    }
+
+    private void checkServer() throws KrbException {
+        KdcReq request = getKdcReq();
+
+        KrbIdentity tgsEntry = getEntry(getTgsPrincipal().getName());
+        setTgsEntry(tgsEntry);
+
+        PrincipalName principal = request.getReqBody().getSname();
+        String serverRealm = request.getReqBody().getRealm();
+        if (serverRealm == null || serverRealm.isEmpty()) {
+            serverRealm = kdcContext.getServerRealm();
+        }
+        principal.setRealm(serverRealm);
+
+        KrbIdentity serverEntry = getEntry(principal.getName());
+        setServerEntry(serverEntry);
+
+        EncryptionType encType = request.getReqBody().getEtypes().listIterator().next();
+        EncryptionKey serverKey = serverEntry.getKeys().get(encType);
+        setServerKey(serverKey);
+    }
+
+    protected KrbError makePreAuthenticationError(KdcContext kdcContext) throws KrbException {
+        EncryptionType requestedType = getEncryptionType();
+        List<EncryptionType> encryptionTypes = kdcContext.getConfig().getEncryptionTypes();
+        boolean isNewEtype = true;
+
+        EtypeInfo2 eTypeInfo2 = new EtypeInfo2();
+
+        EtypeInfo eTypeInfo = new EtypeInfo();
+
+        for (EncryptionType encryptionType : encryptionTypes) {
+            if (!isNewEtype) {
+                EtypeInfoEntry etypeInfoEntry = new EtypeInfoEntry();
+                etypeInfoEntry.setEtype(encryptionType);
+                etypeInfoEntry.setSalt(null);
+                eTypeInfo.add(etypeInfoEntry);
+            }
+
+            EtypeInfo2Entry etypeInfo2Entry = new EtypeInfo2Entry();
+            etypeInfo2Entry.setEtype(encryptionType);
+            eTypeInfo2.add(etypeInfo2Entry);
+        }
+
+        byte[] encTypeInfo = null;
+        byte[] encTypeInfo2 = null;
+        if (!isNewEtype) {
+            encTypeInfo = KrbCodec.encode(eTypeInfo);
+        }
+        encTypeInfo2 = KrbCodec.encode(eTypeInfo2);
+
+        MethodData methodData = new MethodData();
+        methodData.add(new PaDataEntry(PaDataType.ENC_TIMESTAMP, null));
+        if (!isNewEtype) {
+            methodData.add(new PaDataEntry(PaDataType.ETYPE_INFO, encTypeInfo));
+        }
+        methodData.add(new PaDataEntry(PaDataType.ETYPE_INFO2, encTypeInfo2));
+
+        KrbError krbError = new KrbError();
+        krbError.setErrorCode(KrbErrorCode.KDC_ERR_PREAUTH_REQUIRED);
+        byte[] encodedData = KrbCodec.encode(methodData);
+        krbError.setEdata(encodedData);
+
+        return krbError;
+    }
+
+    protected KrbIdentity getEntry(String principal) throws KrbException {
+        KrbIdentity entry = null;
+        KrbErrorCode krbErrorCode = KrbErrorCode.KDC_ERR_C_PRINCIPAL_UNKNOWN;
+
+        try {
+            entry = kdcContext.getIdentityService().getIdentity(principal);
+        } catch (Exception e) {
+            throw new KrbException(krbErrorCode, e);
+        }
+
+        if (entry == null) {
+            throw new KrbException(krbErrorCode);
+        }
+
+        return entry;
+    }
+
+    public ByteBuffer getRequestBody() throws KrbException {
+        return null;
+    }
+
+    public EncryptionKey getArmorKey() throws KrbException {
+        return fastContext.armorKey;
+    }
+
+    public PrincipalName getServerPrincipal() {
+        return serverPrincipal;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TgsRequest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TgsRequest.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TgsRequest.java
new file mode 100644
index 0000000..f60c63d
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TgsRequest.java
@@ -0,0 +1,196 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server.request;
+
+import org.apache.kerby.kerberos.kerb.KrbErrorCode;
+import org.apache.kerby.kerberos.kerb.codec.KrbCodec;
+import org.apache.kerby.kerberos.kerb.common.EncryptionUtil;
+import org.apache.kerby.kerberos.kerb.server.KdcContext;
+import org.apache.kerby.kerberos.kerb.KrbConstant;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
+import org.apache.kerby.kerberos.kerb.spec.ap.ApOption;
+import org.apache.kerby.kerberos.kerb.spec.ap.ApReq;
+import org.apache.kerby.kerberos.kerb.spec.ap.Authenticator;
+import org.apache.kerby.kerberos.kerb.spec.common.*;
+import org.apache.kerby.kerberos.kerb.spec.kdc.*;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaDataEntry;
+import org.apache.kerby.kerberos.kerb.spec.ticket.EncTicketPart;
+import org.apache.kerby.kerberos.kerb.spec.ticket.Ticket;
+import org.apache.kerby.kerberos.kerb.spec.ticket.TicketFlag;
+
+import java.nio.ByteBuffer;
+
+public class TgsRequest extends KdcRequest {
+
+    private EncryptionKey tgtSessionKey;
+
+    public TgsRequest(TgsReq tgsReq, KdcContext kdcContext) {
+        super(tgsReq, kdcContext);
+
+        setPreauthRequired(true);
+    }
+
+    public EncryptionKey getTgtSessionKey() {
+        return tgtSessionKey;
+    }
+
+    public void setTgtSessionKey(EncryptionKey tgtSessionKey) {
+        this.tgtSessionKey = tgtSessionKey;
+    }
+
+    public void verifyAuthenticator(PaDataEntry paDataEntry) throws KrbException {
+        ApReq apReq = KrbCodec.decode(paDataEntry.getPaDataValue(), ApReq.class);
+
+        if (apReq.getPvno() != KrbConstant.KRB_V5) {
+            throw new KrbException(KrbErrorCode.KRB_AP_ERR_BADVERSION);
+        }
+
+        if (apReq.getMsgType() != KrbMessageType.AP_REQ) {
+            throw new KrbException(KrbErrorCode.KRB_AP_ERR_MSG_TYPE);
+        }
+
+        EncryptionType encType = getKdcReq().getReqBody().getEtypes().listIterator().next();
+        EncryptionKey tgsKey = getTgsEntry().getKeys().get(encType);
+
+        Ticket ticket = apReq.getTicket();
+        if (ticket.getTktvno() != KrbConstant.KRB_V5) {
+            throw new KrbException(KrbErrorCode.KRB_AP_ERR_BADVERSION);
+        }
+
+        EncTicketPart encPart = EncryptionUtil.unseal(ticket.getEncryptedEncPart(),
+                tgsKey, KeyUsage.KDC_REP_TICKET, EncTicketPart.class);
+        ticket.setEncPart(encPart);
+
+        EncryptionKey encKey = null;
+        //if (apReq.getApOptions().isFlagSet(ApOptions.USE_SESSION_KEY)) {
+        encKey = ticket.getEncPart().getKey();
+
+        if (encKey == null) {
+            throw new KrbException(KrbErrorCode.KRB_AP_ERR_NOKEY);
+        }
+        Authenticator authenticator = EncryptionUtil.unseal(apReq.getEncryptedAuthenticator(),
+                encKey, KeyUsage.TGS_REQ_AUTH, Authenticator.class);
+
+        if (!authenticator.getCname().equals(ticket.getEncPart().getCname())) {
+            throw new KrbException(KrbErrorCode.KRB_AP_ERR_BADMATCH);
+        }
+
+        HostAddresses hostAddresses = ticket.getEncPart().getClientAddresses();
+        if (hostAddresses == null || hostAddresses.isEmpty()) {
+            if (!kdcContext.getConfig().isEmptyAddressesAllowed()) {
+                throw new KrbException(KrbErrorCode.KRB_AP_ERR_BADADDR);
+            }
+        } else if (!hostAddresses.contains(getClientAddress())) {
+            throw new KrbException(KrbErrorCode.KRB_AP_ERR_BADADDR);
+        }
+
+        PrincipalName serverPrincipal = ticket.getSname();
+        serverPrincipal.setRealm(ticket.getRealm());
+        PrincipalName clientPrincipal = authenticator.getCname();
+        clientPrincipal.setRealm(authenticator.getCrealm());
+
+        if (!authenticator.getCtime().isInClockSkew(
+                kdcContext.getConfig().getAllowableClockSkew() * 1000)) {
+            throw new KrbException(KrbErrorCode.KRB_AP_ERR_SKEW);
+        }
+
+        KerberosTime now = KerberosTime.now();
+        KerberosTime startTime = ticket.getEncPart().getStartTime();
+        if (startTime == null) {
+            startTime = ticket.getEncPart().getAuthTime();
+        }
+        if (! startTime.lessThan(now)) {
+            throw new KrbException(KrbErrorCode.KRB_AP_ERR_TKT_NYV);
+        }
+
+        KerberosTime endTime = ticket.getEncPart().getEndTime();
+        if (! endTime.greaterThan(now)) {
+            throw new KrbException(KrbErrorCode.KRB_AP_ERR_TKT_EXPIRED);
+        }
+
+        apReq.getApOptions().setFlag(ApOption.MUTUAL_REQUIRED);
+
+        setTgtSessionKey(ticket.getEncPart().getKey());
+    }
+
+    @Override
+    protected void makeReply() throws KrbException {
+        Ticket ticket = getTicket();
+
+        TgsRep reply = new TgsRep();
+
+        reply.setCname(getClientEntry().getPrincipal());
+        reply.setCrealm(kdcContext.getServerRealm());
+        reply.setTicket(ticket);
+
+        EncKdcRepPart encKdcRepPart = makeEncKdcRepPart();
+        reply.setEncPart(encKdcRepPart);
+
+        EncryptionKey sessionKey = getTgtSessionKey();
+        EncryptedData encryptedData = EncryptionUtil.seal(encKdcRepPart,
+                sessionKey, KeyUsage.TGS_REP_ENCPART_SESSKEY);
+        reply.setEncryptedEncPart(encryptedData);
+
+        setReply(reply);
+    }
+
+    private EncKdcRepPart makeEncKdcRepPart() {
+        KdcReq request = getKdcReq();
+        Ticket ticket = getTicket();
+
+        EncKdcRepPart encKdcRepPart = new EncTgsRepPart();
+
+        //session key
+        encKdcRepPart.setKey(ticket.getEncPart().getKey());
+
+        LastReq lastReq = new LastReq();
+        LastReqEntry entry = new LastReqEntry();
+        entry.setLrType(LastReqType.THE_LAST_INITIAL);
+        entry.setLrValue(new KerberosTime());
+        lastReq.add(entry);
+        encKdcRepPart.setLastReq(lastReq);
+
+        encKdcRepPart.setNonce(request.getReqBody().getNonce());
+
+        encKdcRepPart.setFlags(ticket.getEncPart().getFlags());
+        encKdcRepPart.setAuthTime(ticket.getEncPart().getAuthTime());
+        encKdcRepPart.setStartTime(ticket.getEncPart().getStartTime());
+        encKdcRepPart.setEndTime(ticket.getEncPart().getEndTime());
+
+        if (ticket.getEncPart().getFlags().isFlagSet(TicketFlag.RENEWABLE)) {
+            encKdcRepPart.setRenewTill(ticket.getEncPart().getRenewtill());
+        }
+
+        encKdcRepPart.setSname(ticket.getSname());
+        encKdcRepPart.setSrealm(ticket.getRealm());
+        encKdcRepPart.setCaddr(ticket.getEncPart().getClientAddresses());
+
+        return encKdcRepPart;
+    }
+
+    public ByteBuffer getRequestBody() throws KrbException {
+        return null;
+    }
+
+    public EncryptionKey getArmorKey() throws KrbException {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/main/resources/kdc.conf
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/resources/kdc.conf b/kerby-kerb/kerb-server/src/main/resources/kdc.conf
new file mode 100644
index 0000000..8f286a1
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/resources/kdc.conf
@@ -0,0 +1,51 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+[logging]
+  default = FILE:/var/log/krb5libs.log
+  kdc = FILE:/var/log/krb5kdc.log
+  admin_server = FILE:/var/log/kadmind.log
+
+[kdcdefaults]
+  kdc_udp_port = 88
+  kdc_tcp_port = 8014
+  restrict_anonymous_to_tgt = true
+  kdc_max_dgram_reply_size = 4096
+
+[realms]
+#  ATHENA.MIT.EDU = {
+#    kadmind_port = 749
+#    max_life = 12h 0m 0s
+#    max_renewable_life = 7d 0h 0m 0s
+#    master_key_type = des3-hmac-sha1
+#    supported_enctypes = des3-hmac-sha1:normal des-cbc-crc:normal des-cbc-crc:v4
+#    database_module = openldap_ldapconf
+# }
+
+[dbdefaults]
+  ldap_kerberos_container_dn = cn=krbcontainer dc=mit dc=edu
+
+[dbmodules]
+#  openldap_ldapconf = {
+#    db_library = kldap
+#    disable_last_success = true
+#    ldap_kdc_dn = cn=krbadmin dc=mit,dc=edu
+#    ldap_kadmind_dn = cn=krbadmin dc=mit dc=edu
+#    ldap_service_password_file = /etc/kerberos/service.keyfile
+#    ldap_servers = ldaps://kerberos.mit.edu
+#    ldap_conns_per_server = 5
+#  }

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTest.java b/kerby-kerb/kerb-server/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTest.java
new file mode 100644
index 0000000..c98c00d
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTest.java
@@ -0,0 +1,70 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+
+public class KdcTest {
+
+    private String serverHost = "localhost";
+    private short serverPort = 8089;
+
+    private SimpleKdcServer kdcServer;
+
+    @Before
+    public void setUp() throws Exception {
+        kdcServer = new SimpleKdcServer();
+        kdcServer.setKdcHost(serverHost);
+        kdcServer.setKdcTcpPort(serverPort);
+        kdcServer.init();
+        kdcServer.start();
+    }
+
+    @Test
+    public void testKdc() throws IOException, InterruptedException {
+        Thread.sleep(15);
+
+        SocketChannel socketChannel = SocketChannel.open();
+        socketChannel.configureBlocking(true);
+        SocketAddress sa = new InetSocketAddress(serverHost, serverPort);
+        socketChannel.connect(sa);
+
+        String BAD_KRB_MESSAGE = "Hello World!";
+        ByteBuffer writeBuffer = ByteBuffer.allocate(4 + BAD_KRB_MESSAGE.getBytes().length);
+        writeBuffer.putInt(BAD_KRB_MESSAGE.getBytes().length);
+        writeBuffer.put(BAD_KRB_MESSAGE.getBytes());
+        writeBuffer.flip();
+
+        socketChannel.write(writeBuffer);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        kdcServer.stop();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-server/src/test/java/org/apache/kerby/kerberos/kerb/server/TestKdcConfigLoad.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/test/java/org/apache/kerby/kerberos/kerb/server/TestKdcConfigLoad.java b/kerby-kerb/kerb-server/src/test/java/org/apache/kerby/kerberos/kerb/server/TestKdcConfigLoad.java
new file mode 100644
index 0000000..56e0acb
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/test/java/org/apache/kerby/kerberos/kerb/server/TestKdcConfigLoad.java
@@ -0,0 +1,57 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.kerby.kerberos.kerb.server;
+
+import org.apache.haox.config.Conf;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+public class TestKdcConfigLoad {
+
+    @Test
+    public void test() throws URISyntaxException, IOException {
+        URL confFileUrl = TestKdcConfigLoad.class.getResource("/kdc.conf");
+        File confFile = new File(confFileUrl.toURI());
+
+        KdcConfig krbConfig = new KdcConfig();
+        Conf conf = krbConfig.getConf();
+        conf.addIniConfig(confFile);
+
+        Assert.assertEquals(krbConfig.getDefaultLoggingLocation(), "FILE:/var/log/krb5libs.log");
+        Assert.assertEquals(krbConfig.getKdcLoggingLocation(), "FILE:/var/log/krb5kdc.log");
+        Assert.assertEquals(krbConfig.getAdminLoggingLocation(), "FILE:/var/log/kadmind.log");
+
+        Assert.assertEquals(krbConfig.getKdcUdpPort(), 88);
+        Assert.assertEquals(krbConfig.getKdcTcpPort(), 8014);
+        Assert.assertTrue(krbConfig.isRestrictAnonymousToTgt());
+        Assert.assertEquals(krbConfig.getKdcMaxDgramReplySize(), 4096);
+
+        String[] ldapContainerDn = krbConfig.getLdapKerberosContainerDn();
+        Assert.assertEquals(ldapContainerDn.length, 3);
+        Assert.assertEquals(ldapContainerDn[0], "cn=krbcontainer");
+        Assert.assertEquals(ldapContainerDn[1], "dc=mit");
+        Assert.assertEquals(ldapContainerDn[2], "dc=edu");
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/pom.xml
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/pom.xml b/kerby-kerb/kerb-util/pom.xml
new file mode 100644
index 0000000..e50f748
--- /dev/null
+++ b/kerby-kerb/kerb-util/pom.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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. See accompanying LICENSE file.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.kerby</groupId>
+    <artifactId>kerby-kerb</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>kerb-util</artifactId>
+
+  <name>Kerby-kerb Util</name>
+  <description>Kerby-kerb Utilities</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerby-config</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerb-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerb-crypto</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>