[Pki-devel] [PATCH] 527 Added option to import client cert from CA.

Endi Sukma Dewata edewata at redhat.com
Wed Sep 10 00:32:55 UTC 2014


A new option has been added to the client-cert-import command to
import a certificate from CA by specifying the serial number.

The client-cert-import has also been modified to get the nickname
of the certificate to import from the CLI argument. For backward
compatibility, if no argument is specified the CLI will try to
get the nickname from the authentication option (-n).

Ticket #1152

-- 
Endi S. Dewata
-------------- next part --------------
From 81f4a954193f4dcc4567130023e7c5ee4448db1c Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata at redhat.com>
Date: Tue, 9 Sep 2014 15:02:47 -0400
Subject: [PATCH] Added option to import client cert from CA.

A new option has been added to the client-cert-import command to
import a certificate from CA by specifying the serial number.

The client-cert-import has also been modified to get the nickname
of the certificate to import from the CLI argument. For backward
compatibility, if no argument is specified the CLI will try to
get the nickname from the authentication option (-n).

Ticket #1152
---
 .../com/netscape/certsrv/client/ClientConfig.java  |  13 ++
 base/java-tools/man/man1/pki-client.1              |  26 +++-
 .../cmstools/client/ClientCertImportCLI.java       | 150 +++++++++++++--------
 3 files changed, 124 insertions(+), 65 deletions(-)

