From d4bef8b123aae1f48c080c5fc92cb341748c816e Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Wed, 25 Sep 2013 23:54:39 -0400
Subject: [PATCH] Fixed CLI authentication issue.

Previously the CLI authentication could fail because it's using a
fixed default subsystem which may not match the command it's trying
to execute. The CLI has now been modified to use the appropriate
default subsystem depending on the command to be executed.
---
 .../netscape/certsrv/account/AccountClient.java    |   4 -
 .../src/com/netscape/certsrv/cert/CertClient.java  |   4 -
 .../com/netscape/certsrv/group/GroupClient.java    |   4 -
 .../src/com/netscape/certsrv/key/KeyClient.java    |   4 -
 .../netscape/certsrv/profile/ProfileClient.java    |   4 -
 .../certsrv/system/KRAConnectorClient.java         |   4 -
 .../certsrv/system/SecurityDomainClient.java       |   4 -
 .../src/com/netscape/certsrv/user/UserClient.java  |   4 -
 .../cms/servlet/csadmin/ConfigurationUtils.java    |   6 +-
 .../src/com/netscape/cmstools/cert/CertCLI.java    |   9 +-
 .../src/com/netscape/cmstools/cli/CLI.java         |  12 +-
 .../src/com/netscape/cmstools/cli/MainCLI.java     | 146 ++++++++-------------
 .../src/com/netscape/cmstools/cli/ProxyCLI.java    | 119 +++++++++++++++++
 .../src/com/netscape/cmstools/group/GroupCLI.java  |   9 +-
 .../src/com/netscape/cmstools/key/KeyCLI.java      |   8 +-
 .../com/netscape/cmstools/profile/ProfileCLI.java  |   8 +-
 .../netscape/cmstools/system/KRAConnectorCLI.java  |   8 +-
 .../cmstools/system/SecurityDomainCLI.java         |   8 +-
 .../src/com/netscape/cmstools/user/UserCLI.java    |   9 +-
 19 files changed, 240 insertions(+), 134 deletions(-)
 create mode 100644 base/java-tools/src/com/netscape/cmstools/cli/ProxyCLI.java

