From a4682ceae6774956461edd03b2485bbacea445f4 Mon Sep 17 00:00:00 2001 From: mharmsen Date: Tue, 4 Oct 2011 01:17:41 +0000 Subject: Bugzilla Bug #688225 - (dogtagIPAv2.1) TRACKER: of the Dogtag fixes for freeIPA 2.1 git-svn-id: svn+ssh://svn.fedorahosted.org/svn/pki/tags/IPA_v2_RHEL_6_2_20111003@2252 c9f7a03b-bd48-0410-a16d-cbbf54688b0b --- .../cms/servlet/profile/ProfileApproveServlet.java | 519 +++++++ .../cms/servlet/profile/ProfileListServlet.java | 169 +++ .../cms/servlet/profile/ProfileProcessServlet.java | 936 ++++++++++++ .../cms/servlet/profile/ProfileReviewServlet.java | 436 ++++++ .../cms/servlet/profile/ProfileSelectServlet.java | 401 +++++ .../cms/servlet/profile/ProfileServlet.java | 499 +++++++ .../servlet/profile/ProfileSubmitCMCServlet.java | 877 +++++++++++ .../cms/servlet/profile/ProfileSubmitServlet.java | 1530 ++++++++++++++++++++ .../cms/servlet/profile/SSLClientCertProvider.java | 40 + 9 files changed, 5407 insertions(+) create mode 100644 pki/base/common/src/com/netscape/cms/servlet/profile/ProfileApproveServlet.java create mode 100644 pki/base/common/src/com/netscape/cms/servlet/profile/ProfileListServlet.java create mode 100644 pki/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java create mode 100644 pki/base/common/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java create mode 100644 pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java create mode 100644 pki/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java create mode 100644 pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java create mode 100644 pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java create mode 100644 pki/base/common/src/com/netscape/cms/servlet/profile/SSLClientCertProvider.java (limited to 'pki/base/common/src/com/netscape/cms/servlet/profile') diff --git a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileApproveServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileApproveServlet.java new file mode 100644 index 000000000..8f3a0f688 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileApproveServlet.java @@ -0,0 +1,519 @@ +// --- 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.profile; + + +import java.io.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.logging.*; +import com.netscape.cms.servlet.common.*; + + +/** + * Toggle the approval state of a profile + * + * @version $Revision$, $Date$ + */ +public class ProfileApproveServlet extends ProfileServlet { + + private static final String PROP_AUTHORITY_ID = "authorityId"; + private String mAuthorityId = null; + + private final static String LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL = + "LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL_4"; + private final static String OP_APPROVE = "approve"; + private final static String OP_DISAPPROVE = "disapprove"; + + public ProfileApproveServlet() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "ImportCert.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID); + } + + /** + * Process the HTTP request. + *

+ * + *

+ * @param cmsReq the object holding the request and response information + * @exception EBaseException an error has occurred + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest request = cmsReq.getHttpReq(); + HttpServletResponse response = cmsReq.getHttpResp(); + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditProfileID = auditProfileID(request); + String auditProfileOp = auditProfileOp(request); + + String userid = null; + IAuthToken authToken = null; + ArgSet args = new ArgSet(); + + Locale locale = getLocale(request); + + IProfile profile = null; + + String profileId = null; + + IProfileSubsystem ps = null; + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + try { + authToken = authenticate(cmsReq); + CMS.debug("uid=" + authToken.getInString("userid")); + userid = authToken.getInString("userid"); + } catch (Exception e) { + CMS.debug(e.toString()); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", + e.toString())); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHENTICATION_ERROR")); + outputTemplate(request, response, args); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.FAILURE, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + + return; + } + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "approve"); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", + e.toString())); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", + e.toString())); + } + + if (authzToken == null) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHORIZATION_ERROR")); + outputTemplate(request, response, args); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.FAILURE, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + + return; + } + + CMS.debug("ProfileApproveServlet: start serving"); + // (1) Read request from the database + + // (2) Get profile id from the request + if (mProfileSubId == null || mProfileSubId.equals("")) { + mProfileSubId = IProfileSubsystem.ID; + } + CMS.debug("ProfileApproveServlet: SubId=" + mProfileSubId); + ps = (IProfileSubsystem) CMS.getSubsystem(mProfileSubId); + + if (ps == null) { + CMS.debug("ProfileApproveServlet: ProfileSubsystem not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.FAILURE, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + + return; + } + + // retrieve request + IAuthority authority = (IAuthority) CMS.getSubsystem(mAuthorityId); + + if (authority == null) { + CMS.debug("ProfileApproveServlet: Authority " + mAuthorityId + + " not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.FAILURE, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + + return; + } + IRequestQueue queue = authority.getRequestQueue(); + + if (queue == null) { + CMS.debug("ProfileApproveServlet: Request Queue of " + + mAuthorityId + " not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.FAILURE, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + + return; + } + + profileId = request.getParameter("profileId"); + + CMS.debug("ProfileApproveServlet: profileId=" + profileId); + + args.set(ARG_ERROR_CODE, "0"); + args.set(ARG_ERROR_REASON, ""); + + try { + if (ps.isProfileEnable(profileId)) { + if (ps.checkOwner()) { + if (ps.getProfileEnableBy(profileId).equals(userid)) { + ps.disableProfile(profileId); + } else { + // only enableBy can disable profile + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_NOT_OWNER")); + outputTemplate(request, response, args); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.FAILURE, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + + return; + } + } else { + ps.disableProfile(profileId); + } + } else { + ps.enableProfile(profileId, userid); + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.SUCCESS, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + } catch (EProfileException e) { + // profile not enabled + CMS.debug("ProfileApproveServlet: profile not error " + + e.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.FAILURE, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + + return; + } + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.FAILURE, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + // } catch( ServletException eAudit2 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + // auditSubjectID, + // ILogger.FAILURE, + // auditProfileID, + // auditProfileOp ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + + try { + profile = ps.getProfile(profileId); + } catch (EProfileException e) { + // profile not found + CMS.debug("ProfileApproveServlet: profile not found " + + e.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, e.toString()); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_NOT_FOUND", profileId)); + outputTemplate(request, response, args); + return; + } + if (profile == null) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_NOT_FOUND", profileId)); + outputTemplate(request, response, args); + return; + } + + Enumeration policySetIds = profile.getProfilePolicySetIds(); + + ArgList setlist = new ArgList(); + + while (policySetIds.hasMoreElements()) { + String setId = (String) policySetIds.nextElement(); + + Enumeration policyIds = profile.getProfilePolicyIds(setId); + ArgList list = new ArgList(); + + while (policyIds.hasMoreElements()) { + String id = (String) policyIds.nextElement(); + IProfilePolicy policy = (IProfilePolicy) + profile.getProfilePolicy(setId, id); + + // (3) query all the profile policies + // (4) default plugins convert request parameters + // into string http parameters + handlePolicy(list, response, locale, + id, policy); + } + ArgSet setArg = new ArgSet(); + + setArg.set(ARG_POLICY_SET_ID, setId); + setArg.set(ARG_POLICY, list); + setlist.add(setArg); + } + args.set(ARG_POLICY_SET_LIST, setlist); + + args.set(ARG_PROFILE_ID, profileId); + args.set(ARG_PROFILE_IS_ENABLED, + Boolean.toString(ps.isProfileEnable(profileId))); + args.set(ARG_PROFILE_ENABLED_BY, ps.getProfileEnableBy(profileId)); + args.set(ARG_PROFILE_NAME, profile.getName(locale)); + args.set(ARG_PROFILE_DESC, profile.getDescription(locale)); + + // (5) return info as template + outputTemplate(request, response, args); + } + + private void handlePolicy(ArgList list, ServletResponse response, + Locale locale, String id, IProfilePolicy policy) { + ArgSet set = new ArgSet(); + + set.set(ARG_POLICY_ID, id); + + // handle default policy + IPolicyDefault def = policy.getDefault(); + String dDesc = def.getText(locale); + + set.set(ARG_DEF_DESC, dDesc); + + ArgList deflist = new ArgList(); + Enumeration defNames = def.getValueNames(); + + if (defNames != null) { + while (defNames.hasMoreElements()) { + ArgSet defset = new ArgSet(); + String defName = (String) defNames.nextElement(); + IDescriptor defDesc = def.getValueDescriptor(locale, defName); + if (defDesc == null) { + CMS.debug("defName=" + defName); + } else { + String defSyntax = defDesc.getSyntax(); + String defConstraint = defDesc.getConstraint(); + String defValueName = defDesc.getDescription(locale); + String defValue = null; + + defset.set(ARG_DEF_ID, defName); + defset.set(ARG_DEF_SYNTAX, defSyntax); + defset.set(ARG_DEF_CONSTRAINT, defConstraint); + defset.set(ARG_DEF_NAME, defValueName); + defset.set(ARG_DEF_VAL, defValue); + deflist.add(defset); + } + } + } + set.set(ARG_DEF_LIST, deflist); + + // handle constraint policy + IPolicyConstraint con = policy.getConstraint(); + String conDesc = con.getText(locale); + + set.set(ARG_CON_DESC, conDesc); + + list.add(set); + } + + /** + * Signed Audit Log Profile ID + * + * This method is called to obtain the "ProfileID" for + * a signed audit log message. + *

+ * + * @param req HTTP request + * @return id string containing the signed audit log message ProfileID + */ + private String auditProfileID(HttpServletRequest req) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String profileID = null; + + // Obtain the profileID + profileID = req.getParameter("profileId"); + + if (profileID != null) { + profileID = profileID.trim(); + } else { + profileID = ILogger.UNIDENTIFIED; + } + + return profileID; + } + + /** + * Signed Audit Log Profile Operation + * + * This method is called to obtain the "Profile Operation" for + * a signed audit log message. + *