diff --git a/base/common/src/com/netscape/certsrv/client/ClientConfig.java b/base/common/src/com/netscape/certsrv/client/ClientConfig.java
index da4e3d780f1aa01a88061ed9af868cb4097b63a5..f59f7320ee427ddf0dcf21f50f2ed5f8f4029aa9 100644
--- a/base/common/src/com/netscape/certsrv/client/ClientConfig.java
+++ b/base/common/src/com/netscape/certsrv/client/ClientConfig.java
@@ -57,6 +57,19 @@ public class ClientConfig {
     String password;
     String messageFormat;
 
+    public ClientConfig() {
+    }
+
+    public ClientConfig(ClientConfig config) {
+        serverURI = config.serverURI;
+        certDatabase = config.certDatabase;
+        certNickname = config.certNickname;
+        certPassword = config.certPassword;
+        username = config.username;
+        password = config.password;
+        messageFormat = config.messageFormat;
+    }
+
     @XmlElement(name="ServerURI")
     public URI getServerURI() {
         return serverURI;
diff --git a/base/java-tools/man/man1/pki-client.1 b/base/java-tools/man/man1/pki-client.1
index 8978c8c44331c2bff38d6b22f4d198310d8353a6..0364f84efb97a7263194799bf44ce625519311e1 100644
--- a/base/java-tools/man/man1/pki-client.1
+++ b/base/java-tools/man/man1/pki-client.1
@@ -22,8 +22,8 @@ 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 <subject DN> [command options]
-\fBpki\fR [CLI options] \fBclient-cert-import\fR [command options]
-\fBpki\fR [CLI options] \fBclient-cert-del\fR [command options]
+\fBpki\fR [CLI options] \fBclient-cert-import\fR <nickname> [command options]
+\fBpki\fR [CLI options] \fBclient-cert-del\fR <nickname> [command options]
 .fi
 
 .SH DESCRIPTION
@@ -50,12 +50,12 @@ 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 view a certificate in the client security database.
 .RE
 .PP
-\fBpki\fR [CLI options] \fBclient-cert-del\fR [command options]
+\fBpki\fR [CLI options] \fBclient-cert-del\fR <nickname> [command options]
 .RS 4
 This command is to delete a certificate from the client security database.
 .RE
@@ -78,13 +78,25 @@ To request a certificate:
 
 .B pki -d <security database location> -c <security database password> client-cert-request <subject DN>
 
-To import a certificate into the security database:
+To import a certificate from a file into the security database:
 
-.B pki -d <security database location> -c <security database password> -n <certificate nickname> client-cert-import --cert <certificate file>
+.B pki -d <security database location> -c <security database password> client-cert-import <nickname> --cert <certificate file>
+
+To import a CA certificate from a file into the security database:
+
+.B pki -d <security database location> -c <security database password> client-cert-import <nickname> --ca-cert <CA certificate file>
+
+To import a certificate from CA server into the security database:
+
+.B pki -d <security database location> -c <security database password> client-cert-import <nickname> --serial <serial number>
+
+To import a CA certificate from CA server into the security database:
+
+.B pki -d <security database location> -c <security database password> client-cert-import <nickname> --ca-server
 
 To delete a certificate from the security database:
 
-.B pki -d <security database location> -c <security database password> client-cert-del <certificate nickname>
+.B pki -d <security database location> -c <security database password> client-cert-del <nickname>
 
 .SH AUTHORS
 Ade Lee <alee at redhat.com>, Endi Dewata <edewata at redhat.com>, and Matthew Harmsen <mharmsen at redhat.com>.
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 90e3d0a3e8c37ca22b177aab6f19703c225e7b2a..5080c55ea0d2a47dc38e5d63367b5dc00840f5e6 100644
--- a/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java
@@ -20,13 +20,19 @@ package com.netscape.cmstools.client;
 
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.net.URI;
 import java.util.Arrays;
 
 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.CertData;
 import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.PKIClient;
+import com.netscape.certsrv.dbs.certdb.CertId;
 import com.netscape.cmstools.cli.CLI;
 import com.netscape.cmstools.cli.MainCLI;
 
@@ -45,7 +51,7 @@ public class ClientCertImportCLI extends CLI {
     }
 
     public void printHelp() {
-        formatter.printHelp(getFullName() + " [OPTIONS...]", options);
+        formatter.printHelp(getFullName() + " <nickname> [OPTIONS...]", options);
     }
 
     public void createOptions() {
@@ -58,6 +64,14 @@ public class ClientCertImportCLI extends CLI {
         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.setArgName("serial number");
+        options.addOption(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 {
@@ -81,100 +95,120 @@ public class ClientCertImportCLI extends CLI {
 
         String[] cmdArgs = cmd.getArgs();
 
-        if (cmdArgs.length != 0) {
+        if (cmdArgs.length > 1) {
             System.err.println("Error: Too many arguments specified.");
             printHelp();
             System.exit(-1);
         }
 
-        byte[] bytes = null;
+        MainCLI mainCLI = (MainCLI)parent.getParent();
+
+        String nickname = null;
+
+        // Get nickname from command argument if specified.
+        if (cmdArgs.length > 0) {
+            nickname = cmdArgs[0];
+        }
+
+        // Otherwise, get nickname from authentication option -n.
+        // This code is used to provide backward compatibility.
+        // TODO: deprecate/remove this code in 10.3.
+        if (nickname == null) {
+            nickname = mainCLI.config.getCertNickname();
+        }
+
+        if (nickname == null) {
+            System.err.println("Error: Missing certificate nickname.");
+            System.exit(-1);
+        }
 
         String certPath = cmd.getOptionValue("cert");
         String caCertPath = cmd.getOptionValue("ca-cert");
         boolean importFromCAServer = cmd.hasOption("ca-server");
+        String serialNumber = cmd.getOptionValue("serial");
+        String trustAttributes = cmd.getOptionValue("trust", "u,u,u");
 
-        boolean isCACert = false;
+        File certFile;
 
         // load the certificate
         if (certPath != null) {
             if (verbose) System.out.println("Loading certificate from " + certPath + ".");
-            bytes = FileUtils.readFileToByteArray(new File(certPath));
-
+            certFile = new File(certPath);
 
         } else if (caCertPath != null) {
             if (verbose) System.out.println("Loading CA certificate from " + caCertPath + ".");
-            bytes = FileUtils.readFileToByteArray(new File(caCertPath));
+            certFile = new File(caCertPath);
 
-            isCACert = true;
+            trustAttributes = "CT,c,";
 
         } else if (importFromCAServer) {
 
             // late initialization
-            MainCLI mainCLI = (MainCLI)parent.parent;
             mainCLI.init();
 
             client = mainCLI.getClient();
-            ClientConfig config = client.getConfig();
+            URI serverURI = mainCLI.config.getServerURI();
 
-            String caServerURI = "http://" + config.getServerURI().getHost() + ":8080/ca";
+            String caServerURI = serverURI.getScheme() + "://" +
+                serverURI.getHost() + ":" + serverURI.getPort() + "/ca";
 
             if (verbose) System.out.println("Downloading CA certificate from " + caServerURI + ".");
-            bytes = client.downloadCACertChain(caServerURI);
+            byte[] bytes = client.downloadCACertChain(caServerURI);
 
-            isCACert = true;
+            certFile = File.createTempFile("pki-client-cert-import-", ".crt", mainCLI.certDatabase);
+            certFile.deleteOnExit();
 
-        } else {
-            System.err.println("Error: Missing certificate to import");
-            printHelp();
-            System.exit(-1);
-        }
-
-        MainCLI mainCLI = (MainCLI)parent.getParent();
-
-        if (mainCLI.config.getCertNickname() == null) {
-            System.err.println("Error: Certificate nickname is required.");
-            System.exit(-1);
-        }
-
-        File certDatabase = mainCLI.certDatabase;
-        File certFile = new File(certDatabase, "import.crt");
-
-        try {
             try (FileOutputStream out = new FileOutputStream(certFile)) {
                 out.write(bytes);
             }
 
-            String flag;
-            if (isCACert) {
-                if (verbose) System.out.println("Importing CA certificate.");
-                flag = "CT,c,";
-
-            } else {
-                if (verbose) System.out.println("Importing certificate.");
-                flag = "u,u,u";
-            }
+            trustAttributes = "CT,c,";
+
+        } else if (serialNumber != null) {
+
+            // connect to CA anonymously
+            ClientConfig config = new ClientConfig(mainCLI.config);
+            config.setCertDatabase(null);
+            config.setCertPassword(null);
+            config.setCertNickname(null);
+
+            PKIClient client = new PKIClient(config, null);
+            CertClient certClient = new CertClient(client, "ca");
+
+            CertData certData = certClient.getCert(new CertId(serialNumber));
 
-            String[] commands = {
-                    "/usr/bin/certutil", "-A",
-                    "-d", certDatabase.getAbsolutePath(),
-                    "-i", certFile.getAbsolutePath(),
-                    "-n", mainCLI.config.getCertNickname(),
-                    "-t", flag
-            };
-
-            Runtime rt = Runtime.getRuntime();
-            Process p = rt.exec(commands);
-
-            int rc = p.waitFor();
-            if (rc != 0) {
-                MainCLI.printMessage("Import failed");
-                return;
+            certFile = File.createTempFile("pki-client-cert-import-", ".crt", mainCLI.certDatabase);
+            certFile.deleteOnExit();
+
+            String encoded = certData.getEncoded();
+            try (PrintWriter out = new PrintWriter(new FileWriter(certFile))) {
+                out.write(encoded);
             }
 
-            MainCLI.printMessage("Imported certificate \"" + mainCLI.config.getCertNickname() + "\"");
+        } else {
+            System.err.println("Error: Missing certificate to import");
+            printHelp();
+            System.exit(-1);
+            return;
+        }
+
+        String[] commands = {
+                "/usr/bin/certutil", "-A",
+                "-d", mainCLI.certDatabase.getAbsolutePath(),
+                "-i", certFile.getAbsolutePath(),
+                "-n", nickname,
+                "-t", trustAttributes
+        };
 
-        } finally {
-            certFile.delete();
+        Runtime rt = Runtime.getRuntime();
+        Process p = rt.exec(commands);
+
+        int rc = p.waitFor();
+        if (rc != 0) {
+            MainCLI.printMessage("Import failed");
+            return;
         }
+
+        MainCLI.printMessage("Imported certificate \"" + nickname + "\"");
     }
 }
-- 
1.8.4.2



More information about the Pki-devel mailing list