From 03c82cbf2a7eacfa02f3e6f74fa3a26e70965159 Mon Sep 17 00:00:00 2001 From: "Endi S. Dewata" Date: Thu, 29 Jan 2015 03:08:25 -0500 Subject: [PATCH] Updated CRMFPopClient parameter handling. The CRMFPopClient has been modified to use Apache Commons CLI library to handle the parameters. The help message has been rewritten to make it more readable. The submitRequest() will now display the error reason. The options in ClientCertRequestCLI have been simplified. A new option was added to generate CRMF request without POP. https://fedorahosted.org/pki/ticket/1074 --- .../src/com/netscape/cmstools/CRMFPopClient.java | 447 ++++++++++++--------- .../src/com/netscape/cmstools/cli/MainCLI.java | 6 +- .../cmstools/client/ClientCertRequestCLI.java | 75 ++-- .../templates/pki_java_command_wrapper.in | 1 + 4 files changed, 312 insertions(+), 217 deletions(-) diff --git a/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java index dd20cba928ee8659cbfe749c4a30b3ab7c458114..ec4570b1f65928e31d59ee3bd711e4b26639a8b0 100644 --- a/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java +++ b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java @@ -34,6 +34,11 @@ import java.security.PublicKey; import netscape.security.x509.X500Name; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.PosixParser; import org.apache.commons.io.FileUtils; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.asn1.ASN1Util; @@ -94,187 +99,251 @@ public class CRMFPopClient { public boolean verbose; - private static void usage() { - - System.out.println("Usage: CRMFPopClient -d -p -h -o -n -a -l -c -m -f -u -r -q \n"); - System.out.println(" Optionally, for ECC key generation per definition in JSS pkcs11.PK11KeyPairGenerator:\n"); - System.out.println(" -k \n"); - System.out.println(" -t \n"); - System.out.println(" -s <1 for sensitive; 0 for non-sensitive; -1 temporaryPairMode dependent; default is -1>\n"); - System.out.println(" -e <1 for extractable; 0 for non-extractable; -1 token dependent; default is -1>\n"); - System.out.println(" Also optional for ECC key generation:\n"); - System.out.println(" -x \n"); - System.out.println(" --transport-cert \n"); - System.out.println(" note: '-x true' can only be used with POP_NONE"); - System.out.println(" available ECC curve names (if provided by the crypto module): nistp256 (secp256r1),nistp384 (secp384r1),nistp521 (secp521r1),nistk163 (sect163k1),sect163r1,nistb163 (sect163r2),sect193r1,sect193r2,nistk233 (sect233k1),nistb233 (sect233r1),sect239k1,nistk283 (sect283k1),nistb283 (sect283r1),nistk409 (sect409k1),nistb409 (sect409r1),nistk571 (sect571k1),nistb571 (sect571r1),secp160k1,secp160r1,secp160r2,secp192k1,nistp192 (secp192r1, prime192v1),secp224k1,nistp224 (secp224r1),secp256k1,prime192v2,prime192v3,prime239v1,prime239v2,prime239v3,c2pnb163v1,c2pnb163v2,c2pnb163v3,c2pnb176v1,c2tnb191v1,c2tnb191v2,c2tnb191v3,c2pnb208w1,c2tnb239v1,c2tnb239v2,c2tnb239v3,c2pnb272w1,c2pnb304w1,c2tnb359w1,c2pnb368w1,c2tnb431r1,secp112r1,secp112r2,secp128r1,secp128r2,sect113r1,sect113r2,sect131r1,sect131r2\n"); - - System.out.println("\n"); - System.out.println("IMPORTANT: The transport certificate file needs to be created to contain the"); - System.out.println(" transport certificate in its base64 encoded format."); + public static Options createOptions() { + + Options options = new Options(); + + Option option = new Option("d", true, "Security database location"); + option.setArgName("database"); + options.addOption(option); + + option = new Option("p", true, "Security token password"); + option.setArgName("password"); + options.addOption(option); + + option = new Option("h", true, "Security token name"); + option.setArgName("token"); + options.addOption(option); + + option = new Option("o", true, "Output file to store base-64 CRMF request"); + option.setArgName("output"); + options.addOption(option); + + option = new Option("n", true, "Subject DN"); + option.setArgName("subject DN"); + options.addOption(option); + + option = new Option("a", true, "Key algorithm"); + option.setArgName("algorithm"); + options.addOption(option); + + option = new Option("l", true, "Key length"); + option.setArgName("length"); + options.addOption(option); + + option = new Option("c", true, "ECC curve name"); + option.setArgName("curve"); + options.addOption(option); + + option = new Option("m", true, "CA server hostname and port"); + option.setArgName("hostname:port"); + options.addOption(option); + + option = new Option("f", true, "Certificate profile"); + option.setArgName("profile"); + options.addOption(option); + + option = new Option("u", true, "Username"); + option.setArgName("username"); + options.addOption(option); + + option = new Option("r", true, "Requestor"); + option.setArgName("requestor"); + options.addOption(option); + + option = new Option("q", true, "POP option"); + option.setArgName("POP option"); + options.addOption(option); + + option = new Option("b", true, "PEM transport certificate"); + option.setArgName("transport cert"); + options.addOption(option); + + option = new Option("k", true, "Attribute encoding"); + option.setArgName("boolean"); + options.addOption(option); + + option = new Option("x", true, "SSL certificate with ECDH ECDSA"); + option.setArgName("boolean"); + options.addOption(option); + + option = new Option("t", true, "Temporary"); + option.setArgName("boolean"); + options.addOption(option); + + option = new Option("s", true, "Sensitive"); + option.setArgName("sensitive"); + options.addOption(option); + + option = new Option("e", true, "Extractable"); + option.setArgName("extractable"); + options.addOption(option); + + options.addOption("v", "verbose", false, "Run in verbose mode."); + options.addOption(null, "help", false, "Show help message."); + + return options; + } + + public static void printHelp() { + + System.out.println("Usage: CRMFPopClient [OPTIONS]"); + System.out.println(); + System.out.println("Options:"); + System.out.println(" -d Security database location (default: current directory)"); + System.out.println(" -h Security token name (default: internal)"); + System.out.println(" -p Security token password"); + System.out.println(" -n Certificate subject DN"); + System.out.println(" -k Attribute value encoding in subject DN (default: false)"); + System.out.println(" - true: enabled"); + System.out.println(" - false: disabled"); + System.out.println(" -a Key algorithm (default: rsa)"); + System.out.println(" - rsa: RSA"); + System.out.println(" - ec: ECC"); + System.out.println(" -f Certificate profile"); + System.out.println(" - RSA default: caEncUserCert"); + System.out.println(" - ECC default: caEncECUserCert"); + System.out.println(" -q POP option (default: POP_SUCCESS)"); + System.out.println(" - POP_NONE"); + System.out.println(" - POP_SUCCESS"); + System.out.println(" - POP_FAIL"); + System.out.println(" -b PEM transport certificate (default: transport.txt)"); + System.out.println(" -v, --verbose Run in verbose mode."); + System.out.println(" --help Show help message."); + System.out.println(); + System.out.println("With RSA algorithm the following options can be specified:"); + System.out.println(" -l Key length (default: 2048)"); + System.out.println(); + System.out.println("With ECC algorithm the following options can be specified:"); + System.out.println(" -c ECC curve name (default: nistp256)"); + System.out.println(" -t Temporary (default: true)"); + System.out.println(" - true: temporary (session)"); + System.out.println(" - false: permanent (token)"); + System.out.println(" -s <-1|0|1> Sensitive (default: -1)"); + System.out.println(" - -1: temporaryPairMode dependent"); + System.out.println(" - 0: non-sensitive"); + System.out.println(" - 1: sensitive"); + System.out.println(" -e <-1|0|1> Extractable (default: -1)"); + System.out.println(" - -1: token dependent"); + System.out.println(" - 0: non-extractable"); + System.out.println(" - 1: extractable"); + System.out.println(" -x Certificate type (default: false)"); + System.out.println(" - true: SSL certificate with ECDH ECDSA (reqires POP_NONE)"); + System.out.println(" - false: otherwise"); + System.out.println(); + System.out.println("To store the CRMF request the following options are required:"); + System.out.println(" -o Output file to store base-64 CRMF request"); + System.out.println(); + System.out.println("To submit the CRMF request the following options are required:"); + System.out.println(" -m CA server hostname and port"); + System.out.println(" -u Username"); + System.out.println(" -r Requestor"); + System.out.println(); + System.out.println("Available ECC curve names:"); + System.out.println(" nistp256 (secp256r1), nistp384 (secp384r1), nistp521 (secp521r1), nistk163 (sect163k1),"); + System.out.println(" sect163r1, nistb163 (sect163r2), sect193r1, sect193r2, nistk233 (sect233k1),"); + System.out.println(" nistb233 (sect233r1), sect239k1, nistk283 (sect283k1), nistb283 (sect283r1),"); + System.out.println(" nistk409 (sect409k1), nistb409 (sect409r1),nistk571 (sect571k1), nistb571 (sect571r1),"); + System.out.println(" secp160k1, secp160r1, secp160r2, secp192k1, nistp192 (secp192r1, prime192v1),"); + System.out.println(" secp224k1, nistp224 (secp224r1), secp256k1, prime192v2, prime192v3, prime239v1,"); + System.out.println(" prime239v2, prime239v3, c2pnb163v1, c2pnb163v2, c2pnb163v3, c2pnb176v1, c2tnb191v1,"); + System.out.println(" c2tnb191v2, c2tnb191v3, c2pnb208w1, c2tnb239v1, c2tnb239v2, c2tnb239v3, c2pnb272w1,"); + System.out.println(" c2pnb304w1, c2tnb359w1, c2pnb368w1, c2tnb431r1, secp112r1, secp112r2, secp128r1,"); + System.out.println(" secp128r2, sect113r1, sect113r2, sect131r1, sect131r2"); + } + + public static void printError(String message) { + System.err.println("ERROR: " + message); + System.err.println("Try 'CRMFPopClient --help' for more information."); } public static void main(String args[]) throws Exception { + Options options = createOptions(); + CommandLine cmd = null; + + try { + CommandLineParser parser = new PosixParser(); + cmd = parser.parse(options, args); + + } catch (Exception e) { + printError(e.getMessage()); + System.exit(1); + } + + if (cmd.hasOption("help")) { + printHelp(); + System.exit(0); + } + CRMFPopClient client = new CRMFPopClient(); + client.verbose = cmd.hasOption("v"); - String databaseDir = "."; - String tokenPassword = null; - String tokenName = null; + String databaseDir = cmd.getOptionValue("d", "."); + String tokenPassword = cmd.getOptionValue("p"); + String tokenName = cmd.getOptionValue("h"); - // "rsa" or "ec" - String algorithm = "rsa"; + String algorithm = cmd.getOptionValue("a", "rsa"); + int keySize = Integer.parseInt(cmd.getOptionValue("l", "2048")); - /* default RSA key size */ - int keySize = 2048; + String profileID = cmd.getOptionValue("f"); + String subjectDN = cmd.getOptionValue("n"); + boolean encodingEnabled = Boolean.parseBoolean(cmd.getOptionValue("k", "false")); - /* default ECC key curve name */ - String curve = "nistp256"; + String transportCertFilename = cmd.getOptionValue("b", "transport.txt"); - boolean encodingEnabled = false; /* enable encoding attribute values if true */ - boolean temporary = true; /* session if true; token if false */ - int sensitive = -1; /* -1, 0, or 1 */ - int extractable = -1; /* -1, 0, or 1 */ - boolean sslECDH = false; + String popOption = cmd.getOptionValue("q", "POP_SUCCESS"); - String username = null; - String requestor = null; - String profileName = null; + String curve = cmd.getOptionValue("c", "nistp256"); + boolean sslECDH = Boolean.parseBoolean(cmd.getOptionValue("x", "false")); + boolean temporary = Boolean.parseBoolean(cmd.getOptionValue("t", "true")); + int sensitive = Integer.parseInt(cmd.getOptionValue("s", "-1")); + int extractable = Integer.parseInt(cmd.getOptionValue("e", "-1")); - // format: "host:port" - String hostPort = null; - String subjectDN = null; - boolean submitRequest = false; + String output = cmd.getOptionValue("o"); - // POP_NONE, POP_SUCCESS, or POP_FAIL - String popOption = "POP_SUCCESS"; - boolean withPop = true; + String hostPort = cmd.getOptionValue("m"); + String username = cmd.getOptionValue("u"); + String requestor = cmd.getOptionValue("r"); - String output = null; - String transportCertFilename = "transport.txt"; - - for (int i=0; i rdns = dn.getRDNs(); - 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); + 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) { @@ -325,7 +329,8 @@ public class ClientCertRequestCLI extends CLI { boolean sslECDH, boolean temporary, int sensitive, - int extractable + int extractable, + boolean withPop ) throws Exception { CryptoManager manager = CryptoManager.getInstance(); @@ -348,15 +353,17 @@ public class ClientCertRequestCLI extends CLI { CertRequest certRequest = client.createCertRequest(token, transportCert, algorithm, keyPair, subject); - Signature signer = client.createSigner(token, algorithm, keyPair); + ProofOfPossession pop = null; + if (withPop) { + Signature signer = client.createSigner(token, algorithm, keyPair); - ByteArrayOutputStream bo = new ByteArrayOutputStream(); - certRequest.encode(bo); - signer.update(bo.toByteArray()); + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + certRequest.encode(bo); + signer.update(bo.toByteArray()); + byte[] signature = signer.sign(); - byte[] signature = signer.sign(); - - ProofOfPossession pop = client.createPop(algorithm, signature); + pop = client.createPop(algorithm, signature); + } return client.createCRMFRequest(certRequest, pop); } diff --git a/base/java-tools/templates/pki_java_command_wrapper.in b/base/java-tools/templates/pki_java_command_wrapper.in index dbc4986160241ebe60bfe5538467982d5c393535..4474084cfe519d0adb1e1eb42ce0ddf323509666 100644 --- a/base/java-tools/templates/pki_java_command_wrapper.in +++ b/base/java-tools/templates/pki_java_command_wrapper.in @@ -131,6 +131,7 @@ fi JNI_JAR_DIR=`source /usr/share/pki/etc/pki.conf && source /etc/pki/pki.conf && echo $JNI_JAR_DIR` CP=${JNI_JAR_DIR}/jss4.jar +CP=/usr/share/java/commons-cli.jar:${CP} CP=/usr/share/java/commons-codec.jar:${CP} CP=/usr/share/java/commons-io.jar:${CP} CP=/usr/share/java/ldapjdk.jar:${CP} -- 1.8.4.2