+ * + * @param req HTTP request + * @return operation string containing either OP_APPROVE, OP_DISAPPROVE, + * or SIGNED_AUDIT_EMPTY_VALUE + */ + private String auditProfileOp(HttpServletRequest req) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + if (mProfileSubId == null || + mProfileSubId.equals("")) { + mProfileSubId = IProfileSubsystem.ID; + } + + IProfileSubsystem ps = (IProfileSubsystem) + CMS.getSubsystem(mProfileSubId); + + if (ps == null) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + String profileID = auditProfileID(req); + + if (profileID == ILogger.UNIDENTIFIED) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + if (ps.isProfileEnable(profileID)) { + return OP_DISAPPROVE; + } else { + return OP_APPROVE; + } + } +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileListServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileListServlet.java new file mode 100644 index 000000000..0090e6fdc --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileListServlet.java @@ -0,0 +1,169 @@ +// --- 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.profile; + + +import java.util.Enumeration; +import java.util.Locale; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileSubsystem; +import com.netscape.certsrv.template.ArgList; +import com.netscape.certsrv.template.ArgSet; +import com.netscape.cms.servlet.common.CMSRequest; + + +/** + * List all enabled profiles. + * + * @version $Revision$, $Date$ + */ +public class ProfileListServlet extends ProfileServlet { + + private static final String PROP_AUTHORITY_ID = "authorityId"; + + private String mAuthorityId = null; + + public ProfileListServlet() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "ImportCert.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID); + } + + /** + * Process the HTTP request. + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest request = cmsReq.getHttpReq(); + HttpServletResponse response = cmsReq.getHttpResp(); + + CMS.debug("ProfileListServlet: start serving"); + + Locale locale = getLocale(request); + + ArgSet args = new ArgSet(); + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "list"); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } + + if (authzToken == null) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHORIZATION_ERROR")); + outputTemplate(request, response, args); + return; + } + + // (1) Read request from the database + + // (2) Get profile id from the request + if (mProfileSubId == null || mProfileSubId.equals("")) { + mProfileSubId = IProfileSubsystem.ID; + } + CMS.debug("ProfileListServlet: SubId=" + mProfileSubId); + IProfileSubsystem ps = (IProfileSubsystem) + CMS.getSubsystem(mProfileSubId); + + if (ps == null) { + CMS.debug("ProfileListServlet: ProfileSubsystem " + + mProfileSubId + " not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + + ArgList list = new ArgList(); + Enumeration e = ps.getProfileIds(); + + if (e != null) { + while (e.hasMoreElements()) { + String id = (String) e.nextElement(); + IProfile profile = null; + + try { + profile = ps.getProfile(id); + } catch (EBaseException e1) { + // skip bad profile + CMS.debug("ProfileListServlet: profile " + id + + " not found (skipped) " + e1.toString()); + continue; + } + if (profile == null) { + CMS.debug("ProfileListServlet: profile " + id + + " not found (skipped)"); + continue; + } + + String name = profile.getName(locale); + String desc = profile.getDescription(locale); + + ArgSet profileArgs = new ArgSet(); + + profileArgs.set(ARG_PROFILE_IS_ENABLED, + Boolean.toString(ps.isProfileEnable(id))); + profileArgs.set(ARG_PROFILE_ENABLED_BY, + ps.getProfileEnableBy(id)); + profileArgs.set(ARG_PROFILE_ID, id); + profileArgs.set(ARG_PROFILE_IS_VISIBLE, + Boolean.toString(profile.isVisible())); + profileArgs.set(ARG_PROFILE_NAME, name); + profileArgs.set(ARG_PROFILE_DESC, desc); + list.add(profileArgs); + + } + } + args.set(ARG_RECORD, list); + args.set(ARG_ERROR_CODE, "0"); + args.set(ARG_ERROR_REASON, ""); + + // (5) return info as template + outputTemplate(request, response, args); + } + +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java new file mode 100644 index 000000000..92cfa9bff --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java @@ -0,0 +1,936 @@ +// --- 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.profile; + + +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.ca.*; +import com.netscape.cms.servlet.common.*; + +import java.security.cert.*; +import netscape.security.x509.*; + + +/** + * This servlet approves profile-based request. + * + * @version $Revision$, $Date$ + */ +public class ProfileProcessServlet extends ProfileServlet { + private static final String PROP_AUTHORITY_ID = "authorityId"; + private String mAuthorityId = null; + private Nonces mNonces = null; + + private final static String SIGNED_AUDIT_CERT_REQUEST_REASON = + "requestNotes"; + private final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5"; + + public ProfileProcessServlet() { + } + + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID); + + ICertificateAuthority authority = null; + if (mAuthorityId != null) + authority = (ICertificateAuthority) CMS.getSubsystem(mAuthorityId); + + if (authority != null && authority.noncesEnabled()) { + mNonces = authority.getNonces(); + } + } + + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest request = cmsReq.getHttpReq(); + HttpServletResponse response = cmsReq.getHttpResp(); + + IStatsSubsystem statsSub = (IStatsSubsystem)CMS.getSubsystem("stats"); + if (statsSub != null) { + statsSub.startTiming("approval", true /* main action */); + } + + IAuthToken authToken = null; + ArgSet args = new ArgSet(); + + Locale locale = getLocale(request); + + if (mAuthMgr != null) { + try { + authToken = authenticate(cmsReq); + } catch (EBaseException e) { + CMS.debug("ProfileProcessServlet: " + e.toString()); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHENTICATION_ERROR")); + outputTemplate(request, response, args); + if (statsSub != null) { + statsSub.endTiming("approval"); + } + return; + } + } + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "approve"); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } + + if (authzToken == null) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHORIZATION_ERROR")); + outputTemplate(request, response, args); + if (statsSub != null) { + statsSub.endTiming("approval"); + } + return; + } + + if (mNonces != null) { + String requestNonce = request.getParameter(ARG_REQUEST_NONCE); + boolean nonceVerified = false; + if (requestNonce != null) { + long nonce = Long.parseLong(requestNonce.trim()); + X509Certificate cert1 = mNonces.getCertificate(nonce); + X509Certificate cert2 = getSSLClientCertificate(request); + if (cert1 == null) { + CMS.debug("ProfileProcessServlet: Unknown nonce"); + } else if (cert1 != null && cert2 != null && cert1.equals(cert2)) { + nonceVerified = true; + mNonces.removeNonce(nonce); + } + } else { + CMS.debug("ProfileProcessServlet: Missing nonce"); + } + CMS.debug("ProfileProcessServlet: nonceVerified="+nonceVerified); + if (!nonceVerified) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHORIZATION_ERROR")); + outputTemplate(request, response, args); + if (statsSub != null) { + statsSub.endTiming("approval"); + } + return; + } + } + + CMS.debug("ProfileProcessServlet: start serving"); + + // (1) Read request from the database + + // (2) Get profile id from the request + if (mProfileSubId == null || mProfileSubId.equals("")) { + mProfileSubId = IProfileSubsystem.ID; + } + CMS.debug("ProfileProcessServlet: SubId=" + mProfileSubId); + IProfileSubsystem ps = (IProfileSubsystem) + CMS.getSubsystem(mProfileSubId); + + if (ps == null) { + CMS.debug("ProfileProcessServlet: ProfileSubsystem not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + if (statsSub != null) { + statsSub.endTiming("approval"); + } + return; + } + + // retrieve request + IAuthority authority = (IAuthority) CMS.getSubsystem(mAuthorityId); + + if (authority == null) { + CMS.debug("ProfileProcessServlet: Authority " + mAuthorityId + + " not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + if (statsSub != null) { + statsSub.endTiming("approval"); + } + return; + } + IRequestQueue queue = authority.getRequestQueue(); + + if (queue == null) { + CMS.debug("ProfileProcessServlet: Request Queue of " + + mAuthorityId + " not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + if (statsSub != null) { + statsSub.endTiming("approval"); + } + return; + } + + String requestId = request.getParameter("requestId"); + + if (requestId == null || requestId.equals("")) { + CMS.debug("ProfileProcessServlet: Request Id not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_REQUEST_ID_NOT_FOUND")); + outputTemplate(request, response, args); + if (statsSub != null) { + statsSub.endTiming("approval"); + } + return; + } + + IRequest req = null; + + CMS.debug("ProfileProcessServlet: requestId=" + requestId); + try { + req = queue.findRequest(new RequestId(requestId)); + } catch (EBaseException e) { + // request not found + CMS.debug("ProfileProcessServlet: request not found requestId=" + + requestId + " " + e.toString()); + } + if (req == null) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_REQUEST_NOT_FOUND", requestId)); + outputTemplate(request, response, args); + if (statsSub != null) { + statsSub.endTiming("approval"); + } + return; + } + + // check if the request is in one of the terminal states + if (!req.getRequestStatus().equals(RequestStatus.PENDING)) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_REQUEST_NOT_PENDING", requestId)); + args.set(ARG_REQUEST_ID, requestId); + outputTemplate(request, response, args); + if (statsSub != null) { + statsSub.endTiming("approval"); + } + return; + } + + String profileId = req.getExtDataInString("profileId"); + + CMS.debug("ProfileProcessServlet: profileId=" + profileId); + if (profileId == null || profileId.equals("")) { + CMS.debug("ProfileProcessServlet: Profile Id not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_ID_NOT_FOUND")); + outputTemplate(request, response, args); + if (statsSub != null) { + statsSub.endTiming("approval"); + } + return; + } + + String op = request.getParameter("op"); + if (op == null) { + CMS.debug("ProfileProcessServlet: No op found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_OP_NOT_FOUND")); + outputTemplate(request, response, args); + if (statsSub != null) { + statsSub.endTiming("approval"); + } + return; + } + + + IProfile profile = null; + + try { + profile = ps.getProfile(profileId); + } catch (EProfileException e) { + // profile not found + CMS.debug("ProfileProcessServlet: profile not found " + + " " + " profileId=" + profileId + " " + e.toString()); + } + if (profile == null) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_NOT_FOUND", profileId)); + outputTemplate(request, response, args); + if (statsSub != null) { + statsSub.endTiming("approval"); + } + return; + } + + // if profile is currently disabled, dont do anything + if (!ps.isProfileEnable(profileId)) { + CMS.debug("ProfileProcessServlet: Profile Id not enabled"); + args.set(ARG_OP, op); + args.set(ARG_REQUEST_ID, req.getRequestId().toString()); + args.set(ARG_REQUEST_STATUS, req.getRequestStatus().toString()); + args.set(ARG_REQUEST_TYPE, req.getRequestType()); + args.set(ARG_PROFILE_ID, profileId); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_ID_NOT_ENABLED")); + outputTemplate(request, response, args); + if (statsSub != null) { + statsSub.endTiming("approval"); + } + return; + } + + + args.set(ARG_ERROR_CODE, "0"); + args.set(ARG_ERROR_REASON, ""); + + try { + if (op.equals("assign")) { + String owner = req.getRequestOwner(); + + // assigned owner + if (owner != null && owner.length() > 0) { + if (!grantPermission(req, authToken)) { + CMS.debug("ProfileProcessServlet: Permission not granted to assign request."); + args.set(ARG_OP, op); + args.set(ARG_REQUEST_ID, req.getRequestId().toString()); + args.set(ARG_REQUEST_STATUS, req.getRequestStatus().toString()); + args.set(ARG_REQUEST_TYPE, req.getRequestType()); + args.set(ARG_PROFILE_ID, profileId); + args.set(ARG_PROFILE_ID, profileId); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, "CMS_PROFILE_DENY_OPERATION")); + outputTemplate(request, response, args); + if (statsSub != null) { + statsSub.endTiming("approval"); + } + return; + } + } + assignRequest(request, args, req, queue, profile, locale); + } else { + if (grantPermission(req, authToken)) { + if (op.equals("approve")) { + checkProfileVersion(profile, req, locale); + updateValues(request, req, queue, profile, locale); + updateNotes(request, req); + approveRequest(request, args, req, queue, profile, locale); + } else if (op.equals("reject")) { + updateNotes(request, req); + rejectRequest(request, args, req, queue, profile, locale); + } else if (op.equals("cancel")) { + updateNotes(request, req); + cancelRequest(request, args, req, queue, profile, locale); + } else if (op.equals("update")) { + checkProfileVersion(profile, req, locale); + updateValues(request, req, queue, profile, locale); + updateNotes(request, req); + } else if (op.equals("validate")) { + updateValues(request, req, queue, profile, locale); + } else if (op.equals("unassign")) { + unassignRequest(request, args, req, queue, profile, locale); + } + } else { + CMS.debug("ProfileProcessServlet: Permission not granted to approve/reject/cancel/update/validate/unassign request."); + args.set(ARG_OP, op); + args.set(ARG_REQUEST_ID, req.getRequestId().toString()); + args.set(ARG_REQUEST_STATUS, req.getRequestStatus().toString()); + args.set(ARG_REQUEST_TYPE, req.getRequestType()); + args.set(ARG_PROFILE_ID, profileId); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, "CMS_PROFILE_DENY_OPERATION")); + outputTemplate(request, response, args); + if (statsSub != null) { + statsSub.endTiming("approval"); + } + return; + } + } + + // commit request to the storage + if (!op.equals("validate")) { + try { + if (op.equals("approve")) { + queue.markAsServiced(req); + } else { + queue.updateRequest(req); + } + } catch (EBaseException e) { + CMS.debug("ProfileProcessServlet: Request commit error " + + e.toString()); + // save request to disk + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + if (statsSub != null) { + statsSub.endTiming("approval"); + } + return; + } + } + } catch (ERejectException e) { + CMS.debug("ProfileProcessServlet: execution rejected " + + e.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_REJECTED", e.toString())); + } catch (EDeferException e) { + CMS.debug("ProfileProcessServlet: execution defered " + + e.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_DEFERRED", e.toString())); + } catch (EPropertyException e) { + CMS.debug("ProfileProcessServlet: execution error " + + e.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_PROPERTY_ERROR", e.toString())); + } catch (EProfileException e) { + CMS.debug("ProfileProcessServlet: execution error " + + e.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + } + + args.set(ARG_OP, op); + args.set(ARG_REQUEST_ID, req.getRequestId().toString()); + args.set(ARG_REQUEST_STATUS, req.getRequestStatus().toString()); + args.set(ARG_REQUEST_TYPE, req.getRequestType()); + args.set(ARG_PROFILE_ID, profileId); + outputTemplate(request, response, args); + if (statsSub != null) { + statsSub.endTiming("approval"); + } + } + + public boolean grantPermission(IRequest req, IAuthToken token) { + + try { + boolean enable = CMS.getConfigStore().getBoolean("request.assignee.enable", + false); + if (!enable) + return true; + String owner = req.getRequestOwner(); + + // unassigned owner + if (owner == null || owner.length() == 0) + return true; + String uid = token.getInString(IAuthToken.USER_ID); + if (uid.equals(owner)) + return true; + } catch (Exception e) { + } + + return false; + } + + /** + * Check if the request creation time is older than the profile + * lastModified attribute. + */ + protected void checkProfileVersion(IProfile profile, IRequest req, + Locale locale) throws EProfileException { + IConfigStore profileConfig = profile.getConfigStore(); + if (profileConfig != null) { + String lastModified = null; + try { + lastModified = profileConfig.getString("lastModified",""); + } catch (EBaseException e) { + CMS.debug(e.toString()); + throw new EProfileException( e.toString() ); + } + if (!lastModified.equals("")) { + Date profileModifiedAt = new Date(Long.parseLong(lastModified)); + CMS.debug("ProfileProcessServlet: Profile Last Modified=" + + profileModifiedAt); + Date reqCreatedAt = req.getCreationTime(); + CMS.debug("ProfileProcessServlet: Request Created At=" + + reqCreatedAt); + if (profileModifiedAt.after(reqCreatedAt)) { + CMS.debug("Profile Newer Than Request"); + throw new ERejectException("Profile Newer Than Request"); + } + } + } + } + + protected void assignRequest(ServletRequest request, ArgSet args, + IRequest req, + IRequestQueue queue, IProfile profile, Locale locale) + throws EProfileException { + + String id = auditSubjectID(); + req.setRequestOwner(id); + } + + protected void unassignRequest(ServletRequest request, ArgSet args, + IRequest req, + IRequestQueue queue, IProfile profile, Locale locale) + throws EProfileException { + + req.setRequestOwner(""); + } + + /** + * Cancel request + *

+ * + * (Certificate Request Processed - a manual "agent" profile based cert + * cancellation) + *

+ * + *

+ * @param request the servlet request + * @param args argument set + * @param req the certificate request + * @param queue the certificate request queue + * @param profile this profile + * @param locale the system locale + * @exception EProfileException an error related to this profile has + * occurred + */ + protected void cancelRequest(ServletRequest request, ArgSet args, + IRequest req, + IRequestQueue queue, IProfile profile, Locale locale) + throws EProfileException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = auditRequesterID(req); + String auditInfoValue = auditInfoValue(req); + + // try { + req.setRequestStatus(RequestStatus.CANCELED); + + // 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_CANCELLATION, + auditInfoValue); + + audit(auditMessage); + // } catch( EProfileException eAudit1 ) { + // // 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_CANCELLATION, + // auditInfoValue ); + // + // audit( auditMessage ); + // } + } + + /** + * Reject request + *

+ * + * (Certificate Request Processed - a manual "agent" profile based cert + * rejection) + *

+ * + *

+ * @param request the servlet request + * @param args argument set + * @param req the certificate request + * @param queue the certificate request queue + * @param profile this profile + * @param locale the system locale + * @exception EProfileException an error related to this profile has + * occurred + */ + protected void rejectRequest(ServletRequest request, ArgSet args, + IRequest req, + IRequestQueue queue, IProfile profile, Locale locale) + throws EProfileException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = auditRequesterID(req); + String auditInfoValue = auditInfoValue(req); + + // try { + req.setRequestStatus(RequestStatus.REJECTED); + + // 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_REJECTION, + auditInfoValue); + + audit(auditMessage); + // } catch( EProfileException eAudit1 ) { + // // 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_REJECTION, + // auditInfoValue ); + // + // audit( auditMessage ); + // } + } + + /** + * Approve request + *

+ * + * (Certificate Request Processed - a manual "agent" profile based cert + * acceptance) + *

+ * + *

