From a4682ceae6774956461edd03b2485bbacea445f4 Mon Sep 17 00:00:00 2001 From: mharmsen Date: Tue, 4 Oct 2011 01:17:41 +0000 Subject: Bugzilla Bug #688225 - (dogtagIPAv2.1) TRACKER: of the Dogtag fixes for freeIPA 2.1 git-svn-id: svn+ssh://svn.fedorahosted.org/svn/pki/tags/IPA_v2_RHEL_6_2_20111003@2252 c9f7a03b-bd48-0410-a16d-cbbf54688b0b --- .../java-tools/src/com/netscape/cmstools/AtoB.java | 140 +++ .../src/com/netscape/cmstools/AuditVerify.java | 322 ++++++ .../java-tools/src/com/netscape/cmstools/BtoA.java | 116 +++ .../src/com/netscape/cmstools/CMCEnroll.java | 456 ++++++++ .../src/com/netscape/cmstools/CMCRequest.java | 1100 ++++++++++++++++++++ .../src/com/netscape/cmstools/CMCResponse.java | 244 +++++ .../src/com/netscape/cmstools/CMCRevoke.java | 410 ++++++++ .../src/com/netscape/cmstools/CRMFPopClient.java | 646 ++++++++++++ .../src/com/netscape/cmstools/ExtJoiner.java | 98 ++ .../src/com/netscape/cmstools/GenExtKeyUsage.java | 98 ++ .../com/netscape/cmstools/GenIssuerAltNameExt.java | 130 +++ .../netscape/cmstools/GenSubjectAltNameExt.java | 130 +++ .../src/com/netscape/cmstools/HttpClient.java | 410 ++++++++ .../src/com/netscape/cmstools/OCSPClient.java | 270 +++++ .../src/com/netscape/cmstools/PKCS10Client.java | 269 +++++ .../src/com/netscape/cmstools/PKCS12Export.java | 301 ++++++ .../src/com/netscape/cmstools/PasswordCache.java | 879 ++++++++++++++++ .../src/com/netscape/cmstools/PrettyPrintCert.java | 233 +++++ .../src/com/netscape/cmstools/PrettyPrintCrl.java | 199 ++++ .../src/com/netscape/cmstools/TestCRLSigning.java | 135 +++ .../src/com/netscape/cmstools/TokenInfo.java | 99 ++ 21 files changed, 6685 insertions(+) create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/AtoB.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/AuditVerify.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/BtoA.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/CMCEnroll.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/CMCRequest.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/CMCResponse.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/CMCRevoke.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/ExtJoiner.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/GenExtKeyUsage.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/GenIssuerAltNameExt.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/GenSubjectAltNameExt.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/HttpClient.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/OCSPClient.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/PKCS10Client.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/PasswordCache.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/PrettyPrintCert.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/PrettyPrintCrl.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/TestCRLSigning.java create mode 100644 pki/base/java-tools/src/com/netscape/cmstools/TokenInfo.java (limited to 'pki/base/java-tools/src/com/netscape') diff --git a/pki/base/java-tools/src/com/netscape/cmstools/AtoB.java b/pki/base/java-tools/src/com/netscape/cmstools/AtoB.java new file mode 100644 index 000000000..bdeaee273 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/AtoB.java @@ -0,0 +1,140 @@ +// --- 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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools; + + +import java.io.*; + + +/** + * The AtoB class is a utility program designed to "translate" an ASCII + * BASE 64 encoded blob into a BINARY BASE 64 encoded blob. It assumes + * that the name of a data file is passed to the program via the command line, + * and that the contents contain a blob encoded in an ASCII BASE 64 + * format. Note that the data file may contain an optional "-----BEGIN" header + * and/or an optional "-----END" trailer. + * + *

+ * The program may be invoked as follows: + *

