summaryrefslogtreecommitdiffstats
path: root/pki/base/common/src/com/netscape/cms/publish/publishers/FileBasedPublisher.java
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/common/src/com/netscape/cms/publish/publishers/FileBasedPublisher.java')
-rw-r--r--pki/base/common/src/com/netscape/cms/publish/publishers/FileBasedPublisher.java424
1 files changed, 424 insertions, 0 deletions
diff --git a/pki/base/common/src/com/netscape/cms/publish/publishers/FileBasedPublisher.java b/pki/base/common/src/com/netscape/cms/publish/publishers/FileBasedPublisher.java
new file mode 100644
index 000000000..18af1a98b
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/publish/publishers/FileBasedPublisher.java
@@ -0,0 +1,424 @@
+// --- 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.cms.publish.publishers;
+
+
+import java.math.*;
+import java.io.*;
+import java.security.cert.*;
+import java.util.*;
+import java.util.zip.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.publish.*;
+import org.mozilla.jss.util.Base64OutputStream;
+
+/**
+ * This publisher writes certificate and CRL into
+ * a directory.
+ *
+ * @version $Revision$, $Date$
+ */
+public class FileBasedPublisher implements ILdapPublisher, IExtendedPluginInfo {
+ private static final String PROP_DIR = "directory";
+ private static final String PROP_DER = "Filename.der";
+ private static final String PROP_B64 = "Filename.b64";
+ private static final String PROP_LNK = "latestCrlLink";
+ private static final String PROP_GMT = "timeStamp";
+ private static final String PROP_EXT = "crlLinkExt";
+ private static final String PROP_ZIP = "zipCRLs";
+ private static final String PROP_LEV = "zipLevel";
+ private IConfigStore mConfig = null;
+ private String mDir = null;
+ private ILogger mLogger = CMS.getLogger();
+ private String mCrlIssuingPointId;
+ protected boolean mDerAttr = true;
+ protected boolean mB64Attr = false;
+ protected boolean mLatestCRL = false;
+ protected boolean mZipCRL = false;
+ protected String mTimeStamp = null;
+ protected String mLinkExt = null;
+ protected int mZipLevel = 9;
+
+ public void setIssuingPointId(String crlIssuingPointId)
+ {
+ mCrlIssuingPointId = crlIssuingPointId;
+ }
+ /**
+ * Returns the implementation name.
+ */
+ public String getImplName() {
+ return "FileBasedPublisher";
+ }
+
+ /**
+ * Returns the description of the ldap publisher.
+ */
+
+ public String getDescription() {
+ return "This publisher writes the Certificates and CRLs into files.";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_DIR + ";string;Directory in which to put the files (absolute path or relative path to cert-* instance directory).",
+ PROP_DER + ";boolean;Store certificates or CRLs into *.der files.",
+ PROP_B64 + ";boolean;Store certificates or CRLs into *.b64 files.",
+ PROP_GMT + ";choice(LocalTime,GMT);Use local time or GMT to time stamp CRL file name with CRL's 'thisUpdate' field.",
+ PROP_LNK + ";boolean;Generate link to the latest binary CRL. It requires '"+PROP_DER+"' to be enabled.",
+ PROP_EXT + ";string;Name extension used by link to the latest CRL. Default name extension is 'der'.",
+ PROP_ZIP + ";boolean;Generate compressed CRLs.",
+ PROP_LEV + ";choice(0,1,2,3,4,5,6,7,8,9);Set compression level from 0 to 9.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ldappublish-publisher-filepublisher",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Stores the certificates or CRLs into files. Certificate is named as cert-<serialno>.der or *.b64, and CRL is named as <IssuingPoint>-<thisUpdate-time>.der or *.b64."
+ };
+
+ return params;
+ }
+
+ /**
+ * Returns the current instance parameters.
+ */
+ public Vector getInstanceParams() {
+ Vector v = new Vector();
+ String dir = "";
+ String ext = "";
+
+ try {
+ dir = mConfig.getString(PROP_DIR);
+ } catch (EBaseException e) {
+ }
+ try {
+ ext = mConfig.getString(PROP_EXT);
+ } catch (EBaseException e) {
+ }
+ try {
+ mTimeStamp = mConfig.getString(PROP_GMT);
+ } catch (EBaseException e) {
+ }
+ try {
+ mZipLevel = mConfig.getInteger(PROP_LEV, 9);
+ } catch (EBaseException e) {
+ }
+ try {
+ if (mTimeStamp == null || (!mTimeStamp.equals("GMT")))
+ mTimeStamp = "LocalTime";
+ v.addElement(PROP_DIR+"=" + dir);
+ v.addElement(PROP_DER+"=" + mConfig.getBoolean(PROP_DER,true));
+ v.addElement(PROP_B64+"=" + mConfig.getBoolean(PROP_B64,false));
+ v.addElement(PROP_GMT+"=" + mTimeStamp);
+ v.addElement(PROP_LNK+"=" + mConfig.getBoolean(PROP_LNK,false));
+ v.addElement(PROP_EXT+"=" + ext);
+ v.addElement(PROP_ZIP+"=" + mConfig.getBoolean(PROP_ZIP,false));
+ v.addElement(PROP_LEV+"=" + mZipLevel);
+ } catch (Exception e) {
+ }
+ return v;
+ }
+
+ /**
+ * Returns the initial default parameters.
+ */
+ public Vector getDefaultParams() {
+ Vector v = new Vector();
+
+ v.addElement(PROP_DIR+"=");
+ v.addElement(PROP_DER+"=true");
+ v.addElement(PROP_B64+"=false");
+ v.addElement(PROP_GMT+"=LocalTime");
+ v.addElement(PROP_LNK+"=false");
+ v.addElement(PROP_EXT+"=");
+ v.addElement(PROP_ZIP+"=false");
+ v.addElement(PROP_LEV+"=9");
+ return v;
+ }
+
+ /**
+ * Initializes this plugin.
+ */
+ public void init(IConfigStore config) {
+ mConfig = config;
+ String dir = null;
+ String ext = null;
+
+ try {
+ dir = mConfig.getString(PROP_DIR, null);
+ mDerAttr = mConfig.getBoolean(PROP_DER, true);
+ mB64Attr = mConfig.getBoolean(PROP_B64, false);
+ mTimeStamp = mConfig.getString(PROP_GMT, "LocalTime");
+ mLatestCRL = mConfig.getBoolean(PROP_LNK, false);
+ mLinkExt = mConfig.getString(PROP_EXT, null);
+ mZipCRL = mConfig.getBoolean(PROP_ZIP, false);
+ mZipLevel = mConfig.getInteger(PROP_LEV, 9);
+ } catch (EBaseException e) {
+ }
+ if (dir == null) {
+ throw new RuntimeException("No Directory Specified");
+ }
+
+ // convert to forward slash
+ dir = dir.replace('\\', '/');
+ config.putString(PROP_DIR, dir);
+
+ File dirCheck = new File(dir);
+
+ if (dirCheck.isDirectory()) {
+ mDir = dir;
+ } else {
+ // maybe it is relative path
+ String mInstanceRoot = null;
+
+ try {
+ mInstanceRoot = CMS.getConfigStore().getString("instanceRoot");
+ } catch (Exception e) {
+ throw new RuntimeException("Invalid Instance Dir " + e);
+ }
+ dirCheck = new File(mInstanceRoot +
+ File.separator + dir);
+ if (dirCheck.isDirectory()) {
+ mDir = mInstanceRoot + File.separator + dir;
+ } else {
+ throw new RuntimeException("Invalid Directory " + dir);
+ }
+ }
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ private String[] getCrlNamePrefix(X509CRL crl, boolean useGMT) {
+ String[] namePrefix = {"crl", "crl"};
+
+ if (mCrlIssuingPointId != null && mCrlIssuingPointId.length() != 0) {
+ namePrefix[0] = mCrlIssuingPointId;
+ namePrefix[1] = mCrlIssuingPointId;
+ }
+ java.text.SimpleDateFormat format = new java.text.SimpleDateFormat("yyyyMMdd-HHmmss");
+ TimeZone tz = TimeZone.getTimeZone("GMT");
+ if (useGMT) format.setTimeZone(tz);
+ String timeStamp = format.format(crl.getThisUpdate()).toString();
+ namePrefix[0] += "-" + timeStamp;
+ if (((netscape.security.x509.X509CRLImpl)crl).isDeltaCRL()) {
+ namePrefix[0] += "-delta";
+ namePrefix[1] += "-delta";
+ }
+
+ return namePrefix;
+ }
+
+ private void createLink(String linkName, String fileName) {
+ String cmd = "ln -s " + fileName + " " + linkName + ".new";
+ if (com.netscape.cmsutil.util.Utils.exec(cmd)) {
+ File oldLink = new File(linkName + ".old");
+ if (oldLink.exists()) { // remove old link if exists
+ oldLink.delete();
+ }
+ File link = new File(linkName);
+ if (link.exists()) { // current link becomes an old link
+ link.renameTo(new File(linkName + ".old"));
+ }
+ File newLink = new File(linkName + ".new");
+ if (newLink.exists()) { // new link becomes current link
+ newLink.renameTo(new File(linkName));
+ }
+ oldLink = new File(linkName + ".old");
+ if (oldLink.exists()) { // remove a new old link
+ oldLink.delete();
+ }
+ } else {
+ CMS.debug("FileBasedPublisher: createLink: '" + cmd + "' --- failed");
+ }
+ }
+
+ /**
+ * Publishs a object to the ldap directory.
+ *
+ * @param conn a Ldap connection
+ * (null if LDAP publishing is not enabled)
+ * @param dn dn of the ldap entry to publish cert
+ * (null if LDAP publishing is not enabled)
+ * @param object object to publish
+ * (java.security.cert.X509Certificate or,
+ * java.security.cert.X509CRL)
+ */
+ public void publish(LDAPConnection conn, String dn, Object object)
+ throws ELdapException {
+ CMS.debug("FileBasedPublisher: publish");
+ try {
+ if (object instanceof X509Certificate) {
+ X509Certificate cert = (X509Certificate) object;
+ BigInteger sno = cert.getSerialNumber();
+ String name = mDir +
+ File.separator + "cert-" +
+ sno.toString();
+ if (mDerAttr)
+ {
+ String fileName = name + ".der";
+ FileOutputStream fos = new FileOutputStream(fileName);
+ fos.write(cert.getEncoded());
+ fos.close();
+ }
+ if (mB64Attr)
+ {
+ String fileName = name + ".b64";
+ FileOutputStream fos = new FileOutputStream(fileName);
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ Base64OutputStream b64 =
+ new Base64OutputStream(new PrintStream(new FilterOutputStream(output)));
+ b64.write(cert.getEncoded());
+ b64.flush();
+ (new PrintStream(fos)).print(output.toString("8859_1"));
+ fos.close();
+ }
+ } else if (object instanceof X509CRL) {
+ X509CRL crl = (X509CRL) object;
+ String[] namePrefix = getCrlNamePrefix(crl, mTimeStamp.equals("GMT"));
+ String baseName = mDir + File.separator + namePrefix[0];
+ String tempFile = baseName + ".temp";
+ FileOutputStream fos;
+ ZipOutputStream zos;
+ byte [] encodedArray = null;
+ File destFile = null;
+ String destName = null;
+ File renameFile = null;
+
+ if (mDerAttr) {
+ fos = new FileOutputStream(tempFile);
+ encodedArray = crl.getEncoded();
+ fos.write(encodedArray);
+ fos.close();
+ if (mZipCRL) {
+ zos = new ZipOutputStream(new FileOutputStream(baseName+".zip"));
+ zos.setLevel(mZipLevel);
+ zos.putNextEntry(new ZipEntry(baseName+".der"));
+ zos.write(encodedArray, 0, encodedArray.length);
+ zos.closeEntry();
+ zos.close();
+ }
+ destName = baseName + ".der";
+ destFile = new File(destName);
+
+ if (destFile.exists())
+ destFile.delete();
+ renameFile = new File(tempFile);
+ renameFile.renameTo(destFile);
+
+ if (mLatestCRL) {
+ String linkExt = ".";
+ if (mLinkExt != null && mLinkExt.length() > 0) {
+ linkExt += mLinkExt;
+ } else {
+ linkExt += "der";
+ }
+ String linkName = mDir + File.separator + namePrefix[1] + linkExt;
+ createLink(linkName, destName);
+ if (mZipCRL) {
+ linkName = mDir + File.separator + namePrefix[1] + ".zip";
+ createLink(linkName, baseName+".zip");
+ }
+ }
+ }
+
+ // output base64 file
+ if(mB64Attr==true)
+ {
+ if (encodedArray ==null)
+ encodedArray = crl.getEncoded();
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+
+ fos = new FileOutputStream(tempFile);
+ fos.write(com.netscape.osutil.OSUtil.BtoA(encodedArray).getBytes());
+ fos.close();
+ destName = baseName + ".b64";
+ destFile = new File(destName);
+
+ if(destFile.exists())
+ destFile.delete();
+ renameFile = new File(tempFile);
+ renameFile.renameTo(destFile);
+ }
+ }
+ } catch (IOException e) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_FILE_PUBLISHER_ERROR", e.toString()));
+ } catch (CertificateEncodingException e) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_FILE_PUBLISHER_ERROR", e.toString()));
+ } catch (CRLException e) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_FILE_PUBLISHER_ERROR", e.toString()));
+ }
+ }
+
+ /**
+ * Unpublishs a object to the ldap directory.
+ *
+ * @param conn the Ldap connection
+ * (null if LDAP publishing is not enabled)
+ * @param dn dn of the ldap entry to unpublish cert
+ * (null if LDAP publishing is not enabled)
+ * @param object object to unpublish
+ * (java.security.cert.X509Certificate)
+ */
+ public void unpublish(LDAPConnection conn, String dn, Object object)
+ throws ELdapException {
+ CMS.debug("FileBasedPublisher: unpublish");
+ String name = mDir + File.separator;
+ String fileName;
+
+ if (object instanceof X509Certificate) {
+ X509Certificate cert = (X509Certificate) object;
+ BigInteger sno = cert.getSerialNumber();
+ name += "cert-" + sno.toString();
+ } else if (object instanceof X509CRL) {
+ X509CRL crl = (X509CRL) object;
+ String[] namePrefix = getCrlNamePrefix(crl, mTimeStamp.equals("GMT"));
+ name += namePrefix[0];
+
+ fileName = name + ".zip";
+ File f = new File(fileName);
+ f.delete();
+ }
+ fileName = name + ".der";
+ File f = new File(fileName);
+ f.delete();
+
+ fileName = name + ".b64";
+ f = new File(fileName);
+ f.delete();
+ }
+ /**
+ * returns the Der attribute where it'll be published.
+ */
+ public boolean getDerAttr() {
+ return mDerAttr;
+ }
+ /**
+ * returns the B64 attribute where it'll be published.
+ */
+ public boolean getB64Attr() {
+ return mB64Attr;
+ }
+}