+ * @param request the servlet request + * @param args argument set + * @param req the certificate request + * @param queue the certificate request queue + * @param profile this profile + * @param locale the system locale + * @exception EProfileException an error related to this profile has + * occurred + */ + protected void approveRequest(ServletRequest request, ArgSet args, + IRequest req, + IRequestQueue queue, IProfile profile, Locale locale) + throws EProfileException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = auditRequesterID(req); + + try { + profile.execute(req); + req.setRequestStatus(RequestStatus.COMPLETE); + + ArgList outputlist = new ArgList(); + Enumeration outputIds = profile.getProfileOutputIds(); + + if (outputIds != null) { + while (outputIds.hasMoreElements()) { + String outputId = (String) outputIds.nextElement(); + IProfileOutput profileOutput = profile.getProfileOutput( + outputId); + + Enumeration outputNames = profileOutput.getValueNames(); + + if (outputNames != null) { + while (outputNames.hasMoreElements()) { + ArgSet outputset = new ArgSet(); + String outputName = (String) + outputNames.nextElement(); + IDescriptor outputDesc = + profileOutput.getValueDescriptor(locale, + outputName); + + if (outputDesc == null) + continue; + String outputSyntax = outputDesc.getSyntax(); + String outputConstraint = + outputDesc.getConstraint(); + String outputValueName = + outputDesc.getDescription(locale); + String outputValue = null; + + try { + outputValue = profileOutput.getValue( + outputName, + locale, req); + } catch (EProfileException e) { + CMS.debug("ProfileSubmitServlet: " + + e.toString()); + } + + outputset.set(ARG_OUTPUT_ID, outputName); + outputset.set(ARG_OUTPUT_SYNTAX, outputSyntax); + outputset.set(ARG_OUTPUT_CONSTRAINT, + outputConstraint); + outputset.set(ARG_OUTPUT_NAME, outputValueName); + outputset.set(ARG_OUTPUT_VAL, outputValue); + outputlist.add(outputset); + } + } + } + } + args.set(ARG_OUTPUT_LIST, outputlist); + + // retrieve the certificate + X509CertImpl theCert = req.getExtDataInCert( + IEnrollProfile.REQUEST_ISSUED_CERT); + + // 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(theCert)); + + audit(auditMessage); + + } catch (EProfileException eAudit1) { + // 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, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + audit(auditMessage); + + CMS.debug("ProfileProcessServlet: about to throw EProfileException because of bad profile execute."); + throw new EProfileException(eAudit1.toString()); + + + } + } + + protected void updateValues(ServletRequest request, IRequest req, + IRequestQueue queue, IProfile profile, Locale locale) + throws ERejectException, EDeferException, EPropertyException { + String profileSetId = req.getExtDataInString("profileSetId"); + + Enumeration policies = profile.getProfilePolicies(profileSetId); + int count = 0; + + while (policies.hasMoreElements()) { + IProfilePolicy policy = (IProfilePolicy) policies.nextElement(); + + setValue(locale, count, policy, req, request); + count++; + } + + policies = profile.getProfilePolicies(profileSetId); + count = 0; + while (policies.hasMoreElements()) { + IProfilePolicy policy = (IProfilePolicy) policies.nextElement(); + + validate(locale, count, policy, req, request); + count++; + } + + } + + protected void updateNotes(ServletRequest request, IRequest req) { + String notes = request.getParameter(ARG_REQUEST_NOTES); + + if (notes != null) { + req.setExtData("requestNotes", notes); + } + } + + protected void validate(Locale locale, int count, + IProfilePolicy policy, IRequest req, ServletRequest request) + throws ERejectException, EDeferException { + IPolicyConstraint con = policy.getConstraint(); + + con.validate(req); + } + + protected void setValue(Locale locale, int count, + IProfilePolicy policy, IRequest req, ServletRequest request) + throws EPropertyException { + // handle default policy + IPolicyDefault def = policy.getDefault(); + Enumeration defNames = def.getValueNames(); + + while (defNames.hasMoreElements()) { + String defName = (String) defNames.nextElement(); + String defValue = request.getParameter(defName); + + def.setValue(defName, locale, req, defValue); + } + } + + /** + * Signed Audit Log Requester ID + * + * This method is called to obtain the "RequesterID" for + * a signed audit log message. + *

+ * + * @param request the actual request + * @return id string containing the signed audit log message RequesterID + */ + private String auditRequesterID(IRequest request) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String requesterID = ILogger.UNIDENTIFIED; + + if (request != null) { + // overwrite "requesterID" if and only if "id" != null + String id = request.getRequestId().toString(); + + if (id != null) { + requesterID = id.trim(); + } + } + + return requesterID; + } + + /** + * Signed Audit Log Info Value + * + * This method is called to obtain the "reason" for + * a signed audit log message. + *

+ * + * @param request the actual request + * @return reason string containing the signed audit log message reason + */ + private String auditInfoValue(IRequest request) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String reason = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + + if (request != null) { + // overwrite "reason" if and only if "info" != null + String info = + request.getExtDataInString(SIGNED_AUDIT_CERT_REQUEST_REASON); + + if (info != null) { + reason = info.trim(); + + // overwrite "reason" if and only if "reason" is empty + if (reason.equals("")) { + reason = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } + } + + return reason; + } + + /** + * 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. + *

+ * + * @param x509cert an X509CertImpl + * @return cert string containing the certificate + */ + private String auditInfoCertValue(X509CertImpl x509cert) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + 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(); + + // extract all line separators from the "base64Data" + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < base64Data.length(); i++) { + if (!Character.isWhitespace(base64Data.charAt(i))) { + sb.append(base64Data.charAt(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; + } + } +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java new file mode 100644 index 000000000..1591d5fdf --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java @@ -0,0 +1,436 @@ +// --- 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.profile; + + +import java.io.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.ca.*; +import com.netscape.cms.servlet.common.*; + + +/** + * This servlet allows reviewing of profile-based request. + * + * @version $Revision$, $Date$ + */ +public class ProfileReviewServlet extends ProfileServlet { + + private static final String PROP_AUTHORITY_ID = "authorityId"; + + private String mAuthorityId = null; + private Random mRandom = null; + private Nonces mNonces = null; + + public ProfileReviewServlet() { + } + + /** + * initialize the servlet. This servlet uses the template file + * "ImportCert.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID); + + ICertificateAuthority authority = null; + if (mAuthorityId != null) + authority = (ICertificateAuthority) CMS.getSubsystem(mAuthorityId); + + if (authority != null && authority.noncesEnabled()) { + mNonces = authority.getNonces(); + mRandom = new Random(); + } + } + + /** + * Process the HTTP request. + *

+ * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest request = cmsReq.getHttpReq(); + HttpServletResponse response = cmsReq.getHttpResp(); + + CMS.debug("ProfileReviewServlet: start serving"); + + Locale locale = getLocale(request); + ArgSet args = new ArgSet(); + IAuthToken authToken = null; + + if (mAuthMgr != null) { + try { + authToken = authenticate(request); + } catch (EBaseException e) { + CMS.debug("ReviewReqServlet: " + e.toString()); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHENTICATION_ERROR")); + outputTemplate(request, response, args); + return; + } + } + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "read"); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } + + if (authzToken == null) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHORIZATION_ERROR")); + outputTemplate(request, response, args); + return; + } + + // (1) Read request from the database + + // (2) Get profile id from the request + if (mProfileSubId == null || mProfileSubId.equals("")) { + mProfileSubId = IProfileSubsystem.ID; + } + CMS.debug("ProfileReviewServlet: SubId=" + mProfileSubId); + IProfileSubsystem ps = (IProfileSubsystem) + CMS.getSubsystem(mProfileSubId); + + if (ps == null) { + CMS.debug("ProfileReviewServlet: ProfileSubsystem not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + + // retrieve request + IAuthority authority = (IAuthority) CMS.getSubsystem(mAuthorityId); + + if (authority == null) { + CMS.debug("ProfileReviewServlet: Authority " + mAuthorityId + + " not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + IRequestQueue queue = authority.getRequestQueue(); + + if (queue == null) { + CMS.debug("ProfileReviewServlet: Request Queue of " + + mAuthorityId + " not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + + String requestId = request.getParameter("requestId"); + IRequest req = null; + + CMS.debug("ProfileReviewServlet: requestId=" + requestId); + try { + req = queue.findRequest(new RequestId(requestId)); + } catch (EBaseException e) { + // request not found + CMS.debug("ProfileReviewServlet: request not found requestId=" + + requestId + " " + e.toString()); + } + if (req == null) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_REQUEST_NOT_FOUND", requestId)); + outputTemplate(request, response, args); + return; + } + + String profileId = req.getExtDataInString("profileId"); + + CMS.debug("ProfileReviewServlet: requestId=" + + requestId + " profileId=" + profileId); + IProfile profile = null; + + try { + profile = ps.getProfile(profileId); + } catch (EProfileException e) { + // profile not found + CMS.debug("ProfileReviewServlet: profile not found requestId=" + + requestId + " profileId=" + profileId + " " + e.toString()); + } + if (profile == null) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_NOT_FOUND", profileId)); + outputTemplate(request, response, args); + return; + } + + String profileSetId = req.getExtDataInString("profileSetId"); + + CMS.debug("ProfileReviewServlet: profileSetId=" + profileSetId); + Enumeration policyIds = (profileSetId != null && profileSetId.length() > 0)? + profile.getProfilePolicyIds(profileSetId): null; + int count = 0; + ArgList list = new ArgList(); + + if (policyIds != null) { + while (policyIds.hasMoreElements()) { + String id = (String) policyIds.nextElement(); + IProfilePolicy policy = (IProfilePolicy) + profile.getProfilePolicy(req.getExtDataInString("profileSetId"), + id); + + // (3) query all the profile policies + // (4) default plugins convert request parameters into string + // http parameters + handlePolicy(list, response, locale, + id, policy, req); + count++; + } + } + + if (mNonces != null) { + long n = mRandom.nextLong(); + long m = mNonces.addNonce(n, getSSLClientCertificate(request)); + if ((n + m) != 0) { + args.set(ARG_REQUEST_NONCE, Long.toString(m)); + } + } + + args.set(ARG_REQUEST_ID, req.getRequestId().toString()); + args.set(ARG_REQUEST_TYPE, req.getRequestType()); + args.set(ARG_REQUEST_STATUS, req.getRequestStatus().toString()); + if (req.getRequestOwner() == null) { + args.set(ARG_REQUEST_OWNER, ""); + } else { + args.set(ARG_REQUEST_OWNER, req.getRequestOwner()); + } + args.set(ARG_REQUEST_CREATION_TIME, req.getCreationTime().toString()); + args.set(ARG_REQUEST_MODIFICATION_TIME, + req.getModificationTime().toString()); + + args.set(ARG_PROFILE_ID, profileId); + args.set(ARG_PROFILE_APPROVED_BY, + req.getExtDataInString("profileApprovedBy")); + args.set(ARG_PROFILE_SET_ID, req.getExtDataInString("profileSetId")); + if (profile.isVisible()) { + args.set(ARG_PROFILE_IS_VISIBLE, "true"); + } else { + args.set(ARG_PROFILE_IS_VISIBLE, "false"); + } + args.set(ARG_PROFILE_NAME, profile.getName(locale)); + args.set(ARG_PROFILE_DESC, profile.getDescription(locale)); + args.set(ARG_PROFILE_REMOTE_HOST, + req.getExtDataInString("profileRemoteHost")); + args.set(ARG_PROFILE_REMOTE_ADDR, + req.getExtDataInString("profileRemoteAddr")); + if (req.getExtDataInString("requestNotes") == null) { + args.set(ARG_REQUEST_NOTES, ""); + } else { + args.set(ARG_REQUEST_NOTES, + req.getExtDataInString("requestNotes")); + } + + args.set(ARG_RECORD, list); + args.set(ARG_ERROR_CODE, "0"); + args.set(ARG_ERROR_REASON, ""); + + ArgList inputlist = new ArgList(); + + // populate authentication parameters + + // populate input parameters + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + + Enumeration inputNames = profileInput.getValueNames(); + + if (inputNames != null) { + while (inputNames.hasMoreElements()) { + ArgSet inputset = new ArgSet(); + String inputName = (String) inputNames.nextElement(); + + IDescriptor inputDesc = profileInput.getValueDescriptor(locale, inputName); + + if (inputDesc == null) + continue; + String inputSyntax = inputDesc.getSyntax(); + String inputConstraint = inputDesc.getConstraint(); + String inputValueName = inputDesc.getDescription(locale); + String inputValue = null; + + try { + inputValue = profileInput.getValue(inputName, locale, req); + } catch (EBaseException e) { + CMS.debug("ProfileReviewServlet: " + e.toString()); + } + + inputset.set(ARG_INPUT_ID, inputName); + inputset.set(ARG_INPUT_SYNTAX, inputSyntax); + inputset.set(ARG_INPUT_CONSTRAINT, inputConstraint); + inputset.set(ARG_INPUT_NAME, inputValueName); + inputset.set(ARG_INPUT_VAL, inputValue); + inputlist.add(inputset); + } + } + } + } + args.set(ARG_INPUT_LIST, inputlist); + + // if request in complete state + + ArgList outputlist = new ArgList(); + Enumeration outputIds = profile.getProfileOutputIds(); + + if (outputIds != null) { + while (outputIds.hasMoreElements()) { + String outputId = (String) outputIds.nextElement(); + IProfileOutput profileOutput = profile.getProfileOutput(outputId + ); + + Enumeration outputNames = profileOutput.getValueNames(); + + if (outputNames != null) { + while (outputNames.hasMoreElements()) { + ArgSet outputset = new ArgSet(); + String outputName = (String) outputNames.nextElement + (); + IDescriptor outputDesc = + profileOutput.getValueDescriptor(locale, outputName); + + if (outputDesc == null) + continue; + String outputSyntax = outputDesc.getSyntax(); + String outputConstraint = outputDesc.getConstraint(); + String outputValueName = outputDesc.getDescription(locale); + String outputValue = null; + + try { + outputValue = profileOutput.getValue(outputName, + locale, req); + } catch (EProfileException e) { + CMS.debug("ProfileSubmitServlet: " + e.toString( + )); + } + + outputset.set(ARG_OUTPUT_ID, outputName); + outputset.set(ARG_OUTPUT_SYNTAX, outputSyntax); + outputset.set(ARG_OUTPUT_CONSTRAINT, outputConstraint); + outputset.set(ARG_OUTPUT_NAME, outputValueName); + outputset.set(ARG_OUTPUT_VAL, outputValue); + outputlist.add(outputset); + } + } + } + } + args.set(ARG_OUTPUT_LIST, outputlist); + + // (5) return info as template + outputTemplate(request, response, args); + } + + private void handlePolicy(ArgList list, ServletResponse response, + Locale locale, String id, IProfilePolicy policy, + IRequest req) { + ArgSet set = new ArgSet(); + + set.set(ARG_POLICY_ID, id); + + // handle default policy + IPolicyDefault def = policy.getDefault(); + String dDesc = def.getText(locale); + + set.set(ARG_DEF_DESC, dDesc); + ArgList deflist = new ArgList(); + Enumeration defNames = def.getValueNames(); + + if (defNames != null) { + while (defNames.hasMoreElements()) { + ArgSet defset = new ArgSet(); + String defName = (String) defNames.nextElement(); + IDescriptor defDesc = def.getValueDescriptor(locale, defName); + + if (defDesc == null) + continue; + String defSyntax = defDesc.getSyntax(); + String defConstraint = defDesc.getConstraint(); + String defValueName = defDesc.getDescription(locale); + String defValue = null; + + try { + defValue = def.getValue(defName, locale, req); + } catch (EPropertyException ee) { + CMS.debug("ProfileReviewServlet: " + ee.toString()); + } + + defset.set(ARG_DEF_ID, defName); + defset.set(ARG_DEF_SYNTAX, defSyntax); + defset.set(ARG_DEF_CONSTRAINT, defConstraint); + defset.set(ARG_DEF_NAME, defValueName); + defset.set(ARG_DEF_VAL, defValue); + deflist.add(defset); + } + } + set.set(ARG_DEF_LIST, deflist); + + // handle constraint policy + IPolicyConstraint con = policy.getConstraint(); + + if (con != null) { + String conDesc = con.getText(locale); + + set.set(ARG_CON_DESC, conDesc); + } + + list.add(set); + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java new file mode 100644 index 000000000..7d0edbbc0 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java @@ -0,0 +1,401 @@ +// --- 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.profile; + + +import com.netscape.cms.servlet.common.*; + +import java.io.*; +import java.util.*; +import java.security.cert.*; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.logging.*; +import com.netscape.cms.servlet.common.*; + +import netscape.security.x509.*; + + +/** + * Retrieve detailed information of a particular profile. + * + * @version $Revision$, $Date$ + */ +public class ProfileSelectServlet extends ProfileServlet { + + private static final String PROP_AUTHORITY_ID = "authorityId"; + private String mAuthorityId = null; + + public ProfileSelectServlet() { + } + + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID); + } + + /** + * Process the HTTP request. + * + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest request = cmsReq.getHttpReq(); + HttpServletResponse response = cmsReq.getHttpResp(); + + CMS.debug("ProfileSelectServlet: start serving"); + + Locale locale = getLocale(request); + + IAuthToken authToken = null; + ArgSet args = new ArgSet(); + + if (mAuthMgr != null) { + try { + authToken = authenticate(request); + } catch (EBaseException e) { + CMS.debug("ProcessReqServlet: " + e.toString()); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHENTICATION_ERROR")); + outputTemplate(request, response, args); + return; + } + } + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "read"); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } + + if (authzToken == null) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHORIZATION_ERROR")); + outputTemplate(request, response, args); + return; + } + + // (1) Read request from the database + + // (2) Get profile id from the request + if (mProfileSubId == null || mProfileSubId.equals("")) { + mProfileSubId = IProfileSubsystem.ID; + } + CMS.debug("ProfileSelectServlet: SubId=" + mProfileSubId); + IProfileSubsystem ps = (IProfileSubsystem) + CMS.getSubsystem(mProfileSubId); + + if (ps == null) { + CMS.debug("ProfileSelectServlet: ProfileSubsystem not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + + // retrieve request + IAuthority authority = (IAuthority) CMS.getSubsystem(mAuthorityId); + + if (authority == null) { + CMS.debug("ProfileSelectServlet: Authority " + mAuthorityId + + " not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + IRequestQueue queue = authority.getRequestQueue(); + + if (queue == null) { + CMS.debug("ProfileSelectServlet: Request Queue of " + + mAuthorityId + " not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + + IProfile profile = null; + + String profileId = request.getParameter("profileId"); + + CMS.debug("ProfileSelectServlet: profileId=" + profileId); + + try { + profile = ps.getProfile(profileId); + } catch (EProfileException e) { + // profile not found + CMS.debug("ProfileSelectServlet: profile not found profileId=" + + profileId + " " + e.toString()); + } + if (profile == null) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_NOT_FOUND", profileId)); + outputTemplate(request, response, args); + return; + } + + ArgList setlist = new ArgList(); + Enumeration policySetIds = profile.getProfilePolicySetIds(); + + if (policySetIds != null) { + while (policySetIds.hasMoreElements()) { + String setId = (String) policySetIds.nextElement(); + + ArgList list = new ArgList(); + Enumeration policyIds = profile.getProfilePolicyIds(setId); + + if (policyIds != null) { + while (policyIds.hasMoreElements()) { + String id = (String) policyIds.nextElement(); + IProfilePolicy policy = (IProfilePolicy) + profile.getProfilePolicy(setId, id); + + // (3) query all the profile policies + // (4) default plugins convert request parameters into string + // http parameters + handlePolicy(list, response, locale, + id, policy); + } + } + ArgSet setArg = new ArgSet(); + + setArg.set(ARG_POLICY_SET_ID, setId); + setArg.set(ARG_POLICY, list); + setlist.add(setArg); + } + } + args.set(ARG_POLICY_SET_LIST, setlist); + + args.set(ARG_PROFILE_ID, profileId); + args.set(ARG_PROFILE_IS_ENABLED, + Boolean.toString(ps.isProfileEnable(profileId))); + args.set(ARG_PROFILE_ENABLED_BY, ps.getProfileEnableBy(profileId)); + args.set(ARG_PROFILE_NAME, profile.getName(locale)); + args.set(ARG_PROFILE_DESC, profile.getDescription(locale)); + args.set(ARG_PROFILE_IS_VISIBLE, + Boolean.toString(profile.isVisible())); + args.set(ARG_ERROR_CODE, "0"); + args.set(ARG_ERROR_REASON, ""); + + try { + boolean keyArchivalEnabled = CMS.getConfigStore().getBoolean("ca.connector.KRA.enable", false); + if (keyArchivalEnabled == true) { + CMS.debug("ProfileSelectServlet: keyArchivalEnabled is true"); + + // output transport certificate if present + args.set("transportCert", + CMS.getConfigStore().getString("ca.connector.KRA.transportCert", "")); + } else { + CMS.debug("ProfileSelectServlet: keyArchivalEnabled is false"); + args.set("transportCert", ""); + } + } catch (EBaseException e) { + CMS.debug("ProfileSelectServlet: exception caught:"+e.toString()); + } + + // build authentication + ArgList authlist = new ArgList(); + IProfileAuthenticator authenticator = null; + + try { + authenticator = profile.getAuthenticator(); + } catch (EProfileException e) { + // authenticator not installed correctly + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHENTICATION_MANAGER_NOT_FOUND", + profile.getAuthenticatorId())); + outputTemplate(request, response, args); + return; + } + + if (authenticator != null) { + Enumeration authNames = authenticator.getValueNames(); + + if (authNames != null) { + while (authNames.hasMoreElements()) { + ArgSet authset = new ArgSet(); + String authName = (String) authNames.nextElement(); + IDescriptor authDesc = + authenticator.getValueDescriptor(locale, authName); + + if (authDesc == null) + continue; + String authSyntax = authDesc.getSyntax(); + String authConstraint = authDesc.getConstraint(); + String authValueName = authDesc.getDescription(locale); + + authset.set(ARG_AUTH_ID, authName); + authset.set(ARG_AUTH_SYNTAX, authSyntax); + authset.set(ARG_AUTH_CONSTRAINT, authConstraint); + authset.set(ARG_AUTH_NAME, authValueName); + authlist.add(authset); + } + } + args.set(ARG_AUTH_LIST, authlist); + args.set(ARG_AUTH_NAME, authenticator.getName(locale)); + args.set(ARG_AUTH_DESC, authenticator.getText(locale)); + args.set(ARG_AUTH_IS_SSL, + Boolean.toString(authenticator.isSSLClientRequired())); + } + + // build input list + ArgList inputlist = new ArgList(); + ArgList inputPluginlist = new ArgList(); + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + + if (profileInput != null) { + + ArgSet inputpluginset = new ArgSet(); + inputpluginset.set(ARG_INPUT_PLUGIN_ID, inputId); + inputpluginset.set(ARG_INPUT_PLUGIN_NAME, + profileInput.getName(locale)); + inputpluginset.set(ARG_INPUT_PLUGIN_DESC, + profileInput.getText(locale)); + inputPluginlist.add(inputpluginset); + + Enumeration inputNames = profileInput.getValueNames(); + + if (inputNames != null) { + while (inputNames.hasMoreElements()) { + ArgSet inputset = new ArgSet(); + String inputName = (String) inputNames.nextElement(); + IDescriptor inputDesc = profileInput.getValueDescriptor( + locale, inputName); + + if (inputDesc == null) + continue; + String inputSyntax = inputDesc.getSyntax(); + String inputConstraint = inputDesc.getConstraint(); + String inputValueName = inputDesc.getDescription(locale); + String inputValue = null; + + inputset.set(ARG_INPUT_PLUGIN_ID, inputId); + inputset.set(ARG_INPUT_ID, inputName); + inputset.set(ARG_INPUT_SYNTAX, inputSyntax); + inputset.set(ARG_INPUT_CONSTRAINT, inputConstraint); + inputset.set(ARG_INPUT_NAME, inputValueName); + inputset.set(ARG_INPUT_VAL, inputValue); + inputlist.add(inputset); + } + } + } + } + } + args.set(ARG_INPUT_LIST, inputlist); + args.set(ARG_INPUT_PLUGIN_LIST, inputPluginlist); + args.set(ARG_IS_RENEWAL, profile.isRenewal()); + args.set(ARG_XML_OUTPUT, profile.isXmlOutput()); + + // (5) return info as template + outputTemplate(request, response, args); + } + + private void handlePolicy(ArgList list, ServletResponse response, + Locale locale, String id, IProfilePolicy policy) { + ArgSet set = new ArgSet(); + + set.set(ARG_POLICY_ID, id); + + // handle default policy + IPolicyDefault def = policy.getDefault(); + String dDesc = def.getText(locale); + + set.set(ARG_DEF_DESC, dDesc); + ArgList deflist = new ArgList(); + Enumeration defNames = def.getValueNames(); + + if (defNames != null) { + while (defNames.hasMoreElements()) { + ArgSet defset = new ArgSet(); + String defName = (String) defNames.nextElement(); + IDescriptor defDesc = def.getValueDescriptor(locale, defName); + + if (defDesc == null) + continue; + String defSyntax = defDesc.getSyntax(); + String defConstraint = defDesc.getConstraint(); + String defValueName = defDesc.getDescription(locale); + String defValue = null; + + defset.set(ARG_DEF_ID, defName); + defset.set(ARG_DEF_SYNTAX, defSyntax); + defset.set(ARG_DEF_CONSTRAINT, defConstraint); + defset.set(ARG_DEF_NAME, defValueName); + defset.set(ARG_DEF_VAL, defValue); + deflist.add(defset); + } + } + set.set(ARG_DEF_LIST, deflist); + + // handle constraint policy + IPolicyConstraint con = policy.getConstraint(); + String conDesc = con.getText(locale); + + set.set(ARG_CON_DESC, conDesc); + ArgList conlist = new ArgList(); + Enumeration conNames = con.getConfigNames(); + if (conNames != null) { + while (conNames.hasMoreElements()) { + ArgSet conset = new ArgSet(); + String conName = (String) conNames.nextElement(); + conset.set(ARG_CON_NAME, conName); + conset.set(ARG_CON_VALUE, con.getConfig(conName)); + conlist.add(conset); + } + } + set.set(ARG_CON_LIST, conlist); + + list.add(set); + } + +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java new file mode 100644 index 000000000..40132290a --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java @@ -0,0 +1,499 @@ +// --- 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.profile; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.util.*; +import java.io.*; +import java.security.cert.*; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.authentication.AuthCredentials; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.logging.*; + +import netscape.security.x509.*; + + +/** + * This servlet is the base class of all profile servlets. + * + * @version $Revision$, $Date$ + */ +public class ProfileServlet extends CMSServlet { + + public final static String ARG_ERROR_CODE = "errorCode"; + public final static String ARG_ERROR_REASON = "errorReason"; + public final static String ARG_RECORD = "record"; + public final static String ARG_OP = "op"; + + public final static String ARG_REQUEST_LIST = "requestList"; + public final static String ARG_REQUEST_ID = "requestId"; + public final static String ARG_REQUEST_TYPE = "requestType"; + public final static String ARG_REQUEST_STATUS = "requestStatus"; + public final static String ARG_REQUEST_OWNER = + "requestOwner"; + public final static String ARG_REQUEST_CREATION_TIME = + "requestCreationTime"; + public final static String ARG_REQUEST_MODIFICATION_TIME = + "requestModificationTime"; + public final static String ARG_REQUEST_NONCE = "nonce"; + + public final static String ARG_AUTH_ID = "authId"; + public final static String ARG_AUTH_SYNTAX = "authSyntax"; + public final static String ARG_AUTH_CONSTRAINT = "authConstraint"; + public final static String ARG_AUTH_NAME = "authName"; + public final static String ARG_AUTH_LIST = "authList"; + public final static String ARG_AUTH_DESC = "authDesc"; + public final static String ARG_AUTH_IS_SSL = "authIsSSLClientRequired"; + public final static String ARG_PROFILE = "profile"; + public final static String ARG_REQUEST_NOTES = "requestNotes"; + public final static String ARG_PROFILE_ID = "profileId"; + public final static String ARG_RENEWAL_PROFILE_ID = "rprofileId"; + public final static String ARG_PROFILE_IS_ENABLED = "profileIsEnable"; + public final static String ARG_PROFILE_IS_VISIBLE = "profileIsVisible"; + public final static String ARG_PROFILE_ENABLED_BY = "profileEnableBy"; + public final static String ARG_PROFILE_APPROVED_BY = "profileApprovedBy"; + public final static String ARG_PROFILE_NAME = "profileName"; + public final static String ARG_PROFILE_DESC = "profileDesc"; + public final static String ARG_PROFILE_REMOTE_HOST = "profileRemoteHost"; + public final static String ARG_PROFILE_REMOTE_ADDR = "profileRemoteAddr"; + public final static String ARG_DEF_ID = "defId"; + public final static String ARG_DEF_SYNTAX = "defSyntax"; + public final static String ARG_DEF_CONSTRAINT = "defConstraint"; + public final static String ARG_DEF_NAME = "defName"; + public final static String ARG_DEF_VAL = "defVal"; + public final static String ARG_DEF_DESC = "defDesc"; + public final static String ARG_DEF_LIST = "defList"; + public final static String ARG_CON_DESC = "conDesc"; + public final static String ARG_CON_LIST = "constraint"; + public final static String ARG_CON_NAME = "name"; + public final static String ARG_CON_VALUE = "value"; + public final static String ARG_PROFILE_SET_ID = "profileSetId"; + public final static String ARG_POLICY_SET_ID = "setId"; + public final static String ARG_POLICY = "policy"; + public final static String ARG_POLICY_ID = "policyId"; + public final static String ARG_POLICY_SET_LIST = "policySetList"; + public final static String ARG_INPUT_PLUGIN_LIST = "inputPluginList"; + public final static String ARG_INPUT_PLUGIN_ID = "inputPluginId"; + public final static String ARG_INPUT_PLUGIN_NAME = "inputPluginName"; + public final static String ARG_INPUT_PLUGIN_DESC = "inputPluginDesc"; + public final static String ARG_INPUT_LIST = "inputList"; + public final static String ARG_INPUT_ID = "inputId"; + public final static String ARG_INPUT_SYNTAX = "inputSyntax"; + public final static String ARG_INPUT_CONSTRAINT = "inputConstraint"; + public final static String ARG_INPUT_NAME = "inputName"; + public final static String ARG_INPUT_VAL = "inputVal"; + public final static String ARG_IS_RENEWAL = "renewal"; + public final static String ARG_XML_OUTPUT = "xmlOutput"; + public final static String ARG_OUTPUT_LIST = "outputList"; + public final static String ARG_OUTPUT_ID = "outputId"; + public final static String ARG_OUTPUT_SYNTAX = "outputSyntax"; + public final static String ARG_OUTPUT_CONSTRAINT = "outputConstraint"; + public final static String ARG_OUTPUT_NAME = "outputName"; + public final static String ARG_OUTPUT_VAL = "outputVal"; + + private static final String PROP_TEMPLATE = "templatePath"; + private static final String PROP_AUTH_MGR_ID = "authMgrId"; + private final static String PROP_AUTHMGR = "AuthMgr"; + private final static String PROP_CLIENTAUTH = "GetClientCert"; + private static final String PROP_PROFILE_SUB_ID = "profileSubId"; + private static final String PROP_ID = "ID"; + public final static String PROP_RESOURCEID = "resourceID"; + public final static String AUTHZ_SRC_LDAP = "ldap"; + public final static String AUTHZ_SRC_TYPE = "sourceType"; + public final static String AUTHZ_CONFIG_STORE = "authz"; + public final static String AUTHZ_SRC_XML = "web.xml"; + public final static String PROP_AUTHZ_MGR = "AuthzMgr"; + public final static String PROP_ACL = "ACLinfo"; + public final static String AUTHZ_MGR_BASIC = "BasicAclAuthz"; + public final static String AUTHZ_MGR_LDAP = "DirAclAuthz"; + + private final static String HDR_LANG = "accept-language"; + + private String mTemplate = null; + private String mAuthMgrId = null; + + protected String mId = null; + protected String mGetClientCert = "false"; + protected String mAuthMgr = null; + protected IAuthzSubsystem mAuthz = null; + protected String mAclMethod = null; + protected String mAuthzResourceName = null; + protected ILogger mLogger = CMS.getLogger(); + protected int mLogCategory = ILogger.S_OTHER; + protected String mProfileSubId = null; + + protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger(); + + public ProfileServlet() { + super(); + } + + /** + * initialize the servlet. Servlets implementing this method + * must specify the template to use as a parameter called + * "templatePath" in the servletConfig + * + * @param sc servlet configuration, read from the web.xml file + */ + + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mTemplate = sc.getServletContext().getRealPath( + sc.getInitParameter(PROP_TEMPLATE)); + mGetClientCert = sc.getInitParameter(PROP_CLIENTAUTH); + mAuthMgr = sc.getInitParameter(PROP_AUTHMGR); + mAuthz = (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ); + mAuthzResourceName = sc.getInitParameter(PROP_RESOURCEID); + mProfileSubId = sc.getInitParameter(PROP_PROFILE_SUB_ID); + mId = sc.getInitParameter(PROP_ID); + + try { + mAclMethod = Utils.initializeAuthz(sc, mAuthz, mId); + } catch (ServletException e) { + log(ILogger.LL_FAILURE, e.toString()); + throw e; + } + } + + protected String escapeXML(String v) + { + if (v == null) { + return ""; + } + v = v.replaceAll("&", "&"); + return v; + } + + protected void outputArgValueAsXML(PrintStream ps, String name, IArgValue v) + { + ps.println("<" + name + ">"); + if (v != null) { + if (v instanceof ArgList) { + ArgList list = (ArgList)v; + ps.println(""); + for (int i = 0; i < list.size(); i++) { + outputArgValueAsXML(ps, name, list.get(i)); + } + ps.println(""); + } else if (v instanceof ArgString) { + ArgString str = (ArgString)v; + ps.println(escapeXML(str.getValue())); + } else if (v instanceof ArgSet) { + ArgSet set = (ArgSet)v; + ps.println(""); + Enumeration names = set.getNames(); + while (names.hasMoreElements()) { + String n = (String)names.nextElement(); + outputArgValueAsXML(ps, n, set.get(n)); + } + ps.println(""); + } else { + ps.println(v); + } + } + ps.println(""); + } + + protected void outputThisAsXML(ByteArrayOutputStream bos, ArgSet args) + { + PrintStream ps = new PrintStream(bos); + ps.println(""); + outputArgValueAsXML(ps, "output", args); + ps.println(""); + ps.flush(); + } + + public void outputTemplate(HttpServletRequest request, + HttpServletResponse response, ArgSet args) + throws EBaseException { + + String xmlOutput = request.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + response.setContentType("text/xml"); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + outputThisAsXML(bos, args); + try { + response.setContentLength(bos.size()); + bos.writeTo(response.getOutputStream()); + } catch (Exception e) { + CMS.debug("outputTemplate error " + e); + } + return; + } + IStatsSubsystem statsSub = (IStatsSubsystem)CMS.getSubsystem("stats"); + if (statsSub != null) { + statsSub.startTiming("output_template"); + } + BufferedReader reader = null; + try { + reader = new BufferedReader( + new FileReader(mTemplate)); + + response.setContentType("text/html; charset=UTF-8"); + + PrintWriter writer = response.getWriter(); + + + // output template + String line = null; + + do { + line = reader.readLine(); + if (line != null) { + if (line.indexOf("") == -1) { + writer.println(line); + } else { + // output javascript parameters + writer.println(""); + } + } + } + while (line != null); + reader.close(); + } catch (IOException e) { + CMS.debug(e); + throw new EBaseException(e.toString()); + } finally { + if (statsSub != null) { + statsSub.endTiming("output_template"); + } + } + } + + protected void outputArgList(PrintWriter writer, String name, ArgList list) + throws IOException { + + String h_name = null; + + if (name.indexOf('.') == -1) { + h_name = name; + } else { + h_name = name.substring(name.indexOf('.') + 1); + } + writer.println(name + "Set = new Array;"); + // writer.println(h_name + "Count = 0;"); + + for (int i = 0; i < list.size(); i++) { + writer.println(h_name + " = new Object;"); + IArgValue val = list.get(i); + + if (val instanceof ArgString) { + ArgString str = (ArgString) val; + + outputArgString(writer, name, str); + } else if (val instanceof ArgSet) { + ArgSet set = (ArgSet) val; + + outputArgSet(writer, h_name, set); + writer.println(name + "Set[" + i + "] = " + h_name + ";"); + } + } + } + + protected String escapeJavaScriptString(String v) { + int l = v.length(); + char in[] = new char[l]; + char out[] = new char[l * 4]; + int j = 0; + + v.getChars(0, l, in, 0); + + for (int i = 0; i < l; i++) { + char c = in[i]; + + /* presumably this gives better performance */ + if ((c > 0x23) && (c != 0x5c)) { + out[j++] = c; + continue; + } + + /* some inputs are coming in as '\' and 'n' */ + /* see BZ 500736 for details */ + if ((c == 0x5c) && ((i+1)': + out[j++] = '\\'; + out[j++] = 'x'; + out[j++] = '3'; + out[j++] = 'e'; + break; + + default: + out[j++] = c; + } + } + return new String(out, 0, j); + } + + protected void outputArgString(PrintWriter writer, String name, ArgString str) + throws IOException { + String s = str.getValue(); + + // sub \n with "\n" + if (s != null) { + s = escapeJavaScriptString(s); + } + writer.println(name + "=\"" + s + "\";"); + } + + protected void outputArgSet(PrintWriter writer, String name, ArgSet set) + throws IOException { + Enumeration e = set.getNames(); + + while (e.hasMoreElements()) { + String n = (String) e.nextElement(); + IArgValue val = set.get(n); + + if (val instanceof ArgSet) { + ArgSet set1 = (ArgSet) val; + + outputArgSet(writer, name + "." + n, set1); + } else if (val instanceof ArgList) { + ArgList list = (ArgList) val; + + outputArgList(writer, name + "." + n, list); + } else if (val instanceof ArgString) { + ArgString str = (ArgString) val; + + outputArgString(writer, name + "." + n, str); + } + } + } + + protected void outputData(PrintWriter writer, ArgSet set) + throws IOException { + if (set == null) + return; + Enumeration e = set.getNames(); + + while (e.hasMoreElements()) { + String n = (String) e.nextElement(); + IArgValue val = set.get(n); + + if (val instanceof ArgSet) { + ArgSet set1 = (ArgSet) val; + + outputArgSet(writer, n, set1); + } else if (val instanceof ArgList) { + ArgList list = (ArgList) val; + + outputArgList(writer, n, list); + } else if (val instanceof ArgString) { + ArgString str = (ArgString) val; + + outputArgString(writer, n, str); + } + } + } + + /** + * log according to authority category. + */ + protected void log(int event, int level, String msg) { + mLogger.log(event, mLogCategory, level, + "Servlet " + mId + ": " + msg); + } + + protected void log(int level, String msg) { + mLogger.log(ILogger.EV_SYSTEM, mLogCategory, level, + "Servlet " + mId + ": " + msg); + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader(HDR_LANG); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } + + protected void renderResult(CMSRequest cmsReq) + throws IOException { + // do nothing + } +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java new file mode 100644 index 000000000..27280d4e5 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java @@ -0,0 +1,877 @@ +// --- 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.profile; + + +import java.util.*; +import java.security.cert.*; +import java.io.*; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.logging.*; +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.common.AuthCredentials; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.pkix.cmc.*; + +import netscape.security.x509.*; + + +/** + * This servlet submits end-user request into the profile framework. + * + * @version $Revision$, $Date$ + */ +public class ProfileSubmitCMCServlet extends ProfileServlet { + + private static final String ARG_AUTH_TOKEN = "auth_token"; + private static final String PROP_PROFILE_ID = "profileId"; + private static final String PROP_AUTHORITY_ID = "authorityId"; + + private String mOutputTemplateClassName = null; + private String mProfileId = null; + private String mProfileSubId = null; + private String mReqType = null; + private String mAuthorityId = null; + private String requestBinary = null; + private String requestB64 = null; + + private final static String[] + SIGNED_AUDIT_AUTOMATED_REJECTION_REASON = new String[] { + + /* 0 */ "automated profile cert request rejection: " + + "indeterminate reason for inability to process " + + "cert request due to an EBaseException" + }; + private final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5"; + + public ProfileSubmitCMCServlet() { + } + + /** + * initialize the servlet. And instance of this servlet can + * be set up to always issue certificates against a certain profile + * by setting the 'profileId' configuration in the servletConfig + * If not, the user must specify the profileID when submitting the request + * + * "ImportCert.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID); + mProfileId = sc.getInitParameter(PROP_PROFILE_ID); + mOutputTemplateClassName = sc.getInitParameter("outputTemplateClass"); + mRenderResult = false; + } + + private void setInputsIntoContext(HttpServletRequest request, IProfile profile, IProfileContext ctx) { + + // passing inputs into context + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration inputNames = profileInput.getValueNames(); + + while (inputNames.hasMoreElements()) { + String inputName = (String) inputNames.nextElement(); + + if (request.getParameter(inputName) != null) { + ctx.set(inputName, request.getParameter(inputName)); + } + } + } + } + + } + + private void setCredentialsIntoContext(HttpServletRequest request, IProfileAuthenticator authenticator, IProfileContext ctx) { + Enumeration authIds = authenticator.getValueNames(); + + if (authIds != null) { + while (authIds.hasMoreElements()) { + String authName = (String) authIds.nextElement(); + + if (request.getParameter(authName) != null) { + ctx.set(authName, request.getParameter(authName)); + } + } + } + } + + public IAuthToken authenticate(IProfileAuthenticator authenticator, + HttpServletRequest request) throws EBaseException { + AuthCredentials credentials = new AuthCredentials(); + + // build credential + Enumeration authNames = authenticator.getValueNames(); + + if (authNames != null) { + while (authNames.hasMoreElements()) { + String authName = (String) authNames.nextElement(); + + if (authName.equals("cert_request")) + credentials.set(authName, requestB64); + else + credentials.set(authName, request.getParameter(authName)); + } + } + IAuthToken authToken = authenticator.authenticate(credentials); + + SessionContext sc = SessionContext.getContext(); + if (sc != null) { + sc.put(SessionContext.AUTH_MANAGER_ID, authenticator.getName()); + String userid = authToken.getInString(IAuthToken.USER_ID); + if (userid != null) { + sc.put(SessionContext.USER_ID, userid); + } + } + + return authToken; + } + + private void setInputsIntoRequest(HttpServletRequest request, IProfile +profile, IRequest req) { + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration inputNames = profileInput.getValueNames(); + + if (inputNames != null) { + while (inputNames.hasMoreElements()) { + String inputName = (String) inputNames.nextElement(); + + if (request.getParameter(inputName) != null) { + req.setExtData(inputName, request.getParameter(inputName)); + } + } + } + } + } + } + + /** + * Process the HTTP request + *

+ * + * (Certificate Request Processed - either an automated "EE" profile based + * cert acceptance, or an automated "EE" profile based cert rejection) + *

+ * + *

    + *
  • http.param profileId ID of profile to use to process request + *
  • signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a + * certificate request has just been through the approval process + *
+ * @param cmsReq the object holding the request and response information + * @exception EBaseException an error has occurred + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest request = cmsReq.getHttpReq(); + HttpServletResponse response = cmsReq.getHttpResp(); + + Locale locale = getLocale(request); + ArgSet args = new ArgSet(); + String cert_request_type = + mServletConfig.getInitParameter("cert_request_type"); + String outputFormat = mServletConfig.getInitParameter("outputFormat"); + + int reqlen = request.getContentLength(); + InputStream is = null; + try { + is = request.getInputStream(); + } catch (Exception ee) { + } + byte reqbuf[] = new byte[reqlen]; + int bytesread = 0; + boolean partial = false; + + while (bytesread < reqlen) { + try { + bytesread += is.read(reqbuf, bytesread, reqlen - bytesread); + } catch (Exception ee) { + } + + if (partial == false) { + if (bytesread < reqlen) + partial = true; + } + } + + requestB64 = com.netscape.osutil.OSUtil.BtoA(reqbuf); + + if (CMS.debugOn()) { + CMS.debug("Start of ProfileSubmitCMCServlet Input Parameters"); + Enumeration paramNames = request.getParameterNames(); + + while (paramNames.hasMoreElements()) { + String paramName = (String) paramNames.nextElement(); + // added this facility so that password can be hidden, + // all sensitive parameters should be prefixed with + // __ (double underscores); however, in the event that + // a security parameter slips through, we perform multiple + // additional checks to insure that it is NOT displayed + if( paramName.startsWith("__") || + paramName.endsWith("password") || + paramName.endsWith("passwd") || + paramName.endsWith("pwd") || + paramName.equalsIgnoreCase("admin_password_again") || + paramName.equalsIgnoreCase("directoryManagerPwd") || + paramName.equalsIgnoreCase("bindpassword") || + paramName.equalsIgnoreCase("bindpwd") || + paramName.equalsIgnoreCase("passwd") || + paramName.equalsIgnoreCase("password") || + paramName.equalsIgnoreCase("pin") || + paramName.equalsIgnoreCase("pwd") || + paramName.equalsIgnoreCase("pwdagain") || + paramName.equalsIgnoreCase("uPasswd") ) { + CMS.debug("ProfileSubmitCMCServlet Input Parameter " + + paramName + "='(sensitive)'"); + } else { + CMS.debug("ProfileSubmitCMCServlet Input Parameter " + + paramName + "='" + + request.getParameter(paramName) + "'"); + } + } + CMS.debug("End of ProfileSubmitCMCServlet Input Parameters"); + } + + CMS.debug("ProfileSubmitCMCServlet: start serving"); + + if (mProfileSubId == null || mProfileSubId.equals("")) { + mProfileSubId = IProfileSubsystem.ID; + } + CMS.debug("ProfileSubmitCMCServlet: SubId=" + mProfileSubId); + IProfileSubsystem ps = (IProfileSubsystem) + CMS.getSubsystem(mProfileSubId); + + if (ps == null) { + CMS.debug("ProfileSubmitCMCServlet: ProfileSubsystem not found"); + CMCOutputTemplate template = new CMCOutputTemplate(); + SEQUENCE seq = new SEQUENCE(); + seq.addElement(new INTEGER(0)); + UTF8String s = null; + try { + s = new UTF8String(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR")); + } catch (Exception ee) { + } + template.createFullResponseWithFailedStatus(response, seq, + OtherInfo.INTERNAL_CA_ERROR, s); + return; + } + + // if we did not configure profileId in xml file, + // then accept the user-provided one + String profileId = null; + + if (mProfileId == null) { + profileId = request.getParameter("profileId"); + } else { + profileId = mProfileId; + } + + IProfile profile = null; + + try { + CMS.debug("ProfileSubmitCMCServlet: profileId " + profileId); + profile = ps.getProfile(profileId); + } catch (EProfileException e) { + CMS.debug("ProfileSubmitCMCServlet: profile not found profileId " + + profileId + " " + e.toString()); + } + if (profile == null) { + CMCOutputTemplate template = new CMCOutputTemplate(); + SEQUENCE seq = new SEQUENCE(); + seq.addElement(new INTEGER(0)); + UTF8String s = null; + try { + s = new UTF8String(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId)); + } catch (Exception ee) { + } + template.createFullResponseWithFailedStatus(response, seq, + OtherInfo.INTERNAL_CA_ERROR, s); + return; + } + + if (!ps.isProfileEnable(profileId)) { + CMS.debug("ProfileSubmitCMCServlet: Profile " + profileId + + " not enabled"); + CMCOutputTemplate template = new CMCOutputTemplate(); + SEQUENCE seq = new SEQUENCE(); + seq.addElement(new INTEGER(0)); + UTF8String s = null; + try { + s = new UTF8String(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId)); + } catch (Exception ee) { + } + template.createFullResponseWithFailedStatus(response, seq, + OtherInfo.INTERNAL_CA_ERROR, s); + return; + } + + IProfileContext ctx = profile.createContext(); + if (requestB64 != null) { + ctx.set("cert_request_type", cert_request_type); + ctx.set("cert_request", requestB64); + } + // passing auths into context + IProfileAuthenticator authenticator = null; + + try { + authenticator = profile.getAuthenticator(); + } catch (EProfileException e) { + // authenticator not installed correctly + } + if (authenticator == null) { + CMS.debug("ProfileSubmitCMCServlet: authenticator not found"); + } else { + CMS.debug("ProfileSubmitCMCServlet: authenticator " + + authenticator.getName() + " found"); + setCredentialsIntoContext(request, authenticator, ctx); + } + + setInputsIntoContext(request, profile, ctx); + CMS.debug("ProfileSubmistServlet: set Inputs into Context"); + + // before creating the request, authenticate the request + + IAuthToken authToken = null; + + // for ssl authentication; pass in servlet for retrieving + // ssl client certificates + SessionContext context = SessionContext.getContext(); + + // insert profile context so that input parameter can be retrieved + context.put("profileContext", ctx); + context.put("sslClientCertProvider", + new SSLClientCertProvider(request)); + CMS.debug("ProfileSubmitCMCServlet: set sslClientCertProvider"); + if (authenticator != null) { + try { + authToken = authenticate(authenticator, request); + // authentication success + } catch (EBaseException e) { + CMCOutputTemplate template = new CMCOutputTemplate(); + SEQUENCE seq = new SEQUENCE(); + seq.addElement(new INTEGER(0)); + UTF8String s = null; + try { + s = new UTF8String(e.toString()); + } catch (Exception ee) { + } + template.createFullResponseWithFailedStatus(response, seq, + OtherInfo.BAD_REQUEST, s); + CMS.debug("ProfileSubmitCMCServlet: authentication error " + + e.toString()); + return; + } + + //authorization only makes sense when request is authenticated + AuthzToken authzToken = null; + if (authToken != null) { + CMS.debug("ProfileSubmitCMCServlet authToken not null"); + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "submit"); + } catch (Exception e) { + CMS.debug("ProfileSubmitCMCServlet authorization failure: "+e.toString()); + } + } + + if (authzToken == null) { + CMS.debug("ProfileSubmitCMCServlet authorization failure: authzToken is null"); + CMCOutputTemplate template = new CMCOutputTemplate(); + SEQUENCE seq = new SEQUENCE(); + seq.addElement(new INTEGER(0)); + UTF8String s = null; + try { + s = new UTF8String("ProfileSubmitCMCServlet authorization failure"); + } catch (Exception ee) { + } + template.createFullResponseWithFailedStatus(response, seq, + OtherInfo.BAD_REQUEST, s); + return; + } + } + + IRequest reqs[] = null; + + /////////////////////////////////////////////// + // create request + /////////////////////////////////////////////// + try { + reqs = profile.createRequests(ctx, locale); + } catch (EProfileException e) { + CMS.debug("ProfileSubmitCMCServlet: createRequests " + e.toString()); + CMCOutputTemplate template = new CMCOutputTemplate(); + SEQUENCE seq = new SEQUENCE(); + seq.addElement(new INTEGER(0)); + UTF8String s = null; + try { + s = new UTF8String(e.toString()); + } catch (Exception ee) { + } + template.createFullResponseWithFailedStatus(response, seq, + OtherInfo.INTERNAL_CA_ERROR, s); + return; + } catch (Throwable e) { + CMS.debug("ProfileSubmitCMCServlet: createRequests " + e.toString()); + CMCOutputTemplate template = new CMCOutputTemplate(); + SEQUENCE seq = new SEQUENCE(); + seq.addElement(new INTEGER(0)); + UTF8String s = null; + try { + s = new UTF8String(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR")); + } catch (Exception ee) { + } + template.createFullResponseWithFailedStatus(response, seq, + OtherInfo.INTERNAL_CA_ERROR, s); + return; + } + + TaggedAttribute attr = + (TaggedAttribute)(context.get(OBJECT_IDENTIFIER.id_cmc_lraPOPWitness)); + if (attr != null) { + boolean verifyAllow = true; + try { + verifyAllow = CMS.getConfigStore().getBoolean( + "cmc.lraPopWitness.verify.allow", true); + } catch (EBaseException ee) { + } + + if (!verifyAllow) { + LraPopWitness lraPop = null; + SET vals = attr.getValues(); + if (vals.size() > 0) { + try { + lraPop = (LraPopWitness)(ASN1Util.decode(LraPopWitness.getTemplate(), + ASN1Util.encode(vals.elementAt(0)))); + } catch (InvalidBERException e) { + CMS.debug( + CMS.getUserMessage(locale, "CMS_PROFILE_ENCODING_ERROR")); + } + + SEQUENCE bodyIds = lraPop.getBodyIds(); + + CMCOutputTemplate template = new CMCOutputTemplate(); + template.createFullResponseWithFailedStatus(response, bodyIds, + OtherInfo.POP_FAILED, null); + return; + } + } + } + + // for CMC, requests may be zero. Then check if controls exist. + if (reqs == null) { + Integer nums = (Integer)(context.get("numOfControls")); + CMCOutputTemplate template = new CMCOutputTemplate(); + // if there is only one control GetCert, then simple response + // must be returned. + if (nums != null && nums.intValue() == 1) { + TaggedAttribute attr1 = (TaggedAttribute)(context.get(OBJECT_IDENTIFIER.id_cmc_getCert)); + if (attr1 != null) { + template.createSimpleResponse(response, reqs); + } else + template.createFullResponse(response, reqs, + cert_request_type, null); + } else + template.createFullResponse(response, reqs, + cert_request_type, null); + return; + } + + String errorCode = null; + String errorReason = null; + + /////////////////////////////////////////////// + // populate request + /////////////////////////////////////////////// + for (int k = 0; k < reqs.length; k++) { + // adding parameters to request + setInputsIntoRequest(request, profile, reqs[k]); + + // serial auth token into request + if (authToken != null) { + Enumeration tokenNames = authToken.getElements(); + while (tokenNames.hasMoreElements()) { + String tokenName = (String)tokenNames.nextElement(); + String[] vals = authToken.getInStringArray(tokenName); + if (vals != null) { + for (int i = 0; i < vals.length; i++) { + reqs[k].setExtData(ARG_AUTH_TOKEN + "." + + tokenName + "[" + i + "]", vals[i]); + } + } else { + String val = authToken.getInString(tokenName); + if (val != null) { + reqs[k].setExtData(ARG_AUTH_TOKEN + "." + tokenName, + val); + } + } + } + } + + // put profile framework parameters into the request + reqs[k].setExtData(ARG_PROFILE, "true"); + reqs[k].setExtData(ARG_PROFILE_ID, profileId); + reqs[k].setExtData(ARG_PROFILE_APPROVED_BY, profile.getApprovedBy()); + String setId = profile.getPolicySetId(reqs[k]); + + if (setId == null) { + // no profile set found + CMCOutputTemplate template = new CMCOutputTemplate(); + SEQUENCE seq = new SEQUENCE(); + seq.addElement(new INTEGER(0)); + UTF8String s = null; + try { + s = new UTF8String(CMS.getUserMessage("CMS_PROFILE_NO_POLICY_SET_FOUND")); + } catch (Exception ee) { + } + template.createFullResponseWithFailedStatus(response, seq, + OtherInfo.INTERNAL_CA_ERROR, s); + return; + } + + CMS.debug("ProfileSubmitCMCServlet profileSetid=" + setId); + reqs[k].setExtData(ARG_PROFILE_SET_ID, setId); + reqs[k].setExtData(ARG_PROFILE_REMOTE_HOST, request.getRemoteHost()); + reqs[k].setExtData(ARG_PROFILE_REMOTE_ADDR, request.getRemoteAddr()); + + CMS.debug("ProfileSubmitCMCServlet: request " + + reqs[k].getRequestId().toString()); + + try { + CMS.debug("ProfileSubmitCMCServlet: populating request inputs"); + // give authenticator a chance to populate the request + if (authenticator != null) { + authenticator.populate(authToken, reqs[k]); + } + profile.populateInput(ctx, reqs[k]); + profile.populate(reqs[k]); + } catch (EProfileException e) { + CMS.debug("ProfileSubmitCMCServlet: populate " + e.toString()); + CMCOutputTemplate template = new CMCOutputTemplate(); + SEQUENCE seq = new SEQUENCE(); + seq.addElement(new INTEGER(0)); + UTF8String s = null; + try { + s = new UTF8String(e.toString()); + } catch (Exception ee) { + } + template.createFullResponseWithFailedStatus(response, seq, + OtherInfo.BAD_REQUEST, s); + return; + } catch (Throwable e) { + CMS.debug("ProfileSubmitCMCServlet: populate " + e.toString()); + // throw new IOException("Profile " + profileId + + // " cannot populate"); + CMCOutputTemplate template = new CMCOutputTemplate(); + SEQUENCE seq = new SEQUENCE(); + seq.addElement(new INTEGER(0)); + UTF8String s = null; + try { + s = new UTF8String(e.toString()); + } catch (Exception ee) { + } + template.createFullResponseWithFailedStatus(response, seq, + OtherInfo.INTERNAL_CA_ERROR, s); + return; + } + } + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = ILogger.UNIDENTIFIED; + String auditInfoCertValue = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + + int responseType = 0; + try { + /////////////////////////////////////////////// + // submit request + /////////////////////////////////////////////// + int error_codes[] = null; + if (reqs != null && reqs.length > 0) + error_codes = new int[reqs.length]; + for (int k = 0; k < reqs.length; k++) { + try { + // reset the "auditRequesterID" + auditRequesterID = auditRequesterID(reqs[k]); + + + // print request debug + if (reqs[k] != null) { + Enumeration reqKeys = reqs[k].getExtDataKeys(); + while (reqKeys.hasMoreElements()) { + String reqKey = (String)reqKeys.nextElement(); + String reqVal = reqs[k].getExtDataInString(reqKey); + if (reqVal != null) { + CMS.debug("ProfileSubmitCMCServlet: key=$request." + reqKey + "$ value=" + reqVal); + } + } + } + + profile.submit(authToken, reqs[k]); + reqs[k].setRequestStatus(RequestStatus.COMPLETE); + + // reset the "auditInfoCertValue" + auditInfoCertValue = auditInfoCertValue(reqs[k]); + + 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 (EDeferException e) { + // return defer message to the user + reqs[k].setRequestStatus(RequestStatus.PENDING); + // need to notify + INotify notify = profile.getRequestQueue().getPendingNotify(); + if (notify != null) { + notify.notify(reqs[k]); + } + + CMS.debug("ProfileSubmitCMCServlet: submit " + e.toString()); + errorCode = "2"; + errorReason = CMS.getUserMessage(locale, + "CMS_PROFILE_DEFERRED", + e.toString()); + } catch (ERejectException e) { + // return error to the user + reqs[k].setRequestStatus(RequestStatus.REJECTED); + CMS.debug("ProfileSubmitCMCServlet: submit " + e.toString()); + errorCode = "3"; + errorReason = CMS.getUserMessage(locale, + "CMS_PROFILE_REJECTED", + e.toString()); + } catch (Throwable e) { + // return error to the user + CMS.debug("ProfileSubmitCMCServlet: submit " + e.toString()); + errorCode = "1"; + errorReason = CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR"); + } + + try { + if (errorCode == null) { + profile.getRequestQueue().markAsServiced(reqs[k]); + } else { + profile.getRequestQueue().updateRequest(reqs[k]); + } + } catch (EBaseException e) { + CMS.debug("ProfileSubmitCMCServlet: updateRequest " + + e.toString()); + } + + if (errorCode != null) { + if (errorCode.equals("1")) { + // 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_REJECTION, + errorReason); + + audit(auditMessage); + } else if (errorCode.equals("2")) { + // do NOT store a message in the signed audit log file + // as this errorCode indicates that a process has been + // deferred for manual acceptance/cancellation/rejection + } else if (errorCode.equals("3")) { + // 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_REJECTION, + errorReason); + + audit(auditMessage); + } + error_codes[k] = Integer.parseInt(errorCode); + } else + error_codes[k] = 0; + } + + if (errorCode != null) { + // create the CMC full enrollment response + CMCOutputTemplate template = new CMCOutputTemplate(); + template.createFullResponse(response, reqs, cert_request_type, error_codes); + + return; + } + + /////////////////////////////////////////////// + // output output list + /////////////////////////////////////////////// + + CMS.debug("ProfileSubmitCMCServlet: done serving"); + CMCOutputTemplate template = new CMCOutputTemplate(); + if (cert_request_type.equals("pkcs10") || cert_request_type.equals("crmf")) { + + if (outputFormat != null &&outputFormat.equals("pkcs7")) { + byte[] pkcs7 = CMS.getPKCS7(locale, reqs[0]); + response.setContentType("application/pkcs7-mime"); + response.setContentLength(pkcs7.length); + try { + OutputStream os = response.getOutputStream(); + os.write(pkcs7); + os.flush(); + } catch (Exception ee) { + } + return; + } + template.createSimpleResponse(response, reqs); + } else if (cert_request_type.equals("cmc")) { + Integer nums = (Integer)(context.get("numOfControls")); + if (nums != null && nums.intValue() == 1) { + TaggedAttribute attr1 = + (TaggedAttribute)(context.get(OBJECT_IDENTIFIER.id_cmc_getCert)); + if (attr1 != null) { + template.createSimpleResponse(response, reqs); + return; + } + } + template.createFullResponse(response, reqs, cert_request_type, + error_codes); + } + } finally { + context.releaseContext(); + } + } + + /** + * Signed Audit Log Requester ID + * + * This method is called to obtain the "RequesterID" for + * a signed audit log message. + *

+ * + * @param request the actual request + * @return id string containing the signed audit log message RequesterID + */ + private String auditRequesterID(IRequest request) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String requesterID = ILogger.UNIDENTIFIED; + + if (request != null) { + // overwrite "requesterID" if and only if "id" != null + String id = request.getRequestId().toString(); + + if (id != null) { + requesterID = id.trim(); + } + } + + return requesterID; + } + + /** + * 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. + *

+ * + * @param request 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(); + + // extract all line separators from the "base64Data" + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < base64Data.length(); i++) { + if (!Character.isWhitespace(base64Data.charAt(i))) { + sb.append(base64Data.charAt(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; + } + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java new file mode 100644 index 000000000..389267678 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java @@ -0,0 +1,1530 @@ +// --- 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.profile; + + +import java.util.*; +import java.math.BigInteger; +import java.security.cert.*; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.logging.*; +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.common.AuthCredentials; +import com.netscape.cmsutil.xml.*; +import com.netscape.cmsutil.util.*; +import org.w3c.dom.*; +import netscape.security.x509.*; + + +/** + * This servlet submits end-user request into the profile framework. + * + * @author Christina Fu (renewal support) + * @version $Revision$, $Date$ + */ +public class ProfileSubmitServlet extends ProfileServlet { + + private static final String ARG_AUTH_TOKEN = "auth_token"; + private static final String ARG_REQUEST_OWNER = "requestOwner"; + private static final String PROP_PROFILE_ID = "profileId"; + private static final String PROP_AUTHORITY_ID = "authorityId"; + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + + private String mProfileId = null; + private String mProfileSubId = null; + private String mReqType = null; + private String mAuthorityId = null; + + private final static String[] + SIGNED_AUDIT_AUTOMATED_REJECTION_REASON = new String[] { + + /* 0 */ "automated profile cert request rejection: " + + "indeterminate reason for inability to process " + + "cert request due to an EBaseException" + }; + private final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5"; + + public ProfileSubmitServlet() { + } + + /** + * initialize the servlet. And instance of this servlet can + * be set up to always issue certificates against a certain profile + * by setting the 'profileId' configuration in the servletConfig + * If not, the user must specify the profileID when submitting the request + * + * "ImportCert.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID); + mProfileId = sc.getInitParameter(PROP_PROFILE_ID); + } + + private void setInputsIntoContext(HttpServletRequest request, IProfile profile, IProfileContext ctx) { + // passing inputs into context + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration inputNames = profileInput.getValueNames(); + + while (inputNames.hasMoreElements()) { + String inputName = (String) inputNames.nextElement(); + if (request.getParameter(inputName) != null) { + // all subject name parameters start with sn_, no other input parameters do + if (inputName.matches("^sn_.*")) { + ctx.set(inputName, escapeValueRfc1779(request.getParameter(inputName), false).toString()); + } else { + ctx.set(inputName, request.getParameter(inputName)); + } + } + } + } + } + + } + + /* + * fill input info from "request" to context. + * This is expected to be used by renewal where the request + * is retrieved from request record + */ + private void setInputsIntoContext(IRequest request, IProfile profile, IProfileContext ctx, Locale locale) { + // passing inputs into context + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration inputNames = profileInput.getValueNames(); + + while (inputNames.hasMoreElements()) { + String inputName = (String) inputNames.nextElement(); + String inputValue = ""; + CMS.debug("ProfileSubmitServlet: setInputsIntoContext() getting input name= " + inputName); + try { + inputValue = profileInput.getValue(inputName, locale, request); + } catch (Exception e) { + CMS.debug("ProfileSubmitServlet: setInputsIntoContext() getvalue() failed: " + e.toString()); + } + + if (inputValue != null) { + CMS.debug("ProfileSubmitServlet: setInputsIntoContext() setting value in ctx:"+ inputValue); + ctx.set(inputName, inputValue); + } else { + CMS.debug("ProfileSubmitServlet: setInputsIntoContext() value null"); + } + } + } + } + + } + + + + private void setCredentialsIntoContext(HttpServletRequest request, IProfileAuthenticator authenticator, IProfileContext ctx) { + Enumeration authIds = authenticator.getValueNames(); + + if (authIds != null) { + CMS.debug("ProfileSubmitServlet:setCredentialsIntoContext() authNames not null"); + while (authIds.hasMoreElements()) { + String authName = (String) authIds.nextElement(); + + CMS.debug("ProfileSubmitServlet:setCredentialsIntoContext() authName:"+ + authName); + if (request.getParameter(authName) != null) { + CMS.debug("ProfileSubmitServlet:setCredentialsIntoContext() authName found in request"); + ctx.set(authName, request.getParameter(authName)); + } else { + CMS.debug("ProfileSubmitServlet:setCredentialsIntoContext() authName not found in request"); + } + } + } else { + CMS.debug("ProfileSubmitServlet:setCredentialsIntoContext() authIds` null"); + } + } + + String getUidFromDN(String userdn) { + StringTokenizer st = new StringTokenizer(userdn, ","); + while (st.hasMoreTokens()) { + String t = st.nextToken(); + int i = t.indexOf("="); + + if (i == -1) { + continue; + } + String n = t.substring(0, i); + if (n.equalsIgnoreCase("uid")) { + String v = t.substring(i + 1); + CMS.debug("ProfileSubmitServlet:: getUidFromDN(): uid found:"+v); + return v; + } else { + continue; + } + } + return null; + } + + /* + * authenticate for renewal - more to add necessary params/values + * to the session context + */ + public IAuthToken authenticate(IProfileAuthenticator authenticator, + HttpServletRequest request, IRequest origReq, SessionContext context) + throws EBaseException { + IAuthToken authToken = authenticate(authenticator, request); + // For renewal, fill in necessary params + if (authToken!= null) { + String ouid = origReq.getExtDataInString("auth_token.uid"); + // if the orig cert was manually approved, then there was + // no auth token uid. Try to get the uid from the cert dn + // itself, if possible + if (ouid == null) { + String sdn = (String) context.get("origSubjectDN"); + if (sdn != null) { + ouid = getUidFromDN(sdn); + if (ouid != null) + CMS.debug("ProfileSubmitServlet: renewal: authToken original uid not found"); + } + } else { + CMS.debug("ProfileSubmitServlet: renewal: authToken original uid found in orig request auth_token"); + } + String auid = authToken.getInString("uid"); + if (auid != null) { // not through ssl client auth + CMS.debug("ProfileSubmitServlet: renewal: authToken uid found:"+auid); + // authenticated with uid + // put "orig_req.auth_token.uid" so that authz with + // UserOrigReqAccessEvaluator will work + if (ouid != null) { + context.put("orig_req.auth_token.uid", ouid); + CMS.debug("ProfileSubmitServlet: renewal: authToken original uid found:"+ouid); + } else { + CMS.debug("ProfileSubmitServlet: renewal: authToken original uid not found"); + } + } else { // through ssl client auth? + CMS.debug("ProfileSubmitServlet: renewal: authToken uid not found:"); + // put in orig_req's uid + if (ouid != null) { + CMS.debug("ProfileSubmitServlet: renewal: origReq uid not null:" +ouid+". Setting authtoken"); + authToken.set("uid", ouid); + context.put(SessionContext.USER_ID, ouid); + } else { + CMS.debug("ProfileSubmitServlet: renewal: origReq uid not found"); +// throw new EBaseException("origReq uid not found"); + } + } + + String userdn = origReq.getExtDataInString("auth_token.userdn"); + if (userdn != null) { + CMS.debug("ProfileSubmitServlet: renewal: origReq userdn not null:"+userdn+". Setting authtoken"); + authToken.set("userdn", userdn); + } else { + CMS.debug("ProfileSubmitServlet: renewal: origReq userdn not found"); +// throw new EBaseException("origReq userdn not found"); + } + } else { + CMS.debug("ProfileSubmitServlet: renewal: authToken null"); + } + return authToken; + } + + public IAuthToken authenticate(IProfileAuthenticator authenticator, + HttpServletRequest request) throws EBaseException { + AuthCredentials credentials = new AuthCredentials(); + + // build credential + Enumeration authNames = authenticator.getValueNames(); + + if (authNames != null) { + while (authNames.hasMoreElements()) { + String authName = (String) authNames.nextElement(); + + credentials.set(authName, request.getParameter(authName)); + } + } + + credentials.set("clientHost", request.getRemoteHost()); + IAuthToken authToken = authenticator.authenticate(credentials); + + SessionContext sc = SessionContext.getContext(); + if (sc != null) { + sc.put(SessionContext.AUTH_MANAGER_ID, authenticator.getName()); + String userid = authToken.getInString(IAuthToken.USER_ID); + if (userid != null) { + sc.put(SessionContext.USER_ID, userid); + } + } + + return authToken; + } + + private void setInputsIntoRequest(HttpServletRequest request, IProfile profile, IRequest req) { + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration inputNames = profileInput.getValueNames(); + + if (inputNames != null) { + while (inputNames.hasMoreElements()) { + String inputName = (String) inputNames.nextElement(); + + if (request.getParameter(inputName) != null) { + // special characters in subject names parameters must be escaped + if (inputName.matches("^sn_.*")) { + req.setExtData(inputName, escapeValueRfc1779(request.getParameter(inputName), false).toString()); + } else { + req.setExtData(inputName, request.getParameter(inputName)); + } + } + } + } + } + } + } + + /* + * fill input info from orig request to the renew request. + * This is expected to be used by renewal where the request + * is retrieved from request record + */ + private void setInputsIntoRequest(IRequest request, IProfile profile, IRequest req, Locale locale) { + // passing inputs into request + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration inputNames = profileInput.getValueNames(); + + while (inputNames.hasMoreElements()) { + String inputName = (String) inputNames.nextElement(); + String inputValue = ""; + CMS.debug("ProfileSubmitServlet: setInputsIntoRequest() getting input name= " + inputName); + try { + inputValue = profileInput.getValue(inputName, locale, request); + } catch (Exception e) { + CMS.debug("ProfileSubmitServlet: setInputsIntoRequest() getvalue() failed: " + e.toString()); + } + + if (inputValue != null) { + CMS.debug("ProfileSubmitServlet: setInputsIntoRequest() setting value in ctx:"+ inputValue); + req.setExtData(inputName, inputValue); + } else { + CMS.debug("ProfileSubmitServlet: setInputsIntoRequest() value null"); + } + } + } + } + + } + + private void setOutputIntoArgs(IProfile profile, ArgList outputlist, Locale locale, IRequest req) { + Enumeration outputIds = profile.getProfileOutputIds(); + + if (outputIds != null) { + while (outputIds.hasMoreElements()) { + String outputId = (String) outputIds.nextElement(); + IProfileOutput profileOutput = profile.getProfileOutput(outputId); + + Enumeration outputNames = profileOutput.getValueNames(); + + if (outputNames != null) { + while (outputNames.hasMoreElements()) { + ArgSet outputset = new ArgSet(); + String outputName = (String) outputNames.nextElement(); + IDescriptor outputDesc = + profileOutput.getValueDescriptor(locale, outputName); + + if (outputDesc == null) + continue; + String outputSyntax = outputDesc.getSyntax(); + String outputConstraint = outputDesc.getConstraint(); + String outputValueName = outputDesc.getDescription(locale); + String outputValue = null; + + try { + outputValue = profileOutput.getValue(outputName, + locale, req); + } catch (EProfileException e) { + CMS.debug("ProfileSubmitServlet: " + e.toString()); + } + + outputset.set(ARG_OUTPUT_ID, outputName); + outputset.set(ARG_OUTPUT_SYNTAX, outputSyntax); + outputset.set(ARG_OUTPUT_CONSTRAINT, outputConstraint); + outputset.set(ARG_OUTPUT_NAME, outputValueName); + outputset.set(ARG_OUTPUT_VAL, outputValue); + outputlist.add(outputset); + } + } + } + } + } + + /** + * Process the HTTP request + *

+ * + * (Certificate Request Processed - either an automated "EE" profile based + * cert acceptance, or an automated "EE" profile based cert rejection) + *

+ * + *

    + *
  • http.param profileId ID of profile to use to process request + *
  • signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a + * certificate request has just been through the approval process + *
+ * @param cmsReq the object holding the request and response information + * @exception EBaseException an error has occurred + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest request = cmsReq.getHttpReq(); + HttpServletResponse response = cmsReq.getHttpResp(); + boolean xmlOutput = false; + + String v = request.getParameter("xml"); + if ((v != null) && (v.equalsIgnoreCase("true"))) { + xmlOutput = true; + } + v = request.getParameter("xmlOutput"); + if ((v != null) && (v.equalsIgnoreCase("true"))) { + xmlOutput = true; + } + if (xmlOutput) { + CMS.debug("xmlOutput true"); + } else { + CMS.debug("xmlOutput false"); + } + + IStatsSubsystem statsSub = (IStatsSubsystem)CMS.getSubsystem("stats"); + if (statsSub != null) { + statsSub.startTiming("enrollment", true /* main action */); + } + + long startTime = CMS.getCurrentDate().getTime(); + Locale locale = getLocale(request); + ArgSet args = new ArgSet(); + + if (CMS.debugOn()) { + CMS.debug("Start of ProfileSubmitServlet Input Parameters"); + Enumeration paramNames = request.getParameterNames(); + + while (paramNames.hasMoreElements()) { + String paramName = (String) paramNames.nextElement(); + // added this facility so that password can be hidden, + // all sensitive parameters should be prefixed with + // __ (double underscores); however, in the event that + // a security parameter slips through, we perform multiple + // additional checks to insure that it is NOT displayed + if( paramName.startsWith("__") || + paramName.endsWith("password") || + paramName.endsWith("passwd") || + paramName.endsWith("pwd") || + paramName.equalsIgnoreCase("admin_password_again") || + paramName.equalsIgnoreCase("directoryManagerPwd") || + paramName.equalsIgnoreCase("bindpassword") || + paramName.equalsIgnoreCase("bindpwd") || + paramName.equalsIgnoreCase("passwd") || + paramName.equalsIgnoreCase("password") || + paramName.equalsIgnoreCase("pin") || + paramName.equalsIgnoreCase("pwd") || + paramName.equalsIgnoreCase("pwdagain") || + paramName.equalsIgnoreCase("uPasswd") ) { + CMS.debug("ProfileSubmitServlet Input Parameter " + + paramName + "='(sensitive)'"); + } else { + CMS.debug("ProfileSubmitServlet Input Parameter " + + paramName + "='" + + request.getParameter(paramName) + "'"); + } + } + CMS.debug("End of ProfileSubmitServlet Input Parameters"); + } + + CMS.debug("ProfileSubmitServlet: start serving"); + + if (mProfileSubId == null || mProfileSubId.equals("")) { + mProfileSubId = IProfileSubsystem.ID; + } + CMS.debug("ProfileSubmitServlet: SubId=" + mProfileSubId); + IProfileSubsystem ps = (IProfileSubsystem) + CMS.getSubsystem(mProfileSubId); + + if (ps == null) { + CMS.debug("ProfileSubmitServlet: ProfileSubsystem not found"); + if (xmlOutput) { + outputError(response, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + } else { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + } + if (statsSub != null) { + statsSub.endTiming("enrollment"); + } + return; + } + + /* + * Renewal - Renewal is retrofitted into the Profile Enrollment + * Framework. The authentication and authorization are taken from + * the renewal profile, while the input (with requests) and grace + * period constraint are taken from the original cert's request record. + * + * Things to note: + * * the renew request will contain the original profile instead + * of the new + * * there is no request for system and admin certs generated at + * time of installation configuration. + */ + String renewal = request.getParameter("renewal"); + boolean isRenewal = false; + if ((renewal!= null) && (renewal.equalsIgnoreCase("true"))) { + CMS.debug("ProfileSubmitServlet: isRenewal true"); + isRenewal = true; + request.setAttribute("reqType", (Object)"renewal"); + } else { + CMS.debug("ProfileSubmitServlet: isRenewal false"); + } + + String renewProfileId = null; + IRequest origReq = null; + Integer origSeqNum = 0; + + // if we did not configure profileId in xml file, + // then accept the user-provided one + String profileId = null; + + if (mProfileId == null) { + profileId = request.getParameter("profileId"); + } else { + profileId = mProfileId; + } + + CMS.debug("ProfileSubmitServlet: profileId " + profileId); + // This is the expiration date of the orig. cert that will + // be used in the RenewGracePeriodConstraint + Date origNotAfter = null; + String origSubjectDN = null; + + if (isRenewal) { + // dig up the original request to "clone" + renewProfileId = profileId; + CMS.debug("ProfileSubmitServlet: renewProfileId ="+renewProfileId); + IAuthority authority = (IAuthority) CMS.getSubsystem(mAuthorityId); + if (authority == null) { + CMS.debug("ProfileSubmitServlet: renewal: Authority " + mAuthorityId + + " not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + IRequestQueue queue = authority.getRequestQueue(); + + if (queue == null) { + CMS.debug("ProfileSubmitServlet: renewal: Request Queue of " + + mAuthorityId + " not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + + String serial = request.getParameter("serial_num"); + BigInteger certSerial = null; + // if serial number is sent with request, then the authentication + // method is not ssl client auth. In this case, an alternative + // authentication method is used (default: ldap based) + if (serial != null) { + CMS.debug("ProfileSubmitServlet: renewal: found serial_num"); + certSerial = new BigInteger(serial); + // usr_origreq evaluator should be used to authorize ownership + // of the cert + } else { + CMS.debug("ProfileSubmitServlet: renewal: serial_num not found, must do ssl client auth"); + // ssl client auth is to be used + // this is not authentication. Just use the cert to search + // for orig request and find the right profile + SSLClientCertProvider sslCCP = new SSLClientCertProvider(request); + X509Certificate[] certs = sslCCP.getClientCertificateChain(); + certSerial = null; + if (certs == null || certs.length == 0) { + CMS.debug("ProfileSubmitServlet: renewal: no ssl client cert chain"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } else { // has ssl client cert + CMS.debug("ProfileSubmitServlet: renewal: has ssl client cert chain"); + // shouldn't expect leaf cert to be always at the + // same location + X509Certificate clientCert = null; + for (int i = 0; i< certs.length; i++) { + clientCert = certs[i]; + byte [] extBytes = clientCert.getExtensionValue("2.5.29.19"); + // try to see if this is a leaf cert + // look for BasicConstraint extension + if (extBytes == null) { + // found leaf cert + CMS.debug("ProfileSubmitServlet: renewal: found leaf cert"); + break; + } else { + CMS.debug("ProfileSubmitServlet: renewal: found cert having BasicConstraints ext"); + // it's got BasicConstraints extension + // so it's not likely to be a leaf cert, + // however, check the isCA field regardless + try { + BasicConstraintsExtension bce = + new BasicConstraintsExtension(true, extBytes); + if (bce != null) { + if (!(Boolean)bce.get("is_ca")) { + CMS.debug("ProfileSubmitServlet: renewal: found CA cert in chain"); + break; + } // else found a ca cert, continue + } + } catch (Exception e) { + CMS.debug("ProfileSubmitServlet: renewal: exception:"+ + e.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + } + } + if (clientCert == null) { + CMS.debug("ProfileSubmitServlet: renewal: no client cert in chain"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + // convert to java X509 cert interface + try { + byte[] certEncoded = clientCert.getEncoded(); + + clientCert = new X509CertImpl(certEncoded); + } catch (Exception e) { + CMS.debug("ProfileSubmitServlet: renewal: exception:"+e.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + + certSerial = clientCert.getSerialNumber(); + } + } + + CMS.debug("ProfileSubmitServlet: renewal: serial number of cert to renew:"+ certSerial.toString()); + + try { + ICertificateRepository certDB = null; + if (authority instanceof ICertificateAuthority) { + certDB = ((ICertificateAuthority) authority).getCertificateRepository(); + } + if (certDB == null) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + ICertRecord rec = (ICertRecord) certDB.readCertificateRecord(certSerial); + if (rec == null) { + CMS.debug("ProfileSubmitServlet: renewal cert record not found for serial number "+ certSerial.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } else { + CMS.debug("ProfileSubmitServlet: renewal cert record found for serial number:"+ certSerial.toString()); + // check to see if the cert is revoked or revoked_expired + if ((rec.getStatus().equals(ICertRecord.STATUS_REVOKED)) || (rec.getStatus().equals(ICertRecord.STATUS_REVOKED_EXPIRED))) { + CMS.debug("ProfileSubmitServlet: renewal cert found to be revoked. Serial number = "+ certSerial.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_CA_CANNOT_RENEW_REVOKED_CERT", certSerial.toString())); + outputTemplate(request, response, args); + return; + } + MetaInfo metaInfo = (MetaInfo) rec.get(ICertRecord.ATTR_META_INFO); + // note: CA's internal certs don't have request ids + // so some other way needs to be done + if (metaInfo != null) { + String rid = (String) metaInfo.get(ICertRecord.META_REQUEST_ID); + + if (rid != null) { + origReq = queue.findRequest(new RequestId(rid)); + if (origReq != null) { + CMS.debug("ProfileSubmitServlet: renewal: found original enrollment request id:"+ rid); + // debug: print the extData keys + Enumeration en = origReq.getExtDataKeys(); +/* + CMS.debug("ProfileSubmitServlet: renewal: origRequest extdata key print BEGINS"); + while (en.hasMoreElements()) { + String next = (String) en.nextElement(); + CMS.debug("ProfileSubmitServlet: renewal: origRequest extdata key:"+ next); + } + CMS.debug("ProfileSubmitServlet: renewal: origRequest extdata key print ENDS"); +*/ + String requestorE = origReq.getExtDataInString("requestor_email"); + CMS.debug("ProfileSubmitServlet: renewal original requestor email="+requestorE); + profileId = origReq.getExtDataInString("profileId"); + if (profileId != null) + CMS.debug("ProfileSubmitServlet: renewal original profileId="+profileId); + else { + CMS.debug("ProfileSubmitServlet: renewal original profileId not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + origSeqNum = origReq.getExtDataInInteger(IEnrollProfile.REQUEST_SEQ_NUM); + + } else { //if origReq + CMS.debug("ProfileSubmitServlet: renewal original request not found for request id "+ rid); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + } else { + CMS.debug("ProfileSubmitServlet: renewal: cert record locating request id in MetaInfo failed for serial number "+ certSerial.toString()); + CMS.debug("ProfileSubmitServlet: renewal: cert may be bootstrapped system cert during installation/configuration - no request record exists"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR"+": original request not found")); + outputTemplate(request, response, args); + return; + } + } else { + CMS.debug("ProfileSubmitServlet: renewal: cert record locating MetaInfo failed for serial number "+ certSerial.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + // get orig cert expiration date + CMS.debug("ProfileSubmitServlet: renewal: before getting origNotAfter"); + X509CertImpl origCert = rec.getCertificate(); + origNotAfter = origCert.getNotAfter(); + CMS.debug("ProfileSubmitServlet: renewal: origNotAfter ="+ + origNotAfter.toString()); + origSubjectDN = origCert.getSubjectDN().getName(); + CMS.debug("ProfileSubmitServlet: renewal: orig subj dn ="+ + origSubjectDN); + } + } catch (Exception e) { + CMS.debug("ProfileSubmitServlet: renewal: exception:"+e.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + } // end isRenewal + + IProfile profile = null; + IProfile renewProfile = null; + + try { + profile = ps.getProfile(profileId); + if (isRenewal) { + // in case of renew, "profile" is the orig profile + // while "renewProfile" is the current profile used for renewal + renewProfile = ps.getProfile(renewProfileId); + } + } catch (EProfileException e) { + if(profile == null) { + CMS.debug("ProfileSubmitServlet: profile not found profileId " + + profileId + " " + e.toString()); + } + if (renewProfile == null) { + CMS.debug("ProfileSubmitServlet: profile not found renewProfileId " + + renewProfileId + " " + e.toString()); + } + } + if (profile == null) { + if (xmlOutput) { + outputError(response, CMS.getUserMessage(locale,"CMS_PROFILE_NOT_FOUND", profileId)); + } else { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_NOT_FOUND", profileId)); + outputTemplate(request, response, args); + } + return; + } + if (isRenewal && (renewProfile == null)) { + if (xmlOutput) { + outputError(response, CMS.getUserMessage(locale,"CMS_PROFILE_NOT_FOUND", renewProfileId)); + } else { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_NOT_FOUND", renewProfileId)); + outputTemplate(request, response, args); + } + return; + } + + if (!ps.isProfileEnable(profileId)) { + CMS.debug("ProfileSubmitServlet: Profile " + profileId + + " not enabled"); + if (xmlOutput) { + outputError(response, CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId)); + } else { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_NOT_FOUND", profileId)); + outputTemplate(request, response, args); + } + if (statsSub != null) { + statsSub.endTiming("enrollment"); + } + return; + } + + if (isRenewal) { + if (!ps.isProfileEnable(renewProfileId)) { + CMS.debug("ProfileSubmitServlet: renewal Profile " + renewProfileId + + " not enabled"); + if (xmlOutput) { + outputError(response, CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", renewProfileId)); + } else { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_NOT_FOUND", renewProfileId)); + outputTemplate(request, response, args); + } + return; + } + } + + IProfileContext ctx = profile.createContext(); + // passing auths into context + IProfileAuthenticator authenticator = null; + IProfileAuthenticator origAuthenticator = null; + + try { + if (isRenewal) { + authenticator = renewProfile.getAuthenticator(); + origAuthenticator = profile.getAuthenticator(); + } else { + authenticator = profile.getAuthenticator(); + } + } catch (EProfileException e) { + // authenticator not installed correctly + CMS.debug("ProfileSubmitServlet: renewal: exception:"+e.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + if (authenticator == null) { + CMS.debug("ProfileSubmitServlet: authenticator not found"); + } else { + CMS.debug("ProfileSubmitServlet: authenticator " + + authenticator.getName() + " found"); + setCredentialsIntoContext(request, authenticator, ctx); + } + + // for renewal, this will override or add auth info to the profile context + if (isRenewal) { + if (origAuthenticator!= null) { + CMS.debug("ProfileSubmitServlet: for renewal, original authenticator " + + origAuthenticator.getName() + " found"); + setCredentialsIntoContext(request, origAuthenticator, ctx); + } else { + CMS.debug("ProfileSubmitServlet: for renewal, original authenticator not found"); + } + } + + CMS.debug("ProfileSubmistServlet: set Inputs into profile Context"); + if (isRenewal) { + // for renewal, input needs to be retrieved from the orig req record + CMS.debug("ProfileSubmitServlet: set original Inputs into profile Context"); + setInputsIntoContext(origReq, profile, ctx, locale); + ctx.set(IEnrollProfile.CTX_RENEWAL, "true"); + ctx.set("renewProfileId", renewProfileId); + ctx.set(IEnrollProfile.CTX_RENEWAL_SEQ_NUM, origSeqNum.toString()); + } else { + setInputsIntoContext(request, profile, ctx); + } + + // before creating the request, authenticate the request + + IAuthToken authToken = null; + + // for ssl authentication; pass in servlet for retrieving + // ssl client certificates + SessionContext context = SessionContext.getContext(); + + // insert profile context so that input parameter can be retrieved + context.put("profileContext", ctx); + context.put("sslClientCertProvider", + new SSLClientCertProvider(request)); + CMS.debug("ProfileSubmitServlet: set sslClientCertProvider"); + if ((isRenewal == true) && (origSubjectDN != null)) + context.put("origSubjectDN", origSubjectDN); + if (statsSub != null) { + statsSub.startTiming("profile_authentication"); + } + if (authenticator != null) { + try { + if (isRenewal) { + CMS.debug("ProfileSubmitServlet: renewal authenticate begins"); + authToken = authenticate(authenticator, request, origReq, context); + CMS.debug("ProfileSubmitServlet: renewal authenticate ends"); + } else { + authToken = authenticate(authenticator, request); + } + } catch (EBaseException e) { + CMS.debug("ProfileSubmitServlet: authentication error " + + e.toString()); + // authentication error + if (xmlOutput) { + outputError(response, CMS.getUserMessage(locale, "CMS_AUTHENTICATION_ERROR")); + } else { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHENTICATION_ERROR")); + outputTemplate(request, response, args); + } + if (statsSub != null) { + statsSub.endTiming("authentication"); + } + if (statsSub != null) { + statsSub.endTiming("enrollment"); + } + return; + } + } + if (statsSub != null) { + statsSub.endTiming("profile_authentication"); + } + + // authentication success + if (authToken != null) { + CMS.debug("ProfileSubmitServlet authToken not null"); + // do profile authorization + String acl = null; + if (isRenewal) + acl = renewProfile.getAuthzAcl(); + else + acl = profile.getAuthzAcl(); + CMS.debug("ProfileSubmitServlet: authz using acl: "+acl); + if (acl != null && acl.length() > 0) { + try { + AuthzToken authzToken = authorize(mAclMethod, authToken, acl); + } catch (Exception e) { + CMS.debug("ProfileSubmitServlet authorize: "+e.toString()); + if (xmlOutput) { + outputError(response, CMS.getUserMessage(locale, + "CMS_AUTHORIZATION_ERROR")); + } else { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHORIZATION_ERROR")); + outputTemplate(request, response, args); + } + + return; + } + } + } + + IRequest reqs[] = null; + + if (statsSub != null) { + statsSub.startTiming("request_population"); + } + /////////////////////////////////////////////// + // create request + /////////////////////////////////////////////// + try { + reqs = profile.createRequests(ctx, locale); + } catch (EProfileException e) { + CMS.debug(e); + CMS.debug("ProfileSubmitServlet: createRequests " + e.toString()); + if (xmlOutput) { + outputError(response, e.toString()); + } else { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, e.toString()); + outputTemplate(request, response, args); + } + if (statsSub != null) { + statsSub.endTiming("request_population"); + statsSub.endTiming("enrollment"); + } + return; + } catch (Throwable e) { + CMS.debug(e); + CMS.debug("ProfileSubmitServlet: createRequests " + e.toString()); + if (xmlOutput) { + outputError(response, CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR")); + } else { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + } + if (statsSub != null) { + statsSub.endTiming("request_population"); + statsSub.endTiming("enrollment"); + } + return; + } + + String errorCode = null; + String errorReason = null; + + /////////////////////////////////////////////// + // populate request + /////////////////////////////////////////////// + for (int k = 0; k < reqs.length; k++) { + boolean fromRA = false; + String uid = ""; + + // adding parameters to request + if (isRenewal) { + setInputsIntoRequest(origReq, profile, reqs[k], locale); + // set orig expiration date to be used in Validity constraint + reqs[k].setExtData("origNotAfter", + BigInteger.valueOf(origNotAfter.getTime())); + // set subjectDN to be used in subject name default + reqs[k].setExtData(IProfileAuthenticator.AUTHENTICATED_NAME, origSubjectDN); + // set request type + reqs[k].setRequestType("renewal"); + } else + setInputsIntoRequest(request, profile, reqs[k]); + + // serial auth token into request + if (authToken != null) { + Enumeration tokenNames = authToken.getElements(); + while (tokenNames.hasMoreElements()) { + String tokenName = (String) tokenNames.nextElement(); + String[] tokenVals = authToken.getInStringArray(tokenName); + if (tokenVals != null) { + for (int i = 0; i < tokenVals.length; i++) { + reqs[k].setExtData(ARG_AUTH_TOKEN + "." + + tokenName + "[" + i + "]", tokenVals[i]); + } + } else { + String tokenVal = authToken.getInString(tokenName); + if (tokenVal != null) { + reqs[k].setExtData(ARG_AUTH_TOKEN + "." + tokenName, + tokenVal); + // if RA agent, auto assign the request + if (tokenName.equals("uid")) + uid = tokenVal; + if (tokenName.equals("group") && + tokenVal.equals("Registration Manager Agents")) { + fromRA = true; + } + } + } + } + } + + if (fromRA) { + CMS.debug("ProfileSubmitServlet: request from RA: "+ uid); + reqs[k].setExtData(ARG_REQUEST_OWNER, uid); + } + + // put profile framework parameters into the request + reqs[k].setExtData(ARG_PROFILE, "true"); + reqs[k].setExtData(ARG_PROFILE_ID, profileId); + if (isRenewal) + reqs[k].setExtData(ARG_RENEWAL_PROFILE_ID, request.getParameter("profileId")); + reqs[k].setExtData(ARG_PROFILE_APPROVED_BY, profile.getApprovedBy()); + String setId = profile.getPolicySetId(reqs[k]); + + if (setId == null) { + // no profile set found + CMS.debug("ProfileSubmitServlet: no profile policy set found"); + if (xmlOutput) { + outputError(response, FAILED, CMS.getUserMessage("CMS_PROFILE_NO_POLICY_SET_FOUND"), reqs[k].getRequestId().toString()); + } else { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, + CMS.getUserMessage("CMS_PROFILE_NO_POLICY_SET_FOUND")); + outputTemplate(request, response, args); + } + if (statsSub != null) { + statsSub.endTiming("request_population"); + statsSub.endTiming("enrollment"); + } + return; + } + + CMS.debug("ProfileSubmitServlet profileSetid=" + setId); + reqs[k].setExtData(ARG_PROFILE_SET_ID, setId); + reqs[k].setExtData(ARG_PROFILE_REMOTE_HOST, request.getRemoteHost()); + reqs[k].setExtData(ARG_PROFILE_REMOTE_ADDR, request.getRemoteAddr()); + + CMS.debug("ProfileSubmitServlet: request " + + reqs[k].getRequestId().toString()); + + try { + CMS.debug("ProfileSubmitServlet: populating request inputs"); + // give authenticator a chance to populate the request + if (authenticator != null) { + authenticator.populate(authToken, reqs[k]); + } + profile.populateInput(ctx, reqs[k]); + profile.populate(reqs[k]); + } catch (EProfileException e) { + CMS.debug("ProfileSubmitServlet: populate " + e.toString()); + if (xmlOutput) { + outputError(response, FAILED, e.toString(), reqs[k].getRequestId().toString()); + } else { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, e.toString()); + outputTemplate(request, response, args); + } + if (statsSub != null) { + statsSub.endTiming("request_population"); + statsSub.endTiming("enrollment"); + } + return; + } catch (Throwable e) { + CMS.debug("ProfileSubmitServlet: populate " + e.toString()); + // throw new IOException("Profile " + profileId + + // " cannot populate"); + if (xmlOutput) { + outputError(response, FAILED, CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR"), reqs[k].getRequestId().toString()); + } else { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + } + if (statsSub != null) { + statsSub.endTiming("request_population"); + statsSub.endTiming("enrollment"); + } + return; + } + } + if (statsSub != null) { + statsSub.endTiming("request_population"); + } + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = ILogger.UNIDENTIFIED; + String auditInfoCertValue = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + + try { + /////////////////////////////////////////////// + // submit request + /////////////////////////////////////////////// + String requestIds = ""; // deliminated with double space + for (int k = 0; k < reqs.length; k++) { + try { + // reset the "auditRequesterID" + auditRequesterID = auditRequesterID(reqs[k]); + + // print request debug + if (reqs[k] != null) { + requestIds += " "+reqs[k].getRequestId().toString(); + Enumeration reqKeys = reqs[k].getExtDataKeys(); + while (reqKeys.hasMoreElements()) { + String reqKey = (String)reqKeys.nextElement(); + String reqVal = reqs[k].getExtDataInString(reqKey); + if (reqVal != null) { + CMS.debug("ProfileSubmitServlet: key=$request." + reqKey + "$ value=" + reqVal); + } + } + } + + profile.submit(authToken, reqs[k]); + reqs[k].setRequestStatus(RequestStatus.COMPLETE); + + // reset the "auditInfoCertValue" + auditInfoCertValue = auditInfoCertValue(reqs[k]); + + 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 (EDeferException e) { + // return defer message to the user + reqs[k].setRequestStatus(RequestStatus.PENDING); + // need to notify + INotify notify = profile.getRequestQueue().getPendingNotify(); + if (notify != null) { + notify.notify(reqs[k]); + } + + CMS.debug("ProfileSubmitServlet: submit " + e.toString()); + errorCode = "2"; + errorReason = CMS.getUserMessage(locale, + "CMS_PROFILE_DEFERRED", + e.toString()); + } catch (ERejectException e) { + // return error to the user + reqs[k].setRequestStatus(RequestStatus.REJECTED); + CMS.debug("ProfileSubmitServlet: submit " + e.toString()); + errorCode = "3"; + errorReason = CMS.getUserMessage(locale, + "CMS_PROFILE_REJECTED", + e.toString()); + } catch (Throwable e) { + // return error to the user + CMS.debug("ProfileSubmitServlet: submit " + e.toString()); + errorCode = "1"; + errorReason = CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR"); + } + + try { + if (errorCode == null) { + profile.getRequestQueue().markAsServiced(reqs[k]); + } else { + profile.getRequestQueue().updateRequest(reqs[k]); + } + } catch (EBaseException e) { + CMS.debug("ProfileSubmitServlet: updateRequest " + + e.toString()); + } + + if (errorCode != null) { + if (errorCode.equals("1")) { + // 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_REJECTION, + errorReason); + + audit(auditMessage); + } else if (errorCode.equals("2")) { + // do NOT store a message in the signed audit log file + // as this errorCode indicates that a process has been + // deferred for manual acceptance/cancellation/rejection + } else if (errorCode.equals("3")) { + // 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_REJECTION, + errorReason); + + audit(auditMessage); + } + } + } + + if (errorCode != null) { + if (xmlOutput) { + // when errorCode is not null, requestIds should have >=1 + outputError(response, errorCode, errorReason, requestIds); + } else { + ArgList requestlist = new ArgList(); + + for (int k = 0; k < reqs.length; k++) { + ArgSet requestset = new ArgSet(); + + requestset.set(ARG_REQUEST_ID, + reqs[k].getRequestId().toString()); + requestlist.add(requestset); + } + args.set(ARG_REQUEST_LIST, requestlist); + args.set(ARG_ERROR_CODE, errorCode); + args.set(ARG_ERROR_REASON, errorReason); + outputTemplate(request, response, args); + } + if (statsSub != null) { + statsSub.endTiming("enrollment"); + } + return; + } + + /////////////////////////////////////////////// + // output output list + /////////////////////////////////////////////// + if (xmlOutput) { + xmlOutput(response, profile, locale, reqs); + } else { + ArgList outputlist = new ArgList(); + for (int k = 0; k < reqs.length; k++) { + + setOutputIntoArgs(profile, outputlist, locale, reqs[k]); + args.set(ARG_OUTPUT_LIST, outputlist); + } + + CMS.debug("ProfileSubmitServlet: done serving"); + + ArgList requestlist = new ArgList(); + + for (int k = 0; k < reqs.length; k++) { + ArgSet requestset = new ArgSet(); + + requestset.set(ARG_REQUEST_ID, + reqs[k].getRequestId().toString()); + requestlist.add(requestset); + } + args.set(ARG_REQUEST_LIST, requestlist); + args.set(ARG_ERROR_CODE, "0"); + args.set(ARG_ERROR_REASON, ""); + + outputTemplate(request, response, args); + } + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + // (automated cert request processed - "rejected") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + ILogger.SIGNED_AUDIT_REJECTION, + SIGNED_AUDIT_AUTOMATED_REJECTION_REASON[0]); + + audit(auditMessage); + + if (statsSub != null) { + statsSub.endTiming("enrollment"); + } + throw eAudit1; + } finally { + context.releaseContext(); + } + if (statsSub != null) { + statsSub.endTiming("enrollment"); + } + } + + private void xmlOutput(HttpServletResponse httpResp, IProfile profile, Locale locale, IRequest[] reqs) { + try { + XMLObject xmlObj = null; + xmlObj = new XMLObject(); + + Node root = xmlObj.createRoot("XMLResponse"); + xmlObj.addItemToContainer(root, "Status", SUCCESS); + Node n = xmlObj.createContainer(root, "Requests"); + CMS.debug("ProfileSubmitServlet xmlOutput: req len = " +reqs.length); + + for (int i=0; i + * + * @param request the actual request + * @return id string containing the signed audit log message RequesterID + */ + private String auditRequesterID(IRequest request) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String requesterID = ILogger.UNIDENTIFIED; + + if (request != null) { + // overwrite "requesterID" if and only if "id" != null + String id = request.getRequestId().toString(); + + if (id != null) { + requesterID = id.trim(); + } + } + + return requesterID; + } + + /** + * 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. + *

+ * + * @param request 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(); + + // extract all line separators from the "base64Data" + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < base64Data.length(); i++) { + if (!Character.isWhitespace(base64Data.charAt(i))) { + sb.append(base64Data.charAt(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; + } + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/profile/SSLClientCertProvider.java b/pki/base/common/src/com/netscape/cms/servlet/profile/SSLClientCertProvider.java new file mode 100644 index 000000000..c548d0db9 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/SSLClientCertProvider.java @@ -0,0 +1,40 @@ +// --- 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.profile; + +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import java.security.cert.*; +import com.netscape.certsrv.authentication.*; + +public class SSLClientCertProvider implements ISSLClientCertProvider { + private HttpServletRequest mRequest = null; + + public SSLClientCertProvider(HttpServletRequest request) { + mRequest = request; + } + + public X509Certificate[] getClientCertificateChain() { + X509Certificate[] allCerts = (X509Certificate[]) + mRequest.getAttribute("javax.servlet.request.X509Certificate"); + + return allCerts; + } +} + -- cgit