From 6b60698a2c35cb530a379a2970f7fc11af7e5798 Mon Sep 17 00:00:00 2001 From: "Endi S. Dewata" Date: Mon, 6 Oct 2014 12:20:42 -0400 Subject: [PATCH] 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. --- .../src/com/netscape/certsrv/client/PKIClient.java | 6 + base/java-tools/man/man1/pki-client.1 | 44 +++- .../src/com/netscape/cmstools/cli/MainCLI.java | 4 +- .../com/netscape/cmstools/client/ClientCLI.java | 2 + .../cmstools/client/ClientCertImportCLI.java | 172 +++++++++++--- .../cmstools/client/ClientCertModifyCLI.java | 126 ++++++++++ .../cmstools/client/ClientCertShowCLI.java | 256 +++++++++++++++++++++ 7 files changed, 578 insertions(+), 32 deletions(-) create mode 100644 base/java-tools/src/com/netscape/cmstools/client/ClientCertModifyCLI.java create mode 100644 base/java-tools/src/com/netscape/cmstools/client/ClientCertShowCLI.java diff --git a/base/common/src/com/netscape/certsrv/client/PKIClient.java b/base/common/src/com/netscape/certsrv/client/PKIClient.java index c23e8b600b125d0a2da14dcec1880fb05598f42a..e06b4db54569d5ed46fdd138af3ded93e6fd1878 100644 --- a/base/common/src/com/netscape/certsrv/client/PKIClient.java +++ b/base/common/src/com/netscape/certsrv/client/PKIClient.java @@ -104,6 +104,12 @@ public class PKIClient { this.verbose = verbose; } + public X509Certificate getCert(String nickname) + throws NotInitializedException, ObjectNotFoundException, TokenException { + CryptoManager manager = CryptoManager.getInstance(); + return manager.findCertByNickname(nickname); + } + public X509Certificate[] getCerts() throws NotInitializedException { CryptoManager manager = CryptoManager.getInstance(); return manager.getPermCerts(); diff --git a/base/java-tools/man/man1/pki-client.1 b/base/java-tools/man/man1/pki-client.1 index 0364f84efb97a7263194799bf44ce625519311e1..87da255ff0fd5e385aec845f9364ad977d9f7aad 100644 --- a/base/java-tools/man/man1/pki-client.1 +++ b/base/java-tools/man/man1/pki-client.1 @@ -22,7 +22,9 @@ pki-client \- Command-Line Interface for managing the security database on Certi \fBpki\fR [CLI options] \fBclient-init\fR [command options] \fBpki\fR [CLI options] \fBclient-cert-find\fR [command options] \fBpki\fR [CLI options] \fBclient-cert-request\fR [command options] -\fBpki\fR [CLI options] \fBclient-cert-import\fR [command options] +\fBpki\fR [CLI options] \fBclient-cert-import\fR [nickname] [command options] +\fBpki\fR [CLI options] \fBclient-cert-mod\fR [command options] +\fBpki\fR [CLI options] \fBclient-cert-show\fR [command options] \fBpki\fR [CLI options] \fBclient-cert-del\fR [command options] .fi @@ -50,7 +52,17 @@ This command is to list certificates in the client security database. This command is to generate and submit a certificate request. .RE .PP -\fBpki\fR [CLI options] \fBclient-cert-import\fR [command options] +\fBpki\fR [CLI options] \fBclient-cert-import\fR [nickname] [command options] +.RS 4 +This command is to import a certificate into the client security database. +.RE +.PP +\fBpki\fR [CLI options] \fBclient-cert-mod\fR [command options] +.RS 4 +This command is to modify a certificate in the client security database. +.RE +.PP +\fBpki\fR [CLI options] \fBclient-cert-show\fR [command options] .RS 4 This command is to view a certificate in the client security database. .RE @@ -80,11 +92,15 @@ To request a certificate: To import a certificate from a file into the security database: -.B pki -d -c client-cert-import --cert +.B pki -d -c client-cert-import --cert To import a CA certificate from a file into the security database: -.B pki -d -c client-cert-import --ca-cert +.B pki -d -c client-cert-import --ca-cert + +To import certificates and private keys from a PKCS #12 file into the security database: + +.B pki -d -c client-cert-import --pkcs12 --pkcs12-password To import a certificate from CA server into the security database: @@ -94,6 +110,26 @@ To import a CA certificate from CA server into the security database: .B pki -d -c client-cert-import --ca-server +To modify a certificate's trust attributes in the security database: + +.B pki -d -c client-cert-mod --trust + +To display a certificate in the security database: + +.B pki -d -c client-cert-show + +To export a certificate from the security database into a PEM file: + +.B pki -d -c client-cert-show --cert + +To export a certificate chain with the private key from the security database into a PKCS #12 file: + +.B pki -d -c client-cert-show --pkcs12 --pkcs12-password + +To export a client certificate with the private key from the security database into a PEM file: + +.B pki -d -c client-cert-show --client-cert + To delete a certificate from the security database: .B pki -d -c client-cert-del 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 066a7d580553836df62f68188929afc4de20d536..8c3805e007b7384f0b073e92bad88076e39ab2b6 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 443d48bdfbe87253bb9f64e7eae5302c4dcce85c..c9c71521ab631a02d7c386bd4e1b38f8ecbc1e7f 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 5080c55ea0d2a47dc38e5d63367b5dc00840f5e6..afa91d65935e77a5ceda09d9c70dae335e130885 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() + " [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 }; + 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(commands); - + 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 0000000000000000000000000000000000000000..738dca07c3e5c98d89e821846d74a6cd45f64004 --- /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() + " [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 0000000000000000000000000000000000000000..bdd9462f3097c2213b665a4dd0c57413af0d049a --- /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() + " [OPTIONS...]", options); + } + + public void createOptions() { + Option option = new Option(null, "cert", true, "PEM file to store the certificate."); + option.setArgName("file"); + options.addOption(option); + + option = new Option(null, "client-cert", true, "PEM file to store the certificate and the private key."); + option.setArgName("file"); + options.addOption(option); + + option = new Option(null, "pkcs12", true, "PKCS #12 file to store the certificate chain and the private key."); + option.setArgName("password"); + 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); + } + } +} -- 1.8.4.2