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/03/22 01:20:04 UTC

[3/4] directory-kerby git commit: Renamed some modules

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kdc-tool/server-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/Kadmin.java
----------------------------------------------------------------------
diff --git a/kdc-tool/server-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/Kadmin.java b/kdc-tool/server-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/Kadmin.java
deleted file mode 100644
index 6e0c0f1..0000000
--- a/kdc-tool/server-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/Kadmin.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/**
- *  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.tool.kadmin;
-
-import org.apache.kerby.config.Conf;
-import org.apache.kerby.kerberos.kerb.server.KdcConfig;
-import org.apache.kerby.kerberos.tool.kadmin.executor.AddPrincipalExecutor;
-import org.apache.kerby.kerberos.tool.kadmin.executor.KadminCommandExecutor;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Scanner;
-
-public class Kadmin {
-    private static final String PROMPT = Kadmin.class.getSimpleName() + ".local";
-    private static final String REQUEST_LIST = "Available " + PROMPT + " requests:\n" +
-            "\n" +
-            "add_principal, addprinc, ank\n" +
-            "                         Add principal\n" +
-            "delete_principal, delprinc\n" +
-            "                         Delete principal\n" +
-            "modify_principal, modprinc\n" +
-            "                         Modify principal\n" +
-            "rename_principal, renprinc\n" +
-            "                         Rename principal\n" +
-            "change_password, cpw     Change password\n" +
-            "get_principal, getprinc  Get principal\n" +
-            "list_principals, listprincs, get_principals, getprincs\n" +
-            "                         List principals\n" +
-            "add_policy, addpol       Add policy\n" +
-            "modify_policy, modpol    Modify policy\n" +
-            "delete_policy, delpol    Delete policy\n" +
-            "get_policy, getpol       Get policy\n" +
-            "list_policies, listpols, get_policies, getpols\n" +
-            "                         List policies\n" +
-            "get_privs, getprivs      Get privileges\n" +
-            "ktadd, xst               Add entry(s) to a keytab\n" +
-            "ktremove, ktrem          Remove entry(s) from a keytab\n" +
-            "lock                     Lock database exclusively (use with extreme caution!)\n" +
-            "unlock                   Release exclusive database lock\n" +
-            "purgekeys                Purge previously retained old keys from a principal\n" +
-            "get_strings, getstrs     Show string attributes on a principal\n" +
-            "set_string, setstr       Set a string attribute on a principal\n" +
-            "del_string, delstr       Delete a string attribute on a principal\n" +
-            "list_requests, lr, ?     List available requests.\n" +
-            "quit, exit, q            Exit program.";
-
-    private static KdcConfig kdcConfig;
-    private static Conf backendConfig;
-
-    private static void execute(String command) {
-        if (command.equals("list_requests") ||
-                command.equals("lr") ||
-                command.equals("?")) {
-            System.out.println(REQUEST_LIST);
-            return;
-        }
-
-        KadminCommandExecutor executor = null;
-        if (command.startsWith("add_principal") ||
-                command.startsWith("addprinc") ||
-                command.startsWith("ank")) {
-            executor = new AddPrincipalExecutor(kdcConfig, backendConfig);
-        }
-
-        if (executor == null) {
-            System.out.println("Unknown request \"" + command + "\". Type \"?\" for a request list.");
-            return;
-        }
-        executor.execute(command);
-    }
-
-    private static void initConfig(String[] args) {
-        File confDir;
-        if (args.length == 0) {
-            confDir = new File("/etc/kerby/");// for Linux. TODO: fix for Win etc.
-        } else {
-            confDir = new File(args[0]);
-        }
-
-        if (confDir.exists()) {
-            File kdcConfFile = new File(confDir, "kdc.conf");
-            if (kdcConfFile.exists()) {
-                kdcConfig = new KdcConfig();
-                try {
-                    kdcConfig.addIniConfig(kdcConfFile);
-                } catch (IOException e) {
-                    System.err.println("Can not load the kdc configuration file " + kdcConfFile.getAbsolutePath());
-                    e.printStackTrace();
-                }
-            }
-
-            File backendConfigFile = new File(confDir, "backend.conf");
-            if (backendConfigFile.exists()) {
-                backendConfig = new Conf();
-                try {
-                    backendConfig.addIniConfig(backendConfigFile);
-                } catch (IOException e) {
-                    System.err.println("Can not load the backend configuration file " + backendConfigFile.getAbsolutePath());
-                    e.printStackTrace();
-                }
-            }
-        } else {
-            throw new RuntimeException("Can not find configuration directory");
-        }
-    }
-
-    public static void main(String[] args) {
-        initConfig(args);
-        System.out.print(PROMPT + ": ");
-        Scanner scanner = new Scanner(System.in);
-        String input = scanner.nextLine();
-
-        while (!(input.equals("quit") ||
-                input.equals("exit") ||
-                input.equals("q"))) {
-            execute(input);
-            System.out.print(PROMPT + ": ");
-            input = scanner.nextLine();
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kdc-tool/server-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/executor/AddPrincipalExecutor.java
----------------------------------------------------------------------
diff --git a/kdc-tool/server-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/executor/AddPrincipalExecutor.java b/kdc-tool/server-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/executor/AddPrincipalExecutor.java
deleted file mode 100644
index d67a16e..0000000
--- a/kdc-tool/server-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/executor/AddPrincipalExecutor.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/**
- *  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.tool.kadmin.executor;
-
-import org.apache.kerby.config.Config;
-import org.apache.kerby.kerberos.kerb.KrbException;
-import org.apache.kerby.kerberos.kerb.common.EncryptionUtil;
-import org.apache.kerby.kerberos.kerb.identity.KrbIdentity;
-import org.apache.kerby.kerberos.kerb.identity.backend.IdentityBackend;
-import org.apache.kerby.kerberos.kerb.server.KdcConfig;
-import org.apache.kerby.kerberos.kerb.server.KdcConfigKey;
-import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
-import org.apache.kerby.kerberos.kerb.spec.base.EncryptionKey;
-
-import java.io.Console;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Scanner;
-
-public class AddPrincipalExecutor implements KadminCommandExecutor{
-    private static final String USAGE = "usage: add_principal [options] principal\n" +
-            "\toptions are:\n" +
-            "\t\t[-randkey|-nokey] [-x db_princ_args]* [-expire expdate] [-pwexpire pwexpdate] [-maxlife maxtixlife]\n" +
-            "\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n" +
-            "\t\t[-pw password] [-maxrenewlife maxrenewlife]\n" +
-            "\t\t[-e keysaltlist]\n" +
-            "\t\t[{+|-}attribute]\n" +
-            "\tattributes are:\n" +
-            "\t\tallow_postdated allow_forwardable allow_tgs_req allow_renewable\n" +
-            "\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n" +
-            "\t\trequires_hwauth needchange allow_svr password_changing_service\n" +
-            "\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n" +
-            "\n" +
-            "where,\n" +
-            "\t[-x db_princ_args]* - any number of database specific arguments.\n" +
-            "\t\t\tLook at each database documentation for supported arguments";
-
-    private KdcConfig kdcConfig;
-    private Config backendConfig;
-
-    public AddPrincipalExecutor(KdcConfig kdcConfig, Config backendConfig) {
-        this.kdcConfig = kdcConfig;
-        this.backendConfig = backendConfig;
-    }
-
-    @Override
-    public void execute(String input) {
-        String[] commands = input.split(" ");
-        if (commands.length < 2) {
-            System.err.println(USAGE);
-            return;
-        }
-
-        parseOptions(commands);
-        String principal = commands[commands.length - 1];
-        String password = getPassword(principal);
-
-        if (password == null) {
-            return;
-        }
-
-        addPrincipal(principal, password);
-        System.out.println("Principal \"" + principal + "\" created.");
-    }
-
-    private void parseOptions(String[] commands) {
-        //TODO
-    }
-
-    /**
-     * Get password for the input principal from console
-     */
-    private String getPassword(String principal) {
-        String passwordOnce;
-        String passwordTwice;
-
-        Console console = System.console();
-        if (console == null) {
-            System.out.println("Couldn't get Console instance, " +
-                    "maybe you're running this from within an IDE. " +
-                    "Use scanner to read password.");
-            Scanner scanner = new Scanner(System.in);
-            passwordOnce = getPassword(scanner,
-                    "Enter password for principal \"" + principal + "\":");
-            passwordTwice = getPassword(scanner,
-                    "Re-enter password for principal \"" + principal + "\":");
-
-        } else {
-            passwordOnce = getPassword(console,
-                    "Enter password for principal \"" + principal + "\":");
-            passwordTwice = getPassword(console,
-                    "Re-enter password for principal \"" + principal + "\":");
-        }
-
-        if (!passwordOnce.equals(passwordTwice)) {
-            System.err.println("add_principal: Password mismatch while reading password for \"" + principal + "\".");
-            return null;
-        }
-        return passwordOnce;
-    }
-
-    private String getPassword(Scanner scanner, String prompt) {
-        System.out.println(prompt);
-        return scanner.nextLine().trim();
-    }
-
-    private String getPassword(Console console, String prompt) {
-        console.printf(prompt);
-        char[] passwordChars = console.readPassword();
-        String password = new String(passwordChars).trim();
-        Arrays.fill(passwordChars, ' ');
-        return password;
-    }
-
-    private void addPrincipal(String principal, String password) {
-        IdentityBackend backend = initBackend();
-
-        KrbIdentity identity = createIdentity(principal, password);
-        backend.addIdentity(identity);
-    }
-
-    private IdentityBackend initBackend() {
-        String backendClassName = backendConfig.getString(
-                KdcConfigKey.KDC_IDENTITY_BACKEND);
-        if (backendClassName == null) {
-            throw new RuntimeException("Can not find the IdentityBackend class");
-        }
-
-        Class backendClass = null;
-        try {
-            backendClass = Class.forName(backendClassName);
-        } catch (ClassNotFoundException e) {
-            throw new RuntimeException("Failed to load backend class: "
-                    + backendClassName);
-        }
-
-        IdentityBackend backend;
-        try {
-            backend = (IdentityBackend) backendClass.newInstance();
-        } catch (InstantiationException | IllegalAccessException e) {
-            throw new RuntimeException("Failed to create backend: "
-                    + backendClassName);
-        }
-
-        backend.setConfig(backendConfig);
-        backend.initialize();
-        return backend;
-    }
-
-    protected KrbIdentity createIdentity(String principal, String password) {
-        KrbIdentity kid = new KrbIdentity(principal);
-        kid.setCreatedTime(KerberosTime.now());
-        kid.setExpireTime(KerberosTime.NEVER);
-        kid.setDisabled(false);
-        kid.setKeyVersion(1);
-        kid.setLocked(false);
-
-        kid.addKeys(generateKeys(kid.getPrincipalName(), password));
-
-        return kid;
-    }
-
-    protected List<EncryptionKey> generateKeys(String principal, String password) {
-        try {
-            return EncryptionUtil.generateKeys(principal, password, kdcConfig.getEncryptionTypes());
-        } catch (KrbException e) {
-            throw new RuntimeException("Failed to create keys", e);
-        }
-    }
-
-
-
-
-}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kdc-tool/server-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/executor/KadminCommandExecutor.java
----------------------------------------------------------------------
diff --git a/kdc-tool/server-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/executor/KadminCommandExecutor.java b/kdc-tool/server-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/executor/KadminCommandExecutor.java
deleted file mode 100644
index 3c22bbd..0000000
--- a/kdc-tool/server-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/executor/KadminCommandExecutor.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- *  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.tool.kadmin.executor;
-
-public interface KadminCommandExecutor {
-
-    /**
-     * Execute the kadmin command.
-     */
-    public void execute(String input);
-}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-backend/README.md
----------------------------------------------------------------------
diff --git a/kerby-backend/README.md b/kerby-backend/README.md
new file mode 100644
index 0000000..a399471
--- /dev/null
+++ b/kerby-backend/README.md
@@ -0,0 +1 @@
+This contains all kinds of identity back ends for Kerby KDC.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-backend/json-backend/pom.xml
----------------------------------------------------------------------
diff --git a/kerby-backend/json-backend/pom.xml b/kerby-backend/json-backend/pom.xml
new file mode 100644
index 0000000..6f69af5
--- /dev/null
+++ b/kerby-backend/json-backend/pom.xml
@@ -0,0 +1,63 @@
+<?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>kdc-backend</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>Json-identity-backend</artifactId>
+
+  <name>Json identity backend</name>
+  <description>Json identity backend</description>
+
+  <properties>
+    <json.version>2.3.1</json.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerby-config</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerb-identity</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerb-identity-test</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.google.code.gson</groupId>
+      <artifactId>gson</artifactId>
+      <version>${json.version}</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.12</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/JsonIdentityBackend.java
----------------------------------------------------------------------
diff --git a/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/JsonIdentityBackend.java b/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/JsonIdentityBackend.java
new file mode 100644
index 0000000..36e1703
--- /dev/null
+++ b/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/JsonIdentityBackend.java
@@ -0,0 +1,183 @@
+/**
+ *  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.kdc.identitybackend;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+import org.apache.kerby.config.Config;
+import org.apache.kerby.kerberos.kdc.identitybackend.tool.FileHelper;
+import org.apache.kerby.kerberos.kdc.identitybackend.typeAdapter.EncryptionKeyAdapter;
+import org.apache.kerby.kerberos.kdc.identitybackend.typeAdapter.KerberosTimeAdapter;
+import org.apache.kerby.kerberos.kdc.identitybackend.typeAdapter.PrincipalNameAdapter;
+import org.apache.kerby.kerberos.kerb.identity.KrbIdentity;
+import org.apache.kerby.kerberos.kerb.identity.backend.AbstractIdentityBackend;
+import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
+import org.apache.kerby.kerberos.kerb.spec.base.EncryptionKey;
+import org.apache.kerby.kerberos.kerb.spec.base.PrincipalName;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+import java.util.Map.Entry;
+
+/**
+ * A Json file based backend implementation.
+ *
+ */
+public class JsonIdentityBackend extends AbstractIdentityBackend {
+    public static final String JSON_IDENTITY_BACKEND_FILE = "backend.json.file";
+    private File jsonKdbFile;
+    private Gson gson;
+
+    /**
+     * Identities loaded from file
+     */
+    private Map<String, KrbIdentity> ids;
+    private long kdbFileTimeStamp;
+
+    public JsonIdentityBackend() {
+    }
+
+    /**
+     * Constructing an instance using specified config that contains anything
+     * to be used to initialize the json format database.
+     * @param config
+     */
+    public JsonIdentityBackend(Config config) {
+        setConfig(config);
+    }
+
+    @Override
+    public void initialize() {
+        super.initialize();
+        createGson();
+        load();
+    }
+
+    /**
+     * Load identities from file
+     */
+    public void load() {
+        String jsonFile = getConfig().getString(JSON_IDENTITY_BACKEND_FILE);
+        if (jsonFile == null || jsonFile.isEmpty()) {
+            throw new RuntimeException("No json kdb file is found");
+        }
+
+        jsonKdbFile = new File(jsonFile);
+        if (! jsonKdbFile.exists()) {
+            try {
+                jsonKdbFile.createNewFile();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        checkAndLoad();
+    }
+
+    /**
+     * check kdb file timestamp to see if it's changed or not. If
+     * necessary load the kdb again.
+     */
+    private void checkAndLoad() {
+        long nowTimeStamp = jsonKdbFile.lastModified();
+
+        if (kdbFileTimeStamp == 0 || nowTimeStamp != kdbFileTimeStamp) {
+            //load ids
+            String existsFileJson = FileHelper.readFromFile(jsonKdbFile);
+
+            ids = gson.fromJson(existsFileJson,
+                    new TypeToken<LinkedHashMap<String, KrbIdentity>>() {
+                    }.getType());
+        }
+
+        if (ids == null) {
+            ids = new LinkedHashMap<>();
+        }
+    }
+
+    @Override
+    protected KrbIdentity doGetIdentity(String principalName) {
+        checkAndLoad();
+        return ids.get(principalName);
+    }
+
+    @Override
+    protected KrbIdentity doAddIdentity(KrbIdentity identity) {
+        checkAndLoad();
+        ids.put(identity.getPrincipalName(), identity);
+        idsToFile(ids);
+
+        return identity;
+    }
+
+    @Override
+    protected KrbIdentity doUpdateIdentity(KrbIdentity identity) {
+        checkAndLoad();
+        ids.put(identity.getPrincipalName(), identity);
+        idsToFile(ids);
+
+        return identity;
+    }
+
+    @Override
+    protected void doDeleteIdentity(String principalName) {
+        checkAndLoad();
+        ids.remove(principalName);
+        idsToFile(ids);
+    }
+
+    @Override
+    public List<String> getIdentities(int start, int limit) {
+        LinkedHashMap<String, KrbIdentity> linkedIds = (LinkedHashMap<String, KrbIdentity>) ids;
+        Iterator<Entry<String, KrbIdentity>> iterator = linkedIds.entrySet().iterator();
+
+        int index = 0;
+        for(; index < start; index++) {
+            iterator.next();
+        }
+
+        List<String> principals = new ArrayList<>();
+        for (; index < limit; index++) {
+            Entry<String, KrbIdentity> entry = iterator.next();
+            principals.add(entry.getKey());
+        }
+
+        return principals;
+    }
+
+    private void createGson() {
+        GsonBuilder gsonBuilder = new GsonBuilder();
+        gsonBuilder.registerTypeAdapter(EncryptionKey.class, new EncryptionKeyAdapter());
+        gsonBuilder.registerTypeAdapter(PrincipalName.class, new PrincipalNameAdapter());
+        gsonBuilder.registerTypeAdapter(KerberosTime.class, new KerberosTimeAdapter());
+        gsonBuilder.enableComplexMapKeySerialization();
+        gsonBuilder.setPrettyPrinting();
+        gson = gsonBuilder.create();
+    }
+
+    private void idsToFile(Map<String, KrbIdentity> ids) {
+        String newFileJson = gson.toJson(ids);
+        FileHelper.writeToFile(newFileJson, jsonKdbFile);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/tool/FileHelper.java
----------------------------------------------------------------------
diff --git a/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/tool/FileHelper.java b/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/tool/FileHelper.java
new file mode 100644
index 0000000..b6c275b
--- /dev/null
+++ b/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/tool/FileHelper.java
@@ -0,0 +1,74 @@
+/**
+ *  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.kdc.identitybackend.tool;
+
+import java.io.*;
+
+public class FileHelper {
+
+    public static String readFromFile(File file) {
+        assert (file != null);
+
+        BufferedReader reader = null;
+        try {
+            FileInputStream fileInputStream = new FileInputStream(file);
+            reader = new BufferedReader(new InputStreamReader(fileInputStream));
+            StringBuilder stringBuilder = new StringBuilder();
+            String line = null;
+            while ((line = reader.readLine()) != null) {
+                stringBuilder.append(line);
+            }
+            return stringBuilder.toString();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                if (reader != null) {
+                    reader.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        return null;
+    }
+
+    public static void writeToFile(String string, File file) {
+        assert (file != null);
+
+        BufferedWriter bufferedWriter = null;
+        try {
+            FileWriter fileWriter = new FileWriter(file);
+            bufferedWriter = new BufferedWriter(fileWriter);
+            bufferedWriter.write(string);
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                if (bufferedWriter != null){
+                    bufferedWriter.close();
+                }
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/typeAdapter/EncryptionKeyAdapter.java
----------------------------------------------------------------------
diff --git a/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/typeAdapter/EncryptionKeyAdapter.java b/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/typeAdapter/EncryptionKeyAdapter.java
new file mode 100644
index 0000000..721b0e9
--- /dev/null
+++ b/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/typeAdapter/EncryptionKeyAdapter.java
@@ -0,0 +1,55 @@
+/**
+ *  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.kdc.identitybackend.typeAdapter;
+
+import com.google.gson.*;
+import org.apache.kerby.kerberos.kerb.spec.base.EncryptionKey;
+import org.apache.kerby.kerberos.kerb.spec.base.EncryptionType;
+import org.apache.kerby.util.HexUtil;
+
+import java.lang.reflect.Type;
+
+public class EncryptionKeyAdapter implements JsonSerializer<EncryptionKey>,
+        JsonDeserializer<EncryptionKey> {
+
+    @Override
+    public EncryptionKey deserialize(JsonElement jsonElement, Type type,
+                                     JsonDeserializationContext jsonDeserializationContext)
+            throws JsonParseException {
+        JsonObject jsonObject = (JsonObject) jsonElement;
+        EncryptionKey encryptionKey = new EncryptionKey();
+        encryptionKey.setKvno(jsonObject.get("kvno").getAsInt());
+        String encryptionTypeString = jsonObject.get("keyType").getAsString();
+        EncryptionType encryptionType = EncryptionType.fromName(encryptionTypeString);
+        encryptionKey.setKeyType(encryptionType);
+        encryptionKey.setKeyData(HexUtil.hex2bytes(jsonObject.get("keyData").getAsString()));
+        return encryptionKey;
+    }
+
+    @Override
+    public JsonElement serialize(EncryptionKey encryptionKey,
+                                 Type type, JsonSerializationContext jsonSerializationContext) {
+        JsonObject jsonObject = new JsonObject();
+        jsonObject.addProperty("kvno", encryptionKey.getKvno());
+        jsonObject.addProperty("keyType", encryptionKey.getKeyType().getName());
+        jsonObject.addProperty("keyData", HexUtil.bytesToHex(encryptionKey.getKeyData()));
+        return jsonObject;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/typeAdapter/KerberosTimeAdapter.java
----------------------------------------------------------------------
diff --git a/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/typeAdapter/KerberosTimeAdapter.java b/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/typeAdapter/KerberosTimeAdapter.java
new file mode 100644
index 0000000..b4f6a85
--- /dev/null
+++ b/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/typeAdapter/KerberosTimeAdapter.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.kdc.identitybackend.typeAdapter;
+
+import com.google.gson.*;
+import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
+
+import java.lang.reflect.Type;
+
+public class KerberosTimeAdapter implements JsonSerializer<KerberosTime>,
+        JsonDeserializer<KerberosTime> {
+
+    @Override
+    public KerberosTime deserialize(JsonElement jsonElement, Type type,
+                                    JsonDeserializationContext jsonDeserializationContext)
+            throws JsonParseException {
+        String timeString = jsonElement.getAsString();
+        long time = Long.valueOf(timeString);
+        return new KerberosTime(time);
+    }
+
+    @Override
+    public JsonElement serialize(KerberosTime kerberosTime, Type type,
+                                 JsonSerializationContext jsonSerializationContext) {
+        String timeString = String.valueOf(kerberosTime.getTime());
+        return new JsonPrimitive(timeString);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/typeAdapter/PrincipalNameAdapter.java
----------------------------------------------------------------------
diff --git a/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/typeAdapter/PrincipalNameAdapter.java b/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/typeAdapter/PrincipalNameAdapter.java
new file mode 100644
index 0000000..869cc59
--- /dev/null
+++ b/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/typeAdapter/PrincipalNameAdapter.java
@@ -0,0 +1,42 @@
+/**
+ *  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.kdc.identitybackend.typeAdapter;
+
+import com.google.gson.*;
+import org.apache.kerby.kerberos.kerb.spec.base.PrincipalName;
+
+import java.lang.reflect.Type;
+
+public class PrincipalNameAdapter implements JsonSerializer<PrincipalName>,
+        JsonDeserializer<PrincipalName> {
+
+    @Override
+    public PrincipalName deserialize(JsonElement jsonElement, Type type,
+                                     JsonDeserializationContext jsonDeserializationContext)
+            throws JsonParseException {
+        return new PrincipalName(jsonElement.getAsString());
+    }
+
+    @Override
+    public JsonElement serialize(PrincipalName principalName,
+                                 Type type, JsonSerializationContext jsonSerializationContext) {
+        return new JsonPrimitive(principalName.getName());
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-backend/json-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/JsonBackendTest.java
----------------------------------------------------------------------
diff --git a/kerby-backend/json-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/JsonBackendTest.java b/kerby-backend/json-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/JsonBackendTest.java
new file mode 100644
index 0000000..9894e10
--- /dev/null
+++ b/kerby-backend/json-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/JsonBackendTest.java
@@ -0,0 +1,73 @@
+/**
+ *  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.identity.backend;
+
+import org.apache.kerby.config.Conf;
+import org.apache.kerby.config.Config;
+import org.apache.kerby.kerberos.kdc.identitybackend.JsonIdentityBackend;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.File;
+
+/**
+ * Json backend test
+ */
+public class JsonBackendTest extends BackendTest {
+    private static IdentityBackend backend;
+
+    @BeforeClass
+    public static void setup() {
+        File testDir = new File(System.getProperty("test.dir", "target"));
+        String jsonBackendFileString = new File(testDir, "json-identity-backend-file").getAbsolutePath();
+
+        Config backendConfig = new Conf();
+        backendConfig.setString(JsonIdentityBackend.JSON_IDENTITY_BACKEND_FILE, jsonBackendFileString);
+
+        backend = new JsonIdentityBackend(backendConfig);
+        backend.initialize();
+    }
+
+    @Test
+    public void testGet() {
+        super.testGet(backend);
+    }
+
+    @Test
+    public void testStore() {
+        super.testStore(backend);
+    }
+
+    @Test
+    public void testUpdate() {
+        super.testUpdate(backend);
+    }
+
+    @Test
+    public void testDelete() {
+        super.testDelete(backend);
+    }
+
+    @Test
+    public void testGetIdentities() {
+        super.testGetIdentities(backend);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-backend/ldap-backend/pom.xml
----------------------------------------------------------------------
diff --git a/kerby-backend/ldap-backend/pom.xml b/kerby-backend/ldap-backend/pom.xml
new file mode 100644
index 0000000..545c5a9
--- /dev/null
+++ b/kerby-backend/ldap-backend/pom.xml
@@ -0,0 +1,62 @@
+<?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>kdc-backend</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>ldap-identity-backend</artifactId>
+
+  <name>Ldap identity backend</name>
+  <description>Ldap identity backend</description>
+
+  <properties>
+    <ldap.api.version>1.0.0-M28</ldap.api.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerby-config</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerb-identity</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.directory.api</groupId>
+      <artifactId>api-ldap-client-api</artifactId>
+      <version>${ldap.api.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerb-identity-test</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.12</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-backend/ldap-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/LdapIdentityBackend.java
----------------------------------------------------------------------
diff --git a/kerby-backend/ldap-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/LdapIdentityBackend.java b/kerby-backend/ldap-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/LdapIdentityBackend.java
new file mode 100644
index 0000000..54e3fb9
--- /dev/null
+++ b/kerby-backend/ldap-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/LdapIdentityBackend.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.kdc.identitybackend;
+
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.kerby.config.Config;
+import org.apache.kerby.kerberos.kerb.identity.KrbIdentity;
+import org.apache.kerby.kerberos.kerb.identity.backend.AbstractIdentityBackend;
+
+import java.util.List;
+
+/**
+ * An LDAP based backend implementation.
+ *
+ */
+public class LdapIdentityBackend extends AbstractIdentityBackend {
+
+    // the connection to the LDAP server
+    // in case of ApacheDS this will be an instance of LdapCoreSessionConnection
+    private LdapConnection connection;
+
+    private Dn baseDn;
+
+    /**
+     * Constructing an instance using specified config that contains anything
+     * to be used to initialize an LdapConnection and necessary baseDn.
+     * @param config
+     */
+    public LdapIdentityBackend(Config config) {
+        setConfig(config);
+    }
+
+    public void initialize() {
+        super.initialize();
+
+        // init Ldap connection and baseDn.
+    }
+
+    @Override
+    protected KrbIdentity doGetIdentity(String principalName) {
+        return null;
+    }
+
+    @Override
+    protected KrbIdentity doAddIdentity(KrbIdentity identity) {
+        return null;
+    }
+
+    @Override
+    protected KrbIdentity doUpdateIdentity(KrbIdentity identity) {
+        return null;
+    }
+
+    @Override
+    protected void doDeleteIdentity(String principalName) {
+
+    }
+
+    @Override
+    public List<String> getIdentities(int start, int limit) {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/LdapBackendTest.java
----------------------------------------------------------------------
diff --git a/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/LdapBackendTest.java b/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/LdapBackendTest.java
new file mode 100644
index 0000000..74ac597
--- /dev/null
+++ b/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/LdapBackendTest.java
@@ -0,0 +1,43 @@
+/**
+ *  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.identity.backend;
+
+import org.apache.kerby.config.Conf;
+import org.apache.kerby.kerberos.kdc.identitybackend.LdapIdentityBackend;
+import org.junit.Before;
+
+/**
+ * Ldap backend test
+ */
+public class LdapBackendTest extends BackendTest {
+    private IdentityBackend backend;
+
+    @Before
+    public void setup() {
+        Conf config = new Conf();
+        backend = new LdapIdentityBackend(config);
+        backend.initialize();
+    }
+
+    //@Test
+    public void testGet() {
+        super.testGet(backend);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-backend/pom.xml
----------------------------------------------------------------------
diff --git a/kerby-backend/pom.xml b/kerby-backend/pom.xml
new file mode 100644
index 0000000..2cbae64
--- /dev/null
+++ b/kerby-backend/pom.xml
@@ -0,0 +1,42 @@
+<?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-all</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>kdc-backend</artifactId>
+  <name>Kdc Backends</name>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <modules>
+    <module>ldap-backend</module>
+    <module>json-backend</module>
+    <module>zookeeper-backend</module>
+  </modules>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerby-util</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-backend/zookeeper-backend/pom.xml
----------------------------------------------------------------------
diff --git a/kerby-backend/zookeeper-backend/pom.xml b/kerby-backend/zookeeper-backend/pom.xml
new file mode 100644
index 0000000..d756646
--- /dev/null
+++ b/kerby-backend/zookeeper-backend/pom.xml
@@ -0,0 +1,55 @@
+<?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>kdc-backend</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>zookeeper-backend</artifactId>
+  <name>Zookeeper identity backend</name>
+  <description>Zookeeper identity backend</description>
+
+  <properties>
+    <zookeeper.version>3.4.6</zookeeper.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerby-config</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerb-identity</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.zookeeper</groupId>
+      <artifactId>zookeeper</artifactId>
+      <version>${zookeeper.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerb-identity-test</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/ZKConfKey.java
----------------------------------------------------------------------
diff --git a/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/ZKConfKey.java b/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/ZKConfKey.java
new file mode 100644
index 0000000..a9d798d
--- /dev/null
+++ b/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/ZKConfKey.java
@@ -0,0 +1,53 @@
+/**
+ *  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.kdc.identitybackend;
+
+import org.apache.kerby.config.ConfigKey;
+
+/**
+ * Define all the ZK backend related configuration items with default values.
+ */
+public enum ZKConfKey implements ConfigKey {
+    ZK_HOST("127.0.0.1"),
+    ZK_PORT(9015),
+    DATA_DIR,
+    DATA_LOG_DIR
+    ;
+
+    private Object defaultValue;
+
+    private ZKConfKey() {
+        this.defaultValue = null;
+    }
+
+    private ZKConfKey(Object defaultValue) {
+        this.defaultValue = defaultValue;
+    }
+
+    @Override
+    public String getPropertyKey() {
+        return name().toLowerCase();
+    }
+
+    @Override
+    public Object getDefaultValue() {
+        return this.defaultValue;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/ZookeeperIdentityBackend.java
----------------------------------------------------------------------
diff --git a/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/ZookeeperIdentityBackend.java b/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/ZookeeperIdentityBackend.java
new file mode 100644
index 0000000..a1c795b
--- /dev/null
+++ b/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/ZookeeperIdentityBackend.java
@@ -0,0 +1,156 @@
+/**
+ *  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.kdc.identitybackend;
+
+import org.apache.kerby.config.Config;
+import org.apache.kerby.kerberos.kerb.identity.KrbIdentity;
+import org.apache.kerby.kerberos.kerb.identity.backend.AbstractIdentityBackend;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.server.ServerConfig;
+import org.apache.zookeeper.server.ZooKeeperServerMain;
+import org.apache.zookeeper.server.quorum.QuorumPeerConfig;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * A Zookeeper based backend implementation. Currently it uses an embedded
+ * Zookeeper. In follow up it will be enhanced to support standalone Zookeeper
+ * cluster for replication and reliability.
+ *
+ */
+public class ZookeeperIdentityBackend extends AbstractIdentityBackend
+        implements Watcher {
+    private Config config;
+    private String zkHost;
+    private int zkPort;
+    private File dataDir;
+    private File dataLogDir;
+
+    /**
+     * Constructing an instance using specified config that contains anything
+     * to be used to init the Zookeeper backend.
+     * @param config
+     */
+    public ZookeeperIdentityBackend(Config config) {
+        this.config = config;
+        init();
+    }
+
+    private void init() {
+        zkHost = config.getString(ZKConfKey.ZK_HOST);
+        zkPort = config.getInt(ZKConfKey.ZK_PORT);
+        dataDir = new File(config.getString(ZKConfKey.DATA_DIR));
+        dataLogDir = new File(config.getString(ZKConfKey.DATA_LOG_DIR));
+
+        startEmbeddedZookeeper();
+        connectZK();
+    }
+
+    /**
+     * Prepare connection to Zookeeper server.
+     */
+    private void connectZK() {
+        try {
+            ZooKeeper zooKeeper = new ZooKeeper(zkHost, zkPort, null);
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to prepare Zookeeper connection");
+        }
+    }
+
+    /**
+     * Load identities from file
+     */
+    public void load() throws IOException {
+        // TODO: prepare zookeeper connection to the server.
+        ZooKeeper zooKeeper = null;
+
+        // TODO: load the kdb file from zookeeper
+    }
+
+    private void startEmbeddedZookeeper() {
+
+        Properties startupProperties = new Properties();
+        startupProperties.put("dataDir", dataDir.getAbsolutePath());
+        startupProperties.put("dataLogDir", dataLogDir.getAbsolutePath());
+        startupProperties.put("clientPort", zkPort);
+
+        QuorumPeerConfig quorumConfiguration = new QuorumPeerConfig();
+        try {
+            quorumConfiguration.parseProperties(startupProperties);
+        } catch(Exception e) {
+            throw new RuntimeException(e);
+        }
+
+        final ZooKeeperServerMain zooKeeperServer = new ZooKeeperServerMain();
+        final ServerConfig configuration = new ServerConfig();
+        configuration.readFrom(quorumConfiguration);
+
+        new Thread() {
+            public void run() {
+                try {
+                    zooKeeperServer.runFromConfig(configuration);
+                } catch (IOException e) {
+                    e.printStackTrace();
+                    //log.error("ZooKeeper Failed", e);
+                }
+            }
+        }.start();
+
+    }
+
+    /**
+     * This will watch all the kdb update event so that it's timely synced.
+     * @param event
+     */
+    @Override
+    public void process(WatchedEvent event) {
+        System.out.print("I got an event: " + event);
+    }
+
+    @Override
+    protected KrbIdentity doGetIdentity(String principalName) {
+        return null;
+    }
+
+    @Override
+    protected KrbIdentity doAddIdentity(KrbIdentity identity) {
+        return null;
+    }
+
+    @Override
+    protected KrbIdentity doUpdateIdentity(KrbIdentity identity) {
+        return null;
+    }
+
+    @Override
+    protected void doDeleteIdentity(String principalName) {
+
+    }
+
+    @Override
+    public List<String> getIdentities(int start, int limit) {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-backend/zookeeper-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/ZookeeperBackendTest.java
----------------------------------------------------------------------
diff --git a/kerby-backend/zookeeper-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/ZookeeperBackendTest.java b/kerby-backend/zookeeper-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/ZookeeperBackendTest.java
new file mode 100644
index 0000000..6dc734a
--- /dev/null
+++ b/kerby-backend/zookeeper-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/ZookeeperBackendTest.java
@@ -0,0 +1,66 @@
+/**
+ *  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.identity.backend;
+
+import org.apache.kerby.config.Conf;
+import org.apache.kerby.kerberos.kdc.identitybackend.ZKConfKey;
+import org.apache.kerby.kerberos.kdc.identitybackend.ZookeeperIdentityBackend;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.File;
+
+/**
+ * Ldap backend test
+ */
+public class ZookeeperBackendTest extends BackendTest {
+    private static IdentityBackend backend;
+
+    @BeforeClass
+    public static void setup() {
+        Conf config = new Conf();
+
+        File testdir = new File(System.getProperty("test.dir", "target"));
+        File instanceDir = new File(testdir, "zookeeper");
+        instanceDir.mkdirs();
+        File dataDir = new File(instanceDir, "data");
+        dataDir.mkdirs();
+        config.setString(ZKConfKey.DATA_DIR.getPropertyKey(), dataDir.getAbsolutePath());
+        File dataLogDir = new File(instanceDir, "log");
+        dataLogDir.mkdirs();
+        config.setString(ZKConfKey.DATA_LOG_DIR.getPropertyKey(), dataLogDir.getAbsolutePath());
+
+        backend = new ZookeeperIdentityBackend(config);
+        backend.initialize();
+        backend.start();
+    }
+
+    //@Test
+    public void testGet() {
+        super.testGet(backend);
+    }
+
+    @AfterClass
+    public static void tearDown() {
+        backend.stop();
+        backend.release();
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-dist/tool-dist/pom.xml
----------------------------------------------------------------------
diff --git a/kerby-dist/tool-dist/pom.xml b/kerby-dist/tool-dist/pom.xml
index 009b2bf..2e07f87 100644
--- a/kerby-dist/tool-dist/pom.xml
+++ b/kerby-dist/tool-dist/pom.xml
@@ -54,7 +54,7 @@
                   <tasks>
                     <copy file="../../kerby-kerb/kerb-client/target/kerb-client-${project.version}-jar-with-dependencies.jar" tofile="lib/kerb-client-${project.version}-jar-with-dependencies.jar"/>
                     <copy file="../../kdc-tool/client-tool/target/client-tool-${project.version}.jar" tofile="lib/client-tool-${project.version}.jar"/>
-                    <copy file="../../kdc-tool/server-tool/target/server-tool-${project.version}.jar" tofile="lib/server-tool-${project.version}.jar"/>
+                    <copy file="../../kdc-tool/kdc-tool/target/kdc-tool-${project.version}.jar" tofile="lib/kdc-tool-${project.version}.jar"/>
                   </tasks>
                 </configuration>
                 <goals>

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-tool/README.md
----------------------------------------------------------------------
diff --git a/kerby-tool/README.md b/kerby-tool/README.md
new file mode 100644
index 0000000..b65c688
--- /dev/null
+++ b/kerby-tool/README.md
@@ -0,0 +1,2 @@
+This contains all kinds of tools provided by or serving for Kerby KDC,
+including both client side and server side.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-tool/client-tool/pom.xml
----------------------------------------------------------------------
diff --git a/kerby-tool/client-tool/pom.xml b/kerby-tool/client-tool/pom.xml
new file mode 100644
index 0000000..c87174c
--- /dev/null
+++ b/kerby-tool/client-tool/pom.xml
@@ -0,0 +1,56 @@
+<?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>kdc-tool</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>client-tool</artifactId>
+  <name>Client Tool</name>
+  <description>Kerby KDC client tool</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-client</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerb-server</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>com.nimbusds</groupId>
+      <artifactId>nimbus-jose-jwt</artifactId>
+      <version>3.8.2</version>
+    </dependency>
+
+  </dependencies>
+  
+</project>

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/ToolUtil.java
----------------------------------------------------------------------
diff --git a/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/ToolUtil.java b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/ToolUtil.java
new file mode 100644
index 0000000..f70543e
--- /dev/null
+++ b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/ToolUtil.java
@@ -0,0 +1,90 @@
+/**
+ *  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.tool;
+
+import org.apache.kerby.kerberos.kerb.client.KOption;
+import org.apache.kerby.kerberos.kerb.client.KOptionType;
+import org.apache.kerby.kerberos.kerb.client.KrbOption;
+import org.apache.kerby.kerberos.kerb.client.KOptions;
+
+import java.io.File;
+
+/**
+ * Tool utilities.
+ */
+public class ToolUtil {
+
+    /**
+     * Parse string value according to kopt type.
+     * @param kopt
+     * @param strValue
+     * @return true when successful, false otherwise
+     */
+    public static boolean parseSetValue(KOption kopt, String strValue) {
+        KOptionType kt = kopt.getType();
+        if (kt == KOptionType.NOV) {
+            return true; // no need of a value
+        }
+        if (strValue == null || strValue.isEmpty()) {
+            return false;
+        }
+
+        if (kt == KOptionType.FILE) {
+            // May check file sanity
+            kopt.setValue(new File(strValue));
+        } else if (kt == KOptionType.DIR) {
+            File dir = new File(strValue);
+            if (! dir.exists()) {
+                throw new IllegalArgumentException("Invalid dir:" + strValue);
+            }
+            kopt.setValue(dir);
+        } else if (kt == KOptionType.INT) {
+            try {
+                Integer num = Integer.valueOf(strValue);
+                kopt.setValue(num);
+            } catch (NumberFormatException nfe) {
+                throw new IllegalArgumentException("Invalid integer:" + strValue);
+            }
+        } else if (kt == KOptionType.FILE) {
+            kopt.setValue(strValue);
+        } else {
+            throw new IllegalArgumentException("Not recognised option:" + strValue);
+        }
+
+        return true;
+    }
+
+    /**
+     * Convert tool (like kinit) options to KrbOptions.
+     * @param krbOptions
+     * @return krb options
+     */
+    public static KOptions convertOptions(KOptions krbOptions) {
+        KOptions results = new KOptions();
+
+        for (KOption toolOpt : krbOptions.getOptions()) {
+            KrbOption krbOpt = KrbOption.fromOptionName(toolOpt.getOptionName());
+            krbOpt.setValue(toolOpt.getValue());
+            results.add(krbOpt);
+        }
+
+        return results;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/kinit/Kinit.java
----------------------------------------------------------------------
diff --git a/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/kinit/Kinit.java b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/kinit/Kinit.java
new file mode 100644
index 0000000..f3da909
--- /dev/null
+++ b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/kinit/Kinit.java
@@ -0,0 +1,164 @@
+/**
+ *  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.tool.kinit;
+
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.client.KOptionType;
+import org.apache.kerby.kerberos.kerb.client.KOptions;
+import org.apache.kerby.kerberos.kerb.client.KrbClient;
+import org.apache.kerby.kerberos.kerb.spec.ticket.TgtTicket;
+import org.apache.kerby.kerberos.tool.ToolUtil;
+
+import java.io.Console;
+import java.util.Arrays;
+import java.util.Scanner;
+
+/**
+ * kinit like tool
+ */
+public class Kinit {
+
+    private static final String USAGE =
+            "Usage: kinit [-V] [-l lifetime] [-s start_time]\n" +
+                    "\t\t[-r renewable_life] [-f | -F] [-p | -P] -n [-a | -A] [-C] [-E]\n" +
+                    "\t\t[-v] [-R] [-k [-i|-t keytab_file]] [-c cachename]\n" +
+                    "\t\t[-S service_name] [-T ticket_armor_cache]\n" +
+                    "\t\t[-X <attribute>[=<value>]] <principal>\n\n" +
+                    "\tDESCRIPTION:\n" +
+                    "\t\tkinit obtains and caches an initial ticket-granting ticket for principal.\n\n" +
+                    "\tOPTIONS:\n" +
+                    "\t\t-V verbose\n" +
+                    "\t\t-l lifetime\n" +
+                    "\t\t--s start time\n" +
+                    "\t\t-r renewable lifetime\n" +
+                    "\t\t-f forwardable\n" +
+                    "\t\t-F not forwardable\n" +
+                    "\t\t-p proxiable\n" +
+                    "\t\t-P not proxiable\n" +
+                    "\t\t-n anonymous\n" +
+                    "\t\t-a include addresses\n" +
+                    "\t\t-A do not include addresses\n" +
+                    "\t\t-v validate\n" +
+                    "\t\t-R renew\n" +
+                    "\t\t-C canonicalize\n" +
+                    "\t\t-E client is enterprise principal name\n" +
+                    "\t\t-k use keytab\n" +
+                    "\t\t-i use default client keytab (with -k)\n" +
+                    "\t\t-t filename of keytab to use\n" +
+                    "\t\t-c Kerberos 5 cache name\n" +
+                    "\t\t-S service\n" +
+                    "\t\t-T armor credential cache\n" +
+                    "\t\t-X <attribute>[=<value>]\n" +
+                    "\n";
+
+
+    private static void printUsage(String error) {
+        System.err.println(error + "\n");
+        System.err.println(USAGE);
+        System.exit(-1);
+    }
+
+    /**
+     * Get password for the input principal from console
+     */
+    private static String getPassword(String principal) {
+        Console console = System.console();
+        if (console == null) {
+            System.out.println("Couldn't get Console instance, " +
+                    "maybe you're running this from within an IDE. " +
+                    "Use scanner to read password.");
+            System.out.println("Password for " + principal + ":");
+            Scanner scanner = new Scanner(System.in);
+            return scanner.nextLine().trim();
+        }
+        console.printf("Password for " + principal + ":");
+        char[] passwordChars = console.readPassword();
+        String password = new String(passwordChars).trim();
+        Arrays.fill(passwordChars, ' ');
+
+        return password;
+    }
+
+    private static int requestTicket(String principal, KOptions kinitOptions) {
+        KrbClient krbClient = new KrbClient();
+        krbClient.init();
+
+        String password = getPassword(principal);
+
+        try {
+            TgtTicket tgt = krbClient.requestTgtTicket(principal, password,
+                    ToolUtil.convertOptions(kinitOptions));
+            // TODO: write tgt into credentials cache.
+            return 0;
+        } catch (KrbException e) {
+            System.err.println("Error occurred:" + e.getMessage());
+            return -1;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        KOptions ktOptions = new KOptions();
+        KinitOption kto;
+        String principal = null;
+
+        int i = 0;
+        String opt, param, error;
+        while (i < args.length) {
+            error = null;
+
+            opt = args[i++];
+            if (opt.startsWith("-")) {
+                kto = KinitOption.fromName(opt);
+                if (kto == KinitOption.NONE) {
+                    error = "Invalid option:" + opt;
+                    break;
+                }
+            } else {
+                principal = opt;
+                break;
+            }
+
+            if (kto.getType() != KOptionType.NOV) { // require a parameter
+                param = null;
+                if (i < args.length) {
+                    param = args[i++];
+                }
+                if (param != null) {
+                    ToolUtil.parseSetValue(kto, param);
+                } else {
+                    error = "Option " + opt + " require a parameter";
+                }
+            }
+
+            if (error != null) {
+                printUsage(error);
+            }
+            ktOptions.add(kto);
+        }
+
+        if (principal == null) {
+            printUsage("No principal is specified");
+        }
+
+        int errNo = Kinit.requestTicket(principal, ktOptions);
+        System.exit(errNo);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/kinit/KinitOption.java
----------------------------------------------------------------------
diff --git a/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/kinit/KinitOption.java b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/kinit/KinitOption.java
new file mode 100644
index 0000000..cade8a8
--- /dev/null
+++ b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/kinit/KinitOption.java
@@ -0,0 +1,133 @@
+/**
+ *  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.tool.kinit;
+
+import org.apache.kerby.kerberos.kerb.client.KOption;
+import org.apache.kerby.kerberos.kerb.client.KOptionType;
+
+public enum KinitOption implements KOption {
+    NONE("NONE"),
+    LIFE_TIME("-l", "lifetime", KOptionType.INT),
+    START_TIME("-s", "start time", KOptionType.INT),
+    RENEWABLE_LIFE("-r", "renewable lifetime", KOptionType.INT),
+    FORWARDABLE("-f", "forwardable"),
+    NOT_FORWARDABLE("-F", "not forwardable"),
+    PROXIABLE("-p", "proxiable"),
+    NOT_PROXIABLE("-P", "not proxiable"),
+    ANONYMOUS("-n", "anonymous"),
+    INCLUDE_ADDRESSES("-a", "include addresses"),
+    NOT_INCLUDE_ADDRESSES("-A", "do not include addresses"),
+    VALIDATE("-v", "validate"),
+    RENEW("-R", "renew"),
+    CANONICALIZE("-C", "canonicalize"),
+    AS_ENTERPRISE_PN("-E", "client is enterprise principal name"),
+    USE_KEYTAB("-k", "use keytab"),
+    USE_DFT_KEYTAB("-i", "use default client keytab (with -k)"),
+    USER_KEYTAB_FILE("-t", "filename of keytab to use", KOptionType.STR),
+    KRB5_CACHE("-c", "Kerberos 5 cache name", KOptionType.STR),
+    SERVICE("-S", "service", KOptionType.STR),
+    ARMOR_CACHE("-T", "armor credential cache", KOptionType.FILE),
+    XATTR("-X", "<attribute>[=<value>]", KOptionType.STR),
+    ;
+
+    private String name;
+    private KOptionType type = KOptionType.NONE;
+    private String description;
+    private Object value;
+
+    KinitOption(String description) {
+        this(description, KOptionType.NOV); // As a flag by default
+    }
+
+    KinitOption(String description, KOptionType type) {
+        this.description = description;
+        this.type = type;
+    }
+
+    KinitOption(String name, String description) {
+        this(name, description, KOptionType.NOV); // As a flag by default
+    }
+
+    KinitOption(String name, String description, KOptionType type) {
+        this.name = name;
+        this.description = description;
+        this.type = type;
+    }
+
+    @Override
+    public String getOptionName() {
+        return name();
+    }
+
+    @Override
+    public void setType(KOptionType type) {
+        this.type = type;
+    }
+
+    @Override
+    public KOptionType getType() {
+        return this.type;
+    }
+
+    @Override
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    @Override
+    public String getName() {
+        if (name != null) {
+            return name;
+        }
+        return name();
+    }
+
+    @Override
+    public String getDescription() {
+        return this.description;
+    }
+
+    @Override
+    public void setValue(Object value) {
+        this.value = value;
+    }
+
+    @Override
+    public Object getValue() {
+        return value;
+    }
+
+    public static KinitOption fromName(String name) {
+        if (name != null) {
+            for (KinitOption ko : values()) {
+                if (ko.getName().equals(name)) {
+                    return (KinitOption) ko;
+                }
+            }
+        }
+        return NONE;
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/AuthzDataEntry.java
----------------------------------------------------------------------
diff --git a/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/AuthzDataEntry.java b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/AuthzDataEntry.java
new file mode 100644
index 0000000..2d57fbf
--- /dev/null
+++ b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/AuthzDataEntry.java
@@ -0,0 +1,52 @@
+/**
+ *  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.tool.token;
+
+import org.apache.kerby.asn1.type.Asn1FieldInfo;
+import org.apache.kerby.asn1.type.Asn1Integer;
+import org.apache.kerby.asn1.type.Asn1OctetString;
+import org.apache.kerby.asn1.type.Asn1SequenceType;
+
+/**
+ AuthorizationData       ::= SEQUENCE OF SEQUENCE {
+     ad-type         [0] Int32,
+     ad-data         [1] OCTET STRING
+ }
+ */
+public class AuthzDataEntry extends Asn1SequenceType {
+    static int AD_TYPE = 0;
+    static int AD_DATA = 1;
+
+    public AuthzDataEntry() {
+        super(new Asn1FieldInfo[] {
+                new Asn1FieldInfo(AD_TYPE, Asn1Integer.class),
+                new Asn1FieldInfo(AD_DATA, Asn1OctetString.class)
+        });
+    }
+
+    public int getAuthzType() {
+        Integer value = getFieldAsInteger(AD_TYPE);
+        return value;
+    }
+
+    public byte[] getAuthzData() {
+        return getFieldAsOctets(AD_DATA);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/TokenCache.java
----------------------------------------------------------------------
diff --git a/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/TokenCache.java b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/TokenCache.java
new file mode 100644
index 0000000..d737085
--- /dev/null
+++ b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/TokenCache.java
@@ -0,0 +1,82 @@
+/**
+ *  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.tool.token;
+
+import java.io.*;
+
+public class TokenCache {
+    private static final String DEFAULT_TOKEN_CACHE_PATH = ".tokenauth";
+    private static final String TOKEN_CACHE_FILE = ".tokenauth.token";
+
+    public static String readToken(String tokenCacheFile) {
+        File cacheFile = null;
+
+        if (tokenCacheFile != null && ! tokenCacheFile.isEmpty()) {
+            cacheFile = new File(tokenCacheFile);
+            if (!cacheFile.exists()) {
+                throw new RuntimeException("Invalid token cache specified: " + tokenCacheFile);
+            };
+        } else {
+            cacheFile = getDefaultTokenCache();
+            if (!cacheFile.exists()) {
+                throw new RuntimeException("No token cache available by default");
+            };
+        }
+
+        String token = null;
+        try {
+            BufferedReader reader = new BufferedReader(new FileReader(cacheFile));
+            String line = reader.readLine();
+            reader.close();
+            if (line != null) {
+                token = line;
+            }
+        } catch (IOException ex) {
+            //NOP
+        }
+
+        return token;
+    }
+
+    public static void writeToken(String token) {
+        File cacheFile = getDefaultTokenCache();
+
+        try {
+            Writer writer = new FileWriter(cacheFile);
+            writer.write(token.toString());
+            writer.close();
+            // sets read-write permissions to owner only
+            cacheFile.setReadable(false, false);
+            cacheFile.setReadable(true, true);
+            cacheFile.setWritable(true, true);
+        }
+        catch (IOException ioe) {
+            // if case of any error we just delete the cache, if user-only
+            // write permissions are not properly set a security exception
+            // is thrown and the file will be deleted.
+            cacheFile.delete();
+        }
+    }
+
+    public static File getDefaultTokenCache() {
+        String homeDir = System.getProperty("user.home", DEFAULT_TOKEN_CACHE_PATH);
+        return new File(homeDir, TOKEN_CACHE_FILE);
+    }
+}