Merge remote-tracking branch 'asf/trunk' into trunk
diff --git a/has-project/has-client/src/main/java/org/apache/kerby/has/client/HasAuthAdminClient.java b/has-project/has-client/src/main/java/org/apache/kerby/has/client/HasAuthAdminClient.java
index 1ce0c4d..e9a7dc9 100644
--- a/has-project/has-client/src/main/java/org/apache/kerby/has/client/HasAuthAdminClient.java
+++ b/has-project/has-client/src/main/java/org/apache/kerby/has/client/HasAuthAdminClient.java
@@ -87,7 +87,7 @@
             try {
                 conn = getHttpsConnection(url, true);
             } catch (Exception e) {
-                throw new RuntimeException("Error occurred when creating https connection.");
+                throw new RuntimeException("Error occurred when creating https connection. " + e.getMessage());
             }
         }
         if (method.equals("POST") || method.equals("PUT")) {
@@ -96,11 +96,11 @@
         return conn;
     }
 
-    private String getBaseURL() {
+    private String getKadminBaseURL() {
         String url = null;
         if (hasConfig.getHttpsPort() != null && hasConfig.getHttpsHost() != null) {
             url = "https://" + hasConfig.getHttpsHost() + ":" + hasConfig.getHttpsPort()
-                + "/has/v1/admin/";
+                + "/has/v1/kadmin/";
         }
         if (url == null) {
             throw new RuntimeException("Please set the https address and port.");
@@ -114,7 +114,7 @@
 
         URL url;
         try {
-            url = new URL(getBaseURL() + "addprincipal?principal=" + principal);
+            url = new URL(getKadminBaseURL() + "addprincipal?principal=" + principal);
         } catch (MalformedURLException e) {
             throw new KrbException("Failed to create a URL object.", e);
         }
@@ -150,7 +150,7 @@
 
         URL url;
         try {
-            url = new URL(getBaseURL() + "addprincipal?principal=" + principal
+            url = new URL(getKadminBaseURL() + "addprincipal?principal=" + principal
                 + "&password=" + password);
         } catch (MalformedURLException e) {
             throw new KrbException("Failed to create a URL object.", e);
@@ -191,7 +191,7 @@
 
         URL url;
         try {
-            url = new URL(getBaseURL() + "deleteprincipal?principal=" + principal);
+            url = new URL(getKadminBaseURL() + "deleteprincipal?principal=" + principal);
         } catch (MalformedURLException e) {
             throw new KrbException("Failed to create a URL object.", e);
         }
@@ -231,7 +231,7 @@
 
         URL url;
         try {
-            url = new URL(getBaseURL() + "renameprincipal?oldprincipal=" + oldPrincipal
+            url = new URL(getKadminBaseURL() + "renameprincipal?oldprincipal=" + oldPrincipal
                 + "&newprincipal=" + newPrincipal);
         } catch (MalformedURLException e) {
             throw new KrbException("Failed to create a URL object.", e);
@@ -267,7 +267,7 @@
 
         URL url;
         try {
-            url = new URL(getBaseURL() + "getprincipals");
+            url = new URL(getKadminBaseURL() + "listprincipals");
         } catch (MalformedURLException e) {
             throw new KrbException("Failed to create a URL object.", e);
         }
@@ -304,7 +304,7 @@
 
         URL url;
         try {
-            url = new URL(getBaseURL() + "getprincipals?exp=" + exp);
+            url = new URL(getKadminBaseURL() + "getprincipals?exp=" + exp);
         } catch (MalformedURLException e) {
             throw new KrbException("Failed to create a URL object. ", e);
         }
@@ -360,7 +360,7 @@
     public void exportKeytab(File keytab, String principal) throws KrbException {
         URL url;
         try {
-            url = new URL(getBaseURL() + "exportkeytab?principal=" + principal);
+            url = new URL(getKadminBaseURL() + "exportkeytab?principal=" + principal);
         } catch (MalformedURLException e) {
             LOG.error("Failed to create a URL object." + e.getMessage());
             throw new KrbException("Failed to create a URL object.", e);
@@ -399,7 +399,7 @@
     public void exportKeytab(File keytabFile, List<String> principals) throws KrbException {
         HttpURLConnection httpConn;
         for (String principal : principals) {
-            String request = getBaseURL() + "exportkeytab?principal=" + principal;
+            String request = getKadminBaseURL() + "exportkeytab?principal=" + principal;
             URL url;
             try {
                 url = new URL(request);
diff --git a/has-project/has-client/src/main/java/org/apache/kerby/has/client/HasClient.java b/has-project/has-client/src/main/java/org/apache/kerby/has/client/HasClient.java
index e94ae5d..be0e804 100755
--- a/has-project/has-client/src/main/java/org/apache/kerby/has/client/HasClient.java
+++ b/has-project/has-client/src/main/java/org/apache/kerby/has/client/HasClient.java
@@ -121,7 +121,7 @@
                 config = HasUtil.getHasConfig(confFile);
             } catch (HasException e) {
                 LOG.error("Failed to get has client config: " + e.getMessage());
-                throw new HasException("Failed to get has client config: " + e);
+                throw new HasException("Failed to get has client config: " + e.getMessage());
             }
         } else {
             config = new HasConfig();
diff --git a/has-project/has-common/src/main/java/org/apache/kerby/has/common/util/HasUtil.java b/has-project/has-common/src/main/java/org/apache/kerby/has/common/util/HasUtil.java
index 19cbaea..6b01058 100644
--- a/has-project/has-common/src/main/java/org/apache/kerby/has/common/util/HasUtil.java
+++ b/has-project/has-common/src/main/java/org/apache/kerby/has/common/util/HasUtil.java
@@ -50,9 +50,10 @@
                     + hasConfFile.getAbsolutePath());
             }
             return hasConfig;
+        } else {
+            throw new HasException(hasConfFile.getName() + "not found in "
+                + hasConfFile.getParent() + ". ");
         }
-
-        return null;
     }
 
     public static void setEnableConf(File hasConfFile, String value)
diff --git a/has-project/has-server/src/main/java/org/apache/kerby/has/server/HasServer.java b/has-project/has-server/src/main/java/org/apache/kerby/has/server/HasServer.java
index 17cb8b4..121c7ca 100644
--- a/has-project/has-server/src/main/java/org/apache/kerby/has/server/HasServer.java
+++ b/has-project/has-server/src/main/java/org/apache/kerby/has/server/HasServer.java
@@ -143,6 +143,9 @@
 
     public File initKdcServer() throws KrbException {
         File adminKeytabFile = new File(workDir, "admin.keytab");
+        if (kdcServer == null) {
+            throw new KrbException("Please start KDC server first.");
+        }
         LocalKadmin kadmin = new LocalKadminImpl(kdcServer.getKdcSetting(),
             kdcServer.getIdentityService());
         if (adminKeytabFile.exists()) {
@@ -220,54 +223,50 @@
             // Parse has-server.conf to get http_host and http_port
             File confFile = new File(confDir, "has-server.conf");
             hasConfig = HasUtil.getHasConfig(confFile);
-            if (hasConfig != null) {
-                try {
-                    String httpHost;
-                    String httpPort;
-                    String httpsHost;
-                    String httpsPort;
-                    if (hasConfig.getHttpHost() != null) {
-                        httpHost = hasConfig.getHttpHost();
-                    } else {
-                        LOG.info("Cannot get the http_host from has-server.conf, using the default http host.");
-                        httpHost = WebConfigKey.HAS_HTTP_HOST_DEFAULT;
-                    }
-                    if (hasConfig.getHttpPort() != null) {
-                        httpPort = hasConfig.getHttpPort();
-                    } else {
-                        LOG.info("Cannot get the http_port from has-server.conf, using the default http port.");
-                        httpPort = String.valueOf(WebConfigKey.HAS_HTTP_PORT_DEFAULT);
-                    }
-                    if (hasConfig.getHttpsHost() != null) {
-                        httpsHost = hasConfig.getHttpsHost();
-                    } else {
-                        LOG.info("Cannot get the https_host from has-server.conf, using the default https host.");
-                        httpsHost = WebConfigKey.HAS_HTTPS_HOST_DEFAULT;
-                    }
-                    if (hasConfig.getHttpsPort() != null) {
-                        httpsPort = hasConfig.getHttpsPort();
-                    } else {
-                        LOG.info("Cannot get the https_port from has-server.conf , using the default https port.");
-                        httpsPort = String.valueOf(WebConfigKey.HAS_HTTPS_PORT_DEFAULT);
-                    }
-                    String hasHttpAddress = httpHost + ":" + httpPort;
-                    String hasHttpsAddress = httpsHost + ":" + httpsPort;
-                    LOG.info("The web server http address: " + hasHttpAddress);
-                    LOG.info("The web server https address: " + hasHttpsAddress);
-
-                    conf.setString(WebConfigKey.HAS_HTTP_ADDRESS_KEY, hasHttpAddress);
-                    conf.setString(WebConfigKey.HAS_HTTPS_ADDRESS_KEY, hasHttpsAddress);
-                    conf.setString(WebConfigKey.HAS_HTTP_POLICY_KEY,
-                        HttpConfig.Policy.HTTP_AND_HTTPS.name());
-                    conf.setString(WebConfigKey.HAS_SERVER_HTTPS_KEYSTORE_RESOURCE_KEY,
-                        hasConfig.getSslServerConf());
-                    webServer = new WebServer(conf);
-                } catch (NumberFormatException e) {
-                    throw new IllegalArgumentException("https_port should be a number. "
-                        + e.getMessage());
+            try {
+                String httpHost;
+                String httpPort;
+                String httpsHost;
+                String httpsPort;
+                if (hasConfig.getHttpHost() != null) {
+                    httpHost = hasConfig.getHttpHost();
+                } else {
+                    LOG.info("Cannot get the http_host from has-server.conf, using the default http host.");
+                    httpHost = WebConfigKey.HAS_HTTP_HOST_DEFAULT;
                 }
-            } else {
-                throw new HasException("has-server.conf not found in " + confDir + ". ");
+                if (hasConfig.getHttpPort() != null) {
+                    httpPort = hasConfig.getHttpPort();
+                } else {
+                    LOG.info("Cannot get the http_port from has-server.conf, using the default http port.");
+                    httpPort = String.valueOf(WebConfigKey.HAS_HTTP_PORT_DEFAULT);
+                }
+                if (hasConfig.getHttpsHost() != null) {
+                    httpsHost = hasConfig.getHttpsHost();
+                } else {
+                    LOG.info("Cannot get the https_host from has-server.conf, using the default https host.");
+                    httpsHost = WebConfigKey.HAS_HTTPS_HOST_DEFAULT;
+                }
+                if (hasConfig.getHttpsPort() != null) {
+                    httpsPort = hasConfig.getHttpsPort();
+                } else {
+                    LOG.info("Cannot get the https_port from has-server.conf , using the default https port.");
+                    httpsPort = String.valueOf(WebConfigKey.HAS_HTTPS_PORT_DEFAULT);
+                }
+                String hasHttpAddress = httpHost + ":" + httpPort;
+                String hasHttpsAddress = httpsHost + ":" + httpsPort;
+                LOG.info("The web server http address: " + hasHttpAddress);
+                LOG.info("The web server https address: " + hasHttpsAddress);
+
+                conf.setString(WebConfigKey.HAS_HTTP_ADDRESS_KEY, hasHttpAddress);
+                conf.setString(WebConfigKey.HAS_HTTPS_ADDRESS_KEY, hasHttpsAddress);
+                conf.setString(WebConfigKey.HAS_HTTP_POLICY_KEY,
+                    HttpConfig.Policy.HTTP_AND_HTTPS.name());
+                conf.setString(WebConfigKey.HAS_SERVER_HTTPS_KEYSTORE_RESOURCE_KEY,
+                    hasConfig.getSslServerConf());
+                webServer = new WebServer(conf);
+            } catch (NumberFormatException e) {
+                throw new IllegalArgumentException("https_port should be a number. "
+                    + e.getMessage());
             }
         } else {
             hasConfig = webServer.getConf();
diff --git a/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/WebServer.java b/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/WebServer.java
index abf3a9a..1b1f9e6 100644
--- a/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/WebServer.java
+++ b/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/WebServer.java
@@ -81,9 +81,10 @@
 
             Map<String, String> params = getAuthFilterParams(conf);
 
-            String adminPathSpec = "/has/v1/admin/*";
+            String kadminPathSpec = "/has/v1/kadmin/*";
+            String hadminPathSpec = "/has/v1/hadmin/*";
             HttpServer2.defineFilter(httpServer.getWebAppContext(), name, className,
-                params, new String[]{adminPathSpec});
+                params, new String[]{kadminPathSpec, hadminPathSpec});
             HttpServer2.LOG.info("Added filter '" + name + "' (class=" + className
                 + ")");
         }
diff --git a/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/rest/KadminApi.java b/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/rest/KadminApi.java
index 61c9a25..10ff6c8 100644
--- a/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/rest/KadminApi.java
+++ b/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/rest/KadminApi.java
@@ -25,7 +25,6 @@
 import org.apache.kerby.kerberos.kerb.admin.kadmin.local.LocalKadminImpl;
 import org.apache.kerby.kerberos.kerb.server.KdcSetting;
 import org.codehaus.jettison.json.JSONArray;
-import org.codehaus.jettison.json.JSONObject;
 
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
@@ -98,12 +97,11 @@
     }
 
     @GET
-    @Path("/getprincipals")
+    @Path("/listprincipals")
     @Produces(MediaType.APPLICATION_JSON)
-    public Response getprincipals(@QueryParam("exp") String exp) {
+    public Response listPrincipals(@QueryParam("exp") String exp) {
         if (httpRequest.isSecure()) {
             WebServer.LOG.info("Request to get principals.");
-            JSONObject result = new JSONObject();
             String msg;
             LocalKadminImpl localKadmin;
             HasServer hasServer = WebServer.getHasServerFromContext(context);
@@ -122,9 +120,7 @@
                     principals.put(princ);
                 }
                 WebServer.LOG.info("Success to get principals with JSON.");
-                result.put("result", "success");
-                result.put("msg", principals.toString());
-                return Response.ok(result.toString()).build();
+                return Response.ok(principals.toString()).build();
             } catch (Exception e) {
                 msg = "Failed to get principals,because : " + e.getMessage();
                 WebServer.LOG.error(msg);
@@ -144,7 +140,7 @@
     @POST
     @Path("/addprincipal")
     @Produces(MediaType.TEXT_PLAIN)
-    public Response addprincipal(@QueryParam(PrincipalParam.NAME) @DefaultValue(PrincipalParam.DEFAULT)
+    public Response addPrincipal(@QueryParam(PrincipalParam.NAME) @DefaultValue(PrincipalParam.DEFAULT)
                                  final PrincipalParam principal,
                                  @QueryParam(PasswordParam.NAME) @DefaultValue(PasswordParam.DEFAULT)
                                  final PasswordParam password) {
@@ -161,14 +157,31 @@
                 WebServer.LOG.error(msg);
                 return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
             }
-            try {
-                localKadmin.addPrincipal(principal.getValue(), password.getValue());
-                msg = "Add principal successfully.";
-                return Response.ok(msg).build();
-            } catch (Exception e) {
-                msg = "Failed to add " + principal + " principal, because: " + e.getMessage();
+            if (principal.getValue() == null) {
+                msg = "Value of principal is null.";
                 WebServer.LOG.error(msg);
-                return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
+                return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
+            }
+            if (password.getValue() == null || password.getValue().equals("")) {
+                try {
+                    localKadmin.addPrincipal(principal.getValue());
+                    msg = "Add principal successfully.";
+                    return Response.ok(msg).build();
+                } catch (KrbException e) {
+                    msg = "Failed to add " + principal + " principal, because: " + e.getMessage();
+                    WebServer.LOG.error(msg);
+                    return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
+                }
+            } else {
+                try {
+                    localKadmin.addPrincipal(principal.getValue(), password.getValue());
+                    msg = "Add principal successfully.";
+                    return Response.ok(msg).build();
+                } catch (KrbException e) {
+                    msg = "Failed to add " + principal + " principal, because: " + e.getMessage();
+                    WebServer.LOG.error(msg);
+                    return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
+                }
             }
         }
         return Response.status(Response.Status.FORBIDDEN).entity("HTTPS required.\n").build();
@@ -222,7 +235,7 @@
     @DELETE
     @Path("/deleteprincipal")
     @Produces(MediaType.TEXT_PLAIN)
-    public Response deleteprincipal(@QueryParam(PrincipalParam.NAME) @DefaultValue(PrincipalParam.DEFAULT)
+    public Response deletePrincipal(@QueryParam(PrincipalParam.NAME) @DefaultValue(PrincipalParam.DEFAULT)
                                     final PrincipalParam principal) {
         if (httpRequest.isSecure()) {
             WebServer.LOG.info("Request to delete the principal named " + principal.getValue());
diff --git a/kerby-dist/has-dist/bin/admin-remote.sh b/kerby-dist/has-dist/bin/admin-remote.sh
new file mode 100644
index 0000000..6aebc81
--- /dev/null
+++ b/kerby-dist/has-dist/bin/admin-remote.sh
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+
+# 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.
+
+CONF_DIR=$1
+APP_MAIN=org.apache.kerby.kerberos.tool.admin.AdminRemoteTool
+
+# Reset HAS_CONF_DIR if CONF_DIR not null
+if [ "$CONF_DIR" != "" ]; then
+  if [ ! -d "$CONF_DIR" ]; then
+    echo "[ERROR] ${CONF_DIR} is not a directory"
+    usage
+  fi
+else
+  if [ "$HAS_CONF_DIR" != "" ] && [ -d "$HAS_CONF_DIR" ]; then
+    CONF_DIR=${HAS_CONF_DIR}
+  else
+    echo "[ERROR] HAS_CONF_DIR is null or not a directory"
+    exit
+  fi
+fi
+
+# Load HAS environment variables
+if [ -f "${CONF_DIR}/has-env.sh" ]; then
+  . "${CONF_DIR}/has-env.sh"
+fi
+
+# Get HAS_HOME directory
+bin=`dirname "$0"`
+HAS_HOME=`cd ${bin}/..; pwd`
+cd ${HAS_HOME}
+
+for var in $*; do
+  if [ X"$var" = X"-D" ]; then
+    DEBUG="-Xdebug -Xrunjdwp:transport=dt_socket,address=8012,server=y,suspend=y"
+  fi
+done
+
+echo "[INFO] conf_dir=$CONF_DIR"
+HAS_OPTS="-DHAS_LOGFILE=admin-remote"
+
+java ${DEBUG} -classpath target/lib/*:. ${HAS_OPTS} ${APP_MAIN} ${CONF_DIR}
diff --git a/kerby-dist/has-dist/bin/has-init.sh b/kerby-dist/has-dist/bin/has-init.sh
index 2bbbf6a..176b4d6 100644
--- a/kerby-dist/has-dist/bin/has-init.sh
+++ b/kerby-dist/has-dist/bin/has-init.sh
@@ -17,7 +17,7 @@
 # limitations under the License.
 
 CONF_DIR=$1
-APP_MAIN=org.apache.kerby.kerberos.tool.HasInitTool
+APP_MAIN=org.apache.kerby.kerberos.tool.init.HasInitTool
 
 # Reset HAS_CONF_DIR if CONF_DIR not null
 if [ "$CONF_DIR" != "" ]; then
@@ -51,6 +51,6 @@
 done
 
 echo "[INFO] conf_dir=$CONF_DIR"
-HAS_OPTS="-DHAS_LOGFILE=kdcinit"
+HAS_OPTS="-DHAS_LOGFILE=has-init"
 
 java ${DEBUG} -classpath target/lib/*:. ${HAS_OPTS} ${APP_MAIN} ${CONF_DIR}
diff --git a/kerby-dist/has-dist/conf/hadmin.conf b/kerby-dist/has-dist/conf/admin.conf
similarity index 82%
rename from kerby-dist/has-dist/conf/hadmin.conf
rename to kerby-dist/has-dist/conf/admin.conf
index 125bdfc..e950aea 100644
--- a/kerby-dist/has-dist/conf/hadmin.conf
+++ b/kerby-dist/has-dist/conf/admin.conf
@@ -1,5 +1,5 @@
 [HAS]
-    https_host = hostname
+    https_host = plusplus-desktop
     https_port = 8092
     admin_keytab = /etc/has/admin.keytab
     admin_keytab_principal = kadmin/HADOOP.COM@HADOOP.COM
diff --git a/kerby-dist/has-dist/conf/has-server.conf b/kerby-dist/has-dist/conf/has-server.conf
index 93accaf..43a83fb 100644
--- a/kerby-dist/has-dist/conf/has-server.conf
+++ b/kerby-dist/has-dist/conf/has-server.conf
@@ -20,5 +20,5 @@
   https_host = plusplus-desktop
   https_port = 8092
   filter_auth_type = kerberos
-  enable_conf = false
+  enable_conf = true
 
diff --git a/kerby-dist/has-dist/conf/kdc.conf b/kerby-dist/has-dist/conf/kdc.conf
index 21ccdd1..a2132ac 100644
--- a/kerby-dist/has-dist/conf/kdc.conf
+++ b/kerby-dist/has-dist/conf/kdc.conf
@@ -17,7 +17,7 @@
 #
 
 [kdcdefaults]
-  kdc_host = hostname
+  kdc_host = plusplus-desktop
   kdc_udp_port = 88
   kdc_tcp_port = 88
   kdc_realm = HADOOP.COM
diff --git a/kerby-dist/has-dist/conf/krb5.conf b/kerby-dist/has-dist/conf/krb5.conf
index 55ae355..6c64cf5 100644
--- a/kerby-dist/has-dist/conf/krb5.conf
+++ b/kerby-dist/has-dist/conf/krb5.conf
@@ -25,5 +25,5 @@
     ticket_lifetime = 60
 [realms]
     HADOOP.COM = {
-        kdc = hostname:88
+        kdc = plusplus-desktop:88
     }
diff --git a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/AdminRemoteTool.java b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/AdminRemoteTool.java
new file mode 100644
index 0000000..fc2356c
--- /dev/null
+++ b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/AdminRemoteTool.java
@@ -0,0 +1,132 @@
+/**
+ *  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.admin;
+
+import org.apache.kerby.has.client.HasAuthAdminClient;
+import org.apache.kerby.has.common.HasConfig;
+import org.apache.kerby.has.common.HasException;
+import org.apache.kerby.has.common.util.HasUtil;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.tool.admin.cmd.AddPrincipalRemoteCmd;
+import org.apache.kerby.kerberos.tool.admin.cmd.AdminRemoteCmd;
+import org.apache.kerby.kerberos.tool.admin.cmd.DeletePrincipalRemoteCmd;
+import org.apache.kerby.kerberos.tool.admin.cmd.ListPrincipalsRemoteCmd;
+import org.apache.kerby.kerberos.tool.admin.cmd.RenamePrincipalRemoteCmd;
+import org.apache.kerby.util.OSUtil;
+
+import java.io.File;
+import java.util.Scanner;
+
+public class AdminRemoteTool {
+
+    private static final String PROMPT = "admin.remote";
+    private static final String USAGE = (OSUtil.isWindows()
+        ? "Usage: bin\\admin-remote.cmd" : "Usage: sh bin/admin-remote.sh")
+        + " <conf-file>\n"
+        + "\tExample:\n"
+        + "\t\t"
+        + (OSUtil.isWindows()
+        ? "bin\\admin-remote.cmd" : "sh bin/admin-remote.sh")
+        + " conf\n";
+
+    private static final String LEGAL_COMMANDS = "Available commands are: "
+        + "\n"
+        + "add_principal, addprinc\n"
+        + "                         Add principal\n"
+        + "delete_principal, delprinc\n"
+        + "                         Delete principal\n"
+        + "rename_principal, renprinc\n"
+        + "                         Rename principal\n"
+        + "list_principals, listprincs\n"
+        + "                         List principals\n";
+
+    public static void main(String[] args) {
+
+        HasAuthAdminClient authHasAdminClient = null;
+
+        if (args.length < 1) {
+            System.err.println(USAGE);
+            System.exit(1);
+        }
+
+        String confDirPath = args[0];
+        File confFile = new File(confDirPath, "admin.conf");
+        HasConfig hasConfig;
+        try {
+            hasConfig = HasUtil.getHasConfig(confFile);
+        } catch (HasException e) {
+            System.err.println(e.getMessage());
+            return;
+        }
+
+        if (hasConfig.getFilterAuthType().equals("kerberos")) {
+            authHasAdminClient = new HasAuthAdminClient(hasConfig);
+        }
+
+        System.out.println("enter \"cmd\" to see legal commands.");
+        System.out.print(PROMPT + ": ");
+
+        try (Scanner scanner = new Scanner(System.in, "UTF-8")) {
+            String input = scanner.nextLine();
+
+            while (!(input.equals("quit") || input.equals("exit") || input.equals("q"))) {
+                try {
+                    execute(authHasAdminClient, input);
+                } catch (KrbException e) {
+                    System.err.println(e.getMessage());
+                }
+                System.out.print(PROMPT + ": ");
+                input = scanner.nextLine();
+            }
+        }
+    }
+
+    private static void execute(HasAuthAdminClient hasAuthAdminClient,
+                               String input) throws KrbException {
+        input = input.trim();
+        if (input.startsWith("cmd")) {
+            System.out.println(LEGAL_COMMANDS);
+            return;
+        }
+        AdminRemoteCmd executor;
+
+        String[] items = input.split("\\s+");
+        String cmd = items[0];
+
+        if (cmd.equals("add_principal")
+            || cmd.equals("addprinc")) {
+            executor = new AddPrincipalRemoteCmd(hasAuthAdminClient);
+        } else if (cmd.equals("delete_principal")
+            || cmd.equals("delprinc")) {
+            executor = new DeletePrincipalRemoteCmd(hasAuthAdminClient);
+        } else if (cmd.equals("rename_principal")
+            || cmd.equals("renprinc")) {
+            executor = new RenamePrincipalRemoteCmd(hasAuthAdminClient);
+        } else if (cmd.equals("list_principals")
+            || cmd.equals("listprincs")) {
+            executor = new ListPrincipalsRemoteCmd(hasAuthAdminClient);
+        } else {
+            System.out.println(LEGAL_COMMANDS);
+            return;
+        }
+        executor.execute(items);
+    }
+
+}
diff --git a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/cmd/AddPrincipalRemoteCmd.java b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/cmd/AddPrincipalRemoteCmd.java
new file mode 100644
index 0000000..6cbe325
--- /dev/null
+++ b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/cmd/AddPrincipalRemoteCmd.java
@@ -0,0 +1,65 @@
+/**
+ *  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.admin.cmd;
+
+import org.apache.kerby.has.client.HasAuthAdminClient;
+import org.apache.kerby.kerberos.kerb.KrbException;
+
+/**
+ * Remote add principal cmd
+ */
+public class AddPrincipalRemoteCmd extends AdminRemoteCmd {
+
+    public static final String USAGE = "Usage: add_principal [options] <principal-name>\n"
+        + "\toptions are:\n"
+        + "\t\t[-randkey]\n"
+        + "\t\t[-pw password]"
+        + "\tExample:\n"
+        + "\t\tadd_principal -pw mypassword alice\n";
+
+    public AddPrincipalRemoteCmd(HasAuthAdminClient authHadmin) {
+        super(authHadmin);
+    }
+
+    @Override
+    public void execute(String[] items) throws KrbException {
+        if (items.length < 2) {
+            System.err.println(USAGE);
+            return;
+        }
+
+        String clientPrincipal = items[items.length - 1];
+
+        HasAuthAdminClient client = getAuthAdminClient();
+
+
+        if (!items[1].startsWith("-")) {
+            client.addPrincipal(clientPrincipal);
+        } else if (items[1].startsWith("-randkey")) {
+            client.addPrincipal(clientPrincipal);
+        } else if (items[1].startsWith("-pw")) {
+            String password = items[2];
+            client.addPrincipal(clientPrincipal, password);
+        } else {
+            System.err.println("add_principal cmd format error.");
+            System.err.println(USAGE);
+        }
+    }
+}
diff --git a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/cmd/InitCmd.java b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/cmd/AdminRemoteCmd.java
similarity index 73%
copy from kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/cmd/InitCmd.java
copy to kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/cmd/AdminRemoteCmd.java
index c03d5bd..b5ccee4 100644
--- a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/cmd/InitCmd.java
+++ b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/cmd/AdminRemoteCmd.java
@@ -17,25 +17,25 @@
  *  under the License.
  *
  */
-package org.apache.kerby.kerberos.tool.cmd;
+package org.apache.kerby.kerberos.tool.admin.cmd;
 
-import org.apache.kerby.has.client.HasInitClient;
+import org.apache.kerby.has.client.HasAuthAdminClient;
 import org.apache.kerby.kerberos.kerb.KrbException;
 
-public abstract class InitCmd {
+public abstract class AdminRemoteCmd {
 
-    private HasInitClient client;
+    private HasAuthAdminClient client;
 
-    public InitCmd(HasInitClient client) {
-        this.client = client;
+    public AdminRemoteCmd(HasAuthAdminClient authHadminClient) {
+        this.client = authHadminClient;
     }
 
-    protected HasInitClient getClient() {
+    protected HasAuthAdminClient getAuthAdminClient() {
         return client;
     }
 
     /**
-     * Execute the kdc init cmd.
+     * Execute the admin cmd.
      * @param input Input cmd to execute
      */
     public abstract void execute(String[] input) throws KrbException;
diff --git a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/cmd/DeletePrincipalRemoteCmd.java b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/cmd/DeletePrincipalRemoteCmd.java
new file mode 100644
index 0000000..fee5b0d
--- /dev/null
+++ b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/cmd/DeletePrincipalRemoteCmd.java
@@ -0,0 +1,83 @@
+/**
+ *  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.admin.cmd;
+
+import org.apache.kerby.has.client.HasAuthAdminClient;
+import org.apache.kerby.kerberos.kerb.KrbException;
+
+import java.io.Console;
+import java.util.Scanner;
+
+/**
+ * Remote delete principal cmd
+ */
+public class DeletePrincipalRemoteCmd extends AdminRemoteCmd {
+
+    public static final String USAGE = "Usage: delete_principal <principal-name>\n"
+        + "\tExample:\n"
+        + "\t\tdelete_principal alice\n";
+
+    public DeletePrincipalRemoteCmd(HasAuthAdminClient authHadmin) {
+        super(authHadmin);
+    }
+
+    @Override
+    public void execute(String[] items) throws KrbException {
+        if (items.length < 2) {
+            System.err.println(USAGE);
+            return;
+        }
+
+        HasAuthAdminClient client = getAuthAdminClient();
+
+        String principal = items[items.length - 1];
+        String reply;
+        Console console = System.console();
+        String prompt = "Are you sure to delete the principal? (yes/no, YES/NO, y/n, Y/N) ";
+        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, "UTF-8");
+            reply = getReply(scanner, prompt);
+        } else {
+            reply = getReply(console, prompt);
+        }
+        if (reply.equals("yes") || reply.equals("YES") || reply.equals("y") || reply.equals("Y")) {
+            client.deletePrincipal(principal);
+        } else if (reply.equals("no") || reply.equals("NO") || reply.equals("n") || reply.equals("N")) {
+            System.out.println("Principal \"" + principal + "\"  not deleted.");
+        } else {
+            System.err.println("Unknown request, fail to delete the principal.");
+            System.err.println(USAGE);
+        }
+    }
+
+    private String getReply(Scanner scanner, String prompt) {
+        System.out.println(prompt);
+        return scanner.nextLine().trim();
+    }
+
+    private String getReply(Console console, String prompt) {
+        console.printf(prompt);
+        String line = console.readLine();
+        return line;
+    }
+}
diff --git a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/cmd/ListPrincipalsRemoteCmd.java b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/cmd/ListPrincipalsRemoteCmd.java
new file mode 100644
index 0000000..b46f95c
--- /dev/null
+++ b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/cmd/ListPrincipalsRemoteCmd.java
@@ -0,0 +1,70 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.kerby.kerberos.tool.admin.cmd;
+
+import org.apache.kerby.has.client.HasAuthAdminClient;
+import org.apache.kerby.kerberos.kerb.KrbException;
+
+import java.util.List;
+
+public class ListPrincipalsRemoteCmd extends AdminRemoteCmd {
+    private static final String USAGE = "Usage: list_principals [expression]\n"
+            + "\t'expression' is a shell-style glob expression that can contain the wild-card characters ?, *, and []."
+            + "\tExample:\n"
+            + "\t\tlist_principals [expression]\n";
+
+    public ListPrincipalsRemoteCmd(HasAuthAdminClient authHadmin) {
+        super(authHadmin);
+    }
+
+    @Override
+    public void execute(String[] items) throws KrbException {
+        if (items.length > 2) {
+            System.err.println(USAGE);
+            return;
+        }
+
+        HasAuthAdminClient client = getAuthAdminClient();
+
+        List<String> principalLists = null;
+
+        if (items.length == 1) {
+            try {
+                principalLists = client.getPrincipals();
+            } catch (Exception e) {
+                System.err.println("Errors occurred when getting the principals. " + e.getMessage());
+            }
+        } else {
+            //have expression
+            String exp = items[1];
+            principalLists = client.getPrincipals(exp);
+        }
+
+        if (principalLists.size() == 0 || principalLists.size() == 1 && principalLists.get(0).isEmpty()) {
+            return;
+        } else {
+            System.out.println("Principals are listed:");
+            for (int i = 0; i < principalLists.size(); i++) {
+                System.out.println(principalLists.get(i));
+            }
+        }
+    }
+
+}
diff --git a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/cmd/RenamePrincipalRemoteCmd.java b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/cmd/RenamePrincipalRemoteCmd.java
new file mode 100644
index 0000000..0be563e
--- /dev/null
+++ b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/cmd/RenamePrincipalRemoteCmd.java
@@ -0,0 +1,85 @@
+/**
+ *  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.admin.cmd;
+
+import org.apache.kerby.has.client.HasAuthAdminClient;
+import org.apache.kerby.kerberos.kerb.KrbException;
+
+import java.io.Console;
+import java.util.Scanner;
+
+/**
+ * Remote rename principal cmd
+ */
+public class RenamePrincipalRemoteCmd extends AdminRemoteCmd {
+    public static final String USAGE = "Usage: rename_principal <old_principal_name>"
+        + " <new_principal_name>\n"
+        + "\tExample:\n"
+        + "\t\trename_principal alice bob\n";
+
+    public RenamePrincipalRemoteCmd(HasAuthAdminClient client) {
+        super(client);
+    }
+
+    @Override
+    public void execute(String[] items) throws KrbException {
+        if (items.length < 3) {
+            System.err.println(USAGE);
+            return;
+        }
+
+        HasAuthAdminClient client = getAuthAdminClient();
+
+        String oldPrincipalName = items[items.length - 2];
+        String newPrincipalName = items[items.length - 1];
+
+        String reply;
+        Console console = System.console();
+        String prompt = "Are you sure to rename the principal? (yes/no, YES/NO, y/n, Y/N) ";
+        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, "UTF-8");
+            reply = getReply(scanner, prompt);
+        } else {
+            reply = getReply(console, prompt);
+        }
+        if (reply.equals("yes") || reply.equals("YES") || reply.equals("y") || reply.equals("Y")) {
+            client.renamePrincipal(oldPrincipalName, newPrincipalName);
+        } else if (reply.equals("no") || reply.equals("NO") || reply.equals("n") || reply.equals("N")) {
+            System.out.println("Principal \"" + oldPrincipalName + "\"  not renamed.");
+        } else {
+            System.err.println("Unknown request, fail to rename the principal.");
+            System.err.println(USAGE);
+        }
+    }
+
+    private String getReply(Scanner scanner, String prompt) {
+        System.out.println(prompt);
+        return scanner.nextLine().trim();
+    }
+
+    private String getReply(Console console, String prompt) {
+        console.printf(prompt);
+        String line = console.readLine();
+        return line;
+    }
+}
diff --git a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/HasInitTool.java b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/init/HasInitTool.java
similarity index 92%
rename from kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/HasInitTool.java
rename to kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/init/HasInitTool.java
index b94b618..977d16d 100644
--- a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/HasInitTool.java
+++ b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/init/HasInitTool.java
@@ -17,16 +17,16 @@
  *  under the License.
  *
  */
-package org.apache.kerby.kerberos.tool;
+package org.apache.kerby.kerberos.tool.init;
 
 import org.apache.kerby.has.client.HasInitClient;
 import org.apache.kerby.has.common.HasConfig;
 import org.apache.kerby.has.common.HasException;
 import org.apache.kerby.has.common.util.HasUtil;
 import org.apache.kerby.kerberos.kerb.KrbException;
-import org.apache.kerby.kerberos.tool.cmd.InitCmd;
-import org.apache.kerby.kerberos.tool.cmd.InitKdcCmd;
-import org.apache.kerby.kerberos.tool.cmd.StartKdcCmd;
+import org.apache.kerby.kerberos.tool.init.cmd.InitCmd;
+import org.apache.kerby.kerberos.tool.init.cmd.InitKdcCmd;
+import org.apache.kerby.kerberos.tool.init.cmd.StartKdcCmd;
 import org.apache.kerby.util.OSUtil;
 
 import java.io.File;
@@ -56,7 +56,7 @@
             System.exit(1);
         }
         String confDirPath = args[0];
-        File confFile = new File(confDirPath, "hadmin.conf");
+        File confFile = new File(confDirPath, "admin.conf");
         HasConfig hasConfig;
         try {
             hasConfig = HasUtil.getHasConfig(confFile);
diff --git a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/cmd/InitCmd.java b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/init/cmd/InitCmd.java
similarity index 96%
rename from kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/cmd/InitCmd.java
rename to kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/init/cmd/InitCmd.java
index c03d5bd..63446d7 100644
--- a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/cmd/InitCmd.java
+++ b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/init/cmd/InitCmd.java
@@ -17,7 +17,7 @@
  *  under the License.
  *
  */
-package org.apache.kerby.kerberos.tool.cmd;
+package org.apache.kerby.kerberos.tool.init.cmd;
 
 import org.apache.kerby.has.client.HasInitClient;
 import org.apache.kerby.kerberos.kerb.KrbException;
diff --git a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/cmd/InitKdcCmd.java b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/init/cmd/InitKdcCmd.java
similarity index 96%
rename from kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/cmd/InitKdcCmd.java
rename to kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/init/cmd/InitKdcCmd.java
index 7f13073..d9ad062 100644
--- a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/cmd/InitKdcCmd.java
+++ b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/init/cmd/InitKdcCmd.java
@@ -17,7 +17,7 @@
  *  under the License.
  *
  */
-package org.apache.kerby.kerberos.tool.cmd;
+package org.apache.kerby.kerberos.tool.init.cmd;
 
 import org.apache.kerby.has.client.HasInitClient;
 import org.apache.kerby.kerberos.kerb.KrbException;
@@ -61,7 +61,6 @@
         InputStream content = client.initKdc();
 
         if (content == null) {
-            System.err.println("Failed to init kdc.");
             return;
         }
 
diff --git a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/cmd/StartKdcCmd.java b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/init/cmd/StartKdcCmd.java
similarity index 96%
rename from kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/cmd/StartKdcCmd.java
rename to kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/init/cmd/StartKdcCmd.java
index 05c9932..36405b2 100644
--- a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/cmd/StartKdcCmd.java
+++ b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/init/cmd/StartKdcCmd.java
@@ -17,7 +17,7 @@
  *  under the License.
  *
  */
-package org.apache.kerby.kerberos.tool.cmd;
+package org.apache.kerby.kerberos.tool.init.cmd;
 
 import org.apache.kerby.has.client.HasInitClient;
 import org.apache.kerby.kerberos.kerb.KrbException;