diff --git a/base/common/src/com/netscape/certsrv/account/AccountClient.java b/base/common/src/com/netscape/certsrv/account/AccountClient.java
index 333f65679ba0eef074aa3614d88c4a53f47dc4f8..dcf8975b513076f216b786214ce136d0036b1af9 100644
--- a/base/common/src/com/netscape/certsrv/account/AccountClient.java
+++ b/base/common/src/com/netscape/certsrv/account/AccountClient.java
@@ -30,10 +30,6 @@ public class AccountClient extends Client {
     public AccountResource resource;
     public boolean loggedIn;
 
-    public AccountClient(PKIClient client) throws URISyntaxException {
-        this(client, client.getSubsystem());
-    }
-
     public AccountClient(PKIClient client, String subsystem) throws URISyntaxException {
         super(client, subsystem, "account");
         init();
diff --git a/base/common/src/com/netscape/certsrv/cert/CertClient.java b/base/common/src/com/netscape/certsrv/cert/CertClient.java
index 7ff6af39768edd8533e6d3809fa5318f9c9b6543..b0ebc04bf0972f25cf8814f357cf354b5e86fe0e 100644
--- a/base/common/src/com/netscape/certsrv/cert/CertClient.java
+++ b/base/common/src/com/netscape/certsrv/cert/CertClient.java
@@ -33,10 +33,6 @@ public class CertClient extends Client {
     public CertResource certClient;
     public CertRequestResource certRequestResource;
 
-    public CertClient(PKIClient client) throws URISyntaxException {
-        this(client, client.getSubsystem());
-    }
-
     public CertClient(PKIClient client, String subsystem) throws URISyntaxException {
         super(client, subsystem, "cert");
         init();
diff --git a/base/common/src/com/netscape/certsrv/group/GroupClient.java b/base/common/src/com/netscape/certsrv/group/GroupClient.java
index 33be6e7727766c7e7b5c47cddaec39aae525e7b0..2f11e21b46205d57180567251cb086ae8bd56c2f 100644
--- a/base/common/src/com/netscape/certsrv/group/GroupClient.java
+++ b/base/common/src/com/netscape/certsrv/group/GroupClient.java
@@ -32,10 +32,6 @@ public class GroupClient extends Client {
     public GroupResource groupClient;
     public GroupMemberResource groupMemberClient;
 
-    public GroupClient(PKIClient client) throws URISyntaxException {
-        this(client, client.getSubsystem());
-    }
-
     public GroupClient(PKIClient client, String subsystem) throws URISyntaxException {
         super(client, subsystem, "group");
         init();
diff --git a/base/common/src/com/netscape/certsrv/key/KeyClient.java b/base/common/src/com/netscape/certsrv/key/KeyClient.java
index be4e5ed587ae02f8deb33e64ae7a4aa354a440bc..385996eed490a4789a042eb6a2ae41f02cbc6b03 100644
--- a/base/common/src/com/netscape/certsrv/key/KeyClient.java
+++ b/base/common/src/com/netscape/certsrv/key/KeyClient.java
@@ -31,10 +31,6 @@ public class KeyClient extends Client {
     public KeyResource keyClient;
     public KeyRequestResource keyRequestClient;
 
-    public KeyClient(PKIClient client) throws URISyntaxException {
-        this(client, client.getSubsystem());
-    }
-
     public KeyClient(PKIClient client, String subsystem) throws URISyntaxException {
         super(client, subsystem, "key");
         init();
diff --git a/base/common/src/com/netscape/certsrv/profile/ProfileClient.java b/base/common/src/com/netscape/certsrv/profile/ProfileClient.java
index c4ecf6bec170f61146ecbb4ba6726f54d46a5fdb..64a53b209bc8304213d82eae8afb014fdda622f8 100644
--- a/base/common/src/com/netscape/certsrv/profile/ProfileClient.java
+++ b/base/common/src/com/netscape/certsrv/profile/ProfileClient.java
@@ -29,10 +29,6 @@ public class ProfileClient extends Client {
 
     public ProfileResource profileClient;
 
-    public ProfileClient(PKIClient client) throws URISyntaxException {
-        this(client, client.getSubsystem());
-    }
-
     public ProfileClient(PKIClient client, String subsystem) throws URISyntaxException {
         super(client, subsystem, "profile");
         init();
diff --git a/base/common/src/com/netscape/certsrv/system/KRAConnectorClient.java b/base/common/src/com/netscape/certsrv/system/KRAConnectorClient.java
index 514390eaec7970045ef20668adf23ad7ea91b37e..4a29ca154207fba5f3a40ccea562c3ee97ddbabb 100644
--- a/base/common/src/com/netscape/certsrv/system/KRAConnectorClient.java
+++ b/base/common/src/com/netscape/certsrv/system/KRAConnectorClient.java
@@ -29,10 +29,6 @@ public class KRAConnectorClient extends Client {
 
     public KRAConnectorResource kraConnectorClient;
 
-    public KRAConnectorClient(PKIClient client) throws URISyntaxException {
-        this(client, client.getSubsystem());
-    }
-
     public KRAConnectorClient(PKIClient client, String subsystem) throws URISyntaxException {
         super(client, subsystem, "kraconnector");
         init();
diff --git a/base/common/src/com/netscape/certsrv/system/SecurityDomainClient.java b/base/common/src/com/netscape/certsrv/system/SecurityDomainClient.java
index 3eb21cfce421a0a59c2d5aca4c444c87216841d0..6c6a5d3d5688aad0db25b6b185a890e00c782bda 100644
--- a/base/common/src/com/netscape/certsrv/system/SecurityDomainClient.java
+++ b/base/common/src/com/netscape/certsrv/system/SecurityDomainClient.java
@@ -30,10 +30,6 @@ public class SecurityDomainClient extends Client {
 
     private SecurityDomainResource securityDomainClient;
 
-    public SecurityDomainClient(PKIClient client) throws URISyntaxException {
-        this(client, client.getSubsystem());
-    }
-
     public SecurityDomainClient(PKIClient client, String subsystem) throws URISyntaxException {
         super(client, subsystem, "securitydomain");
         init();
diff --git a/base/common/src/com/netscape/certsrv/user/UserClient.java b/base/common/src/com/netscape/certsrv/user/UserClient.java
index 0c51821fe855eee2299e3545a6585e9be5250443..85b7f059209e53a12274ae46b237222054ce7871 100644
--- a/base/common/src/com/netscape/certsrv/user/UserClient.java
+++ b/base/common/src/com/netscape/certsrv/user/UserClient.java
@@ -33,10 +33,6 @@ public class UserClient extends Client {
     public UserCertResource userCertClient;
     public UserMembershipResource userMembershipClient;
 
-    public UserClient(PKIClient client) throws URISyntaxException {
-        this(client, client.getSubsystem());
-    }
-
     public UserClient(PKIClient client, String subsystem) throws URISyntaxException {
         super(client, subsystem, "user");
         init();
diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
index 2c267288127a326456202b625e084f7ad875c2f5..dab0ed40ef9216a2daaf382b6cc6630ba50e20f9 100644
--- a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
+++ b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
@@ -329,7 +329,7 @@ public class ConfigurationUtils {
         String csType = cs.getString("cs.type");
 
         ClientConfig config = new ClientConfig();
-        config.setServerURI("https://" + sdhost + ":" + sdport + "/ca");
+        config.setServerURI("https://" + sdhost + ":" + sdport);
         config.setUsername(user);
         config.setPassword(passwd);
 
@@ -346,8 +346,8 @@ public class ConfigurationUtils {
         // utilizing an untrusted temporary CA cert.
         connection.addIgnoredCertStatus(SSLCertificateApprovalCallback.ValidityStatus.CA_CERT_INVALID);
 
-        AccountClient accountClient = new AccountClient(client);
-        SecurityDomainClient sdClient = new SecurityDomainClient(client);
+        AccountClient accountClient = new AccountClient(client, "ca");
+        SecurityDomainClient sdClient = new SecurityDomainClient(client, "ca");
 
         try {
             accountClient.login();
diff --git a/base/java-tools/src/com/netscape/cmstools/cert/CertCLI.java b/base/java-tools/src/com/netscape/cmstools/cert/CertCLI.java
index 83cd6851c8393a2e4bb88a1ac09dffa3a323c7dd..c3f43401c001a4878edfff5ba4509913e605a186 100644
--- a/base/java-tools/src/com/netscape/cmstools/cert/CertCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cert/CertCLI.java
@@ -68,7 +68,14 @@ public class CertCLI extends CLI {
 
     public void execute(String[] args) throws Exception {
 
-        certClient = new CertClient(parent.getClient());
+        client = parent.getClient();
+
+        // determine the subsystem
+        String subsystem = client.getSubsystem();
+        if (subsystem == null) subsystem = "ca";
+
+        // create new cert client
+        certClient = new CertClient(client, subsystem);
 
         super.execute(args);
     }
diff --git a/base/java-tools/src/com/netscape/cmstools/cli/CLI.java b/base/java-tools/src/com/netscape/cmstools/cli/CLI.java
index 0adecc17143f8d43f1c000ca7c910fb021d3689d..abe0883b19ad5f60d44e16b7cc02f3a45ce01cf6 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/CLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cli/CLI.java
@@ -87,14 +87,22 @@ public class CLI {
         this.description = description;
     }
 
-    public void addModule(CLI module) {
-        modules.put(module.getName(), module);
+    public CLI getParent() {
+        return parent;
     }
 
     public CLI getModule(String name) {
         return modules.get(name);
     }
 
+    public void addModule(CLI module) {
+        modules.put(module.getName(), module);
+    }
+
+    public CLI removeModule(String name) {
+        return modules.remove(name);
+    }
+
     public PKIClient getClient() {
         return client;
     }
diff --git a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
index 5808254ef143fa7f5cf4fac5b23a95188518d9fb..f77dc8183d144c1a84b48c693f03af41a808420f 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
@@ -35,7 +35,6 @@ import org.mozilla.jss.ssl.SSLCertificateApprovalCallback;
 import org.mozilla.jss.util.IncorrectPasswordException;
 import org.mozilla.jss.util.Password;
 
-import com.netscape.certsrv.account.AccountClient;
 import com.netscape.certsrv.client.ClientConfig;
 import com.netscape.certsrv.client.PKIClient;
 import com.netscape.certsrv.client.PKIConnection;
@@ -60,26 +59,26 @@ public class MainCLI extends CLI {
 
     public File certDatabase;
 
-    public AccountClient accountClient;
-
     String output;
 
     public MainCLI() throws Exception {
         super("pki", "PKI command-line interface");
 
         addModule(new CACLI(this));
-        addModule(new CertCLI(this));
-        addModule(new ClientCLI(this));
-        addModule(new GroupCLI(this));
-        addModule(new KeyCLI(this));
         addModule(new KRACLI(this));
-        addModule(new KRAConnectorCLI(this));
         addModule(new OCSPCLI(this));
-        addModule(new ProfileCLI(this));
-        addModule(new SecurityDomainCLI(this));
         addModule(new TKSCLI(this));
         addModule(new TPSCLI(this));
-        addModule(new UserCLI(this));
+
+        addModule(new ClientCLI(this));
+
+        addModule(new ProxyCLI(new CertCLI(this), "ca"));
+        addModule(new ProxyCLI(new GroupCLI(this), "ca"));
+        addModule(new ProxyCLI(new KeyCLI(this), "kra"));
+        addModule(new ProxyCLI(new KRAConnectorCLI(this), "ca"));
+        addModule(new ProxyCLI(new ProfileCLI(this), "ca"));
+        addModule(new ProxyCLI(new SecurityDomainCLI(this), "ca"));
+        addModule(new ProxyCLI(new UserCLI(this), "ca"));
     }
 
     public String getFullModuleName(String moduleName) {
@@ -96,7 +95,43 @@ public class MainCLI extends CLI {
         formatter.printHelp(name+" [OPTIONS..] <command> [ARGS..]", options);
         System.out.println();
 
-        super.printHelp();
+        int leftPadding = 1;
+        int rightPadding = 25;
+
+        System.out.println("Subsystems:");
+
+        for (CLI module : modules.values()) {
+            if (!(module instanceof SubsystemCLI)) continue;
+
+            String label = module.getFullName();
+
+            int padding = rightPadding - leftPadding - label.length();
+            if (padding < 1)
+                padding = 1;
+
+            System.out.print(StringUtils.repeat(" ", leftPadding));
+            System.out.print(label);
+            System.out.print(StringUtils.repeat(" ", padding));
+            System.out.println(module.getDescription());
+        }
+
+        System.out.println();
+        System.out.println("Commands:");
+
+        for (CLI module : modules.values()) {
+            if (module instanceof SubsystemCLI) continue;
+
+            String label = module.getFullName();
+
+            int padding = rightPadding - leftPadding - label.length();
+            if (padding < 1)
+                padding = 1;
+
+            System.out.print(StringUtils.repeat(" ", leftPadding));
+            System.out.print(label);
+            System.out.print(StringUtils.repeat(" ", padding));
+            System.out.println(module.getDescription());
+        }
     }
 
     public void createOptions(Options options) throws UnknownHostException {
@@ -117,7 +152,7 @@ public class MainCLI extends CLI {
         option.setArgName("port");
         options.addOption(option);
 
-        option = new Option("t", true, "Subsystem type (default: ca)");
+        option = new Option("t", true, "Subsystem type");
         option.setArgName("type");
         options.addOption(option);
 
@@ -168,13 +203,18 @@ public class MainCLI extends CLI {
         String protocol = cmd.getOptionValue("P", "http");
         String hostname = cmd.getOptionValue("h", InetAddress.getLocalHost().getCanonicalHostName());
         String port = cmd.getOptionValue("p", "8080");
-        String type = cmd.getOptionValue("t", "ca");
+        String subsystem = cmd.getOptionValue("t");
 
         if (uri == null)
-            uri = protocol + "://" + hostname + ":" + port + "/" + type;
+            uri = protocol + "://" + hostname + ":" + port;
+
+        if (subsystem != null)
+            uri = uri + "/" + subsystem;
 
         config.setServerURI(uri);
 
+        if (verbose) System.out.println("Server URI: "+uri);
+
         String certDatabase = cmd.getOptionValue("d");
         String certNickname = cmd.getOptionValue("n");
         String certPassword = cmd.getOptionValue("c");
@@ -270,20 +310,10 @@ public class MainCLI extends CLI {
             file.mkdirs();
             connection.setOutput(file);
         }
-
-        String subsystem = config.getSubsystem();
-        if (subsystem != null) {
-            // if server URI includes subsystem, perform authentication
-            // against that subsystem
-            accountClient = new AccountClient(client, subsystem);
-        }
     }
 
     public void execute(String[] args) throws Exception {
 
-        CLI module;
-        String[] moduleArgs;
-
         try {
             createOptions(options);
 
@@ -308,6 +338,8 @@ public class MainCLI extends CLI {
 
             parseOptions(cmd);
 
+            init();
+
             if (verbose) {
                 System.out.print("Command:");
                 for (String arg : cmdArgs) {
@@ -317,65 +349,7 @@ public class MainCLI extends CLI {
                 System.out.println();
             }
 
-            String command = cmdArgs[0];
-            String moduleName;
-            String moduleCommand;
-
-            // If a command contains a '-' sign it will be
-            // split into module name and module command.
-            // Otherwise it's a single command.
-            int i = command.indexOf('-');
-            if (i >= 0) { // <module name>-<module command>
-                moduleName = command.substring(0, i);
-                moduleCommand = command.substring(i+1);
-
-            } else { // <command>
-                moduleName = command;
-                moduleCommand = null;
-            }
-
-            // get command module
-            if (verbose) System.out.println("Module: " + moduleName);
-            module = getModule(moduleName);
-            if (module == null)
-                throw new Error("Invalid module \"" + moduleName + "\".");
-
-            // prepare module arguments
-            if (moduleCommand != null) {
-                moduleArgs = new String[cmdArgs.length];
-                moduleArgs[0] = moduleCommand;
-                System.arraycopy(cmdArgs, 1, moduleArgs, 1, cmdArgs.length-1);
-
-            } else {
-                moduleArgs = new String[cmdArgs.length-1];
-                System.arraycopy(cmdArgs, 1, moduleArgs, 0, cmdArgs.length-1);
-            }
-
-        } catch (Throwable t) {
-            if (verbose) {
-                t.printStackTrace(System.err);
-            } else {
-                System.err.println(t.getClass().getSimpleName()+": "+t.getMessage());
-            }
-            printHelp();
-            System.exit(1);
-            return;
-        }
-
-        if (verbose) System.out.println("Server URI: "+config.getServerURI());
-
-        // execute command
-        try {
-            init();
-
-            // login if subsystem and username/nickname is specified
-            if (config.getSubsystem() != null &&
-                    (config.getUsername() != null || config.getCertNickname() != null)) {
-                accountClient.login();
-            }
-
-            // execute module command
-            module.execute(moduleArgs);
+            super.execute(cmdArgs);
 
         } catch (Throwable t) {
             if (verbose) {
@@ -384,10 +358,6 @@ public class MainCLI extends CLI {
                 System.err.println(t.getClass().getSimpleName()+": "+t.getMessage());
             }
             System.exit(1);
-
-        } finally {
-            // logout if subsystem is specified
-            if (config.getSubsystem() != null) accountClient.logout();
         }
     }
 
diff --git a/base/java-tools/src/com/netscape/cmstools/cli/ProxyCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/ProxyCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..7d76cb1b2ecf62a967679552c4e7ea987fceb597
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/cli/ProxyCLI.java
@@ -0,0 +1,119 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cmstools.cli;
+
+import com.netscape.certsrv.account.AccountClient;
+import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.PKIClient;
+
+
+/**
+ * This class provides a mechanism to authenticate against
+ * the appropriate subsystem for the CLI command.
+ *
+ * @author Endi S. Dewata
+ */
+public class ProxyCLI extends CLI {
+
+    CLI module;
+    String defaultSubsystem;
+
+    public ProxyCLI(CLI module, String defaultSubsystem) {
+        super(module.getName(), module.getDescription(), module.getParent());
+
+        this.module = module;
+        this.defaultSubsystem = defaultSubsystem;
+    }
+
+    public String getName() {
+        return module.getName();
+    }
+
+    public void setName(String name) {
+        module.setName(name);
+    }
+
+    public String getFullName() {
+        return module.getFullName();
+    }
+
+    public String getFullModuleName(String moduleName) {
+        return module.getFullModuleName(moduleName);
+    }
+
+    public String getDescription() {
+        return module.getDescription();
+    }
+
+    public void setDescription(String description) {
+        module.setDescription(description);
+    }
+
+    public CLI getParent() {
+        return module.getParent();
+    }
+
+    public CLI getModule(String name) {
+        return module.getModule(name);
+    }
+
+    public void addModule(CLI module) {
+        this.module.addModule(module);
+    }
+
+    public CLI removeModule(String name) {
+        return module.removeModule(name);
+    }
+
+    public PKIClient getClient() {
+        return module.getClient();
+    }
+
+    public Object getClient(String name) {
+        return module.getClient(name);
+    }
+
+    public void printHelp() {
+        module.printHelp();
+    }
+
+    public void execute(String[] args) throws Exception {
+
+        PKIClient client = module.getParent().getClient();
+        AccountClient accountClient = null;
+
+        try {
+            // login if username or nickname is specified
+            ClientConfig config = client.getConfig();
+            if (config.getUsername() != null || config.getCertNickname() != null) {
+
+                String subsystem = config.getSubsystem();
+                if (subsystem == null) subsystem = defaultSubsystem;
+
+                accountClient = new AccountClient(client, subsystem);
+                accountClient.login();
+            }
+
+            module.execute(args);
+
+        } finally {
+            if (accountClient != null) accountClient.logout();
+        }
+    }
+}
diff --git a/base/java-tools/src/com/netscape/cmstools/group/GroupCLI.java b/base/java-tools/src/com/netscape/cmstools/group/GroupCLI.java
index a7b414e1dd6dbfab7e022b033a69a2db43d389cf..dba9d9ab3c6ec693c090dd188a8d6fd863ec1e4f 100644
--- a/base/java-tools/src/com/netscape/cmstools/group/GroupCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/group/GroupCLI.java
@@ -63,9 +63,14 @@ public class GroupCLI extends CLI {
         client = parent.getClient();
         groupClient = (GroupClient)parent.getClient("group");
 
+        // if this is a top-level command
         if (groupClient == null) {
-            // if parent doesn't have group client then create a new one
-            groupClient = new GroupClient(client);
+            // determine the subsystem
+            String subsystem = client.getSubsystem();
+            if (subsystem == null) subsystem = "ca";
+
+            // create new group client
+            groupClient = new GroupClient(client, subsystem);
         }
 
         super.execute(args);
diff --git a/base/java-tools/src/com/netscape/cmstools/key/KeyCLI.java b/base/java-tools/src/com/netscape/cmstools/key/KeyCLI.java
index bbae4368851097ce5592bc6fc0ced954d9038312..e93cc32f0fa1d15b0826739caef01347705a7558 100644
--- a/base/java-tools/src/com/netscape/cmstools/key/KeyCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/key/KeyCLI.java
@@ -50,7 +50,13 @@ public class KeyCLI extends CLI {
     public void execute(String[] args) throws Exception {
 
         client = parent.getClient();
-        keyClient = new KeyClient(client);
+
+        // determine the subsystem
+        String subsystem = client.getSubsystem();
+        if (subsystem == null) subsystem = "kra";
+
+        // create new key client
+        keyClient = new KeyClient(client, subsystem);
 
         super.execute(args);
     }
diff --git a/base/java-tools/src/com/netscape/cmstools/profile/ProfileCLI.java b/base/java-tools/src/com/netscape/cmstools/profile/ProfileCLI.java
index 7ba472454aa49761c970c900d16ee2cc6f143a8a..77539828386122e587cb888bb858088dde1d2a81 100644
--- a/base/java-tools/src/com/netscape/cmstools/profile/ProfileCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/profile/ProfileCLI.java
@@ -49,7 +49,13 @@ public class ProfileCLI extends CLI {
     public void execute(String[] args) throws Exception {
 
         client = parent.getClient();
-        profileClient = new ProfileClient(client);
+
+        // determine the subsystem
+        String subsystem = client.getSubsystem();
+        if (subsystem == null) subsystem = "ca";
+
+        // create new profile client
+        profileClient = new ProfileClient(client, subsystem);
 
         super.execute(args);
     }
diff --git a/base/java-tools/src/com/netscape/cmstools/system/KRAConnectorCLI.java b/base/java-tools/src/com/netscape/cmstools/system/KRAConnectorCLI.java
index e45072de166d26946e912b0186d0bd5e536226ed..a59809e26ee55b062c3f8b6e9c1ef20d8720e154 100644
--- a/base/java-tools/src/com/netscape/cmstools/system/KRAConnectorCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/system/KRAConnectorCLI.java
@@ -47,7 +47,13 @@ public class KRAConnectorCLI extends CLI {
     public void execute(String[] args) throws Exception {
 
         client = parent.getClient();
-        kraConnectorClient = new KRAConnectorClient(client);
+
+        // determine the subsystem
+        String subsystem = client.getSubsystem();
+        if (subsystem == null) subsystem = "ca";
+
+        // create new KRA connector client
+        kraConnectorClient = new KRAConnectorClient(client, subsystem);
 
         super.execute(args);
     }
diff --git a/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainCLI.java b/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainCLI.java
index b7b54942a80abda5c50b186cfa0e762d147eb5a6..224e215a8ed19e78665ec5c5e971f06aec7aec38 100644
--- a/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainCLI.java
@@ -51,7 +51,13 @@ public class SecurityDomainCLI extends CLI {
     public void execute(String[] args) throws Exception {
 
         client = parent.getClient();
-        securityDomainClient = new SecurityDomainClient(client);
+
+        // determine the subsystem
+        String subsystem = client.getSubsystem();
+        if (subsystem == null) subsystem = "ca";
+
+        // create new security domain client
+        securityDomainClient = new SecurityDomainClient(client, subsystem);
 
         super.execute(args);
     }
diff --git a/base/java-tools/src/com/netscape/cmstools/user/UserCLI.java b/base/java-tools/src/com/netscape/cmstools/user/UserCLI.java
index 74f4df9ddae328b6ba92ebc46c2ba2cc5ffb5688..edbb62cabddb0d4b113044c4eb4ac8002bfc641f 100644
--- a/base/java-tools/src/com/netscape/cmstools/user/UserCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/user/UserCLI.java
@@ -69,9 +69,14 @@ public class UserCLI extends CLI {
         client = parent.getClient();
         userClient = (UserClient)parent.getClient("user");
 
+        // if this is a top-level command
         if (userClient == null) {
-            // if parent doesn't have user client then create a new one
-            userClient = new UserClient(client);
+            // determine the subsystem
+            String subsystem = client.getSubsystem();
+            if (subsystem == null) subsystem = "ca";
+
+            // create new user client
+            userClient = new UserClient(client, subsystem);
         }
 
         super.execute(args);
-- 
1.8.1.4

