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:03 UTC

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

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/TokenExtractor.java
----------------------------------------------------------------------
diff --git a/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/TokenExtractor.java b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/TokenExtractor.java
new file mode 100644
index 0000000..3b570b7
--- /dev/null
+++ b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/TokenExtractor.java
@@ -0,0 +1,102 @@
+/**
+ *  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 com.sun.security.jgss.AuthorizationDataEntry;
+import com.sun.security.jgss.ExtendedGSSContext;
+import com.sun.security.jgss.InquireType;
+import org.apache.kerby.asn1.type.Asn1SequenceOf;
+import org.apache.kerby.kerberos.kerb.spec.base.AuthToken;
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSException;
+
+import java.io.IOException;
+import java.util.List;
+
+public class TokenExtractor {
+    static final int JWT_AUTHZ_DATA_TYPE = 81;
+    public static final int AD_IF_RELEVANT_TYPE = 1;
+
+    /**
+     AuthorizationData       ::= SEQUENCE OF SEQUENCE {
+         ad-type         [0] Int32,
+         ad-data         [1] OCTET STRING
+     }
+     */
+    public static class AuthorizationData extends Asn1SequenceOf<AuthzDataEntry> {
+
+    }
+
+    public static AuthToken checkAuthzData(GSSContext context) throws GSSException, IOException {
+        System.out.println("Looking for token from authorization data in GSSContext");
+
+        Object authzData = null;
+        if (context instanceof ExtendedGSSContext) {
+            ExtendedGSSContext ex = (ExtendedGSSContext)context;
+            authzData = ex.inquireSecContext(
+                    InquireType.KRB5_GET_AUTHZ_DATA);
+        }
+
+        if (authzData != null) {
+            AuthorizationDataEntry[] authzEntries = (AuthorizationDataEntry[]) authzData;
+            AuthToken resultToken = null;
+            for (int i = 0; i < authzEntries.length; ++i) {
+                resultToken = getAuthzToken(authzEntries[i]);
+                if (resultToken != null) {
+                    return resultToken;
+                }
+            }
+        }
+        return null;
+    }
+
+    public static AuthToken getAuthzToken(AuthorizationDataEntry authzDataEntry) throws IOException {
+        if (authzDataEntry.getType() == AD_IF_RELEVANT_TYPE) {
+            String token = getToken(authzDataEntry);
+            if (token == null) {
+                return null;
+            }
+
+            try {
+                return TokenTool.fromJwtToken(token);
+            } catch (Exception e) {
+                // noop when not jwt token
+            }
+        }
+
+        return null;
+    }
+
+    public static String getToken(AuthorizationDataEntry authzDataEntry) throws IOException {
+        List<AuthzDataEntry> entries = decode(authzDataEntry);
+        for (AuthzDataEntry entry : entries) {
+            if (entry.getAuthzType() == JWT_AUTHZ_DATA_TYPE) {
+                return new String(entry.getAuthzData());
+            }
+        }
+        return null;
+    }
+
+    public static List<AuthzDataEntry> decode(AuthorizationDataEntry authzDataEntry) throws IOException {
+        AuthorizationData authzData = new AuthorizationData();
+        authzData.decode(authzDataEntry.getData());
+        return authzData.getElements();
+    }
+}

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/TokenTool.java
----------------------------------------------------------------------
diff --git a/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/TokenTool.java b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/TokenTool.java
new file mode 100644
index 0000000..0aea7e6
--- /dev/null
+++ b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/TokenTool.java
@@ -0,0 +1,125 @@
+/**
+ *  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 com.nimbusds.jose.PlainHeader;
+import com.nimbusds.jwt.JWT;
+import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.jwt.PlainJWT;
+import org.apache.kerby.kerberos.kerb.spec.base.AuthToken;
+
+import java.text.ParseException;
+import java.util.*;
+
+public class TokenTool {
+
+    public static JWT issueToken(String principal, String group, String role) {
+        // must have for kerb-token
+        String krbPrincipal = principal + "@SH.INTEL.COM";
+
+        PlainHeader header = new PlainHeader();
+        //header.setCustomParameter("krbPrincipal", krbPrincipal);
+
+        JWTClaimsSet jwtClaims = new JWTClaimsSet();
+
+        String iss = "token-service";
+        jwtClaims.setIssuer(iss);
+
+        String sub = principal;
+        jwtClaims.setSubject(sub);
+
+        // must have for kerb-token
+        jwtClaims.setSubject(krbPrincipal);
+
+        jwtClaims.setClaim("group", group);
+        if (role != null) {
+            jwtClaims.setClaim("role", role);
+        }
+
+        List<String> aud = new ArrayList<String>();
+        aud.add("krb5kdc-with-token-extension");
+        jwtClaims.setAudience(aud);
+
+        // Set expiration in 60 minutes
+        final Date NOW =  new Date(new Date().getTime() / 1000 * 1000);
+        Date exp = new Date(NOW.getTime() + 1000 * 60 * 60);
+        jwtClaims.setExpirationTime(exp);
+
+        Date nbf = NOW;
+        jwtClaims.setNotBeforeTime(nbf);
+
+        Date iat = NOW;
+        jwtClaims.setIssueTime(iat);
+
+        String jti = UUID.randomUUID().toString();
+        jwtClaims.setJWTID(jti);
+
+        PlainJWT jwt = new PlainJWT(header, jwtClaims);
+        return jwt;
+    }
+
+    public static JWT decodeToken(String token) throws ParseException {
+        PlainJWT jwt = PlainJWT.parse(token);
+
+        return jwt;
+    }
+
+    public static AuthToken fromJwtToken(String token) throws ParseException {
+        Map<String, Object> attrs = decodeAndExtractTokenAttributes(token);
+        return null;//new AuthToken(attrs);
+    }
+
+    public static Map<String, Object> decodeAndExtractTokenAttributes(String token) throws ParseException {
+        PlainJWT jwt = PlainJWT.parse(token);
+
+        Map<String, Object> attrs = new HashMap<String, Object>();
+        attrs.putAll(jwt.getJWTClaimsSet().getAllClaims());
+        //attrs.putAll(jwt.getHeader().getCustomParameters());
+
+        return attrs;
+    }
+
+    public static void main(String[] args) throws ParseException {
+        String principal, group, role = null;
+
+        if (args.length != 2 && args.length != 3) {
+            System.out.println("This is a simple token issuing tool just for kerb-token PoC usage\n");
+            System.out.println("tokeninit <username> <group> [role]\n");
+            System.exit(1);
+        }
+        principal = args[0];
+        group = args[1];
+        if (args.length > 2) {
+            role = args[2];
+        }
+
+        JWT jwt = issueToken(principal, group, role);
+        String token = jwt.serialize();
+
+        TokenCache.writeToken(token);
+        System.out.println("Issued token: " + token);
+
+        /*
+        JWT jwt2 = decodeToken(token);
+        String krbPrincipal = (String) jwt2.getHeader().getCustomParameter("krbPrincipal");
+        System.out.println("Decoded token with krbprincipal: " + krbPrincipal);
+        */
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-tool/kdc-tool/pom.xml
----------------------------------------------------------------------
diff --git a/kerby-tool/kdc-tool/pom.xml b/kerby-tool/kdc-tool/pom.xml
new file mode 100644
index 0000000..de1f5e7
--- /dev/null
+++ b/kerby-tool/kdc-tool/pom.xml
@@ -0,0 +1,75 @@
+<?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>server-tool</artifactId>
+    <name>Server Tool</name>
+    <description>Kerby KDC server 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-identity</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.kerby</groupId>
+        <artifactId>kerb-server</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+    </dependencies>
+
+    <profiles>
+      <profile>
+        <id>dist</id>
+        <build>
+          <plugins>
+            <plugin>
+              <groupId>org.apache.maven.plugins</groupId>
+              <artifactId>maven-assembly-plugin</artifactId>
+              <version>2.2</version>
+              <executions>
+                <execution>
+                  <id>package-all</id>
+                  <phase>package</phase>
+                  <goals>
+                    <goal>single</goal>
+                  </goals>
+                  <configuration>
+                    <descriptorRefs>
+                      <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                  </configuration>
+                </execution>
+              </executions>
+            </plugin>
+          </plugins>
+        </build>
+      </profile>
+    </profiles>
+
+</project>

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/kerby-tool/kdc-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/Kadmin.java
----------------------------------------------------------------------
diff --git a/kerby-tool/kdc-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/Kadmin.java b/kerby-tool/kdc-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/Kadmin.java
new file mode 100644
index 0000000..6e0c0f1
--- /dev/null
+++ b/kerby-tool/kdc-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/Kadmin.java
@@ -0,0 +1,139 @@
+/**
+ *  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/kerby-tool/kdc-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/executor/AddPrincipalExecutor.java
----------------------------------------------------------------------
diff --git a/kerby-tool/kdc-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/executor/AddPrincipalExecutor.java b/kerby-tool/kdc-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/executor/AddPrincipalExecutor.java
new file mode 100644
index 0000000..d67a16e
--- /dev/null
+++ b/kerby-tool/kdc-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/executor/AddPrincipalExecutor.java
@@ -0,0 +1,191 @@
+/**
+ *  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/kerby-tool/kdc-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/executor/KadminCommandExecutor.java
----------------------------------------------------------------------
diff --git a/kerby-tool/kdc-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/executor/KadminCommandExecutor.java b/kerby-tool/kdc-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/executor/KadminCommandExecutor.java
new file mode 100644
index 0000000..3c22bbd
--- /dev/null
+++ b/kerby-tool/kdc-tool/src/main/java/org/apache/kerby/kerberos/tool/kadmin/executor/KadminCommandExecutor.java
@@ -0,0 +1,28 @@
+/**
+ *  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-tool/pom.xml
----------------------------------------------------------------------
diff --git a/kerby-tool/pom.xml b/kerby-tool/pom.xml
new file mode 100644
index 0000000..107fbcd
--- /dev/null
+++ b/kerby-tool/pom.xml
@@ -0,0 +1,34 @@
+<?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-tool</artifactId>
+  <name>Kdc Tool Project</name>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <modules>
+    <module>client-tool</module>
+    <module>kdc-tool</module>
+  </modules>
+
+</project>

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/1f62f801/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 8bf88da..bc35da1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -41,9 +41,9 @@
     <module>kerby-asn1</module>
     <module>kerby-kerb</module>
     <module>kerby-kdc</module>
-    <module>kdc-tool</module>
+    <module>kerby-tool</module>
     <module>kerby-kdc-test</module>
-    <module>kdc-backend</module>
+    <module>kerby-backend</module>
     <module>kerby-dist</module>
     <module>benchmark</module>
     <module>kerby-provider</module>