+ *
+ *      AtoB <input filename> <output filename>
+ *
+ *      NOTE:  <input filename>   must contain an ASCII
+ *                                BASE 64 encoded blob
+ *
+ *             <output filename>  contains a BINARY
+ *                                BASE 64 encoded blob
+ * 
+ * + * @version $Revision$, $Date$ + */ +public class AtoB { + // Define constants + public static final int ARGC = 2; + public static final String HEADER = "-----BEGIN"; + public static final String TRAILER = "-----END"; + + public static void main(String argv[]) { + + BufferedReader inputBlob = null; + String asciiBASE64BlobChunk = new String(); + String asciiBASE64Blob = new String(); + byte binaryBASE64Blob[] = null; + FileOutputStream outputBlob = null; + + // (1) Check that two arguments were submitted to the program + if (argv.length != ARGC) { + System.out.println("Usage: AtoB " + + " " + + ""); + return; + } + + // (2) Create a DataInputStream() object to the BASE 64 + // encoded blob contained within the file + // specified on the command line + try { + inputBlob = new BufferedReader(new InputStreamReader( + new BufferedInputStream( + new FileInputStream( + argv[0])))); + } catch (FileNotFoundException e) { + System.out.println("AtoB(): can''t find file " + + argv[0] + ":\n" + e); + return; + } + + // (3) Read the entire contents of the specified BASE 64 encoded + // blob into a String() object throwing away any + // headers beginning with HEADER and any trailers beginning + // with TRAILER + try { + while ((asciiBASE64BlobChunk = inputBlob.readLine()) != null) { + if (!(asciiBASE64BlobChunk.startsWith(HEADER)) && + !(asciiBASE64BlobChunk.startsWith(TRAILER))) { + asciiBASE64Blob += asciiBASE64BlobChunk.trim(); + } + } + } catch (IOException e) { + System.out.println("AtoB(): Unexpected BASE64 " + + "encoded error encountered in readLine():\n" + + e); + } + + // (4) Close the DataInputStream() object + try { + inputBlob.close(); + } catch (IOException e) { + System.out.println("AtoB(): Unexpected BASE64 " + + "encoded error encountered in close():\n" + e); + } + + // (5) Decode the ASCII BASE 64 blob enclosed in the + // String() object into a BINARY BASE 64 byte[] object + + binaryBASE64Blob = com.netscape.osutil.OSUtil.AtoB(asciiBASE64Blob); + + // (6) Finally, print the actual AtoB blob to the + // specified output file + try { + outputBlob = new FileOutputStream(argv[1]); + } catch (IOException e) { + System.out.println("AtoB(): unable to open file " + + argv[1] + " for writing:\n" + e); + return; + } + + try { + outputBlob.write(binaryBASE64Blob); + } catch (IOException e) { + System.out.println("AtoB(): I/O error " + + "encountered during write():\n" + + e); + } + + try { + outputBlob.close(); + } catch (IOException e) { + System.out.println("AtoB(): Unexpected error " + + "encountered while attempting to close() " + + argv[1] + ":\n" + e); + } + } +} + diff --git a/pki/base/java-tools/src/com/netscape/cmstools/AuditVerify.java b/pki/base/java-tools/src/com/netscape/cmstools/AuditVerify.java new file mode 100644 index 000000000..66a6a6cd8 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/AuditVerify.java @@ -0,0 +1,322 @@ +// --- 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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools; + + +import java.io.*; +import java.util.*; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.X509Certificate; +import org.mozilla.jss.crypto.ObjectNotFoundException; +import org.mozilla.jss.util.Base64InputStream; +import java.security.*; +import java.security.interfaces.*; +import netscape.security.x509.X509CertImpl; + +/** + * Tool for verifying signed audit logs + * + * @version $Revision$, $Date$ + */ +public class AuditVerify { + + private static void usage() { + System.out.println("Usage: AuditVerify -d -n -a [-P ] [-v]"); + System.exit(1); + } + + public static final String CRYPTO_PROVIDER = "Mozilla-JSS"; + + public static byte[] base64decode(String input) throws Exception { + return com.netscape.osutil.OSUtil.AtoB(input); + } + + // We always sign 0x0a as the line separator, regardless of what + // line separator characters are used in the log file. This helps + // signature verification be platform-independent. + private static final byte LINE_SEP_BYTE = 0x0a; + + private static void output(int linenum, String mesg) throws IOException { + System.out.println("Line " + linenum + ": " + mesg); + } + + private static void writeFile(String curfileName) { + System.out.println("======\nFile: " + curfileName + "\n======"); + } + + private static void writeSigStatus(int linenum, String sigStartFile, + int sigStartLine, String sigStopFile, int sigStopLine, String mesg) + throws IOException + { + output(linenum, mesg + ": signature of " + sigStartFile + ":" + + sigStartLine + " to " + sigStopFile + ":" + sigStopLine); + } + + private static class PrefixFilter implements FilenameFilter { + private String prefix; + public PrefixFilter(String prefix) { + this.prefix = prefix; + } + public boolean accept(File dir, String name) { + // look for cert* in this directory + return( name.indexOf(prefix + "cert") != -1 ); + } + } + + public static boolean validPrefix(String configDir, String prefix) + throws IOException + { + File dir = new File(configDir); + if( ! dir.isDirectory() ) { + System.out.println("ERROR: \"" + dir + "\" is not a directory"); + usage(); + } + + String matchingFiles[] = dir.list( new PrefixFilter(prefix) ); + + // prefix may be valid if at least one file matched the pattern + return (matchingFiles.length > 0); + } + + public static boolean isSigningCert(X509CertImpl cert) { + boolean[] keyUsage = null; + + try { + keyUsage = cert.getKeyUsage(); + } catch (Exception e) { + e.printStackTrace(); + } + return (keyUsage == null) ? false : keyUsage[0]; + } + + + public static void main(String args[]) { + try { + + String dbdir = null; + String logListFile = null; + String signerNick = null; + String prefix = null; + boolean verbose = false; + + for(int i = 0; i < args.length; ++i) { + if( args[i].equals("-d") ) { + if( ++i >= args.length ) usage(); + dbdir = args[i]; + } else if( args[i].equals("-a") ) { + if( ++i >= args.length ) usage(); + logListFile = args[i]; + } else if( args[i].equals("-n") ) { + if( ++i >= args.length ) usage(); + signerNick = args[i]; + } else if( args[i].equals("-P") ) { + if( ++i >= args.length ) usage(); + prefix = args[i]; + } else if( args[i].equals("-v") ) { + verbose = true; + } else { + System.out.println("Unrecognized argument(" + i + "): " + + args[i]); + usage(); + } + } + if( dbdir == null || logListFile == null || signerNick == null) { + System.out.println("Argument omitted"); + usage(); + } + + // get list of log files + Vector logFiles = new Vector(); + BufferedReader r = new BufferedReader(new FileReader(logListFile)); + String listLine; + while( (listLine = r.readLine()) != null ) { + StringTokenizer tok = new StringTokenizer(listLine, ","); + while( tok.hasMoreElements() ) { + logFiles.addElement( ((String)tok.nextElement()).trim()); + } + } + if( logFiles.size() == 0 ) { + System.out.println("Error: no log files listed in " + logListFile); + System.exit(1); + } + + // initialize crypto stuff + if( prefix == null ) { + if( ! validPrefix(dbdir, "")) { + System.out.println("ERROR: \"" + dbdir + + "\" does not contain any security databases"); + usage(); + } + CryptoManager.initialize(dbdir); + } else { + if( ! validPrefix(dbdir, prefix) ) { + System.out.println("ERROR: \"" + prefix + + "\" is not a valid prefix"); + usage(); + } + CryptoManager.initialize( + new CryptoManager.InitializationValues(dbdir, prefix, prefix, + "secmod.db") + ); + } + CryptoManager cm = CryptoManager.getInstance(); + X509Certificate signerCert = cm.findCertByNickname(signerNick); + + X509CertImpl cert_i = null; + if (signerCert != null) { + byte[] signerCert_b = signerCert.getEncoded(); + cert_i = new X509CertImpl(signerCert_b); + } else { + System.out.println("ERROR: signing certificate not found"); + System.exit(1); + } + + // verify signer's certificate + // not checking validity because we want to allow verifying old logs + // + if (!isSigningCert(cert_i)) { + System.out.println("info: signing certificate is not a signing certificate"); + System.exit(1); + } + + PublicKey pubk = signerCert.getPublicKey(); + String sigAlgorithm=null; + if( pubk instanceof RSAPublicKey ) { + sigAlgorithm = "SHA-256/RSA"; + } else if( pubk instanceof DSAPublicKey ) { + sigAlgorithm = "SHA-256/DSA"; + } else { + System.out.println("Error: unknown key type: " + + pubk.getAlgorithm()); + System.exit(1); + } + Signature sig = Signature.getInstance(sigAlgorithm, CRYPTO_PROVIDER); + sig.initVerify(pubk); + + int goodSigCount = 0; + int badSigCount = 0; + + int lastFileWritten = -1; + + int sigStartLine = 1; + int sigStopLine = 1; + String sigStartFile = (String) logFiles.elementAt(0); + String sigStopFile = null; + int signedLines = 1; + + boolean lastLineWasSig = false; + + for( int curfile = 0; curfile < logFiles.size(); ++curfile) { + String curfileName = (String) logFiles.elementAt(curfile); + BufferedReader br = new BufferedReader(new FileReader(curfileName)); + + if( verbose ) { + writeFile(curfileName); + lastFileWritten = curfile; + } + + String curLine; + int linenum = 0; + while( (curLine = br.readLine()) != null ) { + ++linenum; + if( curLine.indexOf("AUDIT_LOG_SIGNING") != -1 ) { + if( curfile == 0 && linenum == 1 ) { + // Ignore the first signature of the first file, + // since it signs data we don't have access to. + if( verbose ) { + output(linenum, + "Ignoring first signature of log series"); + } + } else { + int sigStart = curLine.indexOf("sig: ") + 5; + if( sigStart < 5 ) { + output(linenum, "INVALID SIGNATURE"); + ++badSigCount; + } else { + byte[] logSig = + base64decode(curLine.substring(sigStart)); + + // verify the signature + if( sig.verify(logSig) ) { + // signature verifies correctly + if( verbose ) { + writeSigStatus(linenum, sigStartFile, + sigStartLine, sigStopFile, sigStopLine, + "verification succeeded"); + } + ++goodSigCount; + } else { + if( lastFileWritten < curfile ) { + writeFile(curfileName); + lastFileWritten = curfile; + } + writeSigStatus(linenum, sigStartFile, + sigStartLine, sigStopFile, sigStopLine, + "VERIFICATION FAILED"); + ++badSigCount; + } + } + sig.initVerify(pubk); + signedLines = 0; + sigStartLine = linenum; + sigStartFile = curfileName; + } + } + + byte[] lineBytes = curLine.getBytes("UTF-8"); + sig.update(lineBytes); + sig.update(LINE_SEP_BYTE); + ++signedLines; + sigStopLine = linenum; + sigStopFile = curfileName; + } + + } + + // Make sure there were no unsigned log entries at the end. + // The first signed line is the previous signature, but anything + // more than that is data. + if( signedLines > 1 ) { + System.out.println( + "ERROR: log entries after " + sigStartFile + + ":" + sigStartLine + " are UNSIGNED"); + badSigCount++; + } + + System.out.println("\nVerification process complete."); + System.out.println("Valid signatures: " + goodSigCount); + System.out.println("Invalid signatures: " + badSigCount); + + if( badSigCount > 0 ) { + System.exit(2); + } else { + System.exit(0); + } + + } catch(FileNotFoundException fnfe) { + System.out.println(fnfe); + } catch(ObjectNotFoundException onfe) { + System.out.println("ERROR: certificate not found"); + } catch(Exception e) { + e.printStackTrace(); + } + + System.out.println("Verification process FAILED."); + System.exit(1); + } +} diff --git a/pki/base/java-tools/src/com/netscape/cmstools/BtoA.java b/pki/base/java-tools/src/com/netscape/cmstools/BtoA.java new file mode 100644 index 000000000..d00fb6122 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/BtoA.java @@ -0,0 +1,116 @@ +// --- 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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools; + + +import java.io.*; + + +/** + * The BtoA class is a utility program designed to "translate" a BINARY + * BASE 64 encoded blob into an ASCII BASE 64 encoded blob. It assumes + * that the name of a data file is passed to the program via the command line, + * and that the contents contain a blob encoded in a BINARY BASE 64 + * format. + * + *

+ * The program may be invoked as follows: + *

+ *
+ *      BtoA <input filename> <output filename>
+ *
+ *      NOTE:  <input filename>   must contain a BINARY
+ *                                BASE 64 encoded blob
+ *
+ *             <output filename>  contains an ASCII
+ *                                BASE 64 encoded blob
+ * 
+ * + * @version $Revision$, $Date$ + */ +public class BtoA { + // Define constants + public static final int ARGC = 2; + + public static void main(String argv[]) { + + FileInputStream inputBlob = null; + FileOutputStream outputBlob = null; + + // (1) Check that two arguments were submitted to the program + if (argv.length != ARGC) { + System.out.println("Usage: BtoA " + + " " + + ""); + return; + } + + // (2) Create a DataInputStream() object to the BASE 64 + // encoded blob contained within the file + // specified on the command line + try { + inputBlob = new FileInputStream(argv[0]); + } catch (FileNotFoundException e) { + System.out.println("BtoA(): can''t find file " + + argv[0] + ":\n" + e); + return; + } + + // (3) Create a FileOutputStream() object to the BASE 64 + // specified output file + try { + outputBlob = new FileOutputStream(argv[1]); + } catch (IOException e) { + System.out.println("BtoA(): unable to open file " + + argv[1] + " for writing:\n" + e); + return; + } + + // (4) Convert the BINARY BASE 64 blob into an ASCII BASE 64 blob + + try { + byte data[] = new byte[inputBlob.available()]; + inputBlob.read(data); + String out = com.netscape.osutil.OSUtil.BtoA(data); + outputBlob.write(out.getBytes()); + } catch (IOException e) { + System.out.println("BtoA(): Unexpected BASE64 " + + "encoded error encountered:\n" + + e); + } + + // (5) Close the DataInputStream() object + try { + inputBlob.close(); + } catch (IOException e) { + System.out.println("BtoA(): Unexpected input error " + + "encountered while attempting to close() " + + argv[0] + ":\n" + e); + } + + // (6) Close the FileOutputStream() object + try { + outputBlob.close(); + } catch (IOException e) { + System.out.println("BtoA(): Unexpected output error " + + "encountered while attempting to close() " + + argv[1] + ":\n" + e); + } + } +} + diff --git a/pki/base/java-tools/src/com/netscape/cmstools/CMCEnroll.java b/pki/base/java-tools/src/com/netscape/cmstools/CMCEnroll.java new file mode 100644 index 000000000..23c6547b4 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/CMCEnroll.java @@ -0,0 +1,456 @@ +// --- 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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools; + + +import org.mozilla.jss.pkix.cmc.*; +import org.mozilla.jss.pkix.cms.*; +import org.mozilla.jss.pkix.cert.*; +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.pkcs10.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.SignatureAlgorithm; +import org.mozilla.jss.crypto.DigestAlgorithm; +import org.mozilla.jss.crypto.X509Certificate; +import org.mozilla.jss.util.*; + +import org.mozilla.jss.*; + +import netscape.security.util.*; +import netscape.security.x509.*; +import netscape.security.pkcs.PKCS10; + +import java.security.*; +import java.security.cert.CertificateException; +import java.math.*; +import java.security.Principal; +import java.lang.*; +import java.lang.reflect.*; +import java.io.*; +import java.util.*; + + + +/** + * Tool for signing PKCS #10 , return CMC enrollment request + * + *

+ * @version $Revision$, $Date$ + + */ +public class CMCEnroll { + + public static final String PR_REQUEST_CMC = "CMC"; + public static final String PR_REQUEST_PKCS10 = "PKCS10"; + + public static final int ARGC = 4; + private static final String CERTDB = "cert8.db"; + private static final String KEYDB = "key3.db"; + public static final String HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----"; + public static final String TRAILER = "-----END NEW CERTIFICATE REQUEST-----"; + + void cleanArgs(String[] s) { + + } + + public static X509Certificate getCertificate(String tokenname, + String nickname) throws Exception { + CryptoManager manager = CryptoManager.getInstance(); + CryptoToken token = null; + + if (tokenname.equals("internal")) { + token = manager.getInternalKeyStorageToken(); + } else { + token = manager.getTokenByName(tokenname); + } + StringBuffer certname = new StringBuffer(); + + if (!token.equals(manager.getInternalKeyStorageToken())) { + certname.append(tokenname); + certname.append(":"); + } + certname.append(nickname); + try { + return manager.findCertByNickname(certname.toString()); + } catch (ObjectNotFoundException e) { + throw new IOException("Signing Certificate not found"); + } + } + + public static java.security.PrivateKey getPrivateKey(String tokenname, String nickname) + throws Exception { + + X509Certificate cert = getCertificate(tokenname, nickname); + + return CryptoManager.getInstance().findPrivKeyByCert(cert); + } + + + /** + * getCMCBlob create and return the enrollent request. + *

+ * @param signerCert the certificate of the authorized signer of the CMC revocation request. + * @param manager the crypto manger. + * @param nValue the nickname of the certificate inside the token. + * @param rValue request PKCS#10 file name. + * @return the CMC revocation request encoded in base64 + */ + static String getCMCBlob(X509Certificate signerCert,CryptoManager manager, String nValue, String rValue) { + + String asciiBASE64Blob = rValue; // input pkcs10 blob + String tokenname = "internal"; + + try { + + java.security.PrivateKey privKey = null; + PKCS10 pkcs = null; + SignerIdentifier si = null; + ContentInfo fullEnrollmentReq = null; + + try { + byte[] decodedBytes = com.netscape.osutil.OSUtil.AtoB(asciiBASE64Blob); + + pkcs = new PKCS10(decodedBytes); + } catch (IOException e) { + throw new IOException("Internal Error - " + e.toString()); + } catch (SignatureException e) { + throw new IOException("Internal Error - " + e.toString()); + } catch (NoSuchAlgorithmException e) { + throw new IOException("Internal Error - " + e.toString()); + } + + String hasSki = "true"; + + BigInteger serialno = signerCert.getSerialNumber(); + byte[] certB = signerCert.getEncoded(); + X509CertImpl impl = new X509CertImpl(certB); + X500Name issuerName = (X500Name) impl.getIssuerDN(); + byte[] issuerByte = issuerName.getEncoded(); + ByteArrayInputStream istream = new ByteArrayInputStream(issuerByte); + + Name issuer = (Name) Name.getTemplate().decode(istream); + IssuerAndSerialNumber ias = new IssuerAndSerialNumber(issuer, new INTEGER(serialno.toString())); + + si = new SignerIdentifier(SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias, null); + privKey = getPrivateKey(tokenname, nValue); + + // create CMC req + // transfer pkcs10 to jss class + int bpid = 1; + ByteArrayInputStream crInputStream = new ByteArrayInputStream(pkcs.toByteArray()); + CertificationRequest cr = (CertificationRequest) CertificationRequest.getTemplate().decode(crInputStream); + + TaggedCertificationRequest tcr = new + TaggedCertificationRequest(new + INTEGER(bpid++), cr); + TaggedRequest trq = new + TaggedRequest(TaggedRequest.PKCS10, tcr, + null); + + SEQUENCE reqSequence = new SEQUENCE(); + + reqSequence.addElement(trq); + + // Add some control sequence + // Verisign has transactionID,senderNonce + SEQUENCE controlSeq = new SEQUENCE(); + + Date date = new Date(); + String salt = "lala123" + date.toString(); + byte[] dig; + + try { + MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1"); + + dig = SHA1Digest.digest(salt.getBytes()); + } catch (NoSuchAlgorithmException ex) { + dig = salt.getBytes(); + } + + String sn = com.netscape.osutil.OSUtil.BtoA(dig); + + TaggedAttribute senderNonce = new TaggedAttribute(new + INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_senderNonce, + new OCTET_STRING(sn.getBytes())); + + controlSeq.addElement(senderNonce); + + // Verisign recommend transactionId be MD5 hash of publicKey + byte[] transId; + + try { + MessageDigest MD5Digest = MessageDigest.getInstance("MD5"); + + transId = MD5Digest.digest(pkcs.getSubjectPublicKeyInfo().getKey()); + } catch (Exception ex) { + transId = salt.getBytes(); + } + + TaggedAttribute transactionId = new TaggedAttribute(new + INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_transactionId, + new INTEGER(1, transId)); + + controlSeq.addElement(transactionId); + + PKIData pkidata = new PKIData(controlSeq, reqSequence, new SEQUENCE(), new SEQUENCE()); + + EncapsulatedContentInfo ci = new + EncapsulatedContentInfo(OBJECT_IDENTIFIER.id_cct_PKIData, + pkidata); + // SHA1 is the default digest Alg for now. + DigestAlgorithm digestAlg = null; + SignatureAlgorithm signAlg = SignatureAlgorithm.RSASignatureWithSHA1Digest; + org.mozilla.jss.crypto.PrivateKey.Type signingKeyType = ((org.mozilla.jss.crypto.PrivateKey) privKey).getType(); + + if (signingKeyType.equals(org.mozilla.jss.crypto.PrivateKey.Type.DSA)) + signAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest; + MessageDigest SHADigest = null; + byte[] digest = null; + + try { + SHADigest = MessageDigest.getInstance("SHA1"); + digestAlg = DigestAlgorithm.SHA1; + + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + + pkidata.encode((OutputStream) ostream); + digest = SHADigest.digest(ostream.toByteArray()); + } catch (NoSuchAlgorithmException e) { + } + SignerInfo signInfo = new + SignerInfo(si, null, null, OBJECT_IDENTIFIER.id_cct_PKIData, digest, signAlg, + (org.mozilla.jss.crypto.PrivateKey) privKey); + SET signInfos = new SET(); + + signInfos.addElement(signInfo); + + SET digestAlgs = new SET(); + + if (digestAlg != null) { + AlgorithmIdentifier ai = new AlgorithmIdentifier(digestAlg.toOID(), null); + + digestAlgs.addElement(ai); + } + + org.mozilla.jss.crypto.X509Certificate[] agentChain = manager.buildCertificateChain(signerCert); + SET certs = new SET(); + + for (int i = 0; i < agentChain.length; i++) { + ANY cert = new ANY(agentChain[i].getEncoded()); + + certs.addElement(cert); + } + SignedData req = new SignedData(digestAlgs, ci, certs, null, signInfos); + + fullEnrollmentReq = new + ContentInfo(req); + + ByteArrayOutputStream bs = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(bs); + + if (fullEnrollmentReq != null) { + // format is PR_REQUEST_CMC + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + fullEnrollmentReq.encode(os); + ps.print(com.netscape.osutil.OSUtil.BtoA(os.toByteArray())); + //fullEnrollmentReq.print(ps); // no header/trailer + } else { + // format is PR_REQUEST_PKCS10 + pkcs.print(ps); + } + asciiBASE64Blob = bs.toString(); + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + return asciiBASE64Blob; + } + + /** Creates a new instance of CMCEnroll */ + public static void main(String[]s) { + + String dValue = null, nValue = null, rValue = null, pValue = null; + FileOutputStream outputBlob = null; + + // default path is "." + String mPath = "."; + // default prefix is "" + String mPrefix = ""; + + boolean bWrongParam = false; + + // (1) Check that two arguments were submitted to the program + if (s.length != (ARGC * 2)) { + System.out.println("Wrong number of parameters:" + s.length); + System.out.println("Usage: CMCEnroll " + + "-d

" + + "-n " + + "-r " + + "-p " + ); + bWrongParam = true; + }else { + int length; + int i; + + length = s.length; + for (i = 0; i < length; i++) { + if (s[i].equals("-d")) { + dValue = s[i + 1]; + } else if (s[i].equals("-n")) { + nValue = s[i + 1]; + } else if (s[i].equals("-r")) { + rValue = s[i + 1]; + } else if (s[i].equals("-p")) { + pValue = s[i + 1]; + } + if (s[i].equals("")) + bWrongParam = true; + + } + + if (dValue == null || nValue == null || rValue == null || pValue == null ) + bWrongParam = true; + else if (dValue.length() == 0 || nValue.length() == 0 || rValue.length() == 0 || + pValue.length() == 0 ) + bWrongParam = true; + if (bWrongParam == true) { + System.out.println("Usage: CMCEnroll " + + "-d " + + "-n " + + "-r " + + "-p " + ); + System.exit(0); + } + + try { + // initialize CryptoManager + mPath = dValue; + System.out.println("cert/key prefix = " + mPrefix); + System.out.println("path = " + mPath); + CryptoManager.InitializationValues vals = + new CryptoManager.InitializationValues(mPath, mPrefix, + mPrefix, "secmod.db"); + + CryptoManager.initialize(vals); + + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = cm.getInternalKeyStorageToken(); + Password pass = new Password(pValue.toCharArray()); + + token.login(pass); + CryptoStore store = token.getCryptoStore(); + X509Certificate[] list = store.getCertificates(); + X509Certificate signerCert = null; + + signerCert = cm.findCertByNickname(nValue); + + BufferedReader inputBlob = null; + + try { + inputBlob = new BufferedReader(new InputStreamReader( + new BufferedInputStream( + new FileInputStream( + rValue)))); + } catch (FileNotFoundException e) { + System.out.println("CMCEnroll: can''t find file " + + rValue + ":\n" + e); + return; + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + // (3) Read the entire contents of the specified BASE 64 encoded + // blob into a String() object throwing away any + // headers beginning with HEADER and any trailers beginning + // with TRAILER + String asciiBASE64BlobChunk = new String(); + String asciiBASE64Blob = new String(); + + try { + while ((asciiBASE64BlobChunk = inputBlob.readLine()) != null) { + if (!(asciiBASE64BlobChunk.startsWith(HEADER)) && + !(asciiBASE64BlobChunk.startsWith(TRAILER))) { + asciiBASE64Blob += asciiBASE64BlobChunk.trim(); + } + } + } catch (IOException e) { + System.out.println("CMCEnroll: Unexpected BASE64 " + + "encoded error encountered in readLine():\n" + + e); + } + // (4) Close the DataInputStream() object + try { + inputBlob.close(); + } catch (IOException e) { + System.out.println("CMCEnroll(): Unexpected BASE64 " + + "encoded error encountered in close():\n" + e); + } + + asciiBASE64Blob = getCMCBlob(signerCert,cm, nValue, asciiBASE64Blob ); + // (5) Decode the ASCII BASE 64 blob enclosed in the + // String() object into a BINARY BASE 64 byte[] object + byte binaryBASE64Blob[] = null; + + binaryBASE64Blob = com.netscape.osutil.OSUtil.AtoB(asciiBASE64Blob); + + // (6) Finally, print the actual CMCEnroll blob to the + // specified output file + try { + outputBlob = new FileOutputStream(rValue + ".out"); + } catch (IOException e) { + System.out.println("CMCEnroll: unable to open file " + + rValue + ".out" + " for writing:\n" + e); + return; + } + + System.out.println(HEADER); + System.out.println(asciiBASE64Blob + TRAILER); + try { + asciiBASE64Blob = HEADER + "\n" + asciiBASE64Blob + TRAILER; + outputBlob.write(asciiBASE64Blob.getBytes()); + } catch (IOException e) { + System.out.println("CMCEnroll: I/O error " + + "encountered during write():\n" + + e); + } + + try { + outputBlob.close(); + } catch (IOException e) { + System.out.println("CMCEnroll: Unexpected error " + + "encountered while attempting to close() " + + "\n" + e); + } + + }catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + + return; + } + } +} diff --git a/pki/base/java-tools/src/com/netscape/cmstools/CMCRequest.java b/pki/base/java-tools/src/com/netscape/cmstools/CMCRequest.java new file mode 100644 index 000000000..9c5b74c05 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/CMCRequest.java @@ -0,0 +1,1100 @@ +// --- 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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools; + + +import org.mozilla.jss.pkix.cmc.*; +import org.mozilla.jss.pkix.cms.*; +import org.mozilla.jss.pkix.cert.*; +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.pkcs10.*; +import org.mozilla.jss.pkcs11.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.pkix.crmf.*; +import org.mozilla.jss.pkix.cmmf.*; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.SignatureAlgorithm; +import org.mozilla.jss.crypto.DigestAlgorithm; +import org.mozilla.jss.crypto.X509Certificate; +import org.mozilla.jss.util.*; + +import org.mozilla.jss.*; + +import netscape.security.util.*; +import netscape.security.x509.*; +import netscape.security.pkcs.PKCS10; + +import java.security.*; +import java.security.cert.CertificateException; +import java.math.*; +import java.security.Principal; +import java.lang.*; +import java.lang.reflect.*; +import java.io.*; +import java.util.*; + +import com.netscape.cmsutil.util.*; + + +/** + * Tool for creating CMC full request + * + *

+ * @version $Revision$, $Date$ + * + */ +public class CMCRequest { + + public static final String PR_REQUEST_CMC = "CMC"; + public static final String PR_REQUEST_CRMF = "CRMF"; + + public static final int ARGC = 1; + private static final String CERTDB = "cert8.db"; + private static final String KEYDB = "key3.db"; + public static final String HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----"; + public static final String TRAILER = "-----END NEW CERTIFICATE REQUEST-----"; + + void cleanArgs(String[] s) { + + } + + public static X509Certificate getCertificate(String tokenname, + String nickname) throws Exception { + CryptoManager manager = CryptoManager.getInstance(); + CryptoToken token = null; + + if (tokenname.equals("internal")) { + token = manager.getInternalKeyStorageToken(); + } else { + token = manager.getTokenByName(tokenname); + } + StringBuffer certname = new StringBuffer(); + + if (!token.equals(manager.getInternalKeyStorageToken())) { + certname.append(tokenname); + certname.append(":"); + } + certname.append(nickname); + try { + return manager.findCertByNickname(certname.toString()); + } catch (ObjectNotFoundException e) { + throw new IOException("Signing Certificate not found"); + } + } + + public static java.security.PrivateKey getPrivateKey(String tokenname, String nickname) + throws Exception { + + X509Certificate cert = getCertificate(tokenname, nickname); + + return CryptoManager.getInstance().findPrivKeyByCert(cert); + } + + + /** + * getCMCBlob create and return the enrollent request. + *

+ * @param signerCert the certificate of the authorized signer of the CMC revocation request. + * @param nickname the nickname of the certificate inside the token. + * @param rValue CRMF/PKCS10 request. + * @param format either crmf or pkcs10 + * @return the CMC enrollment request encoded in base64 + */ + static ContentInfo getCMCBlob(X509Certificate signerCert, String nickname, + String[] rValue, String format, CryptoManager manager, String transactionMgtEnable, + String transactionMgtId, String identityProofEnable, String identityProofSharedSecret, + SEQUENCE controlSeq, SEQUENCE otherMsgSeq, int bpid) { + + String tokenname = "internal"; + + ContentInfo fullEnrollmentReq = null; + try { + java.security.PrivateKey privKey = null; + SignerIdentifier si = null; + + BigInteger serialno = signerCert.getSerialNumber(); + byte[] certB = signerCert.getEncoded(); + X509CertImpl impl = new X509CertImpl(certB); + X500Name issuerName = (X500Name) impl.getIssuerDN(); + byte[] issuerByte = issuerName.getEncoded(); + ByteArrayInputStream istream = new ByteArrayInputStream(issuerByte); + + Name issuer = (Name) Name.getTemplate().decode(istream); + IssuerAndSerialNumber ias = new IssuerAndSerialNumber( + issuer, new INTEGER(serialno.toString())); + + si = new SignerIdentifier( + SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias, null); + privKey = getPrivateKey(tokenname, nickname); + + TaggedRequest trq = null; + PKCS10 pkcs = null; + CertReqMsg certReqMsg = null; + + // create CMC req + SEQUENCE reqSequence = new SEQUENCE(); + try { + for (int k=0; k"); + System.out.println("For example, CMCRequest CMCRequest.cfg"); + System.out.println(""); + System.out.println("The configuration file should look like as follows:"); + System.out.println(""); + System.out.println("#numRequests: Total number of PKCS10 requests or CRMF requests."); + System.out.println("numRequests=1"); + System.out.println(""); + System.out.println("#input: full path for the PKCS10 request or CRMF request,"); + System.out.println("#the content must be in Base-64 encoded format"); + System.out.println("#Multiple files are supported. They must be separated by space."); + System.out.println("input=crmf1"); + System.out.println(""); + System.out.println("#output: full path for the CMC request in binary format"); + System.out.println("output=/u/doc/cmcReq"); + System.out.println(""); + System.out.println("#nickname: nickname for agent certificate which will be used"); + System.out.println("#to sign the CMC full request."); + System.out.println("nickname=CMS Agent Certificate"); + System.out.println(""); + System.out.println("#dbdir: directory for cert8.db, key3.db and secmod.db"); + System.out.println("dbdir=/u/smith/.netscape"); + System.out.println(""); + System.out.println("#password: password for cert8.db which stores the agent"); + System.out.println("#certificate"); + System.out.println("password=pass"); + System.out.println(""); + System.out.println("#format: request format, either pkcs10 or crmf"); + System.out.println("format=crmf"); + System.out.println(""); + System.out.println("#confirmCertAcceptance.enable: if true, then the request will"); + System.out.println("#contain this control. Otherwise, false."); + System.out.println("confirmCertAcceptance.enable=true"); + System.out.println(""); + System.out.println("#confirmCertAcceptance.serial: The serial number for"); + System.out.println("#confirmCertAcceptance control"); + System.out.println("confirmCertAcceptance.serial=3"); + System.out.println(""); + System.out.println("#confirmCertAcceptance.issuer: The issuer name for"); + System.out.println("#confirmCertAcceptance control"); + System.out.println("confirmCertAcceptance.issuer=cn=Certificate Manager,c=us"); + System.out.println(""); + System.out.println("#getCert.enable: if true, then the request will contain this"); + System.out.println("#control. Otherwise, false."); + System.out.println("getCert.enable=true"); + System.out.println(""); + System.out.println("#getCert.serial: The serial number for getCert control"); + System.out.println("getCert.serial=3"); + System.out.println(""); + System.out.println("#getCert.issuer: The issuer name for getCert control"); + System.out.println("getCert.issuer=cn=Certificate Manager,c=us"); + System.out.println(""); + System.out.println("#dataReturn.enable: if true, then the request will contain"); + System.out.println("#this control. Otherwise, false."); + System.out.println("dataReturn.enable=true"); + System.out.println(""); + System.out.println("#dataReturn.data: data contained in the control."); + System.out.println("dataReturn.data=test"); + System.out.println(""); + System.out.println("#transactionMgt.enable: if true, then the request will contain"); + System.out.println("#this control. Otherwise, false."); + System.out.println("transactionMgt.enable=true"); + System.out.println(""); + System.out.println("#transactionMgt.id: transaction identifier. Verisign recommend"); + System.out.println("#transactionId to be MD5 hash of publicKey."); + System.out.println("transactionMgt.id="); + System.out.println(""); + System.out.println("#senderNonce.enable: if true, then the request will contain this"); + System.out.println("#control. Otherwise, false."); + System.out.println("senderNonce.enable=true"); + System.out.println(""); + System.out.println("#senderNonce.id: sender nonce"); + System.out.println("senderNonce.id="); + System.out.println(""); + System.out.println("#revRequest.enable: if true, then the request will contain this"); + System.out.println("#control. Otherwise, false."); + System.out.println("revRequest.enable=true"); + System.out.println(""); + System.out.println("#revRequest.nickname: The nickname for the revoke certificate"); + System.out.println("revRequest.nickname=newuser's 102504a ID"); + System.out.println(""); + System.out.println("#revRequest.issuer: The issuer name for the certificate being"); + System.out.println("#revoked."); + System.out.println("revRequest.issuer=cn=Certificate Manager,c=us"); + System.out.println(""); + System.out.println("#revRequest.serial: The serial number for the certificate being"); + System.out.println("#revoked."); + System.out.println("revRequest.serial=61"); + System.out.println(""); + System.out.println("#revRequest.reason: The reason for revoking this certificate: "); + System.out.println("# unspecified, keyCompromise, caCompromise,"); + System.out.println("# affiliationChanged, superseded, cessationOfOperation,"); + System.out.println("# certificateHold, removeFromCRL"); + System.out.println("revRequest.reason=unspecified"); + System.out.println(""); + System.out.println("#revRequest.sharedSecret: The sharedSecret"); + System.out.println("revRequest.sharedSecret="); + System.out.println(""); + System.out.println("#revRequest.comment: The human readable comment"); + System.out.println("revRequest.comment="); + System.out.println(""); + System.out.println("#revRequest.invalidityDatePresent: if true, the current time will be the"); + System.out.println("# invalidityDate. If false, no invalidityDate"); + System.out.println("# is present."); + System.out.println("revRequest.invalidityDatePresent=false"); + System.out.println(""); + System.out.println("#identityProof.enable: if true, then the request will contain"); + System.out.println("#this control. Otherwise, false."); + System.out.println("identityProof.enable=true"); + System.out.println(""); + System.out.println("#identityProof.sharedSecret: Shared Secret"); + System.out.println("identityProof.sharedSecret=testing"); + System.out.println(""); + System.out.println("#popLinkWitness.enable: if true, then the request will contain"); + System.out.println("#this control. Otherwise, false."); + System.out.println("#If you want to test this control, make sure to use CRMFPopClient "); + System.out.println("# to generate the CRMF request which will include the "); + System.out.println("#idPOPLinkWitness attribute in the controls section of the "); + System.out.println("#CertRequest structure."); + System.out.println("popLinkWitness.enable=false"); + System.out.println(""); + System.out.println("#LraPopWitness.enable: if true, then the request will contain this"); + System.out.println("#control. Otherwise, false."); + System.out.println("LraPopWitness.enable=true"); + System.out.println(""); + System.out.println("#LraPopWitness.bodyPartIDs: List of body part IDs"); + System.out.println("#Each id is separated by space."); + System.out.println("LraPopWitness.bodyPartIDs=1"); + System.exit(1); + } + + private static int addLraPopWitnessAttr(int bpid, SEQUENCE seq, String bodyPartIDs) { + StringTokenizer tokenizer = new StringTokenizer(bodyPartIDs, " "); + SEQUENCE bodyList = new SEQUENCE(); + while (tokenizer.hasMoreTokens()) { + String s = (String)tokenizer.nextToken(); + bodyList.addElement(new INTEGER(s)); + } + LraPopWitness lra = new LraPopWitness(new INTEGER(0), bodyList); + TaggedAttribute cont = new TaggedAttribute(new + INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_lraPOPWitness, lra); + System.out.println("Successfully create LRA POP witness control. bpid = "+(bpid-1)); + System.out.println(""); + seq.addElement(cont); + return bpid; + } + + private static int addConfirmCertAttr(int bpid, SEQUENCE seq, String confirmCertIssuer, + String confirmCertSerial) { + try { + INTEGER serial = new INTEGER(confirmCertSerial); + X500Name issuername = new X500Name(confirmCertIssuer); + byte[] issuerbyte = issuername.getEncoded(); + ANY issuern = new ANY(issuerbyte); + CMCCertId cmcCertId = new CMCCertId(issuern, serial, null); + TaggedAttribute cmcCertIdControl = new TaggedAttribute(new + INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_idConfirmCertAcceptance, cmcCertId); + System.out.println("Successfully create confirm certificate acceptance control. bpid = "+(bpid-1)); + System.out.println(""); + seq.addElement(cmcCertIdControl); + } catch (Exception e) { + System.out.println("Error in creating confirm certificate acceptance control. Check the parameters."); + System.exit(1); + } + return bpid; + } + + private static ENUMERATED toCRLReason(String str) { + if (str.equalsIgnoreCase("unspecified")) { + return RevRequest.unspecified; + } else if (str.equalsIgnoreCase("keyCompromise")) { + return RevRequest.keyCompromise; + } else if (str.equalsIgnoreCase("caCompromise")) { + return RevRequest.cACompromise; + } else if (str.equalsIgnoreCase("affiliationChanged")) { + return RevRequest.affiliationChanged; + } else if (str.equalsIgnoreCase("superseded")) { + return RevRequest.superseded; + } else if (str.equalsIgnoreCase("cessationOfOperation")) { + return RevRequest.cessationOfOperation; + } else if (str.equalsIgnoreCase("certificateHold")) { + return RevRequest.certificateHold; + } else if (str.equalsIgnoreCase("removeFromCRL")) { + return RevRequest.removeFromCRL; + } + + System.out.println("Unrecognized CRL reason"); + System.exit(1); + + return RevRequest.unspecified; + } + + private static int addIdentityProofAttr(int bpid, SEQUENCE seq, SEQUENCE reqSequence, + String sharedSecret) { + byte[] b = ASN1Util.encode(reqSequence); + byte[] key = null; + byte[] finalDigest = null; + try { + MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1"); + key = SHA1Digest.digest(sharedSecret.getBytes()); + } catch (NoSuchAlgorithmException ex) { + System.out.println( "CMCRequest::addIdentityProofAttr() - " + + "No such algorithm!" ); + return -1; + } + + try { + MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1"); + HMACDigest hmacDigest = new HMACDigest(SHA1Digest, key); + hmacDigest.update(b); + finalDigest = hmacDigest.digest(); + } catch (NoSuchAlgorithmException ex) { + } + + TaggedAttribute identityProof = new TaggedAttribute(new + INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_identityProof, + new OCTET_STRING(finalDigest)); + seq.addElement(identityProof); + System.out.println("Identity Proof control: "); + System.out.print(" Value: "); + for (int i=0; i 0) + sharedSecret = new OCTET_STRING(revRequestSharedSecret.getBytes()); + if (revRequestComment.length() > 0) + comment = new UTF8String(revRequestComment); + if (invalidityDatePresent.equals("true")) + d = new GeneralizedTime(new Date()); + RevRequest revRequest = + new RevRequest(new ANY(subjectname.getEncoded()), snumber, + reason, d, sharedSecret, comment); + int revokeBpid = bpid; + TaggedAttribute revRequestControl = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_revokeRequest, revRequest); + seq.addElement(revRequestControl); + + if (sharedSecret != null) { + System.out.println("Successfully create revRequest control. bpid = "+(bpid-1)); + System.out.println(""); + return bpid; + } + + EncapsulatedContentInfo revokeContent = new EncapsulatedContentInfo( + OBJECT_IDENTIFIER.id_cct_PKIData, revRequestControl); + DigestAlgorithm digestAlg1 = null; + SignatureAlgorithm signAlg1 = SignatureAlgorithm.RSASignatureWithSHA1Digest; + java.security.PrivateKey revokePrivKey = null; + X509Certificate revokeCert = null; + try { + revokeCert = manager.findCertByNickname(nickname1); + } catch (ObjectNotFoundException e) { + System.out.println("Certificate not found: "+nickname1); + System.exit(1); + } + revokePrivKey = manager.findPrivKeyByCert(revokeCert); + org.mozilla.jss.crypto.PrivateKey.Type signingKeyType1 = + ((org.mozilla.jss.crypto.PrivateKey) revokePrivKey).getType(); + if (signingKeyType1.equals(org.mozilla.jss.crypto.PrivateKey.Type.DSA)) + signAlg1 = SignatureAlgorithm.DSASignatureWithSHA1Digest; + + MessageDigest rSHADigest = null; + byte[] rdigest = null; + try { + rSHADigest = MessageDigest.getInstance("SHA1"); + digestAlg1 = DigestAlgorithm.SHA1; + + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + + revRequestControl.encode((OutputStream) ostream); + rdigest = rSHADigest.digest(ostream.toByteArray()); + } catch (NoSuchAlgorithmException e) { + } + + ByteArrayInputStream bistream = + new ByteArrayInputStream(subjectname.getEncoded()); + Name iname = (Name)Name.getTemplate().decode(bistream); + IssuerAndSerialNumber ias1 = new IssuerAndSerialNumber(iname, snumber); + + SignerIdentifier rsi = new SignerIdentifier( + SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias1, null); + + SignerInfo signInfo1 = new SignerInfo(rsi, null, null, + OBJECT_IDENTIFIER.id_cct_PKIData, rdigest, signAlg1, + (org.mozilla.jss.crypto.PrivateKey) revokePrivKey); + + SET signInfos1 = new SET(); + signInfos1.addElement(signInfo1); + SET digestAlgs1 = new SET(); + if (digestAlg1 != null) { + AlgorithmIdentifier ai1 = new AlgorithmIdentifier(digestAlg1.toOID(), null); + digestAlgs1.addElement(ai1); + } + + org.mozilla.jss.crypto.X509Certificate[] revokeCertChain = + manager.buildCertificateChain(revokeCert); + SET certs1 = new SET(); + for (int i=0; i 0) { + int index = str.indexOf("="); + String name = ""; + String val = ""; + if (index == -1) { + System.out.println("Error in configuration file: "+str); + System.exit(1); + } + name = str.substring(0, index); + if (index != str.length()-1) + val = str.substring(index+1); + + if (name.equals("format")) { + format = val; + } else if (name.equals("dbdir")) { + dbdir = val; + } else if (name.equals("nickname")) { + nickname = val; + } else if (name.equals("password")) { + password = val; + } else if (name.equals("output")) { + ofilename = val; + } else if (name.equals("input")) { + ifilename = val; + } else if (name.equals("confirmCertAcceptance.serial")) { + confirmCertSerial = val; + } else if (name.equals("confirmCertAcceptance.issuer")) { + confirmCertIssuer = val; + } else if (name.equals("confirmCertAcceptance.enable")) { + confirmCertEnable = val; + } else if (name.equals("getCert.enable")) { + getCertEnable = val; + } else if (name.equals("getCert.issuer")) { + getCertIssuer = val; + } else if (name.equals("getCert.serial")) { + getCertSerial = val; + } else if (name.equals("dataReturn.enable")) { + dataReturnEnable = val; + } else if (name.equals("dataReturn.data")) { + dataReturnData = val; + } else if (name.equals("transactionMgt.enable")) { + transactionMgtEnable = val; + } else if (name.equals("transactionMgt.id")) { + transactionMgtId = val; + } else if (name.equals("senderNonce.enable")) { + senderNonceEnable = val; + } else if (name.equals("senderNonce")) { + senderNonce = val; + } else if (name.equals("revRequest.enable")) { + revRequestEnable = val; + } else if (name.equals("revRequest.issuer")) { + revRequestIssuer = val; + } else if (name.equals("revRequest.serial")) { + revRequestSerial = val; + } else if (name.equals("revRequest.reason")) { + revRequestReason = val; + } else if (name.equals("revRequest.sharedSecret")) { + revRequestSharedSecret = val; + } else if (name.equals("revRequest.comment")) { + revRequestComment = val; + } else if (name.equals("revRequest.invalidityDatePresent")) { + revRequestInvalidityDatePresent = val; + } else if (name.equals("revRequest.nickname")) { + revCertNickname = val; + } else if (name.equals("identityProof.enable")) { + identityProofEnable = val; + } else if (name.equals("identityProof.sharedSecret")) { + identityProofSharedSecret = val; + } else if (name.equals("popLinkWitness.enable")) { + popLinkWitnessEnable = val; + } else if (name.equals("LraPopWitness.enable")) { + lraPopWitnessEnable = val; + } else if (name.equals("LraPopWitness.bodyPartIDs")) { + bodyPartIDs = val; + } else if (name.equals("numRequests")) { + numRequests = val; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + printUsage(); + } + + if (ifilename == null) { + System.out.println("Missing input filename for PKCS10 or CRMF."); + printUsage(); + } + + int num = 0; + if (numRequests == null) { + System.out.println("Missing numRequests."); + printUsage(); + } else { + try { + num = Integer.parseInt(numRequests); + } catch (Exception ee) { + System.out.println("numRequests must be integer"); + System.exit(1); + } + } + + StringTokenizer tokenizer = new StringTokenizer(ifilename, " "); + String[] ifiles = new String[num]; + for (int i=0; i + * @version $Revision$, $Date$ + * + */ +public class CMCResponse +{ + + public CMCResponse() { + } + + public static void printOutput(String path, String filename) { + byte[] bb = new byte[10000]; + FileInputStream fis = null; + try { + fis = new FileInputStream(filename); + while (fis.available() > 0) + fis.read(bb, 0, 10000); + } catch (Exception e) { + System.out.println("Error reading the response. Exception: "+e.toString()); + System.exit(1); + } + + try { + ByteArrayInputStream bis = new ByteArrayInputStream(bb); + org.mozilla.jss.pkix.cms.ContentInfo cii = (org.mozilla.jss.pkix.cms.ContentInfo) + org.mozilla.jss.pkix.cms.ContentInfo.getTemplate().decode(bis); + + org.mozilla.jss.pkix.cms.SignedData cmcFullResp = + (org.mozilla.jss.pkix.cms.SignedData)cii.getInterpretedContent(); + + String content = ""; + if (cmcFullResp.hasCertificates()) { + SET certs = cmcFullResp.getCertificates(); + int numCerts = certs.size(); + + for (int i = 0; i < numCerts; i++) { + Certificate cert = (Certificate) certs.elementAt(i); + X509CertImpl certImpl = new X509CertImpl(ASN1Util.encode(cert)); + CertPrettyPrint print = new CertPrettyPrint(certImpl); + content += print.toString(Locale.getDefault()); + } + } + + System.out.println("Certificates: "); + System.out.println(content); + System.out.println(""); + EncapsulatedContentInfo ci = cmcFullResp.getContentInfo(); + OBJECT_IDENTIFIER id = ci.getContentType(); + OBJECT_IDENTIFIER dataid = new OBJECT_IDENTIFIER("1.2.840.113549.1.7.1"); + if (!id.equals(OBJECT_IDENTIFIER.id_cct_PKIResponse) && !id.equals(dataid)) { + System.out.println("Invalid CMC Response Format"); + } + + if (!ci.hasContent()) + return; + + OCTET_STRING content1 = ci.getContent(); + ByteArrayInputStream bbis = new ByteArrayInputStream(content1.toByteArray()); + ResponseBody responseBody = (ResponseBody) (new ResponseBody.Template()).decode(bbis); + SEQUENCE controlSequence = responseBody.getControlSequence(); + + int numControls = controlSequence.size(); + System.out.println("Number of controls is "+numControls); + INTEGER bodyPartId = null; + String error = ""; + + for (int i=0; i -i "); + } + + public static void main(String args[]) { + String filename = null, path = null; + if (args.length != 4) { + printUsage(); + System.exit(1); + } + + for (int i=0; i + * @version $Revision$, $Date$ + */ +public class CMCRevoke { + public static final int ARGC = 7; + private static final String CERTDB = "cert8.db"; + private static final String KEYDB = "key3.db"; + public static final String HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----"; + public static final String TRAILER = "-----END NEW CERTIFICATE REQUEST-----"; + static String dValue = null, nValue = null, iValue = null, sValue = null, mValue = null, hValue = null, cValue = null; + + public static final String CMS_BASE_CA_SIGNINGCERT_NOT_FOUND="CA signing certificate not found"; + public static final String PR_INTERNAL_TOKEN_NAME = "internal"; + public static final String PR_REQUEST_CMC = "CMC"; + + static String cleanArgs(String s) { + if (s.startsWith("\"") && s.endsWith("\"")) + return s.substring(1, s.length() - 2); + else if (s.startsWith("\'") && s.endsWith("\'")) + return new String(s.substring(1, s.length() - 2)); + else + return s; + } + + /** + * Creates a new instance of CMCRevoke. + */ + public static void main(String[]s) { + + FileOutputStream outputBlob = null; + + // default path is "." + String mPath = "."; + // default prefix is "" + String mPrefix = ""; + + boolean bWrongParam = false; + + // (1) Check that two arguments were submitted to the program + if (s.length != (ARGC) && s.length != (ARGC - 1)) { + + bWrongParam = true; + System.out.println("Wrong number of parameters:" + s.length); + System.out.println("Usage: CMCRevoke " + + "-d

" + + "-n " + + "-i " + + "-s " + + "-m " + + "-h " + + "-c "); + for (int i = 0; i < s.length; i++) { + System.out.println(i + ":" + s[i]); + } + }else { + int length; + int i; + + length = s.length; + for (i = 0; i < length; i++) { + if (s[i].startsWith("-d")) { + dValue = cleanArgs(s[i].substring(2)); + } else if (s[i].startsWith("-n")) { + nValue = cleanArgs(s[i].substring(2)); + } else if (s[i].startsWith("-i")) { + iValue = cleanArgs(s[i].substring(2)); + } else if (s[i].startsWith("-s")) { + sValue = cleanArgs(s[i].substring(2)); + } else if (s[i].startsWith("-m")) { + mValue = cleanArgs(s[i].substring(2)); + } else if (s[i].startsWith("-h")) { + hValue = cleanArgs(s[i].substring(2)); + } else if (s[i].startsWith("-c")) { + cValue = cleanArgs(s[i].substring(2)); + } + + } + // optional parameter + if (cValue == null) + cValue = new String(); + if (dValue == null || nValue == null || iValue == null || sValue == null || mValue == null || hValue == null) + bWrongParam = true; + else if (dValue.length() == 0 || nValue.length() == 0 || iValue.length() == 0 || + sValue.length() == 0 || mValue.length() == 0 || hValue.length() == 0) + bWrongParam = true; + + if (bWrongParam == true) { + System.out.println("Usage: CMCRevoke " + + "-d " + + "-n " + + "-i " + + "-s " + + "-m " + + "-h " + + "-c "); + for (i = 0; i < s.length; i++) { + System.out.println(i + ":" + s[i]); + } + System.exit(0); + } + + try { + // initialize CryptoManager + mPath = dValue; + System.out.println("cert/key prefix = " + mPrefix); + System.out.println("path = " + mPath); + CryptoManager.InitializationValues vals = + new CryptoManager.InitializationValues(mPath, mPrefix, mPrefix, "secmod.db"); + + CryptoManager.initialize(vals); + + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = cm.getInternalKeyStorageToken(); + Password pass = new Password(hValue.toCharArray()); + + token.login(pass); + CryptoStore store = token.getCryptoStore(); + X509Certificate[] list = store.getCertificates(); + X509Certificate signerCert = null; + + signerCert = cm.findCertByNickname(nValue); + String outBlob = createRevokeReq(signerCert, cm, nValue); + + printCMCRevokeRequest(outBlob); + }catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + + return; + } + } + + /** + * printout CMC revoke request in Base64 encoding to a file CMCRevoke.out + *

+ * @param asciiBASE64Blob the ascii string of the request + */ + static void printCMCRevokeRequest(String asciiBASE64Blob) { + + // (6) Finally, print the actual CMCSigning blob to the + // specified output file + FileOutputStream outputBlob = null; + + try { + outputBlob = new FileOutputStream("CMCRevoke.out"); + } catch (IOException e) { + System.out.println("CMCSigning: unable to open file CMCRevoke.out for writing:\n" + e); + return; + } + + System.out.println(HEADER); + System.out.println(asciiBASE64Blob + TRAILER); + try { + asciiBASE64Blob = HEADER + "\n" + asciiBASE64Blob + TRAILER; + outputBlob.write(asciiBASE64Blob.getBytes()); + } catch (IOException e) { + System.out.println("CMCSigning: I/O error " + + "encountered during write():\n" + + e); + } + + try { + outputBlob.close(); + } catch (IOException e) { + System.out.println("CMCSigning: Unexpected error " + + "encountered while attempting to close() " + + "\n" + e); + } + } + + /** + * getCertificate find the certicate inside the token by its nickname. + *

+ * @param manager the CrytoManager + * @param tokenname the name of the token. it's set to "internal". + * @param nickname the nickname of the certificate inside the token. + * @return the X509Certificate. + */ + public static X509Certificate getCertificate(CryptoManager manager, String tokenname, + String nickname) throws NoSuchTokenException, + Exception, TokenException { + CryptoToken token = null; + + if (tokenname.equals(PR_INTERNAL_TOKEN_NAME)) { + token = manager.getInternalKeyStorageToken(); + } else { + token = manager.getTokenByName(tokenname); + } + StringBuffer certname = new StringBuffer(); + + if (!token.equals(manager.getInternalKeyStorageToken())) { + certname.append(tokenname); + certname.append(":"); + } + certname.append(nickname); + try { + return manager.findCertByNickname(certname.toString()); + } catch (ObjectNotFoundException e) { + throw new Exception(CMS_BASE_CA_SIGNINGCERT_NOT_FOUND); + } + } + + /** + * createRevokeReq create and return the revocation request. + *

+ * @param signerCert the certificate of the authorized signer of the CMC revocation request. + * @param manager the crypto manger. + * @param nValue the nickname of the certificate inside the token. + * @return the CMC revocation request encoded in base64 + */ + static String createRevokeReq(X509Certificate signerCert, CryptoManager manager, String nValue) { + + java.security.PrivateKey privKey = null; + SignerIdentifier si = null; + ContentInfo fullEnrollmentReq = null; + String tokenname = "internal"; + String asciiBASE64Blob = new String(); + + try { + + String hasSki = "true"; + + BigInteger serialno = signerCert.getSerialNumber(); + byte[] certB = signerCert.getEncoded(); + X509CertImpl impl = new X509CertImpl(certB); + X500Name issuerName = (X500Name) impl.getIssuerDN(); + byte[] issuerByte = issuerName.getEncoded(); + ByteArrayInputStream istream = new ByteArrayInputStream(issuerByte); + + Name issuer = (Name) Name.getTemplate().decode(istream); + IssuerAndSerialNumber ias = new IssuerAndSerialNumber(issuer, new INTEGER(serialno.toString())); + + si = new SignerIdentifier(SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias, null); + X509Certificate cert = getCertificate(manager, tokenname, nValue); + + privKey = manager.findPrivKeyByCert(cert); + + if( privKey == null ) { + System.out.println( "CMCRevoke::createRevokeReq() - " + + "privKey is null!" ); + return ""; + } + + int bpid = 1; + // Add some control sequence + // Verisign has transactionID,senderNonce + SEQUENCE controlSeq = new SEQUENCE(); + + Date date = new Date(); + String salt = "lala123" + date.toString(); + byte[] dig; + + try { + MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1"); + + dig = SHA1Digest.digest(salt.getBytes()); + } catch (NoSuchAlgorithmException ex) { + dig = salt.getBytes(); + } + String sn = com.netscape.osutil.OSUtil.BtoA(dig); + + TaggedAttribute senderNonce = new TaggedAttribute(new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_senderNonce, + new OCTET_STRING(sn.getBytes())); + + controlSeq.addElement(senderNonce); + + Name subjectName = new Name(); + + subjectName.addCommonName(iValue); + org.mozilla.jss.pkix.cmmf.RevRequest lRevokeRequest = new org.mozilla.jss.pkix.cmmf.RevRequest(new ANY((new X500Name(iValue)).getEncoded()), + new INTEGER(sValue), + //org.mozilla.jss.pkix.cmmf.RevRequest.unspecified, + new ENUMERATED((new Integer(mValue)). longValue()), + //new GeneralizedTime(new Date(lValue)), + new OCTET_STRING(hValue.getBytes()), + new UTF8String(cValue.toCharArray())); + //byte[] encoded = ASN1Util.encode(lRevokeRequest); + //org.mozilla.jss.asn1.ASN1Template template = new org.mozilla.jss.pkix.cmmf.RevRequest.Template(); + //org.mozilla.jss.pkix.cmmf.RevRequest revRequest = (org.mozilla.jss.pkix.cmmf.RevRequest) + // template.decode(new java.io.ByteArrayInputStream( + // encoded)); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + //lRevokeRequest.encode(os); // khai + TaggedAttribute revokeRequestTag = new TaggedAttribute(new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_revokeRequest, + lRevokeRequest); + + controlSeq.addElement(revokeRequestTag); + PKIData pkidata = new PKIData(controlSeq, new SEQUENCE(), new SEQUENCE(), new SEQUENCE()); + + EncapsulatedContentInfo ci = new EncapsulatedContentInfo(OBJECT_IDENTIFIER.id_cct_PKIData, pkidata); + // SHA1 is the default digest Alg for now. + DigestAlgorithm digestAlg = null; + SignatureAlgorithm signAlg = SignatureAlgorithm.RSASignatureWithSHA1Digest; + org.mozilla.jss.crypto.PrivateKey.Type signingKeyType = ((org.mozilla.jss.crypto.PrivateKey) privKey).getType(); + + if (signingKeyType.equals(org.mozilla.jss.crypto.PrivateKey.Type.DSA)) + signAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest; + MessageDigest SHADigest = null; + byte[] digest = null; + + try { + SHADigest = MessageDigest.getInstance("SHA1"); + digestAlg = DigestAlgorithm.SHA1; + + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + + pkidata.encode((OutputStream) ostream); + digest = SHADigest.digest(ostream.toByteArray()); + } catch (NoSuchAlgorithmException e) { + } + SignerInfo signInfo = new SignerInfo(si, null, null, OBJECT_IDENTIFIER.id_cct_PKIData, digest, signAlg, + (org.mozilla.jss.crypto.PrivateKey) privKey); + SET signInfos = new SET(); + + signInfos.addElement(signInfo); + + SET digestAlgs = new SET(); + + if (digestAlg != null) { + AlgorithmIdentifier ai = new AlgorithmIdentifier(digestAlg.toOID(), null); + + digestAlgs.addElement(ai); + } + + org.mozilla.jss.crypto.X509Certificate[] agentChain = manager.buildCertificateChain(signerCert); + SET certs = new SET(); + + for (int i = 0; i < agentChain.length; i++) { + ANY certificate = new ANY(agentChain[i].getEncoded()); + + certs.addElement(certificate); + } + SignedData req = new SignedData(digestAlgs, ci, certs, null, signInfos); + + fullEnrollmentReq = new ContentInfo(req); + + ByteArrayOutputStream bs = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(bs); + + if (fullEnrollmentReq != null) { + // format is PR_REQUEST_CMC + fullEnrollmentReq.encode(os); + ps.print(com.netscape.osutil.OSUtil.BtoA(os.toByteArray())); + ////fullEnrollmentReq.print(ps); // no header/trailer + } + + asciiBASE64Blob = bs.toString(); + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + return asciiBASE64Blob; + } +} diff --git a/pki/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java b/pki/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java new file mode 100644 index 000000000..dc9bcb0cb --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java @@ -0,0 +1,646 @@ +// --- 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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools; + +import java.io.*; +import java.util.Date; +import java.util.StringTokenizer; +import java.net.URL; +import java.net.URLConnection; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.BufferedReader; + +import java.net.URLEncoder; +import java.security.KeyPair; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import org.mozilla.jss.util.Password; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.KeyPairGenerator; +import org.mozilla.jss.crypto.KeyPairAlgorithm; +//import netscape.security.provider.RSAPublicKey; +import netscape.security.pkcs.PKCS10; +//import java.security.Signature; +import netscape.security.x509.X500Name; +import netscape.security.util.BigInt; +import netscape.security.x509.X500Signer; +import java.io.ByteArrayOutputStream; + +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.pkix.crmf.*; +import com.netscape.cmsutil.util.*; + + +/** + * A command-line utility used to generate a Certificate Request Message + * Format (CRMF) request with proof of possesion (POP). + * + * Usage: + *

+ *     CRMFPopClient  TOKEN_PWD
+ *                    Authenticator HOST PORT USER_NAME PASSWORD
+ *                    POP_OPTION
+ *                    SUBJECT_DN [OUTPUT_CERT_REQ]
+ *
+ *                    ---  or  ---
+ *
+ *     CRMFPopClient  TOKEN_PWD
+ *                    POP_OPTION
+ *                    OUTPUT_CERT_REQ SUBJECT_DN
+ *
+ *
+ *     where POP_OPTION can be [POP_SUCCESS or POP_FAIL or POP_NONE]
+ * 
+ *

+ * Examples: + *

+ *     CRMFPopClient  password123
+ *                    nullAuthMgr host.netscape.com 1026 admin netscape
+ *                    [POP_SUCCESS or POP_FAIL or POP_NONE]
+ *                    CN=MyTest,C=US,UID=MyUid
+ *
+ *                    ---  or  ---
+ *
+ *     CRMFPopClient  password123
+ *                    nullAuthMgr host.netscape.com 1026 admin netscape
+ *                    [POP_SUCCESS or POP_FAIL or POP_NONE]
+ *                    CN=MyTest,C=US,UID=MyUid OUTPUT_CERT_REQ 
+ *
+ *                    ---  or  ---
+ *
+ *     CRMFPopClient  password123
+ *                    [POP_SUCCESS or POP_FAIL or POP_NONE]
+ *                    OUTPUT_CERT_REQ CN=MyTest,C=US,UID=MyUid
+ * 
+ *

+ *

+ * IMPORTANT:  The file "transport.txt" needs to be created to contain the
+ *             transport certificate in its base64 encoded format.  This
+ *             file should consist of one line containing a single certificate
+ *             in base64 encoded format with the header and footer removed.
+ * 
+ *

+ * @version $Revision$, $Date$ + */ +public class CRMFPopClient +{ + + private static void usage() + { + System.out.println(""); + System.out.println("Description: A command-line utility used to generate a"); + System.out.println(" Certificate Request Message Format (CRMF)"); + System.out.println(" request with proof of possesion (POP).\n\n"); + System.out.println("Usage:"); + System.out.println(""); + System.out.println(" CRMFPopClient TOKEN_PWD"); + System.out.println(" Authenticator HOST PORT USER_NAME PASSWORD"); + System.out.println(" POP_OPTION"); + System.out.println(" SUBJECT_DN [OUTPUT_CERT_REQ] \n"); + System.out.println(" --- or ---\n"); + System.out.println(" CRMFPopClient TOKEN_PWD"); + System.out.println(" POP_OPTION"); + System.out.println(" OUTPUT_CERT_REQ SUBJECT_DN\n\n"); + System.out.println(" where POP_OPTION can be [POP_SUCCESS or POP_FAIL or POP_NONE]\n\n"); + System.out.println("Examples:"); + System.out.println(""); + System.out.println(" CRMFPopClient password123"); + System.out.println(" nullAuthMgr host.netscape.com 1026 admin netscape"); + System.out.println(" [POP_SUCCESS or POP_FAIL or POP_NONE]"); + System.out.println(" CN=MyTest,C=US,UID=MyUid\n"); + System.out.println(" --- or ---\n"); + System.out.println(" CRMFPopClient password123"); + System.out.println(" nullAuthMgr host.netscape.com 1026 admin netscape"); + System.out.println(" [POP_SUCCESS or POP_FAIL or POP_NONE]"); + System.out.println(" CN=MyTest,C=US,UID=MyUid OUTPUT_CERT_REQ\n"); + System.out.println(" --- or ---\n"); + System.out.println(" CRMFPopClient password123"); + System.out.println(" [POP_SUCCESS or POP_FAIL or POP_NONE]"); + System.out.println(" OUTPUT_CERT_REQ CN=MyTest,C=US,UID=MyUid"); + System.out.println("\n"); + System.out.println("IMPORTANT: The file \"transport.txt\" needs to be created to contain the"); + System.out.println(" transport certificate in its base64 encoded format. This"); + System.out.println(" file should consist of one line containing a single certificate"); + System.out.println(" in base64 encoded format with the header and footer removed.\n"); + } + private static int getRealArgsLength(String args[]) + { + + int len = args.length; + + String curArg = ""; + int finalLen = len; + + for(int i = 0; i < len; i++) + { + + curArg = args[i]; + // System.out.println("arg[" + i + "] " + curArg); + + + if(curArg == null || curArg.equalsIgnoreCase("")) { + finalLen --; + } + + } + + //System.out.println("getRealArgsLength: returning " + finalLen); + + if(finalLen < 0) + finalLen = 0; + + + return finalLen; + + + } + public static void main(String args[]) + { + String USER_PREFIX = "user"; + + + int argsLen = getRealArgsLength(args); + + // System.out.println("args length " + argsLen); + + + System.out.println("\n\nProof Of Possession Utility...."); + System.out.println(""); + + if(argsLen == 0 || (argsLen != 8 && argsLen != 9 && argsLen != 4)) + { + usage(); + return; + } + + String DB_DIR = "./"; + String TOKEN_PWD = args[0]; + int KEY_LEN = 1024; + + + int PORT = 0; + String USER_NAME = null; + String USER_PWORD = null; + String AUTHENTICATOR = null; + + String HOST = null; + String SUBJ_DN = null; + + + if(argsLen >= 8) + { + AUTHENTICATOR = args[1]; + HOST = args[2]; + + PORT = Integer.parseInt(args[3]); + + USER_NAME = args[4]; + USER_PWORD = args[5]; + + SUBJ_DN = args[7]; + + } + + String POP_OPTION = null; + String OUTPUT_CERT_REQ = null; + + if(argsLen == 4) + POP_OPTION = args[1]; + else + POP_OPTION = args[6]; + + + int doServerHit = 1; + + if(argsLen == 9) + OUTPUT_CERT_REQ = args[8]; + + + + + if(argsLen == 4) + { + doServerHit = 0; + OUTPUT_CERT_REQ = args[2]; + SUBJ_DN = args[3]; + } + + + int dont_do_pop = 0; + + if(POP_OPTION.equals("POP_NONE")) + { + dont_do_pop = 1; + } + + URL url = null; + URLConnection conn = null; + InputStream is = null; + BufferedReader reader = null; + boolean success = false; + int num = 1; + long total_time = 0; + KeyPair pair = null; + + + boolean foundTransport = false; + String transportCert = null; + try { + BufferedReader br = new BufferedReader(new FileReader("./transport.txt")); + transportCert = br.readLine(); + foundTransport = true; + } catch (Exception e) { + System.out.println("ERROR: cannot find ./transport.txt, so no key archival"); + + return; + } + + + + try { + CryptoManager.initialize( DB_DIR ); + } catch (Exception e) { + // it is ok if it is already initialized + System.out.println("INITIALIZATION ERROR: " + e.toString()); +// return; + } + + + try { + CryptoManager manager = CryptoManager.getInstance(); + String token_pwd = TOKEN_PWD; + CryptoToken token = manager.getInternalKeyStorageToken(); + Password password = new Password(token_pwd.toCharArray()); + try { + token.login(password); + } catch (Exception e) { + //System.out.println("login Exception: " + e.toString()); + if (!token.isLoggedIn()) { + token.initPassword(password, password); + } + } + + System.out.println("."); //"done with cryptomanager"); + + KeyPairGenerator kg = token.getKeyPairGenerator( + KeyPairAlgorithm.RSA); + kg.initialize(KEY_LEN); + + String authenticator = AUTHENTICATOR; + pair = kg.genKeyPair(); + + System.out.println("."); //key pair generated"); + + // wrap private key + byte transport[] = com.netscape.osutil.OSUtil.AtoB(transportCert); + + X509Certificate tcert = manager.importCACertPackage(transport); + + byte iv[] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1}; + + KeyGenerator kg1 = token.getKeyGenerator(KeyGenAlgorithm.DES3); + SymmetricKey sk = kg1.generate(); + + System.out.println("."); //before KeyWrapper"); + + // wrap private key using session + KeyWrapper wrapper1 = + token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD); + + System.out.println("."); //key wrapper created"); + + wrapper1.initWrap(sk, new IVParameterSpec(iv)); + + System.out.println("."); //key wrapper inited"); + byte key_data[] = wrapper1.wrap((org.mozilla.jss.crypto.PrivateKey)pair.getPrivate()); + + System.out.println("."); //key wrapper wrapped"); + + // wrap session using transport + KeyWrapper rsaWrap = token.getKeyWrapper( + KeyWrapAlgorithm.RSA); + + System.out.println("."); //got rsaWrapper"); + + rsaWrap.initWrap(tcert.getPublicKey(), null); + + System.out.println("."); //rsaWrap inited"); + + byte session_data[] = rsaWrap.wrap(sk); + + System.out.println("."); //rsaWrapped"); + + try { + // create CRMF + CertTemplate certTemplate = new CertTemplate(); + certTemplate.setVersion(new INTEGER(2)); + + Name n1 = getJssName(SUBJ_DN); + + + Name n = new Name(); + + n.addCommonName("Me"); + n.addCountryName("US"); + n.addElement(new AVA(new OBJECT_IDENTIFIER("0.9.2342.19200300.100.1.1"), new PrintableString("MyUid"))); + + if(n1 != null) + certTemplate.setSubject(n1); + else + certTemplate.setSubject(n); + + certTemplate.setPublicKey(new SubjectPublicKeyInfo(pair.getPublic())); + // set extension + AlgorithmIdentifier algS = new AlgorithmIdentifier(new OBJECT_IDENTIFIER("1.2.840.113549.3.7"), new OCTET_STRING(iv)); + EncryptedValue encValue = new EncryptedValue(null, algS, new BIT_STRING(session_data, 7),null, null,new BIT_STRING(key_data, 7)); + EncryptedKey key = new EncryptedKey(encValue); + PKIArchiveOptions opt = new PKIArchiveOptions(key); + SEQUENCE seq = new SEQUENCE(); + if (foundTransport) { + seq.addElement(new AVA(new OBJECT_IDENTIFIER("1.3.6.1.5.5.7.5.1.4"),opt)); + } + + + // Add idPOPLinkWitness control + String secretValue = "testing"; + byte[] key1 = null; + byte[] finalDigest = null; + try { + MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1"); + key1 = SHA1Digest.digest(secretValue.getBytes()); + } catch (NoSuchAlgorithmException ex) { + } + +/* Example of adding the POP link witness control to CRMF */ +byte[] b = +{0x10, 0x53, 0x42, 0x24, 0x1a, 0x2a, 0x35, 0x3c, + 0x7a, 0x52, 0x54, 0x56, 0x71, 0x65, 0x66, 0x4c, + 0x51, 0x34, 0x35, 0x23, 0x3c, 0x42, 0x43, 0x45, + 0x61, 0x4f, 0x6e, 0x43, 0x1e, 0x2a, 0x2b, 0x31, + 0x32, 0x34, 0x35, 0x36, 0x55, 0x51, 0x48, 0x14, + 0x16, 0x29, 0x41, 0x42, 0x43, 0x7b, 0x63, 0x44, + 0x6a, 0x12, 0x6b, 0x3c, 0x4c, 0x3f, 0x00, 0x14, + 0x51, 0x61, 0x15, 0x22, 0x23, 0x5f, 0x5e, 0x69}; + + try { + MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1"); + HMACDigest hmacDigest = new HMACDigest(SHA1Digest, key1); + hmacDigest.update(b); + finalDigest = hmacDigest.digest(); + } catch (NoSuchAlgorithmException ex) { + } + + + OCTET_STRING ostr = new OCTET_STRING(finalDigest); + seq.addElement(new AVA(OBJECT_IDENTIFIER.id_cmc_idPOPLinkWitness, ostr)); + CertRequest certReq = new CertRequest(new INTEGER(1), certTemplate, seq); + + System.out.println("."); //CertRequest created"); + + + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + certReq.encode(bo); + byte[] toBeVerified = bo.toByteArray(); + + byte popdata[] = ASN1Util.encode(certReq); + byte signature[]; + + System.out.println("."); //CertRequest encoded"); + + Signature signer = token.getSignatureContext( + SignatureAlgorithm.RSASignatureWithMD5Digest); + + System.out.println("."); //signer created"); + + signer.initSign((org.mozilla.jss.crypto.PrivateKey)pair.getPrivate()); + + System.out.println("."); //signer inited"); + + System.out.println("."); //FAIL_OR_SUCC " + FAIL_OR_SUCC); + + if(POP_OPTION.equals("POP_SUCCESS")) + { + System.out.println("Generating Legal POP Data....."); + signer.update(toBeVerified); + } + else if(POP_OPTION.equals("POP_FAIL")) + { + System.out.println("Generating Illegal POP Data....."); + signer.update(iv); + } + else if(dont_do_pop == 1) + { + System.out.println("Generating NO POP Data....."); + } + + System.out.println("."); //signer updated"); + + CertReqMsg crmfMsg = null; + + if(dont_do_pop == 0) + { + signature = signer.sign(); + + System.out.println("Signature completed..."); + System.out.println(""); + + + AlgorithmIdentifier algID = + new AlgorithmIdentifier(SignatureAlgorithm.RSASignatureWithMD5Digest.toOID(), null ); + POPOSigningKey popoKey = new POPOSigningKey(null,algID, new BIT_STRING(signature,0)); + + ProofOfPossession pop = ProofOfPossession.createSignature(popoKey); + + crmfMsg = new CertReqMsg(certReq, pop, null); + + } + else + { + crmfMsg = new CertReqMsg(certReq, null, null); + + } + + //crmfMsg.verify(); + + SEQUENCE s1 = new SEQUENCE(); + s1.addElement(crmfMsg); + byte encoded[] = ASN1Util.encode(s1); + + String Req1 = com.netscape.osutil.OSUtil.BtoA(encoded); + + if(OUTPUT_CERT_REQ != null) + { + System.out.println("Generated Cert Request: ...... "); + System.out.println(""); + + System.out.println(Req1); + System.out.println(""); + System.out.println("End Request:"); + + if(doServerHit == 0) + return; + } + + String Req = URLEncoder.encode(Req1); + + // post PKCS10 + + url = new URL("http://" + HOST + ":" + PORT + "/enrollment?importCert=off&uid="+USER_NAME+"&pwd="+ USER_PWORD+"&authenticator=" + authenticator + "&csrRequestorName=" + USER_PREFIX + 0 + "&CN=testuser&UID=" + USER_PREFIX + 0 + "&SMIME=true&SSLClient=true&ObjectSigning=false&csrRequestorEmail=mail&csrRequestorPhone=1234&csrRequestorComments=hello&CRMFRequest=" + Req + "&submit=Submit&subject=CN%3Dtestuser%2CUID%3D$user%2COU%3DPKI%2CO%3DU.S.Government%2CC%3DUS&certType=client&templateType=DisplayBySerial"); + + //System.out.println("Posting " + url); + + System.out.println(""); + System.out.println("Server Response....."); + System.out.println("--------------------"); + System.out.println(""); + + long start_time = (new Date()).getTime(); + conn = url.openConnection(); + is = conn.getInputStream(); + reader = new BufferedReader(new InputStreamReader(is)); + String line = null; + while ((line = reader.readLine()) != null) { + System.out.println(line); + if (line.equals("CMS Enroll Request Success")) { + success = true; + System.out.println("Enrollment Successful: ......"); + System.out.println(""); + } + } /* while */ + long end_time = (new Date()).getTime(); + total_time += (end_time - start_time); + } catch (Exception e) { + System.out.println("WARNING: " + e.toString()); + e.printStackTrace(); + } + } catch (Exception e) { + System.out.println("ERROR: " + e.toString()); + e.printStackTrace(); + } + } + + static Name getJssName(String dn) + { + + X500Name x5Name = null; + + try { + x5Name= new X500Name(dn); + + } catch(IOException e) { + + System.out.println("Illegal Subject Name: " + dn + " Error: " + e.toString()); + System.out.println("Filling in default Subject Name......"); + return null; + } + + Name ret = new Name(); + + netscape.security.x509.RDN[] names = null; + + names = x5Name.getNames(); + + int nameLen = x5Name.getNamesLength(); + +// System.out.println("x5Name len: " + nameLen); + + netscape.security.x509.RDN cur = null; + + for(int i = 0; i < nameLen ; i++) + { + cur = names[i]; + + String rdnStr = cur.toString(); + + + String[] split = rdnStr.split("="); + + if(split.length != 2) + continue; + + try { + + if(split[0].equals("UID")) + { + + ret.addElement(new AVA(new OBJECT_IDENTIFIER("0.9.2342.19200300.100.1.1"), new PrintableString(split[1]))); + // System.out.println("UID found : " + split[1]); + + } + + if(split[0].equals("C")) + { + ret.addCountryName(split[1]); + // System.out.println("C found : " + split[1]); + continue; + + } + + if(split[0].equals("CN")) + { + ret.addCommonName(split[1]); + // System.out.println("CN found : " + split[1]); + continue; + } + + if(split[0].equals("L")) + { + ret.addLocalityName(split[1]); + // System.out.println("L found : " + split[1]); + continue; + } + + if(split[0].equals("O")) + { + ret.addOrganizationName(split[1]); + // System.out.println("O found : " + split[1]); + continue; + } + + if(split[0].equals("ST")) + { + ret.addStateOrProvinceName(split[1]); + // System.out.println("ST found : " + split[1]); + continue; + } + + if(split[0].equals("OU")) + { + ret.addOrganizationalUnitName(split[1]); + // System.out.println("OU found : " + split[1]); + continue; + } + } catch (Exception e) { + System.out.println("Error constructing RDN: " + rdnStr + " Error: " + e.toString()); + + continue; + } + + + } + + return ret; + + + } +} diff --git a/pki/base/java-tools/src/com/netscape/cmstools/ExtJoiner.java b/pki/base/java-tools/src/com/netscape/cmstools/ExtJoiner.java new file mode 100644 index 000000000..2854c04a1 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/ExtJoiner.java @@ -0,0 +1,98 @@ +// --- 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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools; + + +import java.io.*; +import java.net.*; +import netscape.security.x509.*; +import netscape.security.util.*; + + +/** + * This program joins a sequence of extensions together + * so that the final output can be used in configuration + * wizard for specifing extra extensions in default + * certificates (i.e. CA certificate, SSL certificate). + * + * Usage: + *

+ *  ExtJoiner \
+ *    <ext_file0> <ext_file1> ... <ext_fileN>
+ *
+ *  where,
+ *    <ext_file> is a file that has the base64 
+ *    encoded DER encoding of an X509 Extension
+ * 
+ *  ExtensionSequence ::= SEQUENCE OF Extension;
+ *
+ *  0 30  142: SEQUENCE {
+ *  3 30   69:   SEQUENCE {
+ *  5 06    3:     OBJECT IDENTIFIER issuerAltName (2 5 29 18)
+ * 10 04   62:     OCTET STRING
+ *           :       30 3C 82 01 61 82 01 61 A4 10 30 0E 31 0C 30 0A
+ *           :       06 03 55 04 03 13 03 64 73 61 87 04 01 01 01 01
+ *           :       86 01 61 81 14 74 68 6F 6D 61 73 6B 40 6E 65 74
+ *           :       73 63 61 70 65 2E 63 6F 6D 88 03 29 01 01
+ *           :     }
+ * 74 30   69:   SEQUENCE {
+ * 76 06    3:     OBJECT IDENTIFIER subjectAltName (2 5 29 17)
+ * 81 04   62:     OCTET STRING
+ *           :       30 3C 82 01 61 82 01 61 A4 10 30 0E 31 0C 30 0A
+ *           :       06 03 55 04 03 13 03 64 73 61 87 04 01 01 01 01
+ *           :       86 01 61 81 14 74 68 6F 6D 61 73 6B 40 6E 65 74
+ *           :       73 63 61 70 65 2E 63 6F 6D 88 03 29 01 01
+ *           :     }
+ *           :   }
+ * 
+ * + * @version $Revision$, $Date$ + */ +public class ExtJoiner { + + public static void main(String args[]) { + try { + if (args.length == 0) { + System.out.println("Usage: ExtJoiner ... "); + System.exit(0); + } + DerValue exts[] = new DerValue[args.length]; + + for (int i = 0; i < args.length; i++) { + byte data[] = getFileData(args[i]); + + exts[i] = new DerValue(data); + } + DerOutputStream out = new DerOutputStream(); + + out.putSequence(exts); + System.out.println(com.netscape.osutil.OSUtil.BtoA(out.toByteArray())); + } catch (IOException e) { + System.out.println(e.toString()); + } + } + + public static byte[] getFileData(String fileName) + throws IOException { + FileInputStream fis = new FileInputStream(fileName); + + byte data[] = new byte[fis.available()]; + fis.read(data); + return com.netscape.osutil.OSUtil.BtoA(data).getBytes(); + } +} diff --git a/pki/base/java-tools/src/com/netscape/cmstools/GenExtKeyUsage.java b/pki/base/java-tools/src/com/netscape/cmstools/GenExtKeyUsage.java new file mode 100644 index 000000000..4f0eb55ca --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/GenExtKeyUsage.java @@ -0,0 +1,98 @@ +// --- 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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools; + + +import java.io.*; +import java.util.Vector; +import netscape.security.x509.*; +import netscape.security.util.*; + + +/** + * Generates a DER-encoded Extended Key Usage extension. + * The first parameter is the criticality of the extension, true or false. + * The OIDs to be included in the extension are passed as command-line + * arguments. The OIDs are described in RFC 2459. For example, + * the OID for code signing is 1.3.6.1.5.5.7.3.3. + * + * @version $Revision$, $Date$ + */ +public class GenExtKeyUsage { + + public static void main(String[] args) { + try { + if (args.length < 2) { + System.out.println("Usage: GenExtKeyUsage [true|false] ..."); + System.exit(-1); + } + + boolean critical = false; + + if (args[0].equalsIgnoreCase("true")) { + critical = true; + } else if (args[0].equalsIgnoreCase("false")) { + critical = false; + } else { + System.out.println("Usage: GenExtKeyUsage [true|false] ..."); + System.exit(-1); + } + + // Generate vector of object identifiers from command line + Vector oids = new Vector(); + + for (int i = 1; i < args.length; i++) { + ObjectIdentifier oid = new ObjectIdentifier(args[i]); + + oids.addElement(oid); + } + + // encode all the object identifiers to the DerOutputStream + DerOutputStream contents = new DerOutputStream(); + + for (int i = 0; i < oids.size(); i++) { + contents.putOID((ObjectIdentifier) oids.elementAt(i)); + } + + // stuff the object identifiers into a SEQUENCE + DerOutputStream seq = new DerOutputStream(); + + seq.write(DerValue.tag_Sequence, contents); + + // encode the SEQUENCE in an octet string + DerOutputStream octetString = new DerOutputStream(); + + octetString.putOctetString(seq.toByteArray()); + + // Construct an extension + ObjectIdentifier extKeyUsageOID = new ObjectIdentifier("2.5.29.37"); + Extension extn = new Extension(extKeyUsageOID, critical, + octetString.toByteArray()); + DerOutputStream extdos = new DerOutputStream(); + + extn.encode(extdos); + + // BASE64 encode the whole thing and write it to stdout + + System.out.println(com.netscape.osutil.OSUtil.BtoA(extdos.toByteArray())); + + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/pki/base/java-tools/src/com/netscape/cmstools/GenIssuerAltNameExt.java b/pki/base/java-tools/src/com/netscape/cmstools/GenIssuerAltNameExt.java new file mode 100644 index 000000000..3ce25778b --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/GenIssuerAltNameExt.java @@ -0,0 +1,130 @@ +// --- 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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools; + + +import java.io.*; +import java.net.*; +import netscape.security.x509.*; +import netscape.security.util.*; + + +/** + * This program generates an issuer alternative name extension + * in base-64 encoding. The encoding output can be used with + * the configuration wizard. + * + * Usage: + *
+ *  GenIssuerAltNameExt \
+ *    <general_type0> <general_name0> ... <general_typeN> <general_nameN>
+ *
+ *  where,
+ *    <general_type> can be one of the following string:
+ *      DNSName 
+ *      EDIPartyName
+ *      IPAddressName
+ *      URIName
+ *      RFC822Name
+ *      OIDName
+ *      X500Name
+ *    <general_name> is string
+ * 
+ * + * @version $Revision$, $Date$ + */ +public class GenIssuerAltNameExt { + + public static void main(String args[]) { + try { + if ((args.length == 0) || (args.length % 2 != 0)) { + doUsage(); + System.exit(0); + } + GeneralNames gns = new GeneralNames(); + + for (int i = 0; i < args.length; i += 2) { + GeneralNameInterface gni = + buildGeneralNameInterface( + args[i], args[i + 1]); + + gns.addElement(gni); + } + + IssuerAlternativeNameExtension sane = + new IssuerAlternativeNameExtension(gns); + + output(sane); + } catch (Exception e) { + System.out.println(e.toString()); + } + } + + public static void output(IssuerAlternativeNameExtension ext) + throws Exception { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + ext.encode(os); + + System.out.println( + com.netscape.osutil.OSUtil.BtoA(os.toByteArray()) + ); + } + + public static void doUsage() { + System.out.println(); + System.out.println("Usage: GenIssuerAltNameExt ... "); + System.out.println("where,"); + System.out.println(" can be one of the following string:"); + System.out.println("\tDNSName"); + System.out.println("\tEDIPartyName"); + System.out.println("\tIPAddressName"); + System.out.println("\tURIName"); + System.out.println("\tRFC822Name"); + System.out.println("\tOIDName"); + System.out.println("\tX500Name"); + System.out.println(" is a string"); + } + + public static GeneralNameInterface buildGeneralNameInterface( + String type, String value) throws Exception { + if (type.equals("DNSName")) { + return new DNSName(value); + } else if (type.equals("EDIPartyName")) { + return new DNSName(value); + } else if (type.equals("IPAddressName")) { + InetAddress addr = InetAddress.getByName(value); + + return new IPAddressName(addr.getAddress()); + } else if (type.equals("URIName")) { + return new URIName(value); + } else if (type.equals("OIDName")) { + return new OIDName(new ObjectIdentifier(value)); + } else if (type.equals("RFC822Name")) { + return new RFC822Name(value); + } else if (type.equals("X500Name")) { + return new X500Name(value); + } else { + System.out.println("Error: unknown general_type " + + type); + doUsage(); + System.exit(0); + return null; + } + } +} diff --git a/pki/base/java-tools/src/com/netscape/cmstools/GenSubjectAltNameExt.java b/pki/base/java-tools/src/com/netscape/cmstools/GenSubjectAltNameExt.java new file mode 100644 index 000000000..8d28a04e0 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/GenSubjectAltNameExt.java @@ -0,0 +1,130 @@ +// --- 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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools; + + +import java.io.*; +import java.net.*; +import netscape.security.x509.*; +import netscape.security.util.*; + + +/** + * This program generates an subject alternative name extension + * in base-64 encoding. The encoding output can be used with + * the configuration wizard. + * + * Usage: + *
+ *  GenSubjectAltNameExt \
+ *    <general_type0> <general_name0> ... <general_typeN> <general_nameN>
+ *
+ *  where,
+ *    <general_type> can be one of the following string:
+ *      DNSName 
+ *      EDIPartyName
+ *      IPAddressName
+ *      URIName
+ *      RFC822Name
+ *      OIDName
+ *      X500Name
+ *    <general_name> is string
+ * 
+ * + * @version $Revision$, $Date$ + */ +public class GenSubjectAltNameExt { + + public static void main(String args[]) { + try { + if ((args.length == 0) || (args.length % 2 != 0)) { + doUsage(); + System.exit(0); + } + GeneralNames gns = new GeneralNames(); + + for (int i = 0; i < args.length; i += 2) { + GeneralNameInterface gni = + buildGeneralNameInterface( + args[i], args[i + 1]); + + gns.addElement(gni); + } + + SubjectAlternativeNameExtension sane = + new SubjectAlternativeNameExtension(gns); + + output(sane); + } catch (Exception e) { + System.out.println(e.toString()); + } + } + + public static void output(SubjectAlternativeNameExtension ext) + throws Exception { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + ext.encode(os); + + System.out.println( + com.netscape.osutil.OSUtil.BtoA(os.toByteArray()) + ); + } + + public static void doUsage() { + System.out.println(); + System.out.println("Usage: GenSubjectAltNameExt ... "); + System.out.println("where,"); + System.out.println(" can be one of the following string:"); + System.out.println("\tDNSName"); + System.out.println("\tEDIPartyName"); + System.out.println("\tIPAddressName"); + System.out.println("\tURIName"); + System.out.println("\tRFC822Name"); + System.out.println("\tOIDName"); + System.out.println("\tX500Name"); + System.out.println(" is a string"); + } + + public static GeneralNameInterface buildGeneralNameInterface( + String type, String value) throws Exception { + if (type.equals("DNSName")) { + return new DNSName(value); + } else if (type.equals("EDIPartyName")) { + return new DNSName(value); + } else if (type.equals("IPAddressName")) { + InetAddress addr = InetAddress.getByName(value); + + return new IPAddressName(addr.getAddress()); + } else if (type.equals("URIName")) { + return new URIName(value); + } else if (type.equals("OIDName")) { + return new OIDName(new ObjectIdentifier(value)); + } else if (type.equals("RFC822Name")) { + return new RFC822Name(value); + } else if (type.equals("X500Name")) { + return new X500Name(value); + } else { + System.out.println("Error: unknown general_type " + + type); + doUsage(); + System.exit(0); + return null; + } + } +} diff --git a/pki/base/java-tools/src/com/netscape/cmstools/HttpClient.java b/pki/base/java-tools/src/com/netscape/cmstools/HttpClient.java new file mode 100644 index 000000000..1cfc72456 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/HttpClient.java @@ -0,0 +1,410 @@ +// --- 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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools; + +import java.io.*; +import java.net.*; +import java.util.*; +import java.security.*; + +import org.mozilla.jss.*; +import org.mozilla.jss.util.*; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.ssl.*; +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.CertDatabaseException; +import org.mozilla.jss.pkcs11.*; +import org.mozilla.jss.pkcs11.PK11Token; + +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509Key; +import netscape.security.x509.X500Name; + +import com.netscape.cmsutil.ocsp.*; +import com.netscape.cmsutil.ocsp.Request; + + +/** + * This class implements a CMC Enroll client for testing. + * + * @version $Revision$, $Date$ + */ +public class HttpClient +{ + private String _host = null; + private int _port = 0; + private boolean _secure = false; + + public static final int ARGC = 1; + static final int cipherSuites[] = { + SSLSocket.SSL3_RSA_WITH_RC4_128_MD5, + SSLSocket.SSL3_RSA_WITH_3DES_EDE_CBC_SHA, + SSLSocket.SSL3_RSA_WITH_DES_CBC_SHA, + SSLSocket.SSL3_RSA_EXPORT_WITH_RC4_40_MD5, + SSLSocket.SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5, + SSLSocket.SSL3_RSA_WITH_NULL_MD5, + 0 + }; + + public HttpClient(String host, int port, String secure) + throws Exception + { + _host = host; + _port = port; + if (secure.equals("true")) + _secure = true; + } + + public static byte[] getBytesFromFile(String filename) throws IOException { + File file = new File(filename); + FileInputStream is = new FileInputStream(file); + + long length = file.length(); + + if (length > Integer.MAX_VALUE) { + throw new IOException("Input file " + filename + + " is too large. Must be smaller than " + Integer.MAX_VALUE); + } + + byte[] bytes = new byte[(int)length]; + + int offset = 0; + int numRead = 0; + while (offset < bytes.length + && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) { + offset += numRead; + } + + if (offset < bytes.length) { + throw new IOException("Could not completely read file "+filename); + } + + is.close(); + return bytes; + } + + + public void send(String ifilename, String ofilename, String dbdir, + String nickname, String password, String servlet, String clientmode) + throws Exception + { + byte[] b = getBytesFromFile(ifilename); + + System.out.println("Total number of bytes read = "+b.length); + + DataOutputStream dos = null; + InputStream is = null; + if (_secure) { + try { + CryptoManager.InitializationValues vals = + new CryptoManager.InitializationValues(dbdir, "", "", "secmod.db"); + CryptoManager.initialize(vals); + SSLSocket socket = new SSLSocket(_host, _port); + int i; + + for (i = SSLSocket.SSL2_RC4_128_WITH_MD5; + i <= SSLSocket.SSL2_RC2_128_CBC_EXPORT40_WITH_MD5; ++i) { + try { + socket.setCipherPreference(i, true); + } catch( SocketException e) { + } + } + //skip SSL_EN_IDEA_128_EDE3_CBC_WITH_MD5 + for (i = SSLSocket.SSL2_DES_64_CBC_WITH_MD5; + i <= SSLSocket.SSL2_DES_192_EDE3_CBC_WITH_MD5; ++i) { + try { + socket.setCipherPreference(i, true); + } catch( SocketException e) { + } + } + for (i = 0; cipherSuites[i] != 0; ++i) { + try { + socket.setCipherPreference(cipherSuites[i], true); + } catch( SocketException e) { + } + } + SSLHandshakeCompletedListener listener = new ClientHandshakeCB(this); + socket.addHandshakeCompletedListener(listener); + + if (clientmode != null && clientmode.equals("true")) { + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = cm.getInternalKeyStorageToken(); + Password pass = new Password(password.toCharArray()); + token.login(pass); + CryptoStore store = token.getCryptoStore(); + X509Certificate cert = cm.findCertByNickname(nickname); + if (cert == null) + System.out.println("client cert is null"); + else + System.out.println("client cert is not null"); + socket.setUseClientMode(true); + socket.setClientCertNickname(nickname); + } + + socket.forceHandshake(); + dos = new DataOutputStream(socket.getOutputStream()); + is = socket.getInputStream(); + } catch (Exception e) { + System.out.println("Exception: "+e.toString()); + return; + } + } else { + Socket socket = new Socket(_host, _port); + dos = new DataOutputStream(socket.getOutputStream()); + is = socket.getInputStream(); + } + + // send request + if (servlet == null) { + System.out.println("Missing servlet name."); + printUsage(); + } else { + String s = "POST "+servlet+" HTTP/1.0\r\n"; + dos.writeBytes(s); + } + dos.writeBytes("Content-length: " + b.length + "\r\n"); + dos.writeBytes("\r\n"); + dos.write(b); + dos.flush(); + + FileOutputStream fof = new FileOutputStream(ofilename); + boolean startSaving = false; + int sum = 0; + boolean hack = false; + try { + while (true) + { + int r = is.read(); + if (r == -1) + break; + if (r == 10) { + sum++; + } + if (sum == 6) { + startSaving = true; + continue; + } + if (startSaving) { + if (hack) { + fof.write(r); + } + if (hack == false) { + hack = true; + } + } + } + } catch (IOException e) { + } + fof.close(); + + byte[] bout = getBytesFromFile(ofilename); + System.out.println("Total number of bytes read = "+ bout.length); + + ByteArrayOutputStream bs = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(bs); + ps.print(com.netscape.osutil.OSUtil.BtoA(bout)); + System.out.println(bs.toString()); + + System.out.println(""); + System.out.println("The response in binary format is stored in "+ofilename); + System.out.println(""); + } + + static void printUsage() { + System.out.println(""); + System.out.println("Usage: HttpClient "); + System.out.println("For example, HttpClient HttpClient.cfg"); + System.out.println(""); + System.out.println("The configuration file should look like as follows:"); + System.out.println(""); + System.out.println("#host: host name for the http server"); + System.out.println("host=host1.a.com"); + System.out.println(""); + System.out.println("#port: port number"); + System.out.println("port=1025"); + System.out.println(""); + System.out.println("#secure: true for secure connection, false for nonsecure connection"); + System.out.println("secure=false"); + System.out.println(""); + System.out.println("#input: full path for the enrollment request, the content must be in binary format"); + System.out.println("input=/u/doc/cmcReqCRMFBin"); + System.out.println(""); + System.out.println("#output: full path for the response in binary format"); + System.out.println("output=/u/doc/cmcResp"); + System.out.println(""); + System.out.println("#dbdir: directory for cert8.db, key3.db and secmod.db"); + System.out.println("#This parameter will be ignored if secure=false"); + System.out.println("dbdir=/u/smith/.netscape"); + System.out.println(""); + System.out.println("#clientmode: true for client authentication, false for no client authentication"); + System.out.println("#This parameter will be ignored if secure=false"); + System.out.println("clientmode=false"); + System.out.println(""); + System.out.println("#password: password for cert8.db"); + System.out.println("#This parameter will be ignored if secure=false and clientauth=false"); + System.out.println("password="); + System.out.println(""); + System.out.println("#nickname: nickname for client certificate"); + System.out.println("#This parameter will be ignored if clientmode=false"); + System.out.println("nickname="); + System.out.println(""); + System.out.println("#servlet: servlet name"); + System.out.println("servlet=/ca/profileSubmitCMCFull"); + System.out.println(""); + System.exit(0); + } + + public static void main(String args[]) + { + String host = null, portstr = null, secure = null, dbdir = null, nickname = null ; + String password = null, ofilename = null, ifilename = null; + String servlet = null; + String clientmode = null; + + System.out.println(""); + + // Check that the correct # of arguments were submitted to the program + if( args.length != ( ARGC ) ) { + System.out.println("Wrong number of parameters:" + args.length); + printUsage(); + } + + String configFile = args[0]; + BufferedReader reader = null; + try { + reader = new BufferedReader(new InputStreamReader( + new BufferedInputStream( + new FileInputStream(configFile)))); + } catch (FileNotFoundException e) { + System.out.println("HttpClient: can't find configuration file: "+configFile); + printUsage(); + System.exit(1); + } catch (Exception e) { + e.printStackTrace(); + printUsage(); + return; + } + + try { + String str = ""; + while ((str = reader.readLine()) != null) { + str = str.trim(); + if (!str.startsWith("#") && str.length() > 0) { + StringTokenizer tokenizer = new StringTokenizer(str, "="); + if (tokenizer.hasMoreTokens()) { + String name = tokenizer.nextToken(); + String val = null; + if (tokenizer.countTokens() > 0) + val = tokenizer.nextToken(); + if (name.equals("host")) { + host = val; + } else if (name.equals("port")) { + portstr = val; + } else if (name.equals("secure")) { + secure = val; + } else if (name.equals("dbdir")) { + dbdir = val; + } else if (name.equals("nickname")) { + nickname = val; + } else if (name.equals("password")) { + password = val; + } else if (name.equals("output")) { + ofilename = val; + } else if (name.equals("input")) { + ifilename = val; + } else if (name.equals("clientmode")) { + clientmode = val; + } else if (name.equals("servlet")) { + servlet = val; + } + } + } + } + } catch (Exception e) { + e.printStackTrace(); + printUsage(); + } + + if (host == null) { + System.out.println("Missing host name."); + printUsage(); + } + + if (portstr == null) { + System.out.println("Missing port number."); + printUsage(); + } + + if (servlet == null) { + System.out.println("Missing servlet name."); + printUsage(); + } + + if (ifilename == null) { + System.out.println("Missing input filename for the enrollment request."); + printUsage(); + } + + if (ofilename == null) { + System.out.println("Missing output filename for the response."); + printUsage(); + } + + int port = Integer.parseInt(portstr); + + if (secure != null && secure.equals("true")) { + if (dbdir == null) { + System.out.println("Missing directory name for the cert7.db."); + printUsage(); + } + + if (clientmode != null && clientmode.equals("true")) { + if (password == null) { + System.out.println("Missing password for the cert7.db."); + printUsage(); + } + if (nickname == null) { + System.out.println("Missing nickname for the client certificate"); + printUsage(); + } + } + } + + try { + HttpClient client = + new HttpClient(host, port, secure); + client.send(ifilename, ofilename, dbdir, nickname, password, servlet, clientmode); + } catch (Exception e) { + System.out.println("Error: " + e.toString()); + } + } + + class ClientHandshakeCB implements SSLHandshakeCompletedListener { + Object sc; + + public ClientHandshakeCB(Object sc) { + this.sc = sc; + } + + public void handshakeCompleted(SSLHandshakeCompletedEvent event) { + System.out.println("handshake happened"); + } + } +} diff --git a/pki/base/java-tools/src/com/netscape/cmstools/OCSPClient.java b/pki/base/java-tools/src/com/netscape/cmstools/OCSPClient.java new file mode 100644 index 000000000..30e033926 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/OCSPClient.java @@ -0,0 +1,270 @@ +// --- 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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools; + +import java.io.*; +import java.net.*; +import java.util.*; +import java.security.*; + +import org.mozilla.jss.*; +import org.mozilla.jss.util.*; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.CertDatabaseException; +import org.mozilla.jss.pkcs11.*; +import org.mozilla.jss.pkcs11.PK11Token; + +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509Key; +import netscape.security.x509.X500Name; + +import com.netscape.cmsutil.ocsp.*; +import com.netscape.cmsutil.ocsp.Request; + + +/** + * This class implements a OCSP client for testing. + * + * @version $Revision$, $Date$ + */ +public class OCSPClient +{ + private String _host = null; + private int _port = 0; + + public OCSPClient(String host, int port, String dbdir) + throws Exception + { + _host = host; + _port = port; + CryptoManager.initialize(dbdir); + } + + public void send(String uri, String nickname, int serialno, String output) + throws Exception + { + CryptoManager manager = CryptoManager.getInstance(); + X509Certificate caCert = manager.findCertByNickname(nickname); + OCSPRequest request = getOCSPRequest(caCert, serialno); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + request.encode(os); + byte request_data[] = os.toByteArray(); + sendOCSPRequest(uri, _host, _port, request_data, output); + } + + public void sendRequestData(String uri, String nickname, byte request_data[], String output) + throws Exception + { + sendOCSPRequest(uri, _host, _port, request_data, output); + } + + public OCSPRequest getOCSPRequest(X509Certificate caCert, int serialno) + throws Exception + { + MessageDigest md = MessageDigest.getInstance("SHA"); + + // calculate issuer key hash + X509CertImpl x509Cert = new X509CertImpl(caCert.getEncoded()); + X509Key x509key = (X509Key)x509Cert.getPublicKey(); + byte issuerKeyHash[] = md.digest(x509key.getKey()); + + // calculate name hash + X500Name name = (X500Name)x509Cert.getSubjectDN(); + byte issuerNameHash[] = md.digest(name.getEncoded()); + // constructing the OCSP request + CertID certid = new CertID( + new AlgorithmIdentifier( + new OBJECT_IDENTIFIER("1.3.14.3.2.26"), new NULL()), + new OCTET_STRING(issuerNameHash), + new OCTET_STRING(issuerKeyHash), + new INTEGER(serialno)); + Request request = new Request(certid, null); + SEQUENCE requestList = new SEQUENCE(); + requestList.addElement(request); + TBSRequest tbsRequest = new TBSRequest(null,null,requestList,null); + return new OCSPRequest(tbsRequest, null); + } + + public void sendOCSPRequest(String uri, String host, int port, + byte request_data[], String output) throws Exception + { + Socket socket = new Socket(host, port); + + // send request + System.out.println("URI: " + uri); + + DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); + dos.writeBytes("POST " + uri + " HTTP/1.0\r\n"); + dos.writeBytes("Content-length: " + request_data.length + "\r\n"); + dos.writeBytes("\r\n"); + dos.write(request_data); + dos.flush(); + + System.out.println("Data Length: " + request_data.length); + System.out.println("Data: " + com.netscape.osutil.OSUtil.BtoA(request_data)); + + InputStream iiss = socket.getInputStream(); + FileOutputStream fof = new FileOutputStream(output); + boolean startSaving = false; + int sum = 0; + boolean hack = false; + try { + while (true) + { + int r = iiss.read(); + if (r == -1) + break; + if (r == 10) { + sum++; + } + if (sum == 6) { + startSaving = true; + continue; + } + if (startSaving) { + if (hack) { + fof.write(r); + } + if (hack == false) { + hack = true; + } + } + } // while + } catch (IOException e) { + } + fof.close(); + + // parse OCSPResponse + BufferedInputStream fis = + new BufferedInputStream( + new FileInputStream(output)); + OCSPResponse resp = (OCSPResponse) + OCSPResponse.getTemplate().decode(fis); + OCSPResponseStatus status = resp.getResponseStatus(); + ResponseBytes bytes = resp.getResponseBytes(); + BasicOCSPResponse basic = (BasicOCSPResponse) + BasicOCSPResponse.getTemplate().decode( + new ByteArrayInputStream(bytes.getResponse().toByteArray())); + ResponseData rd = basic.getResponseData(); + for (int i = 0; i < rd.getResponseCount(); i++) { + SingleResponse rd1 = rd.getResponseAt(i); + System.out.println("CertID.serialNumber=" + + rd1.getCertID().getSerialNumber()); + CertStatus status1 = rd1.getCertStatus(); + if (status1 instanceof GoodInfo) { + System.out.println("CertStatus=Good"); + } + if (status1 instanceof UnknownInfo) { + System.out.println("CertStatus=Unknown"); + } + if (status1 instanceof RevokedInfo) { + System.out.println("CertStatus=Revoked"); + } + } + } + + public static void printUsage() + { + System.out.println("Usage: OCSPClient " + + " "); + System.out.println(" = OCSP server hostname"); + System.out.println(" = OCSP server port number"); + System.out.println(" = Certificate Database Directory"); + System.out.println(" = Nickname of CA Certificate"); + System.out.println(" = Serial Number Being Checked, Or Name of file that contains the request"); + System.out.println(" = Filename of Response in DER encoding"); + System.out.println(" = Submit Request Multiple Times"); + System.out.println(" [] = OCSP Service URI (i.e. /ocsp/ee/ocsp)"); + } + + public static void main(String args[]) + { + if (args.length != 7 && args.length !=8 ) + { + System.out.println("ERROR: Invalid number of arguments - got " + + args.length + " expected 7!"); + for (int i = 0; i < args.length; i++) { + System.out.println("arg[" + i + "]=" + args[i]); + } + printUsage(); + System.exit(0); + } + + String host = args[0]; + int port = -1; + try { + port = Integer.parseInt(args[1]); + } catch (Exception e) { + System.out.println("Error: Invalid Port Number"); + printUsage(); + System.exit(0); + } + String dbdir = args[2]; + String nickname = args[3]; + int serialno = -1; + byte data[] = null; + try { + serialno = Integer.parseInt(args[4]); + } catch (Exception e) { + try { + System.out.println("Warning: Serial Number not found. It may be a filename."); + /* it could be a file name */ + FileInputStream fis = new FileInputStream(args[4]); + System.out.println("File Size: " + fis.available()); + data = new byte[fis.available()]; + fis.read(data); + } catch (Exception e1) { + System.out.println("Error: Invalid Serial Number or File Name"); + printUsage(); + System.exit(0); + } + } + String output = args[5]; + int times = 1; + try { + times = Integer.parseInt(args[6]); + } catch (Exception e) { + System.out.println("Error: Invalid Times"); + printUsage(); + System.exit(0); + } + String uri = "/ocsp/ee/ocsp"; + if (args.length > 7) { + uri = args[7]; + } + try { + OCSPClient client = + new OCSPClient(host, port, dbdir); + for (int i = 0; i < times; i ++) { + if (data != null) { + client.sendRequestData(uri, nickname, data, output); + } else { + client.send(uri, nickname, serialno, output); + } + } + System.out.println("Success: Output " + output); + } catch (Exception e) { + System.out.println("Error: " + e.toString()); + printUsage(); + System.exit(0); + } + } +} diff --git a/pki/base/java-tools/src/com/netscape/cmstools/PKCS10Client.java b/pki/base/java-tools/src/com/netscape/cmstools/PKCS10Client.java new file mode 100644 index 000000000..150fe5105 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/PKCS10Client.java @@ -0,0 +1,269 @@ +// --- 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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools; + +import java.util.Date; +import java.util.StringTokenizer; +import java.net.URL; +import java.net.URLConnection; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.BufferedReader; +import java.io.PrintStream; +import java.io.File; +import java.io.FileOutputStream; + +import java.net.URLEncoder; +import java.security.KeyPair; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import org.mozilla.jss.util.Password; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.pkcs10.*; +import org.mozilla.jss.crypto.KeyPairGenerator; +import org.mozilla.jss.crypto.KeyPairAlgorithm; +//import netscape.security.provider.RSAPublicKey; +import netscape.security.pkcs.PKCS10; +//import java.security.Signature; +import netscape.security.x509.X500Name; +import netscape.security.util.BigInt; +import netscape.security.x509.X500Signer; +import java.io.ByteArrayOutputStream; + +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.pkix.crmf.*; +import com.netscape.cmsutil.util.*; + + +/** + * Generates a 1024-bit RSA key pair in the security database, constructs a + * PKCS#10 certificate request with the public key, and outputs the request + * to a file. + *

+ * PKCS #10 is a certification request syntax standard defined by RSA. A CA + * may support multiple types of certificate requests. The Certificate System + * CA supports KEYGEN, PKCS#10, CRMF, and CMC. + *

+ * To get a certificate from the CA, the certificate request needs to be + * submitted to and approved by a CA agent. Once approved, a certificate is + * created for the request, and certificate attributes, such as extensions, + * are populated according to certificate profiles. + *

+ * @version $Revision$, $Date$ + */ +public class PKCS10Client +{ + + private static void printUsage() { + System.out.println("Usage: PKCS10Client -p -d -o -s \n"); + } + + public static void main(String args[]) + { + String dbdir = null, ofilename = null, password = null, subjectName = null; + + if (args.length != 8) { + printUsage(); + System.exit(1); + } + + for (int i=0; i + * @version $Revision$, $Date$ + * + */ +public class PKCS12Export { + + private static boolean debugMode = false; + + private static void debug(String s) { + if (debugMode) + System.out.println("PKCS12Export debug: " + s); + } + + private static void printUsage() { + System.out.println("Usage: PKCS12Export -d -p -w -o "); + System.out.println(""); + System.out.println("If you want to turn on debug, do the following:"); + System.out.println("Usage: PKCS12Export -debug -d -p -w -o "); + } + + private static byte[] getEncodedKey(org.mozilla.jss.crypto.PrivateKey pkey) { + try { + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = cm.getInternalKeyStorageToken(); + KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3); + SymmetricKey sk = kg.generate(); + KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD); + byte iv[] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1}; + IVParameterSpec param = new IVParameterSpec(iv); + wrapper.initWrap(sk, param); + byte[] enckey = wrapper.wrap(pkey); + Cipher c = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD); + c.initDecrypt(sk, param); + byte[] recovered = c.doFinal(enckey); + return recovered; + } catch (Exception e) { + debug("PKCS12Export getEncodedKey: Exception="+e.toString()); + System.exit(1); + } + + return null; + } + + private static void addKeyBag(org.mozilla.jss.crypto.PrivateKey pkey, X509Certificate x509cert, + Password pass, byte[] localKeyId, SEQUENCE safeContents) { + try { + PasswordConverter passConverter = new PasswordConverter(); + byte salt[] = {0x01, 0x01, 0x01, 0x01}; + byte[] priData = getEncodedKey(pkey); + + PrivateKeyInfo pki = (PrivateKeyInfo) + ASN1Util.decode(PrivateKeyInfo.getTemplate(), priData); + ASN1Value key = EncryptedPrivateKeyInfo.createPBE( + PBEAlgorithm.PBE_SHA1_DES3_CBC, + pass, salt, 1, passConverter, pki); + SET keyAttrs = createBagAttrs( + x509cert.getSubjectDN().toString(), localKeyId); + SafeBag keyBag = new SafeBag(SafeBag.PKCS8_SHROUDED_KEY_BAG, + key, keyAttrs); + safeContents.addElement(keyBag); + } catch (Exception e) { + debug("PKCS12Export addKeyBag: Exception="+e.toString()); + System.exit(1); + } + } + + private static byte[] addCertBag(X509Certificate x509cert, String nickname, + SEQUENCE safeContents) throws IOException { + byte[] localKeyId = null; + try { + ASN1Value cert = new OCTET_STRING(x509cert.getEncoded()); + localKeyId = createLocalKeyId(x509cert); + SET certAttrs = null; + if (nickname != null) + certAttrs = createBagAttrs(nickname, localKeyId); + SafeBag certBag = new SafeBag(SafeBag.CERT_BAG, + new CertBag(CertBag.X509_CERT_TYPE, cert), certAttrs); + safeContents.addElement(certBag); + } catch (Exception e) { + debug("PKCS12Export addCertBag: "+e.toString()); + System.exit(1); + } + + return localKeyId; + } + + private static byte[] createLocalKeyId(X509Certificate cert) { + try { + // SHA1 hash of the X509Cert der encoding + byte certDer[] = cert.getEncoded(); + + MessageDigest md = MessageDigest.getInstance("SHA"); + + md.update(certDer); + return md.digest(); + } catch (Exception e) { + debug("PKCS12Export createLocalKeyId: Exception: "+e.toString()); + System.exit(1); + } + + return null; + } + + private static SET createBagAttrs(String nickName, byte localKeyId[]) + throws IOException { + try { + SET attrs = new SET(); + SEQUENCE nickNameAttr = new SEQUENCE(); + + nickNameAttr.addElement(SafeBag.FRIENDLY_NAME); + SET nickNameSet = new SET(); + + nickNameSet.addElement(new BMPString(nickName)); + nickNameAttr.addElement(nickNameSet); + attrs.addElement(nickNameAttr); + SEQUENCE localKeyAttr = new SEQUENCE(); + + localKeyAttr.addElement(SafeBag.LOCAL_KEY_ID); + SET localKeySet = new SET(); + + localKeySet.addElement(new OCTET_STRING(localKeyId)); + localKeyAttr.addElement(localKeySet); + attrs.addElement(localKeyAttr); + return attrs; + } catch (Exception e) { + debug("PKCS12Export createBagAttrs: Exception="+e.toString()); + System.exit(1); + } + + return null; + } + + public static void main(String args[]) { + if (args.length < 8) { + printUsage(); + System.exit(1); + } + + String pwdfile = null; + String dir = null; + String snickname = null; + String pk12pwdfile = null; + String pk12output = null; + for (int i=0; i/config directory, unless the file's full path is specified in the -c option..\nUsage: PasswordCache <-d cert/key db directory> <-h tokenName> <-P cert/key db prefix> <-c pwcache.db_file_full_path> <-k file containing Base64EncodedKeyID> ..."); + System.out.println(" commands:"); + System.out.println(" 'add '"); + System.out.println(" 'change '"); + System.out.println(" 'delete '"); + System.out.println(" 'rekey'"); + System.out.println(" 'list'"); + System.out.println("\nExample:\n\tPasswordCache thePassword1 -d /usr/netscape/servers/cms/alias -P cert-instance1-machine1- -c pwcache.db -k keyidFile list"); + System.exit(1); + } + + private static boolean debugMode = false; + + public PasswordCache() { + } + + private static void debug (String s) { + if (debugMode == true) + System.out.println("PasswordCache debug: "+s); + } + + /** + * clean up an argv by removing the trailing, empty arguments + * + * This is necessary to support the script wrapper which calls the + * tool with arguments in quotes such as: + * "$1" "$2" + * if $2 is not specified, the empty arg "" gets passed, which causes + * an error in the arg-count checking code. + */ + private static String[] cleanArgs(String[] s) { + int length; + int i; + + length = s.length; + debug("before cleanArgs argv length ="+length); + + for (i = length - 1; i >= 0; i--) { + if (s[i].equals("")) { + length--; + } else { + break; + } + } + + String[] new_av = new String[length]; + for (i = 0; i < length; i++) { + new_av[i] = s[i]; + debug("arg "+i+" is "+new_av[i]); + } + debug("after cleanArgs argv length ="+length); + + return new_av; + } + + public static byte[] base64Decode(String s) throws IOException { + byte[] d = com.netscape.osutil.OSUtil.AtoB(s); + return d; + } + + public static String base64Encode(byte[] bytes) throws IOException { + // All this streaming is lame, but Base64OutputStream needs a + // PrintStream + ByteArrayOutputStream output = new ByteArrayOutputStream(); + Base64OutputStream b64 = new Base64OutputStream(new + PrintStream(new + FilterOutputStream(output) + ) + ); + + b64.write(bytes); + b64.flush(); + + // This is internationally safe because Base64 chars are + // contained within 8859_1 + return output.toString("8859_1"); + } + + public static void main(String[]av) { + // default path is "." + String mPath = "."; + String mTokenName = null; + // default prefix is "" + String mPrefix = ""; + String mKeyIdString = null; + byte[] mKeyId = null; + String mCertDB = CERTDB; + String mKeyDB = KEYDB; + String mCacheFile = "pwcache.db"; + + String pwdPath = null; + String instancePath = null; + String instanceName = null; + + String[] argv = cleanArgs(av); + + if (argv.length < 2) { + usage(); + } + + String pw = argv[0]; + + char[] testpw = pw.toCharArray(); + Password pass = new Password(testpw); + + String command = ""; + String aTag = ""; + String aPasswd = ""; + + int i = 0; + for ( i = 1; i < argv.length; ++i) { + if( argv[i].equals("-d") ) { + if( ++i >= argv.length ) usage(); + mPath = argv[i]; + } else if( argv[i].equals("-h") ) { + if( ++i >= argv.length ) usage(); + mTokenName = argv[i]; + } else if( argv[i].equals("-P") ) { + if( ++i >= argv.length ) usage(); + mPrefix = argv[i]; + } else if( argv[i].equals("-c") ) { + if( ++i >= argv.length ) usage(); + mCacheFile = argv[i]; + } else if (argv[i].equals("-k") ) { + if( ++i >= argv.length ) usage(); + String keyFile = argv[i]; + try { + BufferedReader r = new BufferedReader(new FileReader(keyFile)); + String listLine; + mKeyIdString = r.readLine(); + } catch (Exception e) { + System.out.println("Error: "+e.toString()); + System.exit(1); + } + + if (mKeyIdString != null) { + try { + mKeyId = base64Decode(mKeyIdString); + debug("base64Decode of key id string successful"); + } catch (IOException e) { + System.out.println("base64Decode of key id string failed"); + System.exit(1); + } + } + } else { + command = argv[i++]; + debug("command = "+command); + + if ((command.equals("add")) || + (command.equals("change"))) { + aTag = argv[i++]; + aPasswd = argv[i]; + debug("command is "+command+" "+aTag+":"+aPasswd); + } else if (command.equals("delete")) { + aTag = argv[i]; + } else if (command.equals("list")) { + } else if (command.equals("rekey")) { + } + break; + } + } + + try { + // initialize CryptoManager + System.out.println("cert/key prefix = " + mPrefix); + System.out.println("cert/key db path = " + mPath); + System.out.println("password cache file = " + mCacheFile); + + CryptoManager.InitializationValues vals = + new CryptoManager.InitializationValues(mPath, mPrefix, + mPrefix, "secmod.db"); + + CryptoManager.initialize(vals); + + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = null; + if (mTokenName == null) { + token = cm.getInternalKeyStorageToken(); + System.out.println("token name = internal"); + } else { + token = cm.getTokenByName(mTokenName); + System.out.println("token name = "+ mTokenName); + } + + token.login(pass); + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + + // generating new key + if (command.equals("rekey")) { + System.out.println("generating new key..."); + PWsdrCache cache = null; + try { + // compose instance name + File passwordCacheDB = new File( mCacheFile ); + pwdPath = passwordCacheDB.getAbsolutePath(); + int beginIndex = pwdPath.lastIndexOf( "cert-" ); + instancePath = pwdPath.substring( beginIndex ); + int endIndex = 0; + endIndex = instancePath.lastIndexOf( "config" ); + instanceName = instancePath.substring( 0, ( endIndex - 1 ) ); + + cache = new PWsdrCache(mCacheFile, mTokenName, null, true); + cache.deleteUniqueNamedKey( PROP_PWC_NICKNAME + + " " + + instanceName ); + byte[] newKeyId = cache.generateSDRKeyWithNickName( + PROP_PWC_NICKNAME + + " " + + instanceName ); + if (newKeyId != null) { + String newKeyIDString = base64Encode(newKeyId); + System.out.println("key generated successfully with key id = "+ + newKeyIDString); + System.out.println("Save the VALUE portion of this key id in a local file,"); + System.out.println("and under variable \"pwcKeyid\" in CS.cfg !!"); + System.out.println("If you have not already done so,"); + System.out.println("remove the old pwcache.db and use this local file to add passwords."); + // job is done + System.exit(0); + } else { + System.out.println("key expected to be generated but wasn't"); + System.exit(1); + } + } catch (Exception e) { + System.out.println(e.toString()); + System.exit(1); + } + } + + PWsdrCache cache = null; + try { + cache = new PWsdrCache(mCacheFile, mTokenName, mKeyId, true); + } catch (Exception e) { + System.out.println(e.toString()); + System.exit(1); + } + + if ((command.equals("add")) || (command.equals("change"))) { + // current key id must be specified + if (mKeyId == null) { + System.out.println("operation failed: no key id specified"); + System.exit(1); + } + + try { + System.out.println("adding "+aTag+":"+aPasswd); + cache.addEntry(aTag, aPasswd); + } catch (Exception e) { + System.out.println("--failed--"+ e.toString()); + } + } else if (command.equals("list")) { + cache.pprint(); + } else if (command.equals("delete")) { + // current key id must be specified + if (mKeyId == null) { + System.out.println("operation failed: no key id specified"); + System.exit(1); + } + + try { + cache.deleteEntry(aTag); + } catch (Exception e) { + System.out.println("User not found"); + } + } else { + System.out.println("Illegal command: " + command); + System.exit(1); + } + } + + private static boolean badPassword(String pwd) { + // XXX - implement only password checking + return false; +/* + PasswordChecker pwdChecker = new PasswordChecker(); + + if (!pwdChecker.isGoodPassword(pwd)) { + String reason = pwdChecker.getReason(pwd); + + System.out.println("New password does not pass password " + + "quality test: " + reason); + return true; + } else { + return false; + } +*/ + } +} + + +/* + * A class for managing passwords in the SDR password cache + * + * @author Christina Fu + * @version $Revision$, $Date$ + */ +class PWsdrCache { + + public static final String PROP_PWC_NICKNAME = "sso_key"; + + private String mPWcachedb = null; + private byte[] mKeyID = null; + private String mTokenName = null; + private CryptoToken mToken = null; + + // mTool tells if this is called from the PasswordCache tool + private boolean mIsTool = false; + + // for PasswordCache tool (isTool == true) + public PWsdrCache(String pwCache, String pwcTokenname, byte[] keyId, + boolean isTool) throws Exception { + mPWcachedb = pwCache; + mIsTool = isTool; + mTokenName = pwcTokenname; + CryptoManager cm = null; + + if (keyId != null) { + mKeyID = keyId; + } + + cm = CryptoManager.getInstance(); + if (mTokenName != null) { + mToken = cm.getTokenByName(mTokenName); + debug("PWsdrCache: mToken = "+mTokenName); + } else { + mToken = cm.getInternalKeyStorageToken(); + debug("PWsdrCache: mToken = internal"); + } + } + + public byte[] getKeyId() { + return mKeyID; + } + + public String getTokenName() { + return mTokenName; + } + + public void deleteUniqueNamedKey( String nickName ) + throws Exception + { + KeyManager km = new KeyManager( mToken ); + km.deleteUniqueNamedKey( nickName ); + } + + public byte[] generateSDRKey() throws Exception { + return generateSDRKeyWithNickName(PROP_PWC_NICKNAME); + } + + public byte[] generateSDRKeyWithNickName( String nickName ) + throws Exception + { + try { + if (mIsTool == true) { + // generate SDR key + KeyManager km = new KeyManager(mToken); + try { + // Bugscape Bug #54838: Due to the CMS cloning feature, + // we must check for the presence of + // a uniquely named symmetric key + // prior to making an attempt to + // generate it! + // + if( !( km.uniqueNamedKeyExists( nickName ) ) ) { + mKeyID = km.generateUniqueNamedKey( nickName ); + debug("PWsdrCache: SDR key generated"); + } + } catch (TokenException e) { + log (0, "generateSDRKey() failed on "+e.toString()); + throw e; + } + } + } catch (Exception e) { + log (0, e.toString()); + throw e; + } + return mKeyID; + } + + public void addEntry(String tag, String pwd) throws IOException { + addEntry(tag, pwd, (Hashtable) null); + } + + /* + * Store passwd in pwcache. + */ + public void addEntry(Hashtable ht) throws IOException { + addEntry((String) null, (String) null, ht); + } + + /* + * add passwd in pwcache. + */ + public void addEntry(String tag, String pwd, Hashtable tagPwds) throws IOException { + System.out.println("PWsdrCache: in addEntry"); + String stringToAdd = null; + String bufs = null; + + if (tagPwds == null) { + stringToAdd = tag + ":" + pwd + "\n"; + } else { + Enumeration enum1 = tagPwds.keys(); + + while (enum1.hasMoreElements()) { + tag = (String) enum1.nextElement(); + pwd = (String) tagPwds.get(tag); + debug("password tag: " + tag + " stored in " + mPWcachedb); + + if (stringToAdd == null) { + stringToAdd = tag + ":" + pwd + "\n"; + } else { + stringToAdd += tag + ":" + pwd + "\n"; + } + } + } + + String dcrypts = readPWcache(); + System.out.println("PWsdrCache: after readPWcache()"); + if (dcrypts != null) { + // converts to Hashtable, replace if tag exists, add + // if tag doesn't exist + Hashtable ht = string2Hashtable(dcrypts); + + if (ht.containsKey(tag) == false) { + debug("adding new tag: " + tag); + ht.put(tag, pwd); + } else { + debug("replacing tag: " + tag); + ht.put(tag, pwd); + } + bufs = hashtable2String(ht); + } else { + debug("adding new tag: " + tag); + bufs = stringToAdd; + } + + // write update to cache + writePWcache(bufs); + } + + /* + * delete passwd in pwcache. + */ + public void deleteEntry(String tag) throws IOException { + String bufs = null; + + String dcrypts = readPWcache(); + + if (dcrypts != null) { + // converts to Hashtable, replace if tag exists, add + // if tag doesn't exist + Hashtable ht = string2Hashtable(dcrypts); + + if (ht.containsKey(tag) == false) { + debug("tag: " + tag + " does not exist"); + return; + } else { + debug("deleting tag: " + tag); + ht.remove(tag); + } + bufs = hashtable2String(ht); + } else { + debug("password cache contains no tags"); + return; + } + + // write update to cache + writePWcache(bufs); + } + + /* + * reads and decrypts the pwcache.db content + */ + public String readPWcache() throws IOException { + debug("about to read password cache"); + String dcrypts = null; + if (mToken == null) { + debug("mToken is null"); + throw new IOException("token must be specified"); + } + + Decryptor sdr = new Decryptor(mToken); + + // not used, but could used for debugging + int totalRead = 0; + FileInputStream inputs = null; + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + try { + // for SDR -> read, decrypt, append, and write + inputs = new FileInputStream(mPWcachedb); + byte[] readbuf = new byte[2048]; // for now + int numRead = 0; + + while ((numRead = inputs.read(readbuf)) != -1) { + bos.write(readbuf, 0, numRead); + totalRead += numRead; + } + inputs.close(); + } catch (FileNotFoundException e) { + System.out.println("Failed for file " + mPWcachedb + " " + e.toString()); + throw new IOException(e.toString() + ": " + mPWcachedb); + } catch (IOException e) { + System.out.println("Failed for file " + mPWcachedb + " " + e.toString()); + throw new IOException(e.toString() + ": " + mPWcachedb); + } + + if (totalRead > 0) { + try { + // decrypt it first to append + byte[] dcryptb = sdr.decrypt(bos.toByteArray()); + + dcrypts = new String(dcryptb, "UTF-8"); + } catch (TokenException e) { + System.out.println("password cache decrypto failed " + e.toString()); + e.printStackTrace(); + throw new IOException("password cache decrypt failed"); + } catch (UnsupportedEncodingException e) { + System.out.println("password cache decrypto failed " + e.toString()); + e.printStackTrace(); + throw new IOException("password cache decrypt failed"); + } catch (Exception e) { + System.out.println("password cache decrypto failed " + e.toString()); + e.printStackTrace(); + throw new IOException("password cache decrypt failed"); + } + } + + return dcrypts; + } + + /* + * encrypts and writes the whole String buf into pwcache.db + */ + public void writePWcache(String bufs) throws IOException { + + + try { + Encryptor sdr = new Encryptor(mToken, mKeyID, + Encryptor.DEFAULT_ENCRYPTION_ALG); + + byte[] writebuf = null; + + try { + // now encrypt it again + writebuf = sdr.encrypt(bufs.getBytes("UTF-8")); + } catch (Exception e) { + System.out.println("password cache encrypt failed " + e.toString()); + e.printStackTrace(); + throw new IOException("password cache encrypt failed"); + } + + File tmpPWcache = new File(mPWcachedb + ".tmp"); + + if (tmpPWcache.exists()) { + // it wasn't removed? + tmpPWcache.delete(); + } + FileOutputStream outstream = new FileOutputStream(mPWcachedb + ".tmp"); + + outstream.write(writebuf); + outstream.close(); + + // Make certain that this temporary file has + // the correct permissions. + if( !isNT() ) { + exec( "chmod 00660 " + tmpPWcache.getAbsolutePath() ); + } + + File origFile = new File(mPWcachedb); + + try { + // Always remove any pre-existing target file + if( origFile.exists() ) { + origFile.delete(); + } + + if (isNT()) { + // NT is very picky on the path + exec("copy " + + tmpPWcache.getAbsolutePath().replace('/', '\\') + " " + + origFile.getAbsolutePath().replace('/', '\\')); + } else { + // Create a copy of the temporary file which + // preserves the temporary file's permissions. + exec("cp -p " + tmpPWcache.getAbsolutePath() + " " + + origFile.getAbsolutePath()); + } + + // Remove the temporary file if and only if + // the "rename" was successful. + if( origFile.exists() ) { + tmpPWcache.delete(); + + // Make certain that the final file has + // the correct permissions. + if( !isNT() ) { + exec( "chmod 00660 " + origFile.getAbsolutePath() ); + } + + // report success + debug( "Renaming operation completed for " + mPWcachedb ); + } else { + // report failure and exit + debug( "Renaming operation failed for " + mPWcachedb ); + System.exit(1); + } + } catch (IOException exx) { + System.out.println("sdrPWcache: Error " + exx.toString()); + throw new IOException(exx.toString() + ": " + mPWcachedb); + } + } catch (FileNotFoundException e) { + System.out.println("sdrPWcache: Error " + e.toString()); + throw new IOException(e.toString() + ": " + mPWcachedb); + } catch (IOException e) { + System.out.println("Failed for file " + mPWcachedb + " " + e.toString()); + throw new IOException(e.toString() + ": " + mPWcachedb); + } catch (Exception e) { + System.out.println("sdrPWcache: Error " + e.toString()); + throw new IOException(e.toString()); + } + } + + public String hashtable2String(Hashtable ht) { + Enumeration enum1 = ht.keys(); + String returnString = null; + + while (enum1.hasMoreElements()) { + String tag = (String) enum1.nextElement(); + String pwd = (String) ht.get(tag); + + if (returnString == null) { + returnString = tag + ":" + pwd + "\n"; + } else { + returnString += tag + ":" + pwd + "\n"; + } + } + return returnString; + } + + public Hashtable string2Hashtable(String cache) { + Hashtable ht = new Hashtable(); + + // first, break into lines + StringTokenizer st = new StringTokenizer(cache, "\n"); + + while (st.hasMoreTokens()) { + String line = (String) st.nextToken(); + // break into tag:password format for each line + int colonIdx = line.indexOf(":"); + + if (colonIdx != -1) { + String tag = line.substring(0, colonIdx); + String passwd = line.substring(colonIdx + 1, + line.length()); + + ht.put(tag.trim(), passwd.trim()); + } else { + //invalid format...log or throw...later + } + } + return ht; + } + + /* + * get password from cache. This one supplies cache file name + */ + public Password getEntry(String fileName, String tag) { + mPWcachedb = fileName; + return getEntry(tag); + } + + /* + * if tag found with pwd, return it + * if tag not found, return null, which will cause it to give up + */ + public Password getEntry(String tag) { + Hashtable pwTable = null; + String pw = null; + + debug("in getEntry, tag=" + tag); + + if (mPWcachedb == null) { + debug("mPWcachedb file path name is not initialized"); + return null; + } + + String dcrypts = null; + + try { + dcrypts = readPWcache(); + } catch (IOException e) { + System.out.println("dfailed readPWcache() " + e.toString()); + return null; + } + + if (dcrypts != null) { + // parse the cache + String cache = dcrypts; + + // this is created and destroyed at each use + pwTable = string2Hashtable(cache); + debug("in getEntry, pw cache parsed"); + pw = (String) pwTable.get(tag); + } + + if (pw != null) { + debug("getEntry gotten password for " + tag); + return new Password(pw.toCharArray()); + } else { + System.out.println("getEntry did not get password for tag " + tag); + return null; + } + } + + //copied from IOUtil.java + /** + * Checks if this is NT. + */ + public static boolean isNT() { + return ((File.separator).equals("\\")); + } + + public static boolean exec(String cmd) throws IOException { + try { + String cmds[] = null; + + if (isNT()) { + // NT + cmds = new String[3]; + cmds[0] = "cmd"; + cmds[1] = "/c"; + cmds[2] = cmd; + } else { + // UNIX + cmds = new String[3]; + cmds[0] = "/bin/sh"; + cmds[1] = "-c"; + cmds[2] = cmd; + } + Process process = Runtime.getRuntime().exec(cmds); + + process.waitFor(); + BufferedReader pOut = null; + String l = null; + + if (process.exitValue() == 0) { + + /** + pOut = new BufferedReader( + new InputStreamReader(process.getInputStream())); + while ((l = pOut.readLine()) != null) { + System.out.println(l); + } + **/ + return true; + } else { + + /** + pOut = new BufferedReader( + new InputStreamReader(process.getErrorStream())); + l = null; + while ((l = pOut.readLine()) != null) { + System.out.println(l); + } + **/ + return false; + } + } catch (Exception e) { + return false; + } + } + + public void debug(String msg) { + System.out.println(msg); + } + + public void log(int level, String msg) { + System.out.println(msg); + } + + /* + * list passwds in pwcache. + */ + public boolean pprint() { + String bufs = null; + String dcrypts = null; + + try { + dcrypts = readPWcache(); + } catch (IOException e) { + System.out.println("failed readPWcache() " + e.toString()); + return false; + } + + debug("----- Password Cache Content -----"); + + if (dcrypts != null) { + // first, break into lines + StringTokenizer st = new StringTokenizer(dcrypts, "\n"); + + while (st.hasMoreTokens()) { + String line = (String) st.nextToken(); + // break into tag:password format for each line + int colonIdx = line.indexOf(":"); + + if (colonIdx != -1) { + String tag = line.substring(0, colonIdx); + String passwd = line.substring(colonIdx + 1, + line.length()); + + debug(tag.trim() + + " : " + passwd.trim()); + } else { + //invalid format...log or throw...later + debug("invalid format"); + } + } + } // else print nothing + return true; + } +} diff --git a/pki/base/java-tools/src/com/netscape/cmstools/PrettyPrintCert.java b/pki/base/java-tools/src/com/netscape/cmstools/PrettyPrintCert.java new file mode 100644 index 000000000..b5ed8177f --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/PrettyPrintCert.java @@ -0,0 +1,233 @@ +// --- 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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools; + + +import java.io.*; +import java.util.*; +import java.security.*; +import java.security.cert.*; +import netscape.security.x509.*; +import netscape.security.util.*; + + +/** + * The PrettyPrintCert class is a utility program designed to "pretty print" + * a certificate. It assumes that the name of a data file is passed to the + * program via the command line, and that the contents contain a certificate + * encoded in an ASCII BASE 64 format. Note that the data file may contain + * an optional "-----BEGIN" header and/or an optional "-----END" trailer. + * + *

+ * The program may be invoked as follows: + *

+ *
+ *      PrettyPrintCert <input filename> [output filename]
+ *
+ *      NOTE:  <input filename>   must contain an ASCII
+ *                                BASE 64 encoded certificate
+ *
+ *             <output filename>  contains a certificate displayed
+ *                                in a "pretty print" ASCII format
+ * 
+ * + * @version $Revision$, $Date$ + */ + +public class PrettyPrintCert { + // Define constants + public static final int ARGC = 2; + public static final String HEADER = "-----BEGIN"; + public static final String TRAILER = "-----END"; + + public static void usageAndExit() { + System.out.println("Usage: PrettyPrintCert " + + "[options] " + + " " + + "[output filename]"); + System.out.println("\n options: "); + System.out.println(" -simpleinfo : prints limited cert info in easy to parse format"); + System.exit(0); + } + + public static void main(String argv[]) { + + BufferedReader inputCert = null; + String encodedBASE64CertChunk = new String(); + String encodedBASE64Cert = new String(); + byte decodedBASE64Cert[] = null; + X509CertImpl cert = null; + Locale aLocale = null; + CertPrettyPrint certDetails = null; + String pp = new String(); + FileOutputStream outputCert = null; + boolean mSimpleInfo = false; + String inputfile = null; + String outputfile = null; + + // parse arguments + + for (int i = 0; i < argv.length; i++) { + + // deal with empty arguments passed in by script + if (argv[i].equals("")) { + continue; + } + + // parse options + if (argv[i].charAt(0) == '-') { + if (argv[i].equals("-simpleinfo")) { + mSimpleInfo = true; + continue; + } else { + System.out.println("Illegal option: " + argv[i]); + usageAndExit(); + } + } + + // deal with filename + + if (inputfile == null) { + inputfile = argv[i]; + continue; + } + + if (outputfile == null) { + outputfile = argv[i]; + continue; + } + + System.out.println("Error - Too many arguments"); + System.exit(0); + } + + if (inputfile == null) { + usageAndExit(); + } + + // (2) Create a DataInputStream() object to the BASE 64 + // encoded certificate contained within the file + // specified on the command line + try { + inputCert = new BufferedReader(new InputStreamReader( + new BufferedInputStream( + new FileInputStream( + inputfile)))); + } catch (FileNotFoundException e) { + System.out.println("PrettyPrintCert: can't find file " + + inputfile + ":\n" + e); + return; + } + + // (3) Read the entire contents of the specified BASE 64 encoded + // certificate into a String() object throwing away any + // headers beginning with HEADER and any trailers beginning + // with TRAILER + try { + while ((encodedBASE64CertChunk = inputCert.readLine()) != null) { + if (!(encodedBASE64CertChunk.startsWith(HEADER)) && + !(encodedBASE64CertChunk.startsWith(TRAILER))) { + encodedBASE64Cert += encodedBASE64CertChunk.trim(); + } + } + } catch (IOException e) { + System.out.println("PrettyPrintCert: Unexpected BASE64 " + + "encoded error encountered in readLine():\n" + + e); + } + + // (4) Close the DataInputStream() object + try { + inputCert.close(); + } catch (IOException e) { + System.out.println("PrettyPrintCert: Unexpected BASE64 " + + "encoded error encountered in close():\n" + e); + } + + // (5) Decode the ASCII BASE 64 certificate enclosed in the + // String() object into a BINARY BASE 64 byte[] object + + decodedBASE64Cert = com.netscape.osutil.OSUtil.AtoB(encodedBASE64Cert); + + // (6) Create an X509CertImpl() object from the BINARY BASE 64 + // byte[] object + try { + cert = new X509CertImpl(decodedBASE64Cert); + } catch (CertificateException e) { + System.out.println("PrettyPrintCert: Error encountered " + + "on parsing certificate :\n" + e); + } + + if (mSimpleInfo) { + try { + X509CertInfo certinfo = (X509CertInfo) cert.get("x509.INFO"); + + CertificateSubjectName csn = (CertificateSubjectName) + certinfo.get(X509CertInfo.SUBJECT); + + Enumeration en = csn.getElements(); + + X500Name dname = (X500Name) csn.get(CertificateSubjectName.DN_NAME); + + pp = ""; + RDN[] rdns = dname.getNames(); + + for (int i = rdns.length - 1; i >= 0; i--) { + pp = pp + rdns[i] + "\n"; + } + + } catch (Exception e) { + System.out.println("ERROR"); + e.printStackTrace(); + } + } else { + // (7) For this utility, always specify the default Locale + aLocale = Locale.getDefault(); + + // (8) Create a CertPrettyPrint() object + certDetails = new CertPrettyPrint(cert); + + // (9) Convert the CertPrettyPrint() object into a String() object + pp = certDetails.toString(aLocale); + } + + // (10) Finally, "pretty print" the actual certificate to the console + // unless an output file has been specified + if (outputfile == null) { + System.out.println(pp); + } else { + try { + outputCert = new FileOutputStream(outputfile); + } catch (IOException e) { + System.out.println("PrettyPrintCert: unable to open file " + + argv[1] + " for writing:\n" + e); + return; + } + + try { + outputCert.write(pp.getBytes()); + outputCert.close(); + } catch (IOException e) { + System.out.println("PrettyPrintCert: Unexpected error " + + "encountered while attempting to close() " + + outputfile + ":\n" + e); + } + } + } +} + diff --git a/pki/base/java-tools/src/com/netscape/cmstools/PrettyPrintCrl.java b/pki/base/java-tools/src/com/netscape/cmstools/PrettyPrintCrl.java new file mode 100644 index 000000000..4d410f16f --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/PrettyPrintCrl.java @@ -0,0 +1,199 @@ +// --- 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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools; + + +import java.io.*; +import java.util.*; +import java.security.*; +import java.security.cert.*; +import netscape.security.x509.*; +import netscape.security.util.*; + + +/** + * The PrettyPrintCrl class is a utility program designed to "pretty print" + * a CRL. It assumes that the name of a data file is passed to the + * program via the command line, and that the contents contain a CRL + * encoded in an ASCII BASE 64 format. Note that the data file may contain + * an optional "-----BEGIN" header and/or an optional "-----END" trailer. + * + *

+ * The program may be invoked as follows: + *

+ *
+ *      PrettyPrintCrl <input filename> [output filename]
+ *
+ *      NOTE:  <input filename>   must contain an ASCII
+ *                                BASE 64 encoded CRL
+ *
+ *             <output filename>  contains a CRL displayed
+ *                                in a "pretty print" ASCII format
+ * 
+ * + * @version $Revision$, $Date$ + */ + +public class PrettyPrintCrl { + // Define constants + public static final int ARGC = 2; + public static final String HEADER = "-----BEGIN"; + public static final String TRAILER = "-----END"; + + public static void main(String argv[]) { + + BufferedReader inputCrl = null; + String encodedBASE64CrlChunk = new String(); + String encodedBASE64Crl = new String(); + byte decodedBASE64Crl[] = null; + X509CRLImpl crl = null; + Locale aLocale = null; + CrlPrettyPrint CrlDetails = null; + String pp = new String(); + FileOutputStream outputCrl = null; + + // (1) Check that at least one argument was submitted to the program + if ((argv.length < 1) || (argv.length > ARGC)) { + System.out.println("Usage: PrettyPrintCrl " + + " " + + "[output filename]"); + return; + } + + try { + OIDMap.addAttribute(DeltaCRLIndicatorExtension.class.getName(), + DeltaCRLIndicatorExtension.OID, + DeltaCRLIndicatorExtension.NAME); + } catch (CertificateException e) { + } + try { + OIDMap.addAttribute(HoldInstructionExtension.class.getName(), + HoldInstructionExtension.OID, + HoldInstructionExtension.NAME); + } catch (CertificateException e) { + } + try { + OIDMap.addAttribute(InvalidityDateExtension.class.getName(), + InvalidityDateExtension.OID, + InvalidityDateExtension.NAME); + } catch (CertificateException e) { + } + try { + OIDMap.addAttribute(IssuingDistributionPointExtension.class.getName(), + IssuingDistributionPointExtension.OID, + IssuingDistributionPointExtension.NAME); + } catch (CertificateException e) { + } + + // (2) Create a DataInputStream() object to the BASE 64 + // encoded CRL contained within the file + // specified on the command line + try { + inputCrl = new BufferedReader(new InputStreamReader( + new BufferedInputStream( + new FileInputStream( + argv[0])))); + } catch (FileNotFoundException e) { + System.out.println("PrettyPrintCrl(): can''t find file " + + argv[0] + ":\n" + e); + return; + } + + // (3) Read the entire contents of the specified BASE 64 encoded + // CRL into a String() object throwing away any + // headers beginning with HEADER and any trailers beginning + // with TRAILER + try { + while ((encodedBASE64CrlChunk = inputCrl.readLine()) != null) { + if (!(encodedBASE64CrlChunk.startsWith(HEADER)) && + !(encodedBASE64CrlChunk.startsWith(TRAILER))) { + encodedBASE64Crl += encodedBASE64CrlChunk.trim(); + } + } + } catch (IOException e) { + System.out.println("PrettyPrintCrl(): Unexpected BASE64 " + + "encoded error encountered in readLine():\n" + + e); + } + + // (4) Close the DataInputStream() object + try { + inputCrl.close(); + } catch (IOException e) { + System.out.println("PrettyPrintCrl(): Unexpected BASE64 " + + "encoded error encountered in close():\n" + e); + } + + // (5) Decode the ASCII BASE 64 CRL enclosed in the + // String() object into a BINARY BASE 64 byte[] object + + decodedBASE64Crl = com.netscape.osutil.OSUtil.AtoB(encodedBASE64Crl); + + // (6) Create an X509CRLImpl() object from the BINARY BASE 64 + // byte[] object + try { + crl = new X509CRLImpl(decodedBASE64Crl); + } catch (CRLException e) { + System.out.println("PrettyPrintCrl(): Error encountered " + + "on parsing and initialization errors:\n" + e); + } catch (X509ExtensionException e) { + System.out.println("PrettyPrintCrl(): Error encountered " + + "on parsing and initialization errors:\n" + e); + } + + // (7) For this utility, always specify the default Locale + aLocale = Locale.getDefault(); + + // (8) Create a CrlPrettyPrint() object + CrlDetails = new CrlPrettyPrint(crl); + + // (9) Convert the CrlPrettyPrint() object into a String() object + pp = CrlDetails.toString(aLocale); + + // (10) Finally, "pretty print" the actual CRL to the console + // unless an output file has been specified + if (argv.length != ARGC) { + System.out.println(pp); + } else { + try { + outputCrl = new FileOutputStream(argv[1]); + } catch (IOException e) { + System.out.println("PrettyPrintCrl(): unable to open file " + + argv[1] + " for writing:\n" + e); + return; + } + + try { + outputCrl.write(pp.getBytes()); + } catch (IOException e) { + System.out.println("PrettyPrintCrl(): I/O error " + + "encountered during write():\n" + + e); + } + + try { + outputCrl.close(); + } catch (IOException e) { + System.out.println("PrettyPrintCrl(): Unexpected error " + + "encountered while attempting to close() " + + argv[1] + ":\n" + e); + } + } + } +} + diff --git a/pki/base/java-tools/src/com/netscape/cmstools/TestCRLSigning.java b/pki/base/java-tools/src/com/netscape/cmstools/TestCRLSigning.java new file mode 100644 index 000000000..b4fdf5d04 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/TestCRLSigning.java @@ -0,0 +1,135 @@ +// --- 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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools; + +import java.io.*; +import java.net.*; +import java.math.*; +import java.util.*; +import java.security.*; + +import org.mozilla.jss.*; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.util.*; +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.pkix.crmf.*; +import org.mozilla.jss.pkcs7.ContentInfo; +import org.mozilla.jss.pkcs7.*; +import org.mozilla.jss.pkcs11.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.crypto.KeyPairGenerator; +import org.mozilla.jss.crypto.PrivateKey; +import org.mozilla.jss.crypto.Signature; +import org.mozilla.jss.crypto.X509Certificate; +import org.mozilla.jss.util.Base64OutputStream; +import org.mozilla.jss.util.*; +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.CertDatabaseException; +import org.mozilla.jss.pkcs11.*; +import org.mozilla.jss.pkcs11.PK11Token; + +import netscape.security.x509.*; + +import com.netscape.cmsutil.ocsp.*; +import com.netscape.cmsutil.ocsp.Request; + +/** + * Tool used to test out signing a CRL + * + *

+ * @version $Revision$ Date: $ + */ +public class TestCRLSigning +{ + public static void printUsage() + { + System.out.println("Command "); + } + + public static void main(String args[]) throws Exception + { + String dir = args[0]; + String num = args[1]; + String keysize = args[2]; + String tokenname = args[3]; + String tokenpwd = args[4]; + + // initialize JSS + CryptoManager cm = null; + CryptoManager.InitializationValues vals = + new CryptoManager.InitializationValues(dir, "", "", "secmod.db"); + CryptoManager.initialize(vals); + cm = CryptoManager.getInstance(); + + // Login to token + CryptoToken token = null; + if (tokenname.equals("internal")) { + token = cm.getInternalKeyStorageToken(); + } else { + token = cm.getTokenByName(tokenname); + } + Password pass = new Password(tokenpwd.toCharArray()); + token.login(pass); + + // generate key pair + KeyPairGenerator g = token.getKeyPairGenerator(KeyPairAlgorithm.RSA); + g.initialize(Integer.parseInt(keysize)); + KeyPair pair = g.genKeyPair(); + + // generate revoked certificates + long startPutting = System.currentTimeMillis(); + Date curDate = new Date(); + Hashtable badCerts = new Hashtable(); + int n = Integer.parseInt(num); + for (int i = 0; i < n; i++) { + badCerts.put(Integer.toString(i), + new RevokedCertImpl(new BigInteger(Integer.toString(i)), curDate)); + } + long endPutting = System.currentTimeMillis(); + + long startConstructing = System.currentTimeMillis(); + X509CRLImpl crl = new X509CRLImpl( + new X500Name("CN=Signer"), + null, + curDate, + curDate, + badCerts, + null); + long endConstructing = System.currentTimeMillis(); + + + System.out.println("Start signing"); + long startSigning = System.currentTimeMillis(); + crl.sign(pair.getPrivate(), "SHA1withRSA"); + long endSigning = System.currentTimeMillis(); + System.out.println("Done signing"); + + long startData = System.currentTimeMillis(); + byte data[] = crl.getTBSCertList(); + long endData = System.currentTimeMillis(); + + System.out.println("Summary:"); + System.out.println("Insertion time (ms): " + Long.toString(endPutting - startPutting)); + System.out.println("Construction time (ms): " + Long.toString(endConstructing - startConstructing)); + System.out.println("Signing time (ms): " + Long.toString(endSigning - startSigning)); + System.out.println("Data time (ms): " + Long.toString(endData - startData)); + System.out.println("Data size (bytes): " + Long.toString(data.length)); + } +} diff --git a/pki/base/java-tools/src/com/netscape/cmstools/TokenInfo.java b/pki/base/java-tools/src/com/netscape/cmstools/TokenInfo.java new file mode 100644 index 000000000..016839ae9 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/TokenInfo.java @@ -0,0 +1,99 @@ +// --- 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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools; + + +import org.mozilla.jss.pkix.cmc.*; +import org.mozilla.jss.pkix.cms.*; +import org.mozilla.jss.pkix.cert.*; +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.pkcs10.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.SignatureAlgorithm; +import org.mozilla.jss.crypto.DigestAlgorithm; +import org.mozilla.jss.crypto.X509Certificate; +import org.mozilla.jss.util.*; +import org.mozilla.jss.pkcs11.*; + +import org.mozilla.jss.*; + +import netscape.security.util.*; +import netscape.security.x509.*; +import netscape.security.pkcs.PKCS10; + +import java.security.*; +import java.security.cert.CertificateException; +import java.math.*; +import java.security.Principal; +import java.lang.*; +import java.lang.reflect.*; +import java.io.*; +import java.util.*; + + + +/** + * Tool used to determine which external hardware tokens are visible to the + * Certificate System subsystem. This can be used to diagnose whether problems + * using tokens are related to the Certificate System being unable to detect it. + * + *

+ * @version $Revision$ Date: $ + */ +public class TokenInfo { + + /** + * Creates a new instance of CMCRevoke. + */ + public static void main(String[]args) { + try { + if (args.length != 1) { + System.out.println("Usage: TokenInfo "); + System.exit(0); + } + System.out.println("Database Path: " + args[0]); + + CryptoManager.InitializationValues vals = + new CryptoManager.InitializationValues(args[0], + "", "", "secmod.db"); + + CryptoManager.initialize(vals); + + CryptoManager cm = CryptoManager.getInstance(); + Enumeration modules = cm.getModules(); + while (modules.hasMoreElements()) { + PK11Module m = (PK11Module)modules.nextElement(); + System.out.println("Found external module '" + m.getName() + "'"); + } + Enumeration tokens = cm.getExternalTokens(); + + while (tokens.hasMoreElements()) { + CryptoToken t = (CryptoToken)tokens.nextElement(); + System.out.println("Found external token '" + t.getName() + "'"); + } + + }catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + + } +} -- cgit