// --- 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.listeners;
import java.io.File;
import java.io.IOException;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.util.Date;
import java.util.Hashtable;
import netscape.security.x509.RevokedCertImpl;
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.authority.ICertAuthority;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.EPropertyNotFound;
import com.netscape.certsrv.base.IConfigStore;
import com.netscape.certsrv.base.ISubsystem;
import com.netscape.certsrv.ca.ICertificateAuthority;
import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
import com.netscape.certsrv.listeners.EListenersException;
import com.netscape.certsrv.logging.ILogger;
import com.netscape.certsrv.notification.ENotificationException;
import com.netscape.certsrv.notification.IEmailFormProcessor;
import com.netscape.certsrv.notification.IEmailResolver;
import com.netscape.certsrv.notification.IEmailResolverKeys;
import com.netscape.certsrv.notification.IEmailTemplate;
import com.netscape.certsrv.notification.IMailNotification;
import com.netscape.certsrv.request.IRequest;
import com.netscape.certsrv.request.IRequestListener;
import com.netscape.certsrv.request.RequestId;
/**
* a listener for every completed enrollment request
*
* Here is a list of available $TOKENs for email notification templates if certificate is successfully issued:
*
* - $InstanceID
*
- $SerialNumber
*
- $HexSerialNumber
*
- $HttpHost
*
- $HttpPort
*
- $RequestId
*
- $IssuerDN
*
- $SubjectDN
*
- $NotBefore
*
- $NotAfter
*
- $SenderEmail
*
- $RecipientEmail
*
*
* Here is a list of available $TOKENs for email notification templates if certificate request is revoked:
*
* - $RequestId
*
- $InstanceID
*
*
* @version $Revision$, $Date$
*/
public class CertificateRevokedListener implements IRequestListener {
protected final static String PROP_CERT_ISSUED_SUBSTORE = "certRevoked";
protected static final String PROP_ENABLED = "enabled";
protected final static String PROP_NOTIFY_SUBSTORE = "notification";
protected final static String PROP_SENDER_EMAIL = "senderEmail";
protected final static String PROP_EMAIL_SUBJECT = "emailSubject";
public final static String PROP_EMAIL_TEMPLATE = "emailTemplate";
protected final static String REJECT_FILE_NAME = "certRequestRejected";
private boolean mEnabled = false;
private ILogger mLogger = CMS.getLogger();
private String mSenderEmail = null;
private String mSubject = null;
private String mSubject_Success = null;
private String mFormPath = null;
private String mRejectPath = null;
private Hashtable mContentParams = new Hashtable();
private IConfigStore mConfig = null;
private DateFormat mDateFormat = null;
private ICertAuthority mSubsystem = null;
private String mHttpHost = null;
private String mHttpPort = null;
private RequestId mReqId = null;
public CertificateRevokedListener() {
}
public void init(ISubsystem sub, IConfigStore config)
throws EListenersException, EPropertyNotFound, EBaseException {
mSubsystem = (ICertAuthority) sub;
mConfig = mSubsystem.getConfigStore();
IConfigStore nc = mConfig.getSubStore(PROP_NOTIFY_SUBSTORE);
IConfigStore rc = nc.getSubStore(PROP_CERT_ISSUED_SUBSTORE);
mEnabled = rc.getBoolean(PROP_ENABLED, false);
mSenderEmail = rc.getString(PROP_SENDER_EMAIL);
if (mSenderEmail == null) {
throw new EListenersException(CMS.getLogMessage("NO_NOTIFY_SENDER_EMAIL_CONFIG_FOUND"));
}
mFormPath = rc.getString(PROP_EMAIL_TEMPLATE);
String mDir = null;
// figure out the reject email path: same dir as form path,
// same ending as form path
int ridx = mFormPath.lastIndexOf(File.separator);
if (ridx == -1) {
CMS.debug("CertificateRevokedListener: file separator: " + File.separator
+
" not found. Use default /");
ridx = mFormPath.lastIndexOf("/");
mDir = mFormPath.substring(0, ridx + 1);
} else {
mDir = mFormPath.substring(0, ridx +
File.separator.length());
}
CMS.debug("CertificateRevokedListener: template file directory: " + mDir);
mRejectPath = mDir + REJECT_FILE_NAME;
if (mFormPath.endsWith(".html"))
mRejectPath += ".html";
else if (mFormPath.endsWith(".HTML"))
mRejectPath += ".HTML";
else if (mFormPath.endsWith(".htm"))
mRejectPath += ".htm";
else if (mFormPath.endsWith(".HTM"))
mRejectPath += ".HTM";
CMS.debug("CertificateRevokedListener: Reject file path: " + mRejectPath);
mDateFormat = DateFormat.getDateTimeInstance();
mSubject_Success = rc.getString(PROP_EMAIL_SUBJECT,
"Your Certificate Request");
mSubject = new String(mSubject_Success);
// form the cert retrieval URL for the notification
mHttpHost = CMS.getEEHost();
mHttpPort = CMS.getEESSLPort();
// register for this event listener
mSubsystem.registerRequestListener(this);
}
public void accept(IRequest r) {
if (mEnabled != true)
return;
mSubject = mSubject_Success;
mReqId = r.getRequestId();
// is it revoked?
String rs = r.getRequestStatus().toString();
String requestType = r.getRequestType();
if (requestType.equals(IRequest.REVOCATION_REQUEST) == false)
return;
if (rs.equals("complete") == false) {
CMS.debug("CertificateRevokedListener: Request status: " + rs);
//revoked(r);
return;
}
// check if request failed.
if (r.getExtDataInInteger(IRequest.RESULT) == null)
return;
if ((r.getExtDataInInteger(IRequest.RESULT)).equals(IRequest.RES_ERROR)) {
CMS.debug("CertificateRevokedListener: Request errored. " +
"No need to email notify for enrollment request id " +
mReqId);
return;
}
if (requestType.equals(IRequest.REVOCATION_REQUEST)) {
CMS.debug("CertificateRevokedListener: accept() revocation request...");
// Get the certificate from the request
//X509CertImpl issuedCert[] =
// (X509CertImpl[])
RevokedCertImpl crlentries[] =
r.getExtDataInRevokedCertArray(IRequest.CERT_INFO);
if (crlentries != null) {
CMS.debug("CertificateRevokedListener: Sending email notification..");
// do we have an email to send?
String mEmail = null;
IEmailResolverKeys keys = CMS.getEmailResolverKeys();
try {
keys.set(IEmailResolverKeys.KEY_REQUEST, r);
keys.set(IEmailResolverKeys.KEY_CERT,
crlentries[0]);
} catch (EBaseException e) {
log(ILogger.LL_FAILURE,
CMS.getLogMessage("LISTENERS_CERT_ISSUED_SET_RESOLVER", e.toString()));
}
IEmailResolver er = CMS.getReqCertSANameEmailResolver();
try {
mEmail = er.getEmail(keys);
} catch (ENotificationException e) {
log(ILogger.LL_FAILURE,
CMS.getLogMessage("LISTENERS_CERT_ISSUED_EXCEPTION",
e.toString()));
} catch (EBaseException e) {
log(ILogger.LL_FAILURE,
CMS.getLogMessage("LISTENERS_CERT_ISSUED_EXCEPTION",
e.toString()));
} catch (Exception e) {
log(ILogger.LL_FAILURE,
CMS.getLogMessage("LISTENERS_CERT_ISSUED_EXCEPTION",
e.toString()));
}
// now we can mail
if ((mEmail != null) && (!mEmail.equals(""))) {
mailIt(mEmail, crlentries);
} else {
log(ILogger.LL_FAILURE,
CMS.getLogMessage("LISTENERS_CERT_ISSUED_NOTIFY_ERROR",
crlentries[0].getSerialNumber().toString(), mReqId.toString()));
// send failure notification to "sender"
mSubject = "Certificate Issued notification undeliverable";
mailIt(mSenderEmail, crlentries);
}
}
}
}
private void mailIt(String mEmail, RevokedCertImpl crlentries[]) {
IMailNotification mn = CMS.getMailNotification();
mn.setFrom(mSenderEmail);
mn.setTo(mEmail);
mn.setSubject(mSubject);
/*
* get template file from disk
*/
IEmailTemplate template = CMS.getEmailTemplate(mFormPath);
/*
* parse and process the template
*/
if (template != null) {
if (!template.init()) {
return;
}
buildContentParams(crlentries, mEmail);
IEmailFormProcessor et = CMS.getEmailFormProcessor();
String c = et.getEmailContent(template.toString(), mContentParams);
if (template.isHTML()) {
mn.setContentType("text/html");
}
mn.setContent(c);
} else {
log(ILogger.LL_FAILURE,
CMS.getLogMessage("LISTENERS_CERT_ISSUED_TEMPLATE_ERROR",
crlentries[0].getSerialNumber().toString(), mReqId.toString()));
mn.setContent("Serial Number = " +
crlentries[0].getSerialNumber() +
"; Request ID = " + mReqId);
}
try {
mn.sendNotification();
} catch (ENotificationException e) {
log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
} catch (IOException e) {
log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
}
}
private void buildContentParams(RevokedCertImpl crlentries[], String mEmail) {
mContentParams.put(IEmailFormProcessor.TOKEN_ID,
mConfig.getName());
mContentParams.put(IEmailFormProcessor.TOKEN_SERIAL_NUM,
crlentries[0].getSerialNumber().toString());
mContentParams.put(IEmailFormProcessor.TOKEN_HEX_SERIAL_NUM,
Long.toHexString(crlentries[0].getSerialNumber().longValue()));
mContentParams.put(IEmailFormProcessor.TOKEN_REQUEST_ID,
mReqId.toString());
mContentParams.put(IEmailFormProcessor.TOKEN_HTTP_HOST,
mHttpHost);
mContentParams.put(IEmailFormProcessor.TOKEN_HTTP_PORT,
mHttpPort);
try {
RevokedCertImpl revCert = crlentries[0];
ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA);
ICertificateRepository certDB = ca.getCertificateRepository();
X509Certificate cert = certDB.getX509Certificate(revCert.getSerialNumber());
mContentParams.put(IEmailFormProcessor.TOKEN_ISSUER_DN,
cert.getIssuerDN().toString());
mContentParams.put(IEmailFormProcessor.TOKEN_SUBJECT_DN,
cert.getSubjectDN().toString());
Date date = crlentries[0].getRevocationDate();
mContentParams.put(IEmailFormProcessor.TOKEN_REVOCATION_DATE,
mDateFormat.format(date));
} catch (EBaseException e) {
log(ILogger.LL_FAILURE,
CMS.getLogMessage("LISTENERS_CERT_ISSUED_SET_RESOLVER", e.toString()));
}
mContentParams.put(IEmailFormProcessor.TOKEN_SENDER_EMAIL,
mSenderEmail);
mContentParams.put(IEmailFormProcessor.TOKEN_RECIPIENT_EMAIL,
mEmail);
// ... and more
}
/**
* sets the configurable parameters
*/
public void set(String name, String val) {
if (name.equalsIgnoreCase(PROP_ENABLED)) {
if (val.equalsIgnoreCase("true")) {
mEnabled = true;
} else {
mEnabled = false;
}
} else if (name.equalsIgnoreCase(PROP_SENDER_EMAIL)) {
mSenderEmail = val;
} else if (name.equalsIgnoreCase(PROP_EMAIL_SUBJECT)) {
mSubject_Success = val;
mSubject = mSubject_Success;
} else if (name.equalsIgnoreCase(PROP_EMAIL_TEMPLATE)) {
mFormPath = val;
} else {
log(ILogger.LL_FAILURE, CMS.getLogMessage("LISTENERS_CERT_ISSUED_SET"));
}
}
private void log(int level, String msg) {
if (mLogger == null)
return;
mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER,
level, msg);
}
}