summaryrefslogtreecommitdiffstats
path: root/pki/base/common/src/com/netscape/cms/jobs
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/common/src/com/netscape/cms/jobs')
-rw-r--r--pki/base/common/src/com/netscape/cms/jobs/AJobBase.java281
-rw-r--r--pki/base/common/src/com/netscape/cms/jobs/PublishCertsJob.java405
-rw-r--r--pki/base/common/src/com/netscape/cms/jobs/RenewalNotificationJob.java718
-rw-r--r--pki/base/common/src/com/netscape/cms/jobs/RequestInQueueJob.java219
-rw-r--r--pki/base/common/src/com/netscape/cms/jobs/UnpublishExpiredJob.java395
5 files changed, 2018 insertions, 0 deletions
diff --git a/pki/base/common/src/com/netscape/cms/jobs/AJobBase.java b/pki/base/common/src/com/netscape/cms/jobs/AJobBase.java
new file mode 100644
index 000000000..2e26264f8
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/jobs/AJobBase.java
@@ -0,0 +1,281 @@
+// --- 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.jobs;
+
+
+import java.util.*;
+import java.io.*;
+import java.security.*;
+import java.security.cert.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.notification.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.jobs.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * This abstract class is a base job for real job extentions for the
+ * Jobs Scheduler.
+ *
+ * @version $Revision$, $Date$
+ * @see com.netscape.certsrv.jobs.IJob
+ */
+public abstract class AJobBase implements IJob, Runnable {
+ // config parameters...
+ protected static final String PROP_SUMMARY = "summary";
+ protected static final String PROP_ENABLED = "enabled";
+ protected static final String PROP_EMAIL_SUBJECT = "emailSubject";
+ protected static final String PROP_EMAIL_TEMPLATE = "emailTemplate";
+ protected static final String PROP_ITEM_TEMPLATE = "itemTemplate";
+ protected static final String PROP_SENDER_EMAIL = "senderEmail";
+ protected static final String PROP_RECEIVER_EMAIL = "recipientEmail";
+
+ protected static final String STATUS_FAILURE = "failed";
+ protected static final String STATUS_SUCCESS = "succeeded";
+
+ // variables used by the Job Scheduler Daemon
+ protected String mImplName = null;
+ protected IConfigStore mConfig;
+ protected String mId = null;
+ protected String mCron = null;
+ protected IJobCron mJobCron = null;
+
+ protected ILogger mLogger = CMS.getLogger();
+ protected static String[] mConfigParams = null;
+
+ protected String mSummaryMailSubject = null;
+ protected boolean mMailHTML = false;
+ protected String mMailForm = null;
+ protected String mItemForm = null;
+ protected String mSummarySenderEmail = null;
+ protected String mSummaryReceiverEmail = null;
+ protected Hashtable mContentParams = new Hashtable();
+ protected Hashtable mItemParams = new Hashtable();
+
+ public AJobBase() {
+ }
+
+ /**
+ * tells if the job is enabled
+ * @return a boolean value indicating whether the job is enabled
+ * or not
+ */
+ public boolean isEnabled() {
+ boolean enabled = false;
+
+ try {
+ enabled = mConfig.getBoolean(PROP_ENABLED, false);
+ } catch (EBaseException e) {
+ }
+ return enabled;
+ }
+
+ /***********************
+ * abstract methods
+ ***********************/
+ public abstract void init(ISubsystem owner, String id, String implName, IConfigStore
+ config) throws EBaseException;
+
+ public abstract void run();
+
+ /***********************
+ * public methods
+ ***********************/
+
+ /**
+ * get instance id.
+ * @return a String identifier
+ */
+ public String getId() {
+ return mId;
+ }
+
+ /**
+ * set instance id.
+ * @param id String id of the instance
+ */
+ public void setId(String id) {
+ mId = id;
+ }
+
+ /**
+ * get cron string associated with this job
+ * @return a JobCron object that represents the schedule of this job
+ */
+ public IJobCron getJobCron() {
+ return mJobCron;
+ }
+
+ /**
+ * gets the plugin name of this job.
+ * @return a String that is the name of this implementation
+ */
+ public String getImplName() {
+ return mImplName;
+ }
+
+ /**
+ * Gets the configuration substore used by this job
+ * @return configuration store
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /*
+ * get form file content from disk
+ */
+ protected String getTemplateContent(String templatePath) {
+ String templateString = null;
+
+ /*
+ * get template file from disk
+ */
+ IEmailTemplate template = CMS.getEmailTemplate(templatePath);
+
+ if (template != null) {
+ if (!template.init()) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("JOBS_TEMPLATE_INIT_ERROR"));
+ return null;
+ }
+
+ // this should take care of inner tempaltes not being html
+ // we go with the outter template
+ if (template.isHTML()) {
+ mMailHTML = true;
+ }
+ templateString = template.toString();
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("JOBS_TEMPLATE_INIT_ERROR"));
+ }
+
+ return templateString;
+ }
+
+ protected void mailSummary(String content) {
+ // no need for email resolver here...
+ IMailNotification mn = CMS.getMailNotification();
+
+ mn.setFrom(mSummarySenderEmail);
+ mn.setTo(mSummaryReceiverEmail);
+ mn.setSubject(mSummaryMailSubject);
+ if (mMailHTML == true) {
+ mn.setContentType("text/html");
+ }
+
+ mn.setContent(content);
+ try {
+ mn.sendNotification();
+ } catch (ENotificationException e) {
+ // already logged, lets audit
+ mLogger.log(ILogger.EV_AUDIT, null,
+ ILogger.S_OTHER,
+ ILogger.LL_FAILURE, CMS.getLogMessage("JOBS_SEND_NOTIFICATION", e.toString()));
+ } catch (IOException e) {
+ // already logged, lets audit
+ mLogger.log(ILogger.EV_AUDIT, null,
+ ILogger.S_OTHER,
+ ILogger.LL_FAILURE, CMS.getLogMessage("JOBS_SEND_NOTIFICATION", e.toString()));
+ }
+ }
+
+ protected void buildItemParams(X509CertImpl cert) {
+ mItemParams.put(IEmailFormProcessor.TOKEN_SERIAL_NUM,
+ (Object) cert.getSerialNumber().toString());
+ mItemParams.put(IEmailFormProcessor.TOKEN_HEX_SERIAL_NUM,
+ (Object) cert.getSerialNumber().toString(16));
+ mItemParams.put(IEmailFormProcessor.TOKEN_ISSUER_DN,
+ (Object) cert.getIssuerDN().toString());
+ mItemParams.put(IEmailFormProcessor.TOKEN_SUBJECT_DN,
+ (Object) cert.getSubjectDN().toString());
+ mItemParams.put(IEmailFormProcessor.TOKEN_NOT_AFTER,
+ (Object) cert.getNotAfter().toString());
+ mItemParams.put(IEmailFormProcessor.TOKEN_NOT_BEFORE,
+ (Object) cert.getNotBefore().toString());
+ // ... and more
+ }
+
+ protected void buildItemParams(IRequest r) {
+ String re = r.getExtDataInString(IRequest.HTTP_PARAMS, "csrRequestorEmail");
+
+ if (re != null) {
+ mItemParams.put(IEmailFormProcessor.TOKEN_REQUESTOR_EMAIL, re);
+ }
+
+ String ct = r.getExtDataInString(IRequest.HTTP_PARAMS, IRequest.CERT_TYPE);
+
+ if (ct != null) {
+ mItemParams.put(IEmailFormProcessor.TOKEN_CERT_TYPE, ct);
+ }
+
+ String rt = r.getExtDataInString(IRequest.REQ_TYPE);
+
+ if (rt != null) {
+ mItemParams.put(IEmailFormProcessor.TOKEN_REQUEST_TYPE, rt);
+ }
+ }
+
+ protected void buildItemParams(String name, String val) {
+ if (val != null)
+ mItemParams.put(name, val);
+ else {
+ CMS.debug("AJobBase: buildItemParams: null value for name= " + name);
+ mItemParams.put(name, "");
+ }
+ }
+
+ protected void buildContentParams(String name, String val) {
+ if (val != null)
+ mContentParams.put(name, val);
+ else {
+ CMS.debug("AJobBase: buildContentParams: null value for name= " + name);
+ mContentParams.put(name, "");
+ }
+ }
+
+ /**
+ * logs an entry in the log file. Used by classes extending this class.
+ * @param level log level
+ * @param msg log message in String
+ */
+ public void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER,
+ level, mId + ": " + msg);
+ }
+
+ /**
+ * capable of logging multiline entry in the log file. Used by classes extending this class.
+ * @param level log level
+ * @param msg log message in String
+ * @param multiline boolean indicating whether the message is a
+ * multi-lined message.
+ */
+ public void log(int level, String msg, boolean multiline) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER,
+ level, mId + ": " + msg, multiline);
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cms/jobs/PublishCertsJob.java b/pki/base/common/src/com/netscape/cms/jobs/PublishCertsJob.java
new file mode 100644
index 000000000..5da23d045
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/jobs/PublishCertsJob.java
@@ -0,0 +1,405 @@
+// --- 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.jobs;
+
+
+import java.util.*;
+import java.io.*;
+import java.text.DateFormat;
+import java.security.*;
+import java.security.cert.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.notification.*;
+import com.netscape.certsrv.jobs.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.publish.*;
+
+
+/**
+ * a job for the Jobs Scheduler. This job checks in the internal ldap
+ * db for valid certs that have not been published to the
+ * publishing directory.
+ * <p>
+ * the $TOKENS that are available for the this jobs's summary outer form are:<br>
+ * <UL>
+ * $Status
+ * $InstanceID
+ * $SummaryItemList
+ * $SummaryTotalNum
+ * $SummaryTotalSuccess
+ * $SummaryTotalfailure
+ * $ExecutionTime
+ * </UL>
+ * and for the inner list items:
+ * <UL>
+ * $SerialNumber
+ * $IssuerDN
+ * $SubjectDN
+ * $NotAfter
+ * $NotBefore
+ * $RequestorEmail
+ * $CertType
+ * </UL>
+ *
+ * @version $Revision$, $Date$
+ */
+public class PublishCertsJob extends AJobBase
+ implements IJob, Runnable, IExtendedPluginInfo {
+
+ ICertificateAuthority mCa = null;
+ IRequestQueue mReqQ = null;
+ ICertificateRepository mRepository = null;
+ IPublisherProcessor mPublisherProcessor = null;
+ private boolean mSummary = false;
+
+ /* Holds configuration parameters accepted by this implementation.
+ * This list is passed to the configuration console so configuration
+ * for instances of this implementation can be configured through the
+ * console.
+ */
+ protected static String[] mConfigParams =
+ new String[] {
+ "enabled",
+ "cron",
+ "summary.enabled",
+ "summary.emailSubject",
+ "summary.emailTemplate",
+ "summary.itemTemplate",
+ "summary.senderEmail",
+ "summary.recipientEmail"
+ };
+
+ /* Vector of extendedPluginInfo strings */
+ protected static Vector mExtendedPluginInfo = null;
+ static {
+ mExtendedPluginInfo = new Vector();
+ };
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String s[] = {
+ IExtendedPluginInfo.HELP_TEXT +
+ "; A job that checks for valid certificates in the " +
+ "database, that have not been published and publish them to " +
+ "the publishing directory",
+ "cron;string;Format: minute hour dayOfMonth month " +
+ "dayOfWeek. Use '*' for 'every'. For dayOfWeek, 0 is Sunday",
+ "summary.senderEmail;string;Specify the address to be used " +
+ "as the email's 'sender'. Bounces go to this address.",
+ "summary.recipientEmail;string;Who should receive summaries",
+ "enabled;boolean;Enable this plugin",
+ "summary.enabled;boolean;Enable the summary. You must enabled " +
+ "this for the job to work.",
+ "summary.emailSubject;string;Subject of summary email",
+ "summary.emailTemplate;string;Fully qualified pathname of " +
+ "template file of email to be sent",
+ "summary.itemTemplate;string;Fully qualified pathname of " +
+ "file containing template for each item",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-jobrules-unpublishexpiredjobs",
+ };
+
+ return s;
+ }
+
+ /**
+ * initialize from the configuration file
+ */
+ public void init(ISubsystem owner, String id, String implName, IConfigStore config) throws
+ EBaseException {
+ mConfig = config;
+ mId = id;
+ mImplName = implName;
+
+ mCa = (ICertificateAuthority)
+ CMS.getSubsystem("ca");
+ if (mCa == null) {
+ return;
+ }
+
+ mReqQ = mCa.getRequestQueue();
+ mRepository = (ICertificateRepository) mCa.getCertificateRepository();
+ mPublisherProcessor = mCa.getPublisherProcessor();
+
+ // read from the configuration file
+ mCron = mConfig.getString(IJobCron.PROP_CRON);
+ if (mCron == null) {
+ return;
+ }
+
+ // parse cron string into a JobCron class
+ IJobsScheduler scheduler = (IJobsScheduler) owner;
+
+ mJobCron = scheduler.createJobCron(mCron);
+
+ // initialize the summary related config info
+ IConfigStore sc = mConfig.getSubStore(PROP_SUMMARY);
+
+ if (sc.getBoolean(PROP_ENABLED, false)) {
+ mSummary = true;
+ mSummaryMailSubject = sc.getString(PROP_EMAIL_SUBJECT);
+ mMailForm = sc.getString(PROP_EMAIL_TEMPLATE);
+ mItemForm = sc.getString(PROP_ITEM_TEMPLATE);
+ mSummarySenderEmail = sc.getString(PROP_SENDER_EMAIL);
+ mSummaryReceiverEmail = sc.getString(PROP_RECEIVER_EMAIL);
+ } else {
+ mSummary = false;
+ }
+ }
+
+ /**
+ * look in the internal db for certificateRecords that are
+ * valid but not published
+ * The publish() method should set <b>InLdapPublishDir</b> flag accordingly.
+ * if publish unsuccessfully, log it -- unsuccessful certs should be
+ * picked up and attempted again at the next scheduled run
+ */
+ public void run() {
+ CMS.debug("in PublishCertsJob "+
+ getId()+ " : run()");
+ // get time now..."now" is before the loop
+ Date date = CMS.getCurrentDate();
+ long now = date.getTime();
+ DateFormat dateFormat = DateFormat.getDateTimeInstance();
+ String nowString = dateFormat.format(date);
+
+ // form filter
+ String filter = // might need to use "metaInfo"
+ "(!(certMetainfo=" + ICertRecord.META_LDAPPUBLISH +
+ ":true))";
+
+ Enumeration unpublishedCerts = null;
+
+ try {
+ unpublishedCerts = mRepository.findCertRecs(filter);
+ // bug 399150
+ /*
+ CertRecordList list = null;
+ list = mRepository.findCertRecordsInList(filter, null, "serialno", 5);
+ int size = list.getSize();
+ expired = list.getCertRecords(0, size - 1);
+ */
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ }
+
+ int count = 0; // how many have been published successfully
+ int negCount = 0; // how many have NOT been published successfully
+ String contentForm = null;
+ String itemForm = null;
+ String itemListContent = null;
+
+ if (mSummary == true) {
+ contentForm = getTemplateContent(mMailForm);
+ itemForm = getTemplateContent(mItemForm);
+ }
+
+ // filter out the invalid ones and publish them
+ // publish() will set inLdapPublishDir flag
+ while (unpublishedCerts != null && unpublishedCerts.hasMoreElements()) {
+ ICertRecord rec = (ICertRecord) unpublishedCerts.nextElement();
+
+ if (rec == null) break;
+ X509CertImpl cert = rec.getCertificate();
+ Date notBefore = cert.getNotBefore();
+ Date notAfter = cert.getNotAfter();
+
+ // skip CA certs
+ if (cert.getBasicConstraintsIsCA() == true)
+ continue;
+
+ // skip the expired certs
+ if (notAfter.before(date))
+ continue;
+
+ if (mSummary == true)
+ buildItemParams(cert);
+
+ // get request id from cert record MetaInfo
+ MetaInfo minfo = null;
+
+ try {
+ minfo = (MetaInfo) rec.get(ICertRecord.ATTR_META_INFO);
+ } catch (EBaseException e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_META_INFO_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+
+ String ridString = null;
+
+ try {
+ if (minfo != null)
+ ridString = (String) minfo.get(ICertRecord.META_REQUEST_ID);
+ } catch (EBaseException e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_META_REQUEST_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ } catch (NullPointerException e) {
+ // no requestId in MetaInfo...skip to next record
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_META_REQUEST_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+
+ if (ridString != null) {
+ RequestId rid = new RequestId(ridString);
+
+ // get request from request id
+ IRequest req = null;
+
+ try {
+ req = mReqQ.findRequest(rid);
+ if (req != null) {
+ if (mSummary == true)
+ buildItemParams(req);
+ }
+ } catch (EBaseException e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_FIND_REQUEST_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+ try {
+ if ((mPublisherProcessor != null) &&
+ mPublisherProcessor.enabled()) {
+ mPublisherProcessor.publishCert((X509Certificate) cert, req);
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_SUCCESS);
+ count += 1;
+ } else {
+ negCount += 1;
+ }
+ } catch (Exception e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_PUBLISH_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+ } // ridString != null
+ else {
+ try {
+ if ((mPublisherProcessor != null) &&
+ mPublisherProcessor.enabled()) {
+ mPublisherProcessor.publishCert((X509Certificate) cert, null);
+
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_SUCCESS);
+ count += 1;
+ } else {
+ negCount += 1;
+ }
+ } catch (Exception e) {
+ negCount += 1;
+
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_PUBLISH_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+ } // ridString == null
+
+ // inLdapPublishDir flag should have been set by the
+ // publish() method
+
+ // if summary is enabled, form the item content
+ if (mSummary) {
+ IEmailFormProcessor emailItemFormProcessor =
+ CMS.getEmailFormProcessor();
+ String c = emailItemFormProcessor.getEmailContent(itemForm,
+ mItemParams);
+
+ // add item content to the item list
+ if (itemListContent == null) {
+ itemListContent = c;
+ } else {
+ itemListContent += c;
+ }
+ }
+ }
+
+ // time for summary
+ if (mSummary == true) {
+ buildContentParams(IEmailFormProcessor.TOKEN_ID,
+ mId);
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_ITEM_LIST,
+ itemListContent);
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_TOTAL_NUM,
+ String.valueOf(count + negCount));
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_SUCCESS_NUM,
+ String.valueOf(count));
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_FAILURE_NUM,
+ String.valueOf(negCount));
+ buildContentParams(IEmailFormProcessor.TOKEN_EXECUTION_TIME,
+ nowString);
+
+ IEmailFormProcessor emailFormProcessor = CMS.getEmailFormProcessor();
+ String mailContent =
+ emailFormProcessor.getEmailContent(contentForm,
+ mContentParams);
+
+ mailSummary(mailContent);
+ }
+ }
+
+ /**
+ * Returns a list of configuration parameter names.
+ * The list is passed to the configuration console so instances of
+ * this implementation can be configured through the console.
+ *
+ * @return String array of configuration parameter names.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cms/jobs/RenewalNotificationJob.java b/pki/base/common/src/com/netscape/cms/jobs/RenewalNotificationJob.java
new file mode 100644
index 000000000..03df4843d
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/jobs/RenewalNotificationJob.java
@@ -0,0 +1,718 @@
+// --- 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.jobs;
+
+
+import java.util.*;
+import java.io.*;
+import java.text.DateFormat;
+import java.security.*;
+import java.security.cert.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.notification.*;
+import com.netscape.certsrv.jobs.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+
+
+/**
+ * A job for the Jobs Scheduler. This job checks in the internal ldap
+ * db for certs about to expire within the next configurable days and
+ * sends email notifications to the appropriate recipients.
+ *
+ * the $TOKENS that are available for the this jobs's summary outer form are:<br
+ >
+ * <UL>
+ * <LI>$Status
+ * <LI>$InstanceID
+ * <LI>$SummaryItemList
+ * <LI>$SummaryTotalNum
+ * <LI>$SummaryTotalSuccess
+ * <LI>$SummaryTotalfailure
+ * <LI>$ExecutionTime
+ * </UL>
+ * and for the inner list items:
+ * <UL>
+ * <LI>$SerialNumber
+ * <LI>$IssuerDN
+ * <LI>$SubjectDN
+ * <LI>$NotAfter
+ * <LI>$NotBefore
+ * <LI>$RequestorEmail
+ * <LI>$CertType
+ * <LI>$RequestType
+ * <LI>$HttpHost
+ * <LI>$HttpPort
+ * </UL>
+ *
+ * @version $Revision$, $Date$
+ * @see com.netscape.certsrv.jobs.IJob
+ * @see com.netscape.cms.jobs.AJobBase
+ */
+public class RenewalNotificationJob
+ extends AJobBase
+ implements IJob, Runnable, IExtendedPluginInfo {
+
+ // config parameters...
+ public static final String PROP_CRON = "cron";
+
+ /**
+ * Profile ID specifies which profile approves the certificate.
+ */
+ public static final String PROP_PROFILE_ID = "profileId";
+
+ /**
+ * This job will send notification at this much time before the
+ * enpiration date
+ */
+ public static final String PROP_NOTIFYTRIGGEROFFSET =
+ "notifyTriggerOffset";
+
+ /**
+ * This job will stop sending notification this much time after
+ * the expiration date
+ */
+ public static final String PROP_NOTIFYENDOFFSET = "notifyEndOffset";
+
+ /**
+ * sender email address as appeared on the notification email
+ */
+ public static final String PROP_SENDEREMAIL =
+ "senderEmail";
+
+ /**
+ * email subject line as appeared on the notification email
+ */
+ public static final String PROP_EMAILSUBJECT =
+ "emailSubject";
+
+ /**
+ * location of the template file used for email notification
+ */
+ public static final String PROP_EMAILTEMPLATE = "emailTemplate";
+ public static final String PROP_MAXNOTIFYCOUNT = "maxNotifyCount";
+
+ /**
+ * sender email as appeared on the notification summary email
+ */
+ public static final String PROP_SUMMARY_SENDEREMAIL = "summary.senderEmail";
+
+ /**
+ * recipient of the notification summary email
+ */
+ public static final String PROP_SUMMARY_RECIPIENTEMAIL = "summary.recipientEmail";
+
+ /**
+ * email subject as appeared on the notification summary email
+ */
+ public static final String PROP_SUMMARY_SUBJECT = "summary.emailSubject";
+
+ /**
+ * location of the email template used for notification summary
+ */
+ public static final String PROP_SUMMARY_TEMPLATE = "summary.emailTemplate";
+
+ /**
+ * location of the template file for each item appeared on the
+ * notification summary
+ */
+ public static final String PROP_SUMMARY_ITEMTEMPLATE = "summary.itemTemplate";
+
+ /*
+ * Holds configuration parameters accepted by this implementation.
+ * This list is passed to the configuration console so configuration
+ * for instances of this implementation can be configured through the
+ * console.
+ */
+ protected static String[] mConfigParams =
+ new String[] {
+ "enabled",
+ PROP_CRON,
+ PROP_PROFILE_ID,
+ PROP_NOTIFYTRIGGEROFFSET,
+ PROP_NOTIFYENDOFFSET,
+ PROP_SENDEREMAIL,
+ PROP_EMAILSUBJECT,
+ PROP_EMAILTEMPLATE,
+ "summary.enabled",
+ PROP_SUMMARY_RECIPIENTEMAIL,
+ PROP_SUMMARY_SENDEREMAIL,
+ PROP_SUMMARY_SUBJECT,
+ PROP_SUMMARY_ITEMTEMPLATE,
+ PROP_SUMMARY_TEMPLATE,
+ };
+
+ protected ICertificateRepository mCertDB = null;
+ protected ICertificateAuthority mCA = null;
+ protected boolean mSummary = false;
+ protected String mEmailSender = null;
+ protected String mEmailSubject = null;
+ protected String mEmailTemplateName = null;
+ protected String mSummaryItemTemplateName = null;
+ protected String mSummaryTemplateName = null;
+ protected boolean mSummaryHTML = false;
+ protected boolean mHTML = false;
+
+ protected String mHttpHost = null;
+ protected String mHttpPort = null;
+
+ private int mPreDays = 0;
+ private long mPreMS = 0;
+ private int mPostDays = 0;
+ private long mPostMS = 0;
+ private int mMaxNotifyCount = 1;
+ private String[] mProfileId = null;
+
+ /* Vector of extendedPluginInfo strings */
+ protected static Vector mExtendedPluginInfo = null;
+
+ static {
+ mExtendedPluginInfo = new Vector();
+ };
+
+ /**
+ * class constructor
+ */
+ public RenewalNotificationJob () {
+ }
+
+ /**
+ * holds help text for this plugin
+ */
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String s[] = {
+ IExtendedPluginInfo.HELP_TEXT +
+ "; A job that checks for expiring or expired certs" +
+ "notifyTriggerOffset before and notifyEndOffset after " +
+ "the expiration date",
+
+ PROP_PROFILE_ID + ";string;Specify the ID of the profile which "+
+ "approved the certificates that are about to expire. For multiple "+
+ "profiles, each entry is separated by white space. For example, " +
+ "if the administrator just wants to give automated notification " +
+ "when the SSL server certificates are about to expire, then "+
+ "he should enter \"caServerCert caAgentServerCert\" in the profileId textfield. "+
+ "Blank field means all profiles.",
+ PROP_NOTIFYTRIGGEROFFSET + ";number,required;How long (in days) before " +
+ "certificate expiration will the first notification " +
+ "be sent",
+ PROP_NOTIFYENDOFFSET + ";number,required;How long (in days) after " +
+ "certificate expiration will notifications " +
+ "continue to be resent if certificate is not renewed",
+ PROP_CRON + ";string,required;Format: minute hour dayOfMonth Mmonth " +
+ "dayOfWeek. Use '*' for 'every'. For dayOfWeek, 0 is Sunday",
+ PROP_SENDEREMAIL + ";string,required;Specify the address to be used " +
+ "as the email's 'sender'. Bounces go to this address.",
+ PROP_EMAILSUBJECT + ";string,required;Email subject",
+ PROP_EMAILTEMPLATE + ";string,required;Fully qualified pathname of " +
+ "template file of email to be sent",
+ "enabled;boolean;Enable this plugin",
+ "summary.enabled;boolean;Enabled sending of summaries",
+ PROP_SUMMARY_SENDEREMAIL + ";string,required;Sender email address of summary",
+ PROP_SUMMARY_RECIPIENTEMAIL + ";string,required;Who should receive summaries",
+ PROP_SUMMARY_SUBJECT + ";string,required;Subject of summary email",
+ PROP_SUMMARY_TEMPLATE + ";string,required;Fully qualified pathname of " +
+ "template file of email to be sent",
+ PROP_SUMMARY_ITEMTEMPLATE + ";string,required;Fully qualified pathname of " +
+ "file with template to be used for each summary item",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-jobrules-renewalnotification",
+ };
+
+ return s;
+ }
+
+ /**
+ * Initialize from the configuration file.
+ * @param id String name of this instance
+ * @param implName string name of this implementation
+ * @param config configuration store for this instance
+ * @exception EBaseException
+ */
+ public void init(ISubsystem owner, String id, String implName, IConfigStore config) throws
+ EBaseException {
+ mConfig = config;
+ mId = id;
+ mImplName = implName;
+
+ mCA = (ICertificateAuthority)
+ CMS.getSubsystem("ca");
+ if (mCA == null) {
+ mSummary = false;
+ return;
+ }
+
+ mCertDB = (ICertificateRepository) mCA.getCertificateRepository();
+
+ mCron = mConfig.getString(IJobCron.PROP_CRON);
+ if (mCron == null) {
+ return;
+ }
+
+ // parse cron string into a JobCron class
+ IJobsScheduler scheduler = (IJobsScheduler) owner;
+
+ mJobCron = scheduler.createJobCron(mCron);
+ }
+
+ /**
+ * finds out which cert needs notification and notifies the
+ * responsible parties
+ */
+ public void run() {
+ // for forming renewal URL at template
+ mHttpHost = CMS.getEEHost();
+ mHttpPort = CMS.getEESSLPort();
+
+ // read from the configuration file
+ try {
+ mPreDays = mConfig.getInteger(PROP_NOTIFYTRIGGEROFFSET, 30); // in days
+ mPostDays = mConfig.getInteger(PROP_NOTIFYENDOFFSET, 15); // in days
+
+ mEmailSender = mConfig.getString(PROP_SENDEREMAIL);
+ mEmailSubject = mConfig.getString(PROP_EMAILSUBJECT);
+ mEmailTemplateName = mConfig.getString(PROP_EMAILTEMPLATE);
+
+ // initialize the summary related config info
+ IConfigStore sc = mConfig.getSubStore(PROP_SUMMARY);
+
+ if (sc.getBoolean(PROP_ENABLED, false)) {
+ mSummary = true;
+ mSummaryItemTemplateName =
+ mConfig.getString(PROP_SUMMARY_ITEMTEMPLATE);
+ mSummarySenderEmail =
+ mConfig.getString(PROP_SUMMARY_SENDEREMAIL);
+ mSummaryReceiverEmail =
+ mConfig.getString(PROP_SUMMARY_RECIPIENTEMAIL);
+ mSummaryMailSubject =
+ mConfig.getString(PROP_SUMMARY_SUBJECT);
+ mSummaryTemplateName =
+ mConfig.getString(PROP_SUMMARY_TEMPLATE);
+ } else {
+ mSummary = false;
+ }
+
+ long msperday = 86400 * 1000;
+ long mspredays = mPreDays;
+ long mspostdays = mPostDays;
+
+ mPreMS = mspredays * msperday;
+ mPostMS = mspostdays * msperday;
+
+ Date now = CMS.getCurrentDate();
+ DateFormat dateFormat = DateFormat.getDateTimeInstance();
+ String nowString = dateFormat.format(now);
+
+ /*
+ * look in the internal db for certificateRecords that are
+ * 1. within the expiration notification period
+ * 2. has not yet been renewed
+ * 3. notify - use EmailTemplateProcessor to formulate
+ * content, then send
+ * if notified successfully, mark "STATUS_SUCCESS",
+ * else, if notified unsuccessfully, mark "STATUS_FAILURE".
+ */
+
+ /* 1) make target notAfter string */
+
+ Date expiryDate = null;
+ Date stopDate = null;
+
+ /* 2) Assemble ldap Search filter string */
+ // date format: 19991215125306Z
+ long expiryMS = now.getTime() + mPreMS;
+ long stopMS = now.getTime() - mPostMS;
+
+ expiryDate = new Date(expiryMS);
+ stopDate = new Date(stopMS);
+
+ // All cert records which:
+ // 1) expire before the deadline
+ // 2) have not already been renewed
+ // filter format:
+ // (& (notafter<='time')(!(certAutoRenew=DONE))(!certAutoRenew=DISABLED))
+
+ StringBuffer f = new StringBuffer();
+ String profileId = "";
+ try {
+ profileId = mConfig.getString(PROP_PROFILE_ID, "");
+ } catch (EBaseException ee) {
+ }
+
+ if (profileId != null && profileId.length() > 0) {
+ StringTokenizer tokenizer = new StringTokenizer(profileId);
+ int num = tokenizer.countTokens();
+ mProfileId = new String[num];
+ for (int i=0; i<num; i++)
+ mProfileId[i] = tokenizer.nextToken();
+ }
+
+ f.append("(&");
+ if (mProfileId != null) {
+ if (mProfileId.length == 1)
+ f.append("("+ICertRecord.ATTR_META_INFO+ "=" +
+ ICertRecord.META_PROFILE_ID +":"+mProfileId[0]+")");
+ else {
+ f.append("(|");
+ for (int i=0; i<mProfileId.length; i++) {
+ f.append("("+ICertRecord.ATTR_META_INFO+ "=" +
+ ICertRecord.META_PROFILE_ID +":"+mProfileId[i]+")");
+ }
+ f.append(")");
+ }
+ }
+
+ f.append("(" + ICertRecord.ATTR_X509CERT + ".notAfter" + "<=" + expiryDate.getTime() + ")");
+ f.append("(" + ICertRecord.ATTR_X509CERT + ".notAfter" + ">=" + stopDate.getTime() + ")");
+ f.append("(!(" + ICertRecord.ATTR_AUTO_RENEW + "=" + ICertRecord.AUTO_RENEWAL_DONE + "))");
+ f.append("(!(" + ICertRecord.ATTR_AUTO_RENEW + "=" + ICertRecord.AUTO_RENEWAL_DISABLED + "))");
+ f.append("(!(" + ICertRecord.ATTR_CERT_STATUS + "=" + ICertRecord.STATUS_REVOKED + "))");
+ f.append("(!(" + ICertRecord.ATTR_CERT_STATUS + "=" + ICertRecord.STATUS_REVOKED_EXPIRED + "))");
+ f.append(")");
+ String filter = f.toString();
+
+ String emailTemplate =
+ getTemplateContent(mEmailTemplateName);
+
+ mHTML = mMailHTML;
+
+ try {
+ String summaryItemTemplate = null;
+
+ if (mSummary == true) {
+ summaryItemTemplate =
+ getTemplateContent(mSummaryItemTemplateName);
+ }
+
+ ItemCounter ic = new ItemCounter();
+ CertRecProcessor cp = new CertRecProcessor(this, emailTemplate, summaryItemTemplate, ic);
+ //CertRecordList list = mCertDB.findCertRecordsInList(filter, null, "serialno", 5);
+ //list.processCertRecords(0, list.getSize() - 1, cp);
+
+ Enumeration en = mCertDB.findCertRecs(filter);
+
+ while (en.hasMoreElements()) {
+ Object element = (Object) en.nextElement();
+
+ try {
+ cp.process(element);
+ } catch (Exception e) {
+ //Don't abort the entire operation. The error should already be logged
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("JOBS_FAILED_PROCESS", e.toString()));
+ }
+ }
+
+ // Now send the summary
+
+ if (mSummary == true) {
+ try {
+ String summaryTemplate =
+ getTemplateContent(mSummaryTemplateName);
+
+ mSummaryHTML = mMailHTML;
+
+ buildContentParams(IEmailFormProcessor.TOKEN_ID,
+ mId);
+
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_ITEM_LIST,
+ ic.mItemListContent);
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_TOTAL_NUM,
+ String.valueOf(ic.mNumFail + ic.mNumSuccessful));
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_SUCCESS_NUM,
+ String.valueOf(ic.mNumSuccessful));
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_FAILURE_NUM,
+ String.valueOf(ic.mNumFail));
+
+ buildContentParams(IEmailFormProcessor.TOKEN_EXECUTION_TIME,
+ nowString);
+
+ IEmailFormProcessor summaryEmfp = CMS.getEmailFormProcessor();
+
+ String summaryContent =
+ summaryEmfp.getEmailContent(summaryTemplate,
+ mContentParams);
+
+ if (summaryContent == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("JOBS_SUMMARY_CONTENT_NULL"));
+ mailSummary(" no summaryContent");
+ } else {
+ mMailHTML = mSummaryHTML;
+ mailSummary(summaryContent);
+ }
+ } catch (Exception e) {
+ // log error
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("JOBS_EXCEPTION_IN_RUN", e.toString()));
+ }
+ }
+ } catch (EBaseException e) {
+ // log error
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ }
+ } catch (EBaseException ex) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("Configuration error:", ex.toString()));
+ }
+ }
+
+ private String makeLDAPDateString(Date d) {
+
+ String ldfYear = "" + Integer.toString(d.getYear());
+
+ String ldfMonth = getPadded(d.getMonth());
+ String ldfDate = getPadded(d.getDate());
+ String ldfHours = getPadded(d.getHours());
+ String ldfMinutes = getPadded(d.getMinutes());
+ String ldfSeconds = getPadded(d.getSeconds());
+
+ return ldfYear + ldfMonth + ldfDate + ldfHours + ldfMinutes + ldfSeconds + "Z";
+ }
+
+ private String getPadded(int i) {
+ if (i < 10) {
+ return "0" + Integer.toString(i);
+ } else {
+ return "" + Integer.toString(i);
+ }
+ }
+
+ /**
+ * get instance id.
+ * @return a String identifier
+ */
+ public String getId() {
+ return mId;
+ }
+
+ /**
+ * set instance id.
+ * @param id String id of the instance
+ */
+ public void setId(String id) {
+ mId = id;
+ }
+
+ /**
+ * get cron string associated with this job
+ * @return a JobCron object that represents the schedule of this job
+ */
+ public IJobCron getJobCron() {
+ return mJobCron;
+ }
+
+ /**
+ * gets the plugin name of this job.
+ * @return a String that is the name of this implementation
+ */
+ public String getImplName() {
+ return mImplName;
+ }
+
+ /**
+ * Gets the configuration substore used by this job
+ * @return configuration store
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ protected void mailUser(String subject,
+ String msg,
+ String sender,
+ IRequest req,
+ ICertRecord cr)
+ throws IOException, ENotificationException, EBaseException {
+
+ IMailNotification mn = CMS.getMailNotification();
+
+ String rcp = null;
+ // boolean sendFailed = false;
+ Exception sendFailedException = null;
+
+ IEmailResolverKeys keys = CMS.getEmailResolverKeys();
+
+ try {
+ if (req != null) {
+ keys.set(IEmailResolverKeys.KEY_REQUEST, req);
+ }
+ if (cr != null) {
+ Object c = cr.getCertificate();
+
+ if (c != null) {
+ keys.set(IEmailResolverKeys.KEY_CERT, cr.getCertificate());
+ }
+ }
+
+ IEmailResolver er = CMS.getReqCertSANameEmailResolver();
+
+ rcp = er.getEmail(keys);
+
+ } catch (Exception e) {
+ // already logged by the resolver
+ // sendFailed = true;
+ sendFailedException = e;
+ throw (ENotificationException) sendFailedException;
+ }
+
+ mn.setTo(rcp);
+
+ if (sender != null) mn.setFrom(sender);
+ else mn.setFrom("nobody");
+
+ if (subject != null) mn.setSubject(subject);
+ else mn.setFrom("Important message from Certificate Authority");
+
+ if (mHTML == true) mn.setContentType("text/html");
+
+ String failedString = null;
+
+ mn.setContent(msg);
+
+ mn.sendNotification();
+ }
+
+ /**
+ * Returns a list of configuration parameter names.
+ * The list is passed to the configuration console so instances of
+ * this implementation can be configured through the console.
+ *
+ * @return String array of configuration parameter names.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+}
+
+
+class CertRecProcessor implements IElementProcessor {
+ protected RenewalNotificationJob mJob;
+ protected String mEmailTemplate;
+ protected String mSummaryItemTemplate;
+ protected ItemCounter mIC;
+
+ public CertRecProcessor(RenewalNotificationJob job, String emailTemplate,
+ String summaryItemTemplate, ItemCounter ic) {
+ mJob = job;
+ mEmailTemplate = emailTemplate;
+ mSummaryItemTemplate = summaryItemTemplate;
+ mIC = ic;
+ }
+
+ public void process(Object o) throws EBaseException {
+
+ // Get each certRecord
+ ICertRecord cr = (ICertRecord) o;
+
+ String ridString = null;
+ boolean numFailCounted = false;
+
+ if (cr != null) {
+ mJob.buildItemParams(cr.getCertificate());
+ mJob.buildItemParams(IEmailFormProcessor.TOKEN_HTTP_HOST,
+ mJob.mHttpHost);
+ mJob.buildItemParams(IEmailFormProcessor.TOKEN_HTTP_PORT, mJob.mHttpPort);
+
+ MetaInfo metaInfo = null;
+
+ metaInfo = (MetaInfo) cr.get(ICertRecord.ATTR_META_INFO);
+ if (metaInfo == null) {
+ mIC.mNumFail++;
+ numFailCounted = true;
+ if (mJob.mSummary == true)
+ mJob.buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ mJob.STATUS_FAILURE);
+ mJob.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_GET_CERT_ERROR",
+ cr.getCertificate().getSerialNumber().toString(16)));
+ } else {
+ ridString = (String) metaInfo.get(ICertRecord.META_REQUEST_ID);
+ }
+ }
+
+ IRequest req = null;
+
+ if (ridString != null) {
+ RequestId rid = new RequestId(ridString);
+
+ try {
+ req = mJob.mCA.getRequestQueue().findRequest(rid);
+ } catch (Exception e) {
+ // it is ok not to be able to get the request. The main reason
+ // to get the request is to retrieve the requestor's email.
+ // We can retrieve the email from the CertRecord.
+ CMS.debug("huh RenewalNotificationJob Exception: "+e.toString());
+ }
+
+ if (req != null)
+ mJob.buildItemParams(req);
+ } // ridString != null
+
+ try {
+ // send mail to user
+
+ IEmailFormProcessor emfp = CMS.getEmailFormProcessor();
+ String message = emfp.getEmailContent(mEmailTemplate,
+ mJob.mItemParams);
+
+ mJob.mailUser(mJob.mEmailSubject,
+ message,
+ mJob.mEmailSender,
+ req,
+ cr);
+
+ mJob.buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ mJob.STATUS_SUCCESS);
+
+ mIC.mNumSuccessful++;
+
+ } catch (Exception e) {
+ CMS.debug("RenewalNotificationJob Exception: "+e.toString());
+ mJob.buildItemParams(IEmailFormProcessor.TOKEN_STATUS, mJob.STATUS_FAILURE);
+ mJob.log(ILogger.LL_FAILURE, e.toString(), ILogger.L_MULTILINE);
+ if (numFailCounted == false) {
+ mIC.mNumFail++;
+ }
+ }
+
+ if (mJob.mSummary == true) {
+ IEmailFormProcessor summaryItemEmfp =
+ CMS.getEmailFormProcessor();
+ String c =
+ summaryItemEmfp.getEmailContent(mSummaryItemTemplate,
+ mJob.mItemParams);
+
+ if (mIC.mItemListContent == null) {
+ mIC.mItemListContent = c;
+ } else {
+ mIC.mItemListContent += c;
+ }
+ }
+ }
+}
+
+
+class ItemCounter {
+ public int mNumSuccessful = 0;
+ public int mNumFail = 0;
+ public String mItemListContent = null;
+}
diff --git a/pki/base/common/src/com/netscape/cms/jobs/RequestInQueueJob.java b/pki/base/common/src/com/netscape/cms/jobs/RequestInQueueJob.java
new file mode 100644
index 000000000..88a8bf35d
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/jobs/RequestInQueueJob.java
@@ -0,0 +1,219 @@
+// --- 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.jobs;
+
+
+import java.util.*;
+import java.io.*;
+import java.text.DateFormat;
+import java.security.*;
+import java.security.cert.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.notification.*;
+import com.netscape.certsrv.jobs.*;
+import com.netscape.certsrv.authority.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.ldap.*;
+
+
+/**
+ * A job for the Jobs Scheduler. This job checks in the internal ldap
+ * db for requests currently in the request queue and send a summary
+ * report to the administrator
+ * <p>
+ * the $TOKENS that are available for the this jobs's summary outer form are:<br>
+ * <UL>
+ * $InstanceID
+ * $SummaryTotalNum
+ * $ExecutionTime
+ * </UL>
+ *
+ * @version $Revision$, $Date$
+ * @see com.netscape.certsrv.jobs.IJob
+ * @see com.netscape.cms.jobs.AJobBase
+ */
+public class RequestInQueueJob extends AJobBase
+ implements IJob, Runnable, IExtendedPluginInfo {
+ protected static final String PROP_SUBSYSTEM_ID = "subsystemId";
+
+ IAuthority mSub = null;
+ IRequestQueue mReqQ = null;
+ private boolean mSummary = false;
+
+ /* Holds configuration parameters accepted by this implementation.
+ * This list is passed to the configuration console so configuration
+ * for instances of this implementation can be configured through the
+ * console.
+ */
+ protected static String[] mConfigParams =
+ new String[] {
+ "enabled",
+ "cron",
+ "subsystemId",
+ "summary.enabled",
+ "summary.emailSubject",
+ "summary.emailTemplate",
+ "summary.senderEmail",
+ "summary.recipientEmail"
+ };
+
+ /**
+ * holds help text for this plugin
+ */
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String s[] = {
+ IExtendedPluginInfo.HELP_TEXT +
+ "; A job that checks for enrollment requests in the " +
+ "queue, and reports to recipientEmail",
+ "cron;string;Format: minute hour dayOfMonth month " +
+ "dayOfWeek. Use '*' for 'every'. For dayOfWeek, 0 is Sunday",
+ "summary.senderEmail;string;Specify the address to be used " +
+ "as the email's 'sender'. Bounces go to this address.",
+ "summary.recipientEmail;string;Who should receive summaries",
+ "enabled;boolean;Enable this plugin",
+ "summary.enabled;boolean;Enable the summary. You must enabled " +
+ "this for the job to work.",
+ "summary.emailSubject;string;Subject of summary email",
+ "summary.emailTemplate;string;Fully qualified pathname of " +
+ "template file of email to be sent",
+ "subsystemId;choice(ca,ra);The type of subsystem this job is " +
+ "for",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-jobrules-requestinqueuejob",
+ };
+
+ return s;
+ }
+
+ /**
+ * initialize from the configuration file
+ * @param id String name of this instance
+ * @param implName string name of this implementation
+ * @param config configuration store for this instance
+ * @exception EBaseException
+ */
+ public void init(ISubsystem owner, String id, String implName, IConfigStore config) throws
+ EBaseException {
+ mConfig = config;
+ mId = id;
+ mImplName = implName;
+
+ // read from the configuration file
+ String sub = mConfig.getString(PROP_SUBSYSTEM_ID);
+
+ mSub = (IAuthority)
+ CMS.getSubsystem(sub);
+ if (mSub == null) {
+ // take this as disable
+ mSummary = false;
+ return;
+ }
+
+ mReqQ = mSub.getRequestQueue();
+
+ mCron = mConfig.getString(IJobCron.PROP_CRON);
+ if (mCron == null) {
+ return;
+ }
+
+ // parse cron string into a JobCron class
+ IJobsScheduler scheduler = (IJobsScheduler) owner;
+
+ mJobCron = scheduler.createJobCron(mCron);
+
+ // initialize the summary related config info
+ IConfigStore sc = mConfig.getSubStore(PROP_SUMMARY);
+
+ if (sc.getBoolean(PROP_ENABLED, false)) {
+ mSummary = true;
+ mSummaryMailSubject = sc.getString(PROP_EMAIL_SUBJECT);
+ mMailForm = sc.getString(PROP_EMAIL_TEMPLATE);
+ // mItemForm = sc.getString(PROP_ITEM_TEMPLATE);
+ mSummarySenderEmail = sc.getString(PROP_SENDER_EMAIL);
+ mSummaryReceiverEmail = sc.getString(PROP_RECEIVER_EMAIL);
+ } else {
+ mSummary = false;
+ }
+ }
+
+ /**
+ * summarize the queue status and mail it
+ */
+ public void run() {
+ if (mSummary == false) return;
+
+ Date date = CMS.getCurrentDate();
+ long now = date.getTime();
+ DateFormat dateFormat = DateFormat.getDateTimeInstance();
+ String nowString = dateFormat.format(date);
+
+ int count = 0;
+ IRequestList list =
+ mReqQ.listRequestsByStatus(RequestStatus.PENDING);
+
+ while (list != null && list.hasMoreElements()) {
+ RequestId rid = list.nextRequestId();
+
+ /* This is way too slow
+ // get request from request id
+ IRequest req = null;
+ try {
+ req = mReqQ.findRequest(rid);
+ } catch (EBaseException e) {
+ System.out.println(e.toString());
+ }
+ */
+ count++;
+ }
+
+ // if (count == 0) return;
+
+ String contentForm = null;
+
+ contentForm = getTemplateContent(mMailForm);
+
+ buildContentParams(IEmailFormProcessor.TOKEN_ID, mId);
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_TOTAL_NUM,
+ String.valueOf(count));
+ buildContentParams(IEmailFormProcessor.TOKEN_EXECUTION_TIME,
+ nowString);
+
+ IEmailFormProcessor emailFormProcessor = CMS.getEmailFormProcessor();
+ String mailContent =
+ emailFormProcessor.getEmailContent(contentForm,
+ mContentParams);
+
+ mailSummary(mailContent);
+ }
+
+ /**
+ * Returns a list of configuration parameter names.
+ * The list is passed to the configuration console so instances of
+ * this implementation can be configured through the console.
+ *
+ * @return String array of configuration parameter names.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cms/jobs/UnpublishExpiredJob.java b/pki/base/common/src/com/netscape/cms/jobs/UnpublishExpiredJob.java
new file mode 100644
index 000000000..1813bd639
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/jobs/UnpublishExpiredJob.java
@@ -0,0 +1,395 @@
+// --- 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.jobs;
+
+
+import java.util.*;
+import java.io.*;
+import java.text.DateFormat;
+import java.security.*;
+import java.security.cert.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.notification.*;
+import com.netscape.certsrv.jobs.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.publish.*;
+
+
+/**
+ * a job for the Jobs Scheduler. This job checks in the internal ldap
+ * db for certs that have expired and remove them from the ldap
+ * publishing directory.
+ * <p>
+ * the $TOKENS that are available for the this jobs's summary outer form are:<br>
+ * <UL>
+ * $Status
+ * $InstanceID
+ * $SummaryItemList
+ * $SummaryTotalNum
+ * $SummaryTotalSuccess
+ * $SummaryTotalfailure
+ * $ExecutionTime
+ * </UL>
+ * and for the inner list items:
+ * <UL>
+ * $SerialNumber
+ * $IssuerDN
+ * $SubjectDN
+ * $NotAfter
+ * $NotBefore
+ * $RequestorEmail
+ * $CertType
+ * </UL>
+ *
+ * @version $Revision$, $Date$
+ */
+public class UnpublishExpiredJob extends AJobBase
+ implements IJob, Runnable, IExtendedPluginInfo {
+
+ ICertificateAuthority mCa = null;
+ IRequestQueue mReqQ = null;
+ ICertificateRepository mRepository = null;
+ IPublisherProcessor mPublisherProcessor = null;
+ private boolean mSummary = false;
+
+ /* Holds configuration parameters accepted by this implementation.
+ * This list is passed to the configuration console so configuration
+ * for instances of this implementation can be configured through the
+ * console.
+ */
+ protected static String[] mConfigParams =
+ new String[] {
+ "enabled",
+ "cron",
+ "summary.enabled",
+ "summary.emailSubject",
+ "summary.emailTemplate",
+ "summary.itemTemplate",
+ "summary.senderEmail",
+ "summary.recipientEmail"
+ };
+
+ /* Vector of extendedPluginInfo strings */
+ protected static Vector mExtendedPluginInfo = null;
+ static {
+ mExtendedPluginInfo = new Vector();
+ };
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String s[] = {
+ IExtendedPluginInfo.HELP_TEXT +
+ "; A job that checks for expired certificates in the " +
+ "database, and removes them from the publishing " +
+ "directory",
+ "cron;string;Format: minute hour dayOfMonth month " +
+ "dayOfWeek. Use '*' for 'every'. For dayOfWeek, 0 is Sunday",
+ "summary.senderEmail;string;Specify the address to be used " +
+ "as the email's 'sender'. Bounces go to this address.",
+ "summary.recipientEmail;string;Who should receive summaries",
+ "enabled;boolean;Enable this plugin",
+ "summary.enabled;boolean;Enable the summary. You must enabled " +
+ "this for the job to work.",
+ "summary.emailSubject;string;Subject of summary email",
+ "summary.emailTemplate;string;Fully qualified pathname of " +
+ "template file of email to be sent",
+ "summary.itemTemplate;string;Fully qualified pathname of " +
+ "file containing template for each item",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-jobrules-unpublishexpiredjobs",
+ };
+
+ return s;
+ }
+
+ /**
+ * initialize from the configuration file
+ */
+ public void init(ISubsystem owner, String id, String implName, IConfigStore config) throws
+ EBaseException {
+ mConfig = config;
+ mId = id;
+ mImplName = implName;
+
+ mCa = (ICertificateAuthority)
+ CMS.getSubsystem("ca");
+ if (mCa == null) {
+ return;
+ }
+
+ mReqQ = mCa.getRequestQueue();
+ mRepository = (ICertificateRepository) mCa.getCertificateRepository();
+ mPublisherProcessor = mCa.getPublisherProcessor();
+
+ // read from the configuration file
+ mCron = mConfig.getString(IJobCron.PROP_CRON);
+ if (mCron == null) {
+ return;
+ }
+
+ // parse cron string into a JobCron class
+ IJobsScheduler scheduler = (IJobsScheduler) owner;
+
+ mJobCron = scheduler.createJobCron(mCron);
+
+ // initialize the summary related config info
+ IConfigStore sc = mConfig.getSubStore(PROP_SUMMARY);
+
+ if (sc.getBoolean(PROP_ENABLED, false)) {
+ mSummary = true;
+ mSummaryMailSubject = sc.getString(PROP_EMAIL_SUBJECT);
+ mMailForm = sc.getString(PROP_EMAIL_TEMPLATE);
+ mItemForm = sc.getString(PROP_ITEM_TEMPLATE);
+ mSummarySenderEmail = sc.getString(PROP_SENDER_EMAIL);
+ mSummaryReceiverEmail = sc.getString(PROP_RECEIVER_EMAIL);
+ } else {
+ mSummary = false;
+ }
+ }
+
+ /**
+ * look in the internal db for certificateRecords that are
+ * expired.
+ * remove them from ldap publishing directory
+ * if remove successfully, mark <i>false</i> on the
+ * <b>InLdapPublishDir</b> flag,
+ * else, if remove unsuccessfully, log it
+ */
+ public void run() {
+ // System.out.println("in ExpiredUnpublishJob "+
+ // getId()+ " : run()");
+ // get time now..."now" is before the loop
+ Date date = CMS.getCurrentDate();
+ long now = date.getTime();
+ DateFormat dateFormat = DateFormat.getDateTimeInstance();
+ String nowString = dateFormat.format(date);
+
+ // form filter
+ String filter = "(&(x509Cert.notAfter<=" + now +
+ ")(!(x509Cert.notAfter=" + now + "))" +
+ "(" + "certMetainfo=" + ICertRecord.META_LDAPPUBLISH +
+ ":true))";
+ // a test for without CertRecord.META_LDAPPUBLISH
+ //String filter = "(x509Cert.notAfter<="+ now +")";
+
+ Enumeration expired = null;
+
+ try {
+ expired = mRepository.findCertRecs(filter);
+ // bug 399150
+ /*
+ CertRecordList list = null;
+ list = mRepository.findCertRecordsInList(filter, null, "serialno", 5);
+ int size = list.getSize();
+ expired = list.getCertRecords(0, size - 1);
+ */
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ }
+
+ int count = 0; // how many have been unpublished successfully
+ int negCount = 0; // how many have NOT been unpublished successfully
+ String contentForm = null;
+ String itemForm = null;
+ String itemListContent = null;
+
+ if (mSummary == true) {
+ contentForm = getTemplateContent(mMailForm);
+ itemForm = getTemplateContent(mItemForm);
+ }
+
+ // unpublish them and unpublish() will set inLdapPublishDir flag
+ while (expired != null && expired.hasMoreElements()) {
+ ICertRecord rec = (ICertRecord) expired.nextElement();
+
+ if (rec == null) break;
+ X509CertImpl cert = rec.getCertificate();
+
+ if (mSummary == true)
+ buildItemParams(cert);
+
+ // get request id from cert record MetaInfo
+ MetaInfo minfo = null;
+
+ try {
+ minfo = (MetaInfo) rec.get(ICertRecord.ATTR_META_INFO);
+ } catch (EBaseException e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_META_INFO_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+
+ String ridString = null;
+
+ try {
+ if (minfo != null)
+ ridString = (String) minfo.get(ICertRecord.META_REQUEST_ID);
+ } catch (EBaseException e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_META_REQUEST_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ } catch (NullPointerException e) {
+ // no requestId in MetaInfo...skip to next record
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_META_REQUEST_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+
+ if (ridString != null) {
+ RequestId rid = new RequestId(ridString);
+
+ // get request from request id
+ IRequest req = null;
+
+ try {
+ req = mReqQ.findRequest(rid);
+ if (req != null) {
+ if (mSummary == true)
+ buildItemParams(req);
+ }
+ } catch (EBaseException e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_FIND_REQUEST_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+ try {
+ if ((mPublisherProcessor != null) &&
+ mPublisherProcessor.enabled()) {
+ mPublisherProcessor.unpublishCert((X509Certificate) cert, req);
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_SUCCESS);
+ count += 1;
+ } else {
+ negCount += 1;
+ }
+ } catch (Exception e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_UNPUBLISH_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+ } // ridString != null
+ else {
+ try {
+ if ((mPublisherProcessor != null) &&
+ mPublisherProcessor.enabled()) {
+ mPublisherProcessor.unpublishCert((X509Certificate) cert, null);
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_SUCCESS);
+ count += 1;
+ } else {
+ negCount += 1;
+ }
+ } catch (Exception e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_UNPUBLISH_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+ } // ridString == null
+
+ // inLdapPublishDir flag should have been set by the
+ // unpublish() method
+
+ // if summary is enabled, form the item content
+ if (mSummary) {
+ IEmailFormProcessor emailItemFormProcessor =
+ CMS.getEmailFormProcessor();
+ String c = emailItemFormProcessor.getEmailContent(itemForm,
+ mItemParams);
+
+ // add item content to the item list
+ if (itemListContent == null) {
+ itemListContent = c;
+ } else {
+ itemListContent += c;
+ }
+ }
+ }
+
+ // time for summary
+ if (mSummary == true) {
+ buildContentParams(IEmailFormProcessor.TOKEN_ID,
+ mId);
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_ITEM_LIST,
+ itemListContent);
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_TOTAL_NUM,
+ String.valueOf(count + negCount));
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_SUCCESS_NUM,
+ String.valueOf(count));
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_FAILURE_NUM,
+ String.valueOf(negCount));
+ buildContentParams(IEmailFormProcessor.TOKEN_EXECUTION_TIME,
+ nowString);
+
+ IEmailFormProcessor emailFormProcessor = CMS.getEmailFormProcessor();
+ String mailContent =
+ emailFormProcessor.getEmailContent(contentForm,
+ mContentParams);
+
+ mailSummary(mailContent);
+ }
+ }
+
+ /**
+ * Returns a list of configuration parameter names.
+ * The list is passed to the configuration console so instances of
+ * this implementation can be configured through the console.
+ *
+ * @return String array of configuration parameter names.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+}
+