summaryrefslogtreecommitdiffstats
path: root/pki/base/common/src/com/netscape/cmscore/cert
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/common/src/com/netscape/cmscore/cert')
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/CertDateCompare.java52
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/CertPrettyPrint.java44
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/CertUtils.java1072
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/CertificatePair.java271
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/CrlCachePrettyPrint.java257
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/CrlPrettyPrint.java44
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/CrossCertPairSubsystem.java491
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/ExtPrettyPrint.java47
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/OidLoaderSubsystem.java183
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/PrettyPrintFormat.java166
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/PrettyPrintResources.java294
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/PubKeyPrettyPrint.java45
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/X500NameSubsystem.java277
13 files changed, 3243 insertions, 0 deletions
diff --git a/pki/base/common/src/com/netscape/cmscore/cert/CertDateCompare.java b/pki/base/common/src/com/netscape/cmscore/cert/CertDateCompare.java
new file mode 100644
index 000000000..9b6c3dfe0
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/CertDateCompare.java
@@ -0,0 +1,52 @@
+// --- 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.cmscore.cert;
+
+
+import java.util.*;
+import netscape.security.x509.*;
+
+
+/**
+ * Compares validity dates for use in sorting.
+ *
+ * @author kanda
+ * @version $Revision$, $Date$
+ */
+public class CertDateCompare implements Comparator {
+ public CertDateCompare() {
+ }
+
+ public int compare(Object cert1, Object cert2) {
+ Date d1 = null;
+ Date d2 = null;
+
+ try {
+ d1 = ((X509CertImpl) cert1).getNotAfter();
+ d2 = ((X509CertImpl) cert2).getNotAfter();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ if (d1 == d2) return 0;
+ if (d1.after(d2))
+ return 1;
+ else
+ return -1;
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/cert/CertPrettyPrint.java b/pki/base/common/src/com/netscape/cmscore/cert/CertPrettyPrint.java
new file mode 100644
index 000000000..882a38c0c
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/CertPrettyPrint.java
@@ -0,0 +1,44 @@
+// --- 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.cmscore.cert;
+
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.security.PublicKey;
+import java.security.cert.*;
+import netscape.security.util.*;
+import netscape.security.x509.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.certsrv.base.*;
+
+
+/**
+ * This class will display the certificate content in predefined
+ * format.
+ *
+ * @author Jack Pan-Chen
+ * @version $Revision$, $Date$
+ */
+public class CertPrettyPrint extends netscape.security.util.CertPrettyPrint implements ICertPrettyPrint {
+
+ public CertPrettyPrint(Certificate cert) {
+ super(cert);
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/cert/CertUtils.java b/pki/base/common/src/com/netscape/cmscore/cert/CertUtils.java
new file mode 100644
index 000000000..6731ae35d
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/CertUtils.java
@@ -0,0 +1,1072 @@
+// --- 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.cmscore.cert;
+
+
+import java.io.*;
+import java.util.*;
+import java.math.*;
+import java.security.cert.*;
+import netscape.security.x509.*;
+import netscape.security.extensions.*;
+import netscape.security.util.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.osutil.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.logging.ILogger;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import netscape.security.pkcs.*;
+import java.net.SocketException;
+
+import javax.servlet.http.HttpServletRequest;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.CryptoManager.CertificateUsage;
+
+/**
+ * Utility class with assorted methods to check for
+ * smime pairs, determining the type of cert - signature
+ * or encryption ..etc.
+ *
+ * @author kanda
+ * @version $Revision$, $Date$
+ */
+public class CertUtils {
+ public static final String CERT_NEW_REQUEST_HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----";
+ public static final String CERT_NEW_REQUEST_TRAILER = "-----END NEW CERTIFICATE REQUEST-----";
+ public static final String CERT_REQUEST_HEADER = "-----BEGIN CERTIFICATE REQUEST-----";
+ public static final String CERT_REQUEST_TRAILER = "-----END CERTIFICATE REQUEST-----";
+ public static final String CERT_RENEWAL_HEADER = "-----BEGIN RENEWAL CERTIFICATE REQUEST-----";
+ public static final String CERT_RENEWAL_TRAILER = "-----END RENEWAL CERTIFICATE REQUEST-----";
+ public static final String BEGIN_CRL_HEADER =
+ "-----BEGIN CERTIFICATE REVOCATION LIST-----";
+ public static final String END_CRL_HEADER =
+ "-----END CERTIFICATE REVOCATION LIST-----";
+
+ protected static ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+ private final static String LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION =
+ "LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION_3";
+
+ /**
+ * Remove the header and footer in the PKCS10 request.
+ */
+ public static String unwrapPKCS10(String request, boolean checkHeader)
+ throws EBaseException {
+ String unwrapped;
+ String header = null;
+ int head = -1;
+ int trail = -1;
+
+ // check for "-----BEGIN NEW CERTIFICATE REQUEST-----";
+ if (header == null) {
+ head = request.indexOf(CERT_NEW_REQUEST_HEADER);
+ trail = request.indexOf(CERT_NEW_REQUEST_TRAILER);
+
+ if (!(head == -1 && trail == -1)) {
+ header = CERT_NEW_REQUEST_HEADER;
+ }
+ }
+
+ // check for "-----BEGIN CERTIFICATE REQUEST-----";
+ if (header == null) {
+ head = request.indexOf(CERT_REQUEST_HEADER);
+ trail = request.indexOf(CERT_REQUEST_TRAILER);
+
+ // If this is not a request header, check if this is a renewal header.
+ if (!(head == -1 && trail == -1)) {
+ header = CERT_REQUEST_HEADER;
+
+ }
+ }
+
+ // check for "-----BEGIN RENEWAL CERTIFICATE REQUEST-----";
+ if (header == null) {
+ head = request.indexOf(CERT_RENEWAL_HEADER);
+ trail = request.indexOf(CERT_RENEWAL_TRAILER);
+ if (!(head == -1 && trail == -1)) {
+ header = CERT_RENEWAL_HEADER;
+ }
+ }
+
+ // Now validate if any headers or trailers are in place
+ if (head == -1 && checkHeader) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_MISSING_PKCS10_HEADER"));
+ }
+ if (trail == -1 && checkHeader) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_MISSING_PKCS10_TRAILER"));
+ }
+
+ if (header != null) {
+ unwrapped = request.substring(head + header.length(), trail);
+ } else {
+ unwrapped = request;
+ }
+
+ // strip all the crtl-characters (i.e. \r\n)
+ StringTokenizer st = new StringTokenizer(unwrapped, "\t\r\n ");
+ StringBuffer stripped = new StringBuffer();
+
+ while (st.hasMoreTokens()) {
+ stripped.append(st.nextToken());
+ }
+
+ return stripped.toString();
+ }
+
+ public static PKCS10 decodePKCS10(String req) throws EBaseException {
+ String normalized = unwrapPKCS10(req, true);
+ PKCS10 pkcs10 = null;
+
+ try {
+ byte[] decodedBytes = com.netscape.osutil.OSUtil.AtoB(normalized);
+
+ pkcs10 = new PKCS10(decodedBytes);
+ } catch (Exception e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString()));
+ }
+ return pkcs10;
+ }
+
+ public static void setRSAKeyToCertInfo(X509CertInfo info,
+ byte encoded[]) throws EBaseException {
+ try {
+ if (info == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION"));
+ }
+ X509Key key = new X509Key(AlgorithmId.getAlgorithmId(
+ "RSAEncryption"), encoded);
+
+ info.set(X509CertInfo.KEY, key);
+ } catch (Exception e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION"));
+ }
+ }
+
+ public static X509CertInfo createCertInfo(int ver,
+ BigInteger serialno, String alg, String issuerName,
+ Date notBefore, Date notAfter) throws EBaseException {
+ try {
+ X509CertInfo info = new X509CertInfo();
+
+ info.set(X509CertInfo.VERSION, new CertificateVersion(ver));
+ info.set(X509CertInfo.SERIAL_NUMBER, new
+ CertificateSerialNumber(serialno));
+ info.set(X509CertInfo.ALGORITHM_ID, new
+ CertificateAlgorithmId(AlgorithmId.getAlgorithmId(alg)));
+ info.set(X509CertInfo.ISSUER, new
+ CertificateIssuerName(new X500Name(issuerName)));
+ info.set(X509CertInfo.VALIDITY, new
+ CertificateValidity(notBefore, notAfter));
+ return info;
+ } catch (Exception e) {
+ System.out.println(e.toString());
+ return null;
+ }
+ }
+
+ public static void sortCerts(X509CertImpl[] arr) {
+ Arrays.sort(arr, new CertDateCompare());
+ }
+
+ 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 boolean isEncryptionCert(X509CertImpl cert) {
+ boolean[] keyUsage = null;
+
+ try {
+ keyUsage = cert.getKeyUsage();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ if (keyUsage == null)
+ return false;
+ if (keyUsage.length < 3)
+ return false;
+ else if (keyUsage.length == 3)
+ return keyUsage[2];
+ else return keyUsage[2] || keyUsage[3];
+ }
+
+ public static boolean haveSameValidityPeriod(X509CertImpl cert1,
+ X509CertImpl cert2) {
+ long notBefDiff = 0;
+ long notAfterDiff = 0;
+
+ try {
+ notBefDiff = Math.abs(cert1.getNotBefore().getTime() -
+ cert2.getNotBefore().getTime());
+ notAfterDiff = Math.abs(cert1.getNotAfter().getTime() -
+ cert2.getNotAfter().getTime());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ if (notBefDiff > 1000 || notAfterDiff > 1000)
+ return false;
+ else
+ return true;
+ }
+
+ public static boolean isSmimePair(X509CertImpl cert1, X509CertImpl cert2, boolean matchSubjectDN) {
+ // Check for subjectDN equality.
+ if (matchSubjectDN) {
+ String dn1 = cert1.getSubjectDN().toString();
+ String dn2 = cert2.getSubjectDN().toString();
+
+ if (!sameSubjectDN(dn1, dn2))
+ return false;
+ }
+
+ // Check for the presence of signing and encryption certs.
+ boolean hasSigningCert = isSigningCert(cert1) || isSigningCert(cert2);
+
+ if (!hasSigningCert)
+ return false;
+
+ boolean hasEncryptionCert = isEncryptionCert(cert1) || isEncryptionCert(cert2);
+
+ if (!hasEncryptionCert)
+ return false;
+
+ // If both certs have signing & encryption usage set, they are
+ // not really pairs.
+ if ((isSigningCert(cert1) && isEncryptionCert(cert1)) ||
+ (isSigningCert(cert2) && isEncryptionCert(cert2)))
+ return false;
+
+ // See if the certs have the same validity.
+ boolean haveSameValidity =
+ haveSameValidityPeriod(cert1, cert2);
+
+ return haveSameValidity;
+ }
+
+ public static boolean isNotYetValidCert(X509CertImpl cert) {
+ boolean ret = false;
+
+ try {
+ cert.checkValidity();
+ } catch (CertificateExpiredException e) {
+ } catch (CertificateNotYetValidException e) {
+ ret = true;
+ } catch (Exception e) {
+ }
+ return ret;
+ }
+
+ public static boolean isValidCert(X509CertImpl cert) {
+ boolean ret = true;
+
+ try {
+ cert.checkValidity();
+ } catch (Exception e) {
+ ret = false;
+ }
+ return ret;
+ }
+
+ public static boolean isExpiredCert(X509CertImpl cert) {
+ boolean ret = false;
+
+ try {
+ cert.checkValidity();
+ } catch (CertificateExpiredException e) {
+ ret = true;
+ } catch (Exception e) {
+ }
+ return ret;
+ }
+
+ public static boolean sameSubjectDN(String dn1, String dn2) {
+ boolean ret = false;
+
+ // The dn cannot be null.
+ if (dn1 == null || dn2 == null)
+ return false;
+ try {
+ X500Name n1 = new X500Name(dn1);
+ X500Name n2 = new X500Name(dn2);
+
+ ret = n1.equals(n2);
+ } catch (Exception e) {
+ }
+ return ret;
+ }
+
+ public static String getValidCertsDisplayInfo(String cn, X509CertImpl[] validCerts) {
+ StringBuffer sb = new StringBuffer(1024);
+
+ sb.append(cn + "'s Currently Valid Certificates\n\n");
+ sb.append(getCertsDisplayInfo(validCerts));
+ return new String(sb);
+ }
+
+ public static String getExpiredCertsDisplayInfo(String cn, X509CertImpl[] expiredCerts) {
+ StringBuffer sb = new StringBuffer(1024);
+
+ sb.append(cn + "'s Expired Certificates\n\n");
+ sb.append(getCertsDisplayInfo(expiredCerts));
+ return new String(sb);
+ }
+
+ public static String getRenewedCertsDisplayInfo(String cn,
+ X509CertImpl[] validCerts, X509CertImpl[] renewedCerts) {
+ StringBuffer sb = new StringBuffer(1024);
+
+ if (validCerts != null) {
+ sb.append(cn + "'s Currently Valid Certificates\n\n");
+ sb.append(getCertsDisplayInfo(validCerts));
+ sb.append("\n\nRenewed Certificates\n\n\n");
+ } else
+ sb.append(cn + "'s Renewed Certificates\n\n");
+ sb.append(getCertsDisplayInfo(renewedCerts));
+ return new String(sb);
+ }
+
+ public static String getCertsDisplayInfo(X509CertImpl[] validCerts) {
+ // We assume that the given pair is a valid S/MIME pair.
+ StringBuffer sb = new StringBuffer(1024);
+
+ sb.append("Subject DN: " + validCerts[0].getSubjectDN().toString());
+ sb.append("\n");
+ X509CertImpl signingCert, encryptionCert;
+
+ if (isSigningCert(validCerts[0])) {
+ signingCert = validCerts[0];
+ encryptionCert = validCerts[1];
+ } else {
+ signingCert = validCerts[1];
+ encryptionCert = validCerts[0];
+ }
+ sb.append("Signing Certificate Serial No: " + signingCert.getSerialNumber().toString(16).toUpperCase());
+ sb.append("\n");
+ sb.append("Encryption Certificate Serial No: " + encryptionCert.getSerialNumber().toString(16).toUpperCase());
+ sb.append("\n");
+ sb.append("Validity: From: " + signingCert.getNotBefore().toString() + " To: " + signingCert.getNotAfter().toString());
+ sb.append("\n");
+ return new String(sb);
+ }
+
+ /**
+ * Returns the index of the given cert in an array of certs.
+ *
+ * Assumptions: The certs are issued by the same CA
+ *
+ * @param certArray The array of certs.
+ * @param givenCert The certificate we are lokking for in the array.
+ * @return -1 if not found or the index of the given cert in the array.
+ */
+ public static int getCertIndex(X509CertImpl[] certArray, X509CertImpl givenCert) {
+ int i = 0;
+
+ for (; i < certArray.length; i++) {
+ if (certArray[i].getSerialNumber().equals(
+ givenCert.getSerialNumber())) {
+ break;
+ }
+ }
+
+ return ((i == certArray.length) ? -1 : i);
+ }
+
+ /**
+ * Returns the most recently issued signing certificate from an
+ * an array of certs.
+ *
+ * Assumptions: The certs are issued by the same CA
+ *
+ * @param certArray The array of certs.
+ * @param givenCert The certificate we are lokking for in the array.
+ * @return null if there is no recent cert or the most recent cert.
+ */
+ public static X509CertImpl getRecentSigningCert(X509CertImpl[] certArray,
+ X509CertImpl currentCert) {
+ if (certArray == null || currentCert == null)
+ return null;
+
+ // Sort the certificate array.
+ Arrays.sort(certArray, new CertDateCompare());
+
+ // Get the index of the current cert in the array.
+ int i = getCertIndex(certArray, currentCert);
+
+ if (i < 0)
+ return null;
+
+ X509CertImpl recentCert = currentCert;
+
+ for (; i < certArray.length; i++) {
+ // Check if it is a signing cert and has its
+ // NotAfter later than the current cert.
+ if (isSigningCert(certArray[i]) &&
+ certArray[i].getNotAfter().after(recentCert.getNotAfter()))
+ recentCert = certArray[i];
+ }
+ return ((recentCert == currentCert) ? null : recentCert);
+ }
+
+ public static String getCertType(X509CertImpl cert) {
+ StringBuffer sb = new StringBuffer();
+
+ if (isSigningCert(cert))
+ sb.append("signing");
+ if (isEncryptionCert(cert)) {
+ if (sb.length() > 0)
+ sb.append(" ");
+ sb.append("encryption");
+ }
+
+ // Is is object signing cert?
+ try {
+ CertificateExtensions extns = (CertificateExtensions)
+ cert.get(X509CertImpl.NAME + "." +
+ X509CertImpl.INFO + "." +
+ X509CertInfo.EXTENSIONS);
+
+ if (extns != null) {
+ NSCertTypeExtension nsExtn = (NSCertTypeExtension)
+ extns.get(NSCertTypeExtension.NAME);
+
+ if (nsExtn != null) {
+ String nsType = getNSExtensionInfo(nsExtn);
+
+ if (nsType != null) {
+ if (sb.length() > 0)
+ sb.append(" ");
+ sb.append(nsType);
+ }
+ }
+ }
+ }catch (Exception e) {
+ }
+ return (sb.length() > 0) ? sb.toString() : null;
+ }
+
+ public static String getNSExtensionInfo(NSCertTypeExtension nsExtn) {
+ StringBuffer sb = new StringBuffer();
+
+ try {
+ Boolean res;
+
+ res = (Boolean) nsExtn.get(NSCertTypeExtension.SSL_CLIENT);
+ if (res.equals(Boolean.TRUE))
+ sb.append(" ssl_client");
+ res = (Boolean) nsExtn.get(NSCertTypeExtension.SSL_SERVER);
+ if (res.equals(Boolean.TRUE))
+ sb.append(" ssl_server");
+ res = (Boolean) nsExtn.get(NSCertTypeExtension.EMAIL);
+ if (res.equals(Boolean.TRUE))
+ sb.append(" email");
+ res = (Boolean) nsExtn.get(NSCertTypeExtension.OBJECT_SIGNING);
+ if (res.equals(Boolean.TRUE))
+ sb.append(" object_signing");
+ res = (Boolean) nsExtn.get(NSCertTypeExtension.SSL_CA);
+ if (res.equals(Boolean.TRUE))
+ sb.append(" ssl_CA");
+ res = (Boolean) nsExtn.get(NSCertTypeExtension.EMAIL_CA);
+ if (res.equals(Boolean.TRUE))
+ sb.append(" email_CA");
+ res = (Boolean) nsExtn.get(NSCertTypeExtension.OBJECT_SIGNING_CA);
+ if (res.equals(Boolean.TRUE))
+ sb.append(" object_signing_CA");
+ }catch (Exception e) {
+ }
+
+ return (sb.length() > 0) ? sb.toString() : null;
+ }
+
+ public static byte[] readFromFile(String fileName)
+ throws IOException {
+ FileInputStream fin = new FileInputStream(fileName);
+ int available = fin.available();
+ byte[] ba = new byte[available];
+ int nRead = fin.read(ba);
+
+ if (nRead != available)
+ throw new IOException("Error reading data from file: " + fileName);
+ fin.close();
+ return ba;
+ }
+
+ public static void storeInFile(String fileName, byte[] ba)
+ throws IOException {
+ FileOutputStream fout = new FileOutputStream(fileName);
+
+ fout.write(ba);
+ fout.close();
+ }
+
+ public static String toMIME64(X509CertImpl cert) {
+ try {
+ return
+ "-----BEGIN CERTIFICATE-----\n" +
+ com.netscape.osutil.OSUtil.BtoA(cert.getEncoded()) +
+ "-----END CERTIFICATE-----\n";
+ } catch (CertificateException e) {
+ }
+ return null;
+ }
+
+ public static X509Certificate mapCert(String mime64)
+ throws IOException {
+ mime64 = stripCertBrackets(mime64.trim());
+ String newval = normalizeCertStr(mime64);
+ byte rawPub[] = com.netscape.osutil.OSUtil.AtoB(newval);
+ X509Certificate cert = null;
+
+ try {
+ cert = new X509CertImpl(rawPub);
+ } catch (CertificateException e) {
+ }
+ return cert;
+ }
+
+ public static X509Certificate[] mapCertFromPKCS7(String mime64)
+ throws IOException {
+ mime64 = stripCertBrackets(mime64.trim());
+ String newval = normalizeCertStr(mime64);
+ byte rawPub[] = com.netscape.osutil.OSUtil.AtoB(newval);
+ PKCS7 p7 = null;
+
+ try {
+ p7 = new PKCS7(rawPub);
+ return p7.getCertificates();
+ } catch (Exception e) {
+ throw new IOException(e.toString());
+ }
+ }
+
+ public static X509CRL mapCRL(String mime64)
+ throws IOException {
+ mime64 = stripCRLBrackets(mime64.trim());
+ String newval = normalizeCertStr(mime64);
+ byte rawPub[] = com.netscape.osutil.OSUtil.AtoB(newval);
+ X509CRL crl = null;
+
+ try {
+ crl = new X509CRLImpl(rawPub);
+ } catch (Exception e) {
+ }
+ return crl;
+ }
+
+ public static X509CRL mapCRL1(String mime64)
+ throws IOException {
+ mime64 = stripCRLBrackets(mime64.trim());
+ byte rawPub[] = OSUtil.AtoB(mime64);
+ X509CRL crl = null;
+
+ try {
+ crl = new X509CRLImpl(rawPub);
+ } catch (Exception e) {
+ throw new IOException(e.toString());
+ }
+ return crl;
+ }
+
+ public static String normalizeCertStr(String s) {
+ String val = "";
+
+ for (int i = 0; i < s.length(); i++) {
+ if (s.charAt(i) == '\n') {
+ continue;
+ } else if (s.charAt(i) == '\r') {
+ continue;
+ } else if (s.charAt(i) == '"') {
+ continue;
+ } else if (s.charAt(i) == ' ') {
+ continue;
+ }
+ val += s.charAt(i);
+ }
+ return val;
+ }
+
+ public static String stripCRLBrackets(String s) {
+ if (s == null) {
+ return s;
+ }
+ if ((s.startsWith("-----BEGIN CERTIFICATE REVOCATION LIST-----")) &&
+ (s.endsWith("-----END CERTIFICATE REVOCATION LIST-----"))) {
+ return (s.substring(43, (s.length() - 41)));
+ }
+ return s;
+ }
+
+ /**
+ * strips out the begin and end certificate brackets
+ * @param s the string potentially bracketed with
+ * "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----"
+ * @return string without the brackets
+ */
+ public static String stripCertBrackets(String s) {
+ if (s == null) {
+ return s;
+ }
+
+ if ((s.startsWith("-----BEGIN CERTIFICATE-----")) &&
+ (s.endsWith("-----END CERTIFICATE-----"))) {
+ return (s.substring(27, (s.length() - 25)));
+ }
+
+ // To support Thawte's header and footer
+ if ((s.startsWith("-----BEGIN PKCS #7 SIGNED DATA-----")) &&
+ (s.endsWith("-----END PKCS #7 SIGNED DATA-----"))) {
+ return (s.substring(35, (s.length() - 33)));
+ }
+
+ return s;
+ }
+
+ /**
+ * Returns a string that represents a cert's fingerprint.
+ * The fingerprint is a MD5 digest of the DER encoded certificate.
+ * @param cert Certificate to get the fingerprint of.
+ * @return a String that represents the cert's fingerprint.
+ */
+ public static String getFingerPrint(Certificate cert)
+ throws CertificateEncodingException, NoSuchAlgorithmException {
+ byte certDer[] = cert.getEncoded();
+ MessageDigest md = MessageDigest.getInstance("MD5");
+
+ md.update(certDer);
+ byte digestedCert[] = md.digest();
+ PrettyPrintFormat pp = new PrettyPrintFormat(":");
+ StringBuffer sb = new StringBuffer();
+
+ sb.append(pp.toHexString(digestedCert, 4, 20));
+ return sb.toString();
+ }
+
+ /**
+ * Returns a string that has the certificate's fingerprint using
+ * MD5, MD2 and SHA1 hashes.
+ * A certificate's fingerprint is a hash digest of the DER encoded
+ * certificate.
+ * @param cert Certificate to get the fingerprints of.
+ * @return a String with fingerprints using the MD5, MD2 and SHA1 hashes.
+ * For example,
+ * <pre>
+ * MD2: 78:7E:D1:F9:3E:AF:50:18:68:A7:29:50:C3:21:1F:71
+ *
+ * MD5: 0E:89:91:AC:40:50:F7:BE:6E:7B:39:4F:56:73:75:75
+ *
+ * SHA1: DC:D9:F7:AF:E2:83:10:B2:F7:0A:77:E8:50:E2:F7:D1:15:9A:9D:00
+ * </pre>
+ */
+ public static String getFingerPrints(Certificate cert)
+ throws NoSuchAlgorithmException, CertificateEncodingException {
+ byte certDer[] = cert.getEncoded();
+ /*
+ String[] hashes = new String[] {"MD2", "MD5", "SHA1"};
+ String certFingerprints = "";
+ PrettyPrintFormat pp = new PrettyPrintFormat(":");
+
+ for (int i = 0; i < hashes.length; i++) {
+ MessageDigest md = MessageDigest.getInstance(hashes[i]);
+
+ md.update(certDer);
+ certFingerprints += " " + hashes[i] + ":" +
+ pp.toHexString(md.digest(), 6 - hashes[i].length());
+ }
+ return certFingerprints;
+ */
+ return getFingerPrints(certDer);
+ }
+
+ /**
+ * Returns a string that has the certificate's fingerprint using
+ * MD5, MD2 and SHA1 hashes.
+ * A certificate's fingerprint is a hash digest of the DER encoded
+ * certificate.
+ * @param cert Certificate to get the fingerprints of.
+ * @return a String with fingerprints using the MD5, MD2 and SHA1 hashes.
+ * For example,
+ * <pre>
+ * MD2: 78:7E:D1:F9:3E:AF:50:18:68:A7:29:50:C3:21:1F:71
+ *
+ * MD5: 0E:89:91:AC:40:50:F7:BE:6E:7B:39:4F:56:73:75:75
+ *
+ * SHA1: DC:D9:F7:AF:E2:83:10:B2:F7:0A:77:E8:50:E2:F7:D1:15:9A:9D:00
+ * </pre>
+ */
+ public static String getFingerPrints(byte[] certDer)
+ throws NoSuchAlgorithmException/*, CertificateEncodingException*/ {
+ // byte certDer[] = cert.getEncoded();
+ String[] hashes = new String[] {"MD2", "MD5", "SHA1", "SHA256", "SHA512"};
+ String certFingerprints = "";
+ PrettyPrintFormat pp = new PrettyPrintFormat(":");
+
+ for (int i = 0; i < hashes.length; i++) {
+ MessageDigest md = MessageDigest.getInstance(hashes[i]);
+
+ md.update(certDer);
+ certFingerprints += hashes[i] + ":\n" +
+ pp.toHexString(md.digest(), 8, 16);
+ }
+ return certFingerprints;
+ }
+
+ /**
+ * Check if a object identifier in string form is valid,
+ * that is a string in the form n.n.n.n and der encode and decode-able.
+ * @param attrName attribute name (from the configuration file)
+ * @param value object identifier string.
+ */
+ public static ObjectIdentifier checkOID(String attrName, String value)
+ throws EBaseException {
+ String msg = "value must be a object identifier in the form n.n.n.n";
+ String msg1 = "not a valid object identifier.";
+ ObjectIdentifier oid;
+
+ try {
+ oid = ObjectIdentifier.getObjectIdentifier(value);
+ } catch (Exception e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ attrName, msg));
+ }
+
+ // if the OID isn't valid (ex. n.n) the error isn't caught til
+ // encoding time leaving a bad request in the request queue.
+ try {
+ DerOutputStream derOut = new DerOutputStream();
+
+ derOut.putOID(oid);
+ new ObjectIdentifier(new DerInputStream(derOut.toByteArray()));
+ } catch (Exception e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ attrName, msg1));
+ }
+ return oid;
+ }
+
+ public static String trimB64E(String b64e) {
+ StringBuffer tmp = new StringBuffer("");
+ String line = null;
+ StringTokenizer tokens = new StringTokenizer(b64e, "\n");
+
+ while (tokens.hasMoreTokens()) {
+ line = tokens.nextToken();
+ line = line.trim();
+ tmp.append(line.trim());
+ if (tokens.hasMoreTokens())
+ tmp.append("\n");
+ }
+
+ return tmp.toString();
+ }
+
+ /*
+ * verify a certificate by its nickname
+ * returns true if it verifies; false if any not
+ */
+ public static boolean verifySystemCertByNickname(String nickname, String certusage) {
+ boolean r = true;
+ CertificateUsage cu = null;
+ cu = getCertificateUsage(certusage);
+ int ccu = 0;
+
+ if (cu == null) {
+ CMS.debug("CertUtils: verifySystemCertByNickname() failed: "+
+ nickname + " with unsupported certusage ="+ certusage);
+ return false;
+ }
+
+ if (certusage == "")
+ CMS.debug("CertUtils: verifySystemCertByNickname(): required certusage not defined, getting current certusage");
+ CMS.debug("CertUtils: verifySystemCertByNickname(): calling isCertValid()");
+ try {
+ CryptoManager cm = CryptoManager.getInstance();
+ if (cu.getUsage() != CryptoManager.CertificateUsage.CheckAllUsages.getUsage()) {
+ if (cm.isCertValid(nickname, true, cu)) {
+ r = true;
+ CMS.debug("CertUtils: verifySystemCertByNickname() passed:" + nickname);
+ } else {
+ CMS.debug("CertUtils: verifySystemCertByNickname() failed:" + nickname);
+ r = false;
+ }
+ } else {
+ // find out about current cert usage
+ ccu = cm.isCertValid(nickname, true);
+ if (ccu == CertificateUsage.basicCertificateUsages) {
+ /* cert is good for nothing */
+ r = false;
+ CMS.debug("CertUtils: verifySystemCertByNickname() failed: cert is good for nothing:"+ nickname);
+ } else {
+ r = true;
+ CMS.debug("CertUtils: verifySystemCertByNickname() passed:" + nickname);
+
+ if ((ccu & CryptoManager.CertificateUsage.SSLServer.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is SSLServer");
+ if ((ccu & CryptoManager.CertificateUsage.SSLClient.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is SSLClient");
+ if ((ccu & CryptoManager.CertificateUsage.SSLServerWithStepUp.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is SSLServerWithStepUp");
+ if ((ccu & CryptoManager.CertificateUsage.SSLCA.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is SSLCA");
+ if ((ccu & CryptoManager.CertificateUsage.EmailSigner.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is EmailSigner");
+ if ((ccu & CryptoManager.CertificateUsage.EmailRecipient.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is EmailRecipient");
+ if ((ccu & CryptoManager.CertificateUsage.ObjectSigner.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is ObjectSigner");
+ if ((ccu & CryptoManager.CertificateUsage.UserCertImport.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is UserCertImport");
+ if ((ccu & CryptoManager.CertificateUsage.VerifyCA.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is VerifyCA");
+ if ((ccu & CryptoManager.CertificateUsage.ProtectedObjectSigner.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is ProtectedObjectSigner");
+ if ((ccu & CryptoManager.CertificateUsage.StatusResponder.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is StatusResponder");
+ if ((ccu & CryptoManager.CertificateUsage.AnyCA.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is AnyCA");
+ }
+ }
+ } catch (Exception e) {
+ CMS.debug("CertUtils: verifySystemCertByNickname() failed: "+
+ e.toString());
+ r = false;
+ }
+ return r;
+ }
+
+ /*
+ * verify a certificate by its tag name
+ * returns true if it verifies; false if any not
+ */
+ public static boolean verifySystemCertByTag(String tag) {
+ String auditMessage = null;
+ IConfigStore config = CMS.getConfigStore();
+ boolean r = true;
+ try {
+ String subsysType = config.getString("cs.type", "");
+ if (subsysType.equals("")) {
+ CMS.debug("CertUtils: verifySystemCertByTag() cs.type not defined in CS.cfg. System certificates verification not done");
+ r = false;
+ }
+ subsysType = toLowerCaseSubsystemType(subsysType);
+ if (subsysType == null) {
+ CMS.debug("CertUtils: verifySystemCerts() invalid cs.type in CS.cfg. System certificates verification not done");
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE,
+ "");
+
+ audit(auditMessage);
+ r = false;
+ return r;
+ }
+ String nickname = config.getString(subsysType+".cert."+tag+".nickname", "");
+ if (nickname.equals("")) {
+ CMS.debug("CertUtils: verifySystemCertByTag() nickname for cert tag " + tag + " undefined in CS.cfg");
+ r = false;
+ }
+ String certusage = config.getString(subsysType+".cert."+tag+".certusage", "");
+ if (certusage.equals("")) {
+ CMS.debug("CertUtils: verifySystemCertByTag() certusage for cert tag " + tag + " undefined in CS.cfg, getting current certificate usage");
+ }
+ r = verifySystemCertByNickname(nickname, certusage);
+ if (r == true) {
+ // audit here
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ ILogger.SYSTEM_UID,
+ ILogger.SUCCESS,
+ nickname);
+
+ audit(auditMessage);
+ } else {
+ // audit here
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE,
+ nickname);
+
+ audit(auditMessage);
+ }
+ } catch (Exception e) {
+ CMS.debug("CertUtils: verifySystemCertsByTag() failed: "+
+ e.toString());
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE,
+ "");
+
+ audit(auditMessage);
+ r = false;
+ }
+
+ return r;
+ }
+
+ /*
+ * returns CertificateUsage mapping to JSS
+ */
+ public static CertificateUsage getCertificateUsage(String certusage) {
+ CertificateUsage cu = null;
+ if ((certusage == null) || certusage.equals(""))
+ cu = CryptoManager.CertificateUsage.CheckAllUsages;
+ else if (certusage.equalsIgnoreCase("CheckAllUsages"))
+ cu = CryptoManager.CertificateUsage.CheckAllUsages;
+ else if (certusage.equalsIgnoreCase("SSLServer"))
+ cu = CryptoManager.CertificateUsage.SSLServer;
+ else if (certusage.equalsIgnoreCase("SSLServerWithStepUp"))
+ cu = CryptoManager.CertificateUsage.SSLServerWithStepUp;
+ else if (certusage.equalsIgnoreCase("SSLClient"))
+ cu = CryptoManager.CertificateUsage.SSLClient;
+ else if (certusage.equalsIgnoreCase("SSLCA"))
+ cu = CryptoManager.CertificateUsage.SSLCA;
+ else if (certusage.equalsIgnoreCase("AnyCA"))
+ cu = CryptoManager.CertificateUsage.AnyCA;
+ else if (certusage.equalsIgnoreCase("StatusResponder"))
+ cu = CryptoManager.CertificateUsage.StatusResponder;
+ else if (certusage.equalsIgnoreCase("ObjectSigner"))
+ cu = CryptoManager.CertificateUsage.ObjectSigner;
+ else if (certusage.equalsIgnoreCase("UserCertImport"))
+ cu = CryptoManager.CertificateUsage.UserCertImport;
+ else if (certusage.equalsIgnoreCase("ProtectedObjectSigner"))
+ cu = CryptoManager.CertificateUsage.ProtectedObjectSigner;
+ else if (certusage.equalsIgnoreCase("VerifyCA"))
+ cu = CryptoManager.CertificateUsage.VerifyCA;
+ else if (certusage.equalsIgnoreCase("EmailSigner"))
+ cu = CryptoManager.CertificateUsage.EmailSigner;
+
+ return cu;
+ }
+
+ /*
+ * goes through all system certs and check to see if they are good
+ * and audit the result
+ * returns true if all verifies; false if any not
+ */
+ public static boolean verifySystemCerts() {
+ String auditMessage = null;
+ IConfigStore config = CMS.getConfigStore();
+ String certlsit = "";
+ boolean r = true;
+ try {
+ String subsysType = config.getString("cs.type", "");
+ if (subsysType.equals("")) {
+ CMS.debug("CertUtils: verifySystemCerts() cs.type not defined in CS.cfg. System certificates verification not done");
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE,
+ "");
+
+ audit(auditMessage);
+ r = false;
+ return r;
+ }
+ subsysType = toLowerCaseSubsystemType(subsysType);
+ if (subsysType == null) {
+ CMS.debug("CertUtils: verifySystemCerts() invalid cs.type in CS.cfg. System certificates verification not done");
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE,
+ "");
+
+ audit(auditMessage);
+ r = false;
+ return r;
+ }
+ String certlist = config.getString(subsysType+".cert.list", "");
+ if (certlist.equals("")) {
+ CMS.debug("CertUtils: verifySystemCerts() "+subsysType+ ".cert.list not defined in CS.cfg. System certificates verification not done");
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE,
+ "");
+
+ audit(auditMessage);
+ r = false;
+ return r;
+ }
+ StringTokenizer tokenizer = new StringTokenizer(certlist, ",");
+ while (tokenizer.hasMoreTokens()) {
+ String tag = tokenizer.nextToken();
+ tag = tag.trim();
+ CMS.debug("CertUtils: verifySystemCerts() cert tag=" + tag);
+ r = verifySystemCertByTag(tag);
+ }
+ } catch (Exception e) {
+ // audit here
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE,
+ "");
+
+ audit(auditMessage);
+ r = false;
+ CMS.debug("CertUtils: verifySystemCerts():" + e.toString());
+ }
+ return r;
+ }
+
+ public static String toLowerCaseSubsystemType(String s) {
+ String x = null;
+ if (s.equalsIgnoreCase("CA")) {
+ x = "ca";
+ } else if (s.equalsIgnoreCase("KRA")) {
+ x = "kra";
+ } else if (s.equalsIgnoreCase("OCSP")) {
+ x = "ocsp";
+ } else if (s.equalsIgnoreCase("TKS")) {
+ x = "tks";
+ }
+
+ return x;
+ }
+
+ /**
+ * Signed Audit Log
+ * This method is called to store messages to the signed audit log.
+ * @param msg signed audit log message
+ */
+ private static void audit(String msg) {
+ // in this case, do NOT strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (mSignedAuditLogger == null) {
+ return;
+ }
+
+ mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+ null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ msg);
+ }
+
+
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/cert/CertificatePair.java b/pki/base/common/src/com/netscape/cmscore/cert/CertificatePair.java
new file mode 100644
index 000000000..979e0fdd8
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/CertificatePair.java
@@ -0,0 +1,271 @@
+// --- 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.cmscore.cert;
+
+
+import java.io.*;
+import java.security.cert.*;
+import org.mozilla.jss.asn1.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.cert.ICrossCertPairSubsystem;
+
+
+/**
+ * This class implements CertificatePair used for Cross Certification
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class CertificatePair implements ASN1Value {
+ private byte[] mForward; // cert cross-siged by another CA
+ private byte[] mReverse; // subordinate cert signed by this CA
+ private static final Tag TAG = SEQUENCE.TAG;
+
+ /**
+ * construct a CertificatePair. It doesn't matter which is
+ * forward and which is reverse in the parameters. It will figure
+ * it out
+ * @param cert1 one X509Certificate
+ * @param cert2 one X509Certificate
+ */
+ public CertificatePair (X509Certificate cert1, X509Certificate cert2)
+ throws EBaseException {
+ if ((cert1 == null) || (cert2 == null))
+ throw new EBaseException("CertificatePair: both certs can not be null");
+ debug("in CertificatePair()");
+ boolean rightOrder = certOrders(cert1, cert2);
+
+ try {
+ if (rightOrder == false) {
+ mForward = cert2.getEncoded();
+ mReverse = cert1.getEncoded();
+ } else {
+ mForward = cert1.getEncoded();
+ mReverse = cert2.getEncoded();
+ }
+ } catch (CertificateException e) {
+ throw new EBaseException("CertificatePair: constructor failed:" + e.toString());
+ }
+ }
+
+ /**
+ * construct a CertificatePair. It doesn't matter which is
+ * forward and which is reverse in the parameters. It will figure
+ * it out
+ * @param cert1 one certificate byte array
+ * @param cert2 one certificate byte array
+ */
+ public CertificatePair (byte[] cert1, byte[] cert2)
+ throws EBaseException {
+ if ((cert1 == null) || (cert2 == null))
+ throw new EBaseException("CertificatePair: both certs can not be null");
+ boolean rightOrder = certOrders(cert1, cert2);
+
+ if (rightOrder == false) {
+ mForward = cert2;
+ mReverse = cert1;
+ } else {
+ mForward = cert1;
+ mReverse = cert2;
+ }
+ }
+
+ /*
+ * returns true if c1 is forward and cert2 is reverse
+ * returns false if c2 is forward and cert1 is reverse
+ */
+ private boolean certOrders(X509Certificate c1, X509Certificate c2)
+ throws EBaseException {
+ debug("in certOrders() with X509Cert");
+
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem("ca");
+ X509Certificate caCert = (X509Certificate) ca.getCACert();
+
+ debug("got this caCert");
+ // reverse cert is the one signed by this ca
+ // more check really should be done here regarding the
+ // validity of the two certs...later
+
+ /* It looks the DN's returned are not normalized and fail
+ * comparison
+
+ if ((c1.getIssuerDN().equals((Object) caCert.getSubjectDN())))
+ debug("myCA signed c1");
+ else {
+ debug("c1 issuerDN="+c1.getIssuerDN().toString());
+ debug("myCA subjectDN="+caCert.getSubjectDN().toString());
+ }
+
+ if(caCert.getSubjectDN().equals((Object) c2.getSubjectDN()))
+ debug("myCA subject == c2 subject");
+ else {
+ debug("caCert subjectDN="+caCert.getSubjectDN().toString());
+ debug("c2 subjectDN="+c2.getSubjectDN().toString());
+ }
+
+ if ((c2.getIssuerDN().equals((Object) caCert.getSubjectDN())))
+ debug("myCA signed c2");
+ else {
+ debug("c2 issuerDN="+c1.getIssuerDN().toString());
+ debug("myCA subjectDN="+caCert.getSubjectDN().toString());
+ }
+
+ if(caCert.getSubjectDN().equals((Object) c1.getSubjectDN()))
+ debug("myCA subject == c1 subject");
+ else {
+ debug("caCert subjectDN="+caCert.getSubjectDN().toString());
+ debug("c1 subjectDN="+c1.getSubjectDN().toString());
+ }
+
+ if ((c1.getIssuerDN().equals((Object) caCert.getSubjectDN()))
+ && (caCert.getSubjectDN().equals((Object) c2.getSubjectDN())))
+
+ {
+ return false;
+ } else if ((c2.getIssuerDN().equals((Object) caCert.getSubjectDN()))
+ && (caCert.getSubjectDN().equals((Object) c1.getSubjectDN())))
+ {
+ return true;
+ } else {
+ throw new EBaseException("CertificatePair: need correct forward and reverse relationship to construct CertificatePair");
+ }
+ */
+
+ /*
+ * my other attempt:
+ * one of the certs has to share the same public key as this
+ * CA, and that will be the "forward" cert; the other one is
+ * assumed to be the "reverse" cert
+ */
+ byte[] caCertBytes = caCert.getPublicKey().getEncoded();
+
+ if (caCertBytes != null)
+ debug("got cacert public key bytes length=" + caCertBytes.length);
+ else {
+ debug("cacert public key bytes null");
+ throw new EBaseException("CertificatePair: certOrders() fails to get this CA's signing certificate public key encoded");
+ }
+
+ byte[] c1Bytes = c1.getPublicKey().getEncoded();
+
+ if (c1Bytes != null)
+ debug("got c1 public key bytes length=" + c1Bytes.length);
+ else {
+ debug("c1 cert public key bytes length null");
+ throw new EBaseException("CertificatePair::certOrders() public key bytes are of length null");
+ }
+
+ byte[] c2Bytes = c2.getPublicKey().getEncoded();
+
+ if (c2Bytes != null)
+ debug("got c2 public key bytes length=" + c2Bytes.length);
+ else
+ debug("c2 cert public key bytes length null");
+
+ if (byteArraysAreEqual(c1Bytes, caCertBytes)) {
+ debug("c1 has same public key as this ca");
+ return true;
+ } else if (byteArraysAreEqual(c2Bytes, caCertBytes)) {
+ debug("c2 has same public key as this ca");
+
+ return false;
+ } else {
+ debug("neither c1 nor c2 public key matches with this ca");
+ throw new EBaseException("CertificatePair: need correct forward and reverse relationship to construct CertificatePair");
+ }
+ }
+
+ /**
+ * compares contents two byte arrays returning true if exactly same.
+ */
+ public boolean byteArraysAreEqual(byte[] a, byte[] b) {
+ debug("in byteArraysAreEqual()");
+ if (a.length != b.length) {
+ debug("exiting byteArraysAreEqual(): false");
+ return false;
+ }
+ for (int i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ debug("exiting byteArraysAreEqual(): false");
+ return false;
+ }
+ }
+ debug("exiting byteArraysAreEqual(): true");
+ return true;
+ }
+
+ /*
+ * returns true if cert1 is forward and cert2 is reverse
+ * returns false if cert2 is forward and cert1 is reverse
+ */
+ private boolean certOrders(byte[] cert1, byte[] cert2)
+ throws EBaseException {
+ debug("in certOrders() with byte[]");
+ ICrossCertPairSubsystem ccps =
+ (ICrossCertPairSubsystem) CMS.getSubsystem("CrossCertPair");
+ X509Certificate c1 = null;
+ X509Certificate c2 = null;
+
+ try {
+ c1 = ccps.byteArray2X509Cert(cert1);
+ c2 = ccps.byteArray2X509Cert(cert2);
+ } catch (CertificateException e) {
+ throw new EBaseException("CertificatePair: certOrders() failed:" + e.toString());
+ }
+ return certOrders(c1, c2);
+ }
+
+ public void encode(OutputStream os) throws IOException {
+ encode(TAG, os);
+ }
+
+ public void encode(Tag implicitTag, OutputStream os) throws IOException {
+ SEQUENCE seq = new SEQUENCE();
+
+ if (mForward != null) {
+ try {
+ ANY any = new ANY(mForward);
+
+ seq.addElement(any);
+ } catch (InvalidBERException e) {
+ debug("encode error:" + e.toString());
+ }
+ }
+ if (mReverse != null) {
+ try {
+ ANY any = new ANY(mReverse);
+
+ seq.addElement(any);
+ } catch (InvalidBERException e) {
+ debug("encode error:" + e.toString());
+ }
+ }
+
+ seq.encode(implicitTag, os);
+ }
+
+ public Tag getTag() {
+ return TAG;
+ }
+
+ private void debug(String msg) {
+ CMS.debug("CertifiatePair: " + msg);
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/cert/CrlCachePrettyPrint.java b/pki/base/common/src/com/netscape/cmscore/cert/CrlCachePrettyPrint.java
new file mode 100644
index 000000000..693d881c5
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/CrlCachePrettyPrint.java
@@ -0,0 +1,257 @@
+// --- 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.cmscore.cert;
+
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import netscape.security.util.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.ca.*;
+
+import com.netscape.certsrv.apps.*;
+
+/**
+ * This class will display the certificate content in predefined
+ * format.
+ *
+ * @author Andrew Wnuk
+ * @version $Revision$, $Date$
+ */
+public class CrlCachePrettyPrint implements ICRLPrettyPrint
+{
+
+ /*==========================================================
+ * constants
+ *==========================================================*/
+ private final static String CUSTOM_LOCALE = "Custom";
+
+ /*==========================================================
+ * variables
+ *==========================================================*/
+ private ICRLIssuingPoint mIP = null;
+ private PrettyPrintFormat pp = null;
+
+ /*==========================================================
+ * constructors
+ *==========================================================*/
+
+ public CrlCachePrettyPrint(ICRLIssuingPoint ip) {
+ mIP = ip;
+ pp = new PrettyPrintFormat(":");
+ }
+
+ /*==========================================================
+ * public methods
+ *==========================================================*/
+
+ /**
+ * This method return string representation of the certificate
+ * revocation list in predefined format using specified client
+ * local. I18N Support.
+ *
+ * @param clientLocale Locale to be used for localization
+ * @return string representation of the certificate
+ */
+ public String toString(Locale clientLocale) {
+ return toString(clientLocale, 0, 0, 0);
+ }
+
+ public String toString(Locale clientLocale, long crlSize, long pageStart, long pageSize) {
+
+ //get I18N resources
+ ResourceBundle resource = ResourceBundle.getBundle(
+ PrettyPrintResources.class.getName());
+ DateFormat dateFormater = DateFormat.getDateTimeInstance(
+ DateFormat.FULL, DateFormat.FULL, clientLocale);
+ //get timezone and timezone ID
+ String tz = " ";
+ String tzid = " ";
+
+ StringBuffer sb = new StringBuffer();
+
+ try {
+ sb.append(pp.indent(4) + resource.getString(
+ PrettyPrintResources.TOKEN_CRL) + "\n");
+ sb.append(pp.indent(8) + resource.getString(
+ PrettyPrintResources.TOKEN_DATA) + "\n");
+
+ String signingAlgorithm = mIP.getLastSigningAlgorithm();
+ if (signingAlgorithm != null) {
+ sb.append(pp.indent(12) + resource.getString(
+ PrettyPrintResources.TOKEN_SIGALG) +
+ signingAlgorithm + "\n");
+ }
+ sb.append(pp.indent(12) + resource.getString(
+ PrettyPrintResources.TOKEN_ISSUER) +
+ ((ICertificateAuthority)(mIP.getCertificateAuthority()))
+ .getCRLX500Name().toString() + "\n");
+ // Format thisUpdate
+ String thisUpdate = dateFormater.format(mIP.getLastUpdate());
+
+ // get timezone and timezone ID
+ if (TimeZone.getDefault() != null) {
+ tz = TimeZone.getDefault().getDisplayName(
+ TimeZone.getDefault().inDaylightTime(mIP.getLastUpdate()),
+ TimeZone.SHORT,
+ clientLocale);
+ tzid = TimeZone.getDefault().getID();
+ }
+ // Specify ThisUpdate
+ if (tz.equals(tzid) || tzid.equals(CUSTOM_LOCALE)) {
+ // Do NOT append timezone ID
+ sb.append(pp.indent(12)
+ + resource.getString(
+ PrettyPrintResources.TOKEN_THIS_UPDATE)
+ + thisUpdate
+ + "\n");
+ } else {
+ // Append timezone ID
+ sb.append(pp.indent(12)
+ + resource.getString(
+ PrettyPrintResources.TOKEN_THIS_UPDATE)
+ + thisUpdate
+ + " " + tzid + "\n");
+ }
+ // Check for presence of NextUpdate
+ if (mIP.getNextUpdate() != null) {
+ // Format nextUpdate
+ String nextUpdate = dateFormater.format(mIP.getNextUpdate());
+
+ // re-get timezone (just in case it is different . . .)
+ if (TimeZone.getDefault() != null) {
+ tz = TimeZone.getDefault().getDisplayName(
+ TimeZone.getDefault().inDaylightTime(mIP.getNextUpdate()),
+ TimeZone.SHORT,
+ clientLocale);
+ }
+ // Specify NextUpdate
+ if (tz.equals(tzid) || tzid.equals(CUSTOM_LOCALE)) {
+ // Do NOT append timezone ID
+ sb.append(pp.indent(12)
+ + resource.getString(
+ PrettyPrintResources.TOKEN_NEXT_UPDATE)
+ + nextUpdate
+ + "\n");
+ } else {
+ // Append timezone ID
+ sb.append(pp.indent(12)
+ + resource.getString(
+ PrettyPrintResources.TOKEN_NEXT_UPDATE)
+ + nextUpdate
+ + " " + tzid + "\n");
+ }
+ }
+
+ if (crlSize > 0 && pageStart == 0 && pageSize == 0) {
+ sb.append(pp.indent(12) + resource.getString(
+ PrettyPrintResources.TOKEN_REVOKED_CERTIFICATES) + crlSize + "\n");
+ } else if ((crlSize == 0 && pageStart == 0 && pageSize == 0) ||
+ (crlSize > 0 && pageStart > 0 && pageSize > 0)) {
+ sb.append(pp.indent(12) + resource.getString(
+ PrettyPrintResources.TOKEN_REVOKED_CERTIFICATES));
+ long upperLimit = crlSize;
+ if (crlSize > 0 && pageStart > 0 && pageSize > 0) {
+ upperLimit = (pageStart + pageSize - 1 > crlSize) ? crlSize : pageStart + pageSize - 1;
+ sb.append("" + pageStart + "-" + upperLimit + " of " + crlSize);
+ } else {
+ pageStart = 1;
+ sb.append("" + crlSize);
+ }
+ sb.append("\n");
+
+ Set revokedCerts = mIP.getRevokedCertificates((int)(pageStart-1), (int)upperLimit);
+
+ if (revokedCerts != null) {
+ Iterator i = revokedCerts.iterator();
+ long l = 1;
+
+ while ((i.hasNext()) && ((crlSize == 0) || (upperLimit - pageStart + 1 >= l))) {
+ RevokedCertImpl revokedCert = (RevokedCertImpl)i.next();
+
+ if ((crlSize == 0) || (upperLimit - pageStart + 1 >= l)) {
+ sb.append(pp.indent(16) + resource.getString(
+ PrettyPrintResources.TOKEN_SERIAL) + "0x" +
+ revokedCert.getSerialNumber().toString(16).toUpperCase() + "\n");
+ String revocationDate =
+ dateFormater.format(revokedCert.getRevocationDate());
+
+ // re-get timezone
+ // (just in case it is different . . .)
+ if (TimeZone.getDefault() != null) {
+ tz = TimeZone.getDefault().getDisplayName(
+ TimeZone.getDefault().inDaylightTime(
+ revokedCert.getRevocationDate()),
+ TimeZone.SHORT,
+ clientLocale);
+ }
+ // Specify revocationDate
+ if (tz.equals(tzid) ||
+ tzid.equals(CUSTOM_LOCALE)) {
+ // Do NOT append timezone ID
+ sb.append(pp.indent(16)
+ + resource.getString(
+ PrettyPrintResources.TOKEN_REVOCATION_DATE)
+ + revocationDate
+ + "\n");
+ } else {
+ // Append timezone ID
+ sb.append(pp.indent(16)
+ + resource.getString(
+ PrettyPrintResources.TOKEN_REVOCATION_DATE)
+ + revocationDate
+ + " " + tzid + "\n");
+ }
+ if (revokedCert.hasExtensions()) {
+ sb.append(pp.indent(16) + resource.getString(
+ PrettyPrintResources.TOKEN_EXTENSIONS) + "\n");
+ CRLExtensions crlExtensions = revokedCert.getExtensions();
+
+ if (crlExtensions != null) {
+ for (int k = 0; k < crlExtensions.size(); k++) {
+ Extension ext = (Extension) crlExtensions.elementAt(k);
+ ExtPrettyPrint extpp = new ExtPrettyPrint(ext, 20);
+
+ sb.append(extpp.toString());
+ }
+ }
+ }
+ }
+ l++;
+ }
+ } else if (mIP.isCRLCacheEnabled() && mIP.isCRLCacheEmpty()) {
+ sb.append("\n" + pp.indent(16) + resource.getString(
+ PrettyPrintResources.TOKEN_CACHE_IS_EMPTY) + "\n\n");
+ } else {
+ sb.append("\n" + pp.indent(16) + resource.getString(
+ PrettyPrintResources.TOKEN_CACHE_NOT_AVAILABLE) + "\n\n");
+ }
+ }
+
+ } catch (Exception e) {
+ sb.append("\n\n" + pp.indent(4) + resource.getString(
+ PrettyPrintResources.TOKEN_DECODING_ERROR) + "\n\n");
+ CMS.debug("Exception="+e.toString());
+ CMS.debugStackTrace();
+ }
+
+ return sb.toString();
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/cert/CrlPrettyPrint.java b/pki/base/common/src/com/netscape/cmscore/cert/CrlPrettyPrint.java
new file mode 100644
index 000000000..2f7c08dee
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/CrlPrettyPrint.java
@@ -0,0 +1,44 @@
+// --- 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.cmscore.cert;
+
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.security.cert.*;
+import netscape.security.util.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.cmscore.util.*;
+import java.security.*;
+
+
+/**
+ * This class will display the certificate content in predefined
+ * format.
+ *
+ * @author Andrew Wnuk
+ * @version $Revision$, $Date$
+ */
+public class CrlPrettyPrint extends netscape.security.util.CrlPrettyPrint implements ICRLPrettyPrint {
+
+ public CrlPrettyPrint(X509CRLImpl crl) {
+ super(crl);
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/cert/CrossCertPairSubsystem.java b/pki/base/common/src/com/netscape/cmscore/cert/CrossCertPairSubsystem.java
new file mode 100644
index 000000000..41020abd1
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/CrossCertPairSubsystem.java
@@ -0,0 +1,491 @@
+// --- 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.cmscore.cert;
+
+
+import netscape.ldap.*;
+import java.awt.*;
+import java.io.*;
+import java.util.*;
+import java.security.cert.*;
+import netscape.security.util.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.cert.*;
+import com.netscape.certsrv.publish.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.cmscore.ldapconn.*;
+
+
+/**
+ * Subsystem for handling cross certificate pairing and publishing
+ * Intended use:
+ * <ul>
+ * <li> when signing a subordinate CA cert which is intended to be
+ * part of the crossCertificatePair
+ * <li> when this ca submits a request (with existing CA signing key
+ * material to another ca for cross-signing
+ *</ul>
+ * In both cases, administrator needs to "import" the crossSigned
+ * certificates via the admin console. When importCert() is called,
+ * the imported cert will be stored in the internal db
+ * first until it's pairing cert shows up.
+ * If it happens that the above two cases finds its pairing
+ * cert already there, then a CertifiatePair is created and put
+ * in the internal db "crosscertificatepair;binary" attribute
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class CrossCertPairSubsystem implements ICrossCertPairSubsystem {
+
+ public static final String ID = "CrossCertPair";
+ public static final String DN_XCERTS = "cn=crossCerts";
+ public static final String LDAP_ATTR_CA_CERT = "caCertificate;binary";
+ public static final String LDAP_ATTR_XCERT_PAIR = "crossCertificatePair;binary";
+ protected static final String PROP_LDAP = "ldap";
+ protected static final String PROP_BASEDN = "basedn";
+
+ protected IConfigStore mConfig = null;
+ protected LdapBoundConnFactory mLdapConnFactory = null;
+ protected String mBaseDN = null;
+ protected ICertificateAuthority mCa = null;
+ protected IPublisherProcessor mPublisherProcessor = null;
+
+ private String mId = ID;
+ private ILogger mLogger = null;
+
+ public CrossCertPairSubsystem() {
+ }
+
+ /**
+ * Retrieves subsystem identifier.
+ */
+ public String getId() {
+ return mId;
+ }
+
+ public void setId(String id) throws EBaseException {
+ mId = id;
+ }
+
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ try {
+ mConfig = config;
+ mLogger = CMS.getLogger();
+ mCa = (ICertificateAuthority) CMS.getSubsystem("ca");
+ mPublisherProcessor = mCa.getPublisherProcessor();
+
+ // initialize LDAP connection factory
+ IConfigStore ldapConfig = mConfig.getSubStore(PROP_LDAP);
+
+ if (ldapConfig == null) {
+ log(ILogger.LL_MISCONF,
+ CMS.getLogMessage("CMSCORE_DBS_CONF_ERROR",
+ PROP_LDAP));
+ return;
+ }
+
+ mBaseDN = ldapConfig.getString(PROP_BASEDN, null);
+
+ mLdapConnFactory = new LdapBoundConnFactory();
+
+ if (mLdapConnFactory != null)
+ mLdapConnFactory.init(ldapConfig);
+ else {
+ log(ILogger.LL_MISCONF,
+ CMS.getLogMessage("CMSCORE_DBS_CONF_ERROR",
+ PROP_LDAP));
+ return;
+ }
+ } catch (EBaseException e) {
+ if (CMS.isPreOpMode())
+ return;
+ throw e;
+ }
+ }
+
+ /**
+ * "import" the CA cert cross-signed by another CA (potentially a
+ * bridge CA) into internal ldap db.
+ * the imported cert will be stored in the internal db
+ * first until it's pairing cert shows up.
+ * If it happens that it finds its pairing
+ * cert already there, then a CertifiatePair is created and put
+ * in the internal db "crosscertificatepair;binary" attribute
+ *
+ * @param certBytes cert in byte array to be imported
+ */
+ public void importCert(byte[] certBytes) throws EBaseException {
+ debug("importCert(byte[])");
+ X509Certificate cert = null;
+
+ try {
+ cert = byteArray2X509Cert(certBytes);
+ } catch (CertificateException e) {
+ throw new EBaseException("CrossCertPairSubsystem: importCert() failed:" + e.toString());
+
+ }
+
+ importCert((Object) cert);
+ }
+
+ /**
+ * "import" the CA cert cross-signed by another CA (potentially a
+ * bridge CA) into internal ldap db.
+ * the imported cert will be stored in the internal db
+ * first until it's pairing cert shows up.
+ * If it happens that it finds its pairing
+ * cert already there, then a CertifiatePair is created and put
+ * in the internal db "crosscertificatepair;binary" attribute
+ *
+ * @param certBytes cert in byte array to be imported
+ */
+ public synchronized void importCert(Object certObj) throws EBaseException {
+ if (!(certObj instanceof X509Certificate))
+ throw new IllegalArgumentException("Illegal arg to publish");
+
+ debug("in importCert(Object)");
+ X509Certificate cert = (X509Certificate) certObj;
+ // check to see if this is a valid cross-signed ca cert:
+ // 1. does cert2 share the same key pair as this CA's signing
+ // cert
+ // 2. does cert2's subject match this CA's subject?
+ // 3. other valididity checks: is this a ca cert? Is this
+ // cert still valid? If the issuer is not yet trusted, let it
+ // be.
+
+ // get certs from internal db to see if we find a pair
+ LDAPConnection conn = null;
+
+ try {
+ conn = getConn();
+ LDAPSearchResults res = conn.search(mBaseDN, LDAPv2.SCOPE_SUB,
+ DN_XCERTS, null, false);
+
+ if (res.hasMoreElements()) {
+ log(ILogger.LL_INFO, "ldap search found " + DN_XCERTS);
+
+ LDAPEntry entry = (LDAPEntry) res.nextElement();
+ LDAPAttribute caCerts = entry.getAttribute(LDAP_ATTR_CA_CERT);
+ LDAPAttribute certPairs = entry.getAttribute(LDAP_ATTR_XCERT_PAIR);
+
+ if (caCerts == null) {
+ debug("no existing ca certs, just import");
+ addCAcert(conn, cert.getEncoded());
+ return;
+ }
+
+ Enumeration en = caCerts.getByteValues();
+
+ if ((en == null) || (en.hasMoreElements() == false)) {
+ debug("1st potential xcert");
+ addCAcert(conn, cert.getEncoded());
+ debug("potential cross ca cert added to crossCerts entry successfully");
+ return;
+ }
+ byte[] val = null;
+ boolean match = false;
+
+ while (en.hasMoreElements()) {
+ val = (byte[]) en.nextElement();
+ debug("val =" + val.length);
+ if (val.length == 0) {
+ continue;
+ } else {
+ X509Certificate inCert = byteArray2X509Cert(val);
+
+ if (arePair(inCert, cert)) {
+ // found a pair,form xcert, write to
+ // crossCertificatePair attr, remove from
+ // caCertificate attr, and publish if so configured
+ debug("found a pair!");
+ CertificatePair cp = new
+ // CertificatePair(inCert.getEncoded(), cert.getEncoded());
+ CertificatePair(inCert, cert);
+
+ addXCertPair(conn, certPairs, cp);
+ deleteCAcert(conn, inCert.getEncoded());
+ // found a match, get out
+ match = true;
+ break;
+ }
+ }
+ } //while
+ if (match == false) {
+ // don't find a pair, add it into
+ // caCertificate attr for later pairing
+ // opportunities
+ debug("didn't find a pair!");
+ addCAcert(conn, cert.getEncoded());
+ debug("potential cross ca cert added to crossCerts entry successfully");
+ }
+
+ } else {
+ log(ILogger.LL_INFO, "ldap search found no " + DN_XCERTS);
+ }
+ } catch (IOException e) {
+ throw new EBaseException("CrossCertPairSubsystem: importCert() failed:" + e.toString());
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, "exception: " + e.toString());
+ throw new EBaseException("CrossCertPairSubsystem: importCert() failed:" + e.toString());
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, "exception: " + e.toString());
+ throw new EBaseException("CrossCertPairSubsystem: importCert() failed:" + e.toString());
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, "exception: " + e.toString());
+ throw new EBaseException("CrossCertPairSubsystem: importCert() failed:" + e.toString());
+ } finally {
+ try {
+ returnConn(conn);
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, "exception: " + e.toString());
+ throw new EBaseException("CrossCertPairSubsystem: importCert() failed:" + e.toString());
+ }
+ }
+ debug("importCert(Object) completed");
+ }
+
+ /**
+ * are cert1 and cert2 cross-signed certs?
+ * @param cert1 the cert for comparison in our internal db
+ * @param cert2 the cert that's being considered
+ */
+ protected boolean arePair(X509Certificate cert1, X509Certificate cert2) {
+ // 1. does cert1's issuer match cert2's subject?
+ // 2. does cert2's issuer match cert1's subject?
+ if ((cert1.getIssuerDN().equals((Object) cert2.getSubjectDN()))
+ && (cert2.getIssuerDN().equals((Object) cert1.getSubjectDN())))
+ return true;
+ else
+ return false;
+ }
+
+ public X509Certificate byteArray2X509Cert(byte[] certBytes)
+ throws CertificateException {
+ debug("in bytearray2X509Cert()");
+ ByteArrayInputStream inStream = new
+ ByteArrayInputStream(certBytes);
+
+ CertificateFactory cf =
+ CertificateFactory.getInstance("X.509");
+
+ X509Certificate cert = (X509Certificate) cf.generateCertificate(inStream);
+
+ debug("done bytearray2X509Cert()");
+ return cert;
+ }
+
+ public synchronized void addXCertPair(LDAPConnection conn,
+ LDAPAttribute certPairs, CertificatePair pair)
+ throws LDAPException, IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ pair.encode(bos);
+
+ if (ByteValueExists(certPairs, bos.toByteArray()) == true) {
+ debug("cross cert pair exists in internal db, don't add again");
+ return;
+ }
+
+ // add certificatePair
+ LDAPModificationSet modSet = new LDAPModificationSet();
+
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute(LDAP_ATTR_XCERT_PAIR, bos.toByteArray()));
+ conn.modify(DN_XCERTS + "," + mBaseDN, modSet);
+ }
+
+ /**
+ * checks if a byte attribute has a certain value.
+ */
+ public static boolean ByteValueExists(LDAPAttribute attr, byte[] bval) {
+ if (attr == null) {
+ return false;
+ }
+ Enumeration vals = attr.getByteValues();
+ byte[] val = null;
+
+ while (vals.hasMoreElements()) {
+ val = (byte[]) vals.nextElement();
+ if (val.length == 0)
+ continue;
+ if (byteArraysAreEqual(val, bval)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * compares contents two byte arrays returning true if exactly same.
+ */
+ static public boolean byteArraysAreEqual(byte[] a, byte[] b) {
+ debug("in byteArraysAreEqual()");
+ if (a.length != b.length) {
+ debug("exiting byteArraysAreEqual(): false");
+ return false;
+ }
+ for (int i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ debug("exiting byteArraysAreEqual(): false");
+ return false;
+ }
+ }
+ debug("exiting byteArraysAreEqual(): true");
+ return true;
+ }
+
+ public synchronized void addCAcert(LDAPConnection conn, byte[] certEnc)
+ throws LDAPException {
+ LDAPModificationSet modSet = new
+ LDAPModificationSet();
+
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute(LDAP_ATTR_CA_CERT, certEnc));
+ conn.modify(DN_XCERTS + "," + mBaseDN, modSet);
+ }
+
+ public synchronized void deleteCAcert(LDAPConnection conn, byte[] certEnc)
+ throws LDAPException {
+ LDAPModificationSet modSet = new
+ LDAPModificationSet();
+
+ modSet.add(LDAPModification.DELETE,
+ new LDAPAttribute(LDAP_ATTR_CA_CERT, certEnc));
+ conn.modify(DN_XCERTS + "," + mBaseDN, modSet);
+ }
+
+ /**
+ * publish all cert pairs, if publisher is on
+ */
+ public synchronized void publishCertPairs() throws EBaseException {
+ LDAPConnection conn = null;
+
+ if ((mPublisherProcessor == null) ||
+ !mPublisherProcessor.enabled())
+ return;
+
+ try {
+ conn = getConn();
+ // search in internal db for xcerts
+ LDAPSearchResults res = conn.search(mBaseDN, LDAPv2.SCOPE_SUB,
+ DN_XCERTS, null, false);
+
+ debug("trying to publish cert pairs, if any");
+ if ((res == null) || (res.hasMoreElements() == false)) {
+ debug("no cross cert pairs to publish");
+ return;
+ }
+
+ if (res.hasMoreElements()) {
+ log(ILogger.LL_INFO, "ldap search found " + DN_XCERTS);
+
+ LDAPEntry entry = (LDAPEntry) res.nextElement();
+ LDAPAttribute xcerts = entry.getAttribute(LDAP_ATTR_XCERT_PAIR);
+
+ if (xcerts == null) {
+ debug("no cross cert pairs to publish");
+ return;
+ }
+
+ Enumeration en = xcerts.getByteValues();
+
+ if ((en == null) || (en.hasMoreElements() == false)) {
+ debug("publishCertPair found no pairs in internal db");
+ return;
+ }
+ byte[] val = null;
+
+ while (en.hasMoreElements()) {
+ val = (byte[]) en.nextElement();
+ debug("val =" + val.length);
+ if (val.length == 0) {
+ continue;
+ } else {
+ try {
+ //found a cross cert pair, publish if we could
+ IXcertPublisherProcessor xp = null;
+
+ xp = (IXcertPublisherProcessor) mPublisherProcessor;
+ xp.publishXCertPair(val);
+ } catch (Exception e) {
+ throw new EBaseException("CrossCertPairSubsystem: publishCertPairs() failed:" + e.toString());
+ }
+ }
+ }// while
+ }//if
+ } catch (Exception e) {
+ throw new EBaseException("CrossCertPairSubsystem: publishCertPairs() failed:" + e.toString());
+ }
+ }
+
+ protected LDAPConnection getConn() throws ELdapException {
+ if (mLdapConnFactory != null)
+ return mLdapConnFactory.getConn();
+
+ return null;
+ }
+
+ protected void returnConn(LDAPConnection conn) throws ELdapException {
+ if (mLdapConnFactory != null)
+ mLdapConnFactory.returnConn(conn);
+ }
+
+ public void startup() throws EBaseException {
+ }
+
+ /**
+ * Stops this system.
+ */
+ public synchronized void shutdown() {
+ mCa = null;
+ mPublisherProcessor = null;
+ if (mLdapConnFactory != null) {
+ try {
+ mLdapConnFactory.reset();
+ } catch (ELdapException e) {
+ CMS.debug("CrossCertPairSubsystem shutdown exception: "+e.toString());
+ }
+ }
+ mLdapConnFactory = null;
+ }
+
+ /*
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ protected void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM,
+ ILogger.S_XCERT, level, msg);
+ }
+
+ private static void debug(String msg) {
+ CMS.debug("CrossCertPairSubsystem: " + msg);
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/cert/ExtPrettyPrint.java b/pki/base/common/src/com/netscape/cmscore/cert/ExtPrettyPrint.java
new file mode 100644
index 000000000..09aea0aca
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/ExtPrettyPrint.java
@@ -0,0 +1,47 @@
+// --- 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.cmscore.cert;
+
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.math.BigInteger;
+import netscape.security.util.*;
+import netscape.security.extensions.*;
+import netscape.security.x509.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.certsrv.base.*;
+import java.security.*;
+import netscape.security.x509.CRLDistributionPointsExtension.Reason;
+
+
+/**
+ * This class will display the certificate content in predefined
+ * format.
+ *
+ * @author Andrew Wnuk
+ * @version $Revision$, $Date$
+ */
+public class ExtPrettyPrint extends netscape.security.util.ExtPrettyPrint implements IExtPrettyPrint {
+
+ public ExtPrettyPrint(Extension ext, int indentSize) {
+ super(ext, indentSize);
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/cert/OidLoaderSubsystem.java b/pki/base/common/src/com/netscape/cmscore/cert/OidLoaderSubsystem.java
new file mode 100644
index 000000000..7fd33f95f
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/OidLoaderSubsystem.java
@@ -0,0 +1,183 @@
+// --- 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.cmscore.cert;
+
+
+import java.awt.*;
+import java.io.*;
+import java.util.*;
+import com.netscape.certsrv.base.*;
+import netscape.security.x509.*;
+import netscape.security.extensions.*;
+import netscape.security.util.ObjectIdentifier;
+import java.security.cert.CertificateException;
+import com.netscape.cmscore.util.*;
+
+
+/**
+ *
+ * @author stevep
+ * @version $Revision
+ */
+public class OidLoaderSubsystem implements ISubsystem {
+
+ private IConfigStore mConfig = null;
+ public static final String ID = "oidmap";
+ private String mId = ID;
+
+ private static final String PROP_OID = "oid";
+ private static final String PROP_CLASS = "class";
+
+ /**
+ *
+ */
+ private OidLoaderSubsystem() {
+ }
+
+ /**
+ * Retrieves subsystem identifier.
+ */
+ public String getId() {
+ return mId;
+ }
+
+ public void setId(String id) throws EBaseException {
+ mId = id;
+ }
+
+ // singleton enforcement
+
+ private static OidLoaderSubsystem mInstance = new OidLoaderSubsystem();
+
+ public static OidLoaderSubsystem getInstance() {
+ return mInstance;
+ }
+
+ private static final int CertType_data[] = { 2, 16, 840, 1, 113730, 1, 1 };
+
+ /**
+ * Identifies the particular public key used to sign the certificate.
+ */
+ public static final ObjectIdentifier CertType_Id = new
+ ObjectIdentifier(CertType_data);
+
+ private static final String[][] oidMapEntries = new String[][] {
+ {NSCertTypeExtension.class.getName(),
+ CertType_Id.toString(),
+ NSCertTypeExtension.NAME},
+ {CertificateRenewalWindowExtension.class.getName(),
+ CertificateRenewalWindowExtension.ID.toString(),
+ CertificateRenewalWindowExtension.NAME},
+ {CertificateScopeOfUseExtension.class.getName(),
+ CertificateScopeOfUseExtension.ID.toString(),
+ CertificateScopeOfUseExtension.NAME},
+ {DeltaCRLIndicatorExtension.class.getName(),
+ DeltaCRLIndicatorExtension.OID,
+ DeltaCRLIndicatorExtension.NAME},
+ {HoldInstructionExtension.class.getName(),
+ HoldInstructionExtension.OID,
+ HoldInstructionExtension.NAME},
+ {InvalidityDateExtension.class.getName(),
+ InvalidityDateExtension.OID,
+ InvalidityDateExtension.NAME},
+ {IssuingDistributionPointExtension.class.getName(),
+ IssuingDistributionPointExtension.OID,
+ IssuingDistributionPointExtension.NAME},
+ {FreshestCRLExtension.class.getName(),
+ FreshestCRLExtension.OID,
+ FreshestCRLExtension.NAME},
+ };
+
+ /**
+ * Initializes this subsystem with the given
+ * configuration store.
+ * It first initializes resident subsystems,
+ * and it loads and initializes loadable
+ * subsystem specified in the configuration
+ * store.
+ * <P>
+ * Note that individual subsystem should be
+ * initialized in a separated thread if
+ * it has dependency on the initialization
+ * of other subsystems.
+ * <P>
+ *
+ * @param owner owner of this subsystem
+ * @param config configuration store
+ */
+ public synchronized void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ if (Debug.ON) {
+ Debug.trace("OIDLoaderSubsystem started");
+ }
+ mConfig = config;
+
+ Enumeration names = mConfig.getSubStoreNames();
+
+ // load static (build-in) extensions
+
+ for (int i = 0; i < oidMapEntries.length; i++) {
+ try {
+ OIDMap.addAttribute(oidMapEntries[i][0],
+ oidMapEntries[i][1],
+ oidMapEntries[i][2]);
+ } catch (Exception e) {
+ }
+ }
+
+ // load dynamic extensions
+
+ while (names.hasMoreElements()) {
+ String substorename = (String) names.nextElement();
+ IConfigStore substore = mConfig.getSubStore(substorename);
+
+ try {
+ String oidname = substore.getString(PROP_OID);
+ String classname = substore.getString(PROP_CLASS);
+
+ OIDMap.addAttribute(classname,
+ oidname,
+ substorename);
+ } catch (EPropertyNotFound e) {
+ // Log error
+ } catch (CertificateException e) {
+ // log error
+ }
+ }
+ }
+
+ public void startup() throws EBaseException {
+ }
+
+ /**
+ * Stops this system.
+ */
+ public synchronized void shutdown() {
+ }
+
+ /*
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/cert/PrettyPrintFormat.java b/pki/base/common/src/com/netscape/cmscore/cert/PrettyPrintFormat.java
new file mode 100644
index 000000000..550756f31
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/PrettyPrintFormat.java
@@ -0,0 +1,166 @@
+// --- 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.cmscore.cert;
+
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import com.netscape.certsrv.base.*;
+
+
+/**
+ * This class will display the certificate content in predefined
+ * format.
+ *
+ * @author Andrew Wnuk
+ * @version $Revision$, $Date$
+ */
+public class PrettyPrintFormat implements IPrettyPrintFormat {
+
+ /*==========================================================
+ * variables
+ *==========================================================*/
+ private String mSeparator = "";
+ private int mIndentSize = 0;
+ private int mLineLen = 0;
+
+ /*==========================================================
+ * constants
+ *
+ *==========================================================*/
+ private final static String spaces =
+ " " +
+ " " +
+ " " +
+ " " +
+ " ";
+
+ /*==========================================================
+ * constructors
+ *==========================================================*/
+
+ public PrettyPrintFormat(String separator) {
+ mSeparator = separator;
+ }
+
+ public PrettyPrintFormat(String separator, int lineLen) {
+ mSeparator = separator;
+ mLineLen = lineLen;
+ }
+
+ public PrettyPrintFormat(String separator, int lineLen, int indentSize) {
+ mSeparator = separator;
+ mLineLen = lineLen;
+ mIndentSize = indentSize;
+ }
+
+ /*==========================================================
+ * Private methods
+ *==========================================================*/
+
+
+ /*==========================================================
+ * public methods
+ *==========================================================*/
+
+ /**
+ * Provide white space indention
+ * stevep - speed improvements. Factor of 10 improvement
+ * @param numSpace number of white space to be returned
+ * @return white spaces
+ */
+ public String indent(int size) {
+ return spaces.substring(0, size);
+ }
+
+ private static final char[] hexdigits = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+
+ /**
+ * Convert Byte Array to Hex String Format
+ * stevep - speedup by factor of 8
+ * @param byte array of data to hexify
+ * @param indentSize number of spaces to prepend before each line
+ * @param lineLen number of bytes to output on each line (0
+ means: put everything on one line
+ * @param separator the first character of this string will be used as
+ the separator between bytes.
+ * @return string representation
+ */
+
+ public String toHexString(byte[] in, int indentSize,
+ int lineLen, String separator) {
+ StringBuffer sb = new StringBuffer();
+ int hexCount = 0;
+ char c[];
+ int j = 0;
+
+ if (lineLen == 0) {
+ c = new char[in.length * 3 + 1];
+ } else {
+ c = new char[lineLen * 3 + 1];
+ }
+
+ char sep = separator.charAt(0);
+
+ sb.append(indent(indentSize));
+ for (int i = 0; i < in.length; i++) {
+ if (lineLen > 0 && hexCount == lineLen) {
+ c[j++] = '\n';
+ sb.append(c, 0, j);
+ sb.append(indent(indentSize));
+ hexCount = 0;
+ j = 0;
+ }
+ byte x = in[i];
+
+ // output hex digits to buffer
+ c[j++] = hexdigits[(char) ((x >> 4) & 0xf)];
+ c[j++] = hexdigits[(char) (x & 0xf)];
+
+ // if not last char, output separator
+ if (i != in.length - 1) {
+ c[j++] = sep;
+ }
+
+ hexCount++;
+ }
+ if (j > 0) {
+ c[j++] = '\n';
+ sb.append(c, 0, j);
+ }
+ // sb.append("\n");
+
+ return sb.toString();
+ }
+
+ public String toHexString(byte[] in, int indentSize, int lineLen) {
+ return toHexString(in, indentSize, lineLen, mSeparator);
+ }
+
+ public String toHexString(byte[] in, int indentSize) {
+ return toHexString(in, indentSize, mLineLen);
+ }
+
+ public String toHexString(byte[] in) {
+ return toHexString(in, mIndentSize);
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/cert/PrettyPrintResources.java b/pki/base/common/src/com/netscape/cmscore/cert/PrettyPrintResources.java
new file mode 100644
index 000000000..026dbfcbc
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/PrettyPrintResources.java
@@ -0,0 +1,294 @@
+// --- 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.cmscore.cert;
+
+
+import java.util.*;
+import netscape.security.x509.*;
+import netscape.security.extensions.*;
+
+
+/**
+ * Resource Boundle for the Pretty Print
+ *
+ * @author Jack Pan-Chen
+ * @version $Revision$, $Date$
+ */
+
+public class PrettyPrintResources extends ListResourceBundle {
+
+ /**
+ * Returns content
+ */
+ public Object[][] getContents() {
+ return contents;
+ }
+
+ /**
+ * Constants. The suffix represents the number of
+ * possible parameters.
+ */
+
+ //certificate pretty print
+ public final static String TOKEN_CERTIFICATE = "tokenCertificate";
+ public final static String TOKEN_DATA = "tokenData";
+ public final static String TOKEN_VERSION = "tokenVersion";
+ public final static String TOKEN_SERIAL = "tokenSerial";
+ public final static String TOKEN_SIGALG = "tokenSignatureAlgorithm";
+ public final static String TOKEN_ISSUER = "tokenIssuer";
+ public final static String TOKEN_VALIDITY = "tokenValidity";
+ public final static String TOKEN_NOT_BEFORE = "tokenNotBefore";
+ public final static String TOKEN_NOT_AFTER = "tokenNotAfter";
+ public final static String TOKEN_SUBJECT = "tokenSubject";
+ public final static String TOKEN_SPKI = "tokenSPKI";
+ public final static String TOKEN_ALGORITHM = "tokenAlgorithm";
+ public final static String TOKEN_PUBLIC_KEY = "tokenPublicKey";
+ public final static String TOKEN_PUBLIC_KEY_MODULUS = "tokenPublicKeyModulus";
+ public final static String TOKEN_PUBLIC_KEY_EXPONENT = "tokenPublicKeyExponent";
+ public final static String TOKEN_EXTENSIONS = "tokenExtensions";
+ public final static String TOKEN_SIGNATURE = "tokenSignature";
+
+ //extension pretty print
+ public final static String TOKEN_YES = "tokenYes";
+ public final static String TOKEN_NO = "tokenNo";
+ public final static String TOKEN_IDENTIFIER = "tokenIdentifier";
+ public final static String TOKEN_CRITICAL = "tokenCritical";
+ public final static String TOKEN_VALUE = "tokenValue";
+
+ //specific extension token
+ public final static String TOKEN_KEY_TYPE = "tokenKeyType";
+ public final static String TOKEN_CERT_TYPE = "tokenCertType";
+ public final static String TOKEN_SKI = "tokenSKI";
+ public final static String TOKEN_AKI = "tokenAKI";
+ public final static String TOKEN_ACCESS_DESC = "tokenAccessDesc";
+ public final static String TOKEN_OCSP_NOCHECK = "tokenOcspNoCheck";
+ public final static String TOKEN_EXTENDED_KEY_USAGE = "tokenExtendedKeyUsage";
+ public final static String TOKEN_PRIVATE_KEY_USAGE = "tokenPrivateKeyUsage";
+ public final static String TOKEN_PRESENCE_SERVER = "tokenPresenceServer";
+ public final static String TOKEN_AIA = "tokenAIA";
+ public final static String TOKEN_KEY_USAGE = "tokenKeyUsage";
+ public final static String TOKEN_CERT_USAGE = "tokenCertUsage";
+ public final static String TOKEN_KEY_ID = "tokenKeyId";
+ public final static String TOKEN_AUTH_NAME = "tokenAuthName";
+
+ public final static String TOKEN_CRL = "tokenCRL";
+ public final static String TOKEN_THIS_UPDATE = "tokenThisUpdate";
+ public final static String TOKEN_NEXT_UPDATE = "tokenNextUpdate";
+ public final static String TOKEN_REVOKED_CERTIFICATES = "revokedCerts";
+ public final static String TOKEN_REVOCATION_DATE = "revocationDate";
+
+ public final static String TOKEN_REVOCATION_REASON = "revocationReason";
+ public final static String TOKEN_REASON = "reason";
+
+ public final static String TOKEN_BASIC_CONSTRAINTS = "basicConstraints";
+ public final static String TOKEN_NAME_CONSTRAINTS = "tokenNameConstraints";
+ public final static String TOKEN_NSC_COMMENT = "tokenNSCComment";
+ public final static String TOKEN_IS_CA = "isCA";
+ public final static String TOKEN_PATH_LEN = "pathLen";
+ public final static String TOKEN_PATH_LEN_UNLIMITED = "pathLenUnlimited";
+ public final static String TOKEN_PATH_LEN_UNDEFINED = "pathLenUndefined";
+ public final static String TOKEN_PATH_LEN_INVALID = "pathLenInvalid";
+
+ public final static String TOKEN_CRL_NUMBER = "CRLNumber";
+ public final static String TOKEN_NUMBER = "Number";
+
+ public final static String TOKEN_DELTA_CRL_INDICATOR = "DeltaCRLIndicator";
+ public final static String TOKEN_BASE_CRL_NUMBER = "BaseCRLNumber";
+
+ public final static String TOKEN_CERT_SCOPE_OF_USE = "CertificateScopeOfUse";
+ public final static String TOKEN_SCOPE_OF_USE = "ScopeOfUse";
+ public final static String TOKEN_PORT = "Port";
+
+ public final static String TOKEN_ISSUER_ALT_NAME = "IssuerAlternativeName";
+ public final static String TOKEN_ISSUER_NAMES = "IssuerNames";
+
+ public final static String TOKEN_SUBJECT_ALT_NAME = "SubjectAlternativeName";
+ public final static String TOKEN_SUBJECT_NAME = "SubjectName";
+
+ public final static String TOKEN_DECODING_ERROR = "decodingError";
+
+ public final static String TOKEN_FRESHEST_CRL_EXT = "FreshestCRL";
+
+ public final static String TOKEN_CRL_DP_EXT = "CRLDistributionPoints";
+ public final static String TOKEN_CRLDP_NUMPOINTS = "CRLDP_NUMPOINTS";
+ public final static String TOKEN_CRLDP_POINTN = "CRLDP_POINTN";
+ public final static String TOKEN_CRLDP_DISTPOINT = "CRLDP_DISTPOINT";
+ public final static String TOKEN_CRLDP_REASONS = "CRLDP_REASONS";
+ public final static String TOKEN_CRLDP_CRLISSUER = "CRLDP_CRLISSUER";
+
+ public final static String TOKEN_ISSUING_DIST_POINT = "IssuingDistributionPoint";
+ public final static String TOKEN_DIST_POINT_NAME = "DistributionPointName";
+ public final static String TOKEN_FULL_NAME = "FullName";
+ public final static String TOKEN_RELATIVE_NAME = "NameRelativeToCRLIssuer";
+ public final static String TOKEN_ONLY_USER_CERTS = "OnlyContainsUserCerts";
+ public final static String TOKEN_ONLY_CA_CERTS = "OnlyContainsCACerts";
+ public final static String TOKEN_ONLY_SOME_REASONS = "OnlySomeReasons";
+ public final static String TOKEN_INDIRECT_CRL = "IndirectCRL";
+
+ public final static String TOKEN_INVALIDITY_DATE = "invalidityDate";
+ public final static String TOKEN_DATE_OF_INVALIDITY = "dateOfInvalidity";
+
+ public final static String TOKEN_CERTIFICATE_ISSUER = "CertificateIssuer";
+
+ public final static String TOKEN_HOLD_INSTRUCTION = "HoldInstruction";
+ public final static String TOKEN_HOLD_INSTRUCTION_CODE = "HoldInstructionCode";
+ public final static String TOKEN_POLICY_CONSTRAINTS = "PolicyConstraints";
+ public final static String TOKEN_POLICY_MAPPINGS = "PolicyMappings";
+ public final static String TOKEN_SUBJECT_DIR_ATTR = "SubjectDirectoryAttributes";
+
+ // policy constriants extension fields
+ public final static String TOKEN_INHIBIT_POLICY_MAPPING = "inhibitPolicyMapping";
+ public final static String TOKEN_REQUIRE_EXPLICIT_POLICY = "requireExplicitPolicy";
+
+ // policy mappings extension fields
+ public final static String TOKEN_MAPPINGS = "mappings";
+ public final static String TOKEN_MAP = "map";
+ public final static String TOKEN_ISSUER_DOMAIN_POLICY = "issuerDomainPolicy";
+ public final static String TOKEN_SUBJECT_DOMAIN_POLICY = "subjectDomainPolicy";
+
+ // subject directory attribute fields
+ public final static String TOKEN_ATTRIBUTES = "Attributes";
+ public final static String TOKEN_ATTRIBUTE = "Attribute";
+ public final static String TOKEN_VALUES = "Values";
+
+ // field values
+ public final static String TOKEN_NOT_SET = "notSet";
+ public final static String TOKEN_NONE = "none";
+
+ public final static String TOKEN_CACHE_NOT_AVAILABLE = "cacheNotAvailable";
+ public final static String TOKEN_CACHE_IS_EMPTY = "cacheIsEmpty";
+
+ //Tokens should have blank_space as trailer
+ static final Object[][] contents = {
+ {TOKEN_CERTIFICATE, "Certificate: "},
+ {TOKEN_DATA, "Data: "},
+ {TOKEN_VERSION, "Version: "},
+ {TOKEN_SERIAL, "Serial Number: "},
+ {TOKEN_SIGALG, "Signature Algorithm: "},
+ {TOKEN_ISSUER, "Issuer: "},
+ {TOKEN_VALIDITY, "Validity: "},
+ {TOKEN_NOT_BEFORE, "Not Before: "},
+ {TOKEN_NOT_AFTER, "Not After: "},
+ {TOKEN_SUBJECT, "Subject: "},
+ {TOKEN_SPKI, "Subject Public Key Info: "},
+ {TOKEN_ALGORITHM, "Algorithm: "},
+ {TOKEN_PUBLIC_KEY, "Public Key: "},
+ {TOKEN_PUBLIC_KEY_MODULUS, "Public Key Modulus: "},
+ {TOKEN_PUBLIC_KEY_EXPONENT, "Exponent: "},
+ {TOKEN_EXTENSIONS, "Extensions: "},
+ {TOKEN_SIGNATURE, "Signature: "},
+ {TOKEN_YES, "yes "},
+ {TOKEN_NO, "no "},
+ {TOKEN_IDENTIFIER, "Identifier: "},
+ {TOKEN_CRITICAL, "Critical: "},
+ {TOKEN_VALUE, "Value: "},
+ {TOKEN_KEY_TYPE, "Key Type "},
+ {TOKEN_CERT_TYPE, "Netscape Certificate Type "},
+ {TOKEN_SKI, "Subject Key Identifier "},
+ {TOKEN_AKI, "Authority Key Identifier "},
+ {TOKEN_ACCESS_DESC, "Access Description: "},
+ {TOKEN_OCSP_NOCHECK, "OCSP NoCheck: "},
+ {TOKEN_EXTENDED_KEY_USAGE, "Extended Key Usage: "},
+ {TOKEN_PRIVATE_KEY_USAGE, "Private Key Usage: "},
+ {TOKEN_PRESENCE_SERVER, "Presence Server: "},
+ {TOKEN_AIA, "Authority Info Access: "},
+ {TOKEN_KEY_USAGE, "Key Usage: "},
+ {KeyUsageExtension.DIGITAL_SIGNATURE, "Digital Signature "},
+ {KeyUsageExtension.NON_REPUDIATION, "Non Repudiation "},
+ {KeyUsageExtension.KEY_ENCIPHERMENT, "Key Encipherment "},
+ {KeyUsageExtension.DATA_ENCIPHERMENT, "Data Encipherment "},
+ {KeyUsageExtension.KEY_AGREEMENT, "Key Agreement "},
+ {KeyUsageExtension.KEY_CERTSIGN, "Key CertSign "},
+ {KeyUsageExtension.CRL_SIGN, "Crl Sign "},
+ {KeyUsageExtension.ENCIPHER_ONLY, "Encipher Only "},
+ {KeyUsageExtension.DECIPHER_ONLY, "Decipher Only "},
+ {TOKEN_CERT_USAGE, "Certificate Usage: "},
+ {NSCertTypeExtension.SSL_CLIENT, "SSL Client "},
+ {NSCertTypeExtension.SSL_SERVER, "SSL Server "},
+ {NSCertTypeExtension.EMAIL, "Secure Email "},
+ {NSCertTypeExtension.OBJECT_SIGNING, "Object Signing "},
+ {NSCertTypeExtension.SSL_CA, "SSL CA "},
+ {NSCertTypeExtension.EMAIL_CA, "Secure Email CA "},
+ {NSCertTypeExtension.OBJECT_SIGNING_CA, "ObjectSigning CA "},
+ {TOKEN_KEY_ID, "Key Identifier: "},
+ {TOKEN_AUTH_NAME, "Authority Name: "},
+ {TOKEN_CRL, "Certificate Revocation List: "},
+ {TOKEN_THIS_UPDATE, "This Update: "},
+ {TOKEN_NEXT_UPDATE, "Next Update: "},
+ {TOKEN_REVOKED_CERTIFICATES, "Revoked Certificates: "},
+ {TOKEN_REVOCATION_DATE, "Revocation Date: "},
+ {TOKEN_REVOCATION_REASON, "Revocation Reason "},
+ {TOKEN_REASON, "Reason: "},
+ {TOKEN_BASIC_CONSTRAINTS, "Basic Constraints "},
+ {TOKEN_NAME_CONSTRAINTS, "Name Constraints "},
+ {TOKEN_NSC_COMMENT, "Netscape Comment "},
+ {TOKEN_IS_CA, "Is CA: "},
+ {TOKEN_PATH_LEN, "Path Length Constraint: "},
+ {TOKEN_PATH_LEN_UNLIMITED, "UNLIMITED"},
+ {TOKEN_PATH_LEN_UNDEFINED, "UNDEFINED"},
+ {TOKEN_PATH_LEN_INVALID, "INVALID"},
+ {TOKEN_CRL_NUMBER, "CRL Number "},
+ {TOKEN_NUMBER, "Number: "},
+ {TOKEN_DELTA_CRL_INDICATOR, "Delta CRL Indicator "},
+ {TOKEN_BASE_CRL_NUMBER, "Base CRL Number: "},
+ {TOKEN_CERT_SCOPE_OF_USE, "Certificate Scope of Use "},
+ {TOKEN_SCOPE_OF_USE, "Scope of Use: "},
+ {TOKEN_PORT, "Port: "},
+ {TOKEN_ISSUER_ALT_NAME, "Issuer Alternative Name "},
+ {TOKEN_ISSUER_NAMES, "Issuer Names: "},
+ {TOKEN_SUBJECT_ALT_NAME, "Subject Alternative Name "},
+ {TOKEN_DECODING_ERROR, "Decoding Error"},
+ {TOKEN_FRESHEST_CRL_EXT, "Freshest CRL "},
+ {TOKEN_CRL_DP_EXT, "CRL Distribution Points "},
+ {TOKEN_CRLDP_NUMPOINTS, "Number of Points: "},
+ {TOKEN_CRLDP_POINTN, "Point "},
+ {TOKEN_CRLDP_DISTPOINT, "Distribution Point: "},
+ {TOKEN_CRLDP_REASONS, "Reason Flags: "},
+ {TOKEN_CRLDP_CRLISSUER, "CRL Issuer: "},
+ {TOKEN_ISSUING_DIST_POINT, "Issuing Distribution Point "},
+ {TOKEN_DIST_POINT_NAME, "Distribution Point: "},
+ {TOKEN_FULL_NAME, "Full Name: "},
+ {TOKEN_RELATIVE_NAME, "Name Relative To CRL Issuer: "},
+ {TOKEN_ONLY_USER_CERTS, "Only Contains User Certificates: "},
+ {TOKEN_ONLY_CA_CERTS, "Only Contains CA Certificates: "},
+ {TOKEN_ONLY_SOME_REASONS, "Only Some Reasons: "},
+ {TOKEN_INDIRECT_CRL, "Indirect CRL: "},
+ {TOKEN_INVALIDITY_DATE, "Invalidity Date "},
+ {TOKEN_DATE_OF_INVALIDITY, "Invalidity Date: "},
+ {TOKEN_CERTIFICATE_ISSUER, "Certificate Issuer "},
+ {TOKEN_HOLD_INSTRUCTION, "Hold Instruction Code "},
+ {TOKEN_HOLD_INSTRUCTION_CODE, "Hold Instruction Code: "},
+ {TOKEN_POLICY_CONSTRAINTS, "Policy Constraints "},
+ {TOKEN_INHIBIT_POLICY_MAPPING, "Inhibit Policy Mapping: "},
+ {TOKEN_REQUIRE_EXPLICIT_POLICY, "Require Explicit Policy: "},
+ {TOKEN_POLICY_MAPPINGS, "Policy Mappings "},
+ {TOKEN_MAPPINGS, "Mappings: "},
+ {TOKEN_MAP, "Map "},
+ {TOKEN_ISSUER_DOMAIN_POLICY, "Issuer Domain Policy: "},
+ {TOKEN_SUBJECT_DOMAIN_POLICY, "Subject Domain Policy: "},
+ {TOKEN_SUBJECT_DIR_ATTR, "Subject Directory Attributes "},
+ {TOKEN_ATTRIBUTES, "Attributes:" },
+ {TOKEN_ATTRIBUTE, "Attribute "},
+ {TOKEN_VALUES, "Values: "},
+ {TOKEN_NOT_SET, "not set"},
+ {TOKEN_NONE, "none"},
+ {TOKEN_CACHE_NOT_AVAILABLE, "CRL cache is not available. "},
+ {TOKEN_CACHE_IS_EMPTY, "CRL cache is empty. "},
+ };
+
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/cert/PubKeyPrettyPrint.java b/pki/base/common/src/com/netscape/cmscore/cert/PubKeyPrettyPrint.java
new file mode 100644
index 000000000..1f2d16136
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/PubKeyPrettyPrint.java
@@ -0,0 +1,45 @@
+// --- 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.cmscore.cert;
+
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.security.cert.*;
+import netscape.security.util.*;
+import netscape.security.x509.*;
+import netscape.security.provider.RSAPublicKey;
+import com.netscape.cmscore.util.*;
+import java.security.*;
+
+
+/**
+ * This class will display the certificate content in predefined
+ * format.
+ *
+ * @author Jack Pan-Chen
+ * @author Andrew Wnuk
+ * @version $Revision$, $Date$
+ */
+public class PubKeyPrettyPrint extends netscape.security.util.PubKeyPrettyPrint {
+
+ public PubKeyPrettyPrint(PublicKey key) {
+ super(key);
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/cert/X500NameSubsystem.java b/pki/base/common/src/com/netscape/cmscore/cert/X500NameSubsystem.java
new file mode 100644
index 000000000..0efc09d33
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/X500NameSubsystem.java
@@ -0,0 +1,277 @@
+// --- 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.cmscore.cert;
+
+
+import java.awt.*;
+import java.io.*;
+import java.util.*;
+import com.netscape.certsrv.base.*;
+import netscape.security.x509.*;
+import netscape.security.util.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * Subsystem for configuring X500Name related things.
+ * It is used for the following.
+ * <ul>
+ * <li>Add X500Name (string to oid) maps for attributes that
+ * are not supported by default.
+ * <li>Specify an order for encoding Directory Strings other than the default.
+ * </ul>
+ *
+ * @author lhsiao
+ * @version $Revision$
+ */
+public class X500NameSubsystem implements ISubsystem {
+
+ private IConfigStore mConfig = null;
+ public static final String ID = "X500Name";
+ private String mId = ID;
+
+ private static final String
+ PROP_DIR_STR_ENCODING_ORDER = "directoryStringEncodingOrder";
+
+ private static final String PROP_ATTR = "attr";
+ private static final String PROP_OID = "oid";
+ private static final String PROP_CLASS = "class";
+
+ private X500NameSubsystem() {
+ }
+
+ /**
+ * Retrieves subsystem identifier.
+ */
+ public String getId() {
+ return mId;
+ }
+
+ public void setId(String id) throws EBaseException {
+ mId = id;
+ }
+
+ // singleton enforcement
+
+ private static X500NameSubsystem mInstance = new X500NameSubsystem();
+
+ public static X500NameSubsystem getInstance() {
+ return mInstance;
+ }
+
+ /**
+ * Initializes this subsystem with the given configuration store.
+ * All paramters are optional.
+ * <ul>
+ * <li>Change encoding order of Directory Strings:
+ * <pre>
+ * X500Name.directoryStringEncodingOrder=order seperated by commas
+ * For example: Printable,BMPString,UniversalString.
+ * </pre>
+ * Possible values are:
+ * <ul>
+ * <li>Printable
+ * <li>IA5String
+ * <li>UniversalString
+ * <li>BMPString
+ * <li>UTF8String
+ * </ul>
+ * <p>
+ * <li>Add X500Name attributes:
+ * <pre>
+ * X500Name.attr.attribute-name.oid=n.n.n.n
+ * X500Name.attr.attribute-name.class=value converter class
+ * </pre>
+ *
+ * The value converter class converts a string to a ASN.1 value.
+ * It must implement netscape.security.x509.AVAValueConverter interface.
+ * Converter classes provided in CMS are:
+ * <pre>
+ * netscape.security.x509.PrintableConverter -
+ * Converts to a Printable String value. String must have only
+ * printable characters.
+ * netscape.security.x509.IA5StringConverter -
+ * Converts to a IA5String value. String must have only IA5String
+ * characters.
+ * netscape.security.x509.DirStrConverter -
+ * Converts to a Directory (v3) String. String is expected to
+ * be in Directory String format according to rfc2253.
+ * netscape.security.x509.GenericValueConverter -
+ * Converts string character by character in the following order
+ * from smaller character sets to broadest character set.
+ * Printable, IA5String, BMPString, Universal String.
+ * </pre>
+ * </ul>
+ * <P>
+ *
+ * @param owner owner of this subsystem
+ * @param config configuration store
+ */
+ public synchronized void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mLogger = CMS.getLogger();
+ if (Debug.ON) {
+ Debug.trace(ID + " started");
+ }
+ mConfig = config;
+
+ // get order for encoding directory strings if any.
+ setDirStrEncodingOrder();
+
+ // load x500 name maps
+ loadX500NameAttrMaps();
+ }
+
+ /**
+ * Loads X500Name String to attribute maps.
+ * Called from init.
+ */
+ private void loadX500NameAttrMaps()
+ throws EBaseException {
+ X500NameAttrMap globalMap = X500NameAttrMap.getDefault();
+ IConfigStore attrSubStore = mConfig.getSubStore(PROP_ATTR);
+ Enumeration attrNames = attrSubStore.getSubStoreNames();
+
+ while (attrNames.hasMoreElements()) {
+ String name = (String) attrNames.nextElement();
+ IConfigStore substore = attrSubStore.getSubStore(name);
+ String oidString = substore.getString(PROP_OID);
+ ObjectIdentifier oid = CertUtils.checkOID(name, oidString);
+ String className = substore.getString(PROP_CLASS);
+
+ AVAValueConverter convClass = null;
+
+ try {
+ convClass = (AVAValueConverter)
+ Class.forName(className).newInstance();
+ } catch (Exception e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_LOAD_CLASS_FAILED", className, e.toString()));
+ }
+ globalMap.addNameOID(name, oid, convClass);
+ if (Debug.ON) {
+ Debug.trace(ID + ": Loaded " + name + " " + oid + " " + className);
+ }
+ }
+ }
+
+ /**
+ * Set directory string encoding order.
+ * Called from init().
+ */
+ private void setDirStrEncodingOrder()
+ throws EBaseException {
+ String order = mConfig.getString(PROP_DIR_STR_ENCODING_ORDER, null);
+
+ if (order == null || order.length() == 0) // nothing.
+ return;
+ StringTokenizer toker = new StringTokenizer(order, ", \t");
+ int numTokens = toker.countTokens();
+
+ if (numTokens == 0) {
+ String msg = "must be a list of DER tag names seperated by commas.";
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CERT_DIR_STRING", PROP_DIR_STR_ENCODING_ORDER));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ PROP_DIR_STR_ENCODING_ORDER, msg));
+ }
+
+ byte[] tags = new byte[numTokens];
+
+ for (int i = 0; toker.hasMoreTokens(); i++) {
+ String nextTag = (String) toker.nextToken();
+
+ try {
+ tags[i] = derStr2Tag(nextTag);
+ } catch (IllegalArgumentException e) {
+ String msg = "unknown DER tag '" + nextTag + "'.";
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CERT_UNKNOWN_TAG", PROP_DIR_STR_ENCODING_ORDER, nextTag));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ PROP_DIR_STR_ENCODING_ORDER, msg));
+ }
+ }
+
+ DirStrConverter.setDefEncodingOrder(tags);
+ }
+
+ private static String PRINTABLESTRING = "PrintableString";
+ private static String IA5STRING = "IA5String";
+ private static String VISIBLESTRING = "VisibleString";
+ private static String T61STRING = "T61String";
+ private static String BMPSTRING = "BMPString";
+ private static String UNIVERSALSTRING = "UniversalString";
+ private static String UFT8STRING = "UTF8String";
+ private static Hashtable mDerStr2TagHash = new Hashtable();
+
+ static {
+ mDerStr2TagHash.put(
+ PRINTABLESTRING, Byte.valueOf(DerValue.tag_PrintableString));
+ mDerStr2TagHash.put(
+ IA5STRING, Byte.valueOf(DerValue.tag_IA5String));
+ mDerStr2TagHash.put(
+ VISIBLESTRING, Byte.valueOf(DerValue.tag_VisibleString));
+ mDerStr2TagHash.put(
+ T61STRING, Byte.valueOf(DerValue.tag_T61String));
+ mDerStr2TagHash.put(
+ BMPSTRING, Byte.valueOf(DerValue.tag_BMPString));
+ mDerStr2TagHash.put(
+ UNIVERSALSTRING, Byte.valueOf(DerValue.tag_UniversalString));
+ mDerStr2TagHash.put(
+ UFT8STRING, Byte.valueOf(DerValue.tag_UTF8String));
+ }
+
+ private byte derStr2Tag(String s) {
+ if (s == null || s.length() == 0)
+ throw new IllegalArgumentException();
+ Byte tag = (Byte) mDerStr2TagHash.get(s);
+
+ if (tag == null)
+ throw new IllegalArgumentException();
+ return tag.byteValue();
+ }
+
+ public void startup() throws EBaseException {
+ }
+
+ /**
+ * Stops this system.
+ */
+ public synchronized void shutdown() {
+ }
+
+ /*
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ protected ILogger mLogger = null;
+
+ protected void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM,
+ ILogger.S_ADMIN, level, msg);
+ }
+
+}