summaryrefslogtreecommitdiffstats
path: root/pki/base/common/src/com/netscape/cms/servlet/connector/ConnectorServlet.java
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/common/src/com/netscape/cms/servlet/connector/ConnectorServlet.java')
-rw-r--r--pki/base/common/src/com/netscape/cms/servlet/connector/ConnectorServlet.java1092
1 files changed, 1092 insertions, 0 deletions
diff --git a/pki/base/common/src/com/netscape/cms/servlet/connector/ConnectorServlet.java b/pki/base/common/src/com/netscape/cms/servlet/connector/ConnectorServlet.java
new file mode 100644
index 000000000..daf595f81
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/servlet/connector/ConnectorServlet.java
@@ -0,0 +1,1092 @@
+// --- 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.servlet.connector;
+
+import com.netscape.cms.servlet.common.*;
+import com.netscape.cms.servlet.base.*;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+import netscape.security.x509.*;
+//import java.security.*;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import java.io.*;
+import java.util.*;
+
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.authority.*;
+import com.netscape.certsrv.connector.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.profile.*;
+
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.authentication.*;
+import com.netscape.certsrv.authorization.*;
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * Connector servlet
+ * process requests from remote authority -
+ * service request or return status.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ConnectorServlet extends CMSServlet {
+ public static final String INFO = "Connector Servlet";
+ public final static String PROP_AUTHORITY = "authority";
+ protected ServletConfig mConfig = null;
+ protected IAuthority mAuthority = null;
+ protected IRequestEncoder mReqEncoder = null;
+ protected IAuthSubsystem mAuthSubsystem = null;
+ protected ILogger mLogger = CMS.getLogger();
+
+ protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+ private final static String SIGNED_AUDIT_PROTECTION_METHOD_SSL = "ssl";
+ private final static String SIGNED_AUDIT_PROTECTION_METHOD_UNKNOWN =
+ "unknown";
+ private final static String LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS =
+ "LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS_5";
+ private final static String LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST =
+ "LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST_5";
+ private final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED =
+ "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5";
+
+ private final static byte EOL[] = { Character.LINE_SEPARATOR };
+
+ public ConnectorServlet() {
+ }
+
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mConfig = sc;
+ String authority = sc.getInitParameter(PROP_AUTHORITY);
+
+ if (authority != null)
+ mAuthority = (IAuthority)
+ CMS.getSubsystem(authority);
+ mReqEncoder = CMS.getHttpRequestEncoder();
+
+ mAuthSubsystem = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ }
+
+ public void service(HttpServletRequest request,
+ HttpServletResponse response)
+ throws ServletException, IOException {
+
+ boolean running_state = CMS.isInRunningState();
+
+ if (!running_state)
+ throw new IOException(
+ "CMS server is not ready to serve.");
+
+ HttpServletRequest req = (HttpServletRequest) request;
+ HttpServletResponse resp = (HttpServletResponse) response;
+
+ ServletContext servletContext = mConfig.getServletContext();
+
+ CMSRequest cmsRequest = newCMSRequest();
+
+ // set argblock
+ cmsRequest.setHttpParams(CMS.createArgBlock(toHashtable(request)));
+
+ // set http request
+ cmsRequest.setHttpReq(request);
+
+ // set http response
+ cmsRequest.setHttpResp(response);
+
+ // set servlet config.
+ cmsRequest.setServletConfig(mConfig);
+
+ // set servlet context.
+ cmsRequest.setServletContext(mConfig.getServletContext());
+
+ char[] content = null;
+ String encodedreq = null;
+ String method = null;
+ int len = -1;
+ IPKIMessage msg = null;
+ IPKIMessage replymsg = null;
+ IRequest r = null;
+ IRequest reply = null;
+
+ // NOTE must read all bufer before redoing handshake for
+ // ssl client auth for client auth to work.
+
+ // get request method
+ method = req.getMethod();
+
+ // get content length
+ len = request.getContentLength();
+
+ // get content, a base 64 encoded serialized request.
+ if (len > 0) {
+ InputStream in = request.getInputStream();
+ InputStreamReader inreader = new InputStreamReader(in, "UTF8");
+ BufferedReader reader = new BufferedReader(inreader, len);
+
+ content = new char[len];
+ int done = reader.read(content, 0, len);
+ int total = done;
+
+ while (done >= 0 && total < len) {
+ done = reader.read(content, total, len - total);
+ total += done;
+ }
+ reader.close();
+ encodedreq = new String(content);
+ }
+
+ // force client auth handshake, validate RA and get RA's Id.
+ // NOTE must do this after all contents are read for ssl
+ // redohandshake to work
+
+ X509Certificate peerCert;
+
+ try {
+ peerCert = getPeerCert(req);
+ }catch (EBaseException e) {
+ mAuthority.log(ILogger.LL_SECURITY,
+ CMS.getLogMessage("CMSGW_HAS_NO_CLIENT_CERT"));
+ resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ return;
+ }
+
+ if (peerCert == null) {
+ // XXX log something here.
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
+
+ // authenticate RA
+
+ String RA_Id = null;
+ String raUserId = null;
+ IAuthToken token = null;
+
+ try {
+ token = authenticate(request);
+ raUserId = token.getInString("userid");
+ RA_Id = (String) peerCert.getSubjectDN().toString();
+ } catch (EInvalidCredentials e) {
+ // already logged.
+ resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ return;
+ } catch (EBaseException e) {
+ // already logged.
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
+
+ mAuthority.log(ILogger.LL_INFO,
+ "Remote Authority authenticated: " + peerCert.getSubjectDN());
+
+ // authorize
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, token,
+ mAuthzResourceName, "submit");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsRequest.setStatus(CMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ // after cert validated, check http request.
+ if (!method.equalsIgnoreCase("POST")) {
+ resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
+ return;
+ }
+ if (len <= 0) {
+ resp.sendError(HttpServletResponse.SC_LENGTH_REQUIRED);
+ return;
+ }
+
+ // now process request.
+
+ CMS.debug("ConnectorServlet: process request RA_Id=" + RA_Id);
+ try {
+ // decode request.
+ msg = (IPKIMessage) mReqEncoder.decode(encodedreq);
+ // process request
+ replymsg = processRequest(RA_Id, raUserId, msg, token);
+ } catch (IOException e) {
+ CMS.debug("ConnectorServlet: service " + e.toString());
+ CMS.debug(e);
+ mAuthority.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString()));
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ } catch (EBaseException e) {
+ CMS.debug("ConnectorServlet: service " + e.toString());
+ CMS.debug(e);
+ mAuthority.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString()));
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ return;
+ } catch (Exception e) {
+ CMS.debug("ConnectorServlet: service " + e.toString());
+ CMS.debug(e);
+ }
+
+ CMS.debug("ConnectorServlet: done processRequest");
+
+ // encode reply
+ try {
+ String encodedrep = mReqEncoder.encode(replymsg);
+
+ resp.setStatus(HttpServletResponse.SC_OK);
+ resp.setContentType("text/html");
+ resp.setContentLength(encodedrep.length());
+
+ // send reply
+ OutputStream out = response.getOutputStream();
+ OutputStreamWriter writer = new OutputStreamWriter(out, "UTF8");
+
+ writer.write(encodedrep);
+ writer.flush();
+ writer.close();
+ out.flush();
+ } catch (Exception e) {
+ CMS.debug("ConnectorServlet: error writing e=" + e.toString());
+ }
+ CMS.debug("ConnectorServlet: send response RA_Id=" + RA_Id);
+ }
+
+ public static boolean isProfileRequest(IRequest request) {
+ String profileId = request.getExtDataInString("profileId");
+
+ if (profileId == null || profileId.equals(""))
+ return false;
+ else
+ return true;
+ }
+
+ public void normalizeProfileRequest(IRequest request) {
+ // if it is profile request, we need to normalize the
+ // x509certinfo from ra into request
+ X509CertInfo info = null;
+ ByteArrayOutputStream byteStream;
+
+ try {
+ info = request.getExtDataInCertInfo(IEnrollProfile.REQUEST_CERTINFO);
+
+ // request.set(IEnrollProfile.REQUEST_SEQ_NUM, new Integer("0"));
+ CertificateX509Key certKey = (CertificateX509Key)info.get(X509CertInfo.KEY);
+ if (certKey != null) {
+ byteStream = new ByteArrayOutputStream();
+ certKey.encode(byteStream);
+ request.setExtData(IEnrollProfile.REQUEST_KEY,
+ byteStream.toByteArray());
+ }
+
+ CertificateSubjectName certSubject = (CertificateSubjectName)
+ info.get(X509CertInfo.SUBJECT);
+ if (certSubject != null) {
+ request.setExtData(IEnrollProfile.REQUEST_SUBJECT_NAME,
+ certSubject);
+ }
+
+ CertificateValidity certValidity = (CertificateValidity)
+ info.get(X509CertInfo.VALIDITY);
+ if (certValidity != null) {
+ byteStream = new ByteArrayOutputStream();
+ certValidity.encode(byteStream);
+ request.setExtData(IEnrollProfile.REQUEST_VALIDITY,
+ byteStream.toByteArray());
+ }
+
+ CertificateExtensions extensions = (CertificateExtensions)
+ info.get(X509CertInfo.EXTENSIONS);
+ if (extensions != null) {
+ request.setExtData(IEnrollProfile.REQUEST_EXTENSIONS,
+ extensions);
+ }
+
+ CertificateAlgorithmId certAlg = (CertificateAlgorithmId)
+ info.get(X509CertInfo.ALGORITHM_ID);
+ if (certAlg != null) {
+ ByteArrayOutputStream certAlgOut = new ByteArrayOutputStream();
+ certAlg.encode(certAlgOut);
+ request.setExtData(IEnrollProfile.REQUEST_SIGNING_ALGORITHM,
+ certAlgOut.toByteArray());
+ }
+ } catch (Exception e) {
+ CMS.debug("ConnectorServlet: profile normalization " +
+ e.toString());
+ }
+
+ String profileId = request.getExtDataInString("profileId");
+ IProfileSubsystem ps = (IProfileSubsystem)
+ CMS.getSubsystem("profile");
+ IEnrollProfile profile = null;
+
+ // profile subsystem may not be available. In case of KRA for
+ // example
+ if (ps == null) {
+ CMS.debug("ConnectorServlet: Profile Subsystem not found ");
+ return;
+ }
+ try {
+ profile = (IEnrollProfile) (ps.getProfile(profileId));
+ profile.setDefaultCertInfo(request);
+ } catch (EProfileException e) {
+ CMS.debug("ConnectorServlet: normalizeProfileRequest Exception: " + e.toString());
+ }
+ if (profile == null) {
+ CMS.debug("ConnectorServlet: Profile not found " + profileId);
+ return;
+ }
+ }
+
+ /**
+ * Process request
+ * <P>
+ *
+ * (Certificate Request - all "agent" profile cert requests made through a
+ * connector)
+ * <P>
+ *
+ * (Certificate Request Processed - all automated "agent" profile based
+ * cert acceptance made through a connector)
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST used when a
+ * profile cert request is made (before approval process)
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a
+ * certificate request has just been through the approval process
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS used when
+ * inter-CIMC_Boundary data transfer is successful (this is used when data
+ * does not need to be captured)
+ * </ul>
+ * @param source string containing source
+ * @param sourceUserId string containing source user ID
+ * @param msg PKI message
+ * @param token the authentication token
+ * @exception EBaseException an error has occurred
+ * @return PKI message
+ */
+ protected IPKIMessage processRequest(
+ String source, String sourceUserId, IPKIMessage msg, IAuthToken token)
+ throws EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = sourceUserId;
+ String auditProtectionMethod = SIGNED_AUDIT_PROTECTION_METHOD_SSL;
+ String auditRequestType = msg.getReqType();
+ String auditRequesterID = msg.getReqId();
+
+ // additional parms for LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST
+ String auditCertificateSubjectName = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ String subject = null;
+
+ // additional parms for LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED
+ String auditInfoCertValue = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+
+ // "normalize" the "auditSubjectID"
+ if (auditSubjectID != null) {
+ auditSubjectID = auditSubjectID.trim();
+ } else {
+ auditSubjectID = ILogger.UNIDENTIFIED;
+ }
+
+ // "normalize" the "auditRequestType"
+ if (auditRequestType != null) {
+ auditRequestType = auditRequestType.trim();
+ } else {
+ auditRequestType = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ // "normalize" the "auditRequesterID"
+ if (auditRequesterID != null) {
+ auditRequesterID = auditRequesterID.trim();
+ } else {
+ auditRequesterID = ILogger.UNIDENTIFIED;
+ }
+
+ IPKIMessage replymsg = null;
+
+ try {
+ IRequest r = null;
+ IRequestQueue queue = mAuthority.getRequestQueue();
+ String srcid = source + ":" + msg.getReqId();
+
+ // find request in request queue and return result.
+ RequestId thisreqid = queue.findRequestBySourceId(srcid);
+ IRequest thisreq = null;
+
+ if (thisreqid != null) {
+ thisreq = queue.findRequest(thisreqid);
+ if (thisreq == null) {
+ // strange case.
+ String errormsg = "Cannot find request in request queue " +
+ thisreqid;
+
+ mAuthority.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage(
+ "CMSGW_REQUEST_ID_NOT_FOUND_1",
+ thisreqid.toString()));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProtectionMethod,
+ auditRequestType,
+ auditRequesterID);
+
+ audit(auditMessage);
+
+ // NOTE: The signed audit event
+ // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST
+ // does not yet matter at this point!
+
+ throw new EBaseException(errormsg);
+ } else {
+ mAuthority.log(ILogger.LL_INFO,
+ "Found request " + thisreqid + " for " + srcid);
+ replymsg = CMS.getHttpPKIMessage();
+ replymsg.fromRequest(thisreq);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditProtectionMethod,
+ auditRequestType,
+ auditRequesterID);
+
+ audit(auditMessage);
+
+ // NOTE: The signed audit event
+ // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST
+ // does not yet matter at this point!
+
+ return replymsg;
+ }
+ }
+
+ // if not found process request.
+ thisreq = queue.newRequest(msg.getReqType());
+ CMS.debug("ConnectorServlet: created requestId=" +
+ thisreq.getRequestId().toString());
+ thisreq.setSourceId(srcid);
+
+ // NOTE: For the following signed audit message, since we only
+ // care about the "msg.toRequest( thisreq );" command, and
+ // since this command does not throw an EBaseException
+ // (which is the only exception designated by this method),
+ // then this code does NOT need to be contained within its
+ // own special try/catch block.
+ msg.toRequest( thisreq );
+
+ if( isProfileRequest( thisreq ) ) {
+ X509CertInfo info =
+ thisreq.getExtDataInCertInfo(
+ IEnrollProfile.REQUEST_CERTINFO );
+
+ try {
+ CertificateSubjectName sn = ( CertificateSubjectName )
+ info.get( X509CertInfo.SUBJECT );
+
+ // if the cert subject name is NOT MISSING, retrieve the
+ // actual "auditCertificateSubjectName" and "normalize"
+ // it
+ if( sn != null ) {
+ subject = sn.toString();
+ if( subject != null ) {
+ // NOTE: This is ok even if the cert subject
+ // name is "" (empty)!
+ auditCertificateSubjectName = subject.trim();
+ }
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditProfileID(),
+ auditCertificateSubjectName );
+
+ audit( auditMessage );
+ } catch( CertificateException e ) {
+ CMS.debug( "ConnectorServlet: processRequest "
+ + e.toString() );
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditProfileID(),
+ auditCertificateSubjectName );
+
+ audit( auditMessage );
+ } catch( IOException e ) {
+ CMS.debug( "ConnectorServlet: processRequest "
+ + e.toString() );
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditProfileID(),
+ auditCertificateSubjectName );
+
+ audit( auditMessage );
+ }
+ }
+
+ thisreq.setExtData(IRequest.AUTH_TOKEN, token);
+
+ // setting requestor type must come after copy contents. because
+ // requestor is a regular attribute.
+ thisreq.setExtData(IRequest.REQUESTOR_TYPE,
+ IRequest.REQUESTOR_RA);
+ mAuthority.log(ILogger.LL_INFO, "Processing remote request " +
+ srcid);
+
+ // Set this so that request's updateBy is recorded
+ SessionContext s = SessionContext.getContext();
+
+ if (s.get(SessionContext.USER_ID) == null) {
+ s.put(SessionContext.USER_ID, sourceUserId);
+ }
+
+ if (s.get(SessionContext.REQUESTER_ID) == null) {
+ s.put(SessionContext.REQUESTER_ID, msg.getReqId());
+ }
+
+ CMS.debug("ConnectorServlet: calling processRequest instance=" +
+ thisreq);
+ if (isProfileRequest(thisreq)) {
+ normalizeProfileRequest(thisreq);
+ }
+
+ try {
+ queue.processRequest( thisreq );
+
+ if( isProfileRequest( thisreq ) ) {
+ // reset the "auditInfoCertValue"
+ auditInfoCertValue = auditInfoCertValue( thisreq );
+
+ if( auditInfoCertValue != null ) {
+ if( !( auditInfoCertValue.equals(
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE ) ) ) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_ACCEPTANCE,
+ auditInfoCertValue );
+
+ audit( auditMessage );
+ }
+ }
+ }
+ } catch( EBaseException eAudit1 ) {
+ if( isProfileRequest( thisreq ) ) {
+ // reset the "auditInfoCertValue"
+ auditInfoCertValue = auditInfoCertValue( thisreq );
+
+ if( auditInfoCertValue != null ) {
+ if( !( auditInfoCertValue.equals(
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE ) ) ) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_ACCEPTANCE,
+ auditInfoCertValue );
+
+ audit( auditMessage );
+ }
+ }
+ }
+
+ // rethrow EBaseException to primary catch clause
+ // within this method
+ throw eAudit1;
+ }
+
+ replymsg = CMS.getHttpPKIMessage();
+ replymsg.fromRequest(thisreq);
+
+ CMS.debug("ConnectorServlet: replymsg.reqStatus=" +
+ replymsg.getReqStatus());
+
+ //for audit log
+ String agentID = sourceUserId;
+ String initiative = AuditFormat.FROMRA + " trustedManagerID: " +
+ agentID + " remote reqID " + msg.getReqId();
+ String authMgr = AuditFormat.NOAUTH;
+
+ if (token != null) {
+ authMgr =
+ token.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME);
+ }
+
+ if (isProfileRequest(thisreq)) {
+ // XXX audit log
+ CMS.debug("ConnectorServlet: done requestId=" +
+ thisreq.getRequestId().toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditProtectionMethod,
+ auditRequestType,
+ auditRequesterID);
+
+ audit(auditMessage);
+
+ // NOTE: The signed audit event
+ // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST
+ // has already been logged at this point!
+
+ return replymsg;
+ }
+
+ // Get the certificate info from the request
+ X509CertInfo x509Info[] = thisreq.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ try {
+ if (!thisreq.getRequestStatus().equals(RequestStatus.COMPLETE)) {
+ if (x509Info != null) {
+ for (int i = 0; i < x509Info.length; i++) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId(),
+ initiative,
+ authMgr,
+ thisreq.getRequestStatus(),
+ x509Info[i].get(X509CertInfo.SUBJECT),
+ ""}
+ );
+ }
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId(),
+ initiative,
+ authMgr,
+ thisreq.getRequestStatus()}
+ );
+ }
+ } else {
+ if (thisreq.getRequestType().equals(IRequest.ENROLLMENT_REQUEST)) {
+ // XXX make the repeat record.
+ // Get the certificate(s) from the request
+ X509CertImpl x509Certs[] = null;
+
+ if (x509Info != null)
+ x509Certs =
+ thisreq.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ // return potentially more than one certificates.
+ if (x509Certs != null) {
+ for (int i = 0; i < x509Certs.length; i++) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId(),
+ initiative,
+ authMgr,
+ "completed",
+ x509Certs[i].getSubjectDN(),
+ "cert issued serial number: 0x" +
+ x509Certs[i].getSerialNumber().toString(16)}
+ );
+ }
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId(),
+ initiative,
+ authMgr,
+ "completed"}
+ );
+ }
+ } else if (thisreq.getRequestType().equals(IRequest.RENEWAL_REQUEST)) {
+ X509CertImpl[] certs =
+ thisreq.getExtDataInCertArray(IRequest.OLD_CERTS);
+ X509CertImpl old_cert = certs[0];
+
+ certs = thisreq.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+ X509CertImpl renewed_cert = certs[0];
+
+ if (old_cert != null && renewed_cert != null) {
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.RENEWALFORMAT,
+ new Object[] {
+ thisreq.getRequestId(),
+ initiative,
+ authMgr,
+ "completed",
+ old_cert.getSubjectDN(),
+ old_cert.getSerialNumber().toString(16),
+ "new serial number: 0x" +
+ renewed_cert.getSerialNumber().toString(16)}
+ );
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId(),
+ initiative,
+ authMgr,
+ "completed with error"}
+ );
+ }
+ } else if (thisreq.getRequestType().equals(IRequest.REVOCATION_REQUEST)) {
+ Certificate[] oldCerts =
+ thisreq.getExtDataInCertArray(IRequest.OLD_CERTS);
+ RevokedCertImpl crlentries[] =
+ thisreq.getExtDataInRevokedCertArray(IRequest.REVOKED_CERTS);
+ CRLExtensions crlExts = crlentries[0].getExtensions();
+ int reason = 0;
+
+ if (crlExts != null) {
+ Enumeration enum1 = crlExts.getElements();
+
+ while (enum1.hasMoreElements()) {
+ Extension ext = (Extension) enum1.nextElement();
+
+ if (ext instanceof CRLReasonExtension) {
+ reason = ((CRLReasonExtension) ext).getReason().toInt();
+ break;
+ }
+ }
+ }
+
+ int count = oldCerts.length;
+ Integer result = thisreq.getExtDataInInteger(IRequest.RESULT);
+
+ if (result.equals(IRequest.RES_ERROR)) {
+ String[] svcErrors =
+ thisreq.getExtDataInStringArray(IRequest.SVCERRORS);
+
+ if (svcErrors != null && svcErrors.length > 0) {
+ for (int i = 0; i < svcErrors.length; i++) {
+ String err = svcErrors[i];
+
+ if (err != null) {
+ for (int j = 0; j < count; j++) {
+ if (oldCerts[j] != null) {
+ if (oldCerts[j] instanceof X509CertImpl) {
+ X509CertImpl cert = (X509CertImpl) oldCerts[j];
+
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ thisreq.getRequestId(),
+ initiative,
+ "completed with error: " +
+ err,
+ cert.getSubjectDN(),
+ cert.getSerialNumber().toString(16),
+ RevocationReason.fromInt(reason).toString()}
+ );
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ // the success.
+ for (int j = 0; j < count; j++) {
+ if (oldCerts[j] != null) {
+ if (oldCerts[j] instanceof X509CertImpl) {
+ X509CertImpl cert = (X509CertImpl) oldCerts[j];
+
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ thisreq.getRequestId(),
+ initiative,
+ "completed",
+ cert.getSubjectDN(),
+ cert.getSerialNumber().toString(16),
+ RevocationReason.fromInt(reason).toString()}
+ );
+ }
+ }
+ }
+ }
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId(),
+ initiative,
+ authMgr,
+ "completed"}
+ );
+ }
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditProtectionMethod,
+ auditRequestType,
+ auditRequesterID);
+
+ audit(auditMessage);
+ } catch (IOException e) {
+ CMS.debug("ConnectorServlet: process " + e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProtectionMethod,
+ auditRequestType,
+ auditRequesterID);
+
+ audit(auditMessage);
+ } catch (CertificateException e) {
+ CMS.debug("ConnectorServlet: process " + e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProtectionMethod,
+ auditRequestType,
+ auditRequesterID);
+
+ audit(auditMessage);
+ } catch (Exception e) {
+ CMS.debug("ConnectorServlet: process " + e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProtectionMethod,
+ auditRequestType,
+ auditRequesterID);
+
+ audit(auditMessage);
+ } finally {
+ SessionContext.releaseContext();
+ }
+
+ // NOTE: The signed audit event
+ // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST
+ // has already been logged at this point!
+
+ return replymsg;
+ } catch (EBaseException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProtectionMethod,
+ auditRequestType,
+ auditRequesterID);
+
+ audit(auditMessage);
+
+ // NOTE: The signed audit event
+ // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST
+ // has either already been logged, or
+ // does not yet matter at this point!
+
+ return replymsg;
+ }
+ }
+
+ protected X509Certificate
+ getPeerCert(HttpServletRequest req) throws EBaseException {
+ return getSSLClientCertificate(req);
+ }
+
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Signed Audit Log
+ *
+ * This method is inherited by all extended "CMSServlet"s,
+ * and is called to store messages to the signed audit log.
+ * <P>
+ *
+ * @param msg signed audit log message
+ */
+ protected 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);
+ }
+
+ /**
+ * Signed Audit Log Profile ID
+ *
+ * This method is inherited by all extended "EnrollProfile"s,
+ * and is called to obtain the "ProfileID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @return id string containing the signed audit log message ProfileID
+ */
+ protected String auditProfileID() {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String profileID = getId();
+
+ if (profileID != null) {
+ profileID = profileID.trim();
+ } else {
+ profileID = ILogger.UNIDENTIFIED;
+ }
+
+ return profileID;
+ }
+
+ /**
+ * Signed Audit Log Info Certificate Value
+ *
+ * This method is called to obtain the certificate from the passed in
+ * "X509CertImpl" for a signed audit log message.
+ * <P>
+ *
+ * @param request a Request containing an X509CertImpl
+ * @return cert string containing the certificate
+ */
+ private String auditInfoCertValue(IRequest request) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ X509CertImpl x509cert = request.getExtDataInCert(
+ IEnrollProfile.REQUEST_ISSUED_CERT);
+
+ if (x509cert == null) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ byte rawData[] = null;
+
+ try {
+ rawData = x509cert.getEncoded();
+ } catch (CertificateEncodingException e) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ String cert = null;
+
+ // convert "rawData" into "base64Data"
+ if (rawData != null) {
+ String base64Data = null;
+
+ base64Data = com.netscape.osutil.OSUtil.BtoA(rawData).trim();
+
+ StringBuffer sb = new StringBuffer();
+ // extract all line separators from the "base64Data"
+ for (int i = 0; i < base64Data.length(); i++) {
+ if (base64Data.substring(i, i).getBytes() != EOL) {
+ sb.append(base64Data.substring(i, i));
+ }
+ }
+ cert = sb.toString();
+ }
+
+ if (cert != null) {
+ cert = cert.trim();
+
+ if (cert.equals("")) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ } else {
+ return cert;
+ }
+ } else {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+ }
+}
+