summaryrefslogtreecommitdiffstats
path: root/base/java-tools/src
diff options
context:
space:
mode:
authorEndi S. Dewata <edewata@redhat.com>2014-10-06 12:20:42 -0400
committerEndi S. Dewata <edewata@redhat.com>2014-10-09 17:08:11 -0400
commit27e27f8b63bc4c45d25a8bc5e07ac3a8e199565e (patch)
tree5a698f3a56885336a29128b12db9fa0fa2e1a222 /base/java-tools/src
parent72bad14bb14e16455874fd8c38913a7ccca407e2 (diff)
downloadpki-27e27f8b63bc4c45d25a8bc5e07ac3a8e199565e.tar.gz
pki-27e27f8b63bc4c45d25a8bc5e07ac3a8e199565e.tar.xz
pki-27e27f8b63bc4c45d25a8bc5e07ac3a8e199565e.zip
Added CLI to import/export certificates with private keys.
New CLI commands have been added to import/export certificates and private keys into/from the client security database. The CLI can also be used to generate the file needed by Python client library for client certificate authentication.
Diffstat (limited to 'base/java-tools/src')
-rw-r--r--base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java4
-rw-r--r--base/java-tools/src/com/netscape/cmstools/client/ClientCLI.java2
-rw-r--r--base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java172
-rw-r--r--base/java-tools/src/com/netscape/cmstools/client/ClientCertModifyCLI.java126
-rw-r--r--base/java-tools/src/com/netscape/cmstools/client/ClientCertShowCLI.java256
5 files changed, 532 insertions, 28 deletions
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 066a7d580..8c3805e00 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
@@ -494,7 +494,9 @@ public class MainCLI extends CLI {
String command = cmdArgs[0];
if (!command.equals("client-init") &&
!command.equals("client-cert-import") &&
- !command.equals("client-cert-request")) {
+ !command.equals("client-cert-mod") &&
+ !command.equals("client-cert-request") &&
+ !command.equals("client-cert-show")) {
init();
}
diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCLI.java
index 443d48bdf..c9c71521a 100644
--- a/base/java-tools/src/com/netscape/cmstools/client/ClientCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCLI.java
@@ -35,8 +35,10 @@ public class ClientCLI extends CLI {
addModule(new ClientInitCLI(this));
addModule(new ClientCertFindCLI(this));
addModule(new ClientCertImportCLI(this));
+ addModule(new ClientCertModifyCLI(this));
addModule(new ClientCertRemoveCLI(this));
addModule(new ClientCertRequestCLI(this));
+ addModule(new ClientCertShowCLI(this));
}
public String getFullName() {
diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java
index 5080c55ea..afa91d659 100644
--- a/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java
@@ -21,6 +21,7 @@ package com.netscape.cmstools.client;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
+import java.io.IOException;
import java.io.PrintWriter;
import java.net.URI;
import java.util.Arrays;
@@ -51,21 +52,33 @@ public class ClientCertImportCLI extends CLI {
}
public void printHelp() {
- formatter.printHelp(getFullName() + " <nickname> [OPTIONS...]", options);
+ formatter.printHelp(getFullName() + " [nickname] [OPTIONS...]", options);
}
public void createOptions() {
- Option option = new Option(null, "cert", true, "Import certificate file");
+ Option option = new Option(null, "cert", true, "Certificate file to import.");
option.setArgName("path");
options.addOption(option);
- option = new Option(null, "ca-cert", true, "Import CA certificate file");
+ option = new Option(null, "ca-cert", true, "CA certificate file to import.");
+ option.setArgName("path");
+ options.addOption(option);
+
+ option = new Option(null, "pkcs12", true, "PKCS #12 file to import.");
+ option.setArgName("path");
+ options.addOption(option);
+
+ option = new Option(null, "pkcs12-password", true, "PKCS #12 password.");
+ option.setArgName("password");
+ options.addOption(option);
+
+ option = new Option(null, "pkcs12-password-file", true, "PKCS #12 password file.");
option.setArgName("path");
options.addOption(option);
options.addOption(null, "ca-server", false, "Import CA certificate from CA server");
- option = new Option(null, "serial", true, "Serial number of certificate in CA");
+ option = new Option(null, "serial", true, "Serial number of certificate to import from CA server");
option.setArgName("serial number");
options.addOption(option);
@@ -117,30 +130,72 @@ public class ClientCertImportCLI extends CLI {
nickname = mainCLI.config.getCertNickname();
}
- if (nickname == null) {
- System.err.println("Error: Missing certificate nickname.");
- System.exit(-1);
- }
+ // nickname is not required to import PKCS #12 file
String certPath = cmd.getOptionValue("cert");
String caCertPath = cmd.getOptionValue("ca-cert");
+ String pkcs12Path = cmd.getOptionValue("pkcs12");
+ String pkcs12Password = cmd.getOptionValue("pkcs12-password");
+ String pkcs12PasswordPath = cmd.getOptionValue("pkcs12-password-file");
boolean importFromCAServer = cmd.hasOption("ca-server");
String serialNumber = cmd.getOptionValue("serial");
String trustAttributes = cmd.getOptionValue("trust", "u,u,u");
- File certFile;
-
// load the certificate
if (certPath != null) {
- if (verbose) System.out.println("Loading certificate from " + certPath + ".");
- certFile = new File(certPath);
+
+ if (verbose) System.out.println("Importing certificate from " + certPath + ".");
+
+ importCert(
+ mainCLI.certDatabase.getAbsolutePath(),
+ certPath,
+ nickname,
+ trustAttributes);
} else if (caCertPath != null) {
- if (verbose) System.out.println("Loading CA certificate from " + caCertPath + ".");
- certFile = new File(caCertPath);
+
+ if (verbose) System.out.println("Importing CA certificate from " + caCertPath + ".");
trustAttributes = "CT,c,";
+ importCert(
+ mainCLI.certDatabase.getAbsolutePath(),
+ caCertPath,
+ nickname,
+ trustAttributes);
+
+ } else if (pkcs12Path != null) {
+
+ if (verbose) System.out.println("Importing certificates from " + pkcs12Path + ".");
+
+ if (pkcs12Password != null && pkcs12PasswordPath != null) {
+ throw new Exception("PKCS #12 password and password file are mutually exclusive");
+
+ } else if (pkcs12Password != null) {
+ // store password into a temporary file
+ File pkcs12PasswordFile = File.createTempFile("pki-client-cert-import-", ".pwd");
+ pkcs12PasswordFile.deleteOnExit();
+
+ try (PrintWriter out = new PrintWriter(new FileWriter(pkcs12PasswordFile))) {
+ out.print(pkcs12Password);
+ }
+
+ pkcs12PasswordPath = pkcs12PasswordFile.getAbsolutePath();
+
+ } else if (pkcs12PasswordPath != null) {
+ // nothing to do
+
+ } else {
+ throw new Exception("Missing PKCS #12 password");
+ }
+
+ // import certificates and private key into PKCS #12 file
+ importPKCS12(
+ mainCLI.certDatabase.getAbsolutePath(),
+ mainCLI.config.getCertPassword(),
+ pkcs12Path,
+ pkcs12PasswordPath);
+
} else if (importFromCAServer) {
// late initialization
@@ -152,10 +207,10 @@ public class ClientCertImportCLI extends CLI {
String caServerURI = serverURI.getScheme() + "://" +
serverURI.getHost() + ":" + serverURI.getPort() + "/ca";
- if (verbose) System.out.println("Downloading CA certificate from " + caServerURI + ".");
+ if (verbose) System.out.println("Importing CA certificate from " + caServerURI + ".");
byte[] bytes = client.downloadCACertChain(caServerURI);
- certFile = File.createTempFile("pki-client-cert-import-", ".crt", mainCLI.certDatabase);
+ File certFile = File.createTempFile("pki-client-cert-import-", ".crt");
certFile.deleteOnExit();
try (FileOutputStream out = new FileOutputStream(certFile)) {
@@ -164,6 +219,12 @@ public class ClientCertImportCLI extends CLI {
trustAttributes = "CT,c,";
+ importCert(
+ mainCLI.certDatabase.getAbsolutePath(),
+ certFile.getAbsolutePath(),
+ nickname,
+ trustAttributes);
+
} else if (serialNumber != null) {
// connect to CA anonymously
@@ -172,12 +233,15 @@ public class ClientCertImportCLI extends CLI {
config.setCertPassword(null);
config.setCertNickname(null);
+ URI serverURI = config.getServerURI();
+ if (verbose) System.out.println("Importing certificate " + serialNumber + " from " + serverURI + ".");
+
PKIClient client = new PKIClient(config, null);
CertClient certClient = new CertClient(client, "ca");
CertData certData = certClient.getCert(new CertId(serialNumber));
- certFile = File.createTempFile("pki-client-cert-import-", ".crt", mainCLI.certDatabase);
+ File certFile = File.createTempFile("pki-client-cert-import-", ".crt");
certFile.deleteOnExit();
String encoded = certData.getEncoded();
@@ -185,6 +249,12 @@ public class ClientCertImportCLI extends CLI {
out.write(encoded);
}
+ importCert(
+ mainCLI.certDatabase.getAbsolutePath(),
+ certFile.getAbsolutePath(),
+ nickname,
+ trustAttributes);
+
} else {
System.err.println("Error: Missing certificate to import");
printHelp();
@@ -192,23 +262,71 @@ public class ClientCertImportCLI extends CLI {
return;
}
- String[] commands = {
- "/usr/bin/certutil", "-A",
- "-d", mainCLI.certDatabase.getAbsolutePath(),
- "-i", certFile.getAbsolutePath(),
+ if (nickname == null) {
+ MainCLI.printMessage("Imported certificates from PKCS #12 file");
+
+ } else {
+ MainCLI.printMessage("Imported certificate \"" + nickname + "\"");
+ }
+ }
+
+ public void importCert(
+ String dbPath,
+ String certPath,
+ String nickname,
+ String trustAttributes) throws Exception {
+
+ if (nickname == null) {
+ System.err.println("Error: Missing certificate nickname.");
+ System.exit(-1);
+ }
+
+ String[] command = {
+ "/bin/certutil", "-A",
+ "-d", dbPath,
+ "-i", certPath,
"-n", nickname,
"-t", trustAttributes
};
- Runtime rt = Runtime.getRuntime();
- Process p = rt.exec(commands);
+ try {
+ run(command);
+
+ } catch (Exception e) {
+ throw new Exception("Unable to import certificate file", e);
+ }
+ }
+
+ public void importPKCS12(
+ String dbPath,
+ String dbPassword,
+ String pkcs12Path,
+ String pkcs12PasswordPath) throws Exception {
+
+ String[] command = {
+ "/bin/pk12util",
+ "-d", dbPath,
+ "-K", dbPassword,
+ "-i", pkcs12Path,
+ "-w", pkcs12PasswordPath
+ };
+ try {
+ run(command);
+
+ } catch (Exception e) {
+ throw new Exception("Unable to import PKCS #12 file", e);
+ }
+ }
+
+ public void run(String[] command) throws IOException, InterruptedException {
+
+ Runtime rt = Runtime.getRuntime();
+ Process p = rt.exec(command);
int rc = p.waitFor();
+
if (rc != 0) {
- MainCLI.printMessage("Import failed");
- return;
+ throw new IOException("Command failed. RC: " + rc);
}
-
- MainCLI.printMessage("Imported certificate \"" + nickname + "\"");
}
}
diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCertModifyCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCertModifyCLI.java
new file mode 100644
index 000000000..738dca07c
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertModifyCLI.java
@@ -0,0 +1,126 @@
+// --- 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) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cmstools.client;
+
+import java.io.IOException;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class ClientCertModifyCLI extends CLI {
+
+ public ClientCLI clientCLI;
+
+ public ClientCertModifyCLI(ClientCLI clientCLI) {
+ super("cert-mod", "Modify certificate in client security database", clientCLI);
+ this.clientCLI = clientCLI;
+
+ createOptions();
+ }
+
+ public void printHelp() {
+ formatter.printHelp(getFullName() + " <nickname> [OPTIONS...]", options);
+ }
+
+ public void createOptions() {
+ Option option = new Option(null, "trust", true, "Trust attributes. Default: u,u,u.");
+ option.setArgName("trust attributes");
+ options.addOption(option);
+ }
+
+ public void execute(String[] args) throws Exception {
+
+ CommandLine cmd = null;
+
+ try {
+ cmd = parser.parse(options, args);
+
+ } catch (Exception e) {
+ System.err.println("Error: " + e.getMessage());
+ printHelp();
+ System.exit(-1);
+ }
+
+ if (cmd.hasOption("help")) {
+ // Display usage
+ printHelp();
+ System.exit(0);
+ }
+
+ String[] cmdArgs = cmd.getArgs();
+
+ if (cmdArgs.length > 1) {
+ System.err.println("Error: Too many arguments specified.");
+ printHelp();
+ System.exit(-1);
+ }
+
+ if (cmdArgs.length == 0) {
+ System.err.println("Error: Missing certificate nickname.");
+ printHelp();
+ System.exit(-1);
+ }
+
+ MainCLI mainCLI = (MainCLI)parent.getParent();
+
+ String nickname = cmdArgs[0];
+
+ String trustAttributes = cmd.getOptionValue("trust", "u,u,u");
+
+ int rc = modifyCert(
+ mainCLI.certDatabase.getAbsolutePath(),
+ nickname,
+ trustAttributes);
+
+ if (rc != 0) {
+ MainCLI.printMessage("Modified failed");
+ return;
+ }
+
+ MainCLI.printMessage("Modified certificate \"" + nickname + "\"");
+ }
+
+ public int modifyCert(
+ String dbPath,
+ String nickname,
+ String trustAttributes) throws IOException, InterruptedException {
+
+ String[] command = {
+ "/usr/bin/certutil", "-M",
+ "-d", dbPath,
+ "-n", nickname,
+ "-t", trustAttributes
+ };
+
+ return run(command);
+ }
+
+ public int run(String[] command) throws IOException, InterruptedException {
+
+ Runtime rt = Runtime.getRuntime();
+ Process p = rt.exec(command);
+ return p.waitFor();
+ }
+}
diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCertShowCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCertShowCLI.java
new file mode 100644
index 000000000..f79501cfc
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertShowCLI.java
@@ -0,0 +1,256 @@
+// --- 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) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cmstools.client;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.commons.lang.StringUtils;
+import org.mozilla.jss.crypto.X509Certificate;
+
+import com.netscape.certsrv.cert.CertData;
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class ClientCertShowCLI extends CLI {
+
+ public ClientCLI clientCLI;
+
+ public ClientCertShowCLI(ClientCLI clientCLI) {
+ super("cert-show", "Show certificate in client security database", clientCLI);
+ this.clientCLI = clientCLI;
+
+ createOptions();
+ }
+
+ public void printHelp() {
+ formatter.printHelp(getFullName() + " <nickname> [OPTIONS...]", options);
+ }
+
+ public void createOptions() {
+ Option option = new Option(null, "cert", true, "PEM file to store the certificate.");
+ option.setArgName("path");
+ options.addOption(option);
+
+ option = new Option(null, "client-cert", true, "PEM file to store the certificate and the private key.");
+ option.setArgName("path");
+ options.addOption(option);
+
+ option = new Option(null, "pkcs12", true, "PKCS #12 file to store the certificate chain and the private key.");
+ option.setArgName("path");
+ options.addOption(option);
+
+ option = new Option(null, "pkcs12-password", true, "PKCS #12 file password.");
+ option.setArgName("password");
+ options.addOption(option);
+ }
+
+ public void execute(String[] args) throws Exception {
+
+ CommandLine cmd = null;
+
+ try {
+ cmd = parser.parse(options, args);
+
+ } catch (Exception e) {
+ System.err.println("Error: " + e.getMessage());
+ printHelp();
+ System.exit(-1);
+ }
+
+ if (cmd.hasOption("help")) {
+ // Display usage
+ printHelp();
+ System.exit(0);
+ }
+
+ String[] cmdArgs = cmd.getArgs();
+
+ if (cmdArgs.length > 1) {
+ System.err.println("Error: Too many arguments specified.");
+ printHelp();
+ System.exit(-1);
+ }
+
+ if (cmdArgs.length == 0) {
+ System.err.println("Error: Missing certificate nickname.");
+ printHelp();
+ System.exit(-1);
+ }
+
+ MainCLI mainCLI = (MainCLI)parent.getParent();
+
+ String nickname = cmdArgs[0];
+ String certPath = cmd.getOptionValue("cert");
+ String pkcs12Path = cmd.getOptionValue("pkcs12");
+ String pkcs12Password = cmd.getOptionValue("pkcs12-password");
+ String clientCertPath = cmd.getOptionValue("client-cert");
+
+ if (certPath != null) {
+
+ if (verbose) System.out.println("Exporting certificate to " + clientCertPath + ".");
+
+ // late initialization
+ mainCLI.init();
+
+ client = mainCLI.getClient();
+ X509Certificate cert = client.getCert(nickname);
+
+ try (PrintWriter out = new PrintWriter(new FileWriter(certPath))) {
+ out.println(CertData.HEADER);
+ out.println(Utils.base64encode(cert.getEncoded()));
+ out.println(CertData.FOOTER);
+ }
+
+ } else if (pkcs12Path != null) {
+
+ if (verbose) System.out.println("Exporting certificate chain and private key to " + pkcs12Path + ".");
+
+ if (pkcs12Password == null) {
+ throw new Exception("Missing PKCS #12 password");
+ }
+
+ // store password into a temporary file
+ File pkcs12PasswordFile = File.createTempFile("pki-client-cert-show-", ".pwd");
+ pkcs12PasswordFile.deleteOnExit();
+
+ try (PrintWriter out = new PrintWriter(new FileWriter(pkcs12PasswordFile))) {
+ out.print(pkcs12Password);
+ }
+
+ // export certificate chain and private key into PKCS #12 file
+ exportPKCS12(
+ mainCLI.certDatabase.getAbsolutePath(),
+ mainCLI.config.getCertPassword(),
+ pkcs12Path,
+ pkcs12PasswordFile.getAbsolutePath(),
+ nickname);
+
+ } else if (clientCertPath != null) {
+
+ if (verbose) System.out.println("Exporting client certificate and private key to " + clientCertPath + ".");
+
+ // generate random PKCS #12 password
+ pkcs12Password = RandomStringUtils.randomAlphanumeric(16);
+
+ // store password into a temporary file
+ File pkcs12PasswordFile = File.createTempFile("pki-client-cert-show-", ".pwd");
+ pkcs12PasswordFile.deleteOnExit();
+
+ try (PrintWriter out = new PrintWriter(new FileWriter(pkcs12PasswordFile))) {
+ out.print(pkcs12Password);
+ }
+
+ // export certificate chain and private key into a temporary PKCS #12 file
+ File pkcs12File = File.createTempFile("pki-client-cert-show-", ".p12");
+ pkcs12File.deleteOnExit();
+
+ exportPKCS12(
+ mainCLI.certDatabase.getAbsolutePath(),
+ mainCLI.config.getCertPassword(),
+ pkcs12File.getAbsolutePath(),
+ pkcs12PasswordFile.getAbsolutePath(),
+ nickname);
+
+ // export client certificate and private key into a PEM file
+ exportClientCertificate(
+ pkcs12File.getAbsolutePath(),
+ pkcs12PasswordFile.getAbsolutePath(),
+ clientCertPath);
+
+ } else {
+ // late initialization
+ mainCLI.init();
+
+ client = mainCLI.getClient();
+ X509Certificate cert = client.getCert(nickname);
+
+ ClientCLI.printCertInfo(cert);
+ }
+ }
+
+ public void exportPKCS12(
+ String dbPath,
+ String dbPassword,
+ String pkcs12Path,
+ String pkcs12PasswordPath,
+ String nickname) throws Exception {
+
+ String[] command = {
+ "/bin/pk12util",
+ "-d", dbPath,
+ "-K", dbPassword,
+ "-o", pkcs12Path,
+ "-w", pkcs12PasswordPath,
+ "-n", nickname
+ };
+
+ try {
+ run(command);
+
+ } catch (Exception e) {
+ throw new Exception("Unable to export PKCS #12 file", e);
+ }
+ }
+
+ public void exportClientCertificate(
+ String pkcs12Path,
+ String pkcs12PasswordPath,
+ String clientCertPath) throws Exception {
+
+ String[] command = {
+ "/bin/openssl",
+ "pkcs12",
+ "-clcerts", // client certificate only
+ "-nodes", // no encryption
+ "-in", pkcs12Path,
+ "-passin", "file:" + pkcs12PasswordPath,
+ "-out", clientCertPath
+ };
+
+ try {
+ run(command);
+
+ } catch (Exception e) {
+ throw new Exception("Unable to export client certificate", e);
+ }
+ }
+
+ public void run(String[] command) throws IOException, InterruptedException {
+
+ if (verbose) System.out.println("Command: " + StringUtils.join(command, " "));
+
+ Runtime rt = Runtime.getRuntime();
+ Process p = rt.exec(command);
+ int rc = p.waitFor();
+
+ if (rc != 0) {
+ throw new IOException("Command failed. RC: " + rc);
+ }
+ }
+}