From 3603670a8dea1de69f4cf6a154159eb33761dfed Mon Sep 17 00:00:00 2001 From: "Endi S. Dewata" Date: Fri, 5 Sep 2014 16:40:47 -0400 Subject: [PATCH] Added client-cert-request CLI. A new CLI has been added to simplify the process to request a user certificate for client certificate authentication. Ticket #1148 --- base/java-tools/bin/pki | 1 + base/java-tools/man/man1/pki-client.1 | 10 ++ base/java-tools/src/CMakeLists.txt | 10 +- .../src/com/netscape/cmstools/cert/CertCLI.java | 13 ++ .../cmstools/cert/CertRequestSubmitCLI.java | 17 +- .../src/com/netscape/cmstools/cli/MainCLI.java | 6 +- .../com/netscape/cmstools/client/ClientCLI.java | 1 + .../cmstools/client/ClientCertRequestCLI.java | 191 +++++++++++++++++++++ 8 files changed, 230 insertions(+), 19 deletions(-) create mode 100644 base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java diff --git a/base/java-tools/bin/pki b/base/java-tools/bin/pki index a9f9e5c1e0e74be21b90a9b8369cf97428994382..9fd757844c7f0205ec98d0ca88a7a5a013d9d63d 100644 --- a/base/java-tools/bin/pki +++ b/base/java-tools/bin/pki @@ -79,6 +79,7 @@ def run_java_cli(args): '/usr/share/java/jackson-jaxrs-providers/jackson-jaxrs-base.jar', '/usr/share/java/jackson-jaxrs-providers/jackson-jaxrs-json-provider.jar', '/usr/share/java/jaxb-api.jar', + '/usr/share/java/ldapjdk.jar', '/usr/share/java/servlet.jar', resteasy_lib + '/jaxrs-api.jar', resteasy_lib + '/resteasy-atom-provider.jar', diff --git a/base/java-tools/man/man1/pki-client.1 b/base/java-tools/man/man1/pki-client.1 index 9b92c66d6ab7d750d723f057ffe1e8350e09dfcc..8978c8c44331c2bff38d6b22f4d198310d8353a6 100644 --- a/base/java-tools/man/man1/pki-client.1 +++ b/base/java-tools/man/man1/pki-client.1 @@ -21,6 +21,7 @@ pki-client \- Command-Line Interface for managing the security database on Certi \fBpki\fR [CLI options] \fBclient\fR \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-del\fR [command options] .fi @@ -44,6 +45,11 @@ This command is to create a new security database for the client. This command is to list certificates in the client security database. .RE .PP +\fBpki\fR [CLI options] \fBclient-cert-request\fR [command options] +.RS 4 +This command is to generate and submit a certificate request. +.RE +.PP \fBpki\fR [CLI options] \fBclient-cert-import\fR [command options] .RS 4 This command is to view a certificate in the client security database. @@ -68,6 +74,10 @@ To view certificates in the security database: .B pki -d -c client-cert-find +To request a certificate: + +.B pki -d -c client-cert-request + To import a certificate into the security database: .B pki -d -c -n client-cert-import --cert diff --git a/base/java-tools/src/CMakeLists.txt b/base/java-tools/src/CMakeLists.txt index 7c0b695282b4a784a677a4d33b0f9ee3ce6a06c5..ade1ea2b15fa755ac8ddfdbdc022bafeb63bf967 100644 --- a/base/java-tools/src/CMakeLists.txt +++ b/base/java-tools/src/CMakeLists.txt @@ -8,6 +8,14 @@ find_file(JSS_JAR /usr/share/java ) +find_file(LDAPJDK_JAR + NAMES + ldapjdk.jar + PATHS + ${JAVA_LIB_INSTALL_DIR} + /usr/share/java +) + find_file(APACHE_COMMONS_CLI_JAR NAMES apache-commons-cli.jar @@ -94,7 +102,7 @@ javac(pki-tools-classes CLASSPATH ${PKI_NSUTIL_JAR} ${PKI_CMSUTIL_JAR} ${PKI_CERTSRV_JAR} ${XALAN_JAR} ${XERCES_JAR} - ${JSS_JAR} ${COMMONS_CODEC_JAR} ${COMMONS_IO_JAR} + ${JSS_JAR} ${LDAPJDK_JAR} ${COMMONS_CODEC_JAR} ${COMMONS_IO_JAR} ${APACHE_COMMONS_CLI_JAR} ${APACHE_COMMONS_LANG_JAR} ${JAXRS_API_JAR} ${RESTEASY_JAXRS_JAR} ${RESTEASY_ATOM_PROVIDER_JAR} ${HTTPCLIENT_JAR} ${HTTPCORE_JAR} 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 30a808b0675601be57ccc79215c1bc8aef35b36b..9ffa3ad4501bed4fc6102e5b80ab11113883d74e 100644 --- a/base/java-tools/src/com/netscape/cmstools/cert/CertCLI.java +++ b/base/java-tools/src/com/netscape/cmstools/cert/CertCLI.java @@ -26,6 +26,7 @@ import com.netscape.certsrv.cert.CertClient; import com.netscape.certsrv.cert.CertData; import com.netscape.certsrv.cert.CertDataInfo; import com.netscape.certsrv.cert.CertRequestInfo; +import com.netscape.certsrv.cert.CertRequestInfos; import com.netscape.certsrv.cert.CertReviewResponse; import com.netscape.cmstools.cli.CLI; import com.netscape.cmstools.cli.MainCLI; @@ -158,6 +159,18 @@ public class CertCLI extends CLI { } } + public static void printCertRequestInfos(CertRequestInfos infos) { + boolean first = true; + for (CertRequestInfo info : infos.getEntries()) { + if (first) { + first = false; + } else { + System.out.println(); + } + printCertRequestInfo(info); + } + } + public static void printCertRequestInfo(CertRequestInfo info) { System.out.println(" Request ID: " + info.getRequestId()); System.out.println(" Type: " + info.getRequestType()); diff --git a/base/java-tools/src/com/netscape/cmstools/cert/CertRequestSubmitCLI.java b/base/java-tools/src/com/netscape/cmstools/cert/CertRequestSubmitCLI.java index fe2b806b0c324a2790093702344a0f8ca00b5995..608490bb73d7df482d87e67e9c15322ddc2e5f5a 100644 --- a/base/java-tools/src/com/netscape/cmstools/cert/CertRequestSubmitCLI.java +++ b/base/java-tools/src/com/netscape/cmstools/cert/CertRequestSubmitCLI.java @@ -3,7 +3,6 @@ package com.netscape.cmstools.cert; import java.io.File; import java.io.FileNotFoundException; import java.util.Arrays; -import java.util.Collection; import java.util.Scanner; import javax.xml.bind.JAXBException; @@ -12,7 +11,6 @@ import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.ParseException; import com.netscape.certsrv.cert.CertEnrollmentRequest; -import com.netscape.certsrv.cert.CertRequestInfo; import com.netscape.certsrv.cert.CertRequestInfos; import com.netscape.cmstools.cli.CLI; import com.netscape.cmstools.cli.MainCLI; @@ -61,7 +59,7 @@ public class CertRequestSubmitCLI extends CLI { CertEnrollmentRequest erd = getEnrollmentRequest(cmdArgs[0]); CertRequestInfos cri = certCLI.certClient.enrollRequest(erd); MainCLI.printMessage("Submitted certificate request"); - printRequestInformation(cri); + CertCLI.printCertRequestInfos(cri); } catch (FileNotFoundException e) { System.err.println("Error: " + e.getMessage()); @@ -79,17 +77,4 @@ public class CertRequestSubmitCLI extends CLI { return CertEnrollmentRequest.fromXML(xml); } } - - private void printRequestInformation(CertRequestInfos cri) { - Collection allRequests = cri.getEntries(); - boolean first = true; - for (CertRequestInfo x : allRequests) { - if (first) { - first = false; - } else { - System.out.println(); - } - CertCLI.printCertRequestInfo(x); - } - } } 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 e7097e8cae952fac075cb8ac9386feb5d74be789..066a7d580553836df62f68188929afc4de20d536 100644 --- a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java +++ b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java @@ -489,10 +489,12 @@ public class MainCLI extends CLI { System.out.println(); } - // Do not call CryptoManager.initialize() on client-init and client-cert-import + // Do not call CryptoManager.initialize() on some commands // because otherwise the database will be locked. String command = cmdArgs[0]; - if (!command.equals("client-init") && !command.equals("client-cert-import")) { + if (!command.equals("client-init") && + !command.equals("client-cert-import") && + !command.equals("client-cert-request")) { 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 11ede895f727977b30381344146c2e55b3989a92..443d48bdfbe87253bb9f64e7eae5302c4dcce85c 100644 --- a/base/java-tools/src/com/netscape/cmstools/client/ClientCLI.java +++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCLI.java @@ -36,6 +36,7 @@ public class ClientCLI extends CLI { addModule(new ClientCertFindCLI(this)); addModule(new ClientCertImportCLI(this)); addModule(new ClientCertRemoveCLI(this)); + addModule(new ClientCertRequestCLI(this)); } public String getFullName() { diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java new file mode 100644 index 0000000000000000000000000000000000000000..f7d60f1f03ea45288473f88b6dcf369bcfd68629 --- /dev/null +++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java @@ -0,0 +1,191 @@ +// --- 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.util.Vector; + +import netscape.ldap.util.DN; +import netscape.ldap.util.RDN; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.io.FileUtils; + +import com.netscape.certsrv.cert.CertClient; +import com.netscape.certsrv.cert.CertEnrollmentRequest; +import com.netscape.certsrv.cert.CertRequestInfos; +import com.netscape.certsrv.profile.ProfileAttribute; +import com.netscape.certsrv.profile.ProfileInput; +import com.netscape.cmstools.cert.CertCLI; +import com.netscape.cmstools.cli.CLI; +import com.netscape.cmstools.cli.MainCLI; + +/** + * @author Endi S. Dewata + */ +public class ClientCertRequestCLI extends CLI { + + public ClientCLI clientCLI; + + public ClientCertRequestCLI(ClientCLI clientCLI) { + super("cert-request", "Request a certificate", clientCLI); + this.clientCLI = clientCLI; + + createOptions(); + } + + public void printHelp() { + formatter.printHelp(getFullName() + " [OPTIONS...]", options); + } + + public void createOptions() { + Option option = new Option(null, "algorithm", true, "Algorithm (default: rsa)"); + option.setArgName("algorithm"); + options.addOption(option); + + option = new Option(null, "length", true, "RSA key length (default: 1024)"); + option.setArgName("length"); + options.addOption(option); + + option = new Option(null, "profile", true, "Certificate profile (default: caUserCert)"); + option.setArgName("profile"); + options.addOption(option); + + options.addOption(null, "help", false, "Help"); + } + + 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); + } + + String[] cmdArgs = cmd.getArgs(); + + if (cmd.hasOption("help")) { + printHelp(); + System.exit(0); + } + + if (cmdArgs.length > 1) { + System.err.println("Error: Too many arguments specified."); + printHelp(); + System.exit(-1); + } + + if (cmdArgs.length < 1) { + System.err.println("Error: Missing subject DN."); + printHelp(); + System.exit(-1); + } + + String subjectDN = cmdArgs[0]; + + String algorithm = cmd.getOptionValue("algorithm", "rsa"); + String length = cmd.getOptionValue("length", "1024"); + String profileID = cmd.getOptionValue("profile", "caUserCert"); + String requestType = "pkcs10"; + + MainCLI mainCLI = (MainCLI)parent.getParent(); + File certDatabase = mainCLI.certDatabase; + + String password = mainCLI.config.getCertPassword(); + if (password == null) { + System.err.println("Error: Missing security database password."); + System.exit(-1); + } + + File csrFile = File.createTempFile("pki-client-cert-request-", ".csr", certDatabase); + csrFile.deleteOnExit(); + + String[] commands = { + "/usr/bin/PKCS10Client", + "-d", certDatabase.getAbsolutePath(), + "-p", password, + "-a", algorithm, + "-l", length, + "-o", csrFile.getAbsolutePath(), + "-n", subjectDN + }; + + Runtime rt = Runtime.getRuntime(); + Process p = rt.exec(commands); + + int rc = p.waitFor(); + if (rc != 0) { + MainCLI.printMessage("CSR generation failed"); + return; + } + + if (verbose) { + System.out.println("CSR generated: " + csrFile); + } + + String csr = FileUtils.readFileToString(csrFile); + + // late initialization + mainCLI.init(); + client = mainCLI.getClient(); + + CertClient certClient = new CertClient(client, "ca"); + + if (verbose) { + System.out.println("Retrieving " + profileID + " profile."); + } + + CertEnrollmentRequest request = certClient.getEnrollmentTemplate(profileID); + + ProfileInput kg = request.getInput("Key Generation"); + + ProfileAttribute typeAttr = kg.getAttribute("cert_request_type"); + typeAttr.setValue(requestType); + + ProfileAttribute csrAttr = kg.getAttribute("cert_request"); + csrAttr.setValue(csr); + + ProfileInput sn = request.getInput("Subject Name"); + + DN dn = new DN(subjectDN); + Vector rdns = dn.getRDNs(); + + for (int i=0; i< rdns.size(); i++) { + RDN rdn = (RDN)rdns.elementAt(i); + String type = rdn.getTypes()[0].toLowerCase(); + String value = rdn.getValues()[0]; + ProfileAttribute uidAttr = sn.getAttribute("sn_" + type); + uidAttr.setValue(value); + } + + if (verbose) { + System.out.println("Sending certificate request."); + } + + CertRequestInfos infos = certClient.enrollRequest(request); + + MainCLI.printMessage("Submitted certificate request"); + CertCLI.printCertRequestInfos(infos); + } +} -- 1.8